1 use super::types::{KeyCode, KeyModifiers, Mouse, MouseButton, Sequence};
2 
parse_char(ch: char, esc_o: bool) -> Option<Sequence>3 pub(crate) fn parse_char(ch: char, esc_o: bool) -> Option<Sequence> {
4     if esc_o {
5         return match ch {
6             'P'..='S' => Some(Sequence::Key(
7                 KeyCode::F(ch as u8 - b'P' + 1),
8                 KeyModifiers::empty(),
9             )),
10             _ => None,
11         };
12     }
13 
14     let code = match ch {
15         '\r' | '\n' => KeyCode::Enter,
16         '\t' => KeyCode::Tab,
17         '\x7F' => KeyCode::BackTab,
18         '\x1B' => KeyCode::Esc,
19         '\0' => KeyCode::Null,
20         _ => KeyCode::Char(ch),
21     };
22     Some(Sequence::Key(code, KeyModifiers::empty()))
23 }
24 
parse_esc_sequence(ch: char) -> Option<Sequence>25 pub(crate) fn parse_esc_sequence(ch: char) -> Option<Sequence> {
26     // EscO[P-S] is handled in the Performer, see parse_char & esc_o argument
27     // No need to handle other cases here? It's just Alt+$char
28     Some(Sequence::Key(KeyCode::Char(ch), KeyModifiers::ALT))
29 }
30 
parse_csi_sequence( parameters: &[u64], _ignored_count: usize, ch: char, ) -> Option<Sequence>31 pub(crate) fn parse_csi_sequence(
32     parameters: &[u64],
33     _ignored_count: usize,
34     ch: char,
35 ) -> Option<Sequence> {
36     match ch {
37         'A' => Some(Sequence::Key(
38             KeyCode::Up,
39             parse_csi_arrow_key_modifiers(parameters.first().cloned()),
40         )),
41         'B' => Some(Sequence::Key(
42             KeyCode::Down,
43             parse_csi_arrow_key_modifiers(parameters.first().cloned()),
44         )),
45         'C' => Some(Sequence::Key(
46             KeyCode::Right,
47             parse_csi_arrow_key_modifiers(parameters.first().cloned()),
48         )),
49         'D' => Some(Sequence::Key(
50             KeyCode::Left,
51             parse_csi_arrow_key_modifiers(parameters.first().cloned()),
52         )),
53         'H' => Some(Sequence::Key(KeyCode::Home, KeyModifiers::empty())),
54         'F' => Some(Sequence::Key(KeyCode::End, KeyModifiers::empty())),
55         'Z' => Some(Sequence::Key(KeyCode::BackTab, KeyModifiers::empty())),
56         'R' => parse_csi_cursor_position(parameters),
57         'm' => parse_csi_xterm_mouse(parameters, ch),
58         'M' if parameters.first() == Some(&0x3C) => parse_csi_xterm_mouse(parameters, ch),
59         'M' => parse_csi_rxvt_mouse(parameters),
60         '~' => parse_csi_tilde_key_code(parameters),
61         _ => None,
62     }
63 }
64 
parse_csi_arrow_key_modifiers(parameter: Option<u64>) -> KeyModifiers65 fn parse_csi_arrow_key_modifiers(parameter: Option<u64>) -> KeyModifiers {
66     parse_key_modifiers(parameter.map(|x| x.saturating_sub(48)))
67 }
68 
parse_key_modifiers(parameter: Option<u64>) -> KeyModifiers69 fn parse_key_modifiers(parameter: Option<u64>) -> KeyModifiers {
70     if let Some(parameter) = parameter {
71         match parameter {
72             2 => KeyModifiers::SHIFT,
73             3 => KeyModifiers::ALT,
74             4 => KeyModifiers::SHIFT | KeyModifiers::ALT,
75             5 => KeyModifiers::CONTROL,
76             6 => KeyModifiers::SHIFT | KeyModifiers::CONTROL,
77             7 => KeyModifiers::ALT | KeyModifiers::CONTROL,
78             8 => KeyModifiers::SHIFT | KeyModifiers::ALT | KeyModifiers::CONTROL,
79             9 => KeyModifiers::META,
80             10 => KeyModifiers::META | KeyModifiers::SHIFT,
81             11 => KeyModifiers::META | KeyModifiers::ALT,
82             12 => KeyModifiers::META | KeyModifiers::SHIFT | KeyModifiers::ALT,
83             13 => KeyModifiers::META | KeyModifiers::CONTROL,
84             14 => KeyModifiers::META | KeyModifiers::SHIFT | KeyModifiers::CONTROL,
85             15 => KeyModifiers::META | KeyModifiers::ALT | KeyModifiers::CONTROL,
86             16 => {
87                 KeyModifiers::META | KeyModifiers::SHIFT | KeyModifiers::ALT | KeyModifiers::CONTROL
88             }
89             _ => KeyModifiers::empty(),
90         }
91     } else {
92         KeyModifiers::empty()
93     }
94 }
95 
parse_csi_tilde_key_code(parameters: &[u64]) -> Option<Sequence>96 fn parse_csi_tilde_key_code(parameters: &[u64]) -> Option<Sequence> {
97     if parameters.is_empty() {
98         return None;
99     }
100 
101     let modifiers = parse_key_modifiers(parameters.get(1).cloned());
102 
103     let code = match parameters[0] {
104         1 | 7 => KeyCode::Home,
105         2 => KeyCode::Insert,
106         3 => KeyCode::Delete,
107         4 | 8 => KeyCode::End,
108         5 => KeyCode::PageUp,
109         6 => KeyCode::PageDown,
110         p @ 11..=15 => KeyCode::F(p as u8 - 10),
111         p @ 17..=21 => KeyCode::F(p as u8 - 11),
112         p @ 23..=24 => KeyCode::F(p as u8 - 12),
113         _ => return None,
114     };
115 
116     Some(Sequence::Key(code, modifiers))
117 }
118 
parse_csi_cursor_position(parameters: &[u64]) -> Option<Sequence>119 fn parse_csi_cursor_position(parameters: &[u64]) -> Option<Sequence> {
120     // ESC [ Cy ; Cx R
121 
122     if parameters.len() < 2 {
123         return None;
124     }
125 
126     let y = parameters[0] as u16;
127     let x = parameters[1] as u16;
128 
129     Some(Sequence::CursorPosition(x, y))
130 }
131 
parse_csi_xterm_mouse(parameters: &[u64], ch: char) -> Option<Sequence>132 fn parse_csi_xterm_mouse(parameters: &[u64], ch: char) -> Option<Sequence> {
133     // ESC [ < Cb ; Cx ; Cy (;) (M or m)
134 
135     if parameters.len() < 4 {
136         return None;
137     }
138 
139     let cb = parameters[1] as u8;
140     let cx = parameters[2] as u16;
141     let cy = parameters[3] as u16;
142 
143     let up = match ch {
144         'm' => true,
145         'M' => false,
146         _ => return None,
147     };
148 
149     let mut modifiers = KeyModifiers::empty();
150 
151     if cb & 0b0000_0100 == 0b0000_0100 {
152         modifiers |= KeyModifiers::SHIFT;
153     }
154 
155     if cb & 0b0000_1000 == 0b0000_1000 {
156         modifiers |= KeyModifiers::ALT;
157     }
158 
159     if cb & 0b0001_0000 == 0b0001_0000 {
160         modifiers |= KeyModifiers::CONTROL;
161     }
162 
163     let mouse = if cb & 0b0100_0000 == 0b0100_0000 {
164         if cb & 0b0000_0001 == 0b0000_0001 {
165             Mouse::ScrollDown(cx, cy)
166         } else {
167             Mouse::ScrollUp(cx, cy)
168         }
169     } else {
170         let drag = cb & 0b0010_0000 == 0b0010_0000;
171 
172         match (cb & 0b0000_0011, up, drag) {
173             (0, true, _) => Mouse::Up(MouseButton::Left, cx, cy),
174             (0, false, false) => Mouse::Down(MouseButton::Left, cx, cy),
175             (0, false, true) => Mouse::Drag(MouseButton::Left, cx, cy),
176             (1, true, _) => Mouse::Up(MouseButton::Middle, cx, cy),
177             (1, false, false) => Mouse::Down(MouseButton::Middle, cx, cy),
178             (1, false, true) => Mouse::Drag(MouseButton::Middle, cx, cy),
179             (2, true, _) => Mouse::Up(MouseButton::Right, cx, cy),
180             (2, false, false) => Mouse::Down(MouseButton::Right, cx, cy),
181             (2, false, true) => Mouse::Drag(MouseButton::Right, cx, cy),
182             _ => return None,
183         }
184     };
185 
186     Some(Sequence::Mouse(mouse, modifiers))
187 }
188 
parse_csi_rxvt_mouse(parameters: &[u64]) -> Option<Sequence>189 fn parse_csi_rxvt_mouse(parameters: &[u64]) -> Option<Sequence> {
190     // ESC [ Cb ; Cx ; Cy ; M
191 
192     if parameters.len() < 3 {
193         return None;
194     }
195 
196     let cb = parameters[0];
197     let cx = parameters[1] as u16;
198     let cy = parameters[2] as u16;
199 
200     let mut modifiers = KeyModifiers::empty();
201 
202     if cb & 0b0000_0100 == 0b0000_0100 {
203         modifiers |= KeyModifiers::SHIFT;
204     }
205 
206     if cb & 0b0000_1000 == 0b0000_1000 {
207         modifiers |= KeyModifiers::ALT;
208     }
209 
210     if cb & 0b0001_0000 == 0b0001_0000 {
211         modifiers |= KeyModifiers::CONTROL;
212     }
213 
214     let mouse = if cb & 0b0110_0000 == 0b0110_0000 {
215         if cb & 0b0000_0001 == 0b0000_0001 {
216             Mouse::ScrollDown(cx, cy)
217         } else {
218             Mouse::ScrollUp(cx, cy)
219         }
220     } else {
221         let drag = cb & 0b0100_0000 == 0b0100_0000;
222 
223         match (cb & 0b0000_0011, drag) {
224             (0b0000_0000, false) => Mouse::Down(MouseButton::Left, cx, cy),
225             (0b0000_0010, false) => Mouse::Down(MouseButton::Right, cx, cy),
226             (0b0000_0001, false) => Mouse::Down(MouseButton::Middle, cx, cy),
227 
228             (0b0000_0000, true) => Mouse::Drag(MouseButton::Left, cx, cy),
229             (0b0000_0010, true) => Mouse::Drag(MouseButton::Right, cx, cy),
230             (0b0000_0001, true) => Mouse::Drag(MouseButton::Middle, cx, cy),
231 
232             (0b0000_0011, false) => Mouse::Up(MouseButton::Any, cx, cy),
233 
234             _ => return None,
235         }
236     };
237 
238     Some(Sequence::Mouse(mouse, modifiers))
239 }
240