Skip to main content

zui_core/
key.rs

1use std::{io::Error, sync::mpsc::Receiver, thread, time::Duration};
2
3// Key Enum definitions
4// A key (Shamefully Copied from Termion (How do I give credit!?))
5#[derive(Debug, Clone, PartialEq, Eq, Hash)]
6pub enum Key {
7    /// Backspace.
8    Backspace,
9    /// Enter.
10    Enter,
11    /// Tab.
12    Tab,
13    /// Left arrow.
14    Left,
15    /// Right arrow.
16    Right,
17    /// Up arrow.
18    Up,
19    /// Down arrow.
20    Down,
21    /// Home key.
22    Home,
23    /// End key.
24    End,
25    /// Page Up key.
26    PageUp,
27    /// Page Down key.
28    PageDown,
29    /// Backward Tab key.
30    BackTab,
31    /// Delete key.
32    Delete,
33    /// Insert key.
34    Insert,
35    /// Function keys.
36    ///
37    /// Only function keys 1 through 12 are supported.
38    F(u8),
39    /// Normal character.
40    Char(char),
41    // Number
42    Num(u8),
43    /// Ctrl modified character.
44    /// Note that certain keys may not be modifiable with `ctrl`, due to limitations of terminals.
45    Ctrl(char),
46    // Alt modified character
47    Alt(char),
48    /// Null byte.
49    Null,
50    /// Esc key.
51    Esc,
52}
53
54pub struct KeyIterator {
55    bytes: Receiver<Result<u8, Error>>,
56}
57
58impl KeyIterator {
59    pub fn from(rx: Receiver<Result<u8, Error>>) -> KeyIterator {
60        KeyIterator { bytes: rx }
61    }
62}
63
64impl Iterator for KeyIterator {
65    type Item = Key;
66
67    fn next(&mut self) -> Option<Key> {
68        from_byte(&mut self.bytes)
69    }
70}
71
72fn from_byte(i: &mut Receiver<Result<u8, Error>>) -> Option<Key> {
73    let c = i.recv();
74    match c {
75        Ok(c) => {
76            let c = c.unwrap();
77            if c.is_ascii() {
78                match c {
79                    // Ctrl-Characters
80                    1..=8 | 10..=12 | 14..=26 => Some(Key::Ctrl((c + 96) as char)),
81
82                    13 => Some(Key::Enter),
83                    9 => Some(Key::Tab),
84                    // Escape Sequences... AKA Hard Part
85                    27 => {
86                        //TODO: Fix this delay of the main thread (maybe relegate basic processing to spawn)
87                        thread::sleep(Duration::from_micros(100));
88                        match i.try_recv() {
89                            Ok(x) => {
90                                match x {
91                                    // F1-F4
92                                    Ok(79) => match i.try_recv().unwrap() {
93                                        Ok(r) => match r as char {
94                                            'P' => Some(Key::F(1)),
95                                            'Q' => Some(Key::F(2)),
96                                            'R' => Some(Key::F(3)),
97                                            'S' => Some(Key::F(4)),
98                                            _ => Some(Key::Char(r as char)),
99                                        },
100                                        Err(_e) => Some(Key::Null),
101                                    },
102                                    Ok(91) => match i.try_recv().unwrap() {
103                                        Ok(r) => match r {
104                                            65 => Some(Key::Up),
105                                            66 => Some(Key::Down),
106                                            67 => Some(Key::Right),
107                                            68 => Some(Key::Left),
108                                            _ => Some(Key::Char(r as char)),
109                                        },
110                                        Err(_e) => Some(Key::Null),
111                                    },
112                                    Ok(97..=122) => Some(Key::Alt(x.unwrap() as char)),
113                                    _ => Some(Key::Null),
114                                }
115                            }
116                            Err(_e) => Some(Key::Esc),
117                        }
118                    }
119
120                    // Numbers
121                    48..=57 => Some(Key::Num(c - 48)),
122
123                    // Alphabet
124                    127 => Some(Key::Backspace),
125
126                    97..=122 => Some(Key::Char(c as char)),
127                    // Key not recognized, but user can parse it
128                    _ => Some(Key::Char(c as char)),
129                }
130            } else {
131                println!("{}", c);
132                None
133            }
134        }
135        Err(_e) => Some(Key::Null),
136    }
137}