From 2659c359e91a662517d7d1ee126736c5449dacde Mon Sep 17 00:00:00 2001 From: Ryan Devenney Date: Wed, 22 Feb 2023 12:19:19 -0500 Subject: [PATCH] interrupt `input` command with Ctrl + C (#8159) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description GH Issue: [#8074](https://github.com/nushell/nushell/issues/8074) Adding SIGINT Ctrl + C functionality to *most* of the `input` command. `input` with the flags `--suppress-output` and `--bytes-until` are executed in raw mode which allows a ^C signal to be caught as it's input, but an "optionless" call of `input` is using a standard `read_line()` method that takes a ^C input and clears the buffer of any data collected before the ^C. I'm more than happy to alter the "optionless" call but putting it in raw mode hides the user input, so at the moment that's unchanged. # User-Facing Changes Now ^C anywhere in the stdin stream will cause the command to SIGINT (as long as the command isn't optionless), rather than being read in as part of the input. ``` /home/rdevenney/projects/open_source/nushell〉input --suppress-output Error: nu::shell::io_error (link) × I/O error help: SIGINT ``` ``` /home/rdevenney/projects/open_source/nushell〉input --bytes-until "a" Error: nu::shell::io_error (link) × I/O error help: SIGINT ``` As mentioned above, the default input behavior is the same. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --- crates/nu-command/src/platform/input.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/nu-command/src/platform/input.rs b/crates/nu-command/src/platform/input.rs index 45553ea13..3acc6c4ed 100644 --- a/crates/nu-command/src/platform/input.rs +++ b/crates/nu-command/src/platform/input.rs @@ -73,6 +73,12 @@ impl Command for Input { } buffer.push(buf[0]); + // 03 symbolizes SIGINT/Ctrl+C + if buf.contains(&3) { + let _ = crossterm::terminal::disable_raw_mode(); + return Err(ShellError::IOError("SIGINT".to_string())); + } + if buf[0] == c { let _ = crossterm::terminal::disable_raw_mode(); break; @@ -104,13 +110,19 @@ impl Command for Input { match crossterm::event::read() { Ok(Event::Key(k)) => match k.code { // TODO: maintain keycode parity with existing command - KeyCode::Char(_) + KeyCode::Char(c) => { if k.modifiers == KeyModifiers::ALT - || k.modifiers == KeyModifiers::CONTROL => - { - continue + || 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::Char(c) => buf.push(c), KeyCode::Backspace => { let _ = buf.pop(); }