From b4b48cf598bbcbfa19971792462334dae680798e Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Mon, 27 Nov 2023 19:45:25 -0500 Subject: [PATCH 1/3] Respect termios ECHO flag --- Cargo.lock | 12 ++++++++++++ Cargo.toml | 1 + src/engine.rs | 32 ++++++++++++++++++++++++-------- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f318965a..891aec31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -446,6 +446,17 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.3.3", + "cfg-if", + "libc", +] + [[package]] name = "nu-ansi-term" version = "0.49.0" @@ -576,6 +587,7 @@ dependencies = [ "fd-lock", "gethostname", "itertools", + "nix", "nu-ansi-term", "pretty_assertions", "rstest", diff --git a/Cargo.toml b/Cargo.toml index 29334548..872b597e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ crossbeam = { version = "0.8.2", optional = true } crossterm = { version = "0.27.0", features = ["serde"] } fd-lock = "3.0.3" itertools = "0.10.3" +nix = { version = "0.27.1", features = ["term"] } nu-ansi-term = "0.49.0" rusqlite = { version = "0.29.0", optional = true } serde = { version = "1.0", features = ["derive"] } diff --git a/src/engine.rs b/src/engine.rs index e4ca9c7e..b97feb4c 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -149,6 +149,9 @@ pub struct Reedline { // Manage optional kitty protocol kitty_protocol: KittyProtocolGuard, + // Echo typed input + echo_on: bool, + #[cfg(feature = "external_printer")] external_printer: Option>, } @@ -218,6 +221,7 @@ impl Reedline { cursor_shapes: None, bracketed_paste: BracketedPasteGuard::default(), kitty_protocol: KittyProtocolGuard::default(), + echo_on: true, #[cfg(feature = "external_printer")] external_printer: None, } @@ -609,6 +613,14 @@ impl Reedline { /// Returns a [`std::io::Result`] in which the `Err` type is [`std::io::Result`] /// and the `Ok` variant wraps a [`Signal`] which handles user inputs. pub fn read_line(&mut self, prompt: &dyn Prompt) -> Result { + // Needs to be done before `terminal::enable_raw_mode()` which modifies the terminal flags + #[cfg(unix)] + if let Ok(attr) = nix::sys::termios::tcgetattr(std::io::stdin()) { + self.echo_on = attr + .local_flags + .contains(nix::sys::termios::LocalFlags::ECHO); + } + terminal::enable_raw_mode()?; self.bracketed_paste.enter(); self.kitty_protocol.enter(); @@ -618,6 +630,7 @@ impl Reedline { self.bracketed_paste.exit(); self.kitty_protocol.exit(); terminal::disable_raw_mode()?; + result } @@ -1638,14 +1651,17 @@ impl Reedline { let cursor_position_in_buffer = self.editor.insertion_point(); let buffer_to_paint = self.editor.get_buffer(); - let (before_cursor, after_cursor) = self - .highlighter - .highlight(buffer_to_paint, cursor_position_in_buffer) - .render_around_insertion_point( - cursor_position_in_buffer, - prompt, - self.use_ansi_coloring, - ); + let (before_cursor, after_cursor) = if self.echo_on { + self.highlighter + .highlight(buffer_to_paint, cursor_position_in_buffer) + .render_around_insertion_point( + cursor_position_in_buffer, + prompt, + self.use_ansi_coloring, + ) + } else { + (String::new(), String::new()) + }; let hint: String = if self.hints_active() { self.hinter.as_mut().map_or_else(String::new, |hinter| { From 518a8db033cb7336d607ade78be4e64ed8e37b88 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Wed, 20 Dec 2023 17:44:42 -0500 Subject: [PATCH 2/3] Require nix dependency only on unix targets --- Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 872b597e..6d730bae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ crossbeam = { version = "0.8.2", optional = true } crossterm = { version = "0.27.0", features = ["serde"] } fd-lock = "3.0.3" itertools = "0.10.3" -nix = { version = "0.27.1", features = ["term"] } nu-ansi-term = "0.49.0" rusqlite = { version = "0.29.0", optional = true } serde = { version = "1.0", features = ["derive"] } @@ -31,6 +30,9 @@ thiserror = "1.0.31" unicode-segmentation = "1.9.0" unicode-width = "0.1.9" +[target.'cfg(target_family = "unix")'.dependencies] +nix = { version = "0.27.1", features = ["term"] } + [dev-dependencies] gethostname = "0.4.0" pretty_assertions = "1.4.0" From 56cf8e2e7bc384c4cd39eb2045ce0d9d7a0fdaa9 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Wed, 20 Dec 2023 17:52:14 -0500 Subject: [PATCH 3/3] Document `Reedline::echo_on` --- src/engine.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/engine.rs b/src/engine.rs index b97feb4c..0ed808fa 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -149,7 +149,14 @@ pub struct Reedline { // Manage optional kitty protocol kitty_protocol: KittyProtocolGuard, - // Echo typed input + /// Whether to echo typed input + /// + /// On unix systems, this corresponds to the + /// [termios](https://www.man7.org/linux/man-pages/man3/termios.3.html) `ECHO` flag. + /// If it is set by the terminal, typed characters will be printed. + /// Otherwise, typed characters are not shown. + /// + /// On non-unix systems this will always remain `true`. echo_on: bool, #[cfg(feature = "external_printer")]