requestty_ui/events/
termion.rs1use std::{
2 convert::{TryFrom, TryInto},
3 fmt,
4 io::{self, stdin, Stdin},
5};
6
7use termion::{
8 event,
9 input::{self, TermRead},
10};
11
12use super::EventIterator;
13
14#[cfg_attr(docsrs, doc(cfg(feature = "termion")))]
16pub struct TermionEvents {
17 events: input::Keys<Stdin>,
18}
19
20struct Dash;
21
22impl fmt::Debug for Dash {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 f.write_str("_")
25 }
26}
27
28impl fmt::Debug for TermionEvents {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 f.debug_struct("TermionEvents")
31 .field("events", &Dash)
32 .finish()
33 }
34}
35
36impl TermionEvents {
37 pub fn new() -> Self {
39 Self {
40 events: stdin().keys(),
41 }
42 }
43}
44
45impl Default for TermionEvents {
46 fn default() -> Self {
47 Self::new()
48 }
49}
50
51impl EventIterator for TermionEvents {
52 fn next_event(&mut self) -> io::Result<super::KeyEvent> {
53 let e = self
54 .events
55 .next()
56 .expect("TermionEvents ran out of user input!?")?;
57 e.try_into()
58 }
59}
60
61impl TryFrom<event::Key> for super::KeyEvent {
62 type Error = io::Error;
63
64 fn try_from(key: event::Key) -> io::Result<super::KeyEvent> {
65 let key = match key {
66 event::Key::Backspace => super::KeyCode::Backspace.into(),
67 event::Key::Left => super::KeyCode::Left.into(),
68 event::Key::Right => super::KeyCode::Right.into(),
69 event::Key::Up => super::KeyCode::Up.into(),
70 event::Key::Down => super::KeyCode::Down.into(),
71 event::Key::Home => super::KeyCode::Home.into(),
72 event::Key::End => super::KeyCode::End.into(),
73 event::Key::PageUp => super::KeyCode::PageUp.into(),
74 event::Key::PageDown => super::KeyCode::PageDown.into(),
75 event::Key::BackTab => super::KeyCode::BackTab.into(),
76 event::Key::Delete => super::KeyCode::Delete.into(),
77 event::Key::Insert => super::KeyCode::Insert.into(),
78 event::Key::F(n) => super::KeyCode::F(n).into(),
79 event::Key::Char('\n') => super::KeyCode::Enter.into(),
80 event::Key::Char('\t') => super::KeyCode::Tab.into(),
81 event::Key::Char(c) => super::KeyCode::Char(c).into(),
82 event::Key::Alt(c) => parse_char(c, super::KeyModifiers::ALT)?,
83 event::Key::Ctrl(c) => parse_char(c, super::KeyModifiers::CONTROL)?,
84 event::Key::Null => super::KeyCode::Null.into(),
85 event::Key::Esc => super::KeyCode::Esc.into(),
86 _ => unreachable!(),
87 };
88
89 Ok(key)
90 }
91}
92
93fn parse_char(mut c: char, mut modifiers: super::KeyModifiers) -> io::Result<super::KeyEvent> {
94 let code = loop {
95 if c as u32 >= 256 {
96 break super::KeyCode::Char(c);
97 }
98
99 let k = match event::parse_event(c as u8, &mut std::iter::empty())? {
100 event::Event::Key(k) => k,
101 _ => match char::try_from(c as u32) {
102 Ok(c) => break super::KeyCode::Char(c),
103 Err(_) => return Err(io::Error::other("Could not parse an event")),
104 },
105 };
106
107 match k {
108 event::Key::Backspace => break super::KeyCode::Backspace,
109 event::Key::Left => break super::KeyCode::Left,
110 event::Key::Right => break super::KeyCode::Right,
111 event::Key::Up => break super::KeyCode::Up,
112 event::Key::Down => break super::KeyCode::Down,
113 event::Key::Home => break super::KeyCode::Home,
114 event::Key::End => break super::KeyCode::End,
115 event::Key::PageUp => break super::KeyCode::PageUp,
116 event::Key::PageDown => break super::KeyCode::PageDown,
117 event::Key::BackTab => break super::KeyCode::BackTab,
118 event::Key::Delete => break super::KeyCode::Delete,
119 event::Key::Insert => break super::KeyCode::Insert,
120 event::Key::F(n) => break super::KeyCode::F(n),
121 event::Key::Char('\n') => break super::KeyCode::Enter,
122 event::Key::Char('\t') => break super::KeyCode::Tab,
123 event::Key::Char(c @ 'A'..='Z') => {
124 modifiers |= super::KeyModifiers::SHIFT;
125 break super::KeyCode::Char(c);
126 }
127 event::Key::Char(c) => break super::KeyCode::Char(c),
128 event::Key::Alt(new_c) => {
129 modifiers |= super::KeyModifiers::ALT;
130 c = new_c
131 }
132 event::Key::Ctrl(new_c) => {
133 modifiers |= super::KeyModifiers::CONTROL;
134 c = new_c
135 }
136 event::Key::Null => break super::KeyCode::Null,
137 event::Key::Esc => break super::KeyCode::Esc,
138 _ => unreachable!(),
139 }
140 };
141
142 Ok(super::KeyEvent::new(code, modifiers))
143}