strop_core/frontend_input/
notation.rs1use super::{KeyCode, KeyEvent, Modifiers};
5
6pub fn parse(text: &str) -> Keys<'_> {
7 Keys {
8 remaining: text,
9 literal_bytes: 0,
10 }
11}
12pub struct Keys<'a> {
13 remaining: &'a str,
14 literal_bytes: usize,
15}
16impl Iterator for Keys<'_> {
17 type Item = KeyEvent;
18 fn next(&mut self) -> Option<KeyEvent> {
19 let ch = self.remaining.chars().next()?;
20 if self.literal_bytes > 0 {
21 self.remaining = &self.remaining[ch.len_utf8()..];
22 self.literal_bytes -= ch.len_utf8();
23 return Some(KeyEvent::press(KeyCode::Char(ch)));
24 }
25 if ch == '<' {
26 if let Some(end) = self.remaining.find('>') {
27 if let Some(key) = token(&self.remaining[1..end]) {
28 self.remaining = &self.remaining[end + 1..];
29 return Some(key);
30 }
31 self.literal_bytes = end;
32 }
33 }
34 self.remaining = &self.remaining[ch.len_utf8()..];
35 Some(character(ch))
36 }
37}
38
39fn character(ch: char) -> KeyEvent {
40 let code = match ch {
41 '\x1b' => KeyCode::Escape,
42 '\r' | '\n' => KeyCode::Enter,
43 '\x7f' | '\x08' => KeyCode::Backspace,
44 '\t' => KeyCode::Tab,
45 '\0' => KeyCode::Null,
46 '\x01'..='\x1a' => {
47 let mut key = KeyEvent::press(KeyCode::Char(char::from(ch as u8 - 1 + b'a')));
48 key.modifiers.control = true;
49 return key;
50 }
51 '\x1c'..='\x1f' => {
52 let scalar = match ch {
53 '\x1c' => '\\',
54 '\x1d' => ']',
55 '\x1e' => '6',
56 _ => '_',
57 };
58 let mut key = KeyEvent::press(KeyCode::Char(scalar));
59 key.modifiers.control = true;
60 return key;
61 }
62 ch => KeyCode::Char(ch),
63 };
64 KeyEvent::press(code)
65}
66
67fn token(mut text: &str) -> Option<KeyEvent> {
68 let mut modifiers = Modifiers::default();
69 while let Some((modifier, rest)) = text.split_once('-') {
70 if modifier.eq_ignore_ascii_case("c") {
71 modifiers.control = true;
72 } else if modifier.eq_ignore_ascii_case("s") {
73 modifiers.shift = true;
74 } else if modifier.eq_ignore_ascii_case("a") || modifier.eq_ignore_ascii_case("m") {
75 modifiers.alt = true;
76 } else if modifier.eq_ignore_ascii_case("d") || modifier.eq_ignore_ascii_case("super") {
77 modifiers.super_key = true;
78 } else {
79 break;
80 }
81 text = rest;
82 }
83 let mut code = NAMES
84 .iter()
85 .find(|(name, _)| text.eq_ignore_ascii_case(name))
86 .map(|(_, code)| *code);
87 if code.is_none() && text.starts_with(['f', 'F']) {
88 code = text[1..]
89 .parse::<u8>()
90 .ok()
91 .filter(|number| *number != 0)
92 .map(KeyCode::Function);
93 }
94 if code.is_none() {
95 let mut chars = text.chars();
96 if let Some(ch) = chars.next() {
97 if chars.next().is_none() && modifiers != Modifiers::default() {
98 code = Some(KeyCode::Char(ch));
99 }
100 }
101 }
102 let mut code = code?;
103 if code == KeyCode::Tab && modifiers.shift {
104 code = KeyCode::BackTab;
105 }
106 if code == KeyCode::Char('^') && modifiers.control {
107 code = KeyCode::Char('6');
108 modifiers.shift = true;
109 }
110 let mut key = KeyEvent::press(code);
111 key.modifiers = modifiers;
112 Some(key)
113}
114const NAMES: &[(&str, KeyCode)] = &[
115 ("esc", KeyCode::Escape),
116 ("cr", KeyCode::Enter),
117 ("enter", KeyCode::Enter),
118 ("bs", KeyCode::Backspace),
119 ("backspace", KeyCode::Backspace),
120 ("space", KeyCode::Char(' ')),
121 ("lt", KeyCode::Char('<')),
122 ("gt", KeyCode::Char('>')),
123 ("up", KeyCode::Up),
124 ("down", KeyCode::Down),
125 ("left", KeyCode::Left),
126 ("right", KeyCode::Right),
127 ("tab", KeyCode::Tab),
128 ("home", KeyCode::Home),
129 ("end", KeyCode::End),
130 ("pageup", KeyCode::PageUp),
131 ("pagedown", KeyCode::PageDown),
132 ("delete", KeyCode::Delete),
133 ("insert", KeyCode::Insert),
134 ("null", KeyCode::Null),
135];