1#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
7pub enum KeyCode {
8 Char(char),
9 Enter,
10 Esc,
11 Tab,
12 Backspace,
13 Delete,
14 Up,
15 Down,
16 Left,
17 Right,
18 PageUp,
19 PageDown,
20 Home,
21 End,
22 Other,
25}
26
27#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Default)]
29pub struct KeyModifiers(u8);
30
31impl KeyModifiers {
32 pub const NONE: KeyModifiers = KeyModifiers(0);
33 pub const SHIFT: KeyModifiers = KeyModifiers(1);
34 pub const CONTROL: KeyModifiers = KeyModifiers(2);
35 pub const ALT: KeyModifiers = KeyModifiers(4);
36
37 pub fn contains(self, other: KeyModifiers) -> bool {
38 self.0 & other.0 == other.0
39 }
40
41 pub fn is_empty(self) -> bool {
42 self.0 == 0
43 }
44}
45
46impl std::ops::BitOr for KeyModifiers {
47 type Output = KeyModifiers;
48 fn bitor(self, rhs: KeyModifiers) -> KeyModifiers {
49 KeyModifiers(self.0 | rhs.0)
50 }
51}
52
53impl std::ops::BitOrAssign for KeyModifiers {
54 fn bitor_assign(&mut self, rhs: KeyModifiers) {
55 self.0 |= rhs.0;
56 }
57}
58
59impl std::ops::BitAnd for KeyModifiers {
60 type Output = KeyModifiers;
61 fn bitand(self, rhs: KeyModifiers) -> KeyModifiers {
62 KeyModifiers(self.0 & rhs.0)
63 }
64}
65
66#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
68pub struct KeyEvent {
69 pub code: KeyCode,
70 pub modifiers: KeyModifiers,
71}
72
73impl KeyEvent {
74 pub fn new(code: KeyCode, modifiers: KeyModifiers) -> KeyEvent {
75 KeyEvent { code, modifiers }
76 }
77}
78
79#[derive(Default, Debug)]
90pub struct EscPrefix {
91 pending: bool,
92}
93
94impl EscPrefix {
95 pub fn apply(&mut self, key: KeyEvent) -> Option<KeyEvent> {
98 let bare_esc = key.code == KeyCode::Esc && key.modifiers == KeyModifiers::NONE;
99 if std::mem::take(&mut self.pending) {
100 if bare_esc {
101 return Some(key);
102 }
103 return Some(KeyEvent::new(key.code, key.modifiers | KeyModifiers::ALT));
104 }
105 if bare_esc {
106 self.pending = true;
107 return None;
108 }
109 Some(key)
110 }
111
112 pub fn clear(&mut self) {
114 self.pending = false;
115 }
116
117 pub fn is_pending(&self) -> bool {
118 self.pending
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn modifier_sets() {
128 let m = KeyModifiers::CONTROL | KeyModifiers::SHIFT;
129 assert!(m.contains(KeyModifiers::CONTROL));
130 assert!(m.contains(KeyModifiers::SHIFT));
131 assert!(!m.contains(KeyModifiers::ALT));
132 assert!(m.contains(KeyModifiers::NONE));
133 assert_eq!(
134 m & (KeyModifiers::CONTROL | KeyModifiers::ALT),
135 KeyModifiers::CONTROL
136 );
137 let mut n = KeyModifiers::NONE;
138 n |= KeyModifiers::ALT;
139 assert_eq!(n, KeyModifiers::ALT);
140 }
141
142 #[test]
143 fn esc_then_a_key_is_that_key_with_alt() {
144 let mut esc = EscPrefix::default();
145 let plain = |c| KeyEvent::new(KeyCode::Char(c), KeyModifiers::NONE);
146 let alt = |c| KeyEvent::new(KeyCode::Char(c), KeyModifiers::ALT);
147 let bare_esc = KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE);
148 assert_eq!(esc.apply(bare_esc), None);
149 assert!(esc.is_pending());
150 assert_eq!(esc.apply(plain('/')), Some(alt('/')));
151 assert_eq!(esc.apply(plain('/')), Some(plain('/')));
153 assert_eq!(esc.apply(alt('/')), Some(alt('/')));
155 assert_eq!(esc.apply(bare_esc), None);
157 assert_eq!(esc.apply(bare_esc), Some(bare_esc));
158 assert_eq!(esc.apply(bare_esc), None);
160 esc.clear();
161 assert_eq!(esc.apply(plain('a')), Some(plain('a')));
162 esc.apply(bare_esc);
164 assert_eq!(
165 esc.apply(KeyEvent::new(KeyCode::Tab, KeyModifiers::NONE)),
166 Some(KeyEvent::new(KeyCode::Tab, KeyModifiers::ALT))
167 );
168 }
169}