1use crate::{Key, KeyInput, Mods};
42use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers, MediaKeyCode};
43
44impl From<KeyCode> for Key {
45 fn from(code: KeyCode) -> Self {
46 match code {
47 KeyCode::Backspace => Self::Backspace,
48 KeyCode::Enter => Self::Enter,
49 KeyCode::Left => Self::Left,
50 KeyCode::Right => Self::Right,
51 KeyCode::Up => Self::Up,
52 KeyCode::Down => Self::Down,
53 KeyCode::Home => Self::Home,
54 KeyCode::End => Self::End,
55 KeyCode::PageUp => Self::PageUp,
56 KeyCode::PageDown => Self::PageDown,
57 KeyCode::Tab => Self::Tab,
58 KeyCode::BackTab => Self::Backtab,
59 KeyCode::Delete => Self::Delete,
60 KeyCode::Insert => Self::Insert,
61 KeyCode::F(i) => Self::F(i),
62 KeyCode::Char(c) => Self::Char(c),
63 KeyCode::Esc => Self::Esc,
64 KeyCode::ScrollLock => Self::ScrollLock,
65 KeyCode::NumLock => Self::NumLock,
66 KeyCode::PrintScreen => Self::PrintScreen,
67 KeyCode::Menu => Self::Menu,
68 KeyCode::Media(MediaKeyCode::Play) => Self::Play,
69 KeyCode::Media(MediaKeyCode::Pause) => Self::Pause,
70 KeyCode::Media(MediaKeyCode::PlayPause) => Self::PlayPause,
71 KeyCode::Media(MediaKeyCode::Stop) => Self::Stop,
72 KeyCode::Media(MediaKeyCode::Rewind) => Self::Rewind,
73 KeyCode::Media(MediaKeyCode::TrackNext) => Self::NextTrack,
74 KeyCode::Media(MediaKeyCode::TrackPrevious) => Self::PrevTrack,
75 KeyCode::Media(MediaKeyCode::LowerVolume) => Self::VolumeDown,
76 KeyCode::Media(MediaKeyCode::RaiseVolume) => Self::VolumeUp,
77 KeyCode::Media(MediaKeyCode::MuteVolume) => Self::Mute,
78 KeyCode::Modifier(_) | KeyCode::Null => Self::Ignored,
79 _ => Self::Unidentified,
80 }
81 }
82}
83
84impl From<KeyModifiers> for Mods {
85 fn from(from: KeyModifiers) -> Self {
86 let mut to = Mods::NONE;
87 if from.contains(KeyModifiers::CONTROL) {
88 to |= Mods::CTRL;
89 }
90 if from.contains(KeyModifiers::ALT) {
91 to |= Mods::ALT;
92 }
93 if from.contains(KeyModifiers::SUPER) {
94 to |= Mods::SUPER;
95 }
96 if from.contains(KeyModifiers::META) {
97 to |= Mods::CMD;
98 }
99 to
100 }
101}
102
103impl From<&KeyEvent> for KeyInput {
104 fn from(event: &KeyEvent) -> Self {
105 let key: Key = event.code.into();
106 let mods = event.modifiers.into();
107 Self::new(key, mods)
108 }
109}
110
111impl From<KeyEvent> for KeyInput {
112 fn from(event: KeyEvent) -> Self {
113 Self::from(&event)
114 }
115}
116
117impl From<&Event> for KeyInput {
118 fn from(event: &Event) -> Self {
119 match event {
120 Event::Key(event) => event.into(),
121 _ => Key::Ignored.into(),
122 }
123 }
124}
125
126impl From<Event> for KeyInput {
127 fn from(event: Event) -> Self {
128 Self::from(&event)
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135 use crossterm::event::{KeyEventKind, KeyEventState, ModifierKeyCode};
136
137 #[test]
138 fn convert_key_code() {
139 assert_eq!(Key::from(KeyCode::Backspace), Key::Backspace);
140 assert_eq!(Key::from(KeyCode::Char('a')), Key::Char('a'));
141 assert_eq!(Key::from(KeyCode::Char('A')), Key::Char('A'));
142 assert_eq!(Key::from(KeyCode::KeypadBegin), Key::Unidentified);
143 assert_eq!(Key::from(KeyCode::Null), Key::Ignored);
144 assert_eq!(
145 Key::from(KeyCode::Modifier(ModifierKeyCode::LeftControl)),
146 Key::Ignored,
147 );
148 assert_eq!(Key::from(KeyCode::Media(MediaKeyCode::Play)), Key::Play);
149 assert_eq!(Key::from(KeyCode::F(12)), Key::F(12));
150 }
151
152 #[test]
153 fn convert_modifiers() {
154 assert_eq!(Mods::from(KeyModifiers::NONE), Mods::NONE);
155 assert_eq!(
156 Mods::from(
157 KeyModifiers::CONTROL
158 | KeyModifiers::SHIFT
159 | KeyModifiers::ALT
160 | KeyModifiers::META
161 ),
162 Mods::CTRL | Mods::ALT | Mods::CMD,
163 );
164 assert_eq!(Mods::from(KeyModifiers::SUPER), Mods::SUPER);
165 }
166
167 #[test]
168 fn convert_key_event() {
169 assert_eq!(
170 KeyInput::from(KeyEvent {
171 code: KeyCode::Char('A'),
172 modifiers: KeyModifiers::CONTROL | KeyModifiers::SHIFT,
173 kind: KeyEventKind::Press,
174 state: KeyEventState::NONE,
175 }),
176 KeyInput::new('A', Mods::CTRL),
177 );
178 }
179
180 #[test]
181 fn convert_event() {
182 assert_eq!(
183 KeyInput::from(Event::Key(KeyEvent {
184 code: KeyCode::Char('A'),
185 modifiers: KeyModifiers::CONTROL | KeyModifiers::SHIFT,
186 kind: KeyEventKind::Press,
187 state: KeyEventState::NONE,
188 })),
189 KeyInput::new('A', Mods::CTRL),
190 );
191 assert_eq!(
192 KeyInput::from(Event::FocusGained),
193 KeyInput::new(Key::Ignored, Mods::NONE),
194 );
195 }
196}