1use crossterm::event::{KeyCode, KeyModifiers};
2
3#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy)]
5#[allow(clippy::exhaustive_structs)]
6pub struct KeyEvent {
7 pub code: KeyCode,
9 pub modifiers: KeyModifiers,
11}
12
13impl KeyEvent {
14 #[must_use]
16 #[inline]
17 pub fn new(mut code: KeyCode, mut modifiers: KeyModifiers) -> Self {
18 if let KeyCode::Char(c) = code {
20 if modifiers.contains(KeyModifiers::SHIFT) {
21 code = KeyCode::Char(c.to_ascii_uppercase());
22 modifiers.remove(KeyModifiers::SHIFT);
23 }
24 }
25 Self { code, modifiers }
26 }
27}
28
29impl From<crossterm::event::KeyEvent> for KeyEvent {
30 #[inline]
31 fn from(key_event: crossterm::event::KeyEvent) -> Self {
32 Self::new(key_event.code, key_event.modifiers)
33 }
34}
35
36impl From<KeyCode> for KeyEvent {
37 #[inline]
38 fn from(code: KeyCode) -> Self {
39 Self::new(code, KeyModifiers::empty())
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn new_non_character() {
49 assert_eq!(KeyEvent::new(KeyCode::Backspace, KeyModifiers::ALT), KeyEvent {
50 code: KeyCode::Backspace,
51 modifiers: KeyModifiers::ALT
52 });
53 }
54
55 #[test]
56 fn new_lowercase_character_without_shift() {
57 assert_eq!(KeyEvent::new(KeyCode::Char('a'), KeyModifiers::NONE), KeyEvent {
58 code: KeyCode::Char('a'),
59 modifiers: KeyModifiers::NONE
60 });
61 }
62
63 #[test]
64 fn new_uppercase_character_without_shift() {
65 assert_eq!(KeyEvent::new(KeyCode::Char('A'), KeyModifiers::NONE), KeyEvent {
66 code: KeyCode::Char('A'),
67 modifiers: KeyModifiers::NONE
68 });
69 }
70
71 #[test]
72 fn new_lowercase_character_with_shift() {
73 assert_eq!(KeyEvent::new(KeyCode::Char('a'), KeyModifiers::SHIFT), KeyEvent {
74 code: KeyCode::Char('A'),
75 modifiers: KeyModifiers::NONE
76 });
77 }
78
79 #[test]
80 fn new_uppercase_character_with_shift() {
81 assert_eq!(KeyEvent::new(KeyCode::Char('A'), KeyModifiers::SHIFT), KeyEvent {
82 code: KeyCode::Char('A'),
83 modifiers: KeyModifiers::NONE
84 });
85 }
86
87 #[test]
88 fn from_crossterm_key_event() {
89 assert_eq!(
90 KeyEvent::from(crossterm::event::KeyEvent::new(KeyCode::Char('a'), KeyModifiers::ALT)),
91 KeyEvent {
92 code: KeyCode::Char('a'),
93 modifiers: KeyModifiers::ALT
94 }
95 );
96 }
97
98 #[test]
99 fn from_keycode() {
100 assert_eq!(KeyEvent::from(KeyCode::Char('a')), KeyEvent {
101 code: KeyCode::Char('a'),
102 modifiers: KeyModifiers::NONE
103 });
104 }
105}