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