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 parse_csi_report(buf: &[u8]) -> Option<(InputEvent, usize)> {
842 if buf.get(0) != Some(&0x1b) || buf.get(1) != Some(&b'[') {
843 return None;
844 }
845 let mut i = 2;
849 let mut intermediates: Vec<u8> = Vec::new();
850 let mut params: Vec<u8> = Vec::new();
851 let max_scan = buf.len().min(256);
855 while i < max_scan {
856 let b = buf[i];
857 match b {
858 0x30..=0x3F => {
860 params.push(b);
861 i += 1;
862 },
863 0x20..=0x2F => {
865 intermediates.push(b);
866 i += 1;
867 },
868 b't' | b'y' | b'c' | b'n' => {
870 let raw = buf[0..=i].to_vec();
871 return Some((
872 InputEvent::DeviceControlReply {
873 intermediates,
874 params,
875 final_byte: b,
876 raw,
877 },
878 i + 1,
879 ));
880 },
881 0x40..=0x7E => {
882 return None;
884 },
885 _ => {
886 return None;
888 },
889 }
890 }
891 None
892}
893
894fn parse_osc(buf: &[u8]) -> Option<(InputEvent, usize)> {
895 if buf.get(0) != Some(&0x1b) || buf.get(1) != Some(&b']') {
897 return None;
898 }
899 let mut i = 2;
900 while i < buf.len() {
901 match buf.get(i) {
902 Some(&0x07) => {
903 let payload = buf.get(2..i).unwrap_or_default().to_vec();
905 return Some((InputEvent::OperatingSystemCommand(payload), i + 1));
906 },
907 Some(&0x1b) => {
908 if buf.get(i + 1) == Some(&b'\\') {
910 let payload = buf.get(2..i).unwrap_or_default().to_vec();
911 return Some((InputEvent::OperatingSystemCommand(payload), i + 2));
912 }
913 return None;
915 },
916 Some(_) => {
917 i += 1;
918 },
919 None => {
920 return None;
922 },
923 }
924 }
925 None }
927
928#[derive(Debug, Clone, Copy, PartialEq, Eq)]
929enum InputState {
930 Normal,
931 EscapeMaybeAlt,
932 Pasting(usize),
933}
934
935#[derive(Debug)]
936pub struct InputParser {
937 key_map: KeyMap<InputEvent>,
938 buf: ReadBuffer,
939 state: InputState,
940}
941
942#[cfg(windows)]
943mod windows {
944 use super::*;
945 use std;
946 use winapi::um::wincon::{
947 INPUT_RECORD, KEY_EVENT, KEY_EVENT_RECORD, MOUSE_EVENT, MOUSE_EVENT_RECORD,
948 WINDOW_BUFFER_SIZE_EVENT, WINDOW_BUFFER_SIZE_RECORD,
949 };
950 use winapi::um::winuser;
951
952 fn modifiers_from_ctrl_key_state(state: u32) -> Modifiers {
953 use winapi::um::wincon::*;
954
955 let mut mods = Modifiers::NONE;
956
957 if (state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0 {
958 mods |= Modifiers::ALT;
959 }
960
961 if (state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0 {
962 mods |= Modifiers::CTRL;
963 }
964
965 if (state & SHIFT_PRESSED) != 0 {
966 mods |= Modifiers::SHIFT;
967 }
968
969 mods
970 }
971
972 impl InputParser {
973 fn decode_key_record<F: FnMut(InputEvent)>(
974 &mut self,
975 event: &KEY_EVENT_RECORD,
976 callback: &mut F,
977 ) {
978 if event.bKeyDown == 0 {
979 return;
980 }
981
982 let key_code = match std::char::from_u32(*unsafe { event.uChar.UnicodeChar() } as u32) {
983 Some(unicode) if unicode > '\x00' => {
984 let mut buf = [0u8; 4];
985 self.buf
986 .extend_with(unicode.encode_utf8(&mut buf).as_bytes());
987 self.process_bytes(callback, true);
988 return;
989 },
990 _ => match event.wVirtualKeyCode as i32 {
991 winuser::VK_CANCEL => KeyCode::Cancel,
992 winuser::VK_BACK => KeyCode::Backspace,
993 winuser::VK_TAB => KeyCode::Tab,
994 winuser::VK_CLEAR => KeyCode::Clear,
995 winuser::VK_RETURN => KeyCode::Enter,
996 winuser::VK_SHIFT => KeyCode::Shift,
997 winuser::VK_CONTROL => KeyCode::Control,
998 winuser::VK_MENU => KeyCode::Menu,
999 winuser::VK_PAUSE => KeyCode::Pause,
1000 winuser::VK_CAPITAL => KeyCode::CapsLock,
1001 winuser::VK_ESCAPE => KeyCode::Escape,
1002 winuser::VK_PRIOR => KeyCode::PageUp,
1003 winuser::VK_NEXT => KeyCode::PageDown,
1004 winuser::VK_END => KeyCode::End,
1005 winuser::VK_HOME => KeyCode::Home,
1006 winuser::VK_LEFT => KeyCode::LeftArrow,
1007 winuser::VK_RIGHT => KeyCode::RightArrow,
1008 winuser::VK_UP => KeyCode::UpArrow,
1009 winuser::VK_DOWN => KeyCode::DownArrow,
1010 winuser::VK_SELECT => KeyCode::Select,
1011 winuser::VK_PRINT => KeyCode::Print,
1012 winuser::VK_EXECUTE => KeyCode::Execute,
1013 winuser::VK_SNAPSHOT => KeyCode::PrintScreen,
1014 winuser::VK_INSERT => KeyCode::Insert,
1015 winuser::VK_DELETE => KeyCode::Delete,
1016 winuser::VK_HELP => KeyCode::Help,
1017 winuser::VK_LWIN => KeyCode::LeftWindows,
1018 winuser::VK_RWIN => KeyCode::RightWindows,
1019 winuser::VK_APPS => KeyCode::Applications,
1020 winuser::VK_SLEEP => KeyCode::Sleep,
1021 winuser::VK_NUMPAD0 => KeyCode::Numpad0,
1022 winuser::VK_NUMPAD1 => KeyCode::Numpad1,
1023 winuser::VK_NUMPAD2 => KeyCode::Numpad2,
1024 winuser::VK_NUMPAD3 => KeyCode::Numpad3,
1025 winuser::VK_NUMPAD4 => KeyCode::Numpad4,
1026 winuser::VK_NUMPAD5 => KeyCode::Numpad5,
1027 winuser::VK_NUMPAD6 => KeyCode::Numpad6,
1028 winuser::VK_NUMPAD7 => KeyCode::Numpad7,
1029 winuser::VK_NUMPAD8 => KeyCode::Numpad8,
1030 winuser::VK_NUMPAD9 => KeyCode::Numpad9,
1031 winuser::VK_MULTIPLY => KeyCode::Multiply,
1032 winuser::VK_ADD => KeyCode::Add,
1033 winuser::VK_SEPARATOR => KeyCode::Separator,
1034 winuser::VK_SUBTRACT => KeyCode::Subtract,
1035 winuser::VK_DECIMAL => KeyCode::Decimal,
1036 winuser::VK_DIVIDE => KeyCode::Divide,
1037 winuser::VK_F1 => KeyCode::Function(1),
1038 winuser::VK_F2 => KeyCode::Function(2),
1039 winuser::VK_F3 => KeyCode::Function(3),
1040 winuser::VK_F4 => KeyCode::Function(4),
1041 winuser::VK_F5 => KeyCode::Function(5),
1042 winuser::VK_F6 => KeyCode::Function(6),
1043 winuser::VK_F7 => KeyCode::Function(7),
1044 winuser::VK_F8 => KeyCode::Function(8),
1045 winuser::VK_F9 => KeyCode::Function(9),
1046 winuser::VK_F10 => KeyCode::Function(10),
1047 winuser::VK_F11 => KeyCode::Function(11),
1048 winuser::VK_F12 => KeyCode::Function(12),
1049 winuser::VK_F13 => KeyCode::Function(13),
1050 winuser::VK_F14 => KeyCode::Function(14),
1051 winuser::VK_F15 => KeyCode::Function(15),
1052 winuser::VK_F16 => KeyCode::Function(16),
1053 winuser::VK_F17 => KeyCode::Function(17),
1054 winuser::VK_F18 => KeyCode::Function(18),
1055 winuser::VK_F19 => KeyCode::Function(19),
1056 winuser::VK_F20 => KeyCode::Function(20),
1057 winuser::VK_F21 => KeyCode::Function(21),
1058 winuser::VK_F22 => KeyCode::Function(22),
1059 winuser::VK_F23 => KeyCode::Function(23),
1060 winuser::VK_F24 => KeyCode::Function(24),
1061 winuser::VK_NUMLOCK => KeyCode::NumLock,
1062 winuser::VK_SCROLL => KeyCode::ScrollLock,
1063 winuser::VK_LSHIFT => KeyCode::LeftShift,
1064 winuser::VK_RSHIFT => KeyCode::RightShift,
1065 winuser::VK_LCONTROL => KeyCode::LeftControl,
1066 winuser::VK_RCONTROL => KeyCode::RightControl,
1067 winuser::VK_LMENU => KeyCode::LeftMenu,
1068 winuser::VK_RMENU => KeyCode::RightMenu,
1069 winuser::VK_BROWSER_BACK => KeyCode::BrowserBack,
1070 winuser::VK_BROWSER_FORWARD => KeyCode::BrowserForward,
1071 winuser::VK_BROWSER_REFRESH => KeyCode::BrowserRefresh,
1072 winuser::VK_BROWSER_STOP => KeyCode::BrowserStop,
1073 winuser::VK_BROWSER_SEARCH => KeyCode::BrowserSearch,
1074 winuser::VK_BROWSER_FAVORITES => KeyCode::BrowserFavorites,
1075 winuser::VK_BROWSER_HOME => KeyCode::BrowserHome,
1076 winuser::VK_VOLUME_MUTE => KeyCode::VolumeMute,
1077 winuser::VK_VOLUME_DOWN => KeyCode::VolumeDown,
1078 winuser::VK_VOLUME_UP => KeyCode::VolumeUp,
1079 winuser::VK_MEDIA_NEXT_TRACK => KeyCode::MediaNextTrack,
1080 winuser::VK_MEDIA_PREV_TRACK => KeyCode::MediaPrevTrack,
1081 winuser::VK_MEDIA_STOP => KeyCode::MediaStop,
1082 winuser::VK_MEDIA_PLAY_PAUSE => KeyCode::MediaPlayPause,
1083 _ => return,
1084 },
1085 };
1086 let mut modifiers = modifiers_from_ctrl_key_state(event.dwControlKeyState);
1087
1088 let key_code = key_code.normalize_shift_to_upper_case(modifiers);
1089 if let KeyCode::Char(c) = key_code {
1090 if c.is_ascii_uppercase() {
1091 modifiers.remove(Modifiers::SHIFT);
1092 }
1093 }
1094
1095 let input_event = InputEvent::Key(KeyEvent {
1096 key: key_code,
1097 modifiers,
1098 });
1099 for _ in 0..event.wRepeatCount {
1100 callback(input_event.clone());
1101 }
1102 }
1103
1104 fn decode_mouse_record<F: FnMut(InputEvent)>(
1105 &self,
1106 event: &MOUSE_EVENT_RECORD,
1107 callback: &mut F,
1108 ) {
1109 use winapi::um::wincon::*;
1110 let mut buttons = MouseButtons::NONE;
1111
1112 if (event.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) != 0 {
1113 buttons |= MouseButtons::LEFT;
1114 }
1115 if (event.dwButtonState & RIGHTMOST_BUTTON_PRESSED) != 0 {
1116 buttons |= MouseButtons::RIGHT;
1117 }
1118 if (event.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) != 0 {
1119 buttons |= MouseButtons::MIDDLE;
1120 }
1121
1122 let modifiers = modifiers_from_ctrl_key_state(event.dwControlKeyState);
1123
1124 if (event.dwEventFlags & MOUSE_WHEELED) != 0 {
1125 buttons |= MouseButtons::VERT_WHEEL;
1126 if (event.dwButtonState >> 8) != 0 {
1127 buttons |= MouseButtons::WHEEL_POSITIVE;
1128 }
1129 } else if (event.dwEventFlags & MOUSE_HWHEELED) != 0 {
1130 buttons |= MouseButtons::HORZ_WHEEL;
1131 if (event.dwButtonState >> 8) != 0 {
1132 buttons |= MouseButtons::WHEEL_POSITIVE;
1133 }
1134 }
1135
1136 let mouse = InputEvent::Mouse(MouseEvent {
1137 x: event.dwMousePosition.X as u16,
1138 y: event.dwMousePosition.Y as u16,
1139 mouse_buttons: buttons,
1140 modifiers,
1141 });
1142
1143 if (event.dwEventFlags & DOUBLE_CLICK) != 0 {
1144 callback(mouse.clone());
1145 }
1146 callback(mouse);
1147 }
1148
1149 fn decode_resize_record<F: FnMut(InputEvent)>(
1150 &self,
1151 event: &WINDOW_BUFFER_SIZE_RECORD,
1152 callback: &mut F,
1153 ) {
1154 callback(InputEvent::Resized {
1155 rows: event.dwSize.Y as usize,
1156 cols: event.dwSize.X as usize,
1157 });
1158 }
1159
1160 pub fn decode_input_records<F: FnMut(InputEvent)>(
1161 &mut self,
1162 records: &[INPUT_RECORD],
1163 callback: &mut F,
1164 ) {
1165 for record in records {
1166 match record.EventType {
1167 KEY_EVENT => {
1168 self.decode_key_record(unsafe { record.Event.KeyEvent() }, callback)
1169 },
1170 MOUSE_EVENT => {
1171 self.decode_mouse_record(unsafe { record.Event.MouseEvent() }, callback)
1172 },
1173 WINDOW_BUFFER_SIZE_EVENT => self.decode_resize_record(
1174 unsafe { record.Event.WindowBufferSizeEvent() },
1175 callback,
1176 ),
1177 _ => {},
1178 }
1179 }
1180 self.process_bytes(callback, false);
1181 }
1182 }
1183}
1184
1185impl Default for InputParser {
1186 fn default() -> Self {
1187 Self::new()
1188 }
1189}
1190
1191impl InputParser {
1192 pub fn new() -> Self {
1193 Self {
1194 key_map: Self::build_basic_key_map(),
1195 buf: ReadBuffer::new(),
1196 state: InputState::Normal,
1197 }
1198 }
1199
1200 fn build_basic_key_map() -> KeyMap<InputEvent> {
1201 let mut map = KeyMap::new();
1202
1203 let modifier_combos = &[
1204 ("", Modifiers::NONE),
1205 (";1", Modifiers::NONE),
1206 (";2", Modifiers::SHIFT),
1207 (";3", Modifiers::ALT),
1208 (";4", Modifiers::ALT | Modifiers::SHIFT),
1209 (";5", Modifiers::CTRL),
1210 (";6", Modifiers::CTRL | Modifiers::SHIFT),
1211 (";7", Modifiers::CTRL | Modifiers::ALT),
1212 (";8", Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT),
1213 ];
1214 let meta = Modifiers::ALT;
1215 let meta_modifier_combos = &[
1216 (";9", meta),
1217 (";10", meta | Modifiers::SHIFT),
1218 (";11", meta | Modifiers::ALT),
1219 (";12", meta | Modifiers::ALT | Modifiers::SHIFT),
1220 (";13", meta | Modifiers::CTRL),
1221 (";14", meta | Modifiers::CTRL | Modifiers::SHIFT),
1222 (";15", meta | Modifiers::CTRL | Modifiers::ALT),
1223 (
1224 ";16",
1225 meta | Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
1226 ),
1227 ];
1228
1229 let modifier_combos_including_meta =
1230 || modifier_combos.iter().chain(meta_modifier_combos.iter());
1231
1232 for alpha in b'A'..=b'Z' {
1233 let ctrl = [alpha & 0x1f];
1235 map.insert(
1236 &ctrl,
1237 InputEvent::Key(KeyEvent {
1238 key: KeyCode::Char((alpha as char).to_ascii_lowercase()),
1239 modifiers: Modifiers::CTRL,
1240 }),
1241 );
1242
1243 let alt = [0x1b, alpha];
1245 map.insert(
1246 &alt,
1247 InputEvent::Key(KeyEvent {
1248 key: KeyCode::Char(alpha as char),
1249 modifiers: Modifiers::ALT,
1250 }),
1251 );
1252 }
1253
1254 for c in 0..=0x7fu8 {
1255 for (suffix, modifiers) in modifier_combos {
1256 let key = format!("\x1b[{}{}u", c, suffix);
1259 map.insert(
1260 key,
1261 InputEvent::Key(KeyEvent {
1262 key: KeyCode::Char(c as char),
1263 modifiers: *modifiers,
1264 }),
1265 );
1266
1267 if !suffix.is_empty() {
1268 let key = format!("\x1b[27{};{}~", suffix, c);
1270 map.insert(
1271 key,
1272 InputEvent::Key(KeyEvent {
1273 key: match c {
1274 8 | 0x7f => KeyCode::Backspace,
1275 0x1b => KeyCode::Escape,
1276 9 => KeyCode::Tab,
1277 10 | 13 => KeyCode::Enter,
1278 _ => KeyCode::Char(c as char),
1279 },
1280 modifiers: *modifiers,
1281 }),
1282 );
1283 }
1284 }
1285 }
1286
1287 for (keycode, dir) in &[
1289 (KeyCode::UpArrow, b'A'),
1290 (KeyCode::DownArrow, b'B'),
1291 (KeyCode::RightArrow, b'C'),
1292 (KeyCode::LeftArrow, b'D'),
1293 (KeyCode::Home, b'H'),
1294 (KeyCode::End, b'F'),
1295 ] {
1296 let arrow = [0x1b, b'[', *dir];
1298 map.insert(
1299 &arrow,
1300 InputEvent::Key(KeyEvent {
1301 key: *keycode,
1302 modifiers: Modifiers::NONE,
1303 }),
1304 );
1305 for (suffix, modifiers) in modifier_combos_including_meta() {
1306 let key = format!("\x1b[1{}{}", suffix, *dir as char);
1307 map.insert(
1308 key,
1309 InputEvent::Key(KeyEvent {
1310 key: *keycode,
1311 modifiers: *modifiers,
1312 }),
1313 );
1314 }
1315 }
1316 for &(keycode, dir) in &[
1317 (KeyCode::UpArrow, b'a'),
1318 (KeyCode::DownArrow, b'b'),
1319 (KeyCode::RightArrow, b'c'),
1320 (KeyCode::LeftArrow, b'd'),
1321 ] {
1322 for &(seq, mods) in &[
1324 ([0x1b, b'[', dir], Modifiers::SHIFT),
1325 ([0x1b, b'O', dir], Modifiers::CTRL),
1326 ] {
1327 map.insert(
1328 &seq,
1329 InputEvent::Key(KeyEvent {
1330 key: keycode,
1331 modifiers: mods,
1332 }),
1333 );
1334 }
1335 }
1336
1337 for (keycode, dir) in &[
1338 (KeyCode::ApplicationUpArrow, b'A'),
1339 (KeyCode::ApplicationDownArrow, b'B'),
1340 (KeyCode::ApplicationRightArrow, b'C'),
1341 (KeyCode::ApplicationLeftArrow, b'D'),
1342 ] {
1343 let app = [0x1b, b'O', *dir];
1345 map.insert(
1346 &app,
1347 InputEvent::Key(KeyEvent {
1348 key: *keycode,
1349 modifiers: Modifiers::NONE,
1350 }),
1351 );
1352 for (suffix, modifiers) in modifier_combos {
1353 let key = format!("\x1bO1{}{}", suffix, *dir as char);
1354 map.insert(
1355 key,
1356 InputEvent::Key(KeyEvent {
1357 key: *keycode,
1358 modifiers: *modifiers,
1359 }),
1360 );
1361 }
1362 }
1363
1364 for (keycode, c) in &[
1366 (KeyCode::Function(1), b'P'),
1367 (KeyCode::Function(2), b'Q'),
1368 (KeyCode::Function(3), b'R'),
1369 (KeyCode::Function(4), b'S'),
1370 ] {
1371 let key = [0x1b, b'O', *c];
1372 map.insert(
1373 &key,
1374 InputEvent::Key(KeyEvent {
1375 key: *keycode,
1376 modifiers: Modifiers::NONE,
1377 }),
1378 );
1379 }
1380
1381 for (keycode, c) in &[
1383 (KeyCode::Function(1), b'P'),
1384 (KeyCode::Function(2), b'Q'),
1385 (KeyCode::Function(3), b'R'),
1386 (KeyCode::Function(4), b'S'),
1387 ] {
1388 for (suffix, modifiers) in modifier_combos_including_meta() {
1389 let key = format!("\x1b[1{suffix}{code}", code = *c as char, suffix = suffix);
1390 map.insert(
1391 key,
1392 InputEvent::Key(KeyEvent {
1393 key: *keycode,
1394 modifiers: *modifiers,
1395 }),
1396 );
1397 }
1398 }
1399
1400 for (range, offset) in &[
1403 (1..=5, 10),
1405 (6..=10, 11),
1407 (11..=14, 12),
1409 (15..=16, 13),
1411 (17..=20, 14),
1413 ] {
1414 for n in range.clone() {
1415 for (suffix, modifiers) in modifier_combos_including_meta() {
1416 let key = format!("\x1b[{code}{suffix}~", code = n + offset, suffix = suffix);
1417 map.insert(
1418 key,
1419 InputEvent::Key(KeyEvent {
1420 key: KeyCode::Function(n),
1421 modifiers: *modifiers,
1422 }),
1423 );
1424 }
1425 }
1426 }
1427
1428 for (keycode, c) in &[
1429 (KeyCode::Insert, b'2'),
1430 (KeyCode::Delete, b'3'),
1431 (KeyCode::Home, b'1'),
1432 (KeyCode::End, b'4'),
1433 (KeyCode::PageUp, b'5'),
1434 (KeyCode::PageDown, b'6'),
1435 (KeyCode::Home, b'7'),
1437 (KeyCode::End, b'8'),
1438 ] {
1439 for (suffix, modifiers) in &[
1440 (b'~', Modifiers::NONE),
1441 (b'$', Modifiers::SHIFT),
1442 (b'^', Modifiers::CTRL),
1443 (b'@', Modifiers::SHIFT | Modifiers::CTRL),
1444 ] {
1445 let key = [0x1b, b'[', *c, *suffix];
1446 map.insert(
1447 key,
1448 InputEvent::Key(KeyEvent {
1449 key: *keycode,
1450 modifiers: *modifiers,
1451 }),
1452 );
1453 }
1454 }
1455
1456 map.insert(
1457 &[0x7f],
1458 InputEvent::Key(KeyEvent {
1459 key: KeyCode::Backspace,
1460 modifiers: Modifiers::NONE,
1461 }),
1462 );
1463
1464 map.insert(
1465 &[0x8],
1466 InputEvent::Key(KeyEvent {
1467 key: KeyCode::Backspace,
1468 modifiers: Modifiers::NONE,
1469 }),
1470 );
1471
1472 map.insert(
1473 &[0x1b],
1474 InputEvent::Key(KeyEvent {
1475 key: KeyCode::Escape,
1476 modifiers: Modifiers::NONE,
1477 }),
1478 );
1479
1480 map.insert(
1481 &[b'\t'],
1482 InputEvent::Key(KeyEvent {
1483 key: KeyCode::Tab,
1484 modifiers: Modifiers::NONE,
1485 }),
1486 );
1487 map.insert(
1488 b"\x1b[Z",
1489 InputEvent::Key(KeyEvent {
1490 key: KeyCode::Tab,
1491 modifiers: Modifiers::SHIFT,
1492 }),
1493 );
1494
1495 map.insert(
1496 &[b'\r'],
1497 InputEvent::Key(KeyEvent {
1498 key: KeyCode::Enter,
1499 modifiers: Modifiers::NONE,
1500 }),
1501 );
1502 map.insert(
1503 &[b'\n'],
1504 InputEvent::Key(KeyEvent {
1505 key: KeyCode::Enter,
1506 modifiers: Modifiers::NONE,
1507 }),
1508 );
1509
1510 map.insert(
1511 b"\x1b[200~",
1512 InputEvent::Key(KeyEvent {
1513 key: KeyCode::InternalPasteStart,
1514 modifiers: Modifiers::NONE,
1515 }),
1516 );
1517 map.insert(
1518 b"\x1b[201~",
1519 InputEvent::Key(KeyEvent {
1520 key: KeyCode::InternalPasteEnd,
1521 modifiers: Modifiers::NONE,
1522 }),
1523 );
1524 map.insert(
1525 b"\x1b[",
1526 InputEvent::Key(KeyEvent {
1527 key: KeyCode::Char('['),
1528 modifiers: Modifiers::ALT,
1529 }),
1530 );
1531
1532 map
1533 }
1534
1535 fn first_char_and_len(s: &str) -> (char, usize) {
1538 let mut iter = s.chars();
1539 let c = iter.next().unwrap();
1540 (c, c.len_utf8())
1541 }
1542
1543 fn decode_one_char(bytes: &[u8]) -> Option<(char, usize)> {
1546 let bytes = &bytes[..bytes.len().min(4)];
1547 match std::str::from_utf8(bytes) {
1548 Ok(s) => {
1549 let (c, len) = Self::first_char_and_len(s);
1550 Some((c, len))
1551 },
1552 Err(err) => {
1553 let (valid, _after_valid) = bytes.split_at(err.valid_up_to());
1554 if !valid.is_empty() {
1555 let s = unsafe { std::str::from_utf8_unchecked(valid) };
1556 let (c, len) = Self::first_char_and_len(s);
1557 Some((c, len))
1558 } else {
1559 None
1560 }
1561 },
1562 }
1563 }
1564
1565 fn dispatch_callback<F: FnMut(InputEvent)>(&mut self, mut callback: F, event: InputEvent) {
1566 match (self.state, &event) {
1567 (
1568 InputState::Normal,
1569 InputEvent::Key(KeyEvent {
1570 key: KeyCode::InternalPasteStart,
1571 ..
1572 }),
1573 ) => {
1574 self.state = InputState::Pasting(0);
1575 },
1576 (
1577 InputState::EscapeMaybeAlt,
1578 InputEvent::Key(KeyEvent {
1579 key: KeyCode::InternalPasteStart,
1580 ..
1581 }),
1582 ) => {
1583 callback(InputEvent::Key(KeyEvent {
1586 key: KeyCode::Escape,
1587 modifiers: Modifiers::NONE,
1588 }));
1589 self.state = InputState::Pasting(0);
1590 },
1591 (InputState::EscapeMaybeAlt, InputEvent::Key(KeyEvent { key, modifiers })) => {
1592 let key = *key;
1594 let modifiers = *modifiers;
1595 self.state = InputState::Normal;
1596 callback(InputEvent::Key(KeyEvent {
1597 key,
1598 modifiers: modifiers | Modifiers::ALT,
1599 }));
1600 },
1601 (InputState::EscapeMaybeAlt, _) => {
1602 callback(InputEvent::Key(KeyEvent {
1605 key: KeyCode::Escape,
1606 modifiers: Modifiers::NONE,
1607 }));
1608 callback(event);
1609 },
1610 (_, _) => callback(event),
1611 }
1612 }
1613
1614 fn process_bytes<F: FnMut(InputEvent)>(&mut self, mut callback: F, maybe_more: bool) {
1615 while !self.buf.is_empty() {
1616 match self.state {
1617 InputState::Pasting(offset) => {
1618 let end_paste = b"\x1b[201~";
1619 if let Some(idx) = self.buf.find_subsequence(offset, end_paste) {
1620 let pasted =
1621 String::from_utf8_lossy(&self.buf.as_slice()[0..idx]).to_string();
1622 self.buf.advance(pasted.len() + end_paste.len());
1623 callback(InputEvent::Paste(pasted));
1624 self.state = InputState::Normal;
1625 } else {
1626 self.state =
1627 InputState::Pasting(self.buf.len().saturating_sub(end_paste.len()));
1628 return;
1629 }
1630 },
1631 InputState::EscapeMaybeAlt | InputState::Normal => {
1632 if self.state == InputState::Normal
1633 && self.buf.as_slice().get(0) == Some(&b'\x1b')
1634 {
1635 if let Some((event, len)) = parse_sgr_mouse(self.buf.as_slice()) {
1636 self.buf.advance(len);
1637 callback(event);
1638 continue;
1639 }
1640
1641 if let Some((event, len)) = parse_osc(self.buf.as_slice()) {
1643 self.buf.advance(len);
1644 callback(event);
1645 continue;
1646 }
1647
1648 if maybe_more && self.buf.as_slice().starts_with(b"\x1b]") {
1650 return;
1651 }
1652
1653 if maybe_more && self.buf.as_slice().starts_with(b"\x1b[<") {
1654 return;
1655 }
1656
1657 if let Some((event, len)) = parse_csi_report(self.buf.as_slice()) {
1663 self.buf.advance(len);
1664 callback(event);
1665 continue;
1666 }
1667
1668 if maybe_more && self.buf.as_slice().starts_with(b"\x1b[?") {
1673 return;
1674 }
1675 }
1676
1677 match (
1678 self.key_map.lookup(self.buf.as_slice(), maybe_more),
1679 maybe_more,
1680 ) {
1681 (
1687 Found::Exact(
1688 len,
1689 InputEvent::Key(KeyEvent {
1690 key: KeyCode::Escape,
1691 modifiers: Modifiers::NONE,
1692 }),
1693 ),
1694 _,
1695 ) if self.state == InputState::Normal && self.buf.len() > len => {
1696 self.state = InputState::EscapeMaybeAlt;
1697 self.buf.advance(len);
1698 },
1699 (Found::Exact(len, event), _) | (Found::Ambiguous(len, event), false) => {
1700 self.dispatch_callback(&mut callback, event.clone());
1701 self.buf.advance(len);
1702 },
1703 (Found::Ambiguous(_, _), true) | (Found::NeedData, true) => {
1704 return;
1705 },
1706 (Found::None, _) | (Found::NeedData, false) => {
1707 if let Some((c, len)) = Self::decode_one_char(self.buf.as_slice()) {
1709 self.buf.advance(len);
1710 self.dispatch_callback(
1711 &mut callback,
1712 InputEvent::Key(KeyEvent {
1713 key: KeyCode::Char(c),
1714 modifiers: Modifiers::NONE,
1715 }),
1716 );
1717 } else {
1718 return;
1721 }
1722 },
1723 }
1724 },
1725 }
1726 }
1727 }
1728
1729 pub fn parse<F: FnMut(InputEvent)>(&mut self, bytes: &[u8], callback: F, maybe_more: bool) {
1744 self.buf.extend_with(bytes);
1745 self.process_bytes(callback, maybe_more);
1746 }
1747
1748 pub fn parse_as_vec(&mut self, bytes: &[u8], maybe_more: bool) -> Vec<InputEvent> {
1749 let mut result = Vec::new();
1750 self.parse(bytes, |event| result.push(event), maybe_more);
1751 result
1752 }
1753
1754 #[cfg(windows)]
1755 pub fn decode_input_records_as_vec(
1756 &mut self,
1757 records: &[winapi::um::wincon::INPUT_RECORD],
1758 ) -> Vec<InputEvent> {
1759 let mut result = Vec::new();
1760 self.decode_input_records(records, &mut |event| result.push(event));
1761 result
1762 }
1763}
1764
1765#[cfg(test)]
1766mod test {
1767 use super::*;
1768
1769 const NO_MORE: bool = false;
1770 const MAYBE_MORE: bool = true;
1771
1772 #[test]
1773 fn simple() {
1774 let mut p = InputParser::new();
1775 let inputs = p.parse_as_vec(b"hello", NO_MORE);
1776 assert_eq!(
1777 vec![
1778 InputEvent::Key(KeyEvent {
1779 modifiers: Modifiers::NONE,
1780 key: KeyCode::Char('h'),
1781 }),
1782 InputEvent::Key(KeyEvent {
1783 modifiers: Modifiers::NONE,
1784 key: KeyCode::Char('e'),
1785 }),
1786 InputEvent::Key(KeyEvent {
1787 modifiers: Modifiers::NONE,
1788 key: KeyCode::Char('l'),
1789 }),
1790 InputEvent::Key(KeyEvent {
1791 modifiers: Modifiers::NONE,
1792 key: KeyCode::Char('l'),
1793 }),
1794 InputEvent::Key(KeyEvent {
1795 modifiers: Modifiers::NONE,
1796 key: KeyCode::Char('o'),
1797 }),
1798 ],
1799 inputs
1800 );
1801 }
1802
1803 #[test]
1804 fn control_characters() {
1805 let mut p = InputParser::new();
1806 let inputs = p.parse_as_vec(b"\x03\x1bJ\x7f", NO_MORE);
1807 assert_eq!(
1808 vec![
1809 InputEvent::Key(KeyEvent {
1810 modifiers: Modifiers::CTRL,
1811 key: KeyCode::Char('c'),
1812 }),
1813 InputEvent::Key(KeyEvent {
1814 modifiers: Modifiers::ALT,
1815 key: KeyCode::Char('J'),
1816 }),
1817 InputEvent::Key(KeyEvent {
1818 modifiers: Modifiers::NONE,
1819 key: KeyCode::Backspace,
1820 }),
1821 ],
1822 inputs
1823 );
1824 }
1825
1826 #[test]
1827 fn arrow_keys() {
1828 let mut p = InputParser::new();
1829 let inputs = p.parse_as_vec(b"\x1bOA\x1bOB\x1bOC\x1bOD", NO_MORE);
1830 assert_eq!(
1831 vec![
1832 InputEvent::Key(KeyEvent {
1833 modifiers: Modifiers::NONE,
1834 key: KeyCode::ApplicationUpArrow,
1835 }),
1836 InputEvent::Key(KeyEvent {
1837 modifiers: Modifiers::NONE,
1838 key: KeyCode::ApplicationDownArrow,
1839 }),
1840 InputEvent::Key(KeyEvent {
1841 modifiers: Modifiers::NONE,
1842 key: KeyCode::ApplicationRightArrow,
1843 }),
1844 InputEvent::Key(KeyEvent {
1845 modifiers: Modifiers::NONE,
1846 key: KeyCode::ApplicationLeftArrow,
1847 }),
1848 ],
1849 inputs
1850 );
1851 }
1852
1853 #[test]
1854 fn partial() {
1855 let mut p = InputParser::new();
1856 let mut inputs = Vec::new();
1857 p.parse(b"\x1b[11", |evt| inputs.push(evt), true);
1859 p.parse(b"~", |evt| inputs.push(evt), true);
1860 assert_eq!(
1862 vec![InputEvent::Key(KeyEvent {
1863 modifiers: Modifiers::NONE,
1864 key: KeyCode::Function(1),
1865 })],
1866 inputs
1867 );
1868 }
1869
1870 #[test]
1871 fn partial_ambig() {
1872 let mut p = InputParser::new();
1873
1874 assert_eq!(
1875 vec![InputEvent::Key(KeyEvent {
1876 key: KeyCode::Escape,
1877 modifiers: Modifiers::NONE,
1878 })],
1879 p.parse_as_vec(b"\x1b", false)
1880 );
1881
1882 let mut inputs = Vec::new();
1883 p.parse(b"\x1b[11", |evt| inputs.push(evt), MAYBE_MORE);
1885 p.parse(b"", |evt| inputs.push(evt), NO_MORE);
1886 assert_eq!(
1889 vec![
1890 InputEvent::Key(KeyEvent {
1891 modifiers: Modifiers::ALT,
1892 key: KeyCode::Char('['),
1893 }),
1894 InputEvent::Key(KeyEvent {
1895 modifiers: Modifiers::NONE,
1896 key: KeyCode::Char('1'),
1897 }),
1898 InputEvent::Key(KeyEvent {
1899 modifiers: Modifiers::NONE,
1900 key: KeyCode::Char('1'),
1901 }),
1902 ],
1903 inputs
1904 );
1905 }
1906
1907 #[test]
1908 fn partial_mouse() {
1909 let mut p = InputParser::new();
1910 let mut inputs = Vec::new();
1911 p.parse(b"\x1b[<0;0;0", |evt| inputs.push(evt), true);
1913 p.parse(b"M", |evt| inputs.push(evt), true);
1914 assert_eq!(
1916 vec![InputEvent::Mouse(MouseEvent {
1917 x: 0,
1918 y: 0,
1919 mouse_buttons: MouseButtons::LEFT,
1920 modifiers: Modifiers::NONE,
1921 })],
1922 inputs
1923 );
1924 }
1925
1926 #[test]
1927 fn partial_mouse_ambig() {
1928 let mut p = InputParser::new();
1929 let mut inputs = Vec::new();
1930 p.parse(b"\x1b[<", |evt| inputs.push(evt), MAYBE_MORE);
1932 p.parse(b"0;0;0", |evt| inputs.push(evt), NO_MORE);
1933 assert_eq!(
1936 vec![
1937 InputEvent::Key(KeyEvent {
1938 modifiers: Modifiers::ALT,
1939 key: KeyCode::Char('['),
1940 }),
1941 InputEvent::Key(KeyEvent {
1942 modifiers: Modifiers::NONE,
1943 key: KeyCode::Char('<'),
1944 }),
1945 InputEvent::Key(KeyEvent {
1946 modifiers: Modifiers::NONE,
1947 key: KeyCode::Char('0'),
1948 }),
1949 InputEvent::Key(KeyEvent {
1950 modifiers: Modifiers::NONE,
1951 key: KeyCode::Char(';'),
1952 }),
1953 InputEvent::Key(KeyEvent {
1954 modifiers: Modifiers::NONE,
1955 key: KeyCode::Char('0'),
1956 }),
1957 InputEvent::Key(KeyEvent {
1958 modifiers: Modifiers::NONE,
1959 key: KeyCode::Char(';'),
1960 }),
1961 InputEvent::Key(KeyEvent {
1962 modifiers: Modifiers::NONE,
1963 key: KeyCode::Char('0'),
1964 }),
1965 ],
1966 inputs
1967 );
1968 }
1969
1970 #[test]
1971 fn alt_left_bracket() {
1972 let mut p = InputParser::new();
1975
1976 let mut inputs = Vec::new();
1977 p.parse(b"\x1b[", |evt| inputs.push(evt), false);
1978
1979 assert_eq!(
1980 vec![InputEvent::Key(KeyEvent {
1981 modifiers: Modifiers::ALT,
1982 key: KeyCode::Char('['),
1983 }),],
1984 inputs
1985 );
1986 }
1987
1988 #[test]
1989 fn modify_other_keys_parse() {
1990 let mut p = InputParser::new();
1991 let inputs = p.parse_as_vec(
1992 b"\x1b[27;5;13~\x1b[27;5;9~\x1b[27;6;8~\x1b[27;2;127~\x1b[27;6;27~",
1993 NO_MORE,
1994 );
1995 assert_eq!(
1996 vec![
1997 InputEvent::Key(KeyEvent {
1998 key: KeyCode::Enter,
1999 modifiers: Modifiers::CTRL,
2000 }),
2001 InputEvent::Key(KeyEvent {
2002 key: KeyCode::Tab,
2003 modifiers: Modifiers::CTRL,
2004 }),
2005 InputEvent::Key(KeyEvent {
2006 key: KeyCode::Backspace,
2007 modifiers: Modifiers::CTRL | Modifiers::SHIFT,
2008 }),
2009 InputEvent::Key(KeyEvent {
2010 key: KeyCode::Backspace,
2011 modifiers: Modifiers::SHIFT,
2012 }),
2013 InputEvent::Key(KeyEvent {
2014 key: KeyCode::Escape,
2015 modifiers: Modifiers::CTRL | Modifiers::SHIFT,
2016 }),
2017 ],
2018 inputs
2019 );
2020 }
2021
2022 #[test]
2023 fn modify_other_keys_encode() {
2024 let mode = KeyCodeEncodeModes {
2025 encoding: KeyboardEncoding::Xterm,
2026 newline_mode: false,
2027 application_cursor_keys: false,
2028 modify_other_keys: None,
2029 };
2030 let mode_1 = KeyCodeEncodeModes {
2031 encoding: KeyboardEncoding::Xterm,
2032 newline_mode: false,
2033 application_cursor_keys: false,
2034 modify_other_keys: Some(1),
2035 };
2036 let mode_2 = KeyCodeEncodeModes {
2037 encoding: KeyboardEncoding::Xterm,
2038 newline_mode: false,
2039 application_cursor_keys: false,
2040 modify_other_keys: Some(2),
2041 };
2042
2043 assert_eq!(
2044 KeyCode::Enter.encode(Modifiers::CTRL, mode, true).unwrap(),
2045 "\r".to_string()
2046 );
2047 assert_eq!(
2048 KeyCode::Enter
2049 .encode(Modifiers::CTRL, mode_1, true)
2050 .unwrap(),
2051 "\x1b[27;5;13~".to_string()
2052 );
2053 assert_eq!(
2054 KeyCode::Enter
2055 .encode(Modifiers::CTRL | Modifiers::SHIFT, mode_1, true)
2056 .unwrap(),
2057 "\x1b[27;6;13~".to_string()
2058 );
2059
2060 assert_eq!(
2064 KeyCode::Tab.encode(Modifiers::CTRL, mode, true).unwrap(),
2065 "\x1b[9;5u".to_string()
2066 );
2067 assert_eq!(
2068 KeyCode::Tab.encode(Modifiers::CTRL, mode_1, true).unwrap(),
2069 "\x1b[27;5;9~".to_string()
2070 );
2071 assert_eq!(
2072 KeyCode::Tab
2073 .encode(Modifiers::CTRL | Modifiers::SHIFT, mode_1, true)
2074 .unwrap(),
2075 "\x1b[27;6;9~".to_string()
2076 );
2077
2078 assert_eq!(
2079 KeyCode::Char('c')
2080 .encode(Modifiers::CTRL, mode, true)
2081 .unwrap(),
2082 "\x03".to_string()
2083 );
2084 assert_eq!(
2085 KeyCode::Char('c')
2086 .encode(Modifiers::CTRL, mode_1, true)
2087 .unwrap(),
2088 "\x03".to_string()
2089 );
2090 assert_eq!(
2091 KeyCode::Char('c')
2092 .encode(Modifiers::CTRL, mode_2, true)
2093 .unwrap(),
2094 "\x1b[27;5;99~".to_string()
2095 );
2096
2097 assert_eq!(
2098 KeyCode::Char('1')
2099 .encode(Modifiers::CTRL, mode, true)
2100 .unwrap(),
2101 "1".to_string()
2102 );
2103 assert_eq!(
2104 KeyCode::Char('1')
2105 .encode(Modifiers::CTRL, mode_2, true)
2106 .unwrap(),
2107 "\x1b[27;5;49~".to_string()
2108 );
2109
2110 assert_eq!(
2111 KeyCode::Char(',')
2112 .encode(Modifiers::CTRL, mode, true)
2113 .unwrap(),
2114 ",".to_string()
2115 );
2116 assert_eq!(
2117 KeyCode::Char(',')
2118 .encode(Modifiers::CTRL, mode_2, true)
2119 .unwrap(),
2120 "\x1b[27;5;44~".to_string()
2121 );
2122 }
2123
2124 #[test]
2125 fn encode_issue_892() {
2126 let mode = KeyCodeEncodeModes {
2127 encoding: KeyboardEncoding::Xterm,
2128 newline_mode: false,
2129 application_cursor_keys: false,
2130 modify_other_keys: None,
2131 };
2132
2133 assert_eq!(
2134 KeyCode::LeftArrow
2135 .encode(Modifiers::NONE, mode, true)
2136 .unwrap(),
2137 "\x1b[D".to_string()
2138 );
2139 assert_eq!(
2140 KeyCode::LeftArrow
2141 .encode(Modifiers::ALT, mode, true)
2142 .unwrap(),
2143 "\x1b[1;3D".to_string()
2144 );
2145 assert_eq!(
2146 KeyCode::Home.encode(Modifiers::NONE, mode, true).unwrap(),
2147 "\x1b[H".to_string()
2148 );
2149 assert_eq!(
2150 KeyCode::Home.encode(Modifiers::ALT, mode, true).unwrap(),
2151 "\x1b[1;3H".to_string()
2152 );
2153 assert_eq!(
2154 KeyCode::End.encode(Modifiers::NONE, mode, true).unwrap(),
2155 "\x1b[F".to_string()
2156 );
2157 assert_eq!(
2158 KeyCode::End.encode(Modifiers::ALT, mode, true).unwrap(),
2159 "\x1b[1;3F".to_string()
2160 );
2161 assert_eq!(
2162 KeyCode::Tab.encode(Modifiers::ALT, mode, true).unwrap(),
2163 "\x1b\t".to_string()
2164 );
2165 assert_eq!(
2166 KeyCode::PageUp.encode(Modifiers::ALT, mode, true).unwrap(),
2167 "\x1b[5;3~".to_string()
2168 );
2169 assert_eq!(
2170 KeyCode::Function(1)
2171 .encode(Modifiers::NONE, mode, true)
2172 .unwrap(),
2173 "\x1bOP".to_string()
2174 );
2175 }
2176
2177 #[test]
2178 fn partial_bracketed_paste() {
2179 let mut p = InputParser::new();
2180
2181 let input = b"\x1b[200~1234";
2182 let input2 = b"5678\x1b[201~";
2183
2184 let mut inputs = vec![];
2185
2186 p.parse(input, |e| inputs.push(e), false);
2187 p.parse(input2, |e| inputs.push(e), false);
2188
2189 assert_eq!(vec![InputEvent::Paste("12345678".to_owned())], inputs)
2190 }
2191
2192 #[test]
2193 fn mouse_horizontal_scroll() {
2194 let mut p = InputParser::new();
2195
2196 let input = b"\x1b[<66;42;12M\x1b[<67;42;12M";
2197 let res = p.parse_as_vec(input, MAYBE_MORE);
2198
2199 assert_eq!(
2200 vec![
2201 InputEvent::Mouse(MouseEvent {
2202 x: 42,
2203 y: 12,
2204 mouse_buttons: MouseButtons::HORZ_WHEEL | MouseButtons::WHEEL_POSITIVE,
2205 modifiers: Modifiers::NONE,
2206 }),
2207 InputEvent::Mouse(MouseEvent {
2208 x: 42,
2209 y: 12,
2210 mouse_buttons: MouseButtons::HORZ_WHEEL,
2211 modifiers: Modifiers::NONE,
2212 })
2213 ],
2214 res
2215 );
2216 }
2217
2218 #[test]
2219 fn encode_issue_3478_xterm() {
2220 let mode = KeyCodeEncodeModes {
2221 encoding: KeyboardEncoding::Xterm,
2222 newline_mode: false,
2223 application_cursor_keys: false,
2224 modify_other_keys: None,
2225 };
2226
2227 assert_eq!(
2228 KeyCode::Numpad0
2229 .encode(Modifiers::NONE, mode, true)
2230 .unwrap(),
2231 "\u{1b}[2~".to_string()
2232 );
2233 assert_eq!(
2234 KeyCode::Numpad0
2235 .encode(Modifiers::SHIFT, mode, true)
2236 .unwrap(),
2237 "\u{1b}[2;2~".to_string()
2238 );
2239
2240 assert_eq!(
2241 KeyCode::Numpad1
2242 .encode(Modifiers::NONE, mode, true)
2243 .unwrap(),
2244 "\u{1b}[F".to_string()
2245 );
2246 assert_eq!(
2247 KeyCode::Numpad1
2248 .encode(Modifiers::NONE | Modifiers::SHIFT, mode, true)
2249 .unwrap(),
2250 "\u{1b}[1;2F".to_string()
2251 );
2252 }
2253
2254 #[test]
2255 fn encode_tab_with_modifiers() {
2256 let mode = KeyCodeEncodeModes {
2257 encoding: KeyboardEncoding::Xterm,
2258 newline_mode: false,
2259 application_cursor_keys: false,
2260 modify_other_keys: None,
2261 };
2262
2263 let mods_to_result = [
2264 (Modifiers::SHIFT, "\u{1b}[Z"),
2265 (Modifiers::SHIFT | Modifiers::LEFT_SHIFT, "\u{1b}[Z"),
2266 (Modifiers::SHIFT | Modifiers::RIGHT_SHIFT, "\u{1b}[Z"),
2267 (Modifiers::CTRL, "\u{1b}[9;5u"),
2268 (Modifiers::CTRL | Modifiers::LEFT_CTRL, "\u{1b}[9;5u"),
2269 (Modifiers::CTRL | Modifiers::RIGHT_CTRL, "\u{1b}[9;5u"),
2270 (
2271 Modifiers::SHIFT | Modifiers::CTRL | Modifiers::LEFT_CTRL | Modifiers::LEFT_SHIFT,
2272 "\u{1b}[1;5Z",
2273 ),
2274 ];
2275 for (mods, result) in mods_to_result {
2276 assert_eq!(
2277 KeyCode::Tab.encode(mods, mode, true).unwrap(),
2278 result,
2279 "{:?}",
2280 mods
2281 );
2282 }
2283 }
2284
2285 #[test]
2286 fn mouse_button1_press() {
2287 let mut p = InputParser::new();
2288 let res = p.parse_as_vec(b"\x1b[<0;42;12M", true);
2289 assert_eq!(
2290 res,
2291 vec![InputEvent::Mouse(MouseEvent {
2292 x: 42,
2293 y: 12,
2294 mouse_buttons: MouseButtons::LEFT,
2295 modifiers: Modifiers::NONE,
2296 })]
2297 );
2298 }
2299
2300 #[test]
2301 fn mouse_button1_release() {
2302 let mut p = InputParser::new();
2303 let res = p.parse_as_vec(b"\x1b[<0;42;12m", true);
2304 assert_eq!(
2305 res,
2306 vec![InputEvent::Mouse(MouseEvent {
2307 x: 42,
2308 y: 12,
2309 mouse_buttons: MouseButtons::NONE,
2310 modifiers: Modifiers::NONE,
2311 })]
2312 );
2313 }
2314
2315 #[test]
2316 fn mouse_button3_with_shift() {
2317 let mut p = InputParser::new();
2318 let res = p.parse_as_vec(b"\x1b[<6;10;20M", true);
2320 assert_eq!(
2321 res,
2322 vec![InputEvent::Mouse(MouseEvent {
2323 x: 10,
2324 y: 20,
2325 mouse_buttons: MouseButtons::RIGHT,
2326 modifiers: Modifiers::SHIFT,
2327 })]
2328 );
2329 }
2330
2331 #[test]
2332 fn mouse_drag() {
2333 let mut p = InputParser::new();
2334 let res = p.parse_as_vec(b"\x1b[<32;5;5M", true);
2336 assert_eq!(
2337 res,
2338 vec![InputEvent::Mouse(MouseEvent {
2339 x: 5,
2340 y: 5,
2341 mouse_buttons: MouseButtons::LEFT,
2342 modifiers: Modifiers::NONE,
2343 })]
2344 );
2345 }
2346
2347 #[test]
2348 fn mouse_vertical_scroll_up() {
2349 let mut p = InputParser::new();
2350 let res = p.parse_as_vec(b"\x1b[<64;1;1M", true);
2352 assert_eq!(
2353 res,
2354 vec![InputEvent::Mouse(MouseEvent {
2355 x: 1,
2356 y: 1,
2357 mouse_buttons: MouseButtons::VERT_WHEEL | MouseButtons::WHEEL_POSITIVE,
2358 modifiers: Modifiers::NONE,
2359 })]
2360 );
2361 }
2362
2363 #[test]
2364 fn mouse_vertical_scroll_down() {
2365 let mut p = InputParser::new();
2366 let res = p.parse_as_vec(b"\x1b[<65;1;1M", true);
2368 assert_eq!(
2369 res,
2370 vec![InputEvent::Mouse(MouseEvent {
2371 x: 1,
2372 y: 1,
2373 mouse_buttons: MouseButtons::VERT_WHEEL,
2374 modifiers: Modifiers::NONE,
2375 })]
2376 );
2377 }
2378
2379 #[test]
2380 fn mouse_motion_no_buttons() {
2381 let mut p = InputParser::new();
2382 let res = p.parse_as_vec(b"\x1b[<35;10;10M", true);
2384 assert_eq!(
2385 res,
2386 vec![InputEvent::Mouse(MouseEvent {
2387 x: 10,
2388 y: 10,
2389 mouse_buttons: MouseButtons::NONE,
2390 modifiers: Modifiers::NONE,
2391 })]
2392 );
2393 }
2394
2395 #[test]
2396 fn mouse_with_ctrl_alt() {
2397 let mut p = InputParser::new();
2398 let res = p.parse_as_vec(b"\x1b[<24;1;1M", true);
2400 assert_eq!(
2401 res,
2402 vec![InputEvent::Mouse(MouseEvent {
2403 x: 1,
2404 y: 1,
2405 mouse_buttons: MouseButtons::LEFT,
2406 modifiers: Modifiers::ALT | Modifiers::CTRL,
2407 })]
2408 );
2409 }
2410
2411 #[test]
2412 fn mouse_large_coordinates() {
2413 let mut p = InputParser::new();
2414 let res = p.parse_as_vec(b"\x1b[<0;999;999M", true);
2415 assert_eq!(
2416 res,
2417 vec![InputEvent::Mouse(MouseEvent {
2418 x: 999,
2419 y: 999,
2420 mouse_buttons: MouseButtons::LEFT,
2421 modifiers: Modifiers::NONE,
2422 })]
2423 );
2424 }
2425
2426 #[test]
2427 fn mouse_followed_by_key() {
2428 let mut p = InputParser::new();
2429 let res = p.parse_as_vec(b"\x1b[<0;1;1Mhello", false);
2430 assert_eq!(res.len(), 6); assert!(matches!(res[0], InputEvent::Mouse(_)));
2432 assert!(matches!(res[1], InputEvent::Key(_)));
2433 }
2434
2435 #[test]
2436 fn two_mouse_events_back_to_back() {
2437 let mut p = InputParser::new();
2438 let res = p.parse_as_vec(b"\x1b[<0;1;1M\x1b[<0;2;2M", true);
2439 assert_eq!(res.len(), 2);
2440 }
2441
2442 #[test]
2443 fn invalid_sgr_mouse_falls_through() {
2444 let mut p = InputParser::new();
2445 let res = p.parse_as_vec(b"\x1b[<0;1M", false);
2447 assert!(res.iter().all(|e| matches!(e, InputEvent::Key(_))));
2449 }
2450
2451 #[test]
2452 fn osc_bel_terminated() {
2453 let mut p = InputParser::new();
2455 let inputs = p.parse_as_vec(b"\x1b]99;i=test:p=title;Hello\x07", NO_MORE);
2456 assert_eq!(
2457 vec![InputEvent::OperatingSystemCommand(
2458 b"99;i=test:p=title;Hello".to_vec()
2459 )],
2460 inputs
2461 );
2462 }
2463
2464 #[test]
2465 fn osc_st_terminated() {
2466 let mut p = InputParser::new();
2468 let inputs = p.parse_as_vec(b"\x1b]99;i=test:p=title;Hello\x1b\\", NO_MORE);
2469 assert_eq!(
2470 vec![InputEvent::OperatingSystemCommand(
2471 b"99;i=test:p=title;Hello".to_vec()
2472 )],
2473 inputs
2474 );
2475 }
2476
2477 #[test]
2478 fn osc_partial_across_reads() {
2479 let mut p = InputParser::new();
2481 let mut inputs = Vec::new();
2482 p.parse(
2483 b"\x1b]99;i=test:p=title;Hel",
2484 |evt| inputs.push(evt),
2485 MAYBE_MORE,
2486 );
2487 assert!(inputs.is_empty(), "no events yet - sequence incomplete");
2488 p.parse(b"lo\x1b\\", |evt| inputs.push(evt), MAYBE_MORE);
2489 assert_eq!(
2490 vec![InputEvent::OperatingSystemCommand(
2491 b"99;i=test:p=title;Hello".to_vec()
2492 )],
2493 inputs
2494 );
2495 }
2496
2497 #[test]
2498 fn osc_followed_by_keypress() {
2499 let mut p = InputParser::new();
2501 let inputs = p.parse_as_vec(b"\x1b]99;i=test;clicked\x07x", NO_MORE);
2502 assert_eq!(
2503 vec![
2504 InputEvent::OperatingSystemCommand(b"99;i=test;clicked".to_vec()),
2505 InputEvent::Key(KeyEvent {
2506 modifiers: Modifiers::NONE,
2507 key: KeyCode::Char('x'),
2508 }),
2509 ],
2510 inputs
2511 );
2512 }
2513
2514 #[test]
2515 fn keypress_followed_by_osc() {
2516 let mut p = InputParser::new();
2518 let inputs = p.parse_as_vec(b"x\x1b]99;i=test;clicked\x07", NO_MORE);
2519 assert_eq!(
2520 vec![
2521 InputEvent::Key(KeyEvent {
2522 modifiers: Modifiers::NONE,
2523 key: KeyCode::Char('x'),
2524 }),
2525 InputEvent::OperatingSystemCommand(b"99;i=test;clicked".to_vec()),
2526 ],
2527 inputs
2528 );
2529 }
2530
2531 #[test]
2532 fn osc_incomplete_degrades_to_keys() {
2533 let mut p = InputParser::new();
2536 let mut inputs = Vec::new();
2537 p.parse(b"\x1b]99;no-terminator", |evt| inputs.push(evt), MAYBE_MORE);
2538 assert!(inputs.is_empty(), "buffered while maybe_more=true");
2539 p.parse(b"", |evt| inputs.push(evt), NO_MORE);
2540 assert!(!inputs.is_empty(), "must emit something on finalization");
2541 }
2542
2543 #[test]
2544 fn osc_non_99_code() {
2545 let mut p = InputParser::new();
2547 let inputs = p.parse_as_vec(b"\x1b]11;rgb:0000/0000/0000\x1b\\", NO_MORE);
2548 assert_eq!(
2549 vec![InputEvent::OperatingSystemCommand(
2550 b"11;rgb:0000/0000/0000".to_vec()
2551 )],
2552 inputs
2553 );
2554 }
2555
2556 #[test]
2557 fn osc_empty_payload() {
2558 let mut p = InputParser::new();
2560 let inputs = p.parse_as_vec(b"\x1b]\x07", NO_MORE);
2561 assert_eq!(
2562 vec![InputEvent::OperatingSystemCommand(b"".to_vec())],
2563 inputs
2564 );
2565 }
2566
2567 #[test]
2568 fn csi_not_captured_as_osc() {
2569 let mut p = InputParser::new();
2572 let inputs = p.parse_as_vec(b"\x1b[A", NO_MORE);
2573 assert_eq!(
2574 vec![InputEvent::Key(KeyEvent {
2575 modifiers: Modifiers::NONE,
2576 key: KeyCode::UpArrow,
2577 })],
2578 inputs
2579 );
2580 }
2581
2582 fn csi_reply(intermediates: &[u8], params: &[u8], final_byte: u8, raw: &[u8]) -> InputEvent {
2587 InputEvent::DeviceControlReply {
2588 intermediates: intermediates.to_vec(),
2589 params: params.to_vec(),
2590 final_byte,
2591 raw: raw.to_vec(),
2592 }
2593 }
2594
2595 #[test]
2596 fn csi_report_recognises_each_whitelisted_final_byte() {
2597 let bytes = b"\x1b[4;600;800t";
2599 let (evt, consumed) = parse_csi_report(bytes).expect("t accepted");
2600 assert_eq!(consumed, bytes.len());
2601 assert_eq!(evt, csi_reply(b"", b"4;600;800", b't', bytes));
2602
2603 let bytes = b"\x1b[?2026;1$y";
2605 let (evt, consumed) = parse_csi_report(bytes).expect("y accepted");
2606 assert_eq!(consumed, bytes.len());
2607 assert_eq!(evt, csi_reply(b"$", b"?2026;1", b'y', bytes));
2608
2609 let bytes = b"\x1b[?62;1;6c";
2611 let (evt, consumed) = parse_csi_report(bytes).expect("c accepted");
2612 assert_eq!(consumed, bytes.len());
2613 assert_eq!(evt, csi_reply(b"", b"?62;1;6", b'c', bytes));
2614
2615 let bytes = b"\x1b[?997;1n";
2617 let (evt, consumed) = parse_csi_report(bytes).expect("n accepted");
2618 assert_eq!(consumed, bytes.len());
2619 assert_eq!(evt, csi_reply(b"", b"?997;1", b'n', bytes));
2620 }
2621
2622 #[test]
2623 fn csi_report_preserves_intermediates() {
2624 let bytes = b"\x1b[?2026;2$y";
2627 let (evt, _len) = parse_csi_report(bytes).expect("DECRPM accepted");
2628 let InputEvent::DeviceControlReply {
2629 intermediates,
2630 params,
2631 final_byte,
2632 raw,
2633 } = evt
2634 else {
2635 panic!("expected DeviceControlReply, got {:?}", evt);
2636 };
2637 assert_eq!(intermediates, b"$");
2638 assert_eq!(params, b"?2026;2");
2639 assert_eq!(final_byte, b'y');
2640 assert_eq!(raw, bytes);
2641 }
2642
2643 #[test]
2644 fn csi_report_rejects_non_whitelisted_final_bytes() {
2645 assert!(parse_csi_report(b"\x1b[A").is_none());
2647 assert!(parse_csi_report(b"\x1b[24;80R").is_none());
2650 assert!(parse_csi_report(b"\x1b[0m").is_none());
2653 }
2654
2655 #[test]
2656 fn csi_report_returns_none_on_truncated_input() {
2657 assert!(parse_csi_report(b"\x1b[4;600;800").is_none());
2661 assert!(parse_csi_report(b"\x1b[").is_none());
2663 assert!(parse_csi_report(b"").is_none());
2665 }
2666
2667 #[test]
2668 fn csi_report_raw_preserves_input_byte_for_byte() {
2669 let bytes = b"\x1b[4;16;8t";
2673 let (evt, consumed) = parse_csi_report(bytes).expect("accepted");
2674 assert_eq!(consumed, bytes.len());
2675 let InputEvent::DeviceControlReply { raw, .. } = evt else {
2676 panic!("wrong variant");
2677 };
2678 assert_eq!(&raw[..], bytes, "raw must be byte-identical to input");
2679 }
2680}