1#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2pub enum Key {
3 Char(char),
4 CtrlChar(char),
5 Named(String), }
7
8pub fn parse_sequence(seq: &str) -> anyhow::Result<Vec<Key>> {
9 let mut out = Vec::new();
10 let chars: Vec<char> = seq.chars().collect();
11 let mut i = 0;
12 while i < chars.len() {
13 if chars[i] == '<' {
14 let end = chars[i..]
15 .iter()
16 .position(|&c| c == '>')
17 .ok_or_else(|| anyhow::anyhow!("unterminated <...> in {seq}"))?
18 + i;
19 let tok: String = chars[i + 1..end].iter().collect();
20 i = end + 1;
21 if let Some(rest) = tok.strip_prefix("C-") {
22 let ch = rest
23 .chars()
24 .next()
25 .ok_or_else(|| anyhow::anyhow!("bad ctrl in {seq}"))?;
26 out.push(Key::CtrlChar(ch));
27 } else {
28 out.push(Key::Named(tok));
29 }
30 } else {
31 out.push(Key::Char(chars[i]));
32 i += 1;
33 }
34 }
35 Ok(out)
36}