summaryrefslogtreecommitdiffstats
path: root/src/input/key_event.rs
blob: b88fcc4e021c3890a1549b7d4caf93641f3d947f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use crossterm::event::{KeyCode, KeyModifiers};

/// Represents a key event.
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy)]
#[allow(clippy::exhaustive_structs)]
pub(crate) struct KeyEvent {
	/// The key itself.
	pub(crate) code: KeyCode,
	/// Additional key modifiers.
	pub(crate) modifiers: KeyModifiers,
}

impl KeyEvent {
	/// Creates a new `KeyEvent` with `code` and `modifiers`.
	#[must_use]
	pub(crate) fn new(mut code: KeyCode, mut modifiers: KeyModifiers) -> Self {
		// normalize keys with the SHIFT modifier
		if let KeyCode::Char(c) = code {
			if modifiers.contains(KeyModifiers::SHIFT) {
				code = KeyCode::Char(c.to_ascii_uppercase());
				modifiers.remove(KeyModifiers::SHIFT);
			}
		}
		Self { code, modifiers }
	}
}

impl From<crossterm::event::KeyEvent> for KeyEvent {
	fn from(key_event: crossterm::event::KeyEvent) -> Self {
		Self::new(key_event.code, key_event.modifiers)
	}
}

impl From<KeyCode> for KeyEvent {
	fn from(code: KeyCode) -> Self {
		Self::new(code, KeyModifiers::empty())
	}
}

#[cfg(test)]
mod tests {
	use super::*;

	#[test]
	fn new_non_character() {
		assert_eq!(KeyEvent::new(KeyCode::Backspace, KeyModifiers::ALT), KeyEvent {
			code: KeyCode::Backspace,
			modifiers: KeyModifiers::ALT
		});
	}

	#[test]
	fn new_lowercase_character_without_shift() {
		assert_eq!(KeyEvent::new(KeyCode::Char('a'), KeyModifiers::NONE), KeyEvent {
			code: KeyCode::Char('a'),
			modifiers: KeyModifiers::NONE
		});
	}

	#[test]
	fn new_uppercase_character_without_shift() {
		assert_eq!(KeyEvent::new(KeyCode::Char('A'), KeyModifiers::NONE), KeyEvent {
			code: KeyCode::Char('A'),
			modifiers: KeyModifiers::NONE
		});
	}

	#[test]
	fn new_lowercase_character_with_shift() {
		assert_eq!(KeyEvent::new(KeyCode::Char('a'), KeyModifiers::SHIFT), KeyEvent {
			code: KeyCode::Char('A'),
			modifiers: KeyModifiers::NONE
		});
	}

	#[test]
	fn new_uppercase_character_with_shift() {
		assert_eq!(KeyEvent::new(KeyCode::Char('A'), KeyModifiers::SHIFT), KeyEvent {
			code: KeyCode::Char('A'),
			modifiers: KeyModifiers::NONE
		});
	}

	#[test]
	fn from_crossterm_key_event() {
		assert_eq!(
			KeyEvent::from(crossterm::event::KeyEvent::new(KeyCode::Char('a'), KeyModifiers::ALT)),
			KeyEvent {
				code: KeyCode::Char('a'),
				modifiers: KeyModifiers::ALT
			}
		);
	}

	#[test]
	fn from_keycode() {
		assert_eq!(KeyEvent::from(KeyCode::Char('a')), KeyEvent {
			code: KeyCode::Char('a'),
			modifiers: KeyModifiers::NONE
		});
	}
}