1use super::{
2 keys::{parse_sequence, Key},
3 Action,
4};
5use std::str::FromStr;
6
7#[derive(Debug, PartialEq)]
8pub enum Dispatch {
9 Fire(Action),
10 Pending,
11 Unbound,
12}
13
14#[derive(Debug)]
15pub struct Keymap {
16 rules: Vec<(Vec<Key>, Action)>,
17 buffer: std::cell::RefCell<Vec<Key>>,
18}
19
20impl Keymap {
21 pub fn from_config(entries: &[(String, Vec<String>)]) -> anyhow::Result<Self> {
22 let mut rules: Vec<(Vec<Key>, Action)> = Vec::new();
23 for (action_str, seqs) in entries {
24 let action = Action::from_str(action_str).map_err(|e| anyhow::anyhow!(e))?;
25 for s in seqs {
26 rules.push((parse_sequence(s)?, action));
27 }
28 }
29 for i in 0..rules.len() {
31 for j in 0..rules.len() {
32 if i == j {
33 continue;
34 }
35 let (a, _) = &rules[i];
36 let (b, _) = &rules[j];
37 if b.len() > a.len() && &b[..a.len()] == a.as_slice() {
38 return Err(anyhow::anyhow!(
39 "keymap prefix collision: {:?} is a prefix of {:?}",
40 a,
41 b
42 ));
43 }
44 }
45 }
46 Ok(Self {
47 rules,
48 buffer: std::cell::RefCell::new(Vec::new()),
49 })
50 }
51
52 pub fn feed(&self, raw: &str) -> Dispatch {
54 let keys = parse_sequence(raw).unwrap_or_default();
55 let mut buf = self.buffer.borrow_mut();
56 buf.extend(keys);
57
58 for (seq, action) in &self.rules {
60 if *seq == *buf {
61 buf.clear();
62 return Dispatch::Fire(*action);
63 }
64 }
65 for (seq, _) in &self.rules {
67 if seq.len() > buf.len() && seq.starts_with(buf.as_slice()) {
68 return Dispatch::Pending;
69 }
70 }
71 buf.clear();
72 Dispatch::Unbound
73 }
74}