Skip to main content

tattoy_termwiz/
input.rs

1//! This module provides an InputParser struct to help with parsing
2//! input received from a terminal.
3use 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    /// <http://www.leonerd.org.uk/hacks/fixterms/>
24    CsiU,
25    /// <https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md>
26    Win32,
27    /// <https://sw.kovidgoyal.net/kitty/keyboard-protocol/>
28    Kitty(KittyKeyboardFlags),
29}
30
31/// Specifies terminal modes/configuration that can influence how a KeyCode
32/// is encoded when being sent to and application via the pty.
33#[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    /// Detected that the user has resized the terminal
55    Resized {
56        cols: usize,
57        rows: usize,
58    },
59    /// For terminals that support Bracketed Paste mode,
60    /// pastes are collected and reported as this variant.
61    Paste(String),
62    /// The program has woken the input thread.
63    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    /// Which key was pressed
88    pub key: KeyCode,
89
90    /// Which modifiers are down
91    pub modifiers: Modifiers,
92}
93
94/// Which key is pressed.  Not all of these are probable to appear
95/// on most systems.  A lot of this list is @wez trawling docs and
96/// making an entry for things that might be possible in this first pass.
97#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
98#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
99pub enum KeyCode {
100    /// The decoded unicode character
101    Char(char),
102
103    Hyper,
104    Super,
105    Meta,
106
107    /// Ctrl-break on windows
108    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    /// F1-F24 are possible
164    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    /// if SHIFT is held and we have KeyCode::Char('c') we want to normalize
202    /// that keycode to KeyCode::Char('C'); that is what this function does.
203    /// In theory we should give the same treatment to keys like `[` -> `{`
204    /// but that assumes something about the keyboard layout and is probably
205    /// better done in the gui frontend rather than this layer.
206    /// In fact, this function might be better off if it lived elsewhere.
207    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    /// Return true if the key represents a modifier key.
219    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    /// Returns the byte sequence that represents this KeyCode and Modifier combination,
240    pub fn encode(
241        &self,
242        mods: Modifiers,
243        modes: KeyCodeEncodeModes,
244        is_down: bool,
245    ) -> Result<String> {
246        if !is_down {
247            // We only want down events
248            return Ok(String::new());
249        }
250        // We are encoding the key as an xterm-compatible sequence, which does not support
251        // positional modifiers.
252        let mods = mods.remove_positional_mods();
253
254        use KeyCode::*;
255
256        let key = self.normalize_shift_to_upper_case(mods);
257        // Normalize the modifier state for Char's that are uppercase; remove
258        // the SHIFT modifier so that reduce ambiguity below
259        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        // Normalize Backspace and Delete
270        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        // TODO: also respect self.application_keypad
279
280        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            // When alt is pressed, send escape first to indicate to the peer that
304            // ALT is pressed.  We do this only for ascii alnum characters because
305            // eg: on macOS generates altgr style glyphs and keeps the ALT key
306            // in the modifier set.  This confuses eg: zsh which then just displays
307            // <fffffffff> as the input, so we want to avoid that.
308            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                // Backspace sends the default VERASE which is confusingly
318                // the DEL ascii codepoint rather than BS.
319                // We only send BS when CTRL is held.
320                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                        // Strict reading of DECCKM suggests that application_cursor_keys
409                        // only applies when DECANM and DECKPAM are active, but that seems
410                        // to break unmodified cursor keys in vim
411                        /* && self.dec_ansi_mode && self.application_keypad */
412                    ) {
413                    // Use SS3 in application mode
414                    SS3
415                } else {
416                    // otherwise use regular CSI
417                    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                    // F1-F4 are encoded using SS3 if there are no modifiers
452                    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                    // Special case for F1-F4 with modifiers
465                    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                    // Higher numbered F-keys using CSI instead of SS3.
475                    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                        // If no modifiers are held, don't send the modifier
505                        // sequence, as the modifier encoding is a CSI-u extension.
506                        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                    // If no modifiers are held, don't send the modifier
525                    // sequence, as the modifier encoding is a CSI-u extension.
526                    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                    // If no modifiers are held, don't send the modifier
547                    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            // Modifier keys pressed on their own don't expand to anything
556            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
570/// characters that when masked for CTRL could be an ascii control character
571/// or could be a key that a user legitimately wants to process in their
572/// terminal application
573fn 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    // <https://invisible-island.net/xterm/modified-keys.html>
596    match (c, modes.modify_other_keys) {
597        ('c' | 'd' | '\x1b' | '\x7f' | '\x08', Some(1)) => {
598            // Exclude well-known keys from modifyOtherKeys mode 1
599        }
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        // TODO: we could report caps lock, numlock and scrolllock
657
658        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            // TODO: do we want downs instead of ups?
667            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        // Meta is theoretically a distinct modifier of its own, but modern systems don't
904        // have a dedicated Meta key and use the Alt/Option key instead.  The mapping
905        // below is reproduced from the xterm documentation from a time where it was
906        // possible to hold both Alt and Meta down as modifiers.  Since we define meta to
907        // ALT, the use of `meta | ALT` in the table below appears to be redundant,
908        // but makes it easier to see that the mapping matches xterm when viewing
909        // its documentation.
910        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            // Ctrl-[A..=Z] are sent as 1..=26
930            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            // ALT A-Z is often sent with a leading ESC
940            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                // `CSI u` encodings for the ascii range;
953                // see http://www.leonerd.org.uk/hacks/fixterms/
954                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                    // xterm modifyOtherKeys sequences
965                    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        // Common arrow keys
984        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            // Arrow keys in normal mode encoded using CSI
993            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            // rxvt-specific modified arrows.
1019            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            // Arrow keys in application cursor mode encoded using SS3
1040            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        // Function keys 1-4 with no modifiers encoded using SS3
1061        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        // Function keys 1-4 with modifiers
1078        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        // Function keys with modifiers encoded using CSI.
1097        // http://aperiodic.net/phil/archives/Geekery/term-function-keys.html
1098        for (range, offset) in &[
1099            // F1-F5 encoded as 11-15
1100            (1..=5, 10),
1101            // F6-F10 encoded as 17-21
1102            (6..=10, 11),
1103            // F11-F14 encoded as 23-26
1104            (11..=14, 12),
1105            // F15-F16 encoded as 28-29
1106            (15..=16, 13),
1107            // F17-F20 encoded as 31-34
1108            (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            // rxvt
1132            (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    /// Returns the first char from a str and the length of that char
1232    /// in *bytes*.
1233    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    /// This is a horrible function to pull off the first unicode character
1240    /// from the sequence of bytes and return it and the remaining slice.
1241    fn decode_one_char(bytes: &[u8]) -> Option<(char, usize)> {
1242        // This has the potential to be an ugly hotspot since the complexity
1243        // is a function of the length of the entire buffer rather than the length
1244        // of the first char component.  A simple mitigation might be to slice off
1245        // the first 4 bytes.  We pick 4 bytes because the docs for str::len_utf8()
1246        // state that the maximum expansion for a `char` is 4 bytes.
1247        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                // The prior ESC was not part of an ALT sequence, so emit
1285                // it before we start collecting for paste.
1286                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                // Treat this as ALT-key
1294                self.state = InputState::Normal;
1295                callback(InputEvent::Key(KeyEvent {
1296                    key,
1297                    modifiers: modifiers | Modifiers::ALT,
1298                }));
1299            }
1300            (InputState::EscapeMaybeAlt, event) => {
1301                // The prior ESC was not part of an ALT sequence, so emit
1302                // both it and the current event
1303                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                        // Advance our offset so that in the case where we receive a paste that
1326                        // is spread across N reads of size 8K, we don't need to search for the
1327                        // end marker in 8K, 16K, 24K etc. of text until the final buffer is received.
1328                        // Ensure that we use saturating math here for the case where the amount
1329                        // of buffered data after the begin paste is smaller than the end paste marker
1330                        // <https://github.com/wezterm/wezterm/pull/1832>
1331                        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                        // This feels a bit gross because we have two different parsers at play
1339                        // here.  We want to re-use the escape sequence parser to crack the
1340                        // parameters out from things like mouse reports.  The keymap tree doesn't
1341                        // know how to grok this.
1342                        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                        // If we got an unambiguous ESC and we have more data to
1385                        // follow, then this is likely the Meta version of the
1386                        // following keypress.  Buffer up the escape key and
1387                        // consume it from the input.  dispatch_callback() will
1388                        // emit either the ESC or the ALT modified following key.
1389                        (
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                            // No pre-defined key, so pull out a unicode character
1411                            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                                // We need more data to recognize the input, so
1422                                // yield the remainder of the slice
1423                                return;
1424                            }
1425                        }
1426                    }
1427                }
1428            }
1429        }
1430    }
1431
1432    /// Push a sequence of bytes into the parser.
1433    /// Each time input is recognized, the provided `callback` will be passed
1434    /// the decoded `InputEvent`.
1435    /// If not enough data are available to fully decode a sequence, the
1436    /// remaining data will be buffered until the next call.
1437    /// The `maybe_more` flag controls how ambiguous partial sequences are
1438    /// handled. The intent is that `maybe_more` should be set to true if
1439    /// you believe that you will be able to provide more data momentarily.
1440    /// This will cause the parser to defer judgement on partial prefix
1441    /// matches. You should attempt to read and pass the new data in
1442    /// immediately afterwards. If you have attempted a read and no data is
1443    /// immediately available, you should follow up with a call to parse
1444    /// with an empty slice and `maybe_more=false` to allow the partial
1445    /// data to be recognized and processed.
1446    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        // Fragment this F-key sequence across two different pushes
1558        p.parse(b"\x1b[11", |evt| inputs.push(evt), true);
1559        p.parse(b"~", |evt| inputs.push(evt), true);
1560        // make sure we recognize it as just the F-key
1561        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        // An incomplete F-key sequence fragmented across two different pushes
1584        p.parse(b"\x1b[11", |evt| inputs.push(evt), MAYBE_MORE);
1585        p.parse(b"", |evt| inputs.push(evt), NO_MORE);
1586        // since we finish with maybe_more false (NO_MORE), the results should be the longest matching
1587        // parts of said f-key sequence
1588        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        // tests that `Alt` + `[` is recognized as a single
1610        // event rather than two events (one `Esc` the second `Char('[')`)
1611        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        // This case is not conformant with xterm!
1698        // xterm just returns tab for CTRL-Tab when modify_other_keys
1699        // is not set.
1700        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}