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
9pub 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
20pub 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}