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