1use crate::vendored::termwiz::keymap::{Found, KeyMap};
4use crate::vendored::termwiz::readbuf::ReadBuffer;
5use bitflags::bitflags;
6use std::fmt::Write;
7
8pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
9
10bitflags! {
11 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
12 pub struct Modifiers: u16 {
13 const NONE = 0;
14 const SHIFT = 1 << 1;
15 const ALT = 1 << 2;
16 const CTRL = 1 << 3;
17 const SUPER = 1 << 4;
18 const LEFT_ALT = 1 << 5;
19 const RIGHT_ALT = 1 << 6;
20 const LEADER = 1 << 7;
21 const LEFT_CTRL = 1 << 8;
22 const RIGHT_CTRL = 1 << 9;
23 const LEFT_SHIFT = 1 << 10;
24 const RIGHT_SHIFT = 1 << 11;
25 const ENHANCED_KEY = 1 << 12;
26 }
27}
28
29impl Modifiers {
30 pub fn encode_xterm(self) -> u8 {
31 let mut number = 0;
32 if self.contains(Self::SHIFT) {
33 number |= 1;
34 }
35 if self.contains(Self::ALT) {
36 number |= 2;
37 }
38 if self.contains(Self::CTRL) {
39 number |= 4;
40 }
41 number
42 }
43
44 pub fn remove_positional_mods(self) -> Self {
45 self - (Self::LEFT_ALT
46 | Self::RIGHT_ALT
47 | Self::LEFT_CTRL
48 | Self::RIGHT_CTRL
49 | Self::LEFT_SHIFT
50 | Self::RIGHT_SHIFT
51 | Self::ENHANCED_KEY)
52 }
53}
54
55bitflags! {
56 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
57 pub struct KittyKeyboardFlags: u16 {
58 const NONE = 0;
59 const DISAMBIGUATE_ESCAPE_CODES = 1;
60 const REPORT_EVENT_TYPES = 2;
61 const REPORT_ALTERNATE_KEYS = 4;
62 const REPORT_ALL_KEYS_AS_ESCAPE_CODES = 8;
63 const REPORT_ASSOCIATED_TEXT = 16;
64 }
65}
66
67pub fn ctrl_mapping(c: char) -> Option<char> {
68 Some(match c {
69 '@' | '`' | ' ' | '2' => '\x00',
70 'A' | 'a' => '\x01',
71 'B' | 'b' => '\x02',
72 'C' | 'c' => '\x03',
73 'D' | 'd' => '\x04',
74 'E' | 'e' => '\x05',
75 'F' | 'f' => '\x06',
76 'G' | 'g' => '\x07',
77 'H' | 'h' => '\x08',
78 'I' | 'i' => '\x09',
79 'J' | 'j' => '\x0a',
80 'K' | 'k' => '\x0b',
81 'L' | 'l' => '\x0c',
82 'M' | 'm' => '\x0d',
83 'N' | 'n' => '\x0e',
84 'O' | 'o' => '\x0f',
85 'P' | 'p' => '\x10',
86 'Q' | 'q' => '\x11',
87 'R' | 'r' => '\x12',
88 'S' | 's' => '\x13',
89 'T' | 't' => '\x14',
90 'U' | 'u' => '\x15',
91 'V' | 'v' => '\x16',
92 'W' | 'w' => '\x17',
93 'X' | 'x' => '\x18',
94 'Y' | 'y' => '\x19',
95 'Z' | 'z' => '\x1a',
96 '[' | '3' | '{' => '\x1b',
97 '\\' | '4' | '|' => '\x1c',
98 ']' | '5' | '}' => '\x1d',
99 '^' | '6' | '~' => '\x1e',
100 '_' | '7' | '/' => '\x1f',
101 '8' | '?' => '\x7f',
102 _ => return None,
103 })
104}
105
106bitflags! {
107 #[derive(Debug, Default, Clone, PartialEq, Eq)]
108 pub struct MouseButtons: u8 {
109 const NONE = 0;
110 const LEFT = 1<<1;
111 const RIGHT = 1<<2;
112 const MIDDLE = 1<<3;
113 const VERT_WHEEL = 1<<4;
114 const HORZ_WHEEL = 1<<5;
115 const WHEEL_POSITIVE = 1<<6;
118 }
119}
120
121pub const CSI: &str = "\x1b[";
122pub const SS3: &str = "\x1bO";
123
124#[derive(Debug, Clone, PartialEq, Eq)]
125pub enum InputEvent {
126 Key(KeyEvent),
127 Mouse(MouseEvent),
128 PixelMouse(PixelMouseEvent),
129 Resized {
131 cols: usize,
132 rows: usize,
133 },
134 Paste(String),
137 Wake,
139 OperatingSystemCommand(Vec<u8>),
142 DeviceControlReply {
150 intermediates: Vec<u8>,
151 params: Vec<u8>,
152 final_byte: u8,
153 raw: Vec<u8>,
154 },
155}
156
157#[derive(Debug, Clone, PartialEq, Eq)]
158pub struct MouseEvent {
159 pub x: u16,
160 pub y: u16,
161 pub mouse_buttons: MouseButtons,
162 pub modifiers: Modifiers,
163}
164
165#[derive(Debug, Clone, PartialEq, Eq)]
166pub struct PixelMouseEvent {
167 pub x_pixels: u16,
168 pub y_pixels: u16,
169 pub mouse_buttons: MouseButtons,
170 pub modifiers: Modifiers,
171}
172
173#[derive(Debug, Clone, PartialEq, Eq)]
174pub struct KeyEvent {
175 pub key: KeyCode,
177 pub modifiers: Modifiers,
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq)]
182pub enum KeyboardEncoding {
183 Xterm,
184 CsiU,
186 Win32,
188 Kitty(KittyKeyboardFlags),
190}
191
192#[derive(Debug, Clone, Copy)]
195pub struct KeyCodeEncodeModes {
196 pub encoding: KeyboardEncoding,
197 pub application_cursor_keys: bool,
198 pub newline_mode: bool,
199 pub modify_other_keys: Option<i64>,
200}
201
202#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
206pub enum KeyCode {
207 Char(char),
209
210 Hyper,
211 Super,
212 Meta,
213
214 Cancel,
216 Backspace,
217 Tab,
218 Clear,
219 Enter,
220 Shift,
221 Escape,
222 LeftShift,
223 RightShift,
224 Control,
225 LeftControl,
226 RightControl,
227 Alt,
228 LeftAlt,
229 RightAlt,
230 Menu,
231 LeftMenu,
232 RightMenu,
233 Pause,
234 CapsLock,
235 PageUp,
236 PageDown,
237 End,
238 Home,
239 LeftArrow,
240 RightArrow,
241 UpArrow,
242 DownArrow,
243 Select,
244 Print,
245 Execute,
246 PrintScreen,
247 Insert,
248 Delete,
249 Help,
250 LeftWindows,
251 RightWindows,
252 Applications,
253 Sleep,
254 Numpad0,
255 Numpad1,
256 Numpad2,
257 Numpad3,
258 Numpad4,
259 Numpad5,
260 Numpad6,
261 Numpad7,
262 Numpad8,
263 Numpad9,
264 Multiply,
265 Add,
266 Separator,
267 Subtract,
268 Decimal,
269 Divide,
270 Function(u8),
272 NumLock,
273 ScrollLock,
274 Copy,
275 Cut,
276 Paste,
277 BrowserBack,
278 BrowserForward,
279 BrowserRefresh,
280 BrowserStop,
281 BrowserSearch,
282 BrowserFavorites,
283 BrowserHome,
284 VolumeMute,
285 VolumeDown,
286 VolumeUp,
287 MediaNextTrack,
288 MediaPrevTrack,
289 MediaStop,
290 MediaPlayPause,
291 ApplicationLeftArrow,
292 ApplicationRightArrow,
293 ApplicationUpArrow,
294 ApplicationDownArrow,
295 KeyPadHome,
296 KeyPadEnd,
297 KeyPadPageUp,
298 KeyPadPageDown,
299 KeyPadBegin,
300
301 #[doc(hidden)]
302 InternalPasteStart,
303 #[doc(hidden)]
304 InternalPasteEnd,
305}
306
307impl KeyCode {
308 pub fn normalize_shift_to_upper_case(self, modifiers: Modifiers) -> KeyCode {
311 if modifiers.contains(Modifiers::SHIFT) {
312 match self {
313 KeyCode::Char(c) if c.is_ascii_lowercase() => KeyCode::Char(c.to_ascii_uppercase()),
314 _ => self,
315 }
316 } else {
317 self
318 }
319 }
320
321 pub fn is_modifier(self) -> bool {
323 matches!(
324 self,
325 Self::Hyper
326 | Self::Super
327 | Self::Meta
328 | Self::Shift
329 | Self::LeftShift
330 | Self::RightShift
331 | Self::Control
332 | Self::LeftControl
333 | Self::RightControl
334 | Self::Alt
335 | Self::LeftAlt
336 | Self::RightAlt
337 | Self::LeftWindows
338 | Self::RightWindows
339 )
340 }
341
342 pub fn encode(
344 &self,
345 mods: Modifiers,
346 modes: KeyCodeEncodeModes,
347 is_down: bool,
348 ) -> Result<String> {
349 if !is_down {
350 return Ok(String::new());
352 }
353 let mods = mods.remove_positional_mods();
356
357 use KeyCode::*;
358
359 let key = self.normalize_shift_to_upper_case(mods);
360 let mods = match key {
363 Char(c)
364 if (c.is_ascii_punctuation() || c.is_ascii_uppercase())
365 && mods.contains(Modifiers::SHIFT) =>
366 {
367 mods & !Modifiers::SHIFT
368 },
369 _ => mods,
370 };
371
372 let key = match key {
374 Char('\x7f') => Delete,
375 Char('\x08') => Backspace,
376 c => c,
377 };
378
379 let mut buf = String::new();
380
381 match key {
384 Char(c)
385 if is_ambiguous_ascii_ctrl(c)
386 && mods.contains(Modifiers::CTRL)
387 && modes.encoding == KeyboardEncoding::CsiU =>
388 {
389 csi_u_encode(&mut buf, c, mods, &modes)?;
390 },
391 Char(c) if c.is_ascii_uppercase() && mods.contains(Modifiers::CTRL) => {
392 csi_u_encode(&mut buf, c, mods, &modes)?;
393 },
394
395 Char(c) if mods.contains(Modifiers::CTRL) && modes.modify_other_keys == Some(2) => {
396 csi_u_encode(&mut buf, c, mods, &modes)?;
397 },
398 Char(c) if mods.contains(Modifiers::CTRL) && ctrl_mapping(c).is_some() => {
399 let c = ctrl_mapping(c).unwrap();
400 if mods.contains(Modifiers::ALT) {
401 buf.push(0x1b as char);
402 }
403 buf.push(c);
404 },
405
406 Char(c)
412 if (c.is_ascii_alphanumeric() || c.is_ascii_punctuation())
413 && mods.contains(Modifiers::ALT) =>
414 {
415 buf.push(0x1b as char);
416 buf.push(c);
417 },
418
419 Backspace => {
420 if mods.contains(Modifiers::CTRL) {
424 csi_u_encode(&mut buf, '\x08', mods, &modes)?;
425 } else if mods.contains(Modifiers::SHIFT) {
426 csi_u_encode(&mut buf, '\x7f', mods, &modes)?;
427 } else {
428 if mods.contains(Modifiers::ALT) {
429 buf.push(0x1b as char);
430 }
431 buf.push('\x7f');
432 }
433 },
434
435 Enter | Escape => {
436 let c = match key {
437 Enter => '\r',
438 Escape => '\x1b',
439 _ => unreachable!(),
440 };
441 if mods.contains(Modifiers::SHIFT) || mods.contains(Modifiers::CTRL) {
442 csi_u_encode(&mut buf, c, mods, &modes)?;
443 } else {
444 if mods.contains(Modifiers::ALT) {
445 buf.push(0x1b as char);
446 }
447 buf.push(c);
448 if modes.newline_mode && key == Enter {
449 buf.push(0x0a as char);
450 }
451 }
452 },
453
454 Tab if !mods.is_empty() && modes.modify_other_keys.is_some() => {
455 csi_u_encode(&mut buf, '\t', mods, &modes)?;
456 },
457
458 Tab => {
459 if mods.contains(Modifiers::ALT) {
460 buf.push(0x1b as char);
461 }
462 let mods = mods & !Modifiers::ALT;
463 if mods == Modifiers::CTRL {
464 buf.push_str("\x1b[9;5u");
465 } else if mods == Modifiers::CTRL | Modifiers::SHIFT {
466 buf.push_str("\x1b[1;5Z");
467 } else if mods == Modifiers::SHIFT {
468 buf.push_str("\x1b[Z");
469 } else {
470 buf.push('\t');
471 }
472 },
473
474 Char(c) => {
475 if mods.is_empty() {
476 buf.push(c);
477 } else {
478 csi_u_encode(&mut buf, c, mods, &modes)?;
479 }
480 },
481
482 Home
483 | KeyPadHome
484 | End
485 | KeyPadEnd
486 | UpArrow
487 | DownArrow
488 | RightArrow
489 | LeftArrow
490 | ApplicationUpArrow
491 | ApplicationDownArrow
492 | ApplicationRightArrow
493 | ApplicationLeftArrow => {
494 let (force_app, c) = match key {
495 UpArrow => (false, 'A'),
496 DownArrow => (false, 'B'),
497 RightArrow => (false, 'C'),
498 LeftArrow => (false, 'D'),
499 KeyPadHome | Home => (false, 'H'),
500 End | KeyPadEnd => (false, 'F'),
501 ApplicationUpArrow => (true, 'A'),
502 ApplicationDownArrow => (true, 'B'),
503 ApplicationRightArrow => (true, 'C'),
504 ApplicationLeftArrow => (true, 'D'),
505 _ => unreachable!(),
506 };
507
508 let csi_or_ss3 = if force_app || modes.application_cursor_keys {
509 SS3
511 } else {
512 CSI
514 };
515
516 if mods.contains(Modifiers::ALT)
517 || mods.contains(Modifiers::SHIFT)
518 || mods.contains(Modifiers::CTRL)
519 {
520 write!(buf, "{}1;{}{}", CSI, 1 + mods.encode_xterm(), c)?;
521 } else {
522 write!(buf, "{}{}", csi_or_ss3, c)?;
523 }
524 },
525
526 PageUp | PageDown | KeyPadPageUp | KeyPadPageDown | Insert | Delete => {
527 let c = match key {
528 Insert => 2,
529 Delete => 3,
530 KeyPadPageUp | PageUp => 5,
531 KeyPadPageDown | PageDown => 6,
532 _ => unreachable!(),
533 };
534
535 if mods.contains(Modifiers::ALT)
536 || mods.contains(Modifiers::SHIFT)
537 || mods.contains(Modifiers::CTRL)
538 {
539 write!(buf, "\x1b[{};{}~", c, 1 + mods.encode_xterm())?;
540 } else {
541 write!(buf, "\x1b[{}~", c)?;
542 }
543 },
544
545 Function(n) => {
546 if mods.is_empty() && n < 5 {
547 write!(
549 buf,
550 "{}",
551 match n {
552 1 => "\x1bOP",
553 2 => "\x1bOQ",
554 3 => "\x1bOR",
555 4 => "\x1bOS",
556 _ => unreachable!("wat?"),
557 }
558 )?;
559 } else if n < 5 {
560 let code = match n {
562 1 => 'P',
563 2 => 'Q',
564 3 => 'R',
565 4 => 'S',
566 _ => unreachable!("wat?"),
567 };
568 write!(buf, "\x1b[1;{}{code}", 1 + mods.encode_xterm())?;
569 } else {
570 let intro = match n {
572 1 => "\x1b[11",
573 2 => "\x1b[12",
574 3 => "\x1b[13",
575 4 => "\x1b[14",
576 5 => "\x1b[15",
577 6 => "\x1b[17",
578 7 => "\x1b[18",
579 8 => "\x1b[19",
580 9 => "\x1b[20",
581 10 => "\x1b[21",
582 11 => "\x1b[23",
583 12 => "\x1b[24",
584 13 => "\x1b[25",
585 14 => "\x1b[26",
586 15 => "\x1b[28",
587 16 => "\x1b[29",
588 17 => "\x1b[31",
589 18 => "\x1b[32",
590 19 => "\x1b[33",
591 20 => "\x1b[34",
592 21 => "\x1b[42",
593 22 => "\x1b[43",
594 23 => "\x1b[44",
595 24 => "\x1b[45",
596 _ => return Err(format!("unhandled fkey number {}", n).into()),
597 };
598 let encoded_mods = mods.encode_xterm();
599 if encoded_mods == 0 {
600 write!(buf, "{}~", intro)?;
603 } else {
604 write!(buf, "{};{}~", intro, 1 + encoded_mods)?;
605 }
606 }
607 },
608
609 Numpad0 | Numpad3 | Numpad9 | Decimal => {
610 let intro = match key {
611 Numpad0 => "\x1b[2",
612 Numpad3 => "\x1b[6",
613 Numpad9 => "\x1b[6",
614 Decimal => "\x1b[3",
615 _ => unreachable!(),
616 };
617
618 let encoded_mods = mods.encode_xterm();
619 if encoded_mods == 0 {
620 write!(buf, "{}~", intro)?;
621 } else {
622 write!(buf, "{};{}~", intro, 1 + encoded_mods)?;
623 }
624 },
625
626 Numpad1 | Numpad2 | Numpad4 | Numpad5 | KeyPadBegin | Numpad6 | Numpad7 | Numpad8 => {
627 let c = match key {
628 Numpad1 => "F",
629 Numpad2 => "B",
630 Numpad4 => "D",
631 KeyPadBegin | Numpad5 => "E",
632 Numpad6 => "C",
633 Numpad7 => "H",
634 Numpad8 => "A",
635 _ => unreachable!(),
636 };
637
638 let encoded_mods = mods.encode_xterm();
639 if encoded_mods == 0 {
640 write!(buf, "{}{}", CSI, c)?;
641 } else {
642 write!(buf, "{}1;{}{}", CSI, 1 + encoded_mods, c)?;
643 }
644 },
645
646 Multiply | Add | Separator | Subtract | Divide => {},
647
648 Control | LeftControl | RightControl | Alt | LeftAlt | RightAlt | Menu | LeftMenu
650 | RightMenu | Super | Hyper | Shift | LeftShift | RightShift | Meta | LeftWindows
651 | RightWindows | NumLock | ScrollLock | Cancel | Clear | Pause | CapsLock | Select
652 | Print | PrintScreen | Execute | Help | Applications | Sleep | Copy | Cut | Paste
653 | BrowserBack | BrowserForward | BrowserRefresh | BrowserStop | BrowserSearch
654 | BrowserFavorites | BrowserHome | VolumeMute | VolumeDown | VolumeUp
655 | MediaNextTrack | MediaPrevTrack | MediaStop | MediaPlayPause | InternalPasteStart
656 | InternalPasteEnd => {},
657 };
658
659 Ok(buf)
660 }
661}
662
663fn is_ambiguous_ascii_ctrl(c: char) -> bool {
667 matches!(c, 'i' | 'I' | 'm' | 'M' | '[' | '{' | '@')
668}
669
670fn is_ascii(c: char) -> bool {
671 (c as u32) < 0x80
672}
673
674fn csi_u_encode(
675 buf: &mut String,
676 c: char,
677 mods: Modifiers,
678 modes: &KeyCodeEncodeModes,
679) -> Result<()> {
680 if modes.encoding == KeyboardEncoding::CsiU && is_ascii(c) {
681 write!(buf, "\x1b[{};{}u", c as u32, 1 + mods.encode_xterm())?;
682 return Ok(());
683 }
684
685 match (c, modes.modify_other_keys) {
687 ('c' | 'd' | '\x1b' | '\x7f' | '\x08', Some(1)) => {
688 },
690 (c, Some(_)) => {
691 write!(buf, "\x1b[27;{};{}~", 1 + mods.encode_xterm(), c as u32)?;
692 return Ok(());
693 },
694 _ => {},
695 }
696
697 let c = if mods.contains(Modifiers::CTRL) && ctrl_mapping(c).is_some() {
698 ctrl_mapping(c).unwrap()
699 } else {
700 c
701 };
702 if mods.contains(Modifiers::ALT) {
703 buf.push(0x1b as char);
704 }
705 write!(buf, "{}", c)?;
706 Ok(())
707}
708
709#[derive(Debug, Clone, Copy, PartialEq, Eq)]
710enum MouseButton {
711 Button1Press,
712 Button1Release,
713 Button1Drag,
714 Button2Press,
715 Button2Release,
716 Button2Drag,
717 Button3Press,
718 Button3Release,
719 Button3Drag,
720 Button4Press,
721 Button4Release,
722 Button5Press,
723 Button5Release,
724 Button6Press,
725 Button6Release,
726 Button7Press,
727 Button7Release,
728 None,
729}
730
731fn decode_mouse_button(control: u8, p0: i64) -> Option<MouseButton> {
732 match (control, p0 & 0b110_0011) {
733 (b'M', 0) => Some(MouseButton::Button1Press),
734 (b'm', 0) => Some(MouseButton::Button1Release),
735 (b'M', 1) => Some(MouseButton::Button2Press),
736 (b'm', 1) => Some(MouseButton::Button2Release),
737 (b'M', 2) => Some(MouseButton::Button3Press),
738 (b'm', 2) => Some(MouseButton::Button3Release),
739 (b'M', 64) => Some(MouseButton::Button4Press),
740 (b'm', 64) => Some(MouseButton::Button4Release),
741 (b'M', 65) => Some(MouseButton::Button5Press),
742 (b'm', 65) => Some(MouseButton::Button5Release),
743 (b'M', 66) => Some(MouseButton::Button6Press),
744 (b'm', 66) => Some(MouseButton::Button6Release),
745 (b'M', 67) => Some(MouseButton::Button7Press),
746 (b'm', 67) => Some(MouseButton::Button7Release),
747 (b'M', 32) => Some(MouseButton::Button1Drag),
748 (b'M', 33) => Some(MouseButton::Button2Drag),
749 (b'M', 34) => Some(MouseButton::Button3Drag),
750 (b'M', 35) | (b'm', 35) | (b'M', 3) | (b'm', 3) => Some(MouseButton::None),
751 _ => ::core::option::Option::None,
752 }
753}
754
755impl From<MouseButton> for MouseButtons {
756 fn from(button: MouseButton) -> MouseButtons {
757 match button {
758 MouseButton::Button1Press | MouseButton::Button1Drag => MouseButtons::LEFT,
759 MouseButton::Button2Press | MouseButton::Button2Drag => MouseButtons::MIDDLE,
760 MouseButton::Button3Press | MouseButton::Button3Drag => MouseButtons::RIGHT,
761 MouseButton::Button4Press => MouseButtons::VERT_WHEEL | MouseButtons::WHEEL_POSITIVE,
762 MouseButton::Button5Press => MouseButtons::VERT_WHEEL,
763 MouseButton::Button6Press => MouseButtons::HORZ_WHEEL | MouseButtons::WHEEL_POSITIVE,
764 MouseButton::Button7Press => MouseButtons::HORZ_WHEEL,
765 _ => MouseButtons::NONE,
766 }
767 }
768}
769
770fn decode_mouse_modifiers(p0: i64) -> Modifiers {
771 let mut modifiers = Modifiers::NONE;
772 if p0 & 4 != 0 {
773 modifiers |= Modifiers::SHIFT;
774 }
775 if p0 & 8 != 0 {
776 modifiers |= Modifiers::ALT;
777 }
778 if p0 & 16 != 0 {
779 modifiers |= Modifiers::CTRL;
780 }
781 modifiers
782}
783
784fn parse_sgr_mouse(buf: &[u8]) -> Option<(InputEvent, usize)> {
788 if buf.len() < 6 || !buf.starts_with(b"\x1b[<") {
790 return None;
791 }
792 let rest = &buf[3..]; let term_pos = rest.iter().position(|&b| b == b'M' || b == b'm')?;
796 let control = rest[term_pos];
797 let params_str = std::str::from_utf8(&rest[..term_pos]).ok()?;
798
799 let mut parts = params_str.splitn(3, ';');
801 let p0: i64 = parts.next()?.parse().ok()?;
802 let p1: i64 = parts.next()?.parse().ok()?;
803 let p2: i64 = parts.next()?.parse().ok()?;
804
805 let button = decode_mouse_button(control, p0)?;
806 let modifiers = decode_mouse_modifiers(p0);
807 let mouse_buttons: MouseButtons = button.into();
808
809 let consumed = 3 + term_pos + 1; Some((
812 InputEvent::Mouse(MouseEvent {
813 x: p1 as u16,
814 y: p2 as u16,
815 mouse_buttons,
816 modifiers,
817 }),
818 consumed,
819 ))
820}
821
822fn complete_csi_len(buf: &[u8]) -> Option<usize> {
854 if buf.get(0) != Some(&0x1b) || buf.get(1) != Some(&b'[') {
855 return None;
856 }
857 let mut i = 2;
858 let max_scan = buf.len().min(256);
859 while i < max_scan {
860 let b = buf[i];
861 match b {
862 0x30..=0x3F | 0x20..=0x2F => i += 1,
864 0x40..=0x7E => return Some(i + 1),
866 _ => return None,
868 }
869 }
870 None
871}
872
873fn parse_csi_report(buf: &[u8]) -> Option<(InputEvent, usize)> {
874 if buf.get(0) != Some(&0x1b) || buf.get(1) != Some(&b'[') {
875 return None;
876 }
877 let mut i = 2;
881 let mut intermediates: Vec<u8> = Vec::new();
882 let mut params: Vec<u8> = Vec::new();
883 let max_scan = buf.len().min(256);
887 while i < max_scan {
888 let b = buf[i];
889 match b {
890 0x30..=0x3F => {
892 params.push(b);
893 i += 1;
894 },
895 0x20..=0x2F => {
897 intermediates.push(b);
898 i += 1;
899 },
900 b't' | b'y' | b'c' | b'n' => {
902 let raw = buf[0..=i].to_vec();
903 return Some((
904 InputEvent::DeviceControlReply {
905 intermediates,
906 params,
907 final_byte: b,
908 raw,
909 },
910 i + 1,
911 ));
912 },
913 0x40..=0x7E => {
914 return None;
916 },
917 _ => {
918 return None;
920 },
921 }
922 }
923 None
924}
925
926fn parse_osc(buf: &[u8]) -> Option<(InputEvent, usize)> {
927 if buf.get(0) != Some(&0x1b) || buf.get(1) != Some(&b']') {
929 return None;
930 }
931 let mut i = 2;
932 while i < buf.len() {
933 match buf.get(i) {
934 Some(&0x07) => {
935 let payload = buf.get(2..i).unwrap_or_default().to_vec();
937 return Some((InputEvent::OperatingSystemCommand(payload), i + 1));
938 },
939 Some(&0x1b) => {
940 if buf.get(i + 1) == Some(&b'\\') {
942 let payload = buf.get(2..i).unwrap_or_default().to_vec();
943 return Some((InputEvent::OperatingSystemCommand(payload), i + 2));
944 }
945 return None;
947 },
948 Some(_) => {
949 i += 1;
950 },
951 None => {
952 return None;
954 },
955 }
956 }
957 None }
959
960#[derive(Debug, Clone, Copy, PartialEq, Eq)]
961enum InputState {
962 Normal,
963 EscapeMaybeAlt,
964 Pasting(usize),
965}
966
967#[derive(Debug)]
968pub struct InputParser {
969 key_map: KeyMap<InputEvent>,
970 buf: ReadBuffer,
971 state: InputState,
972}
973
974#[cfg(windows)]
975mod windows {
976 use super::*;
977 use std;
978 use winapi::um::wincon::{
979 INPUT_RECORD, KEY_EVENT, KEY_EVENT_RECORD, MOUSE_EVENT, MOUSE_EVENT_RECORD,
980 WINDOW_BUFFER_SIZE_EVENT, WINDOW_BUFFER_SIZE_RECORD,
981 };
982 use winapi::um::winuser;
983
984 fn modifiers_from_ctrl_key_state(state: u32) -> Modifiers {
985 use winapi::um::wincon::*;
986
987 let mut mods = Modifiers::NONE;
988
989 if (state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0 {
990 mods |= Modifiers::ALT;
991 }
992
993 if (state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0 {
994 mods |= Modifiers::CTRL;
995 }
996
997 if (state & SHIFT_PRESSED) != 0 {
998 mods |= Modifiers::SHIFT;
999 }
1000
1001 mods
1002 }
1003
1004 impl InputParser {
1005 fn decode_key_record<F: FnMut(InputEvent)>(
1006 &mut self,
1007 event: &KEY_EVENT_RECORD,
1008 callback: &mut F,
1009 ) {
1010 if event.bKeyDown == 0 {
1011 return;
1012 }
1013
1014 let key_code = match std::char::from_u32(*unsafe { event.uChar.UnicodeChar() } as u32) {
1015 Some(unicode) if unicode > '\x00' => {
1016 let mut buf = [0u8; 4];
1017 self.buf
1018 .extend_with(unicode.encode_utf8(&mut buf).as_bytes());
1019 self.process_bytes(callback, true);
1020 return;
1021 },
1022 _ => match event.wVirtualKeyCode as i32 {
1023 winuser::VK_CANCEL => KeyCode::Cancel,
1024 winuser::VK_BACK => KeyCode::Backspace,
1025 winuser::VK_TAB => KeyCode::Tab,
1026 winuser::VK_CLEAR => KeyCode::Clear,
1027 winuser::VK_RETURN => KeyCode::Enter,
1028 winuser::VK_SHIFT => KeyCode::Shift,
1029 winuser::VK_CONTROL => KeyCode::Control,
1030 winuser::VK_MENU => KeyCode::Menu,
1031 winuser::VK_PAUSE => KeyCode::Pause,
1032 winuser::VK_CAPITAL => KeyCode::CapsLock,
1033 winuser::VK_ESCAPE => KeyCode::Escape,
1034 winuser::VK_PRIOR => KeyCode::PageUp,
1035 winuser::VK_NEXT => KeyCode::PageDown,
1036 winuser::VK_END => KeyCode::End,
1037 winuser::VK_HOME => KeyCode::Home,
1038 winuser::VK_LEFT => KeyCode::LeftArrow,
1039 winuser::VK_RIGHT => KeyCode::RightArrow,
1040 winuser::VK_UP => KeyCode::UpArrow,
1041 winuser::VK_DOWN => KeyCode::DownArrow,
1042 winuser::VK_SELECT => KeyCode::Select,
1043 winuser::VK_PRINT => KeyCode::Print,
1044 winuser::VK_EXECUTE => KeyCode::Execute,
1045 winuser::VK_SNAPSHOT => KeyCode::PrintScreen,
1046 winuser::VK_INSERT => KeyCode::Insert,
1047 winuser::VK_DELETE => KeyCode::Delete,
1048 winuser::VK_HELP => KeyCode::Help,
1049 winuser::VK_LWIN => KeyCode::LeftWindows,
1050 winuser::VK_RWIN => KeyCode::RightWindows,
1051 winuser::VK_APPS => KeyCode::Applications,
1052 winuser::VK_SLEEP => KeyCode::Sleep,
1053 winuser::VK_NUMPAD0 => KeyCode::Numpad0,
1054 winuser::VK_NUMPAD1 => KeyCode::Numpad1,
1055 winuser::VK_NUMPAD2 => KeyCode::Numpad2,
1056 winuser::VK_NUMPAD3 => KeyCode::Numpad3,
1057 winuser::VK_NUMPAD4 => KeyCode::Numpad4,
1058 winuser::VK_NUMPAD5 => KeyCode::Numpad5,
1059 winuser::VK_NUMPAD6 => KeyCode::Numpad6,
1060 winuser::VK_NUMPAD7 => KeyCode::Numpad7,
1061 winuser::VK_NUMPAD8 => KeyCode::Numpad8,
1062 winuser::VK_NUMPAD9 => KeyCode::Numpad9,
1063 winuser::VK_MULTIPLY => KeyCode::Multiply,
1064 winuser::VK_ADD => KeyCode::Add,
1065 winuser::VK_SEPARATOR => KeyCode::Separator,
1066 winuser::VK_SUBTRACT => KeyCode::Subtract,
1067 winuser::VK_DECIMAL => KeyCode::Decimal,
1068 winuser::VK_DIVIDE => KeyCode::Divide,
1069 winuser::VK_F1 => KeyCode::Function(1),
1070 winuser::VK_F2 => KeyCode::Function(2),
1071 winuser::VK_F3 => KeyCode::Function(3),
1072 winuser::VK_F4 => KeyCode::Function(4),
1073 winuser::VK_F5 => KeyCode::Function(5),
1074 winuser::VK_F6 => KeyCode::Function(6),
1075 winuser::VK_F7 => KeyCode::Function(7),
1076 winuser::VK_F8 => KeyCode::Function(8),
1077 winuser::VK_F9 => KeyCode::Function(9),
1078 winuser::VK_F10 => KeyCode::Function(10),
1079 winuser::VK_F11 => KeyCode::Function(11),
1080 winuser::VK_F12 => KeyCode::Function(12),
1081 winuser::VK_F13 => KeyCode::Function(13),
1082 winuser::VK_F14 => KeyCode::Function(14),
1083 winuser::VK_F15 => KeyCode::Function(15),
1084 winuser::VK_F16 => KeyCode::Function(16),
1085 winuser::VK_F17 => KeyCode::Function(17),
1086 winuser::VK_F18 => KeyCode::Function(18),
1087 winuser::VK_F19 => KeyCode::Function(19),
1088 winuser::VK_F20 => KeyCode::Function(20),
1089 winuser::VK_F21 => KeyCode::Function(21),
1090 winuser::VK_F22 => KeyCode::Function(22),
1091 winuser::VK_F23 => KeyCode::Function(23),
1092 winuser::VK_F24 => KeyCode::Function(24),
1093 winuser::VK_NUMLOCK => KeyCode::NumLock,
1094 winuser::VK_SCROLL => KeyCode::ScrollLock,
1095 winuser::VK_LSHIFT => KeyCode::LeftShift,
1096 winuser::VK_RSHIFT => KeyCode::RightShift,
1097 winuser::VK_LCONTROL => KeyCode::LeftControl,
1098 winuser::VK_RCONTROL => KeyCode::RightControl,
1099 winuser::VK_LMENU => KeyCode::LeftMenu,
1100 winuser::VK_RMENU => KeyCode::RightMenu,
1101 winuser::VK_BROWSER_BACK => KeyCode::BrowserBack,
1102 winuser::VK_BROWSER_FORWARD => KeyCode::BrowserForward,
1103 winuser::VK_BROWSER_REFRESH => KeyCode::BrowserRefresh,
1104 winuser::VK_BROWSER_STOP => KeyCode::BrowserStop,
1105 winuser::VK_BROWSER_SEARCH => KeyCode::BrowserSearch,
1106 winuser::VK_BROWSER_FAVORITES => KeyCode::BrowserFavorites,
1107 winuser::VK_BROWSER_HOME => KeyCode::BrowserHome,
1108 winuser::VK_VOLUME_MUTE => KeyCode::VolumeMute,
1109 winuser::VK_VOLUME_DOWN => KeyCode::VolumeDown,
1110 winuser::VK_VOLUME_UP => KeyCode::VolumeUp,
1111 winuser::VK_MEDIA_NEXT_TRACK => KeyCode::MediaNextTrack,
1112 winuser::VK_MEDIA_PREV_TRACK => KeyCode::MediaPrevTrack,
1113 winuser::VK_MEDIA_STOP => KeyCode::MediaStop,
1114 winuser::VK_MEDIA_PLAY_PAUSE => KeyCode::MediaPlayPause,
1115 _ => return,
1116 },
1117 };
1118 let mut modifiers = modifiers_from_ctrl_key_state(event.dwControlKeyState);
1119
1120 let key_code = key_code.normalize_shift_to_upper_case(modifiers);
1121 if let KeyCode::Char(c) = key_code {
1122 if c.is_ascii_uppercase() {
1123 modifiers.remove(Modifiers::SHIFT);
1124 }
1125 }
1126
1127 let input_event = InputEvent::Key(KeyEvent {
1128 key: key_code,
1129 modifiers,
1130 });
1131 for _ in 0..event.wRepeatCount {
1132 callback(input_event.clone());
1133 }
1134 }
1135
1136 fn decode_mouse_record<F: FnMut(InputEvent)>(
1137 &self,
1138 event: &MOUSE_EVENT_RECORD,
1139 callback: &mut F,
1140 ) {
1141 use winapi::um::wincon::*;
1142 let mut buttons = MouseButtons::NONE;
1143
1144 if (event.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) != 0 {
1145 buttons |= MouseButtons::LEFT;
1146 }
1147 if (event.dwButtonState & RIGHTMOST_BUTTON_PRESSED) != 0 {
1148 buttons |= MouseButtons::RIGHT;
1149 }
1150 if (event.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) != 0 {
1151 buttons |= MouseButtons::MIDDLE;
1152 }
1153
1154 let modifiers = modifiers_from_ctrl_key_state(event.dwControlKeyState);
1155
1156 if (event.dwEventFlags & MOUSE_WHEELED) != 0 {
1157 buttons |= MouseButtons::VERT_WHEEL;
1158 if (event.dwButtonState >> 8) != 0 {
1159 buttons |= MouseButtons::WHEEL_POSITIVE;
1160 }
1161 } else if (event.dwEventFlags & MOUSE_HWHEELED) != 0 {
1162 buttons |= MouseButtons::HORZ_WHEEL;
1163 if (event.dwButtonState >> 8) != 0 {
1164 buttons |= MouseButtons::WHEEL_POSITIVE;
1165 }
1166 }
1167
1168 let mouse = InputEvent::Mouse(MouseEvent {
1169 x: event.dwMousePosition.X as u16,
1170 y: event.dwMousePosition.Y as u16,
1171 mouse_buttons: buttons,
1172 modifiers,
1173 });
1174
1175 if (event.dwEventFlags & DOUBLE_CLICK) != 0 {
1176 callback(mouse.clone());
1177 }
1178 callback(mouse);
1179 }
1180
1181 fn decode_resize_record<F: FnMut(InputEvent)>(
1182 &self,
1183 event: &WINDOW_BUFFER_SIZE_RECORD,
1184 callback: &mut F,
1185 ) {
1186 callback(InputEvent::Resized {
1187 rows: event.dwSize.Y as usize,
1188 cols: event.dwSize.X as usize,
1189 });
1190 }
1191
1192 pub fn decode_input_records<F: FnMut(InputEvent)>(
1193 &mut self,
1194 records: &[INPUT_RECORD],
1195 callback: &mut F,
1196 ) {
1197 for record in records {
1198 match record.EventType {
1199 KEY_EVENT => {
1200 self.decode_key_record(unsafe { record.Event.KeyEvent() }, callback)
1201 },
1202 MOUSE_EVENT => {
1203 self.decode_mouse_record(unsafe { record.Event.MouseEvent() }, callback)
1204 },
1205 WINDOW_BUFFER_SIZE_EVENT => self.decode_resize_record(
1206 unsafe { record.Event.WindowBufferSizeEvent() },
1207 callback,
1208 ),
1209 _ => {},
1210 }
1211 }
1212 self.process_bytes(callback, false);
1213 }
1214 }
1215}
1216
1217impl Default for InputParser {
1218 fn default() -> Self {
1219 Self::new()
1220 }
1221}
1222
1223impl InputParser {
1224 pub fn new() -> Self {
1225 Self {
1226 key_map: Self::build_basic_key_map(),
1227 buf: ReadBuffer::new(),
1228 state: InputState::Normal,
1229 }
1230 }
1231
1232 fn build_basic_key_map() -> KeyMap<InputEvent> {
1233 let mut map = KeyMap::new();
1234
1235 let modifier_combos = &[
1236 ("", Modifiers::NONE),
1237 (";1", Modifiers::NONE),
1238 (";2", Modifiers::SHIFT),
1239 (";3", Modifiers::ALT),
1240 (";4", Modifiers::ALT | Modifiers::SHIFT),
1241 (";5", Modifiers::CTRL),
1242 (";6", Modifiers::CTRL | Modifiers::SHIFT),
1243 (";7", Modifiers::CTRL | Modifiers::ALT),
1244 (";8", Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT),
1245 ];
1246 let meta = Modifiers::ALT;
1247 let meta_modifier_combos = &[
1248 (";9", meta),
1249 (";10", meta | Modifiers::SHIFT),
1250 (";11", meta | Modifiers::ALT),
1251 (";12", meta | Modifiers::ALT | Modifiers::SHIFT),
1252 (";13", meta | Modifiers::CTRL),
1253 (";14", meta | Modifiers::CTRL | Modifiers::SHIFT),
1254 (";15", meta | Modifiers::CTRL | Modifiers::ALT),
1255 (
1256 ";16",
1257 meta | Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
1258 ),
1259 ];
1260
1261 let modifier_combos_including_meta =
1262 || modifier_combos.iter().chain(meta_modifier_combos.iter());
1263
1264 for alpha in b'A'..=b'Z' {
1265 let ctrl = [alpha & 0x1f];
1267 map.insert(
1268 &ctrl,
1269 InputEvent::Key(KeyEvent {
1270 key: KeyCode::Char((alpha as char).to_ascii_lowercase()),
1271 modifiers: Modifiers::CTRL,
1272 }),
1273 );
1274
1275 let alt = [0x1b, alpha];
1277 map.insert(
1278 &alt,
1279 InputEvent::Key(KeyEvent {
1280 key: KeyCode::Char(alpha as char),
1281 modifiers: Modifiers::ALT,
1282 }),
1283 );
1284 }
1285
1286 for c in 0..=0x7fu8 {
1287 for (suffix, modifiers) in modifier_combos {
1288 let key = format!("\x1b[{}{}u", c, suffix);
1291 map.insert(
1292 key,
1293 InputEvent::Key(KeyEvent {
1294 key: KeyCode::Char(c as char),
1295 modifiers: *modifiers,
1296 }),
1297 );
1298
1299 if !suffix.is_empty() {
1300 let key = format!("\x1b[27{};{}~", suffix, c);
1302 map.insert(
1303 key,
1304 InputEvent::Key(KeyEvent {
1305 key: match c {
1306 8 | 0x7f => KeyCode::Backspace,
1307 0x1b => KeyCode::Escape,
1308 9 => KeyCode::Tab,
1309 10 | 13 => KeyCode::Enter,
1310 _ => KeyCode::Char(c as char),
1311 },
1312 modifiers: *modifiers,
1313 }),
1314 );
1315 }
1316 }
1317 }
1318
1319 for (keycode, dir) in &[
1321 (KeyCode::UpArrow, b'A'),
1322 (KeyCode::DownArrow, b'B'),
1323 (KeyCode::RightArrow, b'C'),
1324 (KeyCode::LeftArrow, b'D'),
1325 (KeyCode::Home, b'H'),
1326 (KeyCode::End, b'F'),
1327 ] {
1328 let arrow = [0x1b, b'[', *dir];
1330 map.insert(
1331 &arrow,
1332 InputEvent::Key(KeyEvent {
1333 key: *keycode,
1334 modifiers: Modifiers::NONE,
1335 }),
1336 );
1337 for (suffix, modifiers) in modifier_combos_including_meta() {
1338 let key = format!("\x1b[1{}{}", suffix, *dir as char);
1339 map.insert(
1340 key,
1341 InputEvent::Key(KeyEvent {
1342 key: *keycode,
1343 modifiers: *modifiers,
1344 }),
1345 );
1346 }
1347 }
1348 for &(keycode, dir) in &[
1349 (KeyCode::UpArrow, b'a'),
1350 (KeyCode::DownArrow, b'b'),
1351 (KeyCode::RightArrow, b'c'),
1352 (KeyCode::LeftArrow, b'd'),
1353 ] {
1354 for &(seq, mods) in &[
1356 ([0x1b, b'[', dir], Modifiers::SHIFT),
1357 ([0x1b, b'O', dir], Modifiers::CTRL),
1358 ] {
1359 map.insert(
1360 &seq,
1361 InputEvent::Key(KeyEvent {
1362 key: keycode,
1363 modifiers: mods,
1364 }),
1365 );
1366 }
1367 }
1368
1369 for (keycode, dir) in &[
1370 (KeyCode::ApplicationUpArrow, b'A'),
1371 (KeyCode::ApplicationDownArrow, b'B'),
1372 (KeyCode::ApplicationRightArrow, b'C'),
1373 (KeyCode::ApplicationLeftArrow, b'D'),
1374 ] {
1375 let app = [0x1b, b'O', *dir];
1377 map.insert(
1378 &app,
1379 InputEvent::Key(KeyEvent {
1380 key: *keycode,
1381 modifiers: Modifiers::NONE,
1382 }),
1383 );
1384 for (suffix, modifiers) in modifier_combos {
1385 let key = format!("\x1bO1{}{}", suffix, *dir as char);
1386 map.insert(
1387 key,
1388 InputEvent::Key(KeyEvent {
1389 key: *keycode,
1390 modifiers: *modifiers,
1391 }),
1392 );
1393 }
1394 }
1395
1396 for (keycode, c) in &[
1398 (KeyCode::Function(1), b'P'),
1399 (KeyCode::Function(2), b'Q'),
1400 (KeyCode::Function(3), b'R'),
1401 (KeyCode::Function(4), b'S'),
1402 ] {
1403 let key = [0x1b, b'O', *c];
1404 map.insert(
1405 &key,
1406 InputEvent::Key(KeyEvent {
1407 key: *keycode,
1408 modifiers: Modifiers::NONE,
1409 }),
1410 );
1411 }
1412
1413 for (keycode, c) in &[
1415 (KeyCode::Function(1), b'P'),
1416 (KeyCode::Function(2), b'Q'),
1417 (KeyCode::Function(3), b'R'),
1418 (KeyCode::Function(4), b'S'),
1419 ] {
1420 for (suffix, modifiers) in modifier_combos_including_meta() {
1421 let key = format!("\x1b[1{suffix}{code}", code = *c as char, suffix = suffix);
1422 map.insert(
1423 key,
1424 InputEvent::Key(KeyEvent {
1425 key: *keycode,
1426 modifiers: *modifiers,
1427 }),
1428 );
1429 }
1430 }
1431
1432 for (range, offset) in &[
1435 (1..=5, 10),
1437 (6..=10, 11),
1439 (11..=14, 12),
1441 (15..=16, 13),
1443 (17..=20, 14),
1445 ] {
1446 for n in range.clone() {
1447 for (suffix, modifiers) in modifier_combos_including_meta() {
1448 let key = format!("\x1b[{code}{suffix}~", code = n + offset, suffix = suffix);
1449 map.insert(
1450 key,
1451 InputEvent::Key(KeyEvent {
1452 key: KeyCode::Function(n),
1453 modifiers: *modifiers,
1454 }),
1455 );
1456 }
1457 }
1458 }
1459
1460 for (keycode, c) in &[
1461 (KeyCode::Insert, b'2'),
1462 (KeyCode::Delete, b'3'),
1463 (KeyCode::Home, b'1'),
1464 (KeyCode::End, b'4'),
1465 (KeyCode::PageUp, b'5'),
1466 (KeyCode::PageDown, b'6'),
1467 (KeyCode::Home, b'7'),
1469 (KeyCode::End, b'8'),
1470 ] {
1471 for (suffix, modifiers) in &[
1472 (b'~', Modifiers::NONE),
1473 (b'$', Modifiers::SHIFT),
1474 (b'^', Modifiers::CTRL),
1475 (b'@', Modifiers::SHIFT | Modifiers::CTRL),
1476 ] {
1477 let key = [0x1b, b'[', *c, *suffix];
1478 map.insert(
1479 key,
1480 InputEvent::Key(KeyEvent {
1481 key: *keycode,
1482 modifiers: *modifiers,
1483 }),
1484 );
1485 }
1486 }
1487
1488 map.insert(
1489 &[0x7f],
1490 InputEvent::Key(KeyEvent {
1491 key: KeyCode::Backspace,
1492 modifiers: Modifiers::NONE,
1493 }),
1494 );
1495
1496 map.insert(
1497 &[0x8],
1498 InputEvent::Key(KeyEvent {
1499 key: KeyCode::Backspace,
1500 modifiers: Modifiers::NONE,
1501 }),
1502 );
1503
1504 map.insert(
1505 &[0x1b],
1506 InputEvent::Key(KeyEvent {
1507 key: KeyCode::Escape,
1508 modifiers: Modifiers::NONE,
1509 }),
1510 );
1511
1512 map.insert(
1513 &[b'\t'],
1514 InputEvent::Key(KeyEvent {
1515 key: KeyCode::Tab,
1516 modifiers: Modifiers::NONE,
1517 }),
1518 );
1519 map.insert(
1520 b"\x1b[Z",
1521 InputEvent::Key(KeyEvent {
1522 key: KeyCode::Tab,
1523 modifiers: Modifiers::SHIFT,
1524 }),
1525 );
1526
1527 map.insert(
1528 &[b'\r'],
1529 InputEvent::Key(KeyEvent {
1530 key: KeyCode::Enter,
1531 modifiers: Modifiers::NONE,
1532 }),
1533 );
1534 map.insert(
1535 &[b'\n'],
1536 InputEvent::Key(KeyEvent {
1537 key: KeyCode::Enter,
1538 modifiers: Modifiers::NONE,
1539 }),
1540 );
1541
1542 map.insert(
1543 b"\x1b[200~",
1544 InputEvent::Key(KeyEvent {
1545 key: KeyCode::InternalPasteStart,
1546 modifiers: Modifiers::NONE,
1547 }),
1548 );
1549 map.insert(
1550 b"\x1b[201~",
1551 InputEvent::Key(KeyEvent {
1552 key: KeyCode::InternalPasteEnd,
1553 modifiers: Modifiers::NONE,
1554 }),
1555 );
1556 map.insert(
1557 b"\x1b[",
1558 InputEvent::Key(KeyEvent {
1559 key: KeyCode::Char('['),
1560 modifiers: Modifiers::ALT,
1561 }),
1562 );
1563
1564 map
1565 }
1566
1567 fn first_char_and_len(s: &str) -> (char, usize) {
1570 let mut iter = s.chars();
1571 let c = iter.next().unwrap();
1572 (c, c.len_utf8())
1573 }
1574
1575 fn decode_one_char(bytes: &[u8]) -> Option<(char, usize)> {
1578 let bytes = &bytes[..bytes.len().min(4)];
1579 match std::str::from_utf8(bytes) {
1580 Ok(s) => {
1581 let (c, len) = Self::first_char_and_len(s);
1582 Some((c, len))
1583 },
1584 Err(err) => {
1585 let (valid, _after_valid) = bytes.split_at(err.valid_up_to());
1586 if !valid.is_empty() {
1587 let s = unsafe { std::str::from_utf8_unchecked(valid) };
1588 let (c, len) = Self::first_char_and_len(s);
1589 Some((c, len))
1590 } else {
1591 None
1592 }
1593 },
1594 }
1595 }
1596
1597 fn dispatch_callback<F: FnMut(InputEvent)>(&mut self, mut callback: F, event: InputEvent) {
1598 match (self.state, &event) {
1599 (
1600 InputState::Normal,
1601 InputEvent::Key(KeyEvent {
1602 key: KeyCode::InternalPasteStart,
1603 ..
1604 }),
1605 ) => {
1606 self.state = InputState::Pasting(0);
1607 },
1608 (
1609 InputState::EscapeMaybeAlt,
1610 InputEvent::Key(KeyEvent {
1611 key: KeyCode::InternalPasteStart,
1612 ..
1613 }),
1614 ) => {
1615 callback(InputEvent::Key(KeyEvent {
1618 key: KeyCode::Escape,
1619 modifiers: Modifiers::NONE,
1620 }));
1621 self.state = InputState::Pasting(0);
1622 },
1623 (InputState::EscapeMaybeAlt, InputEvent::Key(KeyEvent { key, modifiers })) => {
1624 let key = *key;
1626 let modifiers = *modifiers;
1627 self.state = InputState::Normal;
1628 callback(InputEvent::Key(KeyEvent {
1629 key,
1630 modifiers: modifiers | Modifiers::ALT,
1631 }));
1632 },
1633 (InputState::EscapeMaybeAlt, _) => {
1634 callback(InputEvent::Key(KeyEvent {
1637 key: KeyCode::Escape,
1638 modifiers: Modifiers::NONE,
1639 }));
1640 callback(event);
1641 },
1642 (_, _) => callback(event),
1643 }
1644 }
1645
1646 fn flush_parked_esc_if_held<F: FnMut(InputEvent)>(&mut self, callback: &mut F) {
1654 if self.state == InputState::EscapeMaybeAlt {
1655 callback(InputEvent::Key(KeyEvent {
1656 key: KeyCode::Escape,
1657 modifiers: Modifiers::NONE,
1658 }));
1659 self.state = InputState::Normal;
1660 }
1661 }
1662
1663 fn process_bytes<F: FnMut(InputEvent)>(&mut self, mut callback: F, maybe_more: bool) {
1664 while !self.buf.is_empty() {
1665 match self.state {
1666 InputState::Pasting(offset) => {
1667 let end_paste = b"\x1b[201~";
1668 if let Some(idx) = self.buf.find_subsequence(offset, end_paste) {
1669 let pasted =
1670 String::from_utf8_lossy(&self.buf.as_slice()[0..idx]).to_string();
1671 self.buf.advance(pasted.len() + end_paste.len());
1672 callback(InputEvent::Paste(pasted));
1673 self.state = InputState::Normal;
1674 } else {
1675 self.state =
1676 InputState::Pasting(self.buf.len().saturating_sub(end_paste.len()));
1677 return;
1678 }
1679 },
1680 InputState::EscapeMaybeAlt | InputState::Normal => {
1681 if self.buf.as_slice().get(0) == Some(&b'\x1b') {
1693 if let Some((event, len)) = parse_sgr_mouse(self.buf.as_slice()) {
1694 self.flush_parked_esc_if_held(&mut callback);
1695 self.buf.advance(len);
1696 callback(event);
1697 continue;
1698 }
1699
1700 if let Some((event, len)) = parse_osc(self.buf.as_slice()) {
1702 self.flush_parked_esc_if_held(&mut callback);
1703 self.buf.advance(len);
1704 callback(event);
1705 continue;
1706 }
1707
1708 if maybe_more && self.buf.as_slice().starts_with(b"\x1b]") {
1710 self.flush_parked_esc_if_held(&mut callback);
1711 return;
1712 }
1713
1714 if maybe_more && self.buf.as_slice().starts_with(b"\x1b[<") {
1715 self.flush_parked_esc_if_held(&mut callback);
1716 return;
1717 }
1718
1719 if let Some((event, len)) = parse_csi_report(self.buf.as_slice()) {
1725 self.flush_parked_esc_if_held(&mut callback);
1726 self.buf.advance(len);
1727 callback(event);
1728 continue;
1729 }
1730
1731 if maybe_more && self.buf.as_slice().starts_with(b"\x1b[?") {
1736 self.flush_parked_esc_if_held(&mut callback);
1737 return;
1738 }
1739 }
1740
1741 match (
1742 self.key_map.lookup(self.buf.as_slice(), maybe_more),
1743 maybe_more,
1744 ) {
1745 (
1751 Found::Exact(
1752 len,
1753 InputEvent::Key(KeyEvent {
1754 key: KeyCode::Escape,
1755 modifiers: Modifiers::NONE,
1756 }),
1757 ),
1758 _,
1759 ) if self.state == InputState::Normal && self.buf.len() > len => {
1760 self.state = InputState::EscapeMaybeAlt;
1761 self.buf.advance(len);
1762 },
1763 (Found::Exact(len, event), _) | (Found::Ambiguous(len, event), false) => {
1764 self.dispatch_callback(&mut callback, event.clone());
1765 self.buf.advance(len);
1766 },
1767 (Found::Ambiguous(_, _), true) | (Found::NeedData, true) => {
1768 if let Some(len) = complete_csi_len(self.buf.as_slice()) {
1801 self.buf.advance(len);
1802 continue;
1803 }
1804 return;
1805 },
1806 (Found::None, _) | (Found::NeedData, false) => {
1807 if let Some((c, len)) = Self::decode_one_char(self.buf.as_slice()) {
1809 self.buf.advance(len);
1810 self.dispatch_callback(
1811 &mut callback,
1812 InputEvent::Key(KeyEvent {
1813 key: KeyCode::Char(c),
1814 modifiers: Modifiers::NONE,
1815 }),
1816 );
1817 } else {
1818 return;
1821 }
1822 },
1823 }
1824 },
1825 }
1826 }
1827 }
1828
1829 pub fn parse<F: FnMut(InputEvent)>(&mut self, bytes: &[u8], callback: F, maybe_more: bool) {
1844 self.buf.extend_with(bytes);
1845 self.process_bytes(callback, maybe_more);
1846 }
1847
1848 pub fn parse_as_vec(&mut self, bytes: &[u8], maybe_more: bool) -> Vec<InputEvent> {
1849 let mut result = Vec::new();
1850 self.parse(bytes, |event| result.push(event), maybe_more);
1851 result
1852 }
1853
1854 #[cfg(windows)]
1855 pub fn decode_input_records_as_vec(
1856 &mut self,
1857 records: &[winapi::um::wincon::INPUT_RECORD],
1858 ) -> Vec<InputEvent> {
1859 let mut result = Vec::new();
1860 self.decode_input_records(records, &mut |event| result.push(event));
1861 result
1862 }
1863}
1864
1865#[cfg(test)]
1866mod test {
1867 use super::*;
1868
1869 const NO_MORE: bool = false;
1870 const MAYBE_MORE: bool = true;
1871
1872 #[test]
1873 fn simple() {
1874 let mut p = InputParser::new();
1875 let inputs = p.parse_as_vec(b"hello", NO_MORE);
1876 assert_eq!(
1877 vec![
1878 InputEvent::Key(KeyEvent {
1879 modifiers: Modifiers::NONE,
1880 key: KeyCode::Char('h'),
1881 }),
1882 InputEvent::Key(KeyEvent {
1883 modifiers: Modifiers::NONE,
1884 key: KeyCode::Char('e'),
1885 }),
1886 InputEvent::Key(KeyEvent {
1887 modifiers: Modifiers::NONE,
1888 key: KeyCode::Char('l'),
1889 }),
1890 InputEvent::Key(KeyEvent {
1891 modifiers: Modifiers::NONE,
1892 key: KeyCode::Char('l'),
1893 }),
1894 InputEvent::Key(KeyEvent {
1895 modifiers: Modifiers::NONE,
1896 key: KeyCode::Char('o'),
1897 }),
1898 ],
1899 inputs
1900 );
1901 }
1902
1903 #[test]
1904 fn control_characters() {
1905 let mut p = InputParser::new();
1906 let inputs = p.parse_as_vec(b"\x03\x1bJ\x7f", NO_MORE);
1907 assert_eq!(
1908 vec![
1909 InputEvent::Key(KeyEvent {
1910 modifiers: Modifiers::CTRL,
1911 key: KeyCode::Char('c'),
1912 }),
1913 InputEvent::Key(KeyEvent {
1914 modifiers: Modifiers::ALT,
1915 key: KeyCode::Char('J'),
1916 }),
1917 InputEvent::Key(KeyEvent {
1918 modifiers: Modifiers::NONE,
1919 key: KeyCode::Backspace,
1920 }),
1921 ],
1922 inputs
1923 );
1924 }
1925
1926 #[test]
1927 fn arrow_keys() {
1928 let mut p = InputParser::new();
1929 let inputs = p.parse_as_vec(b"\x1bOA\x1bOB\x1bOC\x1bOD", NO_MORE);
1930 assert_eq!(
1931 vec![
1932 InputEvent::Key(KeyEvent {
1933 modifiers: Modifiers::NONE,
1934 key: KeyCode::ApplicationUpArrow,
1935 }),
1936 InputEvent::Key(KeyEvent {
1937 modifiers: Modifiers::NONE,
1938 key: KeyCode::ApplicationDownArrow,
1939 }),
1940 InputEvent::Key(KeyEvent {
1941 modifiers: Modifiers::NONE,
1942 key: KeyCode::ApplicationRightArrow,
1943 }),
1944 InputEvent::Key(KeyEvent {
1945 modifiers: Modifiers::NONE,
1946 key: KeyCode::ApplicationLeftArrow,
1947 }),
1948 ],
1949 inputs
1950 );
1951 }
1952
1953 #[test]
1954 fn partial() {
1955 let mut p = InputParser::new();
1956 let mut inputs = Vec::new();
1957 p.parse(b"\x1b[11", |evt| inputs.push(evt), true);
1959 p.parse(b"~", |evt| inputs.push(evt), true);
1960 assert_eq!(
1962 vec![InputEvent::Key(KeyEvent {
1963 modifiers: Modifiers::NONE,
1964 key: KeyCode::Function(1),
1965 })],
1966 inputs
1967 );
1968 }
1969
1970 #[test]
1971 fn partial_ambig() {
1972 let mut p = InputParser::new();
1973
1974 assert_eq!(
1975 vec![InputEvent::Key(KeyEvent {
1976 key: KeyCode::Escape,
1977 modifiers: Modifiers::NONE,
1978 })],
1979 p.parse_as_vec(b"\x1b", false)
1980 );
1981
1982 let mut inputs = Vec::new();
1983 p.parse(b"\x1b[11", |evt| inputs.push(evt), MAYBE_MORE);
1985 p.parse(b"", |evt| inputs.push(evt), NO_MORE);
1986 assert_eq!(
1989 vec![
1990 InputEvent::Key(KeyEvent {
1991 modifiers: Modifiers::ALT,
1992 key: KeyCode::Char('['),
1993 }),
1994 InputEvent::Key(KeyEvent {
1995 modifiers: Modifiers::NONE,
1996 key: KeyCode::Char('1'),
1997 }),
1998 InputEvent::Key(KeyEvent {
1999 modifiers: Modifiers::NONE,
2000 key: KeyCode::Char('1'),
2001 }),
2002 ],
2003 inputs
2004 );
2005 }
2006
2007 #[test]
2008 fn partial_mouse() {
2009 let mut p = InputParser::new();
2010 let mut inputs = Vec::new();
2011 p.parse(b"\x1b[<0;0;0", |evt| inputs.push(evt), true);
2013 p.parse(b"M", |evt| inputs.push(evt), true);
2014 assert_eq!(
2016 vec![InputEvent::Mouse(MouseEvent {
2017 x: 0,
2018 y: 0,
2019 mouse_buttons: MouseButtons::LEFT,
2020 modifiers: Modifiers::NONE,
2021 })],
2022 inputs
2023 );
2024 }
2025
2026 #[test]
2027 fn partial_mouse_ambig() {
2028 let mut p = InputParser::new();
2029 let mut inputs = Vec::new();
2030 p.parse(b"\x1b[<", |evt| inputs.push(evt), MAYBE_MORE);
2032 p.parse(b"0;0;0", |evt| inputs.push(evt), NO_MORE);
2033 assert_eq!(
2036 vec![
2037 InputEvent::Key(KeyEvent {
2038 modifiers: Modifiers::ALT,
2039 key: KeyCode::Char('['),
2040 }),
2041 InputEvent::Key(KeyEvent {
2042 modifiers: Modifiers::NONE,
2043 key: KeyCode::Char('<'),
2044 }),
2045 InputEvent::Key(KeyEvent {
2046 modifiers: Modifiers::NONE,
2047 key: KeyCode::Char('0'),
2048 }),
2049 InputEvent::Key(KeyEvent {
2050 modifiers: Modifiers::NONE,
2051 key: KeyCode::Char(';'),
2052 }),
2053 InputEvent::Key(KeyEvent {
2054 modifiers: Modifiers::NONE,
2055 key: KeyCode::Char('0'),
2056 }),
2057 InputEvent::Key(KeyEvent {
2058 modifiers: Modifiers::NONE,
2059 key: KeyCode::Char(';'),
2060 }),
2061 InputEvent::Key(KeyEvent {
2062 modifiers: Modifiers::NONE,
2063 key: KeyCode::Char('0'),
2064 }),
2065 ],
2066 inputs
2067 );
2068 }
2069
2070 #[test]
2071 fn alt_left_bracket() {
2072 let mut p = InputParser::new();
2075
2076 let mut inputs = Vec::new();
2077 p.parse(b"\x1b[", |evt| inputs.push(evt), false);
2078
2079 assert_eq!(
2080 vec![InputEvent::Key(KeyEvent {
2081 modifiers: Modifiers::ALT,
2082 key: KeyCode::Char('['),
2083 }),],
2084 inputs
2085 );
2086 }
2087
2088 #[test]
2089 fn modify_other_keys_parse() {
2090 let mut p = InputParser::new();
2091 let inputs = p.parse_as_vec(
2092 b"\x1b[27;5;13~\x1b[27;5;9~\x1b[27;6;8~\x1b[27;2;127~\x1b[27;6;27~",
2093 NO_MORE,
2094 );
2095 assert_eq!(
2096 vec![
2097 InputEvent::Key(KeyEvent {
2098 key: KeyCode::Enter,
2099 modifiers: Modifiers::CTRL,
2100 }),
2101 InputEvent::Key(KeyEvent {
2102 key: KeyCode::Tab,
2103 modifiers: Modifiers::CTRL,
2104 }),
2105 InputEvent::Key(KeyEvent {
2106 key: KeyCode::Backspace,
2107 modifiers: Modifiers::CTRL | Modifiers::SHIFT,
2108 }),
2109 InputEvent::Key(KeyEvent {
2110 key: KeyCode::Backspace,
2111 modifiers: Modifiers::SHIFT,
2112 }),
2113 InputEvent::Key(KeyEvent {
2114 key: KeyCode::Escape,
2115 modifiers: Modifiers::CTRL | Modifiers::SHIFT,
2116 }),
2117 ],
2118 inputs
2119 );
2120 }
2121
2122 #[test]
2123 fn modify_other_keys_encode() {
2124 let mode = KeyCodeEncodeModes {
2125 encoding: KeyboardEncoding::Xterm,
2126 newline_mode: false,
2127 application_cursor_keys: false,
2128 modify_other_keys: None,
2129 };
2130 let mode_1 = KeyCodeEncodeModes {
2131 encoding: KeyboardEncoding::Xterm,
2132 newline_mode: false,
2133 application_cursor_keys: false,
2134 modify_other_keys: Some(1),
2135 };
2136 let mode_2 = KeyCodeEncodeModes {
2137 encoding: KeyboardEncoding::Xterm,
2138 newline_mode: false,
2139 application_cursor_keys: false,
2140 modify_other_keys: Some(2),
2141 };
2142
2143 assert_eq!(
2144 KeyCode::Enter.encode(Modifiers::CTRL, mode, true).unwrap(),
2145 "\r".to_string()
2146 );
2147 assert_eq!(
2148 KeyCode::Enter
2149 .encode(Modifiers::CTRL, mode_1, true)
2150 .unwrap(),
2151 "\x1b[27;5;13~".to_string()
2152 );
2153 assert_eq!(
2154 KeyCode::Enter
2155 .encode(Modifiers::CTRL | Modifiers::SHIFT, mode_1, true)
2156 .unwrap(),
2157 "\x1b[27;6;13~".to_string()
2158 );
2159
2160 assert_eq!(
2164 KeyCode::Tab.encode(Modifiers::CTRL, mode, true).unwrap(),
2165 "\x1b[9;5u".to_string()
2166 );
2167 assert_eq!(
2168 KeyCode::Tab.encode(Modifiers::CTRL, mode_1, true).unwrap(),
2169 "\x1b[27;5;9~".to_string()
2170 );
2171 assert_eq!(
2172 KeyCode::Tab
2173 .encode(Modifiers::CTRL | Modifiers::SHIFT, mode_1, true)
2174 .unwrap(),
2175 "\x1b[27;6;9~".to_string()
2176 );
2177
2178 assert_eq!(
2179 KeyCode::Char('c')
2180 .encode(Modifiers::CTRL, mode, true)
2181 .unwrap(),
2182 "\x03".to_string()
2183 );
2184 assert_eq!(
2185 KeyCode::Char('c')
2186 .encode(Modifiers::CTRL, mode_1, true)
2187 .unwrap(),
2188 "\x03".to_string()
2189 );
2190 assert_eq!(
2191 KeyCode::Char('c')
2192 .encode(Modifiers::CTRL, mode_2, true)
2193 .unwrap(),
2194 "\x1b[27;5;99~".to_string()
2195 );
2196
2197 assert_eq!(
2198 KeyCode::Char('1')
2199 .encode(Modifiers::CTRL, mode, true)
2200 .unwrap(),
2201 "1".to_string()
2202 );
2203 assert_eq!(
2204 KeyCode::Char('1')
2205 .encode(Modifiers::CTRL, mode_2, true)
2206 .unwrap(),
2207 "\x1b[27;5;49~".to_string()
2208 );
2209
2210 assert_eq!(
2211 KeyCode::Char(',')
2212 .encode(Modifiers::CTRL, mode, true)
2213 .unwrap(),
2214 ",".to_string()
2215 );
2216 assert_eq!(
2217 KeyCode::Char(',')
2218 .encode(Modifiers::CTRL, mode_2, true)
2219 .unwrap(),
2220 "\x1b[27;5;44~".to_string()
2221 );
2222 }
2223
2224 #[test]
2225 fn encode_issue_892() {
2226 let mode = KeyCodeEncodeModes {
2227 encoding: KeyboardEncoding::Xterm,
2228 newline_mode: false,
2229 application_cursor_keys: false,
2230 modify_other_keys: None,
2231 };
2232
2233 assert_eq!(
2234 KeyCode::LeftArrow
2235 .encode(Modifiers::NONE, mode, true)
2236 .unwrap(),
2237 "\x1b[D".to_string()
2238 );
2239 assert_eq!(
2240 KeyCode::LeftArrow
2241 .encode(Modifiers::ALT, mode, true)
2242 .unwrap(),
2243 "\x1b[1;3D".to_string()
2244 );
2245 assert_eq!(
2246 KeyCode::Home.encode(Modifiers::NONE, mode, true).unwrap(),
2247 "\x1b[H".to_string()
2248 );
2249 assert_eq!(
2250 KeyCode::Home.encode(Modifiers::ALT, mode, true).unwrap(),
2251 "\x1b[1;3H".to_string()
2252 );
2253 assert_eq!(
2254 KeyCode::End.encode(Modifiers::NONE, mode, true).unwrap(),
2255 "\x1b[F".to_string()
2256 );
2257 assert_eq!(
2258 KeyCode::End.encode(Modifiers::ALT, mode, true).unwrap(),
2259 "\x1b[1;3F".to_string()
2260 );
2261 assert_eq!(
2262 KeyCode::Tab.encode(Modifiers::ALT, mode, true).unwrap(),
2263 "\x1b\t".to_string()
2264 );
2265 assert_eq!(
2266 KeyCode::PageUp.encode(Modifiers::ALT, mode, true).unwrap(),
2267 "\x1b[5;3~".to_string()
2268 );
2269 assert_eq!(
2270 KeyCode::Function(1)
2271 .encode(Modifiers::NONE, mode, true)
2272 .unwrap(),
2273 "\x1bOP".to_string()
2274 );
2275 }
2276
2277 #[test]
2278 fn partial_bracketed_paste() {
2279 let mut p = InputParser::new();
2280
2281 let input = b"\x1b[200~1234";
2282 let input2 = b"5678\x1b[201~";
2283
2284 let mut inputs = vec![];
2285
2286 p.parse(input, |e| inputs.push(e), false);
2287 p.parse(input2, |e| inputs.push(e), false);
2288
2289 assert_eq!(vec![InputEvent::Paste("12345678".to_owned())], inputs)
2290 }
2291
2292 #[test]
2293 fn mouse_horizontal_scroll() {
2294 let mut p = InputParser::new();
2295
2296 let input = b"\x1b[<66;42;12M\x1b[<67;42;12M";
2297 let res = p.parse_as_vec(input, MAYBE_MORE);
2298
2299 assert_eq!(
2300 vec![
2301 InputEvent::Mouse(MouseEvent {
2302 x: 42,
2303 y: 12,
2304 mouse_buttons: MouseButtons::HORZ_WHEEL | MouseButtons::WHEEL_POSITIVE,
2305 modifiers: Modifiers::NONE,
2306 }),
2307 InputEvent::Mouse(MouseEvent {
2308 x: 42,
2309 y: 12,
2310 mouse_buttons: MouseButtons::HORZ_WHEEL,
2311 modifiers: Modifiers::NONE,
2312 })
2313 ],
2314 res
2315 );
2316 }
2317
2318 #[test]
2319 fn encode_issue_3478_xterm() {
2320 let mode = KeyCodeEncodeModes {
2321 encoding: KeyboardEncoding::Xterm,
2322 newline_mode: false,
2323 application_cursor_keys: false,
2324 modify_other_keys: None,
2325 };
2326
2327 assert_eq!(
2328 KeyCode::Numpad0
2329 .encode(Modifiers::NONE, mode, true)
2330 .unwrap(),
2331 "\u{1b}[2~".to_string()
2332 );
2333 assert_eq!(
2334 KeyCode::Numpad0
2335 .encode(Modifiers::SHIFT, mode, true)
2336 .unwrap(),
2337 "\u{1b}[2;2~".to_string()
2338 );
2339
2340 assert_eq!(
2341 KeyCode::Numpad1
2342 .encode(Modifiers::NONE, mode, true)
2343 .unwrap(),
2344 "\u{1b}[F".to_string()
2345 );
2346 assert_eq!(
2347 KeyCode::Numpad1
2348 .encode(Modifiers::NONE | Modifiers::SHIFT, mode, true)
2349 .unwrap(),
2350 "\u{1b}[1;2F".to_string()
2351 );
2352 }
2353
2354 #[test]
2355 fn encode_tab_with_modifiers() {
2356 let mode = KeyCodeEncodeModes {
2357 encoding: KeyboardEncoding::Xterm,
2358 newline_mode: false,
2359 application_cursor_keys: false,
2360 modify_other_keys: None,
2361 };
2362
2363 let mods_to_result = [
2364 (Modifiers::SHIFT, "\u{1b}[Z"),
2365 (Modifiers::SHIFT | Modifiers::LEFT_SHIFT, "\u{1b}[Z"),
2366 (Modifiers::SHIFT | Modifiers::RIGHT_SHIFT, "\u{1b}[Z"),
2367 (Modifiers::CTRL, "\u{1b}[9;5u"),
2368 (Modifiers::CTRL | Modifiers::LEFT_CTRL, "\u{1b}[9;5u"),
2369 (Modifiers::CTRL | Modifiers::RIGHT_CTRL, "\u{1b}[9;5u"),
2370 (
2371 Modifiers::SHIFT | Modifiers::CTRL | Modifiers::LEFT_CTRL | Modifiers::LEFT_SHIFT,
2372 "\u{1b}[1;5Z",
2373 ),
2374 ];
2375 for (mods, result) in mods_to_result {
2376 assert_eq!(
2377 KeyCode::Tab.encode(mods, mode, true).unwrap(),
2378 result,
2379 "{:?}",
2380 mods
2381 );
2382 }
2383 }
2384
2385 #[test]
2386 fn mouse_button1_press() {
2387 let mut p = InputParser::new();
2388 let res = p.parse_as_vec(b"\x1b[<0;42;12M", true);
2389 assert_eq!(
2390 res,
2391 vec![InputEvent::Mouse(MouseEvent {
2392 x: 42,
2393 y: 12,
2394 mouse_buttons: MouseButtons::LEFT,
2395 modifiers: Modifiers::NONE,
2396 })]
2397 );
2398 }
2399
2400 #[test]
2401 fn mouse_button1_release() {
2402 let mut p = InputParser::new();
2403 let res = p.parse_as_vec(b"\x1b[<0;42;12m", true);
2404 assert_eq!(
2405 res,
2406 vec![InputEvent::Mouse(MouseEvent {
2407 x: 42,
2408 y: 12,
2409 mouse_buttons: MouseButtons::NONE,
2410 modifiers: Modifiers::NONE,
2411 })]
2412 );
2413 }
2414
2415 #[test]
2416 fn mouse_button3_with_shift() {
2417 let mut p = InputParser::new();
2418 let res = p.parse_as_vec(b"\x1b[<6;10;20M", true);
2420 assert_eq!(
2421 res,
2422 vec![InputEvent::Mouse(MouseEvent {
2423 x: 10,
2424 y: 20,
2425 mouse_buttons: MouseButtons::RIGHT,
2426 modifiers: Modifiers::SHIFT,
2427 })]
2428 );
2429 }
2430
2431 #[test]
2432 fn mouse_drag() {
2433 let mut p = InputParser::new();
2434 let res = p.parse_as_vec(b"\x1b[<32;5;5M", true);
2436 assert_eq!(
2437 res,
2438 vec![InputEvent::Mouse(MouseEvent {
2439 x: 5,
2440 y: 5,
2441 mouse_buttons: MouseButtons::LEFT,
2442 modifiers: Modifiers::NONE,
2443 })]
2444 );
2445 }
2446
2447 #[test]
2448 fn mouse_vertical_scroll_up() {
2449 let mut p = InputParser::new();
2450 let res = p.parse_as_vec(b"\x1b[<64;1;1M", true);
2452 assert_eq!(
2453 res,
2454 vec![InputEvent::Mouse(MouseEvent {
2455 x: 1,
2456 y: 1,
2457 mouse_buttons: MouseButtons::VERT_WHEEL | MouseButtons::WHEEL_POSITIVE,
2458 modifiers: Modifiers::NONE,
2459 })]
2460 );
2461 }
2462
2463 #[test]
2464 fn mouse_vertical_scroll_down() {
2465 let mut p = InputParser::new();
2466 let res = p.parse_as_vec(b"\x1b[<65;1;1M", true);
2468 assert_eq!(
2469 res,
2470 vec![InputEvent::Mouse(MouseEvent {
2471 x: 1,
2472 y: 1,
2473 mouse_buttons: MouseButtons::VERT_WHEEL,
2474 modifiers: Modifiers::NONE,
2475 })]
2476 );
2477 }
2478
2479 #[test]
2480 fn mouse_motion_no_buttons() {
2481 let mut p = InputParser::new();
2482 let res = p.parse_as_vec(b"\x1b[<35;10;10M", true);
2484 assert_eq!(
2485 res,
2486 vec![InputEvent::Mouse(MouseEvent {
2487 x: 10,
2488 y: 10,
2489 mouse_buttons: MouseButtons::NONE,
2490 modifiers: Modifiers::NONE,
2491 })]
2492 );
2493 }
2494
2495 #[test]
2496 fn mouse_with_ctrl_alt() {
2497 let mut p = InputParser::new();
2498 let res = p.parse_as_vec(b"\x1b[<24;1;1M", true);
2500 assert_eq!(
2501 res,
2502 vec![InputEvent::Mouse(MouseEvent {
2503 x: 1,
2504 y: 1,
2505 mouse_buttons: MouseButtons::LEFT,
2506 modifiers: Modifiers::ALT | Modifiers::CTRL,
2507 })]
2508 );
2509 }
2510
2511 #[test]
2512 fn mouse_large_coordinates() {
2513 let mut p = InputParser::new();
2514 let res = p.parse_as_vec(b"\x1b[<0;999;999M", true);
2515 assert_eq!(
2516 res,
2517 vec![InputEvent::Mouse(MouseEvent {
2518 x: 999,
2519 y: 999,
2520 mouse_buttons: MouseButtons::LEFT,
2521 modifiers: Modifiers::NONE,
2522 })]
2523 );
2524 }
2525
2526 #[test]
2527 fn mouse_followed_by_key() {
2528 let mut p = InputParser::new();
2529 let res = p.parse_as_vec(b"\x1b[<0;1;1Mhello", false);
2530 assert_eq!(res.len(), 6); assert!(matches!(res[0], InputEvent::Mouse(_)));
2532 assert!(matches!(res[1], InputEvent::Key(_)));
2533 }
2534
2535 #[test]
2536 fn two_mouse_events_back_to_back() {
2537 let mut p = InputParser::new();
2538 let res = p.parse_as_vec(b"\x1b[<0;1;1M\x1b[<0;2;2M", true);
2539 assert_eq!(res.len(), 2);
2540 }
2541
2542 #[test]
2550 fn esc_then_sgr_mouse_emits_esc_and_mouse() {
2551 let mut p = InputParser::new();
2552 let res = p.parse_as_vec(b"\x1b\x1b[<35;42;12M", MAYBE_MORE);
2553 assert_eq!(
2554 res,
2555 vec![
2556 InputEvent::Key(KeyEvent {
2557 key: KeyCode::Escape,
2558 modifiers: Modifiers::NONE,
2559 }),
2560 InputEvent::Mouse(MouseEvent {
2561 x: 42,
2562 y: 12,
2563 mouse_buttons: MouseButtons::NONE,
2564 modifiers: Modifiers::NONE,
2565 }),
2566 ]
2567 );
2568 }
2569
2570 #[test]
2574 fn esc_then_sgr_mouse_across_parse_calls() {
2575 let mut p = InputParser::new();
2576
2577 let mut res = p.parse_as_vec(b"\x1b", MAYBE_MORE);
2582 assert!(
2583 res.is_empty(),
2584 "lone ESC should not emit yet under MAYBE_MORE"
2585 );
2586
2587 res = p.parse_as_vec(b"\x1b[<35;42;12M", MAYBE_MORE);
2593 assert_eq!(
2594 res,
2595 vec![
2596 InputEvent::Key(KeyEvent {
2597 key: KeyCode::Escape,
2598 modifiers: Modifiers::NONE,
2599 }),
2600 InputEvent::Mouse(MouseEvent {
2601 x: 42,
2602 y: 12,
2603 mouse_buttons: MouseButtons::NONE,
2604 modifiers: Modifiers::NONE,
2605 }),
2606 ]
2607 );
2608 }
2609
2610 #[test]
2614 fn alt_esc_still_recognized() {
2615 let mut p = InputParser::new();
2616 let res = p.parse_as_vec(b"\x1b\x1b", NO_MORE);
2617 assert_eq!(
2618 res,
2619 vec![InputEvent::Key(KeyEvent {
2620 key: KeyCode::Escape,
2621 modifiers: Modifiers::ALT,
2622 })]
2623 );
2624 }
2625
2626 #[test]
2631 fn esc_then_osc_emits_esc_and_osc() {
2632 let mut p = InputParser::new();
2633 let res = p.parse_as_vec(b"\x1b\x1b]11;rgb:ffff/ffff/ffff\x1b\\", MAYBE_MORE);
2634 assert_eq!(
2635 res,
2636 vec![
2637 InputEvent::Key(KeyEvent {
2638 key: KeyCode::Escape,
2639 modifiers: Modifiers::NONE,
2640 }),
2641 InputEvent::OperatingSystemCommand(b"11;rgb:ffff/ffff/ffff".to_vec()),
2642 ]
2643 );
2644 }
2645
2646 #[test]
2649 fn esc_then_csi_report_emits_esc_and_report() {
2650 let mut p = InputParser::new();
2651 let res = p.parse_as_vec(b"\x1b\x1b[?2026;0$y", MAYBE_MORE);
2654 assert!(
2655 !res.is_empty(),
2656 "expected at least one event from Esc + CSI report"
2657 );
2658 assert!(
2659 matches!(
2660 res[0],
2661 InputEvent::Key(KeyEvent {
2662 key: KeyCode::Escape,
2663 modifiers: Modifiers::NONE,
2664 })
2665 ),
2666 "first event must be a bare Esc keystroke, got {:?}",
2667 res[0]
2668 );
2669 for ev in &res {
2674 if let InputEvent::Key(KeyEvent { key, modifiers }) = ev {
2675 assert!(
2676 !(matches!(key, KeyCode::Char('[')) && modifiers.contains(Modifiers::ALT)),
2677 "must not emit Alt+`[`; got {:?}",
2678 ev
2679 );
2680 }
2681 }
2682 }
2683
2684 #[test]
2685 fn invalid_sgr_mouse_falls_through() {
2686 let mut p = InputParser::new();
2687 let res = p.parse_as_vec(b"\x1b[<0;1M", false);
2689 assert!(res.iter().all(|e| matches!(e, InputEvent::Key(_))));
2691 }
2692
2693 #[test]
2694 fn osc_bel_terminated() {
2695 let mut p = InputParser::new();
2697 let inputs = p.parse_as_vec(b"\x1b]99;i=test:p=title;Hello\x07", NO_MORE);
2698 assert_eq!(
2699 vec![InputEvent::OperatingSystemCommand(
2700 b"99;i=test:p=title;Hello".to_vec()
2701 )],
2702 inputs
2703 );
2704 }
2705
2706 #[test]
2707 fn osc_st_terminated() {
2708 let mut p = InputParser::new();
2710 let inputs = p.parse_as_vec(b"\x1b]99;i=test:p=title;Hello\x1b\\", NO_MORE);
2711 assert_eq!(
2712 vec![InputEvent::OperatingSystemCommand(
2713 b"99;i=test:p=title;Hello".to_vec()
2714 )],
2715 inputs
2716 );
2717 }
2718
2719 #[test]
2720 fn osc_partial_across_reads() {
2721 let mut p = InputParser::new();
2723 let mut inputs = Vec::new();
2724 p.parse(
2725 b"\x1b]99;i=test:p=title;Hel",
2726 |evt| inputs.push(evt),
2727 MAYBE_MORE,
2728 );
2729 assert!(inputs.is_empty(), "no events yet - sequence incomplete");
2730 p.parse(b"lo\x1b\\", |evt| inputs.push(evt), MAYBE_MORE);
2731 assert_eq!(
2732 vec![InputEvent::OperatingSystemCommand(
2733 b"99;i=test:p=title;Hello".to_vec()
2734 )],
2735 inputs
2736 );
2737 }
2738
2739 #[test]
2740 fn osc_followed_by_keypress() {
2741 let mut p = InputParser::new();
2743 let inputs = p.parse_as_vec(b"\x1b]99;i=test;clicked\x07x", NO_MORE);
2744 assert_eq!(
2745 vec![
2746 InputEvent::OperatingSystemCommand(b"99;i=test;clicked".to_vec()),
2747 InputEvent::Key(KeyEvent {
2748 modifiers: Modifiers::NONE,
2749 key: KeyCode::Char('x'),
2750 }),
2751 ],
2752 inputs
2753 );
2754 }
2755
2756 #[test]
2757 fn keypress_followed_by_osc() {
2758 let mut p = InputParser::new();
2760 let inputs = p.parse_as_vec(b"x\x1b]99;i=test;clicked\x07", NO_MORE);
2761 assert_eq!(
2762 vec![
2763 InputEvent::Key(KeyEvent {
2764 modifiers: Modifiers::NONE,
2765 key: KeyCode::Char('x'),
2766 }),
2767 InputEvent::OperatingSystemCommand(b"99;i=test;clicked".to_vec()),
2768 ],
2769 inputs
2770 );
2771 }
2772
2773 #[test]
2774 fn osc_incomplete_degrades_to_keys() {
2775 let mut p = InputParser::new();
2778 let mut inputs = Vec::new();
2779 p.parse(b"\x1b]99;no-terminator", |evt| inputs.push(evt), MAYBE_MORE);
2780 assert!(inputs.is_empty(), "buffered while maybe_more=true");
2781 p.parse(b"", |evt| inputs.push(evt), NO_MORE);
2782 assert!(!inputs.is_empty(), "must emit something on finalization");
2783 }
2784
2785 #[test]
2786 fn osc_non_99_code() {
2787 let mut p = InputParser::new();
2789 let inputs = p.parse_as_vec(b"\x1b]11;rgb:0000/0000/0000\x1b\\", NO_MORE);
2790 assert_eq!(
2791 vec![InputEvent::OperatingSystemCommand(
2792 b"11;rgb:0000/0000/0000".to_vec()
2793 )],
2794 inputs
2795 );
2796 }
2797
2798 #[test]
2799 fn osc_empty_payload() {
2800 let mut p = InputParser::new();
2802 let inputs = p.parse_as_vec(b"\x1b]\x07", NO_MORE);
2803 assert_eq!(
2804 vec![InputEvent::OperatingSystemCommand(b"".to_vec())],
2805 inputs
2806 );
2807 }
2808
2809 #[test]
2810 fn csi_not_captured_as_osc() {
2811 let mut p = InputParser::new();
2814 let inputs = p.parse_as_vec(b"\x1b[A", NO_MORE);
2815 assert_eq!(
2816 vec![InputEvent::Key(KeyEvent {
2817 modifiers: Modifiers::NONE,
2818 key: KeyCode::UpArrow,
2819 })],
2820 inputs
2821 );
2822 }
2823
2824 fn csi_reply(intermediates: &[u8], params: &[u8], final_byte: u8, raw: &[u8]) -> InputEvent {
2829 InputEvent::DeviceControlReply {
2830 intermediates: intermediates.to_vec(),
2831 params: params.to_vec(),
2832 final_byte,
2833 raw: raw.to_vec(),
2834 }
2835 }
2836
2837 #[test]
2838 fn csi_report_recognises_each_whitelisted_final_byte() {
2839 let bytes = b"\x1b[4;600;800t";
2841 let (evt, consumed) = parse_csi_report(bytes).expect("t accepted");
2842 assert_eq!(consumed, bytes.len());
2843 assert_eq!(evt, csi_reply(b"", b"4;600;800", b't', bytes));
2844
2845 let bytes = b"\x1b[?2026;1$y";
2847 let (evt, consumed) = parse_csi_report(bytes).expect("y accepted");
2848 assert_eq!(consumed, bytes.len());
2849 assert_eq!(evt, csi_reply(b"$", b"?2026;1", b'y', bytes));
2850
2851 let bytes = b"\x1b[?62;1;6c";
2853 let (evt, consumed) = parse_csi_report(bytes).expect("c accepted");
2854 assert_eq!(consumed, bytes.len());
2855 assert_eq!(evt, csi_reply(b"", b"?62;1;6", b'c', bytes));
2856
2857 let bytes = b"\x1b[?997;1n";
2859 let (evt, consumed) = parse_csi_report(bytes).expect("n accepted");
2860 assert_eq!(consumed, bytes.len());
2861 assert_eq!(evt, csi_reply(b"", b"?997;1", b'n', bytes));
2862 }
2863
2864 #[test]
2865 fn csi_report_preserves_intermediates() {
2866 let bytes = b"\x1b[?2026;2$y";
2869 let (evt, _len) = parse_csi_report(bytes).expect("DECRPM accepted");
2870 let InputEvent::DeviceControlReply {
2871 intermediates,
2872 params,
2873 final_byte,
2874 raw,
2875 } = evt
2876 else {
2877 panic!("expected DeviceControlReply, got {:?}", evt);
2878 };
2879 assert_eq!(intermediates, b"$");
2880 assert_eq!(params, b"?2026;2");
2881 assert_eq!(final_byte, b'y');
2882 assert_eq!(raw, bytes);
2883 }
2884
2885 #[test]
2886 fn csi_report_rejects_non_whitelisted_final_bytes() {
2887 assert!(parse_csi_report(b"\x1b[A").is_none());
2889 assert!(parse_csi_report(b"\x1b[24;80R").is_none());
2892 assert!(parse_csi_report(b"\x1b[0m").is_none());
2895 }
2896
2897 #[test]
2898 fn csi_report_returns_none_on_truncated_input() {
2899 assert!(parse_csi_report(b"\x1b[4;600;800").is_none());
2903 assert!(parse_csi_report(b"\x1b[").is_none());
2905 assert!(parse_csi_report(b"").is_none());
2907 }
2908
2909 #[test]
2910 fn csi_report_raw_preserves_input_byte_for_byte() {
2911 let bytes = b"\x1b[4;16;8t";
2915 let (evt, consumed) = parse_csi_report(bytes).expect("accepted");
2916 assert_eq!(consumed, bytes.len());
2917 let InputEvent::DeviceControlReply { raw, .. } = evt else {
2918 panic!("wrong variant");
2919 };
2920 assert_eq!(&raw[..], bytes, "raw must be byte-identical to input");
2921 }
2922}