1use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::str::FromStr;
6
7use crate::error::{Error, Result};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[non_exhaustive]
12pub enum Key {
13 A,
15 B,
16 C,
17 D,
18 E,
19 F,
20 G,
21 H,
22 I,
23 J,
24 K,
25 L,
26 M,
27 N,
28 O,
29 P,
30 Q,
31 R,
32 S,
33 T,
34 U,
35 V,
36 W,
37 X,
38 Y,
39 Z,
40
41 Num0,
43 Num1,
44 Num2,
45 Num3,
46 Num4,
47 Num5,
48 Num6,
49 Num7,
50 Num8,
51 Num9,
52
53 F1,
55 F2,
56 F3,
57 F4,
58 F5,
59 F6,
60 F7,
61 F8,
62 F9,
63 F10,
64 F11,
65 F12,
66 F13,
67 F14,
68 F15,
69 F16,
70 F17,
71 F18,
72 F19,
73 F20,
74
75 Space,
77 Return,
78 Tab,
79 Escape,
80 Delete,
81 ForwardDelete,
82 Insert,
83 Home,
84 End,
85 PageUp,
86 PageDown,
87
88 LeftArrow,
90 RightArrow,
91 UpArrow,
92 DownArrow,
93
94 Minus,
96 Equal,
97 LeftBracket,
98 RightBracket,
99 Backslash,
100 Semicolon,
101 Quote,
102 Comma,
103 Period,
104 Slash,
105 Grave,
106 Section,
107 JisYen,
109 JisUnderscore,
110 JisEisu,
111 JisKana,
112
113 Keypad0,
115 Keypad1,
116 Keypad2,
117 Keypad3,
118 Keypad4,
119 Keypad5,
120 Keypad6,
121 Keypad7,
122 Keypad8,
123 Keypad9,
124 KeypadDecimal,
125 KeypadMultiply,
126 KeypadPlus,
127 KeypadClear,
128 KeypadDivide,
129 KeypadEnter,
130 KeypadMinus,
131 KeypadEquals,
132 KeypadComma,
133
134 CapsLock,
136 ScrollLock,
137 NumLock,
138
139 MouseLeft,
141 MouseRight,
142 MouseMiddle,
143 MouseX1,
145 MouseX2,
147}
148
149impl fmt::Display for Key {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 match self {
152 Key::A => write!(f, "A"),
153 Key::B => write!(f, "B"),
154 Key::C => write!(f, "C"),
155 Key::D => write!(f, "D"),
156 Key::E => write!(f, "E"),
157 Key::F => write!(f, "F"),
158 Key::G => write!(f, "G"),
159 Key::H => write!(f, "H"),
160 Key::I => write!(f, "I"),
161 Key::J => write!(f, "J"),
162 Key::K => write!(f, "K"),
163 Key::L => write!(f, "L"),
164 Key::M => write!(f, "M"),
165 Key::N => write!(f, "N"),
166 Key::O => write!(f, "O"),
167 Key::P => write!(f, "P"),
168 Key::Q => write!(f, "Q"),
169 Key::R => write!(f, "R"),
170 Key::S => write!(f, "S"),
171 Key::T => write!(f, "T"),
172 Key::U => write!(f, "U"),
173 Key::V => write!(f, "V"),
174 Key::W => write!(f, "W"),
175 Key::X => write!(f, "X"),
176 Key::Y => write!(f, "Y"),
177 Key::Z => write!(f, "Z"),
178 Key::Num0 => write!(f, "0"),
179 Key::Num1 => write!(f, "1"),
180 Key::Num2 => write!(f, "2"),
181 Key::Num3 => write!(f, "3"),
182 Key::Num4 => write!(f, "4"),
183 Key::Num5 => write!(f, "5"),
184 Key::Num6 => write!(f, "6"),
185 Key::Num7 => write!(f, "7"),
186 Key::Num8 => write!(f, "8"),
187 Key::Num9 => write!(f, "9"),
188 Key::F1 => write!(f, "F1"),
189 Key::F2 => write!(f, "F2"),
190 Key::F3 => write!(f, "F3"),
191 Key::F4 => write!(f, "F4"),
192 Key::F5 => write!(f, "F5"),
193 Key::F6 => write!(f, "F6"),
194 Key::F7 => write!(f, "F7"),
195 Key::F8 => write!(f, "F8"),
196 Key::F9 => write!(f, "F9"),
197 Key::F10 => write!(f, "F10"),
198 Key::F11 => write!(f, "F11"),
199 Key::F12 => write!(f, "F12"),
200 Key::F13 => write!(f, "F13"),
201 Key::F14 => write!(f, "F14"),
202 Key::F15 => write!(f, "F15"),
203 Key::F16 => write!(f, "F16"),
204 Key::F17 => write!(f, "F17"),
205 Key::F18 => write!(f, "F18"),
206 Key::F19 => write!(f, "F19"),
207 Key::F20 => write!(f, "F20"),
208 Key::Space => write!(f, "Space"),
209 Key::Return => write!(f, "Return"),
210 Key::Tab => write!(f, "Tab"),
211 Key::Escape => write!(f, "Escape"),
212 Key::Delete => write!(f, "Delete"),
213 Key::ForwardDelete => write!(f, "ForwardDelete"),
214 Key::Insert => write!(f, "Insert"),
215 Key::Home => write!(f, "Home"),
216 Key::End => write!(f, "End"),
217 Key::PageUp => write!(f, "PageUp"),
218 Key::PageDown => write!(f, "PageDown"),
219 Key::LeftArrow => write!(f, "Left"),
220 Key::RightArrow => write!(f, "Right"),
221 Key::UpArrow => write!(f, "Up"),
222 Key::DownArrow => write!(f, "Down"),
223 Key::Minus => write!(f, "-"),
224 Key::Equal => write!(f, "="),
225 Key::LeftBracket => write!(f, "["),
226 Key::RightBracket => write!(f, "]"),
227 Key::Backslash => write!(f, "\\"),
228 Key::Semicolon => write!(f, ";"),
229 Key::Quote => write!(f, "'"),
230 Key::Comma => write!(f, ","),
231 Key::Period => write!(f, "."),
232 Key::Slash => write!(f, "/"),
233 Key::Grave => write!(f, "`"),
234 Key::Section => write!(f, "§"),
235 Key::JisYen => write!(f, "¥"),
236 Key::JisUnderscore => write!(f, "JisUnderscore"),
237 Key::JisEisu => write!(f, "Eisu"),
238 Key::JisKana => write!(f, "Kana"),
239 Key::Keypad0 => write!(f, "Keypad0"),
240 Key::Keypad1 => write!(f, "Keypad1"),
241 Key::Keypad2 => write!(f, "Keypad2"),
242 Key::Keypad3 => write!(f, "Keypad3"),
243 Key::Keypad4 => write!(f, "Keypad4"),
244 Key::Keypad5 => write!(f, "Keypad5"),
245 Key::Keypad6 => write!(f, "Keypad6"),
246 Key::Keypad7 => write!(f, "Keypad7"),
247 Key::Keypad8 => write!(f, "Keypad8"),
248 Key::Keypad9 => write!(f, "Keypad9"),
249 Key::KeypadDecimal => write!(f, "KeypadDecimal"),
250 Key::KeypadMultiply => write!(f, "KeypadMultiply"),
251 Key::KeypadPlus => write!(f, "KeypadPlus"),
252 Key::KeypadClear => write!(f, "KeypadClear"),
253 Key::KeypadDivide => write!(f, "KeypadDivide"),
254 Key::KeypadEnter => write!(f, "KeypadEnter"),
255 Key::KeypadMinus => write!(f, "KeypadMinus"),
256 Key::KeypadEquals => write!(f, "KeypadEquals"),
257 Key::KeypadComma => write!(f, "KeypadComma"),
258 Key::CapsLock => write!(f, "CapsLock"),
259 Key::ScrollLock => write!(f, "ScrollLock"),
260 Key::NumLock => write!(f, "NumLock"),
261 Key::MouseLeft => write!(f, "MouseLeft"),
262 Key::MouseRight => write!(f, "MouseRight"),
263 Key::MouseMiddle => write!(f, "MouseMiddle"),
264 Key::MouseX1 => write!(f, "MouseX1"),
265 Key::MouseX2 => write!(f, "MouseX2"),
266 }
267 }
268}
269
270impl FromStr for Key {
271 type Err = Error;
272
273 fn from_str(s: &str) -> Result<Self> {
275 let s = s.trim();
276 match s.to_lowercase().as_str() {
277 "a" => Ok(Key::A),
279 "b" => Ok(Key::B),
280 "c" => Ok(Key::C),
281 "d" => Ok(Key::D),
282 "e" => Ok(Key::E),
283 "f" => Ok(Key::F),
284 "g" => Ok(Key::G),
285 "h" => Ok(Key::H),
286 "i" => Ok(Key::I),
287 "j" => Ok(Key::J),
288 "k" => Ok(Key::K),
289 "l" => Ok(Key::L),
290 "m" => Ok(Key::M),
291 "n" => Ok(Key::N),
292 "o" => Ok(Key::O),
293 "p" => Ok(Key::P),
294 "q" => Ok(Key::Q),
295 "r" => Ok(Key::R),
296 "s" => Ok(Key::S),
297 "t" => Ok(Key::T),
298 "u" => Ok(Key::U),
299 "v" => Ok(Key::V),
300 "w" => Ok(Key::W),
301 "x" => Ok(Key::X),
302 "y" => Ok(Key::Y),
303 "z" => Ok(Key::Z),
304
305 "0" | "num0" => Ok(Key::Num0),
307 "1" | "num1" => Ok(Key::Num1),
308 "2" | "num2" => Ok(Key::Num2),
309 "3" | "num3" => Ok(Key::Num3),
310 "4" | "num4" => Ok(Key::Num4),
311 "5" | "num5" => Ok(Key::Num5),
312 "6" | "num6" => Ok(Key::Num6),
313 "7" | "num7" => Ok(Key::Num7),
314 "8" | "num8" => Ok(Key::Num8),
315 "9" | "num9" => Ok(Key::Num9),
316
317 "f1" => Ok(Key::F1),
319 "f2" => Ok(Key::F2),
320 "f3" => Ok(Key::F3),
321 "f4" => Ok(Key::F4),
322 "f5" => Ok(Key::F5),
323 "f6" => Ok(Key::F6),
324 "f7" => Ok(Key::F7),
325 "f8" => Ok(Key::F8),
326 "f9" => Ok(Key::F9),
327 "f10" => Ok(Key::F10),
328 "f11" => Ok(Key::F11),
329 "f12" => Ok(Key::F12),
330 "f13" => Ok(Key::F13),
331 "f14" => Ok(Key::F14),
332 "f15" => Ok(Key::F15),
333 "f16" => Ok(Key::F16),
334 "f17" => Ok(Key::F17),
335 "f18" => Ok(Key::F18),
336 "f19" => Ok(Key::F19),
337 "f20" => Ok(Key::F20),
338
339 "space" | " " => Ok(Key::Space),
341 "return" | "enter" => Ok(Key::Return),
342 "tab" => Ok(Key::Tab),
343 "escape" | "esc" => Ok(Key::Escape),
344 "delete" | "backspace" => Ok(Key::Delete),
345 "forwarddelete" | "del" => Ok(Key::ForwardDelete),
346 "insert" | "ins" => Ok(Key::Insert),
347 "home" => Ok(Key::Home),
348 "end" => Ok(Key::End),
349 "pageup" => Ok(Key::PageUp),
350 "pagedown" => Ok(Key::PageDown),
351
352 "left" | "leftarrow" => Ok(Key::LeftArrow),
354 "right" | "rightarrow" => Ok(Key::RightArrow),
355 "up" | "uparrow" => Ok(Key::UpArrow),
356 "down" | "downarrow" => Ok(Key::DownArrow),
357
358 "-" | "minus" => Ok(Key::Minus),
360 "=" | "equal" | "equals" => Ok(Key::Equal),
361 "[" | "leftbracket" => Ok(Key::LeftBracket),
362 "]" | "rightbracket" => Ok(Key::RightBracket),
363 "\\" | "backslash" => Ok(Key::Backslash),
364 ";" | "semicolon" => Ok(Key::Semicolon),
365 "'" | "quote" => Ok(Key::Quote),
366 "," | "comma" => Ok(Key::Comma),
367 "." | "period" => Ok(Key::Period),
368 "/" | "slash" => Ok(Key::Slash),
369 "`" | "grave" | "backtick" => Ok(Key::Grave),
370 "§" | "section" => Ok(Key::Section),
371 "¥" | "jisyen" | "yen" => Ok(Key::JisYen),
372 "jisunderscore" => Ok(Key::JisUnderscore),
373 "eisu" | "jiseisu" | "英数" => Ok(Key::JisEisu),
374 "kana" | "jiskana" | "かな" => Ok(Key::JisKana),
375
376 "keypad0" => Ok(Key::Keypad0),
378 "keypad1" => Ok(Key::Keypad1),
379 "keypad2" => Ok(Key::Keypad2),
380 "keypad3" => Ok(Key::Keypad3),
381 "keypad4" => Ok(Key::Keypad4),
382 "keypad5" => Ok(Key::Keypad5),
383 "keypad6" => Ok(Key::Keypad6),
384 "keypad7" => Ok(Key::Keypad7),
385 "keypad8" => Ok(Key::Keypad8),
386 "keypad9" => Ok(Key::Keypad9),
387 "keypad." | "keypaddecimal" => Ok(Key::KeypadDecimal),
388 "keypad*" | "keypadmultiply" => Ok(Key::KeypadMultiply),
389 "keypad+" | "keypadplus" => Ok(Key::KeypadPlus),
390 "keypadclear" => Ok(Key::KeypadClear),
391 "keypad/" | "keypaddivide" => Ok(Key::KeypadDivide),
392 "keypadenter" => Ok(Key::KeypadEnter),
393 "keypad-" | "keypadminus" => Ok(Key::KeypadMinus),
394 "keypad=" | "keypadequals" => Ok(Key::KeypadEquals),
395 "keypad," | "keypadcomma" => Ok(Key::KeypadComma),
396
397 "capslock" | "caps" => Ok(Key::CapsLock),
399 "scrolllock" | "scroll" => Ok(Key::ScrollLock),
400 "numlock" => Ok(Key::NumLock),
401
402 "mouseleft" | "leftclick" | "lmb" | "mouse1" => Ok(Key::MouseLeft),
404 "mouseright" | "rightclick" | "rmb" | "mouse2" => Ok(Key::MouseRight),
405 "mousemiddle" | "middleclick" | "mmb" | "mouse3" => Ok(Key::MouseMiddle),
406 "mousex1" | "mouse4" | "back" | "xbutton1" => Ok(Key::MouseX1),
407 "mousex2" | "mouse5" | "forward" | "xbutton2" => Ok(Key::MouseX2),
408
409 _ => Err(Error::UnknownKey(s.to_string())),
410 }
411 }
412}
413
414#[cfg(test)]
415mod tests {
416 use super::*;
417
418 #[test]
419 fn parse_letters() {
420 assert_eq!("a".parse::<Key>().unwrap(), Key::A);
421 assert_eq!("A".parse::<Key>().unwrap(), Key::A);
422 assert_eq!("z".parse::<Key>().unwrap(), Key::Z);
423 }
424
425 #[test]
426 fn parse_numbers() {
427 assert_eq!("0".parse::<Key>().unwrap(), Key::Num0);
428 assert_eq!("9".parse::<Key>().unwrap(), Key::Num9);
429 assert_eq!("num5".parse::<Key>().unwrap(), Key::Num5);
430 }
431
432 #[test]
433 fn parse_function_keys() {
434 assert_eq!("F1".parse::<Key>().unwrap(), Key::F1);
435 assert_eq!("f12".parse::<Key>().unwrap(), Key::F12);
436 assert_eq!("F20".parse::<Key>().unwrap(), Key::F20);
437 }
438
439 #[test]
440 fn parse_special_keys() {
441 assert_eq!("Space".parse::<Key>().unwrap(), Key::Space);
442 assert_eq!("return".parse::<Key>().unwrap(), Key::Return);
443 assert_eq!("enter".parse::<Key>().unwrap(), Key::Return);
444 assert_eq!("Tab".parse::<Key>().unwrap(), Key::Tab);
445 assert_eq!("Escape".parse::<Key>().unwrap(), Key::Escape);
446 assert_eq!("esc".parse::<Key>().unwrap(), Key::Escape);
447 assert_eq!("Delete".parse::<Key>().unwrap(), Key::Delete);
448 assert_eq!("backspace".parse::<Key>().unwrap(), Key::Delete);
449 }
450
451 #[test]
452 fn parse_arrow_keys() {
453 assert_eq!("Left".parse::<Key>().unwrap(), Key::LeftArrow);
454 assert_eq!("leftarrow".parse::<Key>().unwrap(), Key::LeftArrow);
455 assert_eq!("Right".parse::<Key>().unwrap(), Key::RightArrow);
456 assert_eq!("Up".parse::<Key>().unwrap(), Key::UpArrow);
457 assert_eq!("Down".parse::<Key>().unwrap(), Key::DownArrow);
458 }
459
460 #[test]
461 fn parse_punctuation() {
462 assert_eq!("-".parse::<Key>().unwrap(), Key::Minus);
463 assert_eq!("minus".parse::<Key>().unwrap(), Key::Minus);
464 assert_eq!("=".parse::<Key>().unwrap(), Key::Equal);
465 assert_eq!("[".parse::<Key>().unwrap(), Key::LeftBracket);
466 assert_eq!("]".parse::<Key>().unwrap(), Key::RightBracket);
467 assert_eq!("/".parse::<Key>().unwrap(), Key::Slash);
468 assert_eq!("`".parse::<Key>().unwrap(), Key::Grave);
469 }
470
471 #[test]
472 fn parse_unknown_key_fails() {
473 assert!("unknown".parse::<Key>().is_err());
474 assert!("".parse::<Key>().is_err());
475 }
476
477 #[test]
478 fn key_display_roundtrip() {
479 let keys = [
481 Key::A,
482 Key::Z,
483 Key::Num0,
484 Key::Num9,
485 Key::F1,
486 Key::F12,
487 Key::Space,
488 Key::Return,
489 Key::Tab,
490 Key::Escape,
491 Key::LeftArrow,
492 Key::RightArrow,
493 Key::KeypadPlus,
494 Key::KeypadMinus,
495 Key::KeypadMultiply,
496 Key::KeypadDivide,
497 Key::KeypadDecimal,
498 Key::KeypadEquals,
499 Key::KeypadEnter,
500 Key::KeypadClear,
501 Key::KeypadComma,
502 Key::JisYen,
503 Key::JisUnderscore,
504 Key::JisEisu,
505 Key::JisKana,
506 ];
507 for key in keys {
508 let displayed = format!("{}", key);
509 let parsed: Key = displayed.parse().unwrap();
510 assert_eq!(parsed, key, "Roundtrip failed for {:?}", key);
511 }
512 }
513}