From 1dffc4f9551a92c0d43467696543dc82ae764ed5 Mon Sep 17 00:00:00 2001 From: Andrey Kutejko Date: Mon, 18 May 2020 19:12:31 +0200 Subject: [PATCH] Parse key modifiers (#426) - Improved key modifier support. --- src/event/sys/unix/parse.rs | 79 +++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 25 deletions(-) diff --git a/src/event/sys/unix/parse.rs b/src/event/sys/unix/parse.rs index 911154c..3b246d7 100644 --- a/src/event/sys/unix/parse.rs +++ b/src/event/sys/unix/parse.rs @@ -194,25 +194,45 @@ pub(crate) fn parse_csi_cursor_position(buffer: &[u8]) -> Result 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> { 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(&mut split)?; - if next_parsed::(&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::(&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]