1use crate::bail;
4use crate::error::Result;
5use crate::escape::csi::{KittyKeyboardFlags, MouseReport};
6use crate::escape::parser::Parser;
7use crate::escape::{Action, CSI};
8use crate::keymap::{Found, KeyMap};
9use crate::readbuf::ReadBuffer;
10#[cfg(feature = "use_serde")]
11use serde::{Deserialize, Serialize};
12use std::fmt::Write;
13use wezterm_input_types::ctrl_mapping;
14
15pub use wezterm_input_types::Modifiers;
16
17pub const CSI: &str = "\x1b[";
18pub const SS3: &str = "\x1bO";
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum KeyboardEncoding {
22 Xterm,
23 CsiU,
25 Win32,
27 Kitty(KittyKeyboardFlags),
29}
30
31#[derive(Debug, Clone, Copy)]
34pub struct KeyCodeEncodeModes {
35 pub encoding: KeyboardEncoding,
36 pub application_cursor_keys: bool,
37 pub newline_mode: bool,
38 pub modify_other_keys: Option<i64>,
39}
40
41#[cfg(windows)]
42use winapi::um::wincon::{
43 INPUT_RECORD, KEY_EVENT, KEY_EVENT_RECORD, MOUSE_EVENT, MOUSE_EVENT_RECORD,
44 WINDOW_BUFFER_SIZE_EVENT, WINDOW_BUFFER_SIZE_RECORD,
45};
46
47pub use wezterm_escape_parser::csi::MouseButtons;
48
49#[derive(Debug, Clone, PartialEq, Eq)]
50pub enum InputEvent {
51 Key(KeyEvent),
52 Mouse(MouseEvent),
53 PixelMouse(PixelMouseEvent),
54 Resized {
56 cols: usize,
57 rows: usize,
58 },
59 Paste(String),
62 Wake,
64}
65
66#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
67#[derive(Debug, Clone, PartialEq, Eq)]
68pub struct MouseEvent {
69 pub x: u16,
70 pub y: u16,
71 pub mouse_buttons: MouseButtons,
72 pub modifiers: Modifiers,
73}
74
75#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
76#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct PixelMouseEvent {
78 pub x_pixels: u16,
79 pub y_pixels: u16,
80 pub mouse_buttons: MouseButtons,
81 pub modifiers: Modifiers,
82}
83
84#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
85#[derive(Debug, Clone, PartialEq, Eq)]
86pub struct KeyEvent {
87 pub key: KeyCode,
89
90 pub modifiers: Modifiers,
92}
93
94#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
98#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
99pub enum KeyCode {
100 Char(char),
102
103 Hyper,
104 Super,
105 Meta,
106
107 Cancel,
109 Backspace,
110 Tab,
111 Clear,
112 Enter,
113 Shift,
114 Escape,
115 LeftShift,
116 RightShift,
117 Control,
118 LeftControl,
119 RightControl,
120 Alt,
121 LeftAlt,
122 RightAlt,
123 Menu,
124 LeftMenu,
125 RightMenu,
126 Pause,
127 CapsLock,
128 PageUp,
129 PageDown,
130 End,
131 Home,
132 LeftArrow,
133 RightArrow,
134 UpArrow,
135 DownArrow,
136 Select,
137 Print,
138 Execute,
139 PrintScreen,
140 Insert,
141 Delete,
142 Help,
143 LeftWindows,
144 RightWindows,
145 Applications,
146 Sleep,
147 Numpad0,
148 Numpad1,
149 Numpad2,
150 Numpad3,
151 Numpad4,
152 Numpad5,
153 Numpad6,
154 Numpad7,
155 Numpad8,
156 Numpad9,
157 Multiply,
158 Add,
159 Separator,
160 Subtract,
161 Decimal,
162 Divide,
163 Function(u8),
165 NumLock,
166 ScrollLock,
167 Copy,
168 Cut,
169 Paste,
170 BrowserBack,
171 BrowserForward,
172 BrowserRefresh,
173 BrowserStop,
174 BrowserSearch,
175 BrowserFavorites,
176 BrowserHome,
177 VolumeMute,
178 VolumeDown,
179 VolumeUp,
180 MediaNextTrack,
181 MediaPrevTrack,
182 MediaStop,
183 MediaPlayPause,
184 ApplicationLeftArrow,
185 ApplicationRightArrow,
186 ApplicationUpArrow,
187 ApplicationDownArrow,
188 KeyPadHome,
189 KeyPadEnd,
190 KeyPadPageUp,
191 KeyPadPageDown,
192 KeyPadBegin,
193
194 #[doc(hidden)]
195 InternalPasteStart,
196 #[doc(hidden)]
197 InternalPasteEnd,
198}
199
200impl KeyCode {
201 pub fn normalize_shift_to_upper_case(self, modifiers: Modifiers) -> KeyCode {
208 if modifiers.contains(Modifiers::SHIFT) {
209 match self {
210 KeyCode::Char(c) if c.is_ascii_lowercase() => KeyCode::Char(c.to_ascii_uppercase()),
211 _ => self,
212 }
213 } else {
214 self
215 }
216 }
217
218 pub fn is_modifier(self) -> bool {
220 matches!(
221 self,
222 Self::Hyper
223 | Self::Super
224 | Self::Meta
225 | Self::Shift
226 | Self::LeftShift
227 | Self::RightShift
228 | Self::Control
229 | Self::LeftControl
230 | Self::RightControl
231 | Self::Alt
232 | Self::LeftAlt
233 | Self::RightAlt
234 | Self::LeftWindows
235 | Self::RightWindows
236 )
237 }
238
239 pub fn encode(
241 &self,
242 mods: Modifiers,
243 modes: KeyCodeEncodeModes,
244 is_down: bool,
245 ) -> Result<String> {
246 if !is_down {
247 return Ok(String::new());
249 }
250 let mods = mods.remove_positional_mods();
253
254 use KeyCode::*;
255
256 let key = self.normalize_shift_to_upper_case(mods);
257 let mods = match key {
260 Char(c)
261 if (c.is_ascii_punctuation() || c.is_ascii_uppercase())
262 && mods.contains(Modifiers::SHIFT) =>
263 {
264 mods & !Modifiers::SHIFT
265 }
266 _ => mods,
267 };
268
269 let key = match key {
271 Char('\x7f') => Delete,
272 Char('\x08') => Backspace,
273 c => c,
274 };
275
276 let mut buf = String::new();
277
278 match key {
281 Char(c)
282 if is_ambiguous_ascii_ctrl(c)
283 && mods.contains(Modifiers::CTRL)
284 && modes.encoding == KeyboardEncoding::CsiU =>
285 {
286 csi_u_encode(&mut buf, c, mods, &modes)?;
287 }
288 Char(c) if c.is_ascii_uppercase() && mods.contains(Modifiers::CTRL) => {
289 csi_u_encode(&mut buf, c, mods, &modes)?;
290 }
291
292 Char(c) if mods.contains(Modifiers::CTRL) && modes.modify_other_keys == Some(2) => {
293 csi_u_encode(&mut buf, c, mods, &modes)?;
294 }
295 Char(c) if mods.contains(Modifiers::CTRL) && ctrl_mapping(c).is_some() => {
296 let c = ctrl_mapping(c).unwrap();
297 if mods.contains(Modifiers::ALT) {
298 buf.push(0x1b as char);
299 }
300 buf.push(c);
301 }
302
303 Char(c)
309 if (c.is_ascii_alphanumeric() || c.is_ascii_punctuation())
310 && mods.contains(Modifiers::ALT) =>
311 {
312 buf.push(0x1b as char);
313 buf.push(c);
314 }
315
316 Backspace => {
317 if mods.contains(Modifiers::CTRL) {
321 csi_u_encode(&mut buf, '\x08', mods, &modes)?;
322 } else if mods.contains(Modifiers::SHIFT) {
323 csi_u_encode(&mut buf, '\x7f', mods, &modes)?;
324 } else {
325 if mods.contains(Modifiers::ALT) {
326 buf.push(0x1b as char);
327 }
328 buf.push('\x7f');
329 }
330 }
331
332 Enter | Escape => {
333 let c = match key {
334 Enter => '\r',
335 Escape => '\x1b',
336 _ => unreachable!(),
337 };
338 if mods.contains(Modifiers::SHIFT) || mods.contains(Modifiers::CTRL) {
339 csi_u_encode(&mut buf, c, mods, &modes)?;
340 } else {
341 if mods.contains(Modifiers::ALT) {
342 buf.push(0x1b as char);
343 }
344 buf.push(c);
345 if modes.newline_mode && key == Enter {
346 buf.push(0x0a as char);
347 }
348 }
349 }
350
351 Tab if !mods.is_empty() && modes.modify_other_keys.is_some() => {
352 csi_u_encode(&mut buf, '\t', mods, &modes)?;
353 }
354
355 Tab => {
356 if mods.contains(Modifiers::ALT) {
357 buf.push(0x1b as char);
358 }
359 let mods = mods & !Modifiers::ALT;
360 if mods == Modifiers::CTRL {
361 buf.push_str("\x1b[9;5u");
362 } else if mods == Modifiers::CTRL | Modifiers::SHIFT {
363 buf.push_str("\x1b[1;5Z");
364 } else if mods == Modifiers::SHIFT {
365 buf.push_str("\x1b[Z");
366 } else {
367 buf.push('\t');
368 }
369 }
370
371 Char(c) => {
372 if mods.is_empty() {
373 buf.push(c);
374 } else {
375 csi_u_encode(&mut buf, c, mods, &modes)?;
376 }
377 }
378
379 Home
380 | KeyPadHome
381 | End
382 | KeyPadEnd
383 | UpArrow
384 | DownArrow
385 | RightArrow
386 | LeftArrow
387 | ApplicationUpArrow
388 | ApplicationDownArrow
389 | ApplicationRightArrow
390 | ApplicationLeftArrow => {
391 let (force_app, c) = match key {
392 UpArrow => (false, 'A'),
393 DownArrow => (false, 'B'),
394 RightArrow => (false, 'C'),
395 LeftArrow => (false, 'D'),
396 KeyPadHome | Home => (false, 'H'),
397 End | KeyPadEnd => (false, 'F'),
398 ApplicationUpArrow => (true, 'A'),
399 ApplicationDownArrow => (true, 'B'),
400 ApplicationRightArrow => (true, 'C'),
401 ApplicationLeftArrow => (true, 'D'),
402 _ => unreachable!(),
403 };
404
405 let csi_or_ss3 = if force_app
406 || (
407 modes.application_cursor_keys
408 ) {
413 SS3
415 } else {
416 CSI
418 };
419
420 if mods.contains(Modifiers::ALT)
421 || mods.contains(Modifiers::SHIFT)
422 || mods.contains(Modifiers::CTRL)
423 {
424 write!(buf, "{}1;{}{}", CSI, 1 + mods.encode_xterm(), c)?;
425 } else {
426 write!(buf, "{}{}", csi_or_ss3, c)?;
427 }
428 }
429
430 PageUp | PageDown | KeyPadPageUp | KeyPadPageDown | Insert | Delete => {
431 let c = match key {
432 Insert => 2,
433 Delete => 3,
434 KeyPadPageUp | PageUp => 5,
435 KeyPadPageDown | PageDown => 6,
436 _ => unreachable!(),
437 };
438
439 if mods.contains(Modifiers::ALT)
440 || mods.contains(Modifiers::SHIFT)
441 || mods.contains(Modifiers::CTRL)
442 {
443 write!(buf, "\x1b[{};{}~", c, 1 + mods.encode_xterm())?;
444 } else {
445 write!(buf, "\x1b[{}~", c)?;
446 }
447 }
448
449 Function(n) => {
450 if mods.is_empty() && n < 5 {
451 write!(
453 buf,
454 "{}",
455 match n {
456 1 => "\x1bOP",
457 2 => "\x1bOQ",
458 3 => "\x1bOR",
459 4 => "\x1bOS",
460 _ => unreachable!("wat?"),
461 }
462 )?;
463 } else if n < 5 {
464 let code = match n {
466 1 => 'P',
467 2 => 'Q',
468 3 => 'R',
469 4 => 'S',
470 _ => unreachable!("wat?"),
471 };
472 write!(buf, "\x1b[1;{}{code}", 1 + mods.encode_xterm())?;
473 } else {
474 let intro = match n {
476 1 => "\x1b[11",
477 2 => "\x1b[12",
478 3 => "\x1b[13",
479 4 => "\x1b[14",
480 5 => "\x1b[15",
481 6 => "\x1b[17",
482 7 => "\x1b[18",
483 8 => "\x1b[19",
484 9 => "\x1b[20",
485 10 => "\x1b[21",
486 11 => "\x1b[23",
487 12 => "\x1b[24",
488 13 => "\x1b[25",
489 14 => "\x1b[26",
490 15 => "\x1b[28",
491 16 => "\x1b[29",
492 17 => "\x1b[31",
493 18 => "\x1b[32",
494 19 => "\x1b[33",
495 20 => "\x1b[34",
496 21 => "\x1b[42",
497 22 => "\x1b[43",
498 23 => "\x1b[44",
499 24 => "\x1b[45",
500 _ => bail!("unhandled fkey number {}", n),
501 };
502 let encoded_mods = mods.encode_xterm();
503 if encoded_mods == 0 {
504 write!(buf, "{}~", intro)?;
507 } else {
508 write!(buf, "{};{}~", intro, 1 + encoded_mods)?;
509 }
510 }
511 }
512
513 Numpad0 | Numpad3 | Numpad9 | Decimal => {
514 let intro = match key {
515 Numpad0 => "\x1b[2",
516 Numpad3 => "\x1b[6",
517 Numpad9 => "\x1b[6",
518 Decimal => "\x1b[3",
519 _ => unreachable!(),
520 };
521
522 let encoded_mods = mods.encode_xterm();
523 if encoded_mods == 0 {
524 write!(buf, "{}~", intro)?;
527 } else {
528 write!(buf, "{};{}~", intro, 1 + encoded_mods)?;
529 }
530 }
531
532 Numpad1 | Numpad2 | Numpad4 | Numpad5 | KeyPadBegin | Numpad6 | Numpad7 | Numpad8 => {
533 let c = match key {
534 Numpad1 => "F",
535 Numpad2 => "B",
536 Numpad4 => "D",
537 KeyPadBegin | Numpad5 => "E",
538 Numpad6 => "C",
539 Numpad7 => "H",
540 Numpad8 => "A",
541 _ => unreachable!(),
542 };
543
544 let encoded_mods = mods.encode_xterm();
545 if encoded_mods == 0 {
546 write!(buf, "{}{}", CSI, c)?;
548 } else {
549 write!(buf, "{}1;{}{}", CSI, 1 + encoded_mods, c)?;
550 }
551 }
552
553 Multiply | Add | Separator | Subtract | Divide => {}
554
555 Control | LeftControl | RightControl | Alt | LeftAlt | RightAlt | Menu | LeftMenu
557 | RightMenu | Super | Hyper | Shift | LeftShift | RightShift | Meta | LeftWindows
558 | RightWindows | NumLock | ScrollLock | Cancel | Clear | Pause | CapsLock | Select
559 | Print | PrintScreen | Execute | Help | Applications | Sleep | Copy | Cut | Paste
560 | BrowserBack | BrowserForward | BrowserRefresh | BrowserStop | BrowserSearch
561 | BrowserFavorites | BrowserHome | VolumeMute | VolumeDown | VolumeUp
562 | MediaNextTrack | MediaPrevTrack | MediaStop | MediaPlayPause | InternalPasteStart
563 | InternalPasteEnd => {}
564 };
565
566 Ok(buf)
567 }
568}
569
570fn is_ambiguous_ascii_ctrl(c: char) -> bool {
574 match c {
575 'i' | 'I' | 'm' | 'M' | '[' | '{' | '@' => true,
576 _ => false,
577 }
578}
579
580fn is_ascii(c: char) -> bool {
581 (c as u32) < 0x80
582}
583
584fn csi_u_encode(
585 buf: &mut String,
586 c: char,
587 mods: Modifiers,
588 modes: &KeyCodeEncodeModes,
589) -> Result<()> {
590 if modes.encoding == KeyboardEncoding::CsiU && is_ascii(c) {
591 write!(buf, "\x1b[{};{}u", c as u32, 1 + mods.encode_xterm())?;
592 return Ok(());
593 }
594
595 match (c, modes.modify_other_keys) {
597 ('c' | 'd' | '\x1b' | '\x7f' | '\x08', Some(1)) => {
598 }
600 (c, Some(_)) => {
601 write!(buf, "\x1b[27;{};{}~", 1 + mods.encode_xterm(), c as u32)?;
602 return Ok(());
603 }
604 _ => {}
605 }
606
607 let c = if mods.contains(Modifiers::CTRL) && ctrl_mapping(c).is_some() {
608 ctrl_mapping(c).unwrap()
609 } else {
610 c
611 };
612 if mods.contains(Modifiers::ALT) {
613 buf.push(0x1b as char);
614 }
615 write!(buf, "{}", c)?;
616 Ok(())
617}
618
619#[derive(Debug, Clone, Copy, PartialEq, Eq)]
620enum InputState {
621 Normal,
622 EscapeMaybeAlt,
623 Pasting(usize),
624}
625
626#[derive(Debug)]
627pub struct InputParser {
628 key_map: KeyMap<InputEvent>,
629 buf: ReadBuffer,
630 state: InputState,
631}
632
633#[cfg(windows)]
634mod windows {
635 use super::*;
636 use std;
637 use winapi::um::winuser;
638
639 fn modifiers_from_ctrl_key_state(state: u32) -> Modifiers {
640 use winapi::um::wincon::*;
641
642 let mut mods = Modifiers::NONE;
643
644 if (state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0 {
645 mods |= Modifiers::ALT;
646 }
647
648 if (state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0 {
649 mods |= Modifiers::CTRL;
650 }
651
652 if (state & SHIFT_PRESSED) != 0 {
653 mods |= Modifiers::SHIFT;
654 }
655
656 mods
659 }
660 impl InputParser {
661 fn decode_key_record<F: FnMut(InputEvent)>(
662 &mut self,
663 event: &KEY_EVENT_RECORD,
664 callback: &mut F,
665 ) {
666 if event.bKeyDown == 0 {
668 return;
669 }
670
671 let key_code = match std::char::from_u32(*unsafe { event.uChar.UnicodeChar() } as u32) {
672 Some(unicode) if unicode > '\x00' => {
673 let mut buf = [0u8; 4];
674 self.buf
675 .extend_with(unicode.encode_utf8(&mut buf).as_bytes());
676 self.process_bytes(callback, true);
677 return;
678 }
679 _ => match event.wVirtualKeyCode as i32 {
680 winuser::VK_CANCEL => KeyCode::Cancel,
681 winuser::VK_BACK => KeyCode::Backspace,
682 winuser::VK_TAB => KeyCode::Tab,
683 winuser::VK_CLEAR => KeyCode::Clear,
684 winuser::VK_RETURN => KeyCode::Enter,
685 winuser::VK_SHIFT => KeyCode::Shift,
686 winuser::VK_CONTROL => KeyCode::Control,
687 winuser::VK_MENU => KeyCode::Menu,
688 winuser::VK_PAUSE => KeyCode::Pause,
689 winuser::VK_CAPITAL => KeyCode::CapsLock,
690 winuser::VK_ESCAPE => KeyCode::Escape,
691 winuser::VK_PRIOR => KeyCode::PageUp,
692 winuser::VK_NEXT => KeyCode::PageDown,
693 winuser::VK_END => KeyCode::End,
694 winuser::VK_HOME => KeyCode::Home,
695 winuser::VK_LEFT => KeyCode::LeftArrow,
696 winuser::VK_RIGHT => KeyCode::RightArrow,
697 winuser::VK_UP => KeyCode::UpArrow,
698 winuser::VK_DOWN => KeyCode::DownArrow,
699 winuser::VK_SELECT => KeyCode::Select,
700 winuser::VK_PRINT => KeyCode::Print,
701 winuser::VK_EXECUTE => KeyCode::Execute,
702 winuser::VK_SNAPSHOT => KeyCode::PrintScreen,
703 winuser::VK_INSERT => KeyCode::Insert,
704 winuser::VK_DELETE => KeyCode::Delete,
705 winuser::VK_HELP => KeyCode::Help,
706 winuser::VK_LWIN => KeyCode::LeftWindows,
707 winuser::VK_RWIN => KeyCode::RightWindows,
708 winuser::VK_APPS => KeyCode::Applications,
709 winuser::VK_SLEEP => KeyCode::Sleep,
710 winuser::VK_NUMPAD0 => KeyCode::Numpad0,
711 winuser::VK_NUMPAD1 => KeyCode::Numpad1,
712 winuser::VK_NUMPAD2 => KeyCode::Numpad2,
713 winuser::VK_NUMPAD3 => KeyCode::Numpad3,
714 winuser::VK_NUMPAD4 => KeyCode::Numpad4,
715 winuser::VK_NUMPAD5 => KeyCode::Numpad5,
716 winuser::VK_NUMPAD6 => KeyCode::Numpad6,
717 winuser::VK_NUMPAD7 => KeyCode::Numpad7,
718 winuser::VK_NUMPAD8 => KeyCode::Numpad8,
719 winuser::VK_NUMPAD9 => KeyCode::Numpad9,
720 winuser::VK_MULTIPLY => KeyCode::Multiply,
721 winuser::VK_ADD => KeyCode::Add,
722 winuser::VK_SEPARATOR => KeyCode::Separator,
723 winuser::VK_SUBTRACT => KeyCode::Subtract,
724 winuser::VK_DECIMAL => KeyCode::Decimal,
725 winuser::VK_DIVIDE => KeyCode::Divide,
726 winuser::VK_F1 => KeyCode::Function(1),
727 winuser::VK_F2 => KeyCode::Function(2),
728 winuser::VK_F3 => KeyCode::Function(3),
729 winuser::VK_F4 => KeyCode::Function(4),
730 winuser::VK_F5 => KeyCode::Function(5),
731 winuser::VK_F6 => KeyCode::Function(6),
732 winuser::VK_F7 => KeyCode::Function(7),
733 winuser::VK_F8 => KeyCode::Function(8),
734 winuser::VK_F9 => KeyCode::Function(9),
735 winuser::VK_F10 => KeyCode::Function(10),
736 winuser::VK_F11 => KeyCode::Function(11),
737 winuser::VK_F12 => KeyCode::Function(12),
738 winuser::VK_F13 => KeyCode::Function(13),
739 winuser::VK_F14 => KeyCode::Function(14),
740 winuser::VK_F15 => KeyCode::Function(15),
741 winuser::VK_F16 => KeyCode::Function(16),
742 winuser::VK_F17 => KeyCode::Function(17),
743 winuser::VK_F18 => KeyCode::Function(18),
744 winuser::VK_F19 => KeyCode::Function(19),
745 winuser::VK_F20 => KeyCode::Function(20),
746 winuser::VK_F21 => KeyCode::Function(21),
747 winuser::VK_F22 => KeyCode::Function(22),
748 winuser::VK_F23 => KeyCode::Function(23),
749 winuser::VK_F24 => KeyCode::Function(24),
750 winuser::VK_NUMLOCK => KeyCode::NumLock,
751 winuser::VK_SCROLL => KeyCode::ScrollLock,
752 winuser::VK_LSHIFT => KeyCode::LeftShift,
753 winuser::VK_RSHIFT => KeyCode::RightShift,
754 winuser::VK_LCONTROL => KeyCode::LeftControl,
755 winuser::VK_RCONTROL => KeyCode::RightControl,
756 winuser::VK_LMENU => KeyCode::LeftMenu,
757 winuser::VK_RMENU => KeyCode::RightMenu,
758 winuser::VK_BROWSER_BACK => KeyCode::BrowserBack,
759 winuser::VK_BROWSER_FORWARD => KeyCode::BrowserForward,
760 winuser::VK_BROWSER_REFRESH => KeyCode::BrowserRefresh,
761 winuser::VK_BROWSER_STOP => KeyCode::BrowserStop,
762 winuser::VK_BROWSER_SEARCH => KeyCode::BrowserSearch,
763 winuser::VK_BROWSER_FAVORITES => KeyCode::BrowserFavorites,
764 winuser::VK_BROWSER_HOME => KeyCode::BrowserHome,
765 winuser::VK_VOLUME_MUTE => KeyCode::VolumeMute,
766 winuser::VK_VOLUME_DOWN => KeyCode::VolumeDown,
767 winuser::VK_VOLUME_UP => KeyCode::VolumeUp,
768 winuser::VK_MEDIA_NEXT_TRACK => KeyCode::MediaNextTrack,
769 winuser::VK_MEDIA_PREV_TRACK => KeyCode::MediaPrevTrack,
770 winuser::VK_MEDIA_STOP => KeyCode::MediaStop,
771 winuser::VK_MEDIA_PLAY_PAUSE => KeyCode::MediaPlayPause,
772 _ => return,
773 },
774 };
775 let mut modifiers = modifiers_from_ctrl_key_state(event.dwControlKeyState);
776
777 let key_code = key_code.normalize_shift_to_upper_case(modifiers);
778 if let KeyCode::Char(c) = key_code {
779 if c.is_ascii_uppercase() {
780 modifiers.remove(Modifiers::SHIFT);
781 }
782 }
783
784 let input_event = InputEvent::Key(KeyEvent {
785 key: key_code,
786 modifiers,
787 });
788 for _ in 0..event.wRepeatCount {
789 callback(input_event.clone());
790 }
791 }
792
793 fn decode_mouse_record<F: FnMut(InputEvent)>(
794 &self,
795 event: &MOUSE_EVENT_RECORD,
796 callback: &mut F,
797 ) {
798 use winapi::um::wincon::*;
799 let mut buttons = MouseButtons::NONE;
800
801 if (event.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) != 0 {
802 buttons |= MouseButtons::LEFT;
803 }
804 if (event.dwButtonState & RIGHTMOST_BUTTON_PRESSED) != 0 {
805 buttons |= MouseButtons::RIGHT;
806 }
807 if (event.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) != 0 {
808 buttons |= MouseButtons::MIDDLE;
809 }
810
811 let modifiers = modifiers_from_ctrl_key_state(event.dwControlKeyState);
812
813 if (event.dwEventFlags & MOUSE_WHEELED) != 0 {
814 buttons |= MouseButtons::VERT_WHEEL;
815 if (event.dwButtonState >> 8) != 0 {
816 buttons |= MouseButtons::WHEEL_POSITIVE;
817 }
818 } else if (event.dwEventFlags & MOUSE_HWHEELED) != 0 {
819 buttons |= MouseButtons::HORZ_WHEEL;
820 if (event.dwButtonState >> 8) != 0 {
821 buttons |= MouseButtons::WHEEL_POSITIVE;
822 }
823 }
824
825 let mouse = InputEvent::Mouse(MouseEvent {
826 x: event.dwMousePosition.X as u16,
827 y: event.dwMousePosition.Y as u16,
828 mouse_buttons: buttons,
829 modifiers,
830 });
831
832 if (event.dwEventFlags & DOUBLE_CLICK) != 0 {
833 callback(mouse.clone());
834 }
835 callback(mouse);
836 }
837
838 fn decode_resize_record<F: FnMut(InputEvent)>(
839 &self,
840 event: &WINDOW_BUFFER_SIZE_RECORD,
841 callback: &mut F,
842 ) {
843 callback(InputEvent::Resized {
844 rows: event.dwSize.Y as usize,
845 cols: event.dwSize.X as usize,
846 });
847 }
848
849 pub fn decode_input_records<F: FnMut(InputEvent)>(
850 &mut self,
851 records: &[INPUT_RECORD],
852 callback: &mut F,
853 ) {
854 for record in records {
855 match record.EventType {
856 KEY_EVENT => {
857 self.decode_key_record(unsafe { record.Event.KeyEvent() }, callback)
858 }
859 MOUSE_EVENT => {
860 self.decode_mouse_record(unsafe { record.Event.MouseEvent() }, callback)
861 }
862 WINDOW_BUFFER_SIZE_EVENT => self.decode_resize_record(
863 unsafe { record.Event.WindowBufferSizeEvent() },
864 callback,
865 ),
866 _ => {}
867 }
868 }
869 self.process_bytes(callback, false);
870 }
871 }
872}
873
874impl Default for InputParser {
875 fn default() -> Self {
876 Self::new()
877 }
878}
879
880impl InputParser {
881 pub fn new() -> Self {
882 Self {
883 key_map: Self::build_basic_key_map(),
884 buf: ReadBuffer::new(),
885 state: InputState::Normal,
886 }
887 }
888
889 fn build_basic_key_map() -> KeyMap<InputEvent> {
890 let mut map = KeyMap::new();
891
892 let modifier_combos = &[
893 ("", Modifiers::NONE),
894 (";1", Modifiers::NONE),
895 (";2", Modifiers::SHIFT),
896 (";3", Modifiers::ALT),
897 (";4", Modifiers::ALT | Modifiers::SHIFT),
898 (";5", Modifiers::CTRL),
899 (";6", Modifiers::CTRL | Modifiers::SHIFT),
900 (";7", Modifiers::CTRL | Modifiers::ALT),
901 (";8", Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT),
902 ];
903 let meta = Modifiers::ALT;
911 let meta_modifier_combos = &[
912 (";9", meta),
913 (";10", meta | Modifiers::SHIFT),
914 (";11", meta | Modifiers::ALT),
915 (";12", meta | Modifiers::ALT | Modifiers::SHIFT),
916 (";13", meta | Modifiers::CTRL),
917 (";14", meta | Modifiers::CTRL | Modifiers::SHIFT),
918 (";15", meta | Modifiers::CTRL | Modifiers::ALT),
919 (
920 ";16",
921 meta | Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
922 ),
923 ];
924
925 let modifier_combos_including_meta =
926 || modifier_combos.iter().chain(meta_modifier_combos.iter());
927
928 for alpha in b'A'..=b'Z' {
929 let ctrl = [alpha & 0x1f];
931 map.insert(
932 &ctrl,
933 InputEvent::Key(KeyEvent {
934 key: KeyCode::Char((alpha as char).to_ascii_lowercase()),
935 modifiers: Modifiers::CTRL,
936 }),
937 );
938
939 let alt = [0x1b, alpha];
941 map.insert(
942 &alt,
943 InputEvent::Key(KeyEvent {
944 key: KeyCode::Char(alpha as char),
945 modifiers: Modifiers::ALT,
946 }),
947 );
948 }
949
950 for c in 0..=0x7fu8 {
951 for (suffix, modifiers) in modifier_combos {
952 let key = format!("\x1b[{}{}u", c, suffix);
955 map.insert(
956 key,
957 InputEvent::Key(KeyEvent {
958 key: KeyCode::Char(c as char),
959 modifiers: *modifiers,
960 }),
961 );
962
963 if !suffix.is_empty() {
964 let key = format!("\x1b[27{};{}~", suffix, c);
966 map.insert(
967 key,
968 InputEvent::Key(KeyEvent {
969 key: match c {
970 8 | 0x7f => KeyCode::Backspace,
971 0x1b => KeyCode::Escape,
972 9 => KeyCode::Tab,
973 10 | 13 => KeyCode::Enter,
974 _ => KeyCode::Char(c as char),
975 },
976 modifiers: *modifiers,
977 }),
978 );
979 }
980 }
981 }
982
983 for (keycode, dir) in &[
985 (KeyCode::UpArrow, b'A'),
986 (KeyCode::DownArrow, b'B'),
987 (KeyCode::RightArrow, b'C'),
988 (KeyCode::LeftArrow, b'D'),
989 (KeyCode::Home, b'H'),
990 (KeyCode::End, b'F'),
991 ] {
992 let arrow = [0x1b, b'[', *dir];
994 map.insert(
995 &arrow,
996 InputEvent::Key(KeyEvent {
997 key: *keycode,
998 modifiers: Modifiers::NONE,
999 }),
1000 );
1001 for (suffix, modifiers) in modifier_combos_including_meta() {
1002 let key = format!("\x1b[1{}{}", suffix, *dir as char);
1003 map.insert(
1004 key,
1005 InputEvent::Key(KeyEvent {
1006 key: *keycode,
1007 modifiers: *modifiers,
1008 }),
1009 );
1010 }
1011 }
1012 for &(keycode, dir) in &[
1013 (KeyCode::UpArrow, b'a'),
1014 (KeyCode::DownArrow, b'b'),
1015 (KeyCode::RightArrow, b'c'),
1016 (KeyCode::LeftArrow, b'd'),
1017 ] {
1018 for &(seq, mods) in &[
1020 ([0x1b, b'[', dir], Modifiers::SHIFT),
1021 ([0x1b, b'O', dir], Modifiers::CTRL),
1022 ] {
1023 map.insert(
1024 &seq,
1025 InputEvent::Key(KeyEvent {
1026 key: keycode,
1027 modifiers: mods,
1028 }),
1029 );
1030 }
1031 }
1032
1033 for (keycode, dir) in &[
1034 (KeyCode::ApplicationUpArrow, b'A'),
1035 (KeyCode::ApplicationDownArrow, b'B'),
1036 (KeyCode::ApplicationRightArrow, b'C'),
1037 (KeyCode::ApplicationLeftArrow, b'D'),
1038 ] {
1039 let app = [0x1b, b'O', *dir];
1041 map.insert(
1042 &app,
1043 InputEvent::Key(KeyEvent {
1044 key: *keycode,
1045 modifiers: Modifiers::NONE,
1046 }),
1047 );
1048 for (suffix, modifiers) in modifier_combos {
1049 let key = format!("\x1bO1{}{}", suffix, *dir as char);
1050 map.insert(
1051 key,
1052 InputEvent::Key(KeyEvent {
1053 key: *keycode,
1054 modifiers: *modifiers,
1055 }),
1056 );
1057 }
1058 }
1059
1060 for (keycode, c) in &[
1062 (KeyCode::Function(1), b'P'),
1063 (KeyCode::Function(2), b'Q'),
1064 (KeyCode::Function(3), b'R'),
1065 (KeyCode::Function(4), b'S'),
1066 ] {
1067 let key = [0x1b, b'O', *c];
1068 map.insert(
1069 &key,
1070 InputEvent::Key(KeyEvent {
1071 key: *keycode,
1072 modifiers: Modifiers::NONE,
1073 }),
1074 );
1075 }
1076
1077 for (keycode, c) in &[
1079 (KeyCode::Function(1), b'P'),
1080 (KeyCode::Function(2), b'Q'),
1081 (KeyCode::Function(3), b'R'),
1082 (KeyCode::Function(4), b'S'),
1083 ] {
1084 for (suffix, modifiers) in modifier_combos_including_meta() {
1085 let key = format!("\x1b[1{suffix}{code}", code = *c as char, suffix = suffix);
1086 map.insert(
1087 key,
1088 InputEvent::Key(KeyEvent {
1089 key: *keycode,
1090 modifiers: *modifiers,
1091 }),
1092 );
1093 }
1094 }
1095
1096 for (range, offset) in &[
1099 (1..=5, 10),
1101 (6..=10, 11),
1103 (11..=14, 12),
1105 (15..=16, 13),
1107 (17..=20, 14),
1109 ] {
1110 for n in range.clone() {
1111 for (suffix, modifiers) in modifier_combos_including_meta() {
1112 let key = format!("\x1b[{code}{suffix}~", code = n + offset, suffix = suffix);
1113 map.insert(
1114 key,
1115 InputEvent::Key(KeyEvent {
1116 key: KeyCode::Function(n),
1117 modifiers: *modifiers,
1118 }),
1119 );
1120 }
1121 }
1122 }
1123
1124 for (keycode, c) in &[
1125 (KeyCode::Insert, b'2'),
1126 (KeyCode::Delete, b'3'),
1127 (KeyCode::Home, b'1'),
1128 (KeyCode::End, b'4'),
1129 (KeyCode::PageUp, b'5'),
1130 (KeyCode::PageDown, b'6'),
1131 (KeyCode::Home, b'7'),
1133 (KeyCode::End, b'8'),
1134 ] {
1135 for (suffix, modifiers) in &[
1136 (b'~', Modifiers::NONE),
1137 (b'$', Modifiers::SHIFT),
1138 (b'^', Modifiers::CTRL),
1139 (b'@', Modifiers::SHIFT | Modifiers::CTRL),
1140 ] {
1141 let key = [0x1b, b'[', *c, *suffix];
1142 map.insert(
1143 key,
1144 InputEvent::Key(KeyEvent {
1145 key: *keycode,
1146 modifiers: *modifiers,
1147 }),
1148 );
1149 }
1150 }
1151
1152 map.insert(
1153 &[0x7f],
1154 InputEvent::Key(KeyEvent {
1155 key: KeyCode::Backspace,
1156 modifiers: Modifiers::NONE,
1157 }),
1158 );
1159
1160 map.insert(
1161 &[0x8],
1162 InputEvent::Key(KeyEvent {
1163 key: KeyCode::Backspace,
1164 modifiers: Modifiers::NONE,
1165 }),
1166 );
1167
1168 map.insert(
1169 &[0x1b],
1170 InputEvent::Key(KeyEvent {
1171 key: KeyCode::Escape,
1172 modifiers: Modifiers::NONE,
1173 }),
1174 );
1175
1176 map.insert(
1177 &[b'\t'],
1178 InputEvent::Key(KeyEvent {
1179 key: KeyCode::Tab,
1180 modifiers: Modifiers::NONE,
1181 }),
1182 );
1183 map.insert(
1184 b"\x1b[Z",
1185 InputEvent::Key(KeyEvent {
1186 key: KeyCode::Tab,
1187 modifiers: Modifiers::SHIFT,
1188 }),
1189 );
1190
1191 map.insert(
1192 &[b'\r'],
1193 InputEvent::Key(KeyEvent {
1194 key: KeyCode::Enter,
1195 modifiers: Modifiers::NONE,
1196 }),
1197 );
1198 map.insert(
1199 &[b'\n'],
1200 InputEvent::Key(KeyEvent {
1201 key: KeyCode::Enter,
1202 modifiers: Modifiers::NONE,
1203 }),
1204 );
1205
1206 map.insert(
1207 b"\x1b[200~",
1208 InputEvent::Key(KeyEvent {
1209 key: KeyCode::InternalPasteStart,
1210 modifiers: Modifiers::NONE,
1211 }),
1212 );
1213 map.insert(
1214 b"\x1b[201~",
1215 InputEvent::Key(KeyEvent {
1216 key: KeyCode::InternalPasteEnd,
1217 modifiers: Modifiers::NONE,
1218 }),
1219 );
1220 map.insert(
1221 b"\x1b[",
1222 InputEvent::Key(KeyEvent {
1223 key: KeyCode::Char('['),
1224 modifiers: Modifiers::ALT,
1225 }),
1226 );
1227
1228 map
1229 }
1230
1231 fn first_char_and_len(s: &str) -> (char, usize) {
1234 let mut iter = s.chars();
1235 let c = iter.next().unwrap();
1236 (c, c.len_utf8())
1237 }
1238
1239 fn decode_one_char(bytes: &[u8]) -> Option<(char, usize)> {
1242 let bytes = &bytes[..bytes.len().min(4)];
1248 match std::str::from_utf8(bytes) {
1249 Ok(s) => {
1250 let (c, len) = Self::first_char_and_len(s);
1251 Some((c, len))
1252 }
1253 Err(err) => {
1254 let (valid, _after_valid) = bytes.split_at(err.valid_up_to());
1255 if !valid.is_empty() {
1256 let s = unsafe { std::str::from_utf8_unchecked(valid) };
1257 let (c, len) = Self::first_char_and_len(s);
1258 Some((c, len))
1259 } else {
1260 None
1261 }
1262 }
1263 }
1264 }
1265
1266 fn dispatch_callback<F: FnMut(InputEvent)>(&mut self, mut callback: F, event: InputEvent) {
1267 match (self.state, event) {
1268 (
1269 InputState::Normal,
1270 InputEvent::Key(KeyEvent {
1271 key: KeyCode::InternalPasteStart,
1272 ..
1273 }),
1274 ) => {
1275 self.state = InputState::Pasting(0);
1276 }
1277 (
1278 InputState::EscapeMaybeAlt,
1279 InputEvent::Key(KeyEvent {
1280 key: KeyCode::InternalPasteStart,
1281 ..
1282 }),
1283 ) => {
1284 callback(InputEvent::Key(KeyEvent {
1287 key: KeyCode::Escape,
1288 modifiers: Modifiers::NONE,
1289 }));
1290 self.state = InputState::Pasting(0);
1291 }
1292 (InputState::EscapeMaybeAlt, InputEvent::Key(KeyEvent { key, modifiers })) => {
1293 self.state = InputState::Normal;
1295 callback(InputEvent::Key(KeyEvent {
1296 key,
1297 modifiers: modifiers | Modifiers::ALT,
1298 }));
1299 }
1300 (InputState::EscapeMaybeAlt, event) => {
1301 callback(InputEvent::Key(KeyEvent {
1304 key: KeyCode::Escape,
1305 modifiers: Modifiers::NONE,
1306 }));
1307 callback(event);
1308 }
1309 (_, event) => callback(event),
1310 }
1311 }
1312
1313 fn process_bytes<F: FnMut(InputEvent)>(&mut self, mut callback: F, maybe_more: bool) {
1314 while !self.buf.is_empty() {
1315 match self.state {
1316 InputState::Pasting(offset) => {
1317 let end_paste = b"\x1b[201~";
1318 if let Some(idx) = self.buf.find_subsequence(offset, end_paste) {
1319 let pasted =
1320 String::from_utf8_lossy(&self.buf.as_slice()[0..idx]).to_string();
1321 self.buf.advance(pasted.len() + end_paste.len());
1322 callback(InputEvent::Paste(pasted));
1323 self.state = InputState::Normal;
1324 } else {
1325 self.state =
1332 InputState::Pasting(self.buf.len().saturating_sub(end_paste.len()));
1333 return;
1334 }
1335 }
1336 InputState::EscapeMaybeAlt | InputState::Normal => {
1337 if self.state == InputState::Normal && self.buf.as_slice()[0] == b'\x1b' {
1338 let mut parser = Parser::new();
1343 if let Some((Action::CSI(CSI::Mouse(mouse)), len)) =
1344 parser.parse_first(self.buf.as_slice())
1345 {
1346 self.buf.advance(len);
1347
1348 match mouse {
1349 MouseReport::SGR1006 {
1350 x,
1351 y,
1352 button,
1353 modifiers,
1354 } => {
1355 callback(InputEvent::Mouse(MouseEvent {
1356 x,
1357 y,
1358 mouse_buttons: button.into(),
1359 modifiers,
1360 }));
1361 }
1362 MouseReport::SGR1016 {
1363 x_pixels,
1364 y_pixels,
1365 button,
1366 modifiers,
1367 } => {
1368 callback(InputEvent::PixelMouse(PixelMouseEvent {
1369 x_pixels: x_pixels,
1370 y_pixels: y_pixels,
1371 mouse_buttons: button.into(),
1372 modifiers,
1373 }));
1374 }
1375 }
1376 continue;
1377 }
1378 }
1379
1380 match (
1381 self.key_map.lookup(self.buf.as_slice(), maybe_more),
1382 maybe_more,
1383 ) {
1384 (
1390 Found::Exact(
1391 len,
1392 InputEvent::Key(KeyEvent {
1393 key: KeyCode::Escape,
1394 modifiers: Modifiers::NONE,
1395 }),
1396 ),
1397 _,
1398 ) if self.state == InputState::Normal && self.buf.len() > len => {
1399 self.state = InputState::EscapeMaybeAlt;
1400 self.buf.advance(len);
1401 }
1402 (Found::Exact(len, event), _) | (Found::Ambiguous(len, event), false) => {
1403 self.dispatch_callback(&mut callback, event.clone());
1404 self.buf.advance(len);
1405 }
1406 (Found::Ambiguous(_, _), true) | (Found::NeedData, true) => {
1407 return;
1408 }
1409 (Found::None, _) | (Found::NeedData, false) => {
1410 if let Some((c, len)) = Self::decode_one_char(self.buf.as_slice()) {
1412 self.buf.advance(len);
1413 self.dispatch_callback(
1414 &mut callback,
1415 InputEvent::Key(KeyEvent {
1416 key: KeyCode::Char(c),
1417 modifiers: Modifiers::NONE,
1418 }),
1419 );
1420 } else {
1421 return;
1424 }
1425 }
1426 }
1427 }
1428 }
1429 }
1430 }
1431
1432 pub fn parse<F: FnMut(InputEvent)>(&mut self, bytes: &[u8], callback: F, maybe_more: bool) {
1447 self.buf.extend_with(bytes);
1448 self.process_bytes(callback, maybe_more);
1449 }
1450
1451 pub fn parse_as_vec(&mut self, bytes: &[u8], maybe_more: bool) -> Vec<InputEvent> {
1452 let mut result = Vec::new();
1453 self.parse(bytes, |event| result.push(event), maybe_more);
1454 result
1455 }
1456
1457 #[cfg(windows)]
1458 pub fn decode_input_records_as_vec(&mut self, records: &[INPUT_RECORD]) -> Vec<InputEvent> {
1459 let mut result = Vec::new();
1460 self.decode_input_records(records, &mut |event| result.push(event));
1461 result
1462 }
1463}
1464
1465#[cfg(test)]
1466mod test {
1467 use super::*;
1468
1469 const NO_MORE: bool = false;
1470 const MAYBE_MORE: bool = true;
1471
1472 #[test]
1473 fn simple() {
1474 let mut p = InputParser::new();
1475 let inputs = p.parse_as_vec(b"hello", NO_MORE);
1476 assert_eq!(
1477 vec![
1478 InputEvent::Key(KeyEvent {
1479 modifiers: Modifiers::NONE,
1480 key: KeyCode::Char('h'),
1481 }),
1482 InputEvent::Key(KeyEvent {
1483 modifiers: Modifiers::NONE,
1484 key: KeyCode::Char('e'),
1485 }),
1486 InputEvent::Key(KeyEvent {
1487 modifiers: Modifiers::NONE,
1488 key: KeyCode::Char('l'),
1489 }),
1490 InputEvent::Key(KeyEvent {
1491 modifiers: Modifiers::NONE,
1492 key: KeyCode::Char('l'),
1493 }),
1494 InputEvent::Key(KeyEvent {
1495 modifiers: Modifiers::NONE,
1496 key: KeyCode::Char('o'),
1497 }),
1498 ],
1499 inputs
1500 );
1501 }
1502
1503 #[test]
1504 fn control_characters() {
1505 let mut p = InputParser::new();
1506 let inputs = p.parse_as_vec(b"\x03\x1bJ\x7f", NO_MORE);
1507 assert_eq!(
1508 vec![
1509 InputEvent::Key(KeyEvent {
1510 modifiers: Modifiers::CTRL,
1511 key: KeyCode::Char('c'),
1512 }),
1513 InputEvent::Key(KeyEvent {
1514 modifiers: Modifiers::ALT,
1515 key: KeyCode::Char('J'),
1516 }),
1517 InputEvent::Key(KeyEvent {
1518 modifiers: Modifiers::NONE,
1519 key: KeyCode::Backspace,
1520 }),
1521 ],
1522 inputs
1523 );
1524 }
1525
1526 #[test]
1527 fn arrow_keys() {
1528 let mut p = InputParser::new();
1529 let inputs = p.parse_as_vec(b"\x1bOA\x1bOB\x1bOC\x1bOD", NO_MORE);
1530 assert_eq!(
1531 vec![
1532 InputEvent::Key(KeyEvent {
1533 modifiers: Modifiers::NONE,
1534 key: KeyCode::ApplicationUpArrow,
1535 }),
1536 InputEvent::Key(KeyEvent {
1537 modifiers: Modifiers::NONE,
1538 key: KeyCode::ApplicationDownArrow,
1539 }),
1540 InputEvent::Key(KeyEvent {
1541 modifiers: Modifiers::NONE,
1542 key: KeyCode::ApplicationRightArrow,
1543 }),
1544 InputEvent::Key(KeyEvent {
1545 modifiers: Modifiers::NONE,
1546 key: KeyCode::ApplicationLeftArrow,
1547 }),
1548 ],
1549 inputs
1550 );
1551 }
1552
1553 #[test]
1554 fn partial() {
1555 let mut p = InputParser::new();
1556 let mut inputs = Vec::new();
1557 p.parse(b"\x1b[11", |evt| inputs.push(evt), true);
1559 p.parse(b"~", |evt| inputs.push(evt), true);
1560 assert_eq!(
1562 vec![InputEvent::Key(KeyEvent {
1563 modifiers: Modifiers::NONE,
1564 key: KeyCode::Function(1),
1565 })],
1566 inputs
1567 );
1568 }
1569
1570 #[test]
1571 fn partial_ambig() {
1572 let mut p = InputParser::new();
1573
1574 assert_eq!(
1575 vec![InputEvent::Key(KeyEvent {
1576 key: KeyCode::Escape,
1577 modifiers: Modifiers::NONE,
1578 })],
1579 p.parse_as_vec(b"\x1b", false)
1580 );
1581
1582 let mut inputs = Vec::new();
1583 p.parse(b"\x1b[11", |evt| inputs.push(evt), MAYBE_MORE);
1585 p.parse(b"", |evt| inputs.push(evt), NO_MORE);
1586 assert_eq!(
1589 vec![
1590 InputEvent::Key(KeyEvent {
1591 modifiers: Modifiers::ALT,
1592 key: KeyCode::Char('['),
1593 }),
1594 InputEvent::Key(KeyEvent {
1595 modifiers: Modifiers::NONE,
1596 key: KeyCode::Char('1'),
1597 }),
1598 InputEvent::Key(KeyEvent {
1599 modifiers: Modifiers::NONE,
1600 key: KeyCode::Char('1'),
1601 }),
1602 ],
1603 inputs
1604 );
1605 }
1606
1607 #[test]
1608 fn alt_left_bracket() {
1609 let mut p = InputParser::new();
1612
1613 let mut inputs = Vec::new();
1614 p.parse(b"\x1b[", |evt| inputs.push(evt), false);
1615
1616 assert_eq!(
1617 vec![InputEvent::Key(KeyEvent {
1618 modifiers: Modifiers::ALT,
1619 key: KeyCode::Char('['),
1620 }),],
1621 inputs
1622 );
1623 }
1624
1625 #[test]
1626 fn modify_other_keys_parse() {
1627 let mut p = InputParser::new();
1628 let inputs = p.parse_as_vec(
1629 b"\x1b[27;5;13~\x1b[27;5;9~\x1b[27;6;8~\x1b[27;2;127~\x1b[27;6;27~",
1630 NO_MORE,
1631 );
1632 assert_eq!(
1633 vec![
1634 InputEvent::Key(KeyEvent {
1635 key: KeyCode::Enter,
1636 modifiers: Modifiers::CTRL,
1637 }),
1638 InputEvent::Key(KeyEvent {
1639 key: KeyCode::Tab,
1640 modifiers: Modifiers::CTRL,
1641 }),
1642 InputEvent::Key(KeyEvent {
1643 key: KeyCode::Backspace,
1644 modifiers: Modifiers::CTRL | Modifiers::SHIFT,
1645 }),
1646 InputEvent::Key(KeyEvent {
1647 key: KeyCode::Backspace,
1648 modifiers: Modifiers::SHIFT,
1649 }),
1650 InputEvent::Key(KeyEvent {
1651 key: KeyCode::Escape,
1652 modifiers: Modifiers::CTRL | Modifiers::SHIFT,
1653 }),
1654 ],
1655 inputs
1656 );
1657 }
1658
1659 #[test]
1660 fn modify_other_keys_encode() {
1661 let mode = KeyCodeEncodeModes {
1662 encoding: KeyboardEncoding::Xterm,
1663 newline_mode: false,
1664 application_cursor_keys: false,
1665 modify_other_keys: None,
1666 };
1667 let mode_1 = KeyCodeEncodeModes {
1668 encoding: KeyboardEncoding::Xterm,
1669 newline_mode: false,
1670 application_cursor_keys: false,
1671 modify_other_keys: Some(1),
1672 };
1673 let mode_2 = KeyCodeEncodeModes {
1674 encoding: KeyboardEncoding::Xterm,
1675 newline_mode: false,
1676 application_cursor_keys: false,
1677 modify_other_keys: Some(2),
1678 };
1679
1680 assert_eq!(
1681 KeyCode::Enter.encode(Modifiers::CTRL, mode, true).unwrap(),
1682 "\r".to_string()
1683 );
1684 assert_eq!(
1685 KeyCode::Enter
1686 .encode(Modifiers::CTRL, mode_1, true)
1687 .unwrap(),
1688 "\x1b[27;5;13~".to_string()
1689 );
1690 assert_eq!(
1691 KeyCode::Enter
1692 .encode(Modifiers::CTRL | Modifiers::SHIFT, mode_1, true)
1693 .unwrap(),
1694 "\x1b[27;6;13~".to_string()
1695 );
1696
1697 assert_eq!(
1701 KeyCode::Tab.encode(Modifiers::CTRL, mode, true).unwrap(),
1702 "\x1b[9;5u".to_string()
1703 );
1704 assert_eq!(
1705 KeyCode::Tab.encode(Modifiers::CTRL, mode_1, true).unwrap(),
1706 "\x1b[27;5;9~".to_string()
1707 );
1708 assert_eq!(
1709 KeyCode::Tab
1710 .encode(Modifiers::CTRL | Modifiers::SHIFT, mode_1, true)
1711 .unwrap(),
1712 "\x1b[27;6;9~".to_string()
1713 );
1714
1715 assert_eq!(
1716 KeyCode::Char('c')
1717 .encode(Modifiers::CTRL, mode, true)
1718 .unwrap(),
1719 "\x03".to_string()
1720 );
1721 assert_eq!(
1722 KeyCode::Char('c')
1723 .encode(Modifiers::CTRL, mode_1, true)
1724 .unwrap(),
1725 "\x03".to_string()
1726 );
1727 assert_eq!(
1728 KeyCode::Char('c')
1729 .encode(Modifiers::CTRL, mode_2, true)
1730 .unwrap(),
1731 "\x1b[27;5;99~".to_string()
1732 );
1733
1734 assert_eq!(
1735 KeyCode::Char('1')
1736 .encode(Modifiers::CTRL, mode, true)
1737 .unwrap(),
1738 "1".to_string()
1739 );
1740 assert_eq!(
1741 KeyCode::Char('1')
1742 .encode(Modifiers::CTRL, mode_2, true)
1743 .unwrap(),
1744 "\x1b[27;5;49~".to_string()
1745 );
1746
1747 assert_eq!(
1748 KeyCode::Char(',')
1749 .encode(Modifiers::CTRL, mode, true)
1750 .unwrap(),
1751 ",".to_string()
1752 );
1753 assert_eq!(
1754 KeyCode::Char(',')
1755 .encode(Modifiers::CTRL, mode_2, true)
1756 .unwrap(),
1757 "\x1b[27;5;44~".to_string()
1758 );
1759 }
1760
1761 #[test]
1762 fn encode_issue_892() {
1763 let mode = KeyCodeEncodeModes {
1764 encoding: KeyboardEncoding::Xterm,
1765 newline_mode: false,
1766 application_cursor_keys: false,
1767 modify_other_keys: None,
1768 };
1769
1770 assert_eq!(
1771 KeyCode::LeftArrow
1772 .encode(Modifiers::NONE, mode, true)
1773 .unwrap(),
1774 "\x1b[D".to_string()
1775 );
1776 assert_eq!(
1777 KeyCode::LeftArrow
1778 .encode(Modifiers::ALT, mode, true)
1779 .unwrap(),
1780 "\x1b[1;3D".to_string()
1781 );
1782 assert_eq!(
1783 KeyCode::Home.encode(Modifiers::NONE, mode, true).unwrap(),
1784 "\x1b[H".to_string()
1785 );
1786 assert_eq!(
1787 KeyCode::Home.encode(Modifiers::ALT, mode, true).unwrap(),
1788 "\x1b[1;3H".to_string()
1789 );
1790 assert_eq!(
1791 KeyCode::End.encode(Modifiers::NONE, mode, true).unwrap(),
1792 "\x1b[F".to_string()
1793 );
1794 assert_eq!(
1795 KeyCode::End.encode(Modifiers::ALT, mode, true).unwrap(),
1796 "\x1b[1;3F".to_string()
1797 );
1798 assert_eq!(
1799 KeyCode::Tab.encode(Modifiers::ALT, mode, true).unwrap(),
1800 "\x1b\t".to_string()
1801 );
1802 assert_eq!(
1803 KeyCode::PageUp.encode(Modifiers::ALT, mode, true).unwrap(),
1804 "\x1b[5;3~".to_string()
1805 );
1806 assert_eq!(
1807 KeyCode::Function(1)
1808 .encode(Modifiers::NONE, mode, true)
1809 .unwrap(),
1810 "\x1bOP".to_string()
1811 );
1812 }
1813
1814 #[test]
1815 fn partial_bracketed_paste() {
1816 let mut p = InputParser::new();
1817
1818 let input = b"\x1b[200~1234";
1819 let input2 = b"5678\x1b[201~";
1820
1821 let mut inputs = vec![];
1822
1823 p.parse(input, |e| inputs.push(e), false);
1824 p.parse(input2, |e| inputs.push(e), false);
1825
1826 assert_eq!(vec![InputEvent::Paste("12345678".to_owned())], inputs)
1827 }
1828
1829 #[test]
1830 fn mouse_horizontal_scroll() {
1831 let mut p = InputParser::new();
1832
1833 let input = b"\x1b[<66;42;12M\x1b[<67;42;12M";
1834 let res = p.parse_as_vec(input, MAYBE_MORE);
1835
1836 assert_eq!(
1837 vec![
1838 InputEvent::Mouse(MouseEvent {
1839 x: 42,
1840 y: 12,
1841 mouse_buttons: MouseButtons::HORZ_WHEEL | MouseButtons::WHEEL_POSITIVE,
1842 modifiers: Modifiers::NONE,
1843 }),
1844 InputEvent::Mouse(MouseEvent {
1845 x: 42,
1846 y: 12,
1847 mouse_buttons: MouseButtons::HORZ_WHEEL,
1848 modifiers: Modifiers::NONE,
1849 })
1850 ],
1851 res
1852 );
1853 }
1854
1855 #[test]
1856 fn encode_issue_3478_xterm() {
1857 let mode = KeyCodeEncodeModes {
1858 encoding: KeyboardEncoding::Xterm,
1859 newline_mode: false,
1860 application_cursor_keys: false,
1861 modify_other_keys: None,
1862 };
1863
1864 assert_eq!(
1865 KeyCode::Numpad0
1866 .encode(Modifiers::NONE, mode, true)
1867 .unwrap(),
1868 "\u{1b}[2~".to_string()
1869 );
1870 assert_eq!(
1871 KeyCode::Numpad0
1872 .encode(Modifiers::SHIFT, mode, true)
1873 .unwrap(),
1874 "\u{1b}[2;2~".to_string()
1875 );
1876
1877 assert_eq!(
1878 KeyCode::Numpad1
1879 .encode(Modifiers::NONE, mode, true)
1880 .unwrap(),
1881 "\u{1b}[F".to_string()
1882 );
1883 assert_eq!(
1884 KeyCode::Numpad1
1885 .encode(Modifiers::NONE | Modifiers::SHIFT, mode, true)
1886 .unwrap(),
1887 "\u{1b}[1;2F".to_string()
1888 );
1889 }
1890
1891 #[test]
1892 fn encode_tab_with_modifiers() {
1893 let mode = KeyCodeEncodeModes {
1894 encoding: KeyboardEncoding::Xterm,
1895 newline_mode: false,
1896 application_cursor_keys: false,
1897 modify_other_keys: None,
1898 };
1899
1900 let mods_to_result = [
1901 (Modifiers::SHIFT, "\u{1b}[Z"),
1902 (Modifiers::SHIFT | Modifiers::LEFT_SHIFT, "\u{1b}[Z"),
1903 (Modifiers::SHIFT | Modifiers::RIGHT_SHIFT, "\u{1b}[Z"),
1904 (Modifiers::CTRL, "\u{1b}[9;5u"),
1905 (Modifiers::CTRL | Modifiers::LEFT_CTRL, "\u{1b}[9;5u"),
1906 (Modifiers::CTRL | Modifiers::RIGHT_CTRL, "\u{1b}[9;5u"),
1907 (
1908 Modifiers::SHIFT | Modifiers::CTRL | Modifiers::LEFT_CTRL | Modifiers::LEFT_SHIFT,
1909 "\u{1b}[1;5Z",
1910 ),
1911 ];
1912 for (mods, result) in mods_to_result {
1913 assert_eq!(
1914 KeyCode::Tab.encode(mods, mode, true).unwrap(),
1915 result,
1916 "{:?}",
1917 mods
1918 );
1919 }
1920 }
1921}