fyodor/
input.rs

1use crossterm::event::KeyCode;
2
3pub struct Keylist {
4    case_insensitive: bool,
5    all: bool,
6    keys: Vec<KeyCode>,
7}
8
9impl Keylist {
10    pub fn new(allow_case: bool) -> Self {
11        Self {
12            case_insensitive: allow_case,
13            all: false,
14            keys: Vec::new(),
15        }
16    }
17
18    pub fn allow_case(mut self, allow_case: bool) -> Self {
19        self.case_insensitive = allow_case;
20        self
21    }
22
23    pub fn all(mut self, all: bool) -> Self {
24        self.all = all;
25        self.clear_keys();
26        self
27    }
28
29    pub fn with_keys(mut self, keys: &[KeyCode]) -> Self {
30        self.all = false;
31        self.keys.extend_from_slice(keys);
32        self
33    }
34
35    pub fn with_chars(mut self, keys: &[char]) -> Self {
36        self.all = false;
37        self.keys.extend(keys.iter().map(|c| KeyCode::Char(*c)));
38        self
39    }
40
41    pub fn except_keys(mut self, keys: &[KeyCode]) -> Self {
42        self.all = true;
43        self.keys.extend_from_slice(keys);
44        self
45    }
46
47    pub fn except_chars(mut self, keys: &[char]) -> Self {
48        self.all = true;
49        self.keys.extend(keys.iter().map(|c| KeyCode::Char(*c)));
50        self
51    }
52
53    pub fn clear_keys(&mut self) {
54        self.keys.clear();
55    }
56
57    pub fn keys(&self) -> &[KeyCode] {
58        self.keys.as_ref()
59    }
60}
61
62impl Keylist {
63    pub fn contains(&self, key: KeyCode) -> bool {
64        fn includes(keys: &[KeyCode], key: KeyCode, case_insensitive: bool) -> bool {
65            keys.iter().any(|k| match (*k, key) {
66                (KeyCode::Char(k1), KeyCode::Char(k2)) if case_insensitive => {
67                    k1.eq_ignore_ascii_case(&k2)
68                }
69                (k1, k2) => k1 == k2,
70            })
71        }
72
73        self.all ^ includes(&self.keys, key, self.case_insensitive)
74    }
75}