aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/input/parse.rs44
1 files changed, 36 insertions, 8 deletions
diff --git a/src/input/parse.rs b/src/input/parse.rs
index 77c630ba..0071596b 100644
--- a/src/input/parse.rs
+++ b/src/input/parse.rs
@@ -13,15 +13,16 @@ pub fn parse_terminal_key_sequence(data: &str) -> Option<TerminalKey> {
fn parse_kitty_key_sequence(data: &str) -> Option<TerminalKey> {
let body = data.strip_prefix("\x1b[")?.strip_suffix('u')?;
- let (main, event_type) = match body.rsplit_once(':') {
- Some((head, tail)) if tail.chars().all(|ch| ch.is_ascii_digit()) && head.contains(';') => {
- (head, Some(tail))
- }
- _ => (body, None),
- };
+ let mut fields = body.split(';');
+ let key_part = fields.next()?;
+ let modifier_part = fields.next().unwrap_or("1");
+ let associated_text = fields.next();
+ if fields.next().is_some() {
+ return None;
+ }
- let (key_part, modifier_part) = main.rsplit_once(';').unwrap_or((main, "1"));
- let modifier = modifier_part.parse::<u8>().ok()?.checked_sub(1)?;
+ let (modifier_text, event_type) = split_modifier_and_event(modifier_part);
+ let modifier = modifier_text.parse::<u8>().ok()?.checked_sub(1)?;
let mut key_fields = key_part.split(':');
let codepoint = key_fields.next()?.parse::<u32>().ok()?;
@@ -30,6 +31,12 @@ fn parse_kitty_key_sequence(data: &str) -> Option<TerminalKey> {
.filter(|field| !field.is_empty())
.and_then(|field| field.parse::<u32>().ok());
+ if let Some(text) = associated_text {
+ if text.parse::<u32>().ok()? != codepoint {
+ return None;
+ }
+ }
+
let code = kitty_codepoint_to_keycode(codepoint)?;
let kind = parse_kitty_event_type(event_type)?;
@@ -593,6 +600,27 @@ mod tests {
}
#[test]
+ fn parse_kitty_sequence_with_associated_emoji_text() {
+ let key = parse_terminal_key_sequence("\x1b[128512;1;128512u").unwrap();
+ assert_terminal_key_eq(
+ key,
+ KeyCode::Char('😀'),
+ KeyModifiers::empty(),
+ crossterm::event::KeyEventKind::Press,
+ None,
+ );
+ }
+
+ #[test]
+ fn reject_unmodeled_kitty_associated_text() {
+ assert_eq!(parse_terminal_key_sequence("\x1b[128512;1;128513u"), None);
+ assert_eq!(
+ parse_terminal_key_sequence("\x1b[128512;1;128512:65039u"),
+ None
+ );
+ }
+
+ #[test]
fn parse_kitty_alt_backspace_sequence() {
let key = parse_terminal_key_sequence("\x1b[127;3u").unwrap();
assert_eq!(key.code, KeyCode::Backspace);