input/
key_event.rs

1use crossterm::event::{KeyCode, KeyModifiers};
2
3/// Represents a key event.
4#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy)]
5#[allow(clippy::exhaustive_structs)]
6pub struct KeyEvent {
7	/// The key itself.
8	pub code: KeyCode,
9	/// Additional key modifiers.
10	pub modifiers: KeyModifiers,
11}
12
13impl KeyEvent {
14	/// Creates a new `KeyEvent` with `code` and `modifiers`.
15	#[must_use]
16	#[inline]
17	pub fn new(mut code: KeyCode, mut modifiers: KeyModifiers) -> Self {
18		// normalize keys with the SHIFT modifier
19		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}