mirror of
https://github.com/herdrdev/herdr.git
synced 2026-09-14 18:03:41 +08:00
fix(input): accept parameterized CSI-tilde F1-F4 keys (#4067)
Terminals such as foot send F1-F4 as parameterized CSI-tilde sequences (for example F3 as `\x1b[13;1:1~`). `parse_xterm_modified_special_sequence` mapped codes 15-24 but not 11-14, so these presses were dropped before keybindings saw them. Map 11-14 to F1-F4, matching the unmodified `\x1b[11~`..`\x1b[14~` aliases already accepted. refs #1809
This commit is contained in:
+29
-3
@@ -252,6 +252,10 @@ fn parse_xterm_modified_special_sequence(data: &str) -> Option<TerminalKey> {
|
||||
"3" => KeyCode::Delete,
|
||||
"5" => KeyCode::PageUp,
|
||||
"6" => KeyCode::PageDown,
|
||||
"11" => KeyCode::F(1),
|
||||
"12" => KeyCode::F(2),
|
||||
"13" => KeyCode::F(3),
|
||||
"14" => KeyCode::F(4),
|
||||
"15" => KeyCode::F(5),
|
||||
"17" => KeyCode::F(6),
|
||||
"18" => KeyCode::F(7),
|
||||
@@ -637,9 +641,31 @@ mod tests {
|
||||
crossterm::event::KeyEventKind::Press,
|
||||
None,
|
||||
);
|
||||
assert_eq!(parse_terminal_key_sequence("\x1b[11;2~"), None);
|
||||
assert_eq!(parse_terminal_key_sequence("\x1b[14;1~"), None);
|
||||
assert_eq!(parse_terminal_key_sequence("\x1b[14;3~"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_parameterized_csi_tilde_f1_through_f4() {
|
||||
// foot and some rxvt-style hosts emit F1-F4 as `CSI <code>;<mods>~`
|
||||
// (for example F3 as `\x1b[13;1:1~`), reusing the same code table as the
|
||||
// unmodified `\x1b[11~`..`\x1b[14~` forms.
|
||||
let cases = [
|
||||
("\x1b[11;2~", KeyCode::F(1), KeyModifiers::SHIFT),
|
||||
("\x1b[12;1~", KeyCode::F(2), KeyModifiers::empty()),
|
||||
("\x1b[13;1:1~", KeyCode::F(3), KeyModifiers::empty()),
|
||||
("\x1b[13;2~", KeyCode::F(3), KeyModifiers::SHIFT),
|
||||
("\x1b[14;3~", KeyCode::F(4), KeyModifiers::ALT),
|
||||
];
|
||||
|
||||
for (sequence, code, modifiers) in cases {
|
||||
let parsed = parse_terminal_key_sequence(sequence).unwrap();
|
||||
assert_terminal_key_eq(
|
||||
parsed,
|
||||
code,
|
||||
modifiers,
|
||||
crossterm::event::KeyEventKind::Press,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+5
-2
@@ -1535,6 +1535,9 @@ mod tests {
|
||||
(b"\x1b[57423;1u", KeyCode::Home, KeyModifiers::empty()),
|
||||
(b"\x1bOq", KeyCode::Char('1'), KeyModifiers::empty()),
|
||||
(b"\x1b[14~", KeyCode::F(4), KeyModifiers::empty()),
|
||||
(b"\x1b[11;2~", KeyCode::F(1), KeyModifiers::SHIFT),
|
||||
(b"\x1b[13;1:1~", KeyCode::F(3), KeyModifiers::empty()),
|
||||
(b"\x1b[14;3~", KeyCode::F(4), KeyModifiers::ALT),
|
||||
(b"\x1b[57364;1u", KeyCode::F(1), KeyModifiers::empty()),
|
||||
(b"\x1b[57366;1u", KeyCode::F(3), KeyModifiers::empty()),
|
||||
(b"\x1b[57366;2u", KeyCode::F(3), KeyModifiers::SHIFT),
|
||||
@@ -1574,11 +1577,11 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn modified_rxvt_f_key_alias_stays_unsupported() {
|
||||
fn parses_modified_rxvt_f_key_alias() {
|
||||
let (event, consumed) = extract_one_event(b"\x1b[14;3~").unwrap();
|
||||
|
||||
assert_eq!(consumed, 7);
|
||||
assert!(matches!(event, RawInputEvent::Unsupported));
|
||||
assert_raw_key(event, KeyCode::F(4), KeyModifiers::ALT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user