1use nom::{
2 branch::alt,
3 bytes::complete::tag,
4 character::complete::{char, digit1},
5 combinator::{eof, map_res, opt, value},
6 multi::many1,
7 IResult,
8};
9
10use super::{CommonEdgeEvent, CommonEdgePath, CommonEdgePathPart, CommonKeyClass};
11
12use crate::keybindings::{EdgeEvent, EdgeRepeat};
13
14fn parse_base10_usize(input: &str) -> Result<usize, std::num::ParseIntError> {
15 input.parse::<usize>()
16}
17
18fn parse_special(input: &str) -> IResult<&str, CommonEdgePathPart> {
19 let (input, k) = crate::key::parse::parse_special(input)?;
20 let ret = (EdgeRepeat::Once, EdgeEvent::Key(k));
21
22 return Ok((input, ret));
23}
24
25fn parse_count(input: &str) -> IResult<&str, CommonEdgePathPart> {
26 let (input, _) = tag("{count}")(input)?;
27
28 let rep = EdgeRepeat::Min(1);
29 let evt = EdgeEvent::Class(CommonKeyClass::Count);
30
31 Ok((input, (rep, evt)))
32}
33
34fn parse_repetition_min(input: &str) -> IResult<&str, EdgeRepeat> {
35 let (input, _) = tag(">=")(input)?;
36 let (input, n) = map_res(digit1, parse_base10_usize)(input)?;
37
38 Ok((input, EdgeRepeat::Min(n)))
39}
40
41fn parse_repetition_max(input: &str) -> IResult<&str, EdgeRepeat> {
42 let (input, _) = tag("<=")(input)?;
43 let (input, n) = map_res(digit1, parse_base10_usize)(input)?;
44
45 Ok((input, EdgeRepeat::Max(n)))
46}
47
48fn parse_repetition(input: &str) -> IResult<&str, EdgeRepeat> {
49 alt((
50 value(EdgeRepeat::Min(0), tag("*")),
51 value(EdgeRepeat::Min(1), tag("+")),
52 parse_repetition_min,
53 parse_repetition_max,
54 ))(input)
55}
56
57fn parse_edgename(input: &str) -> IResult<&str, CommonEdgePathPart> {
58 let (input, _) = char('{')(input)?;
59 let (input, e) = alt((
60 value(EdgeEvent::Any, tag("any")),
61 value(EdgeEvent::Class(CommonKeyClass::Count), tag("count")),
62 value(EdgeEvent::Class(CommonKeyClass::Register), tag("register")),
63 value(EdgeEvent::Class(CommonKeyClass::Mark), tag("mark")),
64 value(EdgeEvent::Class(CommonKeyClass::Octal), tag("oct")),
65 value(EdgeEvent::Class(CommonKeyClass::Decimal), tag("dec")),
66 value(EdgeEvent::Class(CommonKeyClass::Hexadecimal), tag("hex")),
67 value(EdgeEvent::Class(CommonKeyClass::Digraph1), tag("digraph1")),
68 value(EdgeEvent::Class(CommonKeyClass::Digraph2), tag("digraph2")),
69 ))(input)?;
70 let (input, rep) = opt(parse_repetition)(input)?;
71 let (input, _) = char('}')(input)?;
72
73 let rep = rep.unwrap_or(EdgeRepeat::Once);
74
75 Ok((input, (rep, e)))
76}
77
78fn parse_key_simple(input: &str) -> IResult<&str, CommonEdgePathPart> {
79 let (input, k) = crate::key::parse::parse_simple(input)?;
80 let rep = EdgeRepeat::Once;
81 let key = EdgeEvent::Key(k);
82
83 Ok((input, (rep, key)))
84}
85
86fn parse_key(input: &str) -> IResult<&str, (EdgeRepeat, CommonEdgeEvent)> {
87 alt((parse_special, parse_count, parse_edgename, parse_key_simple))(input)
88}
89
90pub fn parse(input: &str) -> IResult<&str, CommonEdgePath> {
91 let (input, res) = many1(parse_key)(input)?;
92 let (input, _) = eof(input)?;
93
94 Ok((input, res))
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100 use crate::key::TerminalKey;
101 use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
102
103 macro_rules! once {
104 ($ev: expr) => {
105 (EdgeRepeat::Once, $ev)
106 };
107 }
108
109 macro_rules! evkey {
110 ($k: expr) => {
111 once!(EdgeEvent::Key(key!($k)))
112 };
113 ($k: expr, $km: expr) => {
114 once!(EdgeEvent::Key(key!($k, $km)))
115 };
116 }
117
118 macro_rules! evalt {
119 ($c: literal) => {
120 once!(EdgeEvent::Key(key!($c, KeyModifiers::ALT)))
121 };
122 }
123
124 macro_rules! evctl {
125 ($c: literal) => {
126 once!(EdgeEvent::Key(ctl!($c)))
127 };
128 }
129
130 macro_rules! evclass {
131 ($k: expr) => {
132 once!(EdgeEvent::Class($k))
133 };
134 }
135
136 macro_rules! count {
137 () => {
138 (EdgeRepeat::Min(1), EdgeEvent::Class(CommonKeyClass::Count))
139 };
140 }
141
142 macro_rules! res {
143 ( $( $x: expr ),* ) => {
144 Ok(("", vec![ $( $x, )* ]))
145 };
146 }
147
148 #[test]
149 fn test_ctl_uppercase() {
150 assert_eq!(parse("<C-A>"), res![evctl!('a')]);
151 assert_eq!(parse("<C-B>"), res![evctl!('b')]);
152 }
153
154 #[test]
155 fn test_ctl_lowercase() {
156 assert_eq!(parse("<C-a>"), res![evctl!('a')]);
157 assert_eq!(parse("<C-b>"), res![evctl!('b')]);
158 }
159
160 #[test]
161 fn test_shift_lowercase() {
162 let mods = KeyModifiers::SHIFT;
163
164 assert_eq!(parse("<S-a>"), res![evkey!(KeyCode::Char('A'), mods)]);
165 assert_eq!(parse("<S-q>"), res![evkey!(KeyCode::Char('Q'), mods)]);
166 assert_eq!(parse("<S-1>"), res![evkey!(KeyCode::Char('1'), mods)]);
167 assert_eq!(parse("<S-^>"), res![evkey!(KeyCode::Char('^'), mods)]);
168 }
169
170 #[test]
171 fn test_shift_uppercase() {
172 let mods = KeyModifiers::SHIFT;
173
174 assert_eq!(parse("<S-A>"), res![evkey!(KeyCode::Char('A'), mods)]);
175 assert_eq!(parse("<S-Q>"), res![evkey!(KeyCode::Char('Q'), mods)]);
176 assert_eq!(parse("<S-1>"), res![evkey!(KeyCode::Char('1'), mods)]);
177 assert_eq!(parse("<S-^>"), res![evkey!(KeyCode::Char('^'), mods)]);
178 }
179
180 #[test]
181 fn test_shift_alt() {
182 let mods = KeyModifiers::ALT | KeyModifiers::SHIFT;
183
184 assert_eq!(parse("<S-A-a>"), res![evkey!(KeyCode::Char('A'), mods)]);
185 assert_eq!(parse("<S-A-A>"), res![evkey!(KeyCode::Char('A'), mods)]);
186 assert_eq!(parse("<S-A-q>"), res![evkey!(KeyCode::Char('Q'), mods)]);
187 assert_eq!(parse("<S-A-Q>"), res![evkey!(KeyCode::Char('Q'), mods)]);
188 }
189
190 #[test]
191 fn test_alt_lowercase() {
192 let mods = KeyModifiers::ALT;
193
194 assert_eq!(parse("<A-a>"), res![evkey!(KeyCode::Char('a'), mods)]);
195 assert_eq!(parse("<A-b>"), res![evkey!(KeyCode::Char('b'), mods)]);
196 assert_eq!(parse("<M-a>"), res![evkey!(KeyCode::Char('a'), mods)]);
197 assert_eq!(parse("<M-b>"), res![evkey!(KeyCode::Char('b'), mods)]);
198 }
199
200 #[test]
201 fn test_alt_uppercase() {
202 let mods = KeyModifiers::ALT | KeyModifiers::SHIFT;
203
204 assert_eq!(parse("<A-A>"), res![evkey!(KeyCode::Char('A'), mods)]);
205 assert_eq!(parse("<A-B>"), res![evkey!(KeyCode::Char('B'), mods)]);
206 assert_eq!(parse("<M-A>"), res![evkey!(KeyCode::Char('A'), mods)]);
207 assert_eq!(parse("<M-B>"), res![evkey!(KeyCode::Char('B'), mods)]);
208 }
209
210 #[test]
211 fn test_ctl_no_collision() {
212 assert_eq!(parse("<C-?>"), res![evctl!('?')]);
215 assert_eq!(parse("<BS>"), res![evkey!(KeyCode::Backspace)]);
216 assert_eq!(parse("<C-I>"), res![evctl!('i')]);
217 assert_eq!(parse("<Tab>"), res![evkey!(KeyCode::Tab)]);
218 assert_eq!(parse("<C-M>"), res![evctl!('m')]);
219 assert_eq!(parse("<Enter>"), res![evkey!(KeyCode::Enter)]);
220 assert_eq!(parse("<C-@>"), res![evctl!('@')]);
221 assert_eq!(parse("<C-Space>"), res![evctl!(' ')]);
222 assert_eq!(parse("<C-[>"), res![evctl!('[')]);
223 assert_eq!(parse("<Esc>"), res![evkey!(KeyCode::Esc)]);
224 }
225
226 #[test]
227 fn test_named_ascii() {
228 assert_eq!(parse("<Space>"), res![evkey!(' ')]);
229 assert_eq!(parse("<Bar>"), res![evkey!('|')]);
230 assert_eq!(parse("<Bslash>"), res![evkey!('\\')]);
231 assert_eq!(parse("<lt>"), res![evkey!('<')]);
232 }
233
234 #[test]
235 fn test_arrow_key() {
236 assert_eq!(parse("<Left>"), res![evkey!(KeyCode::Left)]);
237 assert_eq!(parse("<Right>"), res![evkey!(KeyCode::Right)]);
238 assert_eq!(parse("<Up>"), res![evkey!(KeyCode::Up)]);
239 assert_eq!(parse("<Down>"), res![evkey!(KeyCode::Down)]);
240 }
241
242 #[test]
243 fn test_named_ctl() {
244 assert_eq!(parse("<BS>"), res![evkey!(KeyCode::Backspace)]);
246 assert_eq!(parse("<BackSpace>"), res![evkey!(KeyCode::Backspace)]);
247
248 assert_eq!(parse("<NL>"), res![evkey!('\n')]);
250 assert_eq!(parse("<NewLine>"), res![evkey!('\n')]);
251 assert_eq!(parse("<LineFeed>"), res![evkey!('\n')]);
252 assert_eq!(parse("<LF>"), res![evkey!('\n')]);
253
254 assert_eq!(parse("<CR>"), res![evkey!(KeyCode::Enter)]);
256 assert_eq!(parse("<Return>"), res![evkey!(KeyCode::Enter)]);
257 assert_eq!(parse("<Enter>"), res![evkey!(KeyCode::Enter)]);
258
259 assert_eq!(parse("<Esc>"), res![evkey!(KeyCode::Esc)]);
260 assert_eq!(parse("<Tab>"), res![evkey!(KeyCode::Tab)]);
261 assert_eq!(parse("<Nul>"), res![evkey!(KeyCode::Null)]);
262 }
263
264 #[test]
265 fn test_function_key() {
266 assert_eq!(parse("<F1>"), res![evkey!(KeyCode::F(1))]);
267 assert_eq!(parse("<F2>"), res![evkey!(KeyCode::F(2))]);
268 assert_eq!(parse("<F10>"), res![evkey!(KeyCode::F(10))]);
269 }
270
271 #[test]
272 fn test_special_key() {
273 assert_eq!(parse("<PageUp>"), res![evkey!(KeyCode::PageUp)]);
274 assert_eq!(parse("<PageDown>"), res![evkey!(KeyCode::PageDown)]);
275 assert_eq!(parse("<Home>"), res![evkey!(KeyCode::Home)]);
276 assert_eq!(parse("<End>"), res![evkey!(KeyCode::End)]);
277 assert_eq!(parse("<Insert>"), res![evkey!(KeyCode::Insert)]);
278 assert_eq!(parse("<Del>"), res![evkey!(KeyCode::Delete)]);
279 assert_eq!(parse("<Delete>"), res![evkey!(KeyCode::Delete)]);
280 assert_eq!(parse("<Undo>"), res![evkey!(KeyCode::F(14))]);
281 assert_eq!(parse("<Help>"), res![evkey!(KeyCode::F(15))]);
282 assert_eq!(parse("<S-Tab>"), res![evkey!(KeyCode::BackTab, KeyModifiers::SHIFT)]);
283 }
284
285 #[test]
286 fn test_edges() {
287 assert_eq!(parse("{any}"), res![once!(EdgeEvent::Any)]);
288 assert_eq!(parse("{count}"), res![count!()]);
289 assert_eq!(parse("{mark}"), res![evclass!(CommonKeyClass::Mark)]);
290 assert_eq!(parse("{register}"), res![evclass!(CommonKeyClass::Register)]);
291 assert_eq!(parse("{digraph1}"), res![evclass!(CommonKeyClass::Digraph1)]);
292 assert_eq!(parse("{digraph2}"), res![evclass!(CommonKeyClass::Digraph2)]);
293 }
294
295 #[test]
296 fn test_sequence() {
297 assert_eq!(parse("\"{register}"), res![evkey!('"'), evclass!(CommonKeyClass::Register)]);
298 assert_eq!(parse("<C-R>{register}"), res![evctl!('r'), evclass!(CommonKeyClass::Register)]);
299 assert_eq!(parse("r{any}"), res![evkey!('r'), once!(EdgeEvent::Any)]);
300 assert_eq!(parse("gwgw"), res![evkey!('g'), evkey!('w'), evkey!('g'), evkey!('w')]);
301 assert_eq!(parse("<C-K>{digraph1}{digraph2}"), res![
302 evctl!('k'),
303 evclass!(CommonKeyClass::Digraph1),
304 evclass!(CommonKeyClass::Digraph2)
305 ]);
306 }
307
308 #[test]
309 fn test_multiple_modifiers() {
310 assert_eq!(parse("<C-M-X>"), res![evkey!('x', KeyModifiers::CONTROL | KeyModifiers::ALT)]);
311 }
312
313 #[test]
314 fn test_angle_bracket() {
315 assert_eq!(parse("<C-X>>"), res![evctl!('x'), evkey!('>')]);
316 assert_eq!(parse("<C-X><"), res![evctl!('x'), evkey!('<')]);
317 assert_eq!(parse("<M->>"), res![evalt!('>')]);
318 assert_eq!(parse("<M-<>"), res![evalt!('<')]);
319 }
320}