listen for SIGINT signal instead of exit key bind
Describe the bug A clear and concise description of what the bug is.
To Reproduce Steps to reproduce the behavior: Remap Ctrl+Q to quit, with Ctrl+C being now available for copy/paste keybindings in terminal config:
stty intr ^Q
stty -ixon
stty -ixoff
Expected behavior Ctrl+Q should now be interpreted as SIGINT. This works for most applications, but because GitUI enables raw terminal mode, it is up to GitUI to manually respect system settings.
Context (please complete the following information):
- OS/Distro + Version: NixOS 23.11
- GitUI Version: gitui 0.24.3
- Rust version: unknown
GitUI is hard coded to quit on Ctrl+C
it is not hard coded to do that. you can configure the key bindings.
but indeed it would be interesting to honor the signal SIGINT instead of a custom key handler. that should be doable
Ah, my apologies. :)
I’ll try to create a PR in the next couple days!
@cruessler i am not sure if this is really possible with the terminal mode we use. please checkout my branch signal-handler-to-quit to see how far I got - or not :)
@extrawurst I just checked out your branch and found that gitui indeed responded to SIGINT by quitting and logging signal received. exiting when I sent it a signal using kill -INT <pid>. So the issue as described in the title seems already solved. Am I correct in assuming that this issue is less about responding to SIGINT, but rather about gitui somehow not reacting to an alternative shortcut that is supposed to send SIGINT?
Really? It’s been a while, no idea anymore why I thought it does not work 😉 Maybe terminal specific 🤔
For context, I'm using Wezterm (20240203-110809-5046fc22). My Ctrl+Q keybindings still do not work, but Ctrl+C does, which is counter to my configuration.
To maybe get inspiration from another program on how to implement this in an elegant way, I first ran stty intr ^Q and stty start ^C, then opened less, man and tig. None of them seemed to close on ^Q, so I’m wondering whether my setup contains anything that prevents ^Q from working.
I think it's just very common for applications that put the terminal in raw mode to hardcode Ctrl+C and call it a day. It sets a really bad precedent, IMO. Some applications don't even respond to the Ctrl+C standard. On my system, man responds to q, but not Ctrl+C or Ctrl+Q (regardless of stty intr config). And others IIRC respond to Esc, but not q or Ctrl+C or Ctrl+Q. The problem is so irritating that I'm actually considering writing a wrapper to translate the keypresses to misbehaving applications.
It doesn't seem too hard to detect terminal state and then decide which key to interpret as interrupt in raw mode based on that. I could write a mockup program with this behavior, if it helps.
That would help. Or point me to a stackoverflow or any precedence
Here's a minimal example:
use std::io::{self, Read};
use std::os::unix::io::AsRawFd;
use termios::*;
fn main() {
let stdin_fd = io::stdin().as_raw_fd();
let original_term_config = Termios::from_fd(stdin_fd).unwrap();
let interrupt_char = original_term_config.c_cc[VINTR];
let mut raw_termios = original_term_config;
cfmakeraw(&mut raw_termios);
tcsetattr(stdin_fd, TCSANOW, &mut raw_termios).unwrap();
println!("Press the interrupt character to exit...\r");
let mut buffer = [0u8; 1];
loop {
io::stdin().read_exact(&mut buffer).unwrap();
eprintln!("Got: {:?}\r", &buffer);
if buffer[0] == interrupt_char {
break;
}
}
tcsetattr(stdin_fd, TCSANOW, &original_term_config).unwrap();
}
If you use do stty intr ^Q, it will quit when you hit Ctrl+Q, and if you do stty intr ^C, it will quit when you do Ctrl+C. Edge cases seem to work too -- if you do stty intr q it will quit on q.
Thanks for the example!
termios and crossterm encode keys differently. I don’t know whether there is an obvious way to map c_cc[VINTR] to code in KeyEvent (which is what GitUI reacts to). c_cc[VINTR] seems to map a to 1, b to 2 etc.
https://docs.rs/crossterm/latest/crossterm/event/enum.KeyCode.html