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)))
}
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>> {
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 input_event = match (modifier, key) {
(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)),
let modifiers = parse_modifiers(modifier_mask);
(50, 65) => Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::SHIFT)),
(50, 66) => Event::Key(KeyEvent::new(KeyCode::Down, KeyModifiers::SHIFT)),
(50, 67) => Event::Key(KeyEvent::new(KeyCode::Right, KeyModifiers::SHIFT)),
(50, 68) => Event::Key(KeyEvent::new(KeyCode::Left, KeyModifiers::SHIFT)),
let keycode = match key {
b'A' => KeyCode::Up,
b'B' => KeyCode::Down,
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()),
};
let input_event = Event::Key(KeyEvent::new(keycode, modifiers));
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.
let first = next_parsed::<u8>(&mut split)?;
if next_parsed::<u8>(&mut split).is_ok() {
// TODO: handle multiple values for key modifiers (ex: values [3, 2] means Shift+Delete)
return Err(could_not_parse_event_error());
}
let modifiers = if let Ok(modifier_mask) = next_parsed::<u8>(&mut split) {
parse_modifiers(modifier_mask)
} else {
KeyModifiers::NONE
};
let input_event = match first {
1 | 7 => Event::Key(KeyCode::Home.into()),
2 => Event::Key(KeyCode::Insert.into()),
3 => Event::Key(KeyCode::Delete.into()),
4 | 8 => Event::Key(KeyCode::End.into()),
5 => Event::Key(KeyCode::PageUp.into()),
6 => Event::Key(KeyCode::PageDown.into()),
v @ 11..=15 => Event::Key(KeyCode::F(v - 10).into()),
v @ 17..=21 => Event::Key(KeyCode::F(v - 11).into()),
v @ 23..=24 => Event::Key(KeyCode::F(v - 12).into()),
let keycode = match first {
1 | 7 => KeyCode::Home,
2 => KeyCode::Insert,
3 => KeyCode::Delete,
4 | 8 => KeyCode::End,
5 => KeyCode::PageUp,
6 => KeyCode::PageDown,
v @ 11..=15 => KeyCode::F(v - 10),
v @ 17..=21 => KeyCode::F(v - 11),
v @ 23..=24 => KeyCode::F(v - 12),
_ => return Err(could_not_parse_event_error()),
};
let input_event = Event::Key(KeyEvent::new(keycode, modifiers));
Ok(Some(InternalEvent::Event(input_event)))
}
@ -614,7 +637,13 @@ mod tests {
#[test]
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]