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