summaryrefslogtreecommitdiffstats
path: root/vendor/anes/src/parser/parsers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/anes/src/parser/parsers.rs')
-rw-r--r--vendor/anes/src/parser/parsers.rs239
1 files changed, 239 insertions, 0 deletions
diff --git a/vendor/anes/src/parser/parsers.rs b/vendor/anes/src/parser/parsers.rs
new file mode 100644
index 000000000..9bb9acb4f
--- /dev/null
+++ b/vendor/anes/src/parser/parsers.rs
@@ -0,0 +1,239 @@
+use super::types::{KeyCode, KeyModifiers, Mouse, MouseButton, Sequence};
+
+pub(crate) fn parse_char(ch: char, esc_o: bool) -> Option<Sequence> {
+ if esc_o {
+ return match ch {
+ 'P'..='S' => Some(Sequence::Key(
+ KeyCode::F(ch as u8 - b'P' + 1),
+ KeyModifiers::empty(),
+ )),
+ _ => None,
+ };
+ }
+
+ let code = match ch {
+ '\r' | '\n' => KeyCode::Enter,
+ '\t' => KeyCode::Tab,
+ '\x7F' => KeyCode::BackTab,
+ '\x1B' => KeyCode::Esc,
+ '\0' => KeyCode::Null,
+ _ => KeyCode::Char(ch),
+ };
+ Some(Sequence::Key(code, KeyModifiers::empty()))
+}
+
+pub(crate) fn parse_esc_sequence(ch: char) -> Option<Sequence> {
+ // EscO[P-S] is handled in the Performer, see parse_char & esc_o argument
+ // No need to handle other cases here? It's just Alt+$char
+ Some(Sequence::Key(KeyCode::Char(ch), KeyModifiers::ALT))
+}
+
+pub(crate) fn parse_csi_sequence(
+ parameters: &[u64],
+ _ignored_count: usize,
+ ch: char,
+) -> Option<Sequence> {
+ match ch {
+ 'A' => Some(Sequence::Key(
+ KeyCode::Up,
+ parse_csi_arrow_key_modifiers(parameters.first().cloned()),
+ )),
+ 'B' => Some(Sequence::Key(
+ KeyCode::Down,
+ parse_csi_arrow_key_modifiers(parameters.first().cloned()),
+ )),
+ 'C' => Some(Sequence::Key(
+ KeyCode::Right,
+ parse_csi_arrow_key_modifiers(parameters.first().cloned()),
+ )),
+ 'D' => Some(Sequence::Key(
+ KeyCode::Left,
+ parse_csi_arrow_key_modifiers(parameters.first().cloned()),
+ )),
+ 'H' => Some(Sequence::Key(KeyCode::Home, KeyModifiers::empty())),
+ 'F' => Some(Sequence::Key(KeyCode::End, KeyModifiers::empty())),
+ 'Z' => Some(Sequence::Key(KeyCode::BackTab, KeyModifiers::empty())),
+ 'R' => parse_csi_cursor_position(parameters),
+ 'm' => parse_csi_xterm_mouse(parameters, ch),
+ 'M' if parameters.first() == Some(&0x3C) => parse_csi_xterm_mouse(parameters, ch),
+ 'M' => parse_csi_rxvt_mouse(parameters),
+ '~' => parse_csi_tilde_key_code(parameters),
+ _ => None,
+ }
+}
+
+fn parse_csi_arrow_key_modifiers(parameter: Option<u64>) -> KeyModifiers {
+ parse_key_modifiers(parameter.map(|x| x.saturating_sub(48)))
+}
+
+fn parse_key_modifiers(parameter: Option<u64>) -> KeyModifiers {
+ if let Some(parameter) = parameter {
+ match parameter {
+ 2 => KeyModifiers::SHIFT,
+ 3 => KeyModifiers::ALT,
+ 4 => KeyModifiers::SHIFT | KeyModifiers::ALT,
+ 5 => KeyModifiers::CONTROL,
+ 6 => KeyModifiers::SHIFT | KeyModifiers::CONTROL,
+ 7 => KeyModifiers::ALT | KeyModifiers::CONTROL,
+ 8 => KeyModifiers::SHIFT | KeyModifiers::ALT | KeyModifiers::CONTROL,
+ 9 => KeyModifiers::META,
+ 10 => KeyModifiers::META | KeyModifiers::SHIFT,
+ 11 => KeyModifiers::META | KeyModifiers::ALT,
+ 12 => KeyModifiers::META | KeyModifiers::SHIFT | KeyModifiers::ALT,
+ 13 => KeyModifiers::META | KeyModifiers::CONTROL,
+ 14 => KeyModifiers::META | KeyModifiers::SHIFT | KeyModifiers::CONTROL,
+ 15 => KeyModifiers::META | KeyModifiers::ALT | KeyModifiers::CONTROL,
+ 16 => {
+ KeyModifiers::META | KeyModifiers::SHIFT | KeyModifiers::ALT | KeyModifiers::CONTROL
+ }
+ _ => KeyModifiers::empty(),
+ }
+ } else {
+ KeyModifiers::empty()
+ }
+}
+
+fn parse_csi_tilde_key_code(parameters: &[u64]) -> Option<Sequence> {
+ if parameters.is_empty() {
+ return None;
+ }
+
+ let modifiers = parse_key_modifiers(parameters.get(1).cloned());
+
+ let code = match parameters[0] {
+ 1 | 7 => KeyCode::Home,
+ 2 => KeyCode::Insert,
+ 3 => KeyCode::Delete,
+ 4 | 8 => KeyCode::End,
+ 5 => KeyCode::PageUp,
+ 6 => KeyCode::PageDown,
+ p @ 11..=15 => KeyCode::F(p as u8 - 10),
+ p @ 17..=21 => KeyCode::F(p as u8 - 11),
+ p @ 23..=24 => KeyCode::F(p as u8 - 12),
+ _ => return None,
+ };
+
+ Some(Sequence::Key(code, modifiers))
+}
+
+fn parse_csi_cursor_position(parameters: &[u64]) -> Option<Sequence> {
+ // ESC [ Cy ; Cx R
+
+ if parameters.len() < 2 {
+ return None;
+ }
+
+ let y = parameters[0] as u16;
+ let x = parameters[1] as u16;
+
+ Some(Sequence::CursorPosition(x, y))
+}
+
+fn parse_csi_xterm_mouse(parameters: &[u64], ch: char) -> Option<Sequence> {
+ // ESC [ < Cb ; Cx ; Cy (;) (M or m)
+
+ if parameters.len() < 4 {
+ return None;
+ }
+
+ let cb = parameters[1] as u8;
+ let cx = parameters[2] as u16;
+ let cy = parameters[3] as u16;
+
+ let up = match ch {
+ 'm' => true,
+ 'M' => false,
+ _ => return None,
+ };
+
+ let mut modifiers = KeyModifiers::empty();
+
+ if cb & 0b0000_0100 == 0b0000_0100 {
+ modifiers |= KeyModifiers::SHIFT;
+ }
+
+ if cb & 0b0000_1000 == 0b0000_1000 {
+ modifiers |= KeyModifiers::ALT;
+ }
+
+ if cb & 0b0001_0000 == 0b0001_0000 {
+ modifiers |= KeyModifiers::CONTROL;
+ }
+
+ let mouse = if cb & 0b0100_0000 == 0b0100_0000 {
+ if cb & 0b0000_0001 == 0b0000_0001 {
+ Mouse::ScrollDown(cx, cy)
+ } else {
+ Mouse::ScrollUp(cx, cy)
+ }
+ } else {
+ let drag = cb & 0b0010_0000 == 0b0010_0000;
+
+ match (cb & 0b0000_0011, up, drag) {
+ (0, true, _) => Mouse::Up(MouseButton::Left, cx, cy),
+ (0, false, false) => Mouse::Down(MouseButton::Left, cx, cy),
+ (0, false, true) => Mouse::Drag(MouseButton::Left, cx, cy),
+ (1, true, _) => Mouse::Up(MouseButton::Middle, cx, cy),
+ (1, false, false) => Mouse::Down(MouseButton::Middle, cx, cy),
+ (1, false, true) => Mouse::Drag(MouseButton::Middle, cx, cy),
+ (2, true, _) => Mouse::Up(MouseButton::Right, cx, cy),
+ (2, false, false) => Mouse::Down(MouseButton::Right, cx, cy),
+ (2, false, true) => Mouse::Drag(MouseButton::Right, cx, cy),
+ _ => return None,
+ }
+ };
+
+ Some(Sequence::Mouse(mouse, modifiers))
+}
+
+fn parse_csi_rxvt_mouse(parameters: &[u64]) -> Option<Sequence> {
+ // ESC [ Cb ; Cx ; Cy ; M
+
+ if parameters.len() < 3 {
+ return None;
+ }
+
+ let cb = parameters[0];
+ let cx = parameters[1] as u16;
+ let cy = parameters[2] as u16;
+
+ let mut modifiers = KeyModifiers::empty();
+
+ if cb & 0b0000_0100 == 0b0000_0100 {
+ modifiers |= KeyModifiers::SHIFT;
+ }
+
+ if cb & 0b0000_1000 == 0b0000_1000 {
+ modifiers |= KeyModifiers::ALT;
+ }
+
+ if cb & 0b0001_0000 == 0b0001_0000 {
+ modifiers |= KeyModifiers::CONTROL;
+ }
+
+ let mouse = if cb & 0b0110_0000 == 0b0110_0000 {
+ if cb & 0b0000_0001 == 0b0000_0001 {
+ Mouse::ScrollDown(cx, cy)
+ } else {
+ Mouse::ScrollUp(cx, cy)
+ }
+ } else {
+ let drag = cb & 0b0100_0000 == 0b0100_0000;
+
+ match (cb & 0b0000_0011, drag) {
+ (0b0000_0000, false) => Mouse::Down(MouseButton::Left, cx, cy),
+ (0b0000_0010, false) => Mouse::Down(MouseButton::Right, cx, cy),
+ (0b0000_0001, false) => Mouse::Down(MouseButton::Middle, cx, cy),
+
+ (0b0000_0000, true) => Mouse::Drag(MouseButton::Left, cx, cy),
+ (0b0000_0010, true) => Mouse::Drag(MouseButton::Right, cx, cy),
+ (0b0000_0001, true) => Mouse::Drag(MouseButton::Middle, cx, cy),
+
+ (0b0000_0011, false) => Mouse::Up(MouseButton::Any, cx, cy),
+
+ _ => return None,
+ }
+ };
+
+ Some(Sequence::Mouse(mouse, modifiers))
+}