Parse key modifiers (#426)

- Improved key modifier support.
This commit is contained in:
Andrey Kutejko 2020-05-18 19:12:31 +02:00 committed by GitHub
parent bc1f913487
commit 1dffc4f955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -194,25 +194,45 @@ pub(crate) fn parse_csi_cursor_position(buffer: &[u8]) -> Result<Option<Internal
Ok(Some(InternalEvent::CursorPosition(x, y))) Ok(Some(InternalEvent::CursorPosition(x, y)))
} }
fn parse_modifiers(mask: u8) -> KeyModifiers {
let modifier_mask = mask.saturating_sub(1);
let mut modifiers = KeyModifiers::empty();
if modifier_mask & 1 != 0 {
modifiers |= KeyModifiers::SHIFT;
}
if modifier_mask & 2 != 0 {
modifiers |= KeyModifiers::ALT;
}
if modifier_mask & 4 != 0 {
modifiers |= KeyModifiers::CONTROL;
}
modifiers
}
pub(crate) fn parse_csi_modifier_key_code(buffer: &[u8]) -> Result<Option<InternalEvent>> { pub(crate) fn parse_csi_modifier_key_code(buffer: &[u8]) -> Result<Option<InternalEvent>> {
assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [ assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
let modifier = buffer[buffer.len() - 2]; let modifier_mask = buffer[buffer.len() - 2];
let key = buffer[buffer.len() - 1]; let key = buffer[buffer.len() - 1];
let input_event = match (modifier, key) { let modifiers = parse_modifiers(modifier_mask);
(53, 65) => Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::CONTROL)),
(53, 66) => Event::Key(KeyEvent::new(KeyCode::Down, KeyModifiers::CONTROL)),
(53, 67) => Event::Key(KeyEvent::new(KeyCode::Right, KeyModifiers::CONTROL)),
(53, 68) => Event::Key(KeyEvent::new(KeyCode::Left, KeyModifiers::CONTROL)),
(50, 65) => Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::SHIFT)), let keycode = match key {
(50, 66) => Event::Key(KeyEvent::new(KeyCode::Down, KeyModifiers::SHIFT)), b'A' => KeyCode::Up,
(50, 67) => Event::Key(KeyEvent::new(KeyCode::Right, KeyModifiers::SHIFT)), b'B' => KeyCode::Down,
(50, 68) => Event::Key(KeyEvent::new(KeyCode::Left, KeyModifiers::SHIFT)), b'C' => KeyCode::Right,
b'D' => KeyCode::Left,
b'F' => KeyCode::End,
b'H' => KeyCode::Home,
b'P' => KeyCode::F(1),
b'Q' => KeyCode::F(2),
b'R' => KeyCode::F(3),
b'S' => KeyCode::F(4),
_ => return Err(could_not_parse_event_error()), _ => return Err(could_not_parse_event_error()),
}; };
let input_event = Event::Key(KeyEvent::new(keycode, modifiers));
Ok(Some(InternalEvent::Event(input_event))) Ok(Some(InternalEvent::Event(input_event)))
} }
@ -227,24 +247,27 @@ pub(crate) fn parse_csi_special_key_code(buffer: &[u8]) -> Result<Option<Interna
// This CSI sequence can be a list of semicolon-separated numbers. // This CSI sequence can be a list of semicolon-separated numbers.
let first = next_parsed::<u8>(&mut split)?; let first = next_parsed::<u8>(&mut split)?;
if next_parsed::<u8>(&mut split).is_ok() { let modifiers = if let Ok(modifier_mask) = next_parsed::<u8>(&mut split) {
// TODO: handle multiple values for key modifiers (ex: values [3, 2] means Shift+Delete) parse_modifiers(modifier_mask)
return Err(could_not_parse_event_error()); } else {
} KeyModifiers::NONE
};
let input_event = match first { let keycode = match first {
1 | 7 => Event::Key(KeyCode::Home.into()), 1 | 7 => KeyCode::Home,
2 => Event::Key(KeyCode::Insert.into()), 2 => KeyCode::Insert,
3 => Event::Key(KeyCode::Delete.into()), 3 => KeyCode::Delete,
4 | 8 => Event::Key(KeyCode::End.into()), 4 | 8 => KeyCode::End,
5 => Event::Key(KeyCode::PageUp.into()), 5 => KeyCode::PageUp,
6 => Event::Key(KeyCode::PageDown.into()), 6 => KeyCode::PageDown,
v @ 11..=15 => Event::Key(KeyCode::F(v - 10).into()), v @ 11..=15 => KeyCode::F(v - 10),
v @ 17..=21 => Event::Key(KeyCode::F(v - 11).into()), v @ 17..=21 => KeyCode::F(v - 11),
v @ 23..=24 => Event::Key(KeyCode::F(v - 12).into()), v @ 23..=24 => KeyCode::F(v - 12),
_ => return Err(could_not_parse_event_error()), _ => return Err(could_not_parse_event_error()),
}; };
let input_event = Event::Key(KeyEvent::new(keycode, modifiers));
Ok(Some(InternalEvent::Event(input_event))) Ok(Some(InternalEvent::Event(input_event)))
} }
@ -614,7 +637,13 @@ mod tests {
#[test] #[test]
fn test_parse_csi_special_key_code_multiple_values_not_supported() { fn test_parse_csi_special_key_code_multiple_values_not_supported() {
assert!(parse_csi_special_key_code("\x1B[3;2~".as_bytes()).is_err()); assert_eq!(
parse_csi_special_key_code("\x1B[3;2~".as_bytes()).unwrap(),
Some(InternalEvent::Event(Event::Key(KeyEvent::new(
KeyCode::Delete,
KeyModifiers::SHIFT
)))),
);
} }
#[test] #[test]