Fix/input suppress output on windows (#9459)

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` ✔️
This commit is contained in:
Sygmei 2023-06-19 19:04:37 +02:00 committed by GitHub
parent d78e3c3b0d
commit d25fb3ad56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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()));
}
continue;
}
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);
buf.push(c);
}
KeyCode::Backspace => {
let _ = buf.pop();
}
KeyCode::Enter => {
break;
}
_ => continue,
}
}
KeyCode::Backspace => {
let _ = buf.pop();
}
KeyCode::Enter => break,
_ => continue,
},
Ok(_) => continue,