1use std::fmt;
2
3#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Hash)]
5pub struct KeyEvent {
6 pub code: KeyCode,
8 pub modifiers: KeyModifiers,
10}
11
12impl fmt::Display for KeyEvent {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 let code = format!("{}", self.code);
15 let modifiers = self.modifiers.iter().map(|m| match m {
16 KeyModifier::Shift => "",
17 KeyModifier::Control => "C-",
18 KeyModifier::Alt => "A-",
19 KeyModifier::Super => "Su-",
20 KeyModifier::Hyper => "H-",
21 KeyModifier::Meta => "M-",
22 });
23 let mods = modifiers.collect::<String>();
24
25 write!(f, "{mods}{code}",)
26 }
27}
28
29impl KeyEvent {
30 #[must_use]
32 pub fn new(code: KeyCode) -> Self {
33 Self {
34 code,
35 modifiers: KeyModifiers::new(),
36 }
37 }
38 #[must_use]
40 pub fn shift(code: KeyCode) -> Self {
41 Self {
42 modifiers: KeyModifiers::shift(),
43 code,
44 }
45 }
46
47 #[must_use]
49 pub fn ctrl(code: KeyCode) -> Self {
50 Self {
51 modifiers: KeyModifiers::ctrl(),
52 code,
53 }
54 }
55
56 #[must_use]
58 pub fn modifier(mut self, modifier: KeyModifier) -> Self {
59 self.modifiers = self.modifiers.add_modifier(modifier);
60 self
61 }
62}
63
64#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
65pub enum KeyModifier {
66 Shift,
67 Control,
68 Alt,
69 Super,
70 Hyper,
71 Meta,
72}
73
74impl fmt::Display for KeyModifier {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 match self {
77 KeyModifier::Shift => write!(f, "Shift"),
78 KeyModifier::Control => write!(f, "Ctrl"),
79 KeyModifier::Alt => write!(f, "Alt"),
80 KeyModifier::Super => write!(f, "Super"),
81 KeyModifier::Hyper => write!(f, "Hyper"),
82 KeyModifier::Meta => write!(f, "Meta"),
83 }
84 }
85}
86
87#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq, Hash, Default)]
88pub struct KeyModifiers(u32);
89
90impl KeyModifiers {
91 #[must_use]
93 pub fn new() -> Self {
94 KeyModifiers(0)
95 }
96
97 #[must_use]
99 pub fn shift() -> Self {
100 KeyModifiers(0).add_modifier(KeyModifier::Shift)
101 }
102
103 #[must_use]
105 pub fn ctrl() -> Self {
106 KeyModifiers(0).add_modifier(KeyModifier::Control)
107 }
108
109 #[must_use]
110 pub fn add_modifier(mut self, modifier: KeyModifier) -> Self {
111 match modifier {
112 KeyModifier::Shift => self.0 |= 0b0000_0001,
113 KeyModifier::Control => self.0 |= 0b0000_0010,
114 KeyModifier::Alt => self.0 |= 0b0000_0100,
115 KeyModifier::Super => self.0 |= 0b0000_1000,
116 KeyModifier::Hyper => self.0 |= 0b0001_0000,
117 KeyModifier::Meta => self.0 |= 0b0010_0000,
118 }
119 self
120 }
121
122 #[must_use]
123 pub fn remove_modifier(mut self, modifier: KeyModifier) -> Self {
124 match modifier {
125 KeyModifier::Shift => self.0 &= !0b0000_0001,
126 KeyModifier::Control => self.0 &= !0b0000_0010,
127 KeyModifier::Alt => self.0 &= !0b0000_0100,
128 KeyModifier::Super => self.0 &= !0b0000_1000,
129 KeyModifier::Hyper => self.0 &= !0b0001_0000,
130 KeyModifier::Meta => self.0 &= !0b0010_0000,
131 }
132 self
133 }
134
135 #[must_use]
136 pub fn contains(&self, modifier: KeyModifier) -> bool {
137 match modifier {
138 KeyModifier::Shift => self.0 & 0b0000_0001 != 0,
139 KeyModifier::Control => self.0 & 0b0000_0010 != 0,
140 KeyModifier::Alt => self.0 & 0b0000_0100 != 0,
141 KeyModifier::Super => self.0 & 0b0000_1000 != 0,
142 KeyModifier::Hyper => self.0 & 0b0001_0000 != 0,
143 KeyModifier::Meta => self.0 & 0b0010_0000 != 0,
144 }
145 }
146
147 pub fn iter(&self) -> impl Iterator<Item = KeyModifier> + '_ {
148 [
149 KeyModifier::Shift,
150 KeyModifier::Control,
151 KeyModifier::Alt,
152 KeyModifier::Super,
153 KeyModifier::Hyper,
154 KeyModifier::Meta,
155 ]
156 .into_iter()
157 .filter(|&m| self.contains(m))
158 }
159}
160
161#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
163pub enum KeyCode {
164 Backspace,
165 Enter,
166 Left,
167 Right,
168 Up,
169 Down,
170 Home,
171 End,
172 PageUp,
173 PageDown,
174 Tab,
175 BackTab,
176 Delete,
177 Insert,
178 F(u8),
179 Char(char),
180 Null,
181 Esc,
182 Unknown,
183}
184
185impl fmt::Display for KeyCode {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 match self {
188 KeyCode::Backspace => write!(f, "Backspace"),
189 KeyCode::Enter => write!(f, "Enter"),
190 KeyCode::Left => write!(f, "←"),
191 KeyCode::Right => write!(f, "→"),
192 KeyCode::Up => write!(f, "↑"),
193 KeyCode::Down => write!(f, "↓"),
194 KeyCode::Home => write!(f, "Home"),
195 KeyCode::End => write!(f, "End"),
196 KeyCode::PageUp => write!(f, "PageUp"),
197 KeyCode::PageDown => write!(f, "PageDown"),
198 KeyCode::Tab => write!(f, "Tab"),
199 KeyCode::BackTab => write!(f, "BackTab"),
200 KeyCode::Delete => write!(f, "Delete"),
201 KeyCode::Insert => write!(f, "Insert"),
202 KeyCode::F(n) => write!(f, "F{n}"),
203 KeyCode::Char(c) => write!(f, "{c}"),
204 KeyCode::Null => write!(f, "Null"),
205 KeyCode::Esc => write!(f, "Esc"),
206 KeyCode::Unknown => write!(f, "Unknown"),
207 }
208 }
209}