Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustyline ignores user's terminal settings for VINTR and VSUSP on Unix #530

Closed
godmar opened this issue Jun 3, 2021 · 12 comments · Fixed by #535
Closed

rustyline ignores user's terminal settings for VINTR and VSUSP on Unix #530

godmar opened this issue Jun 3, 2021 · 12 comments · Fixed by #535

Comments

@godmar
Copy link

godmar commented Jun 3, 2021

On Unix, users expect to configure the character they type to cause SIGINT to be sent to the foreground process group by typing, e.g. stty intr ^X where ^X is the key combination they wish to use.

rustyline doesn't use signal handling, turns off ISIG, and hardwires Ctrl-C as the interrupt character.
Likewise, the functionality of the VSUSP character (by default Ctrl-Z) appears hardwired as well.

It may be better for it to query the terminal as to which character the user prefers to use and then implement the corresponding actions when it encounters these characters.

PS: this behavior appears to be inherited from the original "guerrilla" linenoise library.

@gwenn
Copy link
Collaborator

gwenn commented Jun 4, 2021

@godmar
Copy link
Author

godmar commented Jun 4, 2021

You are correct in that one would use the termios(3) and specifically tcgetattr to obtain the current settings of these shortcut keys.

@gwenn
Copy link
Collaborator

gwenn commented Jun 4, 2021

Ok, so we should be able to retrieve current config here and overwrite default key bindings accordingly.

@gwenn
Copy link
Collaborator

gwenn commented Jun 13, 2021

Could you please give a try to #535 ?

rustyline % RUST_LOG=rustyline=debug cargo run --example example 2> debug.log
...
[DEBUG rustyline::tty::unix] VINTR: KeyEvent(Char('C'), CTRL)
[DEBUG rustyline::tty::unix] VQUIT: KeyEvent(Char('\\'), CTRL)
[DEBUG rustyline::tty::unix] VSUSP: KeyEvent(Char('Z'), CTRL)
...
[DEBUG rustyline::tty::unix] terminal key binding: KeyEvent(Char('Z'), CTRL) => Suspend
...
[DEBUG rustyline::tty::unix] terminal key binding: KeyEvent(Char('C'), CTRL) => Interrupt

@godmar
Copy link
Author

godmar commented Jul 3, 2021

This doesn't seem to work; setting intr to ^Y still causes Ctrl-C to interrupt:

[DEBUG rustyline::tty::unix] VINTR: KeyEvent(Char('Y'), CTRL)
[DEBUG rustyline::tty::unix] VQUIT: KeyEvent(Char('\\'), CTRL)
[DEBUG rustyline::tty::unix] VSUSP: KeyEvent(Char('Z'), CTRL)
[DEBUG rustyline::edit] old layout: Layout { prompt_size: Position { col: 0, row: 0 }, default_prompt: false, cursor: Position { col: 0, row: 0 }, end: Position { col: 0, row: 0 } }
[DEBUG rustyline::edit] new layout: Layout { prompt_size: Position { col: 3, row: 0 }, default_prompt: true, cursor: Position { col: 3, row: 0 }, end: Position { col: 3, row: 0 } }
1> [DEBUG rustyline::tty::unix] key: KeyEvent(Char('C'), CTRL)
[DEBUG rustyline::keymap] Emacs command: Interrupt

CTRL-C

This may be because of:

            E(K::Char('C'), M::CTRL) => Cmd::Interrupt,

@gwenn
Copy link
Collaborator

gwenn commented Jul 3, 2021

@godmar Could you give it another try ?

@godmar
Copy link
Author

godmar commented Jul 3, 2021

This now works, except for EOF.
Try this perhaps:

diff --git a/examples/example.rs b/examples/example.rs
index 7b3ccc8..f937b8f 100644
--- a/examples/example.rs
+++ b/examples/example.rs
@@ -113,11 +113,11 @@ fn main() -> rustyline::Result<()> {
                 println!("Line: {}", line);
             }
             Err(ReadlineError::Interrupted) => {
-                println!("CTRL-C");
+                println!("Interrupted");
                 break;
             }
             Err(ReadlineError::Eof) => {
-                println!("CTRL-D");
+                println!("Encountered Eof");
                 break;
             }
             Err(err) => {
diff --git a/src/keymap.rs b/src/keymap.rs
index 67c9775..d459062 100644
--- a/src/keymap.rs
+++ b/src/keymap.rs
@@ -1045,6 +1045,7 @@ impl InputState {
             }),
             #[cfg(any(windows, test))]
             E(K::Char('C'), M::CTRL) => Cmd::Interrupt,
+            #[cfg(any(windows, test))]
             E(K::Char('D'), M::CTRL) => {
                 if self.is_emacs_mode() && !wrt.line().is_empty() {
                     Cmd::Kill(if positive {
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index 584076d..e1c31ae 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -1151,6 +1151,7 @@ impl Term for PosixTerminal {
         raw.control_chars[SCI::VTIME as usize] = 0; // with blocking read
 
         let mut key_map: HashMap<KeyEvent, Cmd> = HashMap::with_capacity(3);
+        map_key(&mut key_map, &raw, SCI::VEOF, "VEOF", Cmd::EndOfFile);
         map_key(&mut key_map, &raw, SCI::VINTR, "VINTR", Cmd::Interrupt);
         map_key(&mut key_map, &raw, SCI::VQUIT, "VQUIT", Cmd::Interrupt);
         map_key(&mut key_map, &raw, SCI::VSUSP, "VSUSP", Cmd::Suspend);

@gwenn
Copy link
Collaborator

gwenn commented Jul 3, 2021

Ctrl-d is more complicated. See readline emacs and vi bindings.

@gwenn
Copy link
Collaborator

gwenn commented Jul 31, 2021

See also how editline handle VEOF.

@godmar
Copy link
Author

godmar commented Aug 1, 2021

See also how editline handle VEOF.

Independent of any other logic to which you may be referring, editline seems to respect the termios settings by doing: rl_eof = old.c_cc[VEOF];

@gwenn
Copy link
Collaborator

gwenn commented Aug 5, 2021

https://github.com/kkawakam/rustyline/pull/535/files#diff-4d757ff9c4eb4e65aec9dcecd65fed9feefe7d614d6da04190d9070e8e891c97R467

Trigger Eof error only if line is empty.

@gwenn
Copy link
Collaborator

gwenn commented Dec 4, 2021

Version 9.1.0 released.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants