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