1 //! Mouse and key events.
2
3 use std::io::{Error, ErrorKind};
4 use std::ascii::AsciiExt;
5 use std::str;
6
7 /// An event reported by the terminal.
8 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
9 pub enum Event {
10 /// A key press.
11 Key(Key),
12 /// A mouse button press, release or wheel use at specific coordinates.
13 Mouse(MouseEvent),
14 /// An event that cannot currently be evaluated.
15 Unsupported(Vec<u8>),
16 }
17
18 /// A mouse related event.
19 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
20 pub enum MouseEvent {
21 /// A mouse button was pressed.
22 ///
23 /// The coordinates are one-based.
24 Press(MouseButton, u16, u16),
25 /// A mouse button was released.
26 ///
27 /// The coordinates are one-based.
28 Release(u16, u16),
29 /// A mouse button is held over the given coordinates.
30 ///
31 /// The coordinates are one-based.
32 Hold(u16, u16),
33 }
34
35 /// A mouse button.
36 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
37 pub enum MouseButton {
38 /// The left mouse button.
39 Left,
40 /// The right mouse button.
41 Right,
42 /// The middle mouse button.
43 Middle,
44 /// Mouse wheel is going up.
45 ///
46 /// This event is typically only used with Mouse::Press.
47 WheelUp,
48 /// Mouse wheel is going down.
49 ///
50 /// This event is typically only used with Mouse::Press.
51 WheelDown,
52 }
53
54 /// A key.
55 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
56 pub enum Key {
57 /// Backspace.
58 Backspace,
59 /// Left arrow.
60 Left,
61 /// Right arrow.
62 Right,
63 /// Up arrow.
64 Up,
65 /// Down arrow.
66 Down,
67 /// Home key.
68 Home,
69 /// End key.
70 End,
71 /// Page Up key.
72 PageUp,
73 /// Page Down key.
74 PageDown,
75 /// Delete key.
76 Delete,
77 /// Insert key.
78 Insert,
79 /// Function keys.
80 ///
81 /// Only function keys 1 through 12 are supported.
82 F(u8),
83 /// Normal character.
84 Char(char),
85 /// Alt modified character.
86 Alt(char),
87 /// Ctrl modified character.
88 ///
89 /// Note that certain keys may not be modifiable with `ctrl`, due to limitations of terminals.
90 Ctrl(char),
91 /// Null byte.
92 Null,
93 /// Esc key.
94 Esc,
95
96 #[doc(hidden)]
97 __IsNotComplete,
98 }
99
100 /// Parse an Event from `item` and possibly subsequent bytes through `iter`.
parse_event<I>(item: u8, iter: &mut I) -> Result<Event, Error> where I: Iterator<Item = Result<u8, Error>>101 pub fn parse_event<I>(item: u8, iter: &mut I) -> Result<Event, Error>
102 where I: Iterator<Item = Result<u8, Error>>
103 {
104 let error = Error::new(ErrorKind::Other, "Could not parse an event");
105 match item {
106 b'\x1B' => {
107 // This is an escape character, leading a control sequence.
108 Ok(match iter.next() {
109 Some(Ok(b'O')) => {
110 match iter.next() {
111 // F1-F4
112 Some(Ok(val @ b'P'...b'S')) => Event::Key(Key::F(1 + val - b'P')),
113 _ => return Err(error),
114 }
115 }
116 Some(Ok(b'[')) => {
117 // This is a CSI sequence.
118 parse_csi(iter).ok_or(error)?
119 }
120 Some(Ok(c)) => {
121 let ch = parse_utf8_char(c, iter);
122 Event::Key(Key::Alt(try!(ch)))
123 }
124 Some(Err(_)) | None => return Err(error),
125 })
126 }
127 b'\n' | b'\r' => Ok(Event::Key(Key::Char('\n'))),
128 b'\t' => Ok(Event::Key(Key::Char('\t'))),
129 b'\x7F' => Ok(Event::Key(Key::Backspace)),
130 c @ b'\x01'...b'\x1A' => Ok(Event::Key(Key::Ctrl((c as u8 - 0x1 + b'a') as char))),
131 c @ b'\x1C'...b'\x1F' => Ok(Event::Key(Key::Ctrl((c as u8 - 0x1C + b'4') as char))),
132 b'\0' => Ok(Event::Key(Key::Null)),
133 c => {
134 Ok({
135 let ch = parse_utf8_char(c, iter);
136 Event::Key(Key::Char(try!(ch)))
137 })
138 }
139 }
140 }
141
142 /// Parses a CSI sequence, just after reading ^[
143 ///
144 /// Returns None if an unrecognized sequence is found.
parse_csi<I>(iter: &mut I) -> Option<Event> where I: Iterator<Item = Result<u8, Error>>145 fn parse_csi<I>(iter: &mut I) -> Option<Event>
146 where I: Iterator<Item = Result<u8, Error>>
147 {
148 Some(match iter.next() {
149 Some(Ok(b'[')) => match iter.next() {
150 Some(Ok(val @ b'A'...b'E')) => Event::Key(Key::F(1 + val - b'A')),
151 _ => return None,
152 },
153 Some(Ok(b'D')) => Event::Key(Key::Left),
154 Some(Ok(b'C')) => Event::Key(Key::Right),
155 Some(Ok(b'A')) => Event::Key(Key::Up),
156 Some(Ok(b'B')) => Event::Key(Key::Down),
157 Some(Ok(b'H')) => Event::Key(Key::Home),
158 Some(Ok(b'F')) => Event::Key(Key::End),
159 Some(Ok(b'M')) => {
160 // X10 emulation mouse encoding: ESC [ CB Cx Cy (6 characters only).
161 let mut next = || iter.next().unwrap().unwrap();
162
163 let cb = next() as i8 - 32;
164 // (1, 1) are the coords for upper left.
165 let cx = next().saturating_sub(32) as u16;
166 let cy = next().saturating_sub(32) as u16;
167 Event::Mouse(match cb & 0b11 {
168 0 => {
169 if cb & 0x40 != 0 {
170 MouseEvent::Press(MouseButton::WheelUp, cx, cy)
171 } else {
172 MouseEvent::Press(MouseButton::Left, cx, cy)
173 }
174 }
175 1 => {
176 if cb & 0x40 != 0 {
177 MouseEvent::Press(MouseButton::WheelDown, cx, cy)
178 } else {
179 MouseEvent::Press(MouseButton::Middle, cx, cy)
180 }
181 }
182 2 => MouseEvent::Press(MouseButton::Right, cx, cy),
183 3 => MouseEvent::Release(cx, cy),
184 _ => return None,
185 })
186 }
187 Some(Ok(b'<')) => {
188 // xterm mouse encoding:
189 // ESC [ < Cb ; Cx ; Cy (;) (M or m)
190 let mut buf = Vec::new();
191 let mut c = iter.next().unwrap().unwrap();
192 while match c {
193 b'm' | b'M' => false,
194 _ => true,
195 } {
196 buf.push(c);
197 c = iter.next().unwrap().unwrap();
198 }
199 let str_buf = String::from_utf8(buf).unwrap();
200 let nums = &mut str_buf.split(';');
201
202 let cb = nums.next()
203 .unwrap()
204 .parse::<u16>()
205 .unwrap();
206 let cx = nums.next()
207 .unwrap()
208 .parse::<u16>()
209 .unwrap();
210 let cy = nums.next()
211 .unwrap()
212 .parse::<u16>()
213 .unwrap();
214
215 let event = match cb {
216 0...2 | 64...65 => {
217 let button = match cb {
218 0 => MouseButton::Left,
219 1 => MouseButton::Middle,
220 2 => MouseButton::Right,
221 64 => MouseButton::WheelUp,
222 65 => MouseButton::WheelDown,
223 _ => unreachable!(),
224 };
225 match c {
226 b'M' => MouseEvent::Press(button, cx, cy),
227 b'm' => MouseEvent::Release(cx, cy),
228 _ => return None,
229 }
230 }
231 32 => MouseEvent::Hold(cx, cy),
232 3 => MouseEvent::Release(cx, cy),
233 _ => return None,
234 };
235
236 Event::Mouse(event)
237 }
238 Some(Ok(c @ b'0'...b'9')) => {
239 // Numbered escape code.
240 let mut buf = Vec::new();
241 buf.push(c);
242 let mut c = iter.next().unwrap().unwrap();
243 // The final byte of a CSI sequence can be in the range 64-126, so
244 // let's keep reading anything else.
245 while c < 64 || c > 126 {
246 buf.push(c);
247 c = iter.next().unwrap().unwrap();
248 }
249
250 match c {
251 // rxvt mouse encoding:
252 // ESC [ Cb ; Cx ; Cy ; M
253 b'M' => {
254 let str_buf = String::from_utf8(buf).unwrap();
255
256 let nums: Vec<u16> = str_buf.split(';').map(|n| n.parse().unwrap()).collect();
257
258 let cb = nums[0];
259 let cx = nums[1];
260 let cy = nums[2];
261
262 let event = match cb {
263 32 => MouseEvent::Press(MouseButton::Left, cx, cy),
264 33 => MouseEvent::Press(MouseButton::Middle, cx, cy),
265 34 => MouseEvent::Press(MouseButton::Right, cx, cy),
266 35 => MouseEvent::Release(cx, cy),
267 64 => MouseEvent::Hold(cx, cy),
268 96 | 97 => MouseEvent::Press(MouseButton::WheelUp, cx, cy),
269 _ => return None,
270 };
271
272 Event::Mouse(event)
273 }
274 // Special key code.
275 b'~' => {
276 let str_buf = String::from_utf8(buf).unwrap();
277
278 // This CSI sequence can be a list of semicolon-separated
279 // numbers.
280 let nums: Vec<u8> = str_buf.split(';').map(|n| n.parse().unwrap()).collect();
281
282 if nums.is_empty() {
283 return None;
284 }
285
286 // TODO: handle multiple values for key modififiers (ex: values
287 // [3, 2] means Shift+Delete)
288 if nums.len() > 1 {
289 return None;
290 }
291
292 match nums[0] {
293 1 | 7 => Event::Key(Key::Home),
294 2 => Event::Key(Key::Insert),
295 3 => Event::Key(Key::Delete),
296 4 | 8 => Event::Key(Key::End),
297 5 => Event::Key(Key::PageUp),
298 6 => Event::Key(Key::PageDown),
299 v @ 11...15 => Event::Key(Key::F(v - 10)),
300 v @ 17...21 => Event::Key(Key::F(v - 11)),
301 v @ 23...24 => Event::Key(Key::F(v - 12)),
302 _ => return None,
303 }
304 }
305 _ => return None,
306 }
307 }
308 _ => return None,
309 })
310
311 }
312
313 /// Parse `c` as either a single byte ASCII char or a variable size UTF-8 char.
parse_utf8_char<I>(c: u8, iter: &mut I) -> Result<char, Error> where I: Iterator<Item = Result<u8, Error>>314 fn parse_utf8_char<I>(c: u8, iter: &mut I) -> Result<char, Error>
315 where I: Iterator<Item = Result<u8, Error>>
316 {
317 let error = Err(Error::new(ErrorKind::Other, "Input character is not valid UTF-8"));
318 if c.is_ascii() {
319 Ok(c as char)
320 } else {
321 let bytes = &mut Vec::new();
322 bytes.push(c);
323
324 loop {
325 match iter.next() {
326 Some(Ok(next)) => {
327 bytes.push(next);
328 if let Ok(st) = str::from_utf8(bytes) {
329 return Ok(st.chars().next().unwrap());
330 }
331 if bytes.len() >= 4 {
332 return error;
333 }
334 }
335 _ => return error,
336 }
337 }
338 }
339 }
340
341 #[cfg(test)]
342 #[test]
test_parse_utf8()343 fn test_parse_utf8() {
344 let st = "abcéŷ¤£€ù%323";
345 let ref mut bytes = st.bytes().map(|x| Ok(x));
346 let chars = st.chars();
347 for c in chars {
348 let b = bytes.next().unwrap().unwrap();
349 assert!(c == parse_utf8_char(b, bytes).unwrap());
350 }
351 }
352