From d25fb3ad5683220547d54054bc5290cb0dde116f Mon Sep 17 00:00:00 2001 From: Sygmei <3835355+Sygmei@users.noreply.github.com> Date: Mon, 19 Jun 2023 19:04:37 +0200 Subject: [PATCH] Fix/input suppress output on windows (#9459) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this PR should close #9018 # Description This PR aims to fix the `input` command with `--suppress-output` on Windows This fixes two separates issues : - Keypresses being duplicated in output due to "Release" event not being ignored - "Return" event from entering the `input -s "blah :"` still being in the event buffer (need to be cleared before reading keypresses) # Tests + Formatting - `cargo fmt --all -- --check` ✔️ - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` ✔️ - `cargo test --workspace` ✔️ - `cargo run -- crates/nu-std/tests/run.nu` ✔️ --- .../nu-command/src/platform/input/input_.rs | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/crates/nu-command/src/platform/input/input_.rs b/crates/nu-command/src/platform/input/input_.rs index 31150a4594cf..170ecf34b1db 100644 --- a/crates/nu-command/src/platform/input/input_.rs +++ b/crates/nu-command/src/platform/input/input_.rs @@ -1,4 +1,4 @@ -use crossterm::event::{Event, KeyCode, KeyModifiers}; +use crossterm::event::{Event, KeyCode, KeyEventKind, KeyModifiers}; use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EngineState, Stack}; @@ -7,6 +7,7 @@ use nu_protocol::{ Type, Value, }; use std::io::{Read, Write}; +use std::time::Duration; #[derive(Clone)] pub struct Input; @@ -132,31 +133,46 @@ impl Command for Input { if suppress_output || numchar_exists { crossterm::terminal::enable_raw_mode()?; + // clear terminal events + while crossterm::event::poll(Duration::from_secs(0))? { + // If there's an event, read it to remove it from the queue + let _ = crossterm::event::read()?; + } + loop { if i64::try_from(buf.len()).unwrap_or(0) >= numchar.item { let _ = crossterm::terminal::disable_raw_mode(); break; } match crossterm::event::read() { - Ok(Event::Key(k)) => match k.code { - // TODO: maintain keycode parity with existing command - KeyCode::Char(c) => { - if k.modifiers == KeyModifiers::ALT - || k.modifiers == KeyModifiers::CONTROL - { - if k.modifiers == KeyModifiers::CONTROL && c == 'c' { - crossterm::terminal::disable_raw_mode()?; - return Err(ShellError::IOError("SIGINT".to_string())); + Ok(Event::Key(k)) => match k.kind { + KeyEventKind::Press | KeyEventKind::Repeat => { + match k.code { + // TODO: maintain keycode parity with existing command + KeyCode::Char(c) => { + if k.modifiers == KeyModifiers::ALT + || k.modifiers == KeyModifiers::CONTROL + { + if k.modifiers == KeyModifiers::CONTROL && c == 'c' { + crossterm::terminal::disable_raw_mode()?; + return Err(ShellError::IOError( + "SIGINT".to_string(), + )); + } + continue; + } + + buf.push(c); + } + KeyCode::Backspace => { + let _ = buf.pop(); } - continue; + KeyCode::Enter => { + break; + } + _ => continue, } - - buf.push(c); - } - KeyCode::Backspace => { - let _ = buf.pop(); } - KeyCode::Enter => break, _ => continue, }, Ok(_) => continue,