1use super::{Input, Key};
2use crate::crossterm::event::{
3 Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseEvent, MouseEventKind,
4};
5
6impl From<Event> for Input {
7 fn from(event: Event) -> Self {
9 match event {
10 Event::Key(key) => Self::from(key),
11 Event::Mouse(mouse) => Self::from(mouse),
12 _ => Self::default(),
13 }
14 }
15}
16
17impl From<KeyCode> for Key {
18 fn from(code: KeyCode) -> Self {
20 match code {
21 KeyCode::Char(c) => Key::Char(c),
22 KeyCode::Backspace => Key::Backspace,
23 KeyCode::Enter => Key::Enter,
24 KeyCode::Left => Key::Left,
25 KeyCode::Right => Key::Right,
26 KeyCode::Up => Key::Up,
27 KeyCode::Down => Key::Down,
28 KeyCode::Tab => Key::Tab,
29 KeyCode::Delete => Key::Delete,
30 KeyCode::Home => Key::Home,
31 KeyCode::End => Key::End,
32 KeyCode::PageUp => Key::PageUp,
33 KeyCode::PageDown => Key::PageDown,
34 KeyCode::Esc => Key::Esc,
35 KeyCode::F(x) => Key::F(x),
36 _ => Key::Null,
37 }
38 }
39}
40
41impl From<KeyEvent> for Input {
42 fn from(key: KeyEvent) -> Self {
44 if key.kind == KeyEventKind::Release {
45 return Self::default();
48 }
49
50 let ctrl = key.modifiers.contains(KeyModifiers::CONTROL);
51 let alt = key.modifiers.contains(KeyModifiers::ALT);
52 let shift = key.modifiers.contains(KeyModifiers::SHIFT);
53 let key = Key::from(key.code);
54
55 Self {
56 key,
57 ctrl,
58 alt,
59 shift,
60 }
61 }
62}
63
64impl From<MouseEventKind> for Key {
65 fn from(kind: MouseEventKind) -> Self {
67 match kind {
68 MouseEventKind::ScrollDown => Key::MouseScrollDown,
69 MouseEventKind::ScrollUp => Key::MouseScrollUp,
70 _ => Key::Null,
71 }
72 }
73}
74
75impl From<MouseEvent> for Input {
76 fn from(mouse: MouseEvent) -> Self {
78 let key = Key::from(mouse.kind);
79 let ctrl = mouse.modifiers.contains(KeyModifiers::CONTROL);
80 let alt = mouse.modifiers.contains(KeyModifiers::ALT);
81 let shift = mouse.modifiers.contains(KeyModifiers::SHIFT);
82 Self {
83 key,
84 ctrl,
85 alt,
86 shift,
87 }
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94 use crate::crossterm::event::KeyEventState;
95 use crate::input::tests::input;
96
97 fn key_event(code: KeyCode, modifiers: KeyModifiers) -> KeyEvent {
98 KeyEvent {
99 code,
100 modifiers,
101 kind: KeyEventKind::Press,
102 state: KeyEventState::empty(),
103 }
104 }
105
106 fn mouse_event(kind: MouseEventKind, modifiers: KeyModifiers) -> MouseEvent {
107 MouseEvent {
108 kind,
109 column: 1,
110 row: 1,
111 modifiers,
112 }
113 }
114
115 #[test]
116 fn key_to_input() {
117 for (from, to) in [
118 (
119 key_event(KeyCode::Char('a'), KeyModifiers::empty()),
120 input(Key::Char('a'), false, false, false),
121 ),
122 (
123 key_event(KeyCode::Enter, KeyModifiers::empty()),
124 input(Key::Enter, false, false, false),
125 ),
126 (
127 key_event(KeyCode::Left, KeyModifiers::CONTROL),
128 input(Key::Left, true, false, false),
129 ),
130 (
131 key_event(KeyCode::Right, KeyModifiers::SHIFT),
132 input(Key::Right, false, false, true),
133 ),
134 (
135 key_event(KeyCode::Home, KeyModifiers::ALT),
136 input(Key::Home, false, true, false),
137 ),
138 (
139 key_event(
140 KeyCode::F(1),
141 KeyModifiers::ALT | KeyModifiers::CONTROL | KeyModifiers::SHIFT,
142 ),
143 input(Key::F(1), true, true, true),
144 ),
145 (
146 key_event(KeyCode::NumLock, KeyModifiers::CONTROL),
147 input(Key::Null, true, false, false),
148 ),
149 ] {
150 assert_eq!(Input::from(from), to, "{:?} -> {:?}", from, to);
151 }
152 }
153
154 #[test]
155 fn mouse_to_input() {
156 for (from, to) in [
157 (
158 mouse_event(MouseEventKind::ScrollDown, KeyModifiers::empty()),
159 input(Key::MouseScrollDown, false, false, false),
160 ),
161 (
162 mouse_event(MouseEventKind::ScrollUp, KeyModifiers::CONTROL),
163 input(Key::MouseScrollUp, true, false, false),
164 ),
165 (
166 mouse_event(MouseEventKind::ScrollUp, KeyModifiers::SHIFT),
167 input(Key::MouseScrollUp, false, false, true),
168 ),
169 (
170 mouse_event(MouseEventKind::ScrollDown, KeyModifiers::ALT),
171 input(Key::MouseScrollDown, false, true, false),
172 ),
173 (
174 mouse_event(
175 MouseEventKind::ScrollUp,
176 KeyModifiers::CONTROL | KeyModifiers::ALT,
177 ),
178 input(Key::MouseScrollUp, true, true, false),
179 ),
180 (
181 mouse_event(MouseEventKind::Moved, KeyModifiers::CONTROL),
182 input(Key::Null, true, false, false),
183 ),
184 ] {
185 assert_eq!(Input::from(from), to, "{:?} -> {:?}", from, to);
186 }
187 }
188
189 #[test]
190 fn event_to_input() {
191 for (from, to) in [
192 (
193 Event::Key(key_event(KeyCode::Char('a'), KeyModifiers::empty())),
194 input(Key::Char('a'), false, false, false),
195 ),
196 (
197 Event::Mouse(mouse_event(
198 MouseEventKind::ScrollDown,
199 KeyModifiers::empty(),
200 )),
201 input(Key::MouseScrollDown, false, false, false),
202 ),
203 (Event::FocusGained, input(Key::Null, false, false, false)),
204 ] {
205 assert_eq!(Input::from(from.clone()), to, "{:?} -> {:?}", from, to);
206 }
207 }
208
209 #[test]
211 fn ignore_key_release_event() {
212 let mut from = key_event(KeyCode::Char('a'), KeyModifiers::empty());
213 from.kind = KeyEventKind::Release;
214 let to = input(Key::Null, false, false, false);
215 assert_eq!(Input::from(from), to, "{:?} -> {:?}", from, to);
216 }
217}