Skip to content

Commit

Permalink
Merge pull request #601 from gwenn/dev_tty
Browse files Browse the repository at this point in the history
PreferTerm
  • Loading branch information
gwenn authored Feb 21, 2022
2 parents ad60583 + b50a828 commit fa4c2b3
Show file tree
Hide file tree
Showing 8 changed files with 338 additions and 262 deletions.
2 changes: 0 additions & 2 deletions examples/example.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::borrow::Cow::{self, Borrowed, Owned};

use rustyline::completion::{Completer, FilenameCompleter, Pair};
use rustyline::config::OutputStreamType;
use rustyline::error::ReadlineError;
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
use rustyline::hint::{Hinter, HistoryHinter};
Expand Down Expand Up @@ -86,7 +85,6 @@ fn main() -> rustyline::Result<()> {
.history_ignore_space(true)
.completion_type(CompletionType::List)
.edit_mode(EditMode::Emacs)
.output_stream(OutputStreamType::Stdout)
.build();
let h = MyHelper {
completer: FilenameCompleter::new(),
Expand Down
57 changes: 33 additions & 24 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ pub struct Config {
bell_style: BellStyle,
/// if colors should be enabled.
color_mode: ColorMode,
/// Whether to use stdout or stderr
output_stream: OutputStreamType,
/// Whether to use stdio or not
behavior: Behavior,
/// Horizontal space taken by a tab.
tab_stop: usize,
/// Indentation size for indent/dedent commands
Expand Down Expand Up @@ -141,16 +141,16 @@ impl Config {
self.color_mode = color_mode;
}

/// Tell which output stream should be used: stdout or stderr.
/// Whether to use stdio or not
///
/// By default, stdout is used.
/// By default, stdio is used.
#[must_use]
pub fn output_stream(&self) -> OutputStreamType {
self.output_stream
pub fn behavior(&self) -> Behavior {
self.behavior
}

pub(crate) fn set_output_stream(&mut self, stream: OutputStreamType) {
self.output_stream = stream;
pub(crate) fn set_behavior(&mut self, behavior: Behavior) {
self.behavior = behavior;
}

/// Horizontal space taken by a tab.
Expand Down Expand Up @@ -207,7 +207,7 @@ impl Default for Config {
auto_add_history: false,
bell_style: BellStyle::default(),
color_mode: ColorMode::Enabled,
output_stream: OutputStreamType::Stdout,
behavior: Behavior::default(),
tab_stop: 8,
indent_size: 2,
check_cursor_position: false,
Expand Down Expand Up @@ -291,15 +291,24 @@ pub enum ColorMode {
Disabled,
}

/// Should the editor use stdout or stderr
// TODO console term::TermTarget
/// Should the editor use stdio
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum OutputStreamType {
/// Use stderr
Stderr,
/// Use stdout
Stdout,
pub enum Behavior {
/// Use stdin / stdout
Stdio,
/// Use terminal-style interaction whenever possible, even if 'stdin' and/or
/// 'stdout' are not terminals.
PreferTerm,
// TODO
// Use file-style interaction, reading input from the given file.
// useFile
}

impl Default for Behavior {
fn default() -> Self {
Behavior::Stdio
}
}

/// Configuration builder
Expand Down Expand Up @@ -402,12 +411,12 @@ impl Builder {
self
}

/// Whether to use stdout or stderr.
/// Whether to use stdio or not
///
/// Be default, use stdout
/// By default, stdio is used.
#[must_use]
pub fn output_stream(mut self, stream: OutputStreamType) -> Self {
self.set_output_stream(stream);
pub fn behavior(mut self, behavior: Behavior) -> Self {
self.set_behavior(behavior);
self
}

Expand Down Expand Up @@ -529,11 +538,11 @@ pub trait Configurer {
self.config_mut().set_color_mode(color_mode);
}

/// Whether to use stdout or stderr
/// Whether to use stdio or not
///
/// By default, use stdout
fn set_output_stream(&mut self, stream: OutputStreamType) {
self.config_mut().set_output_stream(stream);
/// By default, stdio is used.
fn set_behavior(&mut self, behavior: Behavior) {
self.config_mut().set_behavior(behavior);
}

/// Horizontal space taken by a tab.
Expand Down
1 change: 0 additions & 1 deletion src/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,6 @@ impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> {
debug_assert!(self.layout.prompt_size <= self.layout.cursor);
debug_assert!(self.layout.cursor <= self.layout.end);
let bits = ch.encode_utf8(&mut self.byte_buffer);
let bits = bits.as_bytes();
self.out.write_and_flush(bits)
} else {
self.refresh(self.prompt, prompt_size, true, Info::Hint)
Expand Down
25 changes: 10 additions & 15 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ use crate::tty::{RawMode, Renderer, Term, Terminal};

pub use crate::binding::{ConditionalEventHandler, Event, EventContext, EventHandler};
use crate::completion::{longest_common_prefix, Candidate, Completer};
pub use crate::config::{
ColorMode, CompletionType, Config, EditMode, HistoryDuplicates, OutputStreamType,
};
pub use crate::config::{Behavior, ColorMode, CompletionType, Config, EditMode, HistoryDuplicates};
use crate::edit::State;
use crate::highlight::Highlighter;
use crate::hint::Hinter;
Expand Down Expand Up @@ -168,7 +166,7 @@ fn complete_line<H: Helper>(
// we got a second tab, maybe show list of possible completions
let show_completions = if candidates.len() > config.completion_prompt_limit() {
let msg = format!("\nDisplay all {} possibilities? (y or n)", candidates.len());
s.out.write_and_flush(msg.as_bytes())?;
s.out.write_and_flush(msg.as_str())?;
s.layout.end.row += 1;
while cmd != Cmd::SelfInsert(1, 'y')
&& cmd != Cmd::SelfInsert(1, 'Y')
Expand Down Expand Up @@ -294,7 +292,7 @@ fn page_completions<C: Candidate, H: Helper>(
let mut ab = String::new();
for row in 0..num_rows {
if row == pause_row {
s.out.write_and_flush(b"\n--More--")?;
s.out.write_and_flush("\n--More--")?;
let mut cmd = Cmd::Noop;
while cmd != Cmd::SelfInsert(1, 'y')
&& cmd != Cmd::SelfInsert(1, 'Y')
Expand All @@ -320,7 +318,7 @@ fn page_completions<C: Candidate, H: Helper>(
_ => break,
}
}
s.out.write_and_flush(b"\n")?;
s.out.write_and_flush("\n")?;
ab.clear();
for col in 0..num_cols {
let i = (col * num_rows) + row;
Expand All @@ -339,9 +337,9 @@ fn page_completions<C: Candidate, H: Helper>(
}
}
}
s.out.write_and_flush(ab.as_bytes())?;
s.out.write_and_flush(ab.as_str())?;
}
s.out.write_and_flush(b"\n")?;
s.out.write_and_flush("\n")?;
s.layout.end.row = 0; // dirty way to make clear_old_rows do nothing
s.layout.cursor.row = 0;
s.refresh_line()?;
Expand Down Expand Up @@ -458,7 +456,7 @@ fn readline_edit<H: Helper>(
.update((left.to_owned() + right).as_ref(), left.len());
}

let mut rdr = editor.term.create_reader(&editor.config, term_key_map)?;
let mut rdr = editor.term.create_reader(&editor.config, term_key_map);
if editor.term.is_output_tty() && editor.config.check_cursor_position() {
if let Err(e) = s.move_cursor_at_leftmost(&mut rdr) {
if s.out.sigwinch() {
Expand Down Expand Up @@ -576,10 +574,7 @@ fn readline_raw<H: Helper>(
}
}
drop(guard); // disable_raw_mode(original_mode)?;
match editor.config.output_stream() {
OutputStreamType::Stdout => writeln!(io::stdout())?,
OutputStreamType::Stderr => writeln!(io::stderr())?,
};
editor.term.writeln()?;
user_input
}

Expand Down Expand Up @@ -735,7 +730,7 @@ impl<H: Helper> Editor<H> {
pub fn with_config(config: Config) -> Self {
let term = Terminal::new(
config.color_mode(),
config.output_stream(),
config.behavior(),
config.tab_stop(),
config.bell_style(),
config.enable_bracketed_paste(),
Expand Down Expand Up @@ -780,7 +775,7 @@ impl<H: Helper> Editor<H> {
stdout.flush()?;

readline_direct(io::stdin().lock(), io::stderr(), &self.helper)
} else if self.term.is_stdin_tty() {
} else if self.term.is_input_tty() {
readline_raw(prompt, initial, self)
} else {
debug!(target: "rustyline", "stdin is not a tty");
Expand Down
15 changes: 8 additions & 7 deletions src/tty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use unicode_width::UnicodeWidthStr;

use crate::config::{BellStyle, ColorMode, Config, OutputStreamType};
use crate::config::{Behavior, BellStyle, ColorMode, Config};
use crate::highlight::Highlighter;
use crate::keys::KeyEvent;
use crate::layout::{Layout, Position};
Expand Down Expand Up @@ -84,7 +84,7 @@ pub trait Renderer {
/// `cols` width terminal starting at `orig`.
fn calculate_position(&self, s: &str, orig: Position) -> Position;

fn write_and_flush(&self, buf: &[u8]) -> Result<()>;
fn write_and_flush(&mut self, buf: &str) -> Result<()>;

/// Beep, used for completion when there is nothing to complete or when all
/// the choices were already shown.
Expand Down Expand Up @@ -131,7 +131,7 @@ impl<'a, R: Renderer + ?Sized> Renderer for &'a mut R {
(**self).calculate_position(s, orig)
}

fn write_and_flush(&self, buf: &[u8]) -> Result<()> {
fn write_and_flush(&mut self, buf: &str) -> Result<()> {
(**self).write_and_flush(buf)
}

Expand Down Expand Up @@ -208,24 +208,25 @@ pub trait Term {

fn new(
color_mode: ColorMode,
stream: OutputStreamType,
behavior: Behavior,
tab_stop: usize,
bell_style: BellStyle,
enable_bracketed_paste: bool,
) -> Self;
/// Check if current terminal can provide a rich line-editing user
/// interface.
fn is_unsupported(&self) -> bool;
/// check if stdin is connected to a terminal.
fn is_stdin_tty(&self) -> bool;
/// check if input stream is connected to a terminal.
fn is_input_tty(&self) -> bool;
/// check if output stream is connected to a terminal.
fn is_output_tty(&self) -> bool;
/// Enable RAW mode for the terminal.
fn enable_raw_mode(&mut self) -> Result<(Self::Mode, Self::KeyMap)>;
/// Create a RAW reader
fn create_reader(&self, config: &Config, key_map: Self::KeyMap) -> Result<Self::Reader>;
fn create_reader(&self, config: &Config, key_map: Self::KeyMap) -> Self::Reader;
/// Create a writer
fn create_writer(&self) -> Self::Writer;
fn writeln(&self) -> Result<()>;
}

// If on Windows platform import Windows TTY module
Expand Down
16 changes: 10 additions & 6 deletions src/tty/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::slice::Iter;
use std::vec::IntoIter;

use super::{RawMode, RawReader, Renderer, Term};
use crate::config::{BellStyle, ColorMode, Config, OutputStreamType};
use crate::config::{Behavior, BellStyle, ColorMode, Config};
use crate::error::ReadlineError;
use crate::highlight::Highlighter;
use crate::keys::KeyEvent;
Expand Down Expand Up @@ -103,7 +103,7 @@ impl Renderer for Sink {
pos
}

fn write_and_flush(&self, _: &[u8]) -> Result<()> {
fn write_and_flush(&mut self, _: &str) -> Result<()> {
Ok(())
}

Expand Down Expand Up @@ -156,7 +156,7 @@ impl Term for DummyTerminal {

fn new(
color_mode: ColorMode,
_stream: OutputStreamType,
_behavior: Behavior,
_tab_stop: usize,
bell_style: BellStyle,
_enable_bracketed_paste: bool,
Expand All @@ -181,7 +181,7 @@ impl Term for DummyTerminal {
true
}

fn is_stdin_tty(&self) -> bool {
fn is_input_tty(&self) -> bool {
true
}

Expand All @@ -195,13 +195,17 @@ impl Term for DummyTerminal {
Ok(((), ()))
}

fn create_reader(&self, _: &Config, _: KeyMap) -> Result<Self::Reader> {
Ok(self.keys.clone().into_iter())
fn create_reader(&self, _: &Config, _: KeyMap) -> Self::Reader {
self.keys.clone().into_iter()
}

fn create_writer(&self) -> Sink {
Sink::new()
}

fn writeln(&self) -> Result<()> {
Ok(())
}
}

#[cfg(unix)]
Expand Down
Loading

0 comments on commit fa4c2b3

Please sign in to comment.