1#[cfg(feature = "termina_0_1")]
2use termina_0_1 as termina;
3use terminput::{
4 Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers, MediaKeyCode,
5 ModifierDirection, ModifierKeyCode, MouseButton, MouseEvent, MouseEventKind, ScrollDirection,
6 UnsupportedEvent,
7};
8
9pub fn to_terminput(value: termina::Event) -> Result<Event, UnsupportedEvent> {
11 Ok(match value {
12 termina::Event::FocusIn => Event::FocusGained,
13 termina::Event::FocusOut => Event::FocusLost,
14 termina::Event::Key(key_event) => Event::Key(to_terminput_key(key_event)?),
15 termina::Event::Mouse(mouse_event) => Event::Mouse(to_terminput_mouse(mouse_event)),
16 termina::Event::Paste(value) => Event::Paste(value),
17 termina::Event::WindowResized(window_size) => Event::Resize {
18 cols: window_size.cols as u32,
19 rows: window_size.rows as u32,
20 },
21 event @ (termina::Event::Dcs(_) | termina::Event::Csi(_)) => {
22 Err(UnsupportedEvent(format!("{event:?}")))?
23 }
24 })
25}
26
27pub fn to_termina(value: Event) -> Result<termina::Event, UnsupportedEvent> {
29 Ok(match value {
30 Event::FocusGained => termina::Event::FocusIn,
31 Event::FocusLost => termina::Event::FocusOut,
32 Event::Key(key_event) => termina::Event::Key(to_termina_key(key_event)),
33 Event::Mouse(mouse_event) => termina::Event::Mouse(to_termina_mouse(mouse_event)?),
34 Event::Paste(value) => termina::Event::Paste(value),
35 Event::Resize { cols, rows } => termina::Event::WindowResized(termina::WindowSize {
36 cols: cols
37 .try_into()
38 .map_err(|e| UnsupportedEvent(format!("{e:?}")))?,
39 rows: rows
40 .try_into()
41 .map_err(|e| UnsupportedEvent(format!("{e:?}")))?,
42 pixel_width: None,
43 pixel_height: None,
44 }),
45 })
46}
47
48pub fn to_terminput_mouse(value: termina::event::MouseEvent) -> MouseEvent {
50 MouseEvent {
51 kind: mouse_kind_to_terminput(value.kind),
52 column: value.column,
53 row: value.row,
54 modifiers: key_modifiers_to_terminput(value.modifiers),
55 }
56}
57
58pub fn to_termina_mouse(value: MouseEvent) -> Result<termina::event::MouseEvent, UnsupportedEvent> {
60 Ok(termina::event::MouseEvent {
61 kind: mouse_kind_to_termina(value.kind)?,
62 column: value.column,
63 row: value.row,
64 modifiers: key_modifiers_to_termina(value.modifiers),
65 })
66}
67
68fn mouse_kind_to_terminput(value: termina::event::MouseEventKind) -> MouseEventKind {
69 match value {
70 termina::event::MouseEventKind::Down(button) => {
71 MouseEventKind::Down(mouse_button_to_terminput(button))
72 }
73 termina::event::MouseEventKind::Up(button) => {
74 MouseEventKind::Up(mouse_button_to_terminput(button))
75 }
76 termina::event::MouseEventKind::Drag(button) => {
77 MouseEventKind::Drag(mouse_button_to_terminput(button))
78 }
79 termina::event::MouseEventKind::Moved => MouseEventKind::Moved,
80 termina::event::MouseEventKind::ScrollDown => MouseEventKind::Scroll(ScrollDirection::Down),
81 termina::event::MouseEventKind::ScrollUp => MouseEventKind::Scroll(ScrollDirection::Up),
82 termina::event::MouseEventKind::ScrollLeft => MouseEventKind::Scroll(ScrollDirection::Left),
83 termina::event::MouseEventKind::ScrollRight => {
84 MouseEventKind::Scroll(ScrollDirection::Right)
85 }
86 }
87}
88
89fn mouse_kind_to_termina(
90 value: MouseEventKind,
91) -> Result<termina::event::MouseEventKind, UnsupportedEvent> {
92 Ok(match value {
93 MouseEventKind::Down(button) => {
94 termina::event::MouseEventKind::Down(mouse_button_to_termina(button)?)
95 }
96 MouseEventKind::Up(button) => {
97 termina::event::MouseEventKind::Up(mouse_button_to_termina(button)?)
98 }
99 MouseEventKind::Drag(button) => {
100 termina::event::MouseEventKind::Drag(mouse_button_to_termina(button)?)
101 }
102 MouseEventKind::Moved => termina::event::MouseEventKind::Moved,
103 MouseEventKind::Scroll(ScrollDirection::Down) => termina::event::MouseEventKind::ScrollDown,
104 MouseEventKind::Scroll(ScrollDirection::Up) => termina::event::MouseEventKind::ScrollUp,
105 MouseEventKind::Scroll(ScrollDirection::Left) => termina::event::MouseEventKind::ScrollLeft,
106 MouseEventKind::Scroll(ScrollDirection::Right) => {
107 termina::event::MouseEventKind::ScrollRight
108 }
109 })
110}
111
112fn mouse_button_to_terminput(value: termina::event::MouseButton) -> MouseButton {
113 match value {
114 termina::event::MouseButton::Left => MouseButton::Left,
115 termina::event::MouseButton::Right => MouseButton::Right,
116 termina::event::MouseButton::Middle => MouseButton::Middle,
117 }
118}
119
120fn mouse_button_to_termina(
121 value: MouseButton,
122) -> Result<termina::event::MouseButton, UnsupportedEvent> {
123 Ok(match value {
124 MouseButton::Left => termina::event::MouseButton::Left,
125 MouseButton::Right => termina::event::MouseButton::Right,
126 MouseButton::Middle => termina::event::MouseButton::Middle,
127 val @ MouseButton::Unknown => Err(UnsupportedEvent(format!("{val:?}")))?,
128 })
129}
130
131pub fn to_terminput_key(value: termina::event::KeyEvent) -> Result<KeyEvent, UnsupportedEvent> {
133 Ok(KeyEvent {
134 code: key_code_to_terminput(value.code)?,
135 modifiers: key_modifiers_to_terminput(value.modifiers),
136 kind: key_kind_to_terminput(value.kind),
137 state: key_state_to_terminput(value.state),
138 })
139}
140
141pub fn to_termina_key(value: KeyEvent) -> termina::event::KeyEvent {
143 termina::event::KeyEvent {
144 code: convert_termina_key_code(value.code, value.modifiers.intersects(KeyModifiers::SHIFT)),
145 modifiers: key_modifiers_to_termina(value.modifiers),
146 kind: key_kind_to_termina(value.kind),
147 state: key_state_to_termina(value.state),
148 }
149}
150
151fn key_code_to_terminput(value: termina::event::KeyCode) -> Result<KeyCode, UnsupportedEvent> {
152 Ok(match value {
153 termina::event::KeyCode::Backspace => KeyCode::Backspace,
154 termina::event::KeyCode::Enter => KeyCode::Enter,
155 termina::event::KeyCode::Left => KeyCode::Left,
156 termina::event::KeyCode::Right => KeyCode::Right,
157 termina::event::KeyCode::Up => KeyCode::Up,
158 termina::event::KeyCode::Down => KeyCode::Down,
159 termina::event::KeyCode::Home => KeyCode::Home,
160 termina::event::KeyCode::End => KeyCode::End,
161 termina::event::KeyCode::PageUp => KeyCode::PageUp,
162 termina::event::KeyCode::PageDown => KeyCode::PageDown,
163 termina::event::KeyCode::Tab => KeyCode::Tab,
164 termina::event::KeyCode::BackTab => KeyCode::Tab,
165 termina::event::KeyCode::Delete => KeyCode::Delete,
166 termina::event::KeyCode::Insert => KeyCode::Insert,
167 termina::event::KeyCode::Function(f) => KeyCode::F(f),
168 termina::event::KeyCode::Char(c) => KeyCode::Char(c),
169 termina::event::KeyCode::Escape => KeyCode::Esc,
170 termina::event::KeyCode::CapsLock => KeyCode::CapsLock,
171 termina::event::KeyCode::ScrollLock => KeyCode::ScrollLock,
172 termina::event::KeyCode::NumLock => KeyCode::NumLock,
173 termina::event::KeyCode::PrintScreen => KeyCode::PrintScreen,
174 termina::event::KeyCode::Pause => KeyCode::Pause,
175 termina::event::KeyCode::Menu => KeyCode::Menu,
176 termina::event::KeyCode::KeypadBegin => KeyCode::KeypadBegin,
177 termina::event::KeyCode::Media(m) => KeyCode::Media(media_code_to_terminput(m)),
178 termina::event::KeyCode::Modifier(m) => {
179 let (code, direction) = convert_modifier_key_code(m);
180 KeyCode::Modifier(code, direction)
181 }
182 termina::event::KeyCode::Null => Err(UnsupportedEvent(format!("{value:?}")))?,
183 })
184}
185
186fn convert_termina_key_code(value: KeyCode, shift: bool) -> termina::event::KeyCode {
187 match value {
188 KeyCode::Backspace => termina::event::KeyCode::Backspace,
189 KeyCode::Enter => termina::event::KeyCode::Enter,
190 KeyCode::Left => termina::event::KeyCode::Left,
191 KeyCode::Right => termina::event::KeyCode::Right,
192 KeyCode::Up => termina::event::KeyCode::Up,
193 KeyCode::Down => termina::event::KeyCode::Down,
194 KeyCode::Home => termina::event::KeyCode::Home,
195 KeyCode::End => termina::event::KeyCode::End,
196 KeyCode::PageUp => termina::event::KeyCode::PageUp,
197 KeyCode::PageDown => termina::event::KeyCode::PageDown,
198 KeyCode::Tab if shift => termina::event::KeyCode::BackTab,
199 KeyCode::Tab => termina::event::KeyCode::Tab,
200 KeyCode::Delete => termina::event::KeyCode::Delete,
201 KeyCode::Insert => termina::event::KeyCode::Insert,
202 KeyCode::F(f) => termina::event::KeyCode::Function(f),
203 KeyCode::Char(c) => termina::event::KeyCode::Char(c),
204 KeyCode::Esc => termina::event::KeyCode::Escape,
205 KeyCode::CapsLock => termina::event::KeyCode::CapsLock,
206 KeyCode::ScrollLock => termina::event::KeyCode::ScrollLock,
207 KeyCode::NumLock => termina::event::KeyCode::NumLock,
208 KeyCode::PrintScreen => termina::event::KeyCode::PrintScreen,
209 KeyCode::Pause => termina::event::KeyCode::Pause,
210 KeyCode::Menu => termina::event::KeyCode::Menu,
211 KeyCode::KeypadBegin => termina::event::KeyCode::KeypadBegin,
212 KeyCode::Media(m) => termina::event::KeyCode::Media(media_code_to_termina(m)),
213 KeyCode::Modifier(code, direction) => {
214 termina::event::KeyCode::Modifier(convert_termina_modifier_key_code(code, direction))
215 }
216 }
217}
218
219fn key_modifiers_to_terminput(value: termina::event::Modifiers) -> KeyModifiers {
220 let mut res = KeyModifiers::empty();
221 if value.intersects(termina::event::Modifiers::ALT) {
222 res |= KeyModifiers::ALT;
223 }
224 if value.intersects(termina::event::Modifiers::SHIFT) {
225 res |= KeyModifiers::SHIFT;
226 }
227 if value.intersects(termina::event::Modifiers::CONTROL) {
228 res |= KeyModifiers::CTRL;
229 }
230 if value.intersects(termina::event::Modifiers::SUPER) {
231 res |= KeyModifiers::SUPER;
232 }
233
234 res
235}
236
237fn key_modifiers_to_termina(value: KeyModifiers) -> termina::event::Modifiers {
238 let mut res = termina::event::Modifiers::empty();
239 if value.intersects(KeyModifiers::ALT) {
240 res |= termina::event::Modifiers::ALT;
241 }
242 if value.intersects(KeyModifiers::SHIFT) {
243 res |= termina::event::Modifiers::SHIFT;
244 }
245 if value.intersects(KeyModifiers::CTRL) {
246 res |= termina::event::Modifiers::CONTROL;
247 }
248 if value.intersects(KeyModifiers::SUPER) {
249 res |= termina::event::Modifiers::SUPER;
250 }
251
252 res
253}
254
255fn key_kind_to_terminput(value: termina::event::KeyEventKind) -> KeyEventKind {
256 match value {
257 termina::event::KeyEventKind::Press => KeyEventKind::Press,
258 termina::event::KeyEventKind::Repeat => KeyEventKind::Repeat,
259 termina::event::KeyEventKind::Release => KeyEventKind::Release,
260 }
261}
262
263fn key_kind_to_termina(value: KeyEventKind) -> termina::event::KeyEventKind {
264 match value {
265 KeyEventKind::Press => termina::event::KeyEventKind::Press,
266 KeyEventKind::Repeat => termina::event::KeyEventKind::Repeat,
267 KeyEventKind::Release => termina::event::KeyEventKind::Release,
268 }
269}
270
271fn media_code_to_terminput(value: termina::event::MediaKeyCode) -> MediaKeyCode {
272 match value {
273 termina::event::MediaKeyCode::Play => MediaKeyCode::Play,
274 termina::event::MediaKeyCode::Pause => MediaKeyCode::Pause,
275 termina::event::MediaKeyCode::PlayPause => MediaKeyCode::PlayPause,
276 termina::event::MediaKeyCode::Reverse => MediaKeyCode::Reverse,
277 termina::event::MediaKeyCode::Stop => MediaKeyCode::Stop,
278 termina::event::MediaKeyCode::FastForward => MediaKeyCode::FastForward,
279 termina::event::MediaKeyCode::Rewind => MediaKeyCode::Rewind,
280 termina::event::MediaKeyCode::TrackNext => MediaKeyCode::TrackNext,
281 termina::event::MediaKeyCode::TrackPrevious => MediaKeyCode::TrackPrevious,
282 termina::event::MediaKeyCode::Record => MediaKeyCode::Record,
283 termina::event::MediaKeyCode::LowerVolume => MediaKeyCode::LowerVolume,
284 termina::event::MediaKeyCode::RaiseVolume => MediaKeyCode::RaiseVolume,
285 termina::event::MediaKeyCode::MuteVolume => MediaKeyCode::MuteVolume,
286 }
287}
288
289fn media_code_to_termina(value: MediaKeyCode) -> termina::event::MediaKeyCode {
290 match value {
291 MediaKeyCode::Play => termina::event::MediaKeyCode::Play,
292 MediaKeyCode::Pause => termina::event::MediaKeyCode::Pause,
293 MediaKeyCode::PlayPause => termina::event::MediaKeyCode::PlayPause,
294 MediaKeyCode::Reverse => termina::event::MediaKeyCode::Reverse,
295 MediaKeyCode::Stop => termina::event::MediaKeyCode::Stop,
296 MediaKeyCode::FastForward => termina::event::MediaKeyCode::FastForward,
297 MediaKeyCode::Rewind => termina::event::MediaKeyCode::Rewind,
298 MediaKeyCode::TrackNext => termina::event::MediaKeyCode::TrackNext,
299 MediaKeyCode::TrackPrevious => termina::event::MediaKeyCode::TrackPrevious,
300 MediaKeyCode::Record => termina::event::MediaKeyCode::Record,
301 MediaKeyCode::LowerVolume => termina::event::MediaKeyCode::LowerVolume,
302 MediaKeyCode::RaiseVolume => termina::event::MediaKeyCode::RaiseVolume,
303 MediaKeyCode::MuteVolume => termina::event::MediaKeyCode::MuteVolume,
304 }
305}
306
307fn convert_modifier_key_code(
308 value: termina::event::ModifierKeyCode,
309) -> (ModifierKeyCode, ModifierDirection) {
310 match value {
311 termina::event::ModifierKeyCode::LeftShift => {
312 (ModifierKeyCode::Shift, ModifierDirection::Left)
313 }
314 termina::event::ModifierKeyCode::LeftControl => {
315 (ModifierKeyCode::Control, ModifierDirection::Left)
316 }
317 termina::event::ModifierKeyCode::LeftAlt => (ModifierKeyCode::Alt, ModifierDirection::Left),
318 termina::event::ModifierKeyCode::LeftSuper => {
319 (ModifierKeyCode::Super, ModifierDirection::Left)
320 }
321 termina::event::ModifierKeyCode::LeftHyper => {
322 (ModifierKeyCode::Hyper, ModifierDirection::Left)
323 }
324 termina::event::ModifierKeyCode::LeftMeta => {
325 (ModifierKeyCode::Meta, ModifierDirection::Left)
326 }
327 termina::event::ModifierKeyCode::RightShift => {
328 (ModifierKeyCode::Shift, ModifierDirection::Right)
329 }
330 termina::event::ModifierKeyCode::RightControl => {
331 (ModifierKeyCode::Control, ModifierDirection::Right)
332 }
333 termina::event::ModifierKeyCode::RightAlt => {
334 (ModifierKeyCode::Alt, ModifierDirection::Right)
335 }
336 termina::event::ModifierKeyCode::RightSuper => {
337 (ModifierKeyCode::Super, ModifierDirection::Right)
338 }
339 termina::event::ModifierKeyCode::RightHyper => {
340 (ModifierKeyCode::Hyper, ModifierDirection::Right)
341 }
342 termina::event::ModifierKeyCode::RightMeta => {
343 (ModifierKeyCode::Meta, ModifierDirection::Right)
344 }
345 termina::event::ModifierKeyCode::IsoLevel3Shift => {
346 (ModifierKeyCode::IsoLevel3Shift, ModifierDirection::Unknown)
347 }
348 termina::event::ModifierKeyCode::IsoLevel5Shift => {
349 (ModifierKeyCode::IsoLevel5Shift, ModifierDirection::Unknown)
350 }
351 }
352}
353
354fn convert_termina_modifier_key_code(
355 code: ModifierKeyCode,
356 direction: ModifierDirection,
357) -> termina::event::ModifierKeyCode {
358 match (code, direction) {
359 (ModifierKeyCode::Shift, ModifierDirection::Left | ModifierDirection::Unknown) => {
360 termina::event::ModifierKeyCode::LeftShift
361 }
362 (ModifierKeyCode::Control, ModifierDirection::Left | ModifierDirection::Unknown) => {
363 termina::event::ModifierKeyCode::LeftControl
364 }
365 (ModifierKeyCode::Alt, ModifierDirection::Left | ModifierDirection::Unknown) => {
366 termina::event::ModifierKeyCode::LeftAlt
367 }
368 (ModifierKeyCode::Super, ModifierDirection::Left | ModifierDirection::Unknown) => {
369 termina::event::ModifierKeyCode::LeftSuper
370 }
371 (ModifierKeyCode::Hyper, ModifierDirection::Left | ModifierDirection::Unknown) => {
372 termina::event::ModifierKeyCode::LeftHyper
373 }
374 (ModifierKeyCode::Meta, ModifierDirection::Left | ModifierDirection::Unknown) => {
375 termina::event::ModifierKeyCode::LeftMeta
376 }
377 (ModifierKeyCode::Shift, ModifierDirection::Right) => {
378 termina::event::ModifierKeyCode::RightShift
379 }
380 (ModifierKeyCode::Control, ModifierDirection::Right) => {
381 termina::event::ModifierKeyCode::RightControl
382 }
383 (ModifierKeyCode::Alt, ModifierDirection::Right) => {
384 termina::event::ModifierKeyCode::RightAlt
385 }
386 (ModifierKeyCode::Super, ModifierDirection::Right) => {
387 termina::event::ModifierKeyCode::RightSuper
388 }
389 (ModifierKeyCode::Hyper, ModifierDirection::Right) => {
390 termina::event::ModifierKeyCode::RightHyper
391 }
392 (ModifierKeyCode::Meta, ModifierDirection::Right) => {
393 termina::event::ModifierKeyCode::RightMeta
394 }
395 (ModifierKeyCode::IsoLevel3Shift, _) => termina::event::ModifierKeyCode::IsoLevel3Shift,
396 (ModifierKeyCode::IsoLevel5Shift, _) => termina::event::ModifierKeyCode::IsoLevel5Shift,
397 }
398}
399
400fn key_state_to_terminput(value: termina::event::KeyEventState) -> KeyEventState {
401 let mut state = KeyEventState::empty();
402 if value.intersects(termina::event::KeyEventState::KEYPAD) {
403 state |= KeyEventState::KEYPAD;
404 }
405 if value.intersects(termina::event::KeyEventState::CAPS_LOCK) {
406 state |= KeyEventState::CAPS_LOCK;
407 }
408 if value.intersects(termina::event::KeyEventState::NUM_LOCK) {
409 state |= KeyEventState::NUM_LOCK;
410 }
411 state
412}
413
414fn key_state_to_termina(value: KeyEventState) -> termina::event::KeyEventState {
415 let mut state = termina::event::KeyEventState::empty();
416 if value.intersects(KeyEventState::KEYPAD) {
417 state |= termina::event::KeyEventState::KEYPAD;
418 }
419 if value.intersects(KeyEventState::CAPS_LOCK) {
420 state |= termina::event::KeyEventState::CAPS_LOCK;
421 }
422 if value.intersects(KeyEventState::NUM_LOCK) {
423 state |= termina::event::KeyEventState::NUM_LOCK;
424 }
425 state
426}