interrupt input command with Ctrl + C (#8159)

# 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:🐚:io_error (link)

  × I/O error
  help: SIGINT
```

```
/home/rdevenney/projects/open_source/nushell〉input --bytes-until "a"
Error: nu:🐚: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.
This commit is contained in:
Ryan Devenney 2023-02-22 12:19:19 -05:00 committed by GitHub
parent e389e51b2b
commit 2659c359e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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();
}