requestty_ui/events/
termion.rs

1use 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/// An iterator over the input keys using the `termion` crate
15#[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    /// Creates a new `TermionEvents` using stdin
38    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}