terminput_termion/
lib.rs

1#![deny(missing_docs)]
2#![doc = include_str!("../README.md")]
3
4use terminput::{
5    Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers, MouseButton, MouseEvent,
6    MouseEventKind, ScrollDirection, UnsupportedEvent,
7};
8
9/// Converts the termion [event](termion::event::Event) to a terminput [event](Event).
10pub fn to_terminput(value: termion::event::Event) -> Result<Event, UnsupportedEvent> {
11    Ok(match value {
12        termion::event::Event::Key(key_event) => Event::Key(key_event_to_terminput(key_event)?),
13        termion::event::Event::Mouse(mouse_event) => {
14            Event::Mouse(mouse_event_to_terminput(mouse_event))
15        }
16        termion::event::Event::Unsupported(val) => Err(UnsupportedEvent(format!("{val:?}")))?,
17    })
18}
19
20/// Converts the terminput [event](Event) to a termion [event](termion::event::Event).
21pub fn to_termion(value: Event) -> Result<termion::event::Event, UnsupportedEvent> {
22    Ok(match value {
23        Event::Key(key_event) => termion::event::Event::Key(key_event_to_termion(key_event)?),
24        Event::Mouse(mouse_event) => {
25            termion::event::Event::Mouse(mouse_event_to_termion(mouse_event)?)
26        }
27        Event::FocusGained | Event::FocusLost | Event::Paste(_) | Event::Resize { .. } => {
28            Err(UnsupportedEvent(format!("{value:?}")))?
29        }
30    })
31}
32
33fn key_event_to_terminput(value: termion::event::Key) -> Result<KeyEvent, UnsupportedEvent> {
34    Ok(match value {
35        termion::event::Key::Backspace => KeyEvent {
36            code: KeyCode::Backspace,
37            modifiers: KeyModifiers::NONE,
38            kind: KeyEventKind::Press,
39            state: KeyEventState::empty(),
40        },
41        termion::event::Key::Left => KeyEvent {
42            code: KeyCode::Left,
43            modifiers: KeyModifiers::NONE,
44            kind: KeyEventKind::Press,
45            state: KeyEventState::empty(),
46        },
47        termion::event::Key::ShiftLeft => KeyEvent {
48            code: KeyCode::Left,
49            modifiers: KeyModifiers::SHIFT,
50            kind: KeyEventKind::Press,
51            state: KeyEventState::empty(),
52        },
53        termion::event::Key::AltLeft => KeyEvent {
54            code: KeyCode::Left,
55            modifiers: KeyModifiers::ALT,
56            kind: KeyEventKind::Press,
57            state: KeyEventState::empty(),
58        },
59        termion::event::Key::CtrlLeft => KeyEvent {
60            code: KeyCode::Left,
61            modifiers: KeyModifiers::CTRL,
62            kind: KeyEventKind::Press,
63            state: KeyEventState::empty(),
64        },
65        termion::event::Key::Right => KeyEvent {
66            code: KeyCode::Right,
67            modifiers: KeyModifiers::NONE,
68            kind: KeyEventKind::Press,
69            state: KeyEventState::empty(),
70        },
71        termion::event::Key::ShiftRight => KeyEvent {
72            code: KeyCode::Right,
73            modifiers: KeyModifiers::SHIFT,
74            kind: KeyEventKind::Press,
75            state: KeyEventState::empty(),
76        },
77        termion::event::Key::AltRight => KeyEvent {
78            code: KeyCode::Right,
79            modifiers: KeyModifiers::ALT,
80            kind: KeyEventKind::Press,
81            state: KeyEventState::empty(),
82        },
83        termion::event::Key::CtrlRight => KeyEvent {
84            code: KeyCode::Right,
85            modifiers: KeyModifiers::CTRL,
86            kind: KeyEventKind::Press,
87            state: KeyEventState::empty(),
88        },
89        termion::event::Key::Up => KeyEvent {
90            code: KeyCode::Up,
91            modifiers: KeyModifiers::NONE,
92            kind: KeyEventKind::Press,
93            state: KeyEventState::empty(),
94        },
95        termion::event::Key::ShiftUp => KeyEvent {
96            code: KeyCode::Up,
97            modifiers: KeyModifiers::SHIFT,
98            kind: KeyEventKind::Press,
99            state: KeyEventState::empty(),
100        },
101        termion::event::Key::AltUp => KeyEvent {
102            code: KeyCode::Up,
103            modifiers: KeyModifiers::ALT,
104            kind: KeyEventKind::Press,
105            state: KeyEventState::empty(),
106        },
107        termion::event::Key::CtrlUp => KeyEvent {
108            code: KeyCode::Up,
109            modifiers: KeyModifiers::CTRL,
110            kind: KeyEventKind::Press,
111            state: KeyEventState::empty(),
112        },
113        termion::event::Key::Down => KeyEvent {
114            code: KeyCode::Down,
115            modifiers: KeyModifiers::NONE,
116            kind: KeyEventKind::Press,
117            state: KeyEventState::empty(),
118        },
119        termion::event::Key::ShiftDown => KeyEvent {
120            code: KeyCode::Down,
121            modifiers: KeyModifiers::SHIFT,
122            kind: KeyEventKind::Press,
123            state: KeyEventState::empty(),
124        },
125        termion::event::Key::AltDown => KeyEvent {
126            code: KeyCode::Down,
127            modifiers: KeyModifiers::ALT,
128            kind: KeyEventKind::Press,
129            state: KeyEventState::empty(),
130        },
131        termion::event::Key::CtrlDown => KeyEvent {
132            code: KeyCode::Down,
133            modifiers: KeyModifiers::CTRL,
134            kind: KeyEventKind::Press,
135            state: KeyEventState::empty(),
136        },
137        termion::event::Key::Home => KeyEvent {
138            code: KeyCode::Home,
139            modifiers: KeyModifiers::NONE,
140            kind: KeyEventKind::Press,
141            state: KeyEventState::empty(),
142        },
143        termion::event::Key::CtrlHome => KeyEvent {
144            code: KeyCode::Home,
145            modifiers: KeyModifiers::CTRL,
146            kind: KeyEventKind::Press,
147            state: KeyEventState::empty(),
148        },
149        termion::event::Key::End => KeyEvent {
150            code: KeyCode::End,
151            modifiers: KeyModifiers::NONE,
152            kind: KeyEventKind::Press,
153            state: KeyEventState::empty(),
154        },
155        termion::event::Key::CtrlEnd => KeyEvent {
156            code: KeyCode::End,
157            modifiers: KeyModifiers::CTRL,
158            kind: KeyEventKind::Press,
159            state: KeyEventState::empty(),
160        },
161        termion::event::Key::PageUp => KeyEvent {
162            code: KeyCode::PageUp,
163            modifiers: KeyModifiers::NONE,
164            kind: KeyEventKind::Press,
165            state: KeyEventState::empty(),
166        },
167        termion::event::Key::PageDown => KeyEvent {
168            code: KeyCode::PageDown,
169            modifiers: KeyModifiers::NONE,
170            kind: KeyEventKind::Press,
171            state: KeyEventState::empty(),
172        },
173        termion::event::Key::BackTab => KeyEvent {
174            code: KeyCode::Tab,
175            modifiers: KeyModifiers::SHIFT,
176            kind: KeyEventKind::Press,
177            state: KeyEventState::empty(),
178        },
179        termion::event::Key::Delete => KeyEvent {
180            code: KeyCode::Delete,
181            modifiers: KeyModifiers::NONE,
182            kind: KeyEventKind::Press,
183            state: KeyEventState::empty(),
184        },
185        termion::event::Key::Insert => KeyEvent {
186            code: KeyCode::Insert,
187            modifiers: KeyModifiers::NONE,
188            kind: KeyEventKind::Press,
189            state: KeyEventState::empty(),
190        },
191        termion::event::Key::F(f) => KeyEvent {
192            code: KeyCode::F(f),
193            modifiers: KeyModifiers::NONE,
194            kind: KeyEventKind::Press,
195            state: KeyEventState::empty(),
196        },
197        termion::event::Key::Char('\n') => KeyEvent {
198            code: KeyCode::Enter,
199            modifiers: KeyModifiers::NONE,
200            kind: KeyEventKind::Press,
201            state: KeyEventState::empty(),
202        },
203        termion::event::Key::Char('\t') => KeyEvent {
204            code: KeyCode::Tab,
205            modifiers: KeyModifiers::NONE,
206            kind: KeyEventKind::Press,
207            state: KeyEventState::empty(),
208        },
209        termion::event::Key::Char(c) => KeyEvent {
210            code: KeyCode::Char(c),
211            modifiers: KeyModifiers::NONE,
212            kind: KeyEventKind::Press,
213            state: KeyEventState::empty(),
214        },
215        termion::event::Key::Alt('\n') => KeyEvent {
216            code: KeyCode::Enter,
217            modifiers: KeyModifiers::ALT,
218            kind: KeyEventKind::Press,
219            state: KeyEventState::empty(),
220        },
221        termion::event::Key::Alt('\t') => KeyEvent {
222            code: KeyCode::Tab,
223            modifiers: KeyModifiers::ALT,
224            kind: KeyEventKind::Press,
225            state: KeyEventState::empty(),
226        },
227        termion::event::Key::Alt(c) => KeyEvent {
228            code: KeyCode::Char(c),
229            modifiers: KeyModifiers::ALT,
230            kind: KeyEventKind::Press,
231            state: KeyEventState::empty(),
232        },
233        termion::event::Key::Ctrl('\n') => KeyEvent {
234            code: KeyCode::Enter,
235            modifiers: KeyModifiers::CTRL,
236            kind: KeyEventKind::Press,
237            state: KeyEventState::empty(),
238        },
239        termion::event::Key::Ctrl('\t') => KeyEvent {
240            code: KeyCode::Tab,
241            modifiers: KeyModifiers::CTRL,
242            kind: KeyEventKind::Press,
243            state: KeyEventState::empty(),
244        },
245        termion::event::Key::Ctrl(c) => KeyEvent {
246            code: KeyCode::Char(c),
247            modifiers: KeyModifiers::CTRL,
248            kind: KeyEventKind::Press,
249            state: KeyEventState::empty(),
250        },
251        termion::event::Key::Esc => KeyEvent {
252            code: KeyCode::Esc,
253            modifiers: KeyModifiers::NONE,
254            kind: KeyEventKind::Press,
255            state: KeyEventState::empty(),
256        },
257        _ => Err(UnsupportedEvent(format!("{value:?}")))?,
258    })
259}
260
261fn key_event_to_termion(value: KeyEvent) -> Result<termion::event::Key, UnsupportedEvent> {
262    if value.kind != KeyEventKind::Press {
263        return Err(UnsupportedEvent(format!("{value:?}")));
264    }
265    if value.modifiers.intersects(KeyModifiers::CTRL) {
266        match value.code {
267            KeyCode::Char(c) => return Ok(termion::event::Key::Ctrl(c)),
268            KeyCode::Left => return Ok(termion::event::Key::CtrlLeft),
269            KeyCode::Right => return Ok(termion::event::Key::CtrlRight),
270            KeyCode::Up => return Ok(termion::event::Key::CtrlUp),
271            KeyCode::Down => return Ok(termion::event::Key::CtrlDown),
272            _ => {}
273        }
274    }
275    if value.modifiers.intersects(KeyModifiers::ALT) {
276        match value.code {
277            KeyCode::Char(c) => return Ok(termion::event::Key::Alt(c)),
278            KeyCode::Left => return Ok(termion::event::Key::AltLeft),
279            KeyCode::Right => return Ok(termion::event::Key::AltRight),
280            KeyCode::Up => return Ok(termion::event::Key::AltUp),
281            KeyCode::Down => return Ok(termion::event::Key::AltDown),
282            _ => {}
283        }
284    }
285    if value.modifiers.intersects(KeyModifiers::SHIFT) {
286        match value.code {
287            KeyCode::Left => return Ok(termion::event::Key::ShiftLeft),
288            KeyCode::Right => return Ok(termion::event::Key::ShiftRight),
289            KeyCode::Up => return Ok(termion::event::Key::ShiftUp),
290            KeyCode::Down => return Ok(termion::event::Key::ShiftDown),
291            _ => {}
292        }
293    }
294    Ok(match value.code {
295        KeyCode::Backspace => termion::event::Key::Backspace,
296        KeyCode::Enter => termion::event::Key::Char('\n'),
297        KeyCode::Left => termion::event::Key::Left,
298        KeyCode::Right => termion::event::Key::Right,
299        KeyCode::Up => termion::event::Key::Up,
300        KeyCode::Down => termion::event::Key::Down,
301        KeyCode::Home => termion::event::Key::Home,
302        KeyCode::End => termion::event::Key::End,
303        KeyCode::PageUp => termion::event::Key::PageUp,
304        KeyCode::PageDown => termion::event::Key::PageDown,
305        KeyCode::Tab if value.modifiers.intersects(KeyModifiers::SHIFT) => {
306            termion::event::Key::BackTab
307        }
308        KeyCode::Tab => termion::event::Key::Char('\t'),
309
310        KeyCode::Delete => termion::event::Key::Delete,
311        KeyCode::Insert => termion::event::Key::Insert,
312        KeyCode::F(f) => termion::event::Key::F(f),
313        KeyCode::Char(c) => termion::event::Key::Char(c),
314        KeyCode::Esc => termion::event::Key::Esc,
315        KeyCode::CapsLock
316        | KeyCode::NumLock
317        | KeyCode::ScrollLock
318        | KeyCode::PrintScreen
319        | KeyCode::Pause
320        | KeyCode::Menu
321        | KeyCode::KeypadBegin
322        | KeyCode::Media(_)
323        | KeyCode::Modifier(_, _) => Err(UnsupportedEvent(format!("{value:?}")))?,
324    })
325}
326
327fn mouse_event_to_terminput(value: termion::event::MouseEvent) -> MouseEvent {
328    match value {
329        termion::event::MouseEvent::Press(termion::event::MouseButton::Left, column, row) => {
330            MouseEvent {
331                kind: MouseEventKind::Down(MouseButton::Left),
332                row: row - 1,
333                column: column - 1,
334                modifiers: KeyModifiers::NONE,
335            }
336        }
337        termion::event::MouseEvent::Press(termion::event::MouseButton::Right, column, row) => {
338            MouseEvent {
339                kind: MouseEventKind::Down(MouseButton::Right),
340                row: row - 1,
341                column: column - 1,
342                modifiers: KeyModifiers::NONE,
343            }
344        }
345        termion::event::MouseEvent::Press(termion::event::MouseButton::Middle, column, row) => {
346            MouseEvent {
347                kind: MouseEventKind::Down(MouseButton::Right),
348                row: row - 1,
349                column: column - 1,
350                modifiers: KeyModifiers::NONE,
351            }
352        }
353        termion::event::MouseEvent::Press(termion::event::MouseButton::WheelDown, row, column) => {
354            MouseEvent {
355                kind: MouseEventKind::Scroll(ScrollDirection::Down),
356                row: row - 1,
357                column: column - 1,
358                modifiers: KeyModifiers::NONE,
359            }
360        }
361        termion::event::MouseEvent::Press(termion::event::MouseButton::WheelUp, row, column) => {
362            MouseEvent {
363                kind: MouseEventKind::Scroll(ScrollDirection::Up),
364                row: row - 1,
365                column: column - 1,
366                modifiers: KeyModifiers::NONE,
367            }
368        }
369        termion::event::MouseEvent::Press(termion::event::MouseButton::WheelLeft, row, column) => {
370            MouseEvent {
371                kind: MouseEventKind::Scroll(ScrollDirection::Left),
372                row: row - 1,
373                column: column - 1,
374                modifiers: KeyModifiers::NONE,
375            }
376        }
377        termion::event::MouseEvent::Press(termion::event::MouseButton::WheelRight, row, column) => {
378            MouseEvent {
379                kind: MouseEventKind::Scroll(ScrollDirection::Right),
380                row: row - 1,
381                column: column - 1,
382                modifiers: KeyModifiers::NONE,
383            }
384        }
385        termion::event::MouseEvent::Release(column, row) => MouseEvent {
386            kind: MouseEventKind::Up(MouseButton::Unknown),
387            row: row - 1,
388            column: column - 1,
389            modifiers: KeyModifiers::NONE,
390        },
391        termion::event::MouseEvent::Hold(column, row) => MouseEvent {
392            kind: MouseEventKind::Drag(MouseButton::Unknown),
393            row: row - 1,
394            column: column - 1,
395            modifiers: KeyModifiers::NONE,
396        },
397    }
398}
399
400fn mouse_event_to_termion(
401    value: MouseEvent,
402) -> Result<termion::event::MouseEvent, UnsupportedEvent> {
403    let column = value.column + 1;
404    let row = value.row + 1;
405    Ok(match value.kind {
406        MouseEventKind::Down(MouseButton::Left) => {
407            termion::event::MouseEvent::Press(termion::event::MouseButton::Left, column, row)
408        }
409        MouseEventKind::Down(MouseButton::Right) => {
410            termion::event::MouseEvent::Press(termion::event::MouseButton::Right, column, row)
411        }
412        MouseEventKind::Down(MouseButton::Middle) => {
413            termion::event::MouseEvent::Press(termion::event::MouseButton::Middle, column, row)
414        }
415        val @ MouseEventKind::Down(MouseButton::Unknown) => {
416            Err(UnsupportedEvent(format!("{val:?}")))?
417        }
418        MouseEventKind::Up(_) => termion::event::MouseEvent::Release(column, row),
419        MouseEventKind::Drag(_) => termion::event::MouseEvent::Hold(column, row),
420        val @ MouseEventKind::Moved => Err(UnsupportedEvent(format!("{val:?}")))?,
421        MouseEventKind::Scroll(ScrollDirection::Down) => {
422            termion::event::MouseEvent::Press(termion::event::MouseButton::WheelDown, column, row)
423        }
424        MouseEventKind::Scroll(ScrollDirection::Up) => {
425            termion::event::MouseEvent::Press(termion::event::MouseButton::WheelUp, column, row)
426        }
427        MouseEventKind::Scroll(ScrollDirection::Left) => {
428            termion::event::MouseEvent::Press(termion::event::MouseButton::WheelLeft, column, row)
429        }
430        MouseEventKind::Scroll(ScrollDirection::Right) => {
431            termion::event::MouseEvent::Press(termion::event::MouseButton::WheelRight, column, row)
432        }
433    })
434}