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}
143
144#[derive(Debug, Clone, PartialEq, Eq)]
145pub struct MouseEvent {
146 pub x: u16,
147 pub y: u16,
148 pub mouse_buttons: MouseButtons,
149 pub modifiers: Modifiers,
150}
151
152#[derive(Debug, Clone, PartialEq, Eq)]
153pub struct PixelMouseEvent {
154 pub x_pixels: u16,
155 pub y_pixels: u16,
156 pub mouse_buttons: MouseButtons,
157 pub modifiers: Modifiers,
158}
159
160#[derive(Debug, Clone, PartialEq, Eq)]
161pub struct KeyEvent {
162 pub key: KeyCode,
164 pub modifiers: Modifiers,
166}
167
168#[derive(Debug, Clone, Copy, PartialEq, Eq)]
169pub enum KeyboardEncoding {
170 Xterm,
171 CsiU,
173 Win32,
175 Kitty(KittyKeyboardFlags),
177}
178
179#[derive(Debug, Clone, Copy)]
182pub struct KeyCodeEncodeModes {
183 pub encoding: KeyboardEncoding,
184 pub application_cursor_keys: bool,
185 pub newline_mode: bool,
186 pub modify_other_keys: Option<i64>,
187}
188
189#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
193pub enum KeyCode {
194 Char(char),
196
197 Hyper,
198 Super,
199 Meta,
200
201 Cancel,
203 Backspace,
204 Tab,
205 Clear,
206 Enter,
207 Shift,
208 Escape,
209 LeftShift,
210 RightShift,
211 Control,
212 LeftControl,
213 RightControl,
214 Alt,
215 LeftAlt,
216 RightAlt,
217 Menu,
218 LeftMenu,
219 RightMenu,
220 Pause,
221 CapsLock,
222 PageUp,
223 PageDown,
224 End,
225 Home,
226 LeftArrow,
227 RightArrow,
228 UpArrow,
229 DownArrow,
230 Select,
231 Print,
232 Execute,
233 PrintScreen,
234 Insert,
235 Delete,
236 Help,
237 LeftWindows,
238 RightWindows,
239 Applications,
240 Sleep,
241 Numpad0,
242 Numpad1,
243 Numpad2,
244 Numpad3,
245 Numpad4,
246 Numpad5,
247 Numpad6,
248 Numpad7,
249 Numpad8,
250 Numpad9,
251 Multiply,
252 Add,
253 Separator,
254 Subtract,
255 Decimal,
256 Divide,
257 Function(u8),
259 NumLock,
260 ScrollLock,
261 Copy,
262 Cut,
263 Paste,
264 BrowserBack,
265 BrowserForward,
266 BrowserRefresh,
267 BrowserStop,
268 BrowserSearch,
269 BrowserFavorites,
270 BrowserHome,
271 VolumeMute,
272 VolumeDown,
273 VolumeUp,
274 MediaNextTrack,
275 MediaPrevTrack,
276 MediaStop,
277 MediaPlayPause,
278 ApplicationLeftArrow,
279 ApplicationRightArrow,
280 ApplicationUpArrow,
281 ApplicationDownArrow,
282 KeyPadHome,
283 KeyPadEnd,
284 KeyPadPageUp,
285 KeyPadPageDown,
286 KeyPadBegin,
287
288 #[doc(hidden)]
289 InternalPasteStart,
290 #[doc(hidden)]
291 InternalPasteEnd,
292}
293
294impl KeyCode {
295 pub fn normalize_shift_to_upper_case(self, modifiers: Modifiers) -> KeyCode {
298 if modifiers.contains(Modifiers::SHIFT) {
299 match self {
300 KeyCode::Char(c) if c.is_ascii_lowercase() => KeyCode::Char(c.to_ascii_uppercase()),
301 _ => self,
302 }
303 } else {
304 self
305 }
306 }
307
308 pub fn is_modifier(self) -> bool {
310 matches!(
311 self,
312 Self::Hyper
313 | Self::Super
314 | Self::Meta
315 | Self::Shift
316 | Self::LeftShift
317 | Self::RightShift
318 | Self::Control
319 | Self::LeftControl
320 | Self::RightControl
321 | Self::Alt
322 | Self::LeftAlt
323 | Self::RightAlt
324 | Self::LeftWindows
325 | Self::RightWindows
326 )
327 }
328
329 pub fn encode(
331 &self,
332 mods: Modifiers,
333 modes: KeyCodeEncodeModes,
334 is_down: bool,
335 ) -> Result<String> {
336 if !is_down {
337 return Ok(String::new());
339 }
340 let mods = mods.remove_positional_mods();
343
344 use KeyCode::*;
345
346 let key = self.normalize_shift_to_upper_case(mods);
347 let mods = match key {
350 Char(c)
351 if (c.is_ascii_punctuation() || c.is_ascii_uppercase())
352 && mods.contains(Modifiers::SHIFT) =>
353 {
354 mods & !Modifiers::SHIFT
355 },
356 _ => mods,
357 };
358
359 let key = match key {
361 Char('\x7f') => Delete,
362 Char('\x08') => Backspace,
363 c => c,
364 };
365
366 let mut buf = String::new();
367
368 match key {
371 Char(c)
372 if is_ambiguous_ascii_ctrl(c)
373 && mods.contains(Modifiers::CTRL)
374 && modes.encoding == KeyboardEncoding::CsiU =>
375 {
376 csi_u_encode(&mut buf, c, mods, &modes)?;
377 },
378 Char(c) if c.is_ascii_uppercase() && mods.contains(Modifiers::CTRL) => {
379 csi_u_encode(&mut buf, c, mods, &modes)?;
380 },
381
382 Char(c) if mods.contains(Modifiers::CTRL) && modes.modify_other_keys == Some(2) => {
383 csi_u_encode(&mut buf, c, mods, &modes)?;
384 },
385 Char(c) if mods.contains(Modifiers::CTRL) && ctrl_mapping(c).is_some() => {
386 let c = ctrl_mapping(c).unwrap();
387 if mods.contains(Modifiers::ALT) {
388 buf.push(0x1b as char);
389 }
390 buf.push(c);
391 },
392
393 Char(c)
399 if (c.is_ascii_alphanumeric() || c.is_ascii_punctuation())
400 && mods.contains(Modifiers::ALT) =>
401 {
402 buf.push(0x1b as char);
403 buf.push(c);
404 },
405
406 Backspace => {
407 if mods.contains(Modifiers::CTRL) {
411 csi_u_encode(&mut buf, '\x08', mods, &modes)?;
412 } else if mods.contains(Modifiers::SHIFT) {
413 csi_u_encode(&mut buf, '\x7f', mods, &modes)?;
414 } else {
415 if mods.contains(Modifiers::ALT) {
416 buf.push(0x1b as char);
417 }
418 buf.push('\x7f');
419 }
420 },
421
422 Enter | Escape => {
423 let c = match key {
424 Enter => '\r',
425 Escape => '\x1b',
426 _ => unreachable!(),
427 };
428 if mods.contains(Modifiers::SHIFT) || mods.contains(Modifiers::CTRL) {
429 csi_u_encode(&mut buf, c, mods, &modes)?;
430 } else {
431 if mods.contains(Modifiers::ALT) {
432 buf.push(0x1b as char);
433 }
434 buf.push(c);
435 if modes.newline_mode && key == Enter {
436 buf.push(0x0a as char);
437 }
438 }
439 },
440
441 Tab if !mods.is_empty() && modes.modify_other_keys.is_some() => {
442 csi_u_encode(&mut buf, '\t', mods, &modes)?;
443 },
444
445 Tab => {
446 if mods.contains(Modifiers::ALT) {
447 buf.push(0x1b as char);
448 }
449 let mods = mods & !Modifiers::ALT;
450 if mods == Modifiers::CTRL {
451 buf.push_str("\x1b[9;5u");
452 } else if mods == Modifiers::CTRL | Modifiers::SHIFT {
453 buf.push_str("\x1b[1;5Z");
454 } else if mods == Modifiers::SHIFT {
455 buf.push_str("\x1b[Z");
456 } else {
457 buf.push('\t');
458 }
459 },
460
461 Char(c) => {
462 if mods.is_empty() {
463 buf.push(c);
464 } else {
465 csi_u_encode(&mut buf, c, mods, &modes)?;
466 }
467 },
468
469 Home
470 | KeyPadHome
471 | End
472 | KeyPadEnd
473 | UpArrow
474 | DownArrow
475 | RightArrow
476 | LeftArrow
477 | ApplicationUpArrow
478 | ApplicationDownArrow
479 | ApplicationRightArrow
480 | ApplicationLeftArrow => {
481 let (force_app, c) = match key {
482 UpArrow => (false, 'A'),
483 DownArrow => (false, 'B'),
484 RightArrow => (false, 'C'),
485 LeftArrow => (false, 'D'),
486 KeyPadHome | Home => (false, 'H'),
487 End | KeyPadEnd => (false, 'F'),
488 ApplicationUpArrow => (true, 'A'),
489 ApplicationDownArrow => (true, 'B'),
490 ApplicationRightArrow => (true, 'C'),
491 ApplicationLeftArrow => (true, 'D'),
492 _ => unreachable!(),
493 };
494
495 let csi_or_ss3 = if force_app || modes.application_cursor_keys {
496 SS3
498 } else {
499 CSI
501 };
502
503 if mods.contains(Modifiers::ALT)
504 || mods.contains(Modifiers::SHIFT)
505 || mods.contains(Modifiers::CTRL)
506 {
507 write!(buf, "{}1;{}{}", CSI, 1 + mods.encode_xterm(), c)?;
508 } else {
509 write!(buf, "{}{}", csi_or_ss3, c)?;
510 }
511 },
512
513 PageUp | PageDown | KeyPadPageUp | KeyPadPageDown | Insert | Delete => {
514 let c = match key {
515 Insert => 2,
516 Delete => 3,
517 KeyPadPageUp | PageUp => 5,
518 KeyPadPageDown | PageDown => 6,
519 _ => unreachable!(),
520 };
521
522 if mods.contains(Modifiers::ALT)
523 || mods.contains(Modifiers::SHIFT)
524 || mods.contains(Modifiers::CTRL)
525 {
526 write!(buf, "\x1b[{};{}~", c, 1 + mods.encode_xterm())?;
527 } else {
528 write!(buf, "\x1b[{}~", c)?;
529 }
530 },
531
532 Function(n) => {
533 if mods.is_empty() && n < 5 {
534 write!(
536 buf,
537 "{}",
538 match n {
539 1 => "\x1bOP",
540 2 => "\x1bOQ",
541 3 => "\x1bOR",
542 4 => "\x1bOS",
543 _ => unreachable!("wat?"),
544 }
545 )?;
546 } else if n < 5 {
547 let code = match n {
549 1 => 'P',
550 2 => 'Q',
551 3 => 'R',
552 4 => 'S',
553 _ => unreachable!("wat?"),
554 };
555 write!(buf, "\x1b[1;{}{code}", 1 + mods.encode_xterm())?;
556 } else {
557 let intro = match n {
559 1 => "\x1b[11",
560 2 => "\x1b[12",
561 3 => "\x1b[13",
562 4 => "\x1b[14",
563 5 => "\x1b[15",
564 6 => "\x1b[17",
565 7 => "\x1b[18",
566 8 => "\x1b[19",
567 9 => "\x1b[20",
568 10 => "\x1b[21",
569 11 => "\x1b[23",
570 12 => "\x1b[24",
571 13 => "\x1b[25",
572 14 => "\x1b[26",
573 15 => "\x1b[28",
574 16 => "\x1b[29",
575 17 => "\x1b[31",
576 18 => "\x1b[32",
577 19 => "\x1b[33",
578 20 => "\x1b[34",
579 21 => "\x1b[42",
580 22 => "\x1b[43",
581 23 => "\x1b[44",
582 24 => "\x1b[45",
583 _ => return Err(format!("unhandled fkey number {}", n).into()),
584 };
585 let encoded_mods = mods.encode_xterm();
586 if encoded_mods == 0 {
587 write!(buf, "{}~", intro)?;
590 } else {
591 write!(buf, "{};{}~", intro, 1 + encoded_mods)?;
592 }
593 }
594 },
595
596 Numpad0 | Numpad3 | Numpad9 | Decimal => {
597 let intro = match key {
598 Numpad0 => "\x1b[2",
599 Numpad3 => "\x1b[6",
600 Numpad9 => "\x1b[6",
601 Decimal => "\x1b[3",
602 _ => unreachable!(),
603 };
604
605 let encoded_mods = mods.encode_xterm();
606 if encoded_mods == 0 {
607 write!(buf, "{}~", intro)?;
608 } else {
609 write!(buf, "{};{}~", intro, 1 + encoded_mods)?;
610 }
611 },
612
613 Numpad1 | Numpad2 | Numpad4 | Numpad5 | KeyPadBegin | Numpad6 | Numpad7 | Numpad8 => {
614 let c = match key {
615 Numpad1 => "F",
616 Numpad2 => "B",
617 Numpad4 => "D",
618 KeyPadBegin | Numpad5 => "E",
619 Numpad6 => "C",
620 Numpad7 => "H",
621 Numpad8 => "A",
622 _ => unreachable!(),
623 };
624
625 let encoded_mods = mods.encode_xterm();
626 if encoded_mods == 0 {
627 write!(buf, "{}{}", CSI, c)?;
628 } else {
629 write!(buf, "{}1;{}{}", CSI, 1 + encoded_mods, c)?;
630 }
631 },
632
633 Multiply | Add | Separator | Subtract | Divide => {},
634
635 Control | LeftControl | RightControl | Alt | LeftAlt | RightAlt | Menu | LeftMenu
637 | RightMenu | Super | Hyper | Shift | LeftShift | RightShift | Meta | LeftWindows
638 | RightWindows | NumLock | ScrollLock | Cancel | Clear | Pause | CapsLock | Select
639 | Print | PrintScreen | Execute | Help | Applications | Sleep | Copy | Cut | Paste
640 | BrowserBack | BrowserForward | BrowserRefresh | BrowserStop | BrowserSearch
641 | BrowserFavorites | BrowserHome | VolumeMute | VolumeDown | VolumeUp
642 | MediaNextTrack | MediaPrevTrack | MediaStop | MediaPlayPause | InternalPasteStart
643 | InternalPasteEnd => {},
644 };
645
646 Ok(buf)
647 }
648}
649
650fn is_ambiguous_ascii_ctrl(c: char) -> bool {
654 matches!(c, 'i' | 'I' | 'm' | 'M' | '[' | '{' | '@')
655}
656
657fn is_ascii(c: char) -> bool {
658 (c as u32) < 0x80
659}
660
661fn csi_u_encode(
662 buf: &mut String,
663 c: char,
664 mods: Modifiers,
665 modes: &KeyCodeEncodeModes,
666) -> Result<()> {
667 if modes.encoding == KeyboardEncoding::CsiU && is_ascii(c) {
668 write!(buf, "\x1b[{};{}u", c as u32, 1 + mods.encode_xterm())?;
669 return Ok(());
670 }
671
672 match (c, modes.modify_other_keys) {
674 ('c' | 'd' | '\x1b' | '\x7f' | '\x08', Some(1)) => {
675 },
677 (c, Some(_)) => {
678 write!(buf, "\x1b[27;{};{}~", 1 + mods.encode_xterm(), c as u32)?;
679 return Ok(());
680 },
681 _ => {},
682 }
683
684 let c = if mods.contains(Modifiers::CTRL) && ctrl_mapping(c).is_some() {
685 ctrl_mapping(c).unwrap()
686 } else {
687 c
688 };
689 if mods.contains(Modifiers::ALT) {
690 buf.push(0x1b as char);
691 }
692 write!(buf, "{}", c)?;
693 Ok(())
694}
695
696#[derive(Debug, Clone, Copy, PartialEq, Eq)]
697enum MouseButton {
698 Button1Press,
699 Button1Release,
700 Button1Drag,
701 Button2Press,
702 Button2Release,
703 Button2Drag,
704 Button3Press,
705 Button3Release,
706 Button3Drag,
707 Button4Press,
708 Button4Release,
709 Button5Press,
710 Button5Release,
711 Button6Press,
712 Button6Release,
713 Button7Press,
714 Button7Release,
715 None,
716}
717
718fn decode_mouse_button(control: u8, p0: i64) -> Option<MouseButton> {
719 match (control, p0 & 0b110_0011) {
720 (b'M', 0) => Some(MouseButton::Button1Press),
721 (b'm', 0) => Some(MouseButton::Button1Release),
722 (b'M', 1) => Some(MouseButton::Button2Press),
723 (b'm', 1) => Some(MouseButton::Button2Release),
724 (b'M', 2) => Some(MouseButton::Button3Press),
725 (b'm', 2) => Some(MouseButton::Button3Release),
726 (b'M', 64) => Some(MouseButton::Button4Press),
727 (b'm', 64) => Some(MouseButton::Button4Release),
728 (b'M', 65) => Some(MouseButton::Button5Press),
729 (b'm', 65) => Some(MouseButton::Button5Release),
730 (b'M', 66) => Some(MouseButton::Button6Press),
731 (b'm', 66) => Some(MouseButton::Button6Release),
732 (b'M', 67) => Some(MouseButton::Button7Press),
733 (b'm', 67) => Some(MouseButton::Button7Release),
734 (b'M', 32) => Some(MouseButton::Button1Drag),
735 (b'M', 33) => Some(MouseButton::Button2Drag),
736 (b'M', 34) => Some(MouseButton::Button3Drag),
737 (b'M', 35) | (b'm', 35) | (b'M', 3) | (b'm', 3) => Some(MouseButton::None),
738 _ => ::core::option::Option::None,
739 }
740}
741
742impl From<MouseButton> for MouseButtons {
743 fn from(button: MouseButton) -> MouseButtons {
744 match button {
745 MouseButton::Button1Press | MouseButton::Button1Drag => MouseButtons::LEFT,
746 MouseButton::Button2Press | MouseButton::Button2Drag => MouseButtons::MIDDLE,
747 MouseButton::Button3Press | MouseButton::Button3Drag => MouseButtons::RIGHT,
748 MouseButton::Button4Press => MouseButtons::VERT_WHEEL | MouseButtons::WHEEL_POSITIVE,
749 MouseButton::Button5Press => MouseButtons::VERT_WHEEL,
750 MouseButton::Button6Press => MouseButtons::HORZ_WHEEL | MouseButtons::WHEEL_POSITIVE,
751 MouseButton::Button7Press => MouseButtons::HORZ_WHEEL,
752 _ => MouseButtons::NONE,
753 }
754 }
755}
756
757fn decode_mouse_modifiers(p0: i64) -> Modifiers {
758 let mut modifiers = Modifiers::NONE;
759 if p0 & 4 != 0 {
760 modifiers |= Modifiers::SHIFT;
761 }
762 if p0 & 8 != 0 {
763 modifiers |= Modifiers::ALT;
764 }
765 if p0 & 16 != 0 {
766 modifiers |= Modifiers::CTRL;
767 }
768 modifiers
769}
770
771fn parse_sgr_mouse(buf: &[u8]) -> Option<(InputEvent, usize)> {
775 if buf.len() < 6 || !buf.starts_with(b"\x1b[<") {
777 return None;
778 }
779 let rest = &buf[3..]; let term_pos = rest.iter().position(|&b| b == b'M' || b == b'm')?;
783 let control = rest[term_pos];
784 let params_str = std::str::from_utf8(&rest[..term_pos]).ok()?;
785
786 let mut parts = params_str.splitn(3, ';');
788 let p0: i64 = parts.next()?.parse().ok()?;
789 let p1: i64 = parts.next()?.parse().ok()?;
790 let p2: i64 = parts.next()?.parse().ok()?;
791
792 let button = decode_mouse_button(control, p0)?;
793 let modifiers = decode_mouse_modifiers(p0);
794 let mouse_buttons: MouseButtons = button.into();
795
796 let consumed = 3 + term_pos + 1; Some((
799 InputEvent::Mouse(MouseEvent {
800 x: p1 as u16,
801 y: p2 as u16,
802 mouse_buttons,
803 modifiers,
804 }),
805 consumed,
806 ))
807}
808
809fn parse_osc(buf: &[u8]) -> Option<(InputEvent, usize)> {
815 if buf.get(0) != Some(&0x1b) || buf.get(1) != Some(&b']') {
817 return None;
818 }
819 let mut i = 2;
820 while i < buf.len() {
821 match buf.get(i) {
822 Some(&0x07) => {
823 let payload = buf.get(2..i).unwrap_or_default().to_vec();
825 return Some((InputEvent::OperatingSystemCommand(payload), i + 1));
826 },
827 Some(&0x1b) => {
828 if buf.get(i + 1) == Some(&b'\\') {
830 let payload = buf.get(2..i).unwrap_or_default().to_vec();
831 return Some((InputEvent::OperatingSystemCommand(payload), i + 2));
832 }
833 return None;
835 },
836 Some(_) => {
837 i += 1;
838 },
839 None => {
840 return None;
842 },
843 }
844 }
845 None }
847
848#[derive(Debug, Clone, Copy, PartialEq, Eq)]
849enum InputState {
850 Normal,
851 EscapeMaybeAlt,
852 Pasting(usize),
853}
854
855#[derive(Debug)]
856pub struct InputParser {
857 key_map: KeyMap<InputEvent>,
858 buf: ReadBuffer,
859 state: InputState,
860}
861
862#[cfg(windows)]
863mod windows {
864 use super::*;
865 use std;
866 use winapi::um::wincon::{
867 INPUT_RECORD, KEY_EVENT, KEY_EVENT_RECORD, MOUSE_EVENT, MOUSE_EVENT_RECORD,
868 WINDOW_BUFFER_SIZE_EVENT, WINDOW_BUFFER_SIZE_RECORD,
869 };
870 use winapi::um::winuser;
871
872 fn modifiers_from_ctrl_key_state(state: u32) -> Modifiers {
873 use winapi::um::wincon::*;
874
875 let mut mods = Modifiers::NONE;
876
877 if (state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0 {
878 mods |= Modifiers::ALT;
879 }
880
881 if (state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0 {
882 mods |= Modifiers::CTRL;
883 }
884
885 if (state & SHIFT_PRESSED) != 0 {
886 mods |= Modifiers::SHIFT;
887 }
888
889 mods
890 }
891
892 impl InputParser {
893 fn decode_key_record<F: FnMut(InputEvent)>(
894 &mut self,
895 event: &KEY_EVENT_RECORD,
896 callback: &mut F,
897 ) {
898 if event.bKeyDown == 0 {
899 return;
900 }
901
902 let key_code = match std::char::from_u32(*unsafe { event.uChar.UnicodeChar() } as u32) {
903 Some(unicode) if unicode > '\x00' => {
904 let mut buf = [0u8; 4];
905 self.buf
906 .extend_with(unicode.encode_utf8(&mut buf).as_bytes());
907 self.process_bytes(callback, true);
908 return;
909 },
910 _ => match event.wVirtualKeyCode as i32 {
911 winuser::VK_CANCEL => KeyCode::Cancel,
912 winuser::VK_BACK => KeyCode::Backspace,
913 winuser::VK_TAB => KeyCode::Tab,
914 winuser::VK_CLEAR => KeyCode::Clear,
915 winuser::VK_RETURN => KeyCode::Enter,
916 winuser::VK_SHIFT => KeyCode::Shift,
917 winuser::VK_CONTROL => KeyCode::Control,
918 winuser::VK_MENU => KeyCode::Menu,
919 winuser::VK_PAUSE => KeyCode::Pause,
920 winuser::VK_CAPITAL => KeyCode::CapsLock,
921 winuser::VK_ESCAPE => KeyCode::Escape,
922 winuser::VK_PRIOR => KeyCode::PageUp,
923 winuser::VK_NEXT => KeyCode::PageDown,
924 winuser::VK_END => KeyCode::End,
925 winuser::VK_HOME => KeyCode::Home,
926 winuser::VK_LEFT => KeyCode::LeftArrow,
927 winuser::VK_RIGHT => KeyCode::RightArrow,
928 winuser::VK_UP => KeyCode::UpArrow,
929 winuser::VK_DOWN => KeyCode::DownArrow,
930 winuser::VK_SELECT => KeyCode::Select,
931 winuser::VK_PRINT => KeyCode::Print,
932 winuser::VK_EXECUTE => KeyCode::Execute,
933 winuser::VK_SNAPSHOT => KeyCode::PrintScreen,
934 winuser::VK_INSERT => KeyCode::Insert,
935 winuser::VK_DELETE => KeyCode::Delete,
936 winuser::VK_HELP => KeyCode::Help,
937 winuser::VK_LWIN => KeyCode::LeftWindows,
938 winuser::VK_RWIN => KeyCode::RightWindows,
939 winuser::VK_APPS => KeyCode::Applications,
940 winuser::VK_SLEEP => KeyCode::Sleep,
941 winuser::VK_NUMPAD0 => KeyCode::Numpad0,
942 winuser::VK_NUMPAD1 => KeyCode::Numpad1,
943 winuser::VK_NUMPAD2 => KeyCode::Numpad2,
944 winuser::VK_NUMPAD3 => KeyCode::Numpad3,
945 winuser::VK_NUMPAD4 => KeyCode::Numpad4,
946 winuser::VK_NUMPAD5 => KeyCode::Numpad5,
947 winuser::VK_NUMPAD6 => KeyCode::Numpad6,
948 winuser::VK_NUMPAD7 => KeyCode::Numpad7,
949 winuser::VK_NUMPAD8 => KeyCode::Numpad8,
950 winuser::VK_NUMPAD9 => KeyCode::Numpad9,
951 winuser::VK_MULTIPLY => KeyCode::Multiply,
952 winuser::VK_ADD => KeyCode::Add,
953 winuser::VK_SEPARATOR => KeyCode::Separator,
954 winuser::VK_SUBTRACT => KeyCode::Subtract,
955 winuser::VK_DECIMAL => KeyCode::Decimal,
956 winuser::VK_DIVIDE => KeyCode::Divide,
957 winuser::VK_F1 => KeyCode::Function(1),
958 winuser::VK_F2 => KeyCode::Function(2),
959 winuser::VK_F3 => KeyCode::Function(3),
960 winuser::VK_F4 => KeyCode::Function(4),
961 winuser::VK_F5 => KeyCode::Function(5),
962 winuser::VK_F6 => KeyCode::Function(6),
963 winuser::VK_F7 => KeyCode::Function(7),
964 winuser::VK_F8 => KeyCode::Function(8),
965 winuser::VK_F9 => KeyCode::Function(9),
966 winuser::VK_F10 => KeyCode::Function(10),
967 winuser::VK_F11 => KeyCode::Function(11),
968 winuser::VK_F12 => KeyCode::Function(12),
969 winuser::VK_F13 => KeyCode::Function(13),
970 winuser::VK_F14 => KeyCode::Function(14),
971 winuser::VK_F15 => KeyCode::Function(15),
972 winuser::VK_F16 => KeyCode::Function(16),
973 winuser::VK_F17 => KeyCode::Function(17),
974 winuser::VK_F18 => KeyCode::Function(18),
975 winuser::VK_F19 => KeyCode::Function(19),
976 winuser::VK_F20 => KeyCode::Function(20),
977 winuser::VK_F21 => KeyCode::Function(21),
978 winuser::VK_F22 => KeyCode::Function(22),
979 winuser::VK_F23 => KeyCode::Function(23),
980 winuser::VK_F24 => KeyCode::Function(24),
981 winuser::VK_NUMLOCK => KeyCode::NumLock,
982 winuser::VK_SCROLL => KeyCode::ScrollLock,
983 winuser::VK_LSHIFT => KeyCode::LeftShift,
984 winuser::VK_RSHIFT => KeyCode::RightShift,
985 winuser::VK_LCONTROL => KeyCode::LeftControl,
986 winuser::VK_RCONTROL => KeyCode::RightControl,
987 winuser::VK_LMENU => KeyCode::LeftMenu,
988 winuser::VK_RMENU => KeyCode::RightMenu,
989 winuser::VK_BROWSER_BACK => KeyCode::BrowserBack,
990 winuser::VK_BROWSER_FORWARD => KeyCode::BrowserForward,
991 winuser::VK_BROWSER_REFRESH => KeyCode::BrowserRefresh,
992 winuser::VK_BROWSER_STOP => KeyCode::BrowserStop,
993 winuser::VK_BROWSER_SEARCH => KeyCode::BrowserSearch,
994 winuser::VK_BROWSER_FAVORITES => KeyCode::BrowserFavorites,
995 winuser::VK_BROWSER_HOME => KeyCode::BrowserHome,
996 winuser::VK_VOLUME_MUTE => KeyCode::VolumeMute,
997 winuser::VK_VOLUME_DOWN => KeyCode::VolumeDown,
998 winuser::VK_VOLUME_UP => KeyCode::VolumeUp,
999 winuser::VK_MEDIA_NEXT_TRACK => KeyCode::MediaNextTrack,
1000 winuser::VK_MEDIA_PREV_TRACK => KeyCode::MediaPrevTrack,
1001 winuser::VK_MEDIA_STOP => KeyCode::MediaStop,
1002 winuser::VK_MEDIA_PLAY_PAUSE => KeyCode::MediaPlayPause,
1003 _ => return,
1004 },
1005 };
1006 let mut modifiers = modifiers_from_ctrl_key_state(event.dwControlKeyState);
1007
1008 let key_code = key_code.normalize_shift_to_upper_case(modifiers);
1009 if let KeyCode::Char(c) = key_code {
1010 if c.is_ascii_uppercase() {
1011 modifiers.remove(Modifiers::SHIFT);
1012 }
1013 }
1014
1015 let input_event = InputEvent::Key(KeyEvent {
1016 key: key_code,
1017 modifiers,
1018 });
1019 for _ in 0..event.wRepeatCount {
1020 callback(input_event.clone());
1021 }
1022 }
1023
1024 fn decode_mouse_record<F: FnMut(InputEvent)>(
1025 &self,
1026 event: &MOUSE_EVENT_RECORD,
1027 callback: &mut F,
1028 ) {
1029 use winapi::um::wincon::*;
1030 let mut buttons = MouseButtons::NONE;
1031
1032 if (event.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) != 0 {
1033 buttons |= MouseButtons::LEFT;
1034 }
1035 if (event.dwButtonState & RIGHTMOST_BUTTON_PRESSED) != 0 {
1036 buttons |= MouseButtons::RIGHT;
1037 }
1038 if (event.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) != 0 {
1039 buttons |= MouseButtons::MIDDLE;
1040 }
1041
1042 let modifiers = modifiers_from_ctrl_key_state(event.dwControlKeyState);
1043
1044 if (event.dwEventFlags & MOUSE_WHEELED) != 0 {
1045 buttons |= MouseButtons::VERT_WHEEL;
1046 if (event.dwButtonState >> 8) != 0 {
1047 buttons |= MouseButtons::WHEEL_POSITIVE;
1048 }
1049 } else if (event.dwEventFlags & MOUSE_HWHEELED) != 0 {
1050 buttons |= MouseButtons::HORZ_WHEEL;
1051 if (event.dwButtonState >> 8) != 0 {
1052 buttons |= MouseButtons::WHEEL_POSITIVE;
1053 }
1054 }
1055
1056 let mouse = InputEvent::Mouse(MouseEvent {
1057 x: event.dwMousePosition.X as u16,
1058 y: event.dwMousePosition.Y as u16,
1059 mouse_buttons: buttons,
1060 modifiers,
1061 });
1062
1063 if (event.dwEventFlags & DOUBLE_CLICK) != 0 {
1064 callback(mouse.clone());
1065 }
1066 callback(mouse);
1067 }
1068
1069 fn decode_resize_record<F: FnMut(InputEvent)>(
1070 &self,
1071 event: &WINDOW_BUFFER_SIZE_RECORD,
1072 callback: &mut F,
1073 ) {
1074 callback(InputEvent::Resized {
1075 rows: event.dwSize.Y as usize,
1076 cols: event.dwSize.X as usize,
1077 });
1078 }
1079
1080 pub fn decode_input_records<F: FnMut(InputEvent)>(
1081 &mut self,
1082 records: &[INPUT_RECORD],
1083 callback: &mut F,
1084 ) {
1085 for record in records {
1086 match record.EventType {
1087 KEY_EVENT => {
1088 self.decode_key_record(unsafe { record.Event.KeyEvent() }, callback)
1089 },
1090 MOUSE_EVENT => {
1091 self.decode_mouse_record(unsafe { record.Event.MouseEvent() }, callback)
1092 },
1093 WINDOW_BUFFER_SIZE_EVENT => self.decode_resize_record(
1094 unsafe { record.Event.WindowBufferSizeEvent() },
1095 callback,
1096 ),
1097 _ => {},
1098 }
1099 }
1100 self.process_bytes(callback, false);
1101 }
1102 }
1103}
1104
1105impl Default for InputParser {
1106 fn default() -> Self {
1107 Self::new()
1108 }
1109}
1110
1111impl InputParser {
1112 pub fn new() -> Self {
1113 Self {
1114 key_map: Self::build_basic_key_map(),
1115 buf: ReadBuffer::new(),
1116 state: InputState::Normal,
1117 }
1118 }
1119
1120 fn build_basic_key_map() -> KeyMap<InputEvent> {
1121 let mut map = KeyMap::new();
1122
1123 let modifier_combos = &[
1124 ("", Modifiers::NONE),
1125 (";1", Modifiers::NONE),
1126 (";2", Modifiers::SHIFT),
1127 (";3", Modifiers::ALT),
1128 (";4", Modifiers::ALT | Modifiers::SHIFT),
1129 (";5", Modifiers::CTRL),
1130 (";6", Modifiers::CTRL | Modifiers::SHIFT),
1131 (";7", Modifiers::CTRL | Modifiers::ALT),
1132 (";8", Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT),
1133 ];
1134 let meta = Modifiers::ALT;
1135 let meta_modifier_combos = &[
1136 (";9", meta),
1137 (";10", meta | Modifiers::SHIFT),
1138 (";11", meta | Modifiers::ALT),
1139 (";12", meta | Modifiers::ALT | Modifiers::SHIFT),
1140 (";13", meta | Modifiers::CTRL),
1141 (";14", meta | Modifiers::CTRL | Modifiers::SHIFT),
1142 (";15", meta | Modifiers::CTRL | Modifiers::ALT),
1143 (
1144 ";16",
1145 meta | Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
1146 ),
1147 ];
1148
1149 let modifier_combos_including_meta =
1150 || modifier_combos.iter().chain(meta_modifier_combos.iter());
1151
1152 for alpha in b'A'..=b'Z' {
1153 let ctrl = [alpha & 0x1f];
1155 map.insert(
1156 &ctrl,
1157 InputEvent::Key(KeyEvent {
1158 key: KeyCode::Char((alpha as char).to_ascii_lowercase()),
1159 modifiers: Modifiers::CTRL,
1160 }),
1161 );
1162
1163 let alt = [0x1b, alpha];
1165 map.insert(
1166 &alt,
1167 InputEvent::Key(KeyEvent {
1168 key: KeyCode::Char(alpha as char),
1169 modifiers: Modifiers::ALT,
1170 }),
1171 );
1172 }
1173
1174 for c in 0..=0x7fu8 {
1175 for (suffix, modifiers) in modifier_combos {
1176 let key = format!("\x1b[{}{}u", c, suffix);
1179 map.insert(
1180 key,
1181 InputEvent::Key(KeyEvent {
1182 key: KeyCode::Char(c as char),
1183 modifiers: *modifiers,
1184 }),
1185 );
1186
1187 if !suffix.is_empty() {
1188 let key = format!("\x1b[27{};{}~", suffix, c);
1190 map.insert(
1191 key,
1192 InputEvent::Key(KeyEvent {
1193 key: match c {
1194 8 | 0x7f => KeyCode::Backspace,
1195 0x1b => KeyCode::Escape,
1196 9 => KeyCode::Tab,
1197 10 | 13 => KeyCode::Enter,
1198 _ => KeyCode::Char(c as char),
1199 },
1200 modifiers: *modifiers,
1201 }),
1202 );
1203 }
1204 }
1205 }
1206
1207 for (keycode, dir) in &[
1209 (KeyCode::UpArrow, b'A'),
1210 (KeyCode::DownArrow, b'B'),
1211 (KeyCode::RightArrow, b'C'),
1212 (KeyCode::LeftArrow, b'D'),
1213 (KeyCode::Home, b'H'),
1214 (KeyCode::End, b'F'),
1215 ] {
1216 let arrow = [0x1b, b'[', *dir];
1218 map.insert(
1219 &arrow,
1220 InputEvent::Key(KeyEvent {
1221 key: *keycode,
1222 modifiers: Modifiers::NONE,
1223 }),
1224 );
1225 for (suffix, modifiers) in modifier_combos_including_meta() {
1226 let key = format!("\x1b[1{}{}", suffix, *dir as char);
1227 map.insert(
1228 key,
1229 InputEvent::Key(KeyEvent {
1230 key: *keycode,
1231 modifiers: *modifiers,
1232 }),
1233 );
1234 }
1235 }
1236 for &(keycode, dir) in &[
1237 (KeyCode::UpArrow, b'a'),
1238 (KeyCode::DownArrow, b'b'),
1239 (KeyCode::RightArrow, b'c'),
1240 (KeyCode::LeftArrow, b'd'),
1241 ] {
1242 for &(seq, mods) in &[
1244 ([0x1b, b'[', dir], Modifiers::SHIFT),
1245 ([0x1b, b'O', dir], Modifiers::CTRL),
1246 ] {
1247 map.insert(
1248 &seq,
1249 InputEvent::Key(KeyEvent {
1250 key: keycode,
1251 modifiers: mods,
1252 }),
1253 );
1254 }
1255 }
1256
1257 for (keycode, dir) in &[
1258 (KeyCode::ApplicationUpArrow, b'A'),
1259 (KeyCode::ApplicationDownArrow, b'B'),
1260 (KeyCode::ApplicationRightArrow, b'C'),
1261 (KeyCode::ApplicationLeftArrow, b'D'),
1262 ] {
1263 let app = [0x1b, b'O', *dir];
1265 map.insert(
1266 &app,
1267 InputEvent::Key(KeyEvent {
1268 key: *keycode,
1269 modifiers: Modifiers::NONE,
1270 }),
1271 );
1272 for (suffix, modifiers) in modifier_combos {
1273 let key = format!("\x1bO1{}{}", suffix, *dir as char);
1274 map.insert(
1275 key,
1276 InputEvent::Key(KeyEvent {
1277 key: *keycode,
1278 modifiers: *modifiers,
1279 }),
1280 );
1281 }
1282 }
1283
1284 for (keycode, c) in &[
1286 (KeyCode::Function(1), b'P'),
1287 (KeyCode::Function(2), b'Q'),
1288 (KeyCode::Function(3), b'R'),
1289 (KeyCode::Function(4), b'S'),
1290 ] {
1291 let key = [0x1b, b'O', *c];
1292 map.insert(
1293 &key,
1294 InputEvent::Key(KeyEvent {
1295 key: *keycode,
1296 modifiers: Modifiers::NONE,
1297 }),
1298 );
1299 }
1300
1301 for (keycode, c) in &[
1303 (KeyCode::Function(1), b'P'),
1304 (KeyCode::Function(2), b'Q'),
1305 (KeyCode::Function(3), b'R'),
1306 (KeyCode::Function(4), b'S'),
1307 ] {
1308 for (suffix, modifiers) in modifier_combos_including_meta() {
1309 let key = format!("\x1b[1{suffix}{code}", code = *c as char, suffix = suffix);
1310 map.insert(
1311 key,
1312 InputEvent::Key(KeyEvent {
1313 key: *keycode,
1314 modifiers: *modifiers,
1315 }),
1316 );
1317 }
1318 }
1319
1320 for (range, offset) in &[
1323 (1..=5, 10),
1325 (6..=10, 11),
1327 (11..=14, 12),
1329 (15..=16, 13),
1331 (17..=20, 14),
1333 ] {
1334 for n in range.clone() {
1335 for (suffix, modifiers) in modifier_combos_including_meta() {
1336 let key = format!("\x1b[{code}{suffix}~", code = n + offset, suffix = suffix);
1337 map.insert(
1338 key,
1339 InputEvent::Key(KeyEvent {
1340 key: KeyCode::Function(n),
1341 modifiers: *modifiers,
1342 }),
1343 );
1344 }
1345 }
1346 }
1347
1348 for (keycode, c) in &[
1349 (KeyCode::Insert, b'2'),
1350 (KeyCode::Delete, b'3'),
1351 (KeyCode::Home, b'1'),
1352 (KeyCode::End, b'4'),
1353 (KeyCode::PageUp, b'5'),
1354 (KeyCode::PageDown, b'6'),
1355 (KeyCode::Home, b'7'),
1357 (KeyCode::End, b'8'),
1358 ] {
1359 for (suffix, modifiers) in &[
1360 (b'~', Modifiers::NONE),
1361 (b'$', Modifiers::SHIFT),
1362 (b'^', Modifiers::CTRL),
1363 (b'@', Modifiers::SHIFT | Modifiers::CTRL),
1364 ] {
1365 let key = [0x1b, b'[', *c, *suffix];
1366 map.insert(
1367 key,
1368 InputEvent::Key(KeyEvent {
1369 key: *keycode,
1370 modifiers: *modifiers,
1371 }),
1372 );
1373 }
1374 }
1375
1376 map.insert(
1377 &[0x7f],
1378 InputEvent::Key(KeyEvent {
1379 key: KeyCode::Backspace,
1380 modifiers: Modifiers::NONE,
1381 }),
1382 );
1383
1384 map.insert(
1385 &[0x8],
1386 InputEvent::Key(KeyEvent {
1387 key: KeyCode::Backspace,
1388 modifiers: Modifiers::NONE,
1389 }),
1390 );
1391
1392 map.insert(
1393 &[0x1b],
1394 InputEvent::Key(KeyEvent {
1395 key: KeyCode::Escape,
1396 modifiers: Modifiers::NONE,
1397 }),
1398 );
1399
1400 map.insert(
1401 &[b'\t'],
1402 InputEvent::Key(KeyEvent {
1403 key: KeyCode::Tab,
1404 modifiers: Modifiers::NONE,
1405 }),
1406 );
1407 map.insert(
1408 b"\x1b[Z",
1409 InputEvent::Key(KeyEvent {
1410 key: KeyCode::Tab,
1411 modifiers: Modifiers::SHIFT,
1412 }),
1413 );
1414
1415 map.insert(
1416 &[b'\r'],
1417 InputEvent::Key(KeyEvent {
1418 key: KeyCode::Enter,
1419 modifiers: Modifiers::NONE,
1420 }),
1421 );
1422 map.insert(
1423 &[b'\n'],
1424 InputEvent::Key(KeyEvent {
1425 key: KeyCode::Enter,
1426 modifiers: Modifiers::NONE,
1427 }),
1428 );
1429
1430 map.insert(
1431 b"\x1b[200~",
1432 InputEvent::Key(KeyEvent {
1433 key: KeyCode::InternalPasteStart,
1434 modifiers: Modifiers::NONE,
1435 }),
1436 );
1437 map.insert(
1438 b"\x1b[201~",
1439 InputEvent::Key(KeyEvent {
1440 key: KeyCode::InternalPasteEnd,
1441 modifiers: Modifiers::NONE,
1442 }),
1443 );
1444 map.insert(
1445 b"\x1b[",
1446 InputEvent::Key(KeyEvent {
1447 key: KeyCode::Char('['),
1448 modifiers: Modifiers::ALT,
1449 }),
1450 );
1451
1452 map
1453 }
1454
1455 fn first_char_and_len(s: &str) -> (char, usize) {
1458 let mut iter = s.chars();
1459 let c = iter.next().unwrap();
1460 (c, c.len_utf8())
1461 }
1462
1463 fn decode_one_char(bytes: &[u8]) -> Option<(char, usize)> {
1466 let bytes = &bytes[..bytes.len().min(4)];
1467 match std::str::from_utf8(bytes) {
1468 Ok(s) => {
1469 let (c, len) = Self::first_char_and_len(s);
1470 Some((c, len))
1471 },
1472 Err(err) => {
1473 let (valid, _after_valid) = bytes.split_at(err.valid_up_to());
1474 if !valid.is_empty() {
1475 let s = unsafe { std::str::from_utf8_unchecked(valid) };
1476 let (c, len) = Self::first_char_and_len(s);
1477 Some((c, len))
1478 } else {
1479 None
1480 }
1481 },
1482 }
1483 }
1484
1485 fn dispatch_callback<F: FnMut(InputEvent)>(&mut self, mut callback: F, event: InputEvent) {
1486 match (self.state, &event) {
1487 (
1488 InputState::Normal,
1489 InputEvent::Key(KeyEvent {
1490 key: KeyCode::InternalPasteStart,
1491 ..
1492 }),
1493 ) => {
1494 self.state = InputState::Pasting(0);
1495 },
1496 (
1497 InputState::EscapeMaybeAlt,
1498 InputEvent::Key(KeyEvent {
1499 key: KeyCode::InternalPasteStart,
1500 ..
1501 }),
1502 ) => {
1503 callback(InputEvent::Key(KeyEvent {
1506 key: KeyCode::Escape,
1507 modifiers: Modifiers::NONE,
1508 }));
1509 self.state = InputState::Pasting(0);
1510 },
1511 (InputState::EscapeMaybeAlt, InputEvent::Key(KeyEvent { key, modifiers })) => {
1512 let key = *key;
1514 let modifiers = *modifiers;
1515 self.state = InputState::Normal;
1516 callback(InputEvent::Key(KeyEvent {
1517 key,
1518 modifiers: modifiers | Modifiers::ALT,
1519 }));
1520 },
1521 (InputState::EscapeMaybeAlt, _) => {
1522 callback(InputEvent::Key(KeyEvent {
1525 key: KeyCode::Escape,
1526 modifiers: Modifiers::NONE,
1527 }));
1528 callback(event);
1529 },
1530 (_, _) => callback(event),
1531 }
1532 }
1533
1534 fn process_bytes<F: FnMut(InputEvent)>(&mut self, mut callback: F, maybe_more: bool) {
1535 while !self.buf.is_empty() {
1536 match self.state {
1537 InputState::Pasting(offset) => {
1538 let end_paste = b"\x1b[201~";
1539 if let Some(idx) = self.buf.find_subsequence(offset, end_paste) {
1540 let pasted =
1541 String::from_utf8_lossy(&self.buf.as_slice()[0..idx]).to_string();
1542 self.buf.advance(pasted.len() + end_paste.len());
1543 callback(InputEvent::Paste(pasted));
1544 self.state = InputState::Normal;
1545 } else {
1546 self.state =
1547 InputState::Pasting(self.buf.len().saturating_sub(end_paste.len()));
1548 return;
1549 }
1550 },
1551 InputState::EscapeMaybeAlt | InputState::Normal => {
1552 if self.state == InputState::Normal
1553 && self.buf.as_slice().get(0) == Some(&b'\x1b')
1554 {
1555 if let Some((event, len)) = parse_sgr_mouse(self.buf.as_slice()) {
1556 self.buf.advance(len);
1557 callback(event);
1558 continue;
1559 }
1560
1561 if let Some((event, len)) = parse_osc(self.buf.as_slice()) {
1563 self.buf.advance(len);
1564 callback(event);
1565 continue;
1566 }
1567
1568 if maybe_more && self.buf.as_slice().starts_with(b"\x1b]") {
1570 return;
1571 }
1572
1573 if maybe_more && self.buf.as_slice().starts_with(b"\x1b[<") {
1574 return;
1575 }
1576 }
1577
1578 match (
1579 self.key_map.lookup(self.buf.as_slice(), maybe_more),
1580 maybe_more,
1581 ) {
1582 (
1588 Found::Exact(
1589 len,
1590 InputEvent::Key(KeyEvent {
1591 key: KeyCode::Escape,
1592 modifiers: Modifiers::NONE,
1593 }),
1594 ),
1595 _,
1596 ) if self.state == InputState::Normal && self.buf.len() > len => {
1597 self.state = InputState::EscapeMaybeAlt;
1598 self.buf.advance(len);
1599 },
1600 (Found::Exact(len, event), _) | (Found::Ambiguous(len, event), false) => {
1601 self.dispatch_callback(&mut callback, event.clone());
1602 self.buf.advance(len);
1603 },
1604 (Found::Ambiguous(_, _), true) | (Found::NeedData, true) => {
1605 return;
1606 },
1607 (Found::None, _) | (Found::NeedData, false) => {
1608 if let Some((c, len)) = Self::decode_one_char(self.buf.as_slice()) {
1610 self.buf.advance(len);
1611 self.dispatch_callback(
1612 &mut callback,
1613 InputEvent::Key(KeyEvent {
1614 key: KeyCode::Char(c),
1615 modifiers: Modifiers::NONE,
1616 }),
1617 );
1618 } else {
1619 return;
1622 }
1623 },
1624 }
1625 },
1626 }
1627 }
1628 }
1629
1630 pub fn parse<F: FnMut(InputEvent)>(&mut self, bytes: &[u8], callback: F, maybe_more: bool) {
1645 self.buf.extend_with(bytes);
1646 self.process_bytes(callback, maybe_more);
1647 }
1648
1649 pub fn parse_as_vec(&mut self, bytes: &[u8], maybe_more: bool) -> Vec<InputEvent> {
1650 let mut result = Vec::new();
1651 self.parse(bytes, |event| result.push(event), maybe_more);
1652 result
1653 }
1654
1655 #[cfg(windows)]
1656 pub fn decode_input_records_as_vec(
1657 &mut self,
1658 records: &[winapi::um::wincon::INPUT_RECORD],
1659 ) -> Vec<InputEvent> {
1660 let mut result = Vec::new();
1661 self.decode_input_records(records, &mut |event| result.push(event));
1662 result
1663 }
1664}
1665
1666#[cfg(test)]
1667mod test {
1668 use super::*;
1669
1670 const NO_MORE: bool = false;
1671 const MAYBE_MORE: bool = true;
1672
1673 #[test]
1674 fn simple() {
1675 let mut p = InputParser::new();
1676 let inputs = p.parse_as_vec(b"hello", NO_MORE);
1677 assert_eq!(
1678 vec![
1679 InputEvent::Key(KeyEvent {
1680 modifiers: Modifiers::NONE,
1681 key: KeyCode::Char('h'),
1682 }),
1683 InputEvent::Key(KeyEvent {
1684 modifiers: Modifiers::NONE,
1685 key: KeyCode::Char('e'),
1686 }),
1687 InputEvent::Key(KeyEvent {
1688 modifiers: Modifiers::NONE,
1689 key: KeyCode::Char('l'),
1690 }),
1691 InputEvent::Key(KeyEvent {
1692 modifiers: Modifiers::NONE,
1693 key: KeyCode::Char('l'),
1694 }),
1695 InputEvent::Key(KeyEvent {
1696 modifiers: Modifiers::NONE,
1697 key: KeyCode::Char('o'),
1698 }),
1699 ],
1700 inputs
1701 );
1702 }
1703
1704 #[test]
1705 fn control_characters() {
1706 let mut p = InputParser::new();
1707 let inputs = p.parse_as_vec(b"\x03\x1bJ\x7f", NO_MORE);
1708 assert_eq!(
1709 vec![
1710 InputEvent::Key(KeyEvent {
1711 modifiers: Modifiers::CTRL,
1712 key: KeyCode::Char('c'),
1713 }),
1714 InputEvent::Key(KeyEvent {
1715 modifiers: Modifiers::ALT,
1716 key: KeyCode::Char('J'),
1717 }),
1718 InputEvent::Key(KeyEvent {
1719 modifiers: Modifiers::NONE,
1720 key: KeyCode::Backspace,
1721 }),
1722 ],
1723 inputs
1724 );
1725 }
1726
1727 #[test]
1728 fn arrow_keys() {
1729 let mut p = InputParser::new();
1730 let inputs = p.parse_as_vec(b"\x1bOA\x1bOB\x1bOC\x1bOD", NO_MORE);
1731 assert_eq!(
1732 vec![
1733 InputEvent::Key(KeyEvent {
1734 modifiers: Modifiers::NONE,
1735 key: KeyCode::ApplicationUpArrow,
1736 }),
1737 InputEvent::Key(KeyEvent {
1738 modifiers: Modifiers::NONE,
1739 key: KeyCode::ApplicationDownArrow,
1740 }),
1741 InputEvent::Key(KeyEvent {
1742 modifiers: Modifiers::NONE,
1743 key: KeyCode::ApplicationRightArrow,
1744 }),
1745 InputEvent::Key(KeyEvent {
1746 modifiers: Modifiers::NONE,
1747 key: KeyCode::ApplicationLeftArrow,
1748 }),
1749 ],
1750 inputs
1751 );
1752 }
1753
1754 #[test]
1755 fn partial() {
1756 let mut p = InputParser::new();
1757 let mut inputs = Vec::new();
1758 p.parse(b"\x1b[11", |evt| inputs.push(evt), true);
1760 p.parse(b"~", |evt| inputs.push(evt), true);
1761 assert_eq!(
1763 vec![InputEvent::Key(KeyEvent {
1764 modifiers: Modifiers::NONE,
1765 key: KeyCode::Function(1),
1766 })],
1767 inputs
1768 );
1769 }
1770
1771 #[test]
1772 fn partial_ambig() {
1773 let mut p = InputParser::new();
1774
1775 assert_eq!(
1776 vec![InputEvent::Key(KeyEvent {
1777 key: KeyCode::Escape,
1778 modifiers: Modifiers::NONE,
1779 })],
1780 p.parse_as_vec(b"\x1b", false)
1781 );
1782
1783 let mut inputs = Vec::new();
1784 p.parse(b"\x1b[11", |evt| inputs.push(evt), MAYBE_MORE);
1786 p.parse(b"", |evt| inputs.push(evt), NO_MORE);
1787 assert_eq!(
1790 vec![
1791 InputEvent::Key(KeyEvent {
1792 modifiers: Modifiers::ALT,
1793 key: KeyCode::Char('['),
1794 }),
1795 InputEvent::Key(KeyEvent {
1796 modifiers: Modifiers::NONE,
1797 key: KeyCode::Char('1'),
1798 }),
1799 InputEvent::Key(KeyEvent {
1800 modifiers: Modifiers::NONE,
1801 key: KeyCode::Char('1'),
1802 }),
1803 ],
1804 inputs
1805 );
1806 }
1807
1808 #[test]
1809 fn partial_mouse() {
1810 let mut p = InputParser::new();
1811 let mut inputs = Vec::new();
1812 p.parse(b"\x1b[<0;0;0", |evt| inputs.push(evt), true);
1814 p.parse(b"M", |evt| inputs.push(evt), true);
1815 assert_eq!(
1817 vec![InputEvent::Mouse(MouseEvent {
1818 x: 0,
1819 y: 0,
1820 mouse_buttons: MouseButtons::LEFT,
1821 modifiers: Modifiers::NONE,
1822 })],
1823 inputs
1824 );
1825 }
1826
1827 #[test]
1828 fn partial_mouse_ambig() {
1829 let mut p = InputParser::new();
1830 let mut inputs = Vec::new();
1831 p.parse(b"\x1b[<", |evt| inputs.push(evt), MAYBE_MORE);
1833 p.parse(b"0;0;0", |evt| inputs.push(evt), NO_MORE);
1834 assert_eq!(
1837 vec![
1838 InputEvent::Key(KeyEvent {
1839 modifiers: Modifiers::ALT,
1840 key: KeyCode::Char('['),
1841 }),
1842 InputEvent::Key(KeyEvent {
1843 modifiers: Modifiers::NONE,
1844 key: KeyCode::Char('<'),
1845 }),
1846 InputEvent::Key(KeyEvent {
1847 modifiers: Modifiers::NONE,
1848 key: KeyCode::Char('0'),
1849 }),
1850 InputEvent::Key(KeyEvent {
1851 modifiers: Modifiers::NONE,
1852 key: KeyCode::Char(';'),
1853 }),
1854 InputEvent::Key(KeyEvent {
1855 modifiers: Modifiers::NONE,
1856 key: KeyCode::Char('0'),
1857 }),
1858 InputEvent::Key(KeyEvent {
1859 modifiers: Modifiers::NONE,
1860 key: KeyCode::Char(';'),
1861 }),
1862 InputEvent::Key(KeyEvent {
1863 modifiers: Modifiers::NONE,
1864 key: KeyCode::Char('0'),
1865 }),
1866 ],
1867 inputs
1868 );
1869 }
1870
1871 #[test]
1872 fn alt_left_bracket() {
1873 let mut p = InputParser::new();
1876
1877 let mut inputs = Vec::new();
1878 p.parse(b"\x1b[", |evt| inputs.push(evt), false);
1879
1880 assert_eq!(
1881 vec![InputEvent::Key(KeyEvent {
1882 modifiers: Modifiers::ALT,
1883 key: KeyCode::Char('['),
1884 }),],
1885 inputs
1886 );
1887 }
1888
1889 #[test]
1890 fn modify_other_keys_parse() {
1891 let mut p = InputParser::new();
1892 let inputs = p.parse_as_vec(
1893 b"\x1b[27;5;13~\x1b[27;5;9~\x1b[27;6;8~\x1b[27;2;127~\x1b[27;6;27~",
1894 NO_MORE,
1895 );
1896 assert_eq!(
1897 vec![
1898 InputEvent::Key(KeyEvent {
1899 key: KeyCode::Enter,
1900 modifiers: Modifiers::CTRL,
1901 }),
1902 InputEvent::Key(KeyEvent {
1903 key: KeyCode::Tab,
1904 modifiers: Modifiers::CTRL,
1905 }),
1906 InputEvent::Key(KeyEvent {
1907 key: KeyCode::Backspace,
1908 modifiers: Modifiers::CTRL | Modifiers::SHIFT,
1909 }),
1910 InputEvent::Key(KeyEvent {
1911 key: KeyCode::Backspace,
1912 modifiers: Modifiers::SHIFT,
1913 }),
1914 InputEvent::Key(KeyEvent {
1915 key: KeyCode::Escape,
1916 modifiers: Modifiers::CTRL | Modifiers::SHIFT,
1917 }),
1918 ],
1919 inputs
1920 );
1921 }
1922
1923 #[test]
1924 fn modify_other_keys_encode() {
1925 let mode = KeyCodeEncodeModes {
1926 encoding: KeyboardEncoding::Xterm,
1927 newline_mode: false,
1928 application_cursor_keys: false,
1929 modify_other_keys: None,
1930 };
1931 let mode_1 = KeyCodeEncodeModes {
1932 encoding: KeyboardEncoding::Xterm,
1933 newline_mode: false,
1934 application_cursor_keys: false,
1935 modify_other_keys: Some(1),
1936 };
1937 let mode_2 = KeyCodeEncodeModes {
1938 encoding: KeyboardEncoding::Xterm,
1939 newline_mode: false,
1940 application_cursor_keys: false,
1941 modify_other_keys: Some(2),
1942 };
1943
1944 assert_eq!(
1945 KeyCode::Enter.encode(Modifiers::CTRL, mode, true).unwrap(),
1946 "\r".to_string()
1947 );
1948 assert_eq!(
1949 KeyCode::Enter
1950 .encode(Modifiers::CTRL, mode_1, true)
1951 .unwrap(),
1952 "\x1b[27;5;13~".to_string()
1953 );
1954 assert_eq!(
1955 KeyCode::Enter
1956 .encode(Modifiers::CTRL | Modifiers::SHIFT, mode_1, true)
1957 .unwrap(),
1958 "\x1b[27;6;13~".to_string()
1959 );
1960
1961 assert_eq!(
1965 KeyCode::Tab.encode(Modifiers::CTRL, mode, true).unwrap(),
1966 "\x1b[9;5u".to_string()
1967 );
1968 assert_eq!(
1969 KeyCode::Tab.encode(Modifiers::CTRL, mode_1, true).unwrap(),
1970 "\x1b[27;5;9~".to_string()
1971 );
1972 assert_eq!(
1973 KeyCode::Tab
1974 .encode(Modifiers::CTRL | Modifiers::SHIFT, mode_1, true)
1975 .unwrap(),
1976 "\x1b[27;6;9~".to_string()
1977 );
1978
1979 assert_eq!(
1980 KeyCode::Char('c')
1981 .encode(Modifiers::CTRL, mode, true)
1982 .unwrap(),
1983 "\x03".to_string()
1984 );
1985 assert_eq!(
1986 KeyCode::Char('c')
1987 .encode(Modifiers::CTRL, mode_1, true)
1988 .unwrap(),
1989 "\x03".to_string()
1990 );
1991 assert_eq!(
1992 KeyCode::Char('c')
1993 .encode(Modifiers::CTRL, mode_2, true)
1994 .unwrap(),
1995 "\x1b[27;5;99~".to_string()
1996 );
1997
1998 assert_eq!(
1999 KeyCode::Char('1')
2000 .encode(Modifiers::CTRL, mode, true)
2001 .unwrap(),
2002 "1".to_string()
2003 );
2004 assert_eq!(
2005 KeyCode::Char('1')
2006 .encode(Modifiers::CTRL, mode_2, true)
2007 .unwrap(),
2008 "\x1b[27;5;49~".to_string()
2009 );
2010
2011 assert_eq!(
2012 KeyCode::Char(',')
2013 .encode(Modifiers::CTRL, mode, true)
2014 .unwrap(),
2015 ",".to_string()
2016 );
2017 assert_eq!(
2018 KeyCode::Char(',')
2019 .encode(Modifiers::CTRL, mode_2, true)
2020 .unwrap(),
2021 "\x1b[27;5;44~".to_string()
2022 );
2023 }
2024
2025 #[test]
2026 fn encode_issue_892() {
2027 let mode = KeyCodeEncodeModes {
2028 encoding: KeyboardEncoding::Xterm,
2029 newline_mode: false,
2030 application_cursor_keys: false,
2031 modify_other_keys: None,
2032 };
2033
2034 assert_eq!(
2035 KeyCode::LeftArrow
2036 .encode(Modifiers::NONE, mode, true)
2037 .unwrap(),
2038 "\x1b[D".to_string()
2039 );
2040 assert_eq!(
2041 KeyCode::LeftArrow
2042 .encode(Modifiers::ALT, mode, true)
2043 .unwrap(),
2044 "\x1b[1;3D".to_string()
2045 );
2046 assert_eq!(
2047 KeyCode::Home.encode(Modifiers::NONE, mode, true).unwrap(),
2048 "\x1b[H".to_string()
2049 );
2050 assert_eq!(
2051 KeyCode::Home.encode(Modifiers::ALT, mode, true).unwrap(),
2052 "\x1b[1;3H".to_string()
2053 );
2054 assert_eq!(
2055 KeyCode::End.encode(Modifiers::NONE, mode, true).unwrap(),
2056 "\x1b[F".to_string()
2057 );
2058 assert_eq!(
2059 KeyCode::End.encode(Modifiers::ALT, mode, true).unwrap(),
2060 "\x1b[1;3F".to_string()
2061 );
2062 assert_eq!(
2063 KeyCode::Tab.encode(Modifiers::ALT, mode, true).unwrap(),
2064 "\x1b\t".to_string()
2065 );
2066 assert_eq!(
2067 KeyCode::PageUp.encode(Modifiers::ALT, mode, true).unwrap(),
2068 "\x1b[5;3~".to_string()
2069 );
2070 assert_eq!(
2071 KeyCode::Function(1)
2072 .encode(Modifiers::NONE, mode, true)
2073 .unwrap(),
2074 "\x1bOP".to_string()
2075 );
2076 }
2077
2078 #[test]
2079 fn partial_bracketed_paste() {
2080 let mut p = InputParser::new();
2081
2082 let input = b"\x1b[200~1234";
2083 let input2 = b"5678\x1b[201~";
2084
2085 let mut inputs = vec![];
2086
2087 p.parse(input, |e| inputs.push(e), false);
2088 p.parse(input2, |e| inputs.push(e), false);
2089
2090 assert_eq!(vec![InputEvent::Paste("12345678".to_owned())], inputs)
2091 }
2092
2093 #[test]
2094 fn mouse_horizontal_scroll() {
2095 let mut p = InputParser::new();
2096
2097 let input = b"\x1b[<66;42;12M\x1b[<67;42;12M";
2098 let res = p.parse_as_vec(input, MAYBE_MORE);
2099
2100 assert_eq!(
2101 vec![
2102 InputEvent::Mouse(MouseEvent {
2103 x: 42,
2104 y: 12,
2105 mouse_buttons: MouseButtons::HORZ_WHEEL | MouseButtons::WHEEL_POSITIVE,
2106 modifiers: Modifiers::NONE,
2107 }),
2108 InputEvent::Mouse(MouseEvent {
2109 x: 42,
2110 y: 12,
2111 mouse_buttons: MouseButtons::HORZ_WHEEL,
2112 modifiers: Modifiers::NONE,
2113 })
2114 ],
2115 res
2116 );
2117 }
2118
2119 #[test]
2120 fn encode_issue_3478_xterm() {
2121 let mode = KeyCodeEncodeModes {
2122 encoding: KeyboardEncoding::Xterm,
2123 newline_mode: false,
2124 application_cursor_keys: false,
2125 modify_other_keys: None,
2126 };
2127
2128 assert_eq!(
2129 KeyCode::Numpad0
2130 .encode(Modifiers::NONE, mode, true)
2131 .unwrap(),
2132 "\u{1b}[2~".to_string()
2133 );
2134 assert_eq!(
2135 KeyCode::Numpad0
2136 .encode(Modifiers::SHIFT, mode, true)
2137 .unwrap(),
2138 "\u{1b}[2;2~".to_string()
2139 );
2140
2141 assert_eq!(
2142 KeyCode::Numpad1
2143 .encode(Modifiers::NONE, mode, true)
2144 .unwrap(),
2145 "\u{1b}[F".to_string()
2146 );
2147 assert_eq!(
2148 KeyCode::Numpad1
2149 .encode(Modifiers::NONE | Modifiers::SHIFT, mode, true)
2150 .unwrap(),
2151 "\u{1b}[1;2F".to_string()
2152 );
2153 }
2154
2155 #[test]
2156 fn encode_tab_with_modifiers() {
2157 let mode = KeyCodeEncodeModes {
2158 encoding: KeyboardEncoding::Xterm,
2159 newline_mode: false,
2160 application_cursor_keys: false,
2161 modify_other_keys: None,
2162 };
2163
2164 let mods_to_result = [
2165 (Modifiers::SHIFT, "\u{1b}[Z"),
2166 (Modifiers::SHIFT | Modifiers::LEFT_SHIFT, "\u{1b}[Z"),
2167 (Modifiers::SHIFT | Modifiers::RIGHT_SHIFT, "\u{1b}[Z"),
2168 (Modifiers::CTRL, "\u{1b}[9;5u"),
2169 (Modifiers::CTRL | Modifiers::LEFT_CTRL, "\u{1b}[9;5u"),
2170 (Modifiers::CTRL | Modifiers::RIGHT_CTRL, "\u{1b}[9;5u"),
2171 (
2172 Modifiers::SHIFT | Modifiers::CTRL | Modifiers::LEFT_CTRL | Modifiers::LEFT_SHIFT,
2173 "\u{1b}[1;5Z",
2174 ),
2175 ];
2176 for (mods, result) in mods_to_result {
2177 assert_eq!(
2178 KeyCode::Tab.encode(mods, mode, true).unwrap(),
2179 result,
2180 "{:?}",
2181 mods
2182 );
2183 }
2184 }
2185
2186 #[test]
2187 fn mouse_button1_press() {
2188 let mut p = InputParser::new();
2189 let res = p.parse_as_vec(b"\x1b[<0;42;12M", true);
2190 assert_eq!(
2191 res,
2192 vec![InputEvent::Mouse(MouseEvent {
2193 x: 42,
2194 y: 12,
2195 mouse_buttons: MouseButtons::LEFT,
2196 modifiers: Modifiers::NONE,
2197 })]
2198 );
2199 }
2200
2201 #[test]
2202 fn mouse_button1_release() {
2203 let mut p = InputParser::new();
2204 let res = p.parse_as_vec(b"\x1b[<0;42;12m", true);
2205 assert_eq!(
2206 res,
2207 vec![InputEvent::Mouse(MouseEvent {
2208 x: 42,
2209 y: 12,
2210 mouse_buttons: MouseButtons::NONE,
2211 modifiers: Modifiers::NONE,
2212 })]
2213 );
2214 }
2215
2216 #[test]
2217 fn mouse_button3_with_shift() {
2218 let mut p = InputParser::new();
2219 let res = p.parse_as_vec(b"\x1b[<6;10;20M", true);
2221 assert_eq!(
2222 res,
2223 vec![InputEvent::Mouse(MouseEvent {
2224 x: 10,
2225 y: 20,
2226 mouse_buttons: MouseButtons::RIGHT,
2227 modifiers: Modifiers::SHIFT,
2228 })]
2229 );
2230 }
2231
2232 #[test]
2233 fn mouse_drag() {
2234 let mut p = InputParser::new();
2235 let res = p.parse_as_vec(b"\x1b[<32;5;5M", true);
2237 assert_eq!(
2238 res,
2239 vec![InputEvent::Mouse(MouseEvent {
2240 x: 5,
2241 y: 5,
2242 mouse_buttons: MouseButtons::LEFT,
2243 modifiers: Modifiers::NONE,
2244 })]
2245 );
2246 }
2247
2248 #[test]
2249 fn mouse_vertical_scroll_up() {
2250 let mut p = InputParser::new();
2251 let res = p.parse_as_vec(b"\x1b[<64;1;1M", true);
2253 assert_eq!(
2254 res,
2255 vec![InputEvent::Mouse(MouseEvent {
2256 x: 1,
2257 y: 1,
2258 mouse_buttons: MouseButtons::VERT_WHEEL | MouseButtons::WHEEL_POSITIVE,
2259 modifiers: Modifiers::NONE,
2260 })]
2261 );
2262 }
2263
2264 #[test]
2265 fn mouse_vertical_scroll_down() {
2266 let mut p = InputParser::new();
2267 let res = p.parse_as_vec(b"\x1b[<65;1;1M", true);
2269 assert_eq!(
2270 res,
2271 vec![InputEvent::Mouse(MouseEvent {
2272 x: 1,
2273 y: 1,
2274 mouse_buttons: MouseButtons::VERT_WHEEL,
2275 modifiers: Modifiers::NONE,
2276 })]
2277 );
2278 }
2279
2280 #[test]
2281 fn mouse_motion_no_buttons() {
2282 let mut p = InputParser::new();
2283 let res = p.parse_as_vec(b"\x1b[<35;10;10M", true);
2285 assert_eq!(
2286 res,
2287 vec![InputEvent::Mouse(MouseEvent {
2288 x: 10,
2289 y: 10,
2290 mouse_buttons: MouseButtons::NONE,
2291 modifiers: Modifiers::NONE,
2292 })]
2293 );
2294 }
2295
2296 #[test]
2297 fn mouse_with_ctrl_alt() {
2298 let mut p = InputParser::new();
2299 let res = p.parse_as_vec(b"\x1b[<24;1;1M", true);
2301 assert_eq!(
2302 res,
2303 vec![InputEvent::Mouse(MouseEvent {
2304 x: 1,
2305 y: 1,
2306 mouse_buttons: MouseButtons::LEFT,
2307 modifiers: Modifiers::ALT | Modifiers::CTRL,
2308 })]
2309 );
2310 }
2311
2312 #[test]
2313 fn mouse_large_coordinates() {
2314 let mut p = InputParser::new();
2315 let res = p.parse_as_vec(b"\x1b[<0;999;999M", true);
2316 assert_eq!(
2317 res,
2318 vec![InputEvent::Mouse(MouseEvent {
2319 x: 999,
2320 y: 999,
2321 mouse_buttons: MouseButtons::LEFT,
2322 modifiers: Modifiers::NONE,
2323 })]
2324 );
2325 }
2326
2327 #[test]
2328 fn mouse_followed_by_key() {
2329 let mut p = InputParser::new();
2330 let res = p.parse_as_vec(b"\x1b[<0;1;1Mhello", false);
2331 assert_eq!(res.len(), 6); assert!(matches!(res[0], InputEvent::Mouse(_)));
2333 assert!(matches!(res[1], InputEvent::Key(_)));
2334 }
2335
2336 #[test]
2337 fn two_mouse_events_back_to_back() {
2338 let mut p = InputParser::new();
2339 let res = p.parse_as_vec(b"\x1b[<0;1;1M\x1b[<0;2;2M", true);
2340 assert_eq!(res.len(), 2);
2341 }
2342
2343 #[test]
2344 fn invalid_sgr_mouse_falls_through() {
2345 let mut p = InputParser::new();
2346 let res = p.parse_as_vec(b"\x1b[<0;1M", false);
2348 assert!(res.iter().all(|e| matches!(e, InputEvent::Key(_))));
2350 }
2351
2352 #[test]
2353 fn osc_bel_terminated() {
2354 let mut p = InputParser::new();
2356 let inputs = p.parse_as_vec(b"\x1b]99;i=test:p=title;Hello\x07", NO_MORE);
2357 assert_eq!(
2358 vec![InputEvent::OperatingSystemCommand(
2359 b"99;i=test:p=title;Hello".to_vec()
2360 )],
2361 inputs
2362 );
2363 }
2364
2365 #[test]
2366 fn osc_st_terminated() {
2367 let mut p = InputParser::new();
2369 let inputs = p.parse_as_vec(b"\x1b]99;i=test:p=title;Hello\x1b\\", NO_MORE);
2370 assert_eq!(
2371 vec![InputEvent::OperatingSystemCommand(
2372 b"99;i=test:p=title;Hello".to_vec()
2373 )],
2374 inputs
2375 );
2376 }
2377
2378 #[test]
2379 fn osc_partial_across_reads() {
2380 let mut p = InputParser::new();
2382 let mut inputs = Vec::new();
2383 p.parse(
2384 b"\x1b]99;i=test:p=title;Hel",
2385 |evt| inputs.push(evt),
2386 MAYBE_MORE,
2387 );
2388 assert!(inputs.is_empty(), "no events yet - sequence incomplete");
2389 p.parse(b"lo\x1b\\", |evt| inputs.push(evt), MAYBE_MORE);
2390 assert_eq!(
2391 vec![InputEvent::OperatingSystemCommand(
2392 b"99;i=test:p=title;Hello".to_vec()
2393 )],
2394 inputs
2395 );
2396 }
2397
2398 #[test]
2399 fn osc_followed_by_keypress() {
2400 let mut p = InputParser::new();
2402 let inputs = p.parse_as_vec(b"\x1b]99;i=test;clicked\x07x", NO_MORE);
2403 assert_eq!(
2404 vec![
2405 InputEvent::OperatingSystemCommand(b"99;i=test;clicked".to_vec()),
2406 InputEvent::Key(KeyEvent {
2407 modifiers: Modifiers::NONE,
2408 key: KeyCode::Char('x'),
2409 }),
2410 ],
2411 inputs
2412 );
2413 }
2414
2415 #[test]
2416 fn keypress_followed_by_osc() {
2417 let mut p = InputParser::new();
2419 let inputs = p.parse_as_vec(b"x\x1b]99;i=test;clicked\x07", NO_MORE);
2420 assert_eq!(
2421 vec![
2422 InputEvent::Key(KeyEvent {
2423 modifiers: Modifiers::NONE,
2424 key: KeyCode::Char('x'),
2425 }),
2426 InputEvent::OperatingSystemCommand(b"99;i=test;clicked".to_vec()),
2427 ],
2428 inputs
2429 );
2430 }
2431
2432 #[test]
2433 fn osc_incomplete_degrades_to_keys() {
2434 let mut p = InputParser::new();
2437 let mut inputs = Vec::new();
2438 p.parse(b"\x1b]99;no-terminator", |evt| inputs.push(evt), MAYBE_MORE);
2439 assert!(inputs.is_empty(), "buffered while maybe_more=true");
2440 p.parse(b"", |evt| inputs.push(evt), NO_MORE);
2441 assert!(!inputs.is_empty(), "must emit something on finalization");
2442 }
2443
2444 #[test]
2445 fn osc_non_99_code() {
2446 let mut p = InputParser::new();
2448 let inputs = p.parse_as_vec(b"\x1b]11;rgb:0000/0000/0000\x1b\\", NO_MORE);
2449 assert_eq!(
2450 vec![InputEvent::OperatingSystemCommand(
2451 b"11;rgb:0000/0000/0000".to_vec()
2452 )],
2453 inputs
2454 );
2455 }
2456
2457 #[test]
2458 fn osc_empty_payload() {
2459 let mut p = InputParser::new();
2461 let inputs = p.parse_as_vec(b"\x1b]\x07", NO_MORE);
2462 assert_eq!(
2463 vec![InputEvent::OperatingSystemCommand(b"".to_vec())],
2464 inputs
2465 );
2466 }
2467
2468 #[test]
2469 fn csi_not_captured_as_osc() {
2470 let mut p = InputParser::new();
2473 let inputs = p.parse_as_vec(b"\x1b[A", NO_MORE);
2474 assert_eq!(
2475 vec![InputEvent::Key(KeyEvent {
2476 modifiers: Modifiers::NONE,
2477 key: KeyCode::UpArrow,
2478 })],
2479 inputs
2480 );
2481 }
2482}