1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3pub enum Key {
4 Up,
6 Down,
8 Left,
10 Right,
12 Enter,
14 Escape,
16 Backspace,
18 Delete,
20 Home,
22 End,
24 Character(char),
26}
27
28impl Key {
29 #[must_use]
31 pub fn label(self) -> String {
32 match self {
33 Self::Up => "↑".to_owned(),
34 Self::Down => "↓".to_owned(),
35 Self::Left => "←".to_owned(),
36 Self::Right => "→".to_owned(),
37 Self::Enter => "Enter".to_owned(),
38 Self::Escape => "Esc".to_owned(),
39 Self::Backspace => "Backspace".to_owned(),
40 Self::Delete => "Del".to_owned(),
41 Self::Home => "Home".to_owned(),
42 Self::End => "End".to_owned(),
43 Self::Character(' ') => "Space".to_owned(),
44 Self::Character(character) => character.to_string(),
45 }
46 }
47
48 #[must_use]
50 pub const fn typed(self) -> Option<char> {
51 match self {
52 Self::Character(character) => Some(character),
53 Self::Up
54 | Self::Down
55 | Self::Left
56 | Self::Right
57 | Self::Enter
58 | Self::Escape
59 | Self::Backspace
60 | Self::Delete
61 | Self::Home
62 | Self::End => None,
63 }
64 }
65}
66
67#[derive(Clone, Copy, Debug, PartialEq, Eq)]
69pub struct Keystroke {
70 pub key: Key,
72 pub control: bool,
74 pub alternate: bool,
76}
77
78impl Keystroke {
79 #[must_use]
81 pub const fn plain(key: Key) -> Self {
82 Self { key, control: false, alternate: false }
83 }
84
85 #[must_use]
87 pub const fn control(key: Key) -> Self {
88 Self { key, control: true, alternate: false }
89 }
90
91 #[must_use]
93 pub const fn modified(self) -> bool {
94 self.control || self.alternate
95 }
96
97 #[must_use]
99 pub fn label(self) -> String {
100 let key = if self.modified() { self.key.label().to_uppercase() } else { self.key.label() };
102 match (self.control, self.alternate) {
103 (false, false) => key,
104 (true, false) => format!("Ctrl+{key}"),
105 (false, true) => format!("Alt+{key}"),
106 (true, true) => format!("Ctrl+Alt+{key}"),
107 }
108 }
109}
110
111pub const EXIT_KEYSTROKE: Keystroke = Keystroke::control(Key::Character('q'));