fix(compatibility): keypad arrow fixes (#80)

* fix(compatibility): make arrow keys work in htop and vim

* docs(terminal): add explanatory comments to character string

* style(format): make rustfmt happy
This commit is contained in:
Aram Drevekenin 2020-12-03 15:58:30 +01:00 committed by GitHub
parent 56c53d2487
commit 5ba9320b2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 14 deletions

View File

@ -389,10 +389,12 @@ impl Screen {
terminal_output.handle_event(event); terminal_output.handle_event(event);
} }
} }
pub fn write_to_active_terminal(&mut self, mut bytes: Vec<u8>) { pub fn write_to_active_terminal(&mut self, input_bytes: Vec<u8>) {
if let Some(active_terminal_id) = &self.get_active_terminal_id() { if let Some(active_terminal_id) = &self.get_active_terminal_id() {
let active_terminal = self.get_active_terminal().unwrap();
let mut adjusted_input = active_terminal.adjust_input_to_terminal(input_bytes);
self.os_api self.os_api
.write_to_tty_stdin(*active_terminal_id, &mut bytes) .write_to_tty_stdin(*active_terminal_id, &mut adjusted_input)
.expect("failed to write to terminal"); .expect("failed to write to terminal");
self.os_api self.os_api
.tcdrain(*active_terminal_id) .tcdrain(*active_terminal_id)

View File

@ -38,6 +38,7 @@ pub struct TerminalPane {
pub should_render: bool, pub should_render: bool,
pub position_and_size: PositionAndSize, pub position_and_size: PositionAndSize,
pub position_and_size_override: Option<PositionAndSize>, pub position_and_size_override: Option<PositionAndSize>,
pub cursor_key_mode: bool, // DECCKM - when set, cursor keys should send ANSI direction codes (eg. "OD") instead of the arrow keys (eg. "")
pending_styles: CharacterStyles, pending_styles: CharacterStyles,
} }
@ -73,6 +74,7 @@ impl TerminalPane {
pending_styles, pending_styles,
position_and_size, position_and_size,
position_and_size_override: None, position_and_size_override: None,
cursor_key_mode: false,
} }
} }
pub fn mark_for_rerender(&mut self) { pub fn mark_for_rerender(&mut self) {
@ -276,6 +278,48 @@ impl TerminalPane {
self.reflow_lines(); self.reflow_lines();
self.mark_for_rerender(); self.mark_for_rerender();
} }
pub fn adjust_input_to_terminal(&self, input_bytes: Vec<u8>) -> Vec<u8> {
// there are some cases in which the terminal state means that input sent to it
// needs to be adjusted.
// here we match against those cases - if need be, we adjust the input and if not
// we send back the original input
match input_bytes.as_slice() {
[27, 91, 68] => {
// left arrow
if self.cursor_key_mode {
// please note that in the line below, there is an ANSI escape code (27) at the beginning of the string,
// some editors will not show this
return "OD".as_bytes().to_vec();
}
}
[27, 91, 67] => {
// right arrow
if self.cursor_key_mode {
// please note that in the line below, there is an ANSI escape code (27) at the beginning of the string,
// some editors will not show this
return "OC".as_bytes().to_vec();
}
}
[27, 91, 65] => {
// up arrow
if self.cursor_key_mode {
// please note that in the line below, there is an ANSI escape code (27) at the beginning of the string,
// some editors will not show this
return "OA".as_bytes().to_vec();
}
}
[27, 91, 66] => {
// down arrow
if self.cursor_key_mode {
// please note that in the line below, there is an ANSI escape code (27) at the beginning of the string,
// some editors will not show this
return "OB".as_bytes().to_vec();
}
}
_ => {}
};
input_bytes
}
fn add_newline(&mut self) { fn add_newline(&mut self) {
self.scroll.add_canonical_line(); self.scroll.add_canonical_line();
// self.reset_all_ansi_codes(); // TODO: find out if we should be resetting here or not // self.reset_all_ansi_codes(); // TODO: find out if we should be resetting here or not
@ -728,9 +772,15 @@ impl vte::Perform for TerminalPane {
_ => false, _ => false,
}; };
if first_intermediate_is_questionmark { if first_intermediate_is_questionmark {
if let Some(&25) = params.get(0) { match params.get(0) {
self.scroll.hide_cursor(); Some(&25) => {
self.mark_for_rerender(); self.scroll.hide_cursor();
self.mark_for_rerender();
}
Some(&1) => {
self.cursor_key_mode = false;
}
_ => {}
}; };
} }
} else if c == 'h' { } else if c == 'h' {
@ -740,9 +790,15 @@ impl vte::Perform for TerminalPane {
_ => false, _ => false,
}; };
if first_intermediate_is_questionmark { if first_intermediate_is_questionmark {
if let Some(&25) = params.get(0) { match params.get(0) {
self.scroll.show_cursor(); Some(&25) => {
self.mark_for_rerender(); self.scroll.show_cursor();
self.mark_for_rerender();
}
Some(&1) => {
self.cursor_key_mode = true;
}
_ => {}
}; };
} }
} else if c == 'r' { } else if c == 'r' {
@ -838,12 +894,7 @@ impl vte::Perform for TerminalPane {
(b'M', None) => { (b'M', None) => {
self.scroll.move_cursor_up_in_scroll_region(1); self.scroll.move_cursor_up_in_scroll_region(1);
} }
_ => { _ => {}
let _ = debug_log_to_file(format!(
"Unhandled esc_dispatch: {}->{:?}",
byte, intermediates
));
}
} }
} }
} }