input/
event.rs

1use crossterm::event::{KeyCode, MouseEvent};
2
3use crate::{KeyEvent, StandardEvent};
4
5/// An event, either from an input device, system change or action event.
6#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy)]
7#[allow(clippy::exhaustive_enums)]
8pub enum Event<CustomEvent: crate::CustomEvent> {
9	/// A keyboard event.
10	Key(KeyEvent),
11	/// An action event.
12	Standard(StandardEvent),
13	/// A mouse event.
14	Mouse(MouseEvent),
15	/// An empty event.
16	None,
17	/// A terminal resize event.
18	Resize(u16, u16),
19	/// Custom application defined events
20	MetaEvent(CustomEvent),
21}
22
23impl<CustomEvent: crate::CustomEvent> From<crossterm::event::Event> for Event<CustomEvent> {
24	#[inline]
25	fn from(event: crossterm::event::Event) -> Self {
26		match event {
27			crossterm::event::Event::Key(evt) => Self::Key(KeyEvent::from(evt)),
28			crossterm::event::Event::Mouse(evt) => Self::Mouse(evt),
29			crossterm::event::Event::Resize(width, height) => Self::Resize(width, height),
30			// ignore these events for now, as we don't need them
31			crossterm::event::Event::FocusGained
32			| crossterm::event::Event::FocusLost
33			| crossterm::event::Event::Paste(_) => Self::None,
34		}
35	}
36}
37
38impl<CustomEvent: crate::CustomEvent> From<KeyEvent> for Event<CustomEvent> {
39	#[inline]
40	fn from(key_event: KeyEvent) -> Self {
41		Self::Key(key_event)
42	}
43}
44
45impl<CustomEvent: crate::CustomEvent> From<MouseEvent> for Event<CustomEvent> {
46	#[inline]
47	fn from(mouse_event: MouseEvent) -> Self {
48		Self::Mouse(mouse_event)
49	}
50}
51
52impl<CustomEvent: crate::CustomEvent> From<StandardEvent> for Event<CustomEvent> {
53	#[inline]
54	fn from(event: StandardEvent) -> Self {
55		Self::Standard(event)
56	}
57}
58
59impl<CustomEvent: crate::CustomEvent> From<KeyCode> for Event<CustomEvent> {
60	#[inline]
61	fn from(code: KeyCode) -> Self {
62		Self::Key(KeyEvent::from(code))
63	}
64}
65
66impl<CustomEvent: crate::CustomEvent> From<char> for Event<CustomEvent> {
67	#[inline]
68	fn from(c: char) -> Self {
69		Self::Key(KeyEvent::from(KeyCode::Char(c)))
70	}
71}
72
73#[cfg(test)]
74mod tests {
75	use crossterm::{
76		event as ct_event,
77		event::{KeyModifiers, MouseEventKind},
78	};
79
80	use super::*;
81	use crate::testutil::local::Event;
82
83	#[test]
84	fn from_crossterm_key_event() {
85		let event = Event::from(ct_event::Event::Key(ct_event::KeyEvent::new(
86			KeyCode::Null,
87			KeyModifiers::empty(),
88		)));
89		assert_eq!(event, Event::Key(KeyEvent::new(KeyCode::Null, KeyModifiers::empty())));
90	}
91
92	#[test]
93	fn from_crossterm_key_event_char_with_modifier() {
94		let event = Event::from(ct_event::Event::Key(ct_event::KeyEvent::new(
95			KeyCode::Char('?'),
96			KeyModifiers::ALT,
97		)));
98
99		assert_eq!(event, Event::Key(KeyEvent::new(KeyCode::Char('?'), KeyModifiers::ALT)));
100	}
101
102	#[test]
103	fn from_crossterm_mouse_event() {
104		let mouse_event = MouseEvent {
105			kind: MouseEventKind::Moved,
106			column: 0,
107			row: 0,
108			modifiers: KeyModifiers::empty(),
109		};
110		let event = Event::from(crossterm::event::Event::Mouse(mouse_event));
111		assert_eq!(event, Event::Mouse(mouse_event));
112	}
113
114	#[test]
115	fn from_crossterm_resize_event() {
116		let event = Event::from(crossterm::event::Event::Resize(100, 100));
117		assert_eq!(event, Event::Resize(100, 100));
118	}
119
120	#[test]
121	fn from_crossterm_focused_gained_event() {
122		let event = Event::from(crossterm::event::Event::FocusGained);
123		assert_eq!(event, Event::None);
124	}
125
126	#[test]
127	fn from_crossterm_focused_lost_event() {
128		let event = Event::from(crossterm::event::Event::FocusLost);
129		assert_eq!(event, Event::None);
130	}
131
132	#[test]
133	fn from_crossterm_paste_event() {
134		let event = Event::from(crossterm::event::Event::Paste(String::from("test")));
135		assert_eq!(event, Event::None);
136	}
137
138	#[test]
139	fn from_meta_event() {
140		let event = Event::from(StandardEvent::Kill);
141		assert_eq!(event, Event::Standard(StandardEvent::Kill));
142	}
143
144	#[test]
145	fn from_key_code() {
146		let event = Event::from(KeyCode::Null);
147		assert_eq!(event, Event::Key(KeyEvent::new(KeyCode::Null, KeyModifiers::empty())));
148	}
149
150	#[test]
151	fn from_mouse_event() {
152		let event = Event::from(MouseEvent {
153			kind: MouseEventKind::Moved,
154			column: 0,
155			row: 0,
156			modifiers: KeyModifiers::empty(),
157		});
158		assert_eq!(
159			event,
160			Event::Mouse(MouseEvent {
161				kind: MouseEventKind::Moved,
162				column: 0,
163				row: 0,
164				modifiers: KeyModifiers::empty(),
165			})
166		);
167	}
168
169	#[test]
170	fn from_char() {
171		let event = Event::from('a');
172		assert_eq!(
173			event,
174			Event::Key(KeyEvent::new(KeyCode::Char('a'), KeyModifiers::empty()))
175		);
176	}
177}