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}