Replace UnknownCsi with generalized Event::Unsupported (#80)
This commit is contained in:
		
							parent
							
								
									f9eaf6d0bc
								
							
						
					
					
						commit
						32ff8ba96e
					
				
							
								
								
									
										131
									
								
								src/event.rs
								
								
								
								
							
							
						
						
									
										131
									
								
								src/event.rs
								
								
								
								
							| 
						 | 
					@ -12,10 +12,7 @@ pub enum Event {
 | 
				
			||||||
    /// A mouse button press, release or wheel use at specific coordinates.
 | 
					    /// A mouse button press, release or wheel use at specific coordinates.
 | 
				
			||||||
    Mouse(MouseEvent),
 | 
					    Mouse(MouseEvent),
 | 
				
			||||||
    /// An event that cannot currently be evaluated.
 | 
					    /// An event that cannot currently be evaluated.
 | 
				
			||||||
    Unsupported,
 | 
					    Unsupported(Vec<u8>),
 | 
				
			||||||
    /// A CSI sequence unrecognized by termion. Does not inlude the leading `^[`.
 | 
					 | 
				
			||||||
    UnknownCsi(Vec<u8>),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A mouse related event.
 | 
					/// A mouse related event.
 | 
				
			||||||
| 
						 | 
					@ -97,27 +94,58 @@ pub enum Key {
 | 
				
			||||||
    Esc,
 | 
					    Esc,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[doc(hidden)]
 | 
					    #[doc(hidden)]
 | 
				
			||||||
    __IsNotComplete
 | 
					    __IsNotComplete,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Parse an Event from `item` and possibly subsequent bytes through `iter`.
 | 
					/// Parse an Event from `item` and possibly subsequent bytes through `iter`.
 | 
				
			||||||
pub fn parse_event<I>(item: Result<u8, Error>, iter: &mut I) -> Result<Event, Error>
 | 
					pub fn parse_event<I>(item: u8, iter: &mut I) -> Result<Event, Error>
 | 
				
			||||||
    where I: Iterator<Item = Result<u8, Error>>
 | 
					    where I: Iterator<Item = Result<u8, Error>>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    let error = Err(Error::new(ErrorKind::Other, "Could not parse an event"));
 | 
					    let error = Error::new(ErrorKind::Other, "Could not parse an event");
 | 
				
			||||||
    match item {
 | 
					    match item {
 | 
				
			||||||
        Ok(b'\x1B') => {
 | 
					        b'\x1B' => {
 | 
				
			||||||
 | 
					            // This is an escape character, leading a control sequence.
 | 
				
			||||||
            Ok(match iter.next() {
 | 
					            Ok(match iter.next() {
 | 
				
			||||||
                Some(Ok(b'O')) => {
 | 
					                Some(Ok(b'O')) => {
 | 
				
			||||||
                    match iter.next() {
 | 
					                    match iter.next() {
 | 
				
			||||||
                        // F1-F4
 | 
					                        // F1-F4
 | 
				
			||||||
                        Some(Ok(val @ b'P'...b'S')) => Event::Key(Key::F(1 + val - b'P')),
 | 
					                        Some(Ok(val @ b'P'...b'S')) => Event::Key(Key::F(1 + val - b'P')),
 | 
				
			||||||
                        _ => return error,
 | 
					                        _ => return Err(error),
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Some(Ok(b'[')) => {
 | 
					                Some(Ok(b'[')) => {
 | 
				
			||||||
                    // This is a CSI sequence.
 | 
					                    // This is a CSI sequence.
 | 
				
			||||||
                    match iter.next() {
 | 
					                    parse_csi(iter).ok_or(error)?
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Some(Ok(c)) => {
 | 
				
			||||||
 | 
					                    let ch = parse_utf8_char(c, iter);
 | 
				
			||||||
 | 
					                    Event::Key(Key::Alt(try!(ch)))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Some(Err(_)) | None => return Err(error),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        b'\n' | b'\r' => Ok(Event::Key(Key::Char('\n'))),
 | 
				
			||||||
 | 
					        b'\t' => Ok(Event::Key(Key::Char('\t'))),
 | 
				
			||||||
 | 
					        b'\x7F' => Ok(Event::Key(Key::Backspace)),
 | 
				
			||||||
 | 
					        c @ b'\x01'...b'\x1A' => Ok(Event::Key(Key::Ctrl((c as u8 - 0x1 + b'a') as char))),
 | 
				
			||||||
 | 
					        c @ b'\x1C'...b'\x1F' => Ok(Event::Key(Key::Ctrl((c as u8 - 0x1C + b'4') as char))),
 | 
				
			||||||
 | 
					        b'\0' => Ok(Event::Key(Key::Null)),
 | 
				
			||||||
 | 
					        c => {
 | 
				
			||||||
 | 
					            Ok({
 | 
				
			||||||
 | 
					                let ch = parse_utf8_char(c, iter);
 | 
				
			||||||
 | 
					                Event::Key(Key::Char(try!(ch)))
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Parses a CSI sequence, just after reading ^[
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Returns None if an unrecognized sequence is found.
 | 
				
			||||||
 | 
					fn parse_csi<I>(iter: &mut I) -> Option<Event>
 | 
				
			||||||
 | 
					    where I: Iterator<Item = Result<u8, Error>>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Some(match iter.next() {
 | 
				
			||||||
        Some(Ok(b'D')) => Event::Key(Key::Left),
 | 
					        Some(Ok(b'D')) => Event::Key(Key::Left),
 | 
				
			||||||
        Some(Ok(b'C')) => Event::Key(Key::Right),
 | 
					        Some(Ok(b'C')) => Event::Key(Key::Right),
 | 
				
			||||||
        Some(Ok(b'A')) => Event::Key(Key::Up),
 | 
					        Some(Ok(b'A')) => Event::Key(Key::Up),
 | 
				
			||||||
| 
						 | 
					@ -126,10 +154,12 @@ where I: Iterator<Item = Result<u8, Error>>
 | 
				
			||||||
        Some(Ok(b'F')) => Event::Key(Key::End),
 | 
					        Some(Ok(b'F')) => Event::Key(Key::End),
 | 
				
			||||||
        Some(Ok(b'M')) => {
 | 
					        Some(Ok(b'M')) => {
 | 
				
			||||||
            // X10 emulation mouse encoding: ESC [ CB Cx Cy (6 characters only).
 | 
					            // X10 emulation mouse encoding: ESC [ CB Cx Cy (6 characters only).
 | 
				
			||||||
                            let cb = iter.next().unwrap().unwrap() as i8 - 32;
 | 
					            let mut next = || iter.next().unwrap().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let cb = next() as i8 - 32;
 | 
				
			||||||
            // (1, 1) are the coords for upper left.
 | 
					            // (1, 1) are the coords for upper left.
 | 
				
			||||||
                            let cx = (iter.next().unwrap().unwrap() as u8).saturating_sub(32) as u16;
 | 
					            let cx = next().saturating_sub(32) as u16;
 | 
				
			||||||
                            let cy = (iter.next().unwrap().unwrap() as u8).saturating_sub(32) as u16;
 | 
					            let cy = next().saturating_sub(32) as u16;
 | 
				
			||||||
            Event::Mouse(match cb & 0b11 {
 | 
					            Event::Mouse(match cb & 0b11 {
 | 
				
			||||||
                0 => {
 | 
					                0 => {
 | 
				
			||||||
                    if cb & 0x40 != 0 {
 | 
					                    if cb & 0x40 != 0 {
 | 
				
			||||||
| 
						 | 
					@ -147,9 +177,9 @@ where I: Iterator<Item = Result<u8, Error>>
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                2 => MouseEvent::Press(MouseButton::Right, cx, cy),
 | 
					                2 => MouseEvent::Press(MouseButton::Right, cx, cy),
 | 
				
			||||||
                3 => MouseEvent::Release(cx, cy),
 | 
					                3 => MouseEvent::Release(cx, cy),
 | 
				
			||||||
                                _ => return error,
 | 
					                _ => return None,
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
                        },
 | 
					        }
 | 
				
			||||||
        Some(Ok(b'<')) => {
 | 
					        Some(Ok(b'<')) => {
 | 
				
			||||||
            // xterm mouse encoding:
 | 
					            // xterm mouse encoding:
 | 
				
			||||||
            // ESC [ < Cb ; Cx ; Cy ; (M or m)
 | 
					            // ESC [ < Cb ; Cx ; Cy ; (M or m)
 | 
				
			||||||
| 
						 | 
					@ -177,20 +207,20 @@ where I: Iterator<Item = Result<u8, Error>>
 | 
				
			||||||
                        2 => MouseButton::Right,
 | 
					                        2 => MouseButton::Right,
 | 
				
			||||||
                        64 => MouseButton::WheelUp,
 | 
					                        64 => MouseButton::WheelUp,
 | 
				
			||||||
                        65 => MouseButton::WheelDown,
 | 
					                        65 => MouseButton::WheelDown,
 | 
				
			||||||
                                        _ => return error,
 | 
					                        _ => unreachable!(),
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
                    match c {
 | 
					                    match c {
 | 
				
			||||||
                        b'M' => MouseEvent::Press(button, cx, cy),
 | 
					                        b'M' => MouseEvent::Press(button, cx, cy),
 | 
				
			||||||
                        b'm' => MouseEvent::Release(cx, cy),
 | 
					                        b'm' => MouseEvent::Release(cx, cy),
 | 
				
			||||||
                                        _ => return error,
 | 
					                        _ => return None,
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                32 => MouseEvent::Hold(cx, cy),
 | 
					                32 => MouseEvent::Hold(cx, cy),
 | 
				
			||||||
                                _ => return error,
 | 
					                _ => return None,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Event::Mouse(event)
 | 
					            Event::Mouse(event)
 | 
				
			||||||
                        },
 | 
					        }
 | 
				
			||||||
        Some(Ok(c @ b'0'...b'9')) => {
 | 
					        Some(Ok(c @ b'0'...b'9')) => {
 | 
				
			||||||
            // Numbered escape code.
 | 
					            // Numbered escape code.
 | 
				
			||||||
            let mut buf = Vec::new();
 | 
					            let mut buf = Vec::new();
 | 
				
			||||||
| 
						 | 
					@ -202,9 +232,6 @@ where I: Iterator<Item = Result<u8, Error>>
 | 
				
			||||||
                buf.push(c);
 | 
					                buf.push(c);
 | 
				
			||||||
                c = iter.next().unwrap().unwrap();
 | 
					                c = iter.next().unwrap().unwrap();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
                            // Include the terminal char in the buffer.
 | 
					 | 
				
			||||||
                            // We'll want it if we return an unknown sequence.
 | 
					 | 
				
			||||||
                            buf.push(c);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            match c {
 | 
					            match c {
 | 
				
			||||||
                // rxvt mouse encoding:
 | 
					                // rxvt mouse encoding:
 | 
				
			||||||
| 
						 | 
					@ -212,8 +239,8 @@ where I: Iterator<Item = Result<u8, Error>>
 | 
				
			||||||
                b'M' => {
 | 
					                b'M' => {
 | 
				
			||||||
                    let str_buf = String::from_utf8(buf).unwrap();
 | 
					                    let str_buf = String::from_utf8(buf).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    // 
 | 
					                    let nums: Vec<u16> = str_buf
 | 
				
			||||||
                                    let nums: Vec<u16> = str_buf[..str_buf.len()-1].split(';')
 | 
					                        .split(';')
 | 
				
			||||||
                        .map(|n| n.parse().unwrap())
 | 
					                        .map(|n| n.parse().unwrap())
 | 
				
			||||||
                        .collect();
 | 
					                        .collect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -227,31 +254,31 @@ where I: Iterator<Item = Result<u8, Error>>
 | 
				
			||||||
                        34 => MouseEvent::Press(MouseButton::Right, cx, cy),
 | 
					                        34 => MouseEvent::Press(MouseButton::Right, cx, cy),
 | 
				
			||||||
                        35 => MouseEvent::Release(cx, cy),
 | 
					                        35 => MouseEvent::Release(cx, cy),
 | 
				
			||||||
                        64 => MouseEvent::Hold(cx, cy),
 | 
					                        64 => MouseEvent::Hold(cx, cy),
 | 
				
			||||||
                                        96 |
 | 
					                        96 | 97 => MouseEvent::Press(MouseButton::WheelUp, cx, cy),
 | 
				
			||||||
                                        97 => MouseEvent::Press(MouseButton::WheelUp, cx, cy),
 | 
					                        _ => return None,
 | 
				
			||||||
                                        _ => return Ok(Event::UnknownCsi(str_buf.into_bytes())),
 | 
					 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Event::Mouse(event)
 | 
					                    Event::Mouse(event)
 | 
				
			||||||
                                },
 | 
					                }
 | 
				
			||||||
                // Special key code.
 | 
					                // Special key code.
 | 
				
			||||||
                b'~' => {
 | 
					                b'~' => {
 | 
				
			||||||
                    let str_buf = String::from_utf8(buf).unwrap();
 | 
					                    let str_buf = String::from_utf8(buf).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // This CSI sequence can be a list of semicolon-separated
 | 
					                    // This CSI sequence can be a list of semicolon-separated
 | 
				
			||||||
                    // numbers.
 | 
					                    // numbers.
 | 
				
			||||||
                                    let nums: Vec<u8> = str_buf[..str_buf.len()-1].split(';')
 | 
					                    let nums: Vec<u8> = str_buf
 | 
				
			||||||
 | 
					                        .split(';')
 | 
				
			||||||
                        .map(|n| n.parse().unwrap())
 | 
					                        .map(|n| n.parse().unwrap())
 | 
				
			||||||
                        .collect();
 | 
					                        .collect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if nums.is_empty() {
 | 
					                    if nums.is_empty() {
 | 
				
			||||||
                                        return Ok(Event::UnknownCsi(str_buf.into_bytes()));
 | 
					                        return None;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // TODO: handle multiple values for key modififiers (ex: values
 | 
					                    // TODO: handle multiple values for key modififiers (ex: values
 | 
				
			||||||
                    // [3, 2] means Shift+Delete)
 | 
					                    // [3, 2] means Shift+Delete)
 | 
				
			||||||
                    if nums.len() > 1 {
 | 
					                    if nums.len() > 1 {
 | 
				
			||||||
                                        return Ok(Event::UnknownCsi(str_buf.into_bytes()));
 | 
					                        return None;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    match nums[0] {
 | 
					                    match nums[0] {
 | 
				
			||||||
| 
						 | 
					@ -264,43 +291,21 @@ where I: Iterator<Item = Result<u8, Error>>
 | 
				
			||||||
                        v @ 11...15 => Event::Key(Key::F(v - 10)),
 | 
					                        v @ 11...15 => Event::Key(Key::F(v - 10)),
 | 
				
			||||||
                        v @ 17...21 => Event::Key(Key::F(v - 11)),
 | 
					                        v @ 17...21 => Event::Key(Key::F(v - 11)),
 | 
				
			||||||
                        v @ 23...24 => Event::Key(Key::F(v - 12)),
 | 
					                        v @ 23...24 => Event::Key(Key::F(v - 12)),
 | 
				
			||||||
                                        _ => return Ok(Event::UnknownCsi(str_buf.into_bytes())),
 | 
					                        _ => return None,
 | 
				
			||||||
                                    }
 | 
					 | 
				
			||||||
                                },
 | 
					 | 
				
			||||||
                                _ => return Ok(Event::UnknownCsi(buf)),
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        },
 | 
					 | 
				
			||||||
                        _ => return error,
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Some(Ok(c)) => {
 | 
					                _ => return None,
 | 
				
			||||||
                    let ch = parse_utf8_char(c, iter);
 | 
					 | 
				
			||||||
                    Event::Key(Key::Alt(try!(ch)))
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
                Some(Err(_)) | None => return error,
 | 
					        }
 | 
				
			||||||
 | 
					        _ => return None,
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
        Ok(b'\n') | Ok(b'\r') => Ok(Event::Key(Key::Char('\n'))),
 | 
					 | 
				
			||||||
        Ok(b'\t') => Ok(Event::Key(Key::Char('\t'))),
 | 
					 | 
				
			||||||
        Ok(b'\x7F') => Ok(Event::Key(Key::Backspace)),
 | 
					 | 
				
			||||||
        Ok(c @ b'\x01'...b'\x1A') => Ok(Event::Key(Key::Ctrl((c as u8 - 0x1 + b'a') as char))),
 | 
					 | 
				
			||||||
        Ok(c @ b'\x1C'...b'\x1F') => {
 | 
					 | 
				
			||||||
            Ok(Event::Key(Key::Ctrl((c as u8 - 0x1C + b'4') as char)))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Ok(b'\0') => Ok(Event::Key(Key::Null)),
 | 
					 | 
				
			||||||
        Ok(c) => {
 | 
					 | 
				
			||||||
            Ok({
 | 
					 | 
				
			||||||
                let ch = parse_utf8_char(c, iter);
 | 
					 | 
				
			||||||
                Event::Key(Key::Char(try!(ch)))
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Err(e) => Err(e),
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Parse `c` as either a single byte ASCII char or a variable size UTF-8 char.
 | 
					/// Parse `c` as either a single byte ASCII char or a variable size UTF-8 char.
 | 
				
			||||||
fn parse_utf8_char<I>(c: u8, iter: &mut I) -> Result<char, Error>
 | 
					fn parse_utf8_char<I>(c: u8, iter: &mut I) -> Result<char, Error>
 | 
				
			||||||
    where I: Iterator<Item = Result<u8, Error>> {
 | 
					    where I: Iterator<Item = Result<u8, Error>>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    let error = Err(Error::new(ErrorKind::Other, "Input character is not valid UTF-8"));
 | 
					    let error = Err(Error::new(ErrorKind::Other, "Input character is not valid UTF-8"));
 | 
				
			||||||
    if c.is_ascii() {
 | 
					    if c.is_ascii() {
 | 
				
			||||||
        Ok(c as char)
 | 
					        Ok(c as char)
 | 
				
			||||||
| 
						 | 
					@ -311,9 +316,11 @@ fn parse_utf8_char<I>(c: u8, iter: &mut I) -> Result<char, Error>
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            bytes.push(iter.next().unwrap().unwrap());
 | 
					            bytes.push(iter.next().unwrap().unwrap());
 | 
				
			||||||
            if let Ok(st) = str::from_utf8(bytes) {
 | 
					            if let Ok(st) = str::from_utf8(bytes) {
 | 
				
			||||||
                return Ok(st.chars().next().unwrap())
 | 
					                return Ok(st.chars().next().unwrap());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if bytes.len() >= 4 {
 | 
				
			||||||
 | 
					                return error;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if bytes.len() >= 4 { return error; }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										77
									
								
								src/input.rs
								
								
								
								
							
							
						
						
									
										77
									
								
								src/input.rs
								
								
								
								
							| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
use std::io::{self, Read, Write};
 | 
					use std::io::{self, Read, Write};
 | 
				
			||||||
use std::ops;
 | 
					use std::ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use event::{parse_event, Event, Key};
 | 
					use event::{self, Event, Key};
 | 
				
			||||||
use raw::IntoRawMode;
 | 
					use raw::IntoRawMode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// An iterator over input keys.
 | 
					/// An iterator over input keys.
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ impl<R: Read> Iterator for Events<R> {
 | 
				
			||||||
        if let Some(c) = self.leftover {
 | 
					        if let Some(c) = self.leftover {
 | 
				
			||||||
            // we have a leftover byte, use it
 | 
					            // we have a leftover byte, use it
 | 
				
			||||||
            self.leftover = None;
 | 
					            self.leftover = None;
 | 
				
			||||||
            return Some(parse_event(Ok(c), &mut source.bytes()).or(Ok(Event::Unsupported)));
 | 
					            return Some(parse_event(c, &mut source.bytes()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Here we read two bytes at a time. We need to distinguish between single ESC key presses,
 | 
					        // Here we read two bytes at a time. We need to distinguish between single ESC key presses,
 | 
				
			||||||
| 
						 | 
					@ -51,15 +51,17 @@ impl<R: Read> Iterator for Events<R> {
 | 
				
			||||||
        let mut buf = [0u8; 2];
 | 
					        let mut buf = [0u8; 2];
 | 
				
			||||||
        let res = match source.read(&mut buf) {
 | 
					        let res = match source.read(&mut buf) {
 | 
				
			||||||
            Ok(0) => return None,
 | 
					            Ok(0) => return None,
 | 
				
			||||||
            Ok(1) => match buf[0] {
 | 
					            Ok(1) => {
 | 
				
			||||||
 | 
					                match buf[0] {
 | 
				
			||||||
                    b'\x1B' => Ok(Event::Key(Key::Esc)),
 | 
					                    b'\x1B' => Ok(Event::Key(Key::Esc)),
 | 
				
			||||||
                c => parse_event(Ok(c), &mut source.bytes()),
 | 
					                    c => parse_event(c, &mut source.bytes()),
 | 
				
			||||||
            },
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            Ok(2) => {
 | 
					            Ok(2) => {
 | 
				
			||||||
                let mut option_iter = &mut Some(buf[1]).into_iter();
 | 
					                let mut option_iter = &mut Some(buf[1]).into_iter();
 | 
				
			||||||
                let result = {
 | 
					                let result = {
 | 
				
			||||||
                    let mut iter = option_iter.map(|c| Ok(c)).chain(source.bytes());
 | 
					                    let mut iter = option_iter.map(|c| Ok(c)).chain(source.bytes());
 | 
				
			||||||
                    parse_event(Ok(buf[0]), &mut iter)
 | 
					                    parse_event(buf[0], &mut iter)
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                // If the option_iter wasn't consumed, keep the byte for later.
 | 
					                // If the option_iter wasn't consumed, keep the byte for later.
 | 
				
			||||||
                self.leftover = option_iter.next();
 | 
					                self.leftover = option_iter.next();
 | 
				
			||||||
| 
						 | 
					@ -69,10 +71,24 @@ impl<R: Read> Iterator for Events<R> {
 | 
				
			||||||
            Err(e) => Err(e),
 | 
					            Err(e) => Err(e),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Some(res.or(Ok(Event::Unsupported)))
 | 
					        Some(res)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_event<I>(item: u8, iter: &mut I) -> Result<Event, io::Error>
 | 
				
			||||||
 | 
					    where I: Iterator<Item = Result<u8, io::Error>>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    let mut buf = vec![item];
 | 
				
			||||||
 | 
					    let result = {
 | 
				
			||||||
 | 
					        let mut iter = iter.inspect(|byte| if let &Ok(byte) = byte {
 | 
				
			||||||
 | 
					            buf.push(byte);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        event::parse_event(item, &mut iter)
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    result.or(Ok(Event::Unsupported(buf)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Extension to `Read` trait.
 | 
					/// Extension to `Read` trait.
 | 
				
			||||||
pub trait TermRead {
 | 
					pub trait TermRead {
 | 
				
			||||||
    /// An iterator over input events.
 | 
					    /// An iterator over input events.
 | 
				
			||||||
| 
						 | 
					@ -105,9 +121,7 @@ impl<R: Read> TermRead for R {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn keys(self) -> Keys<Self> {
 | 
					    fn keys(self) -> Keys<Self> {
 | 
				
			||||||
        Keys {
 | 
					        Keys { iter: self.events() }
 | 
				
			||||||
            iter: self.events(),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn read_line(&mut self) -> io::Result<Option<String>> {
 | 
					    fn read_line(&mut self) -> io::Result<Option<String>> {
 | 
				
			||||||
| 
						 | 
					@ -117,13 +131,16 @@ impl<R: Read> TermRead for R {
 | 
				
			||||||
            match c {
 | 
					            match c {
 | 
				
			||||||
                Err(e) => return Err(e),
 | 
					                Err(e) => return Err(e),
 | 
				
			||||||
                Ok(0) | Ok(3) | Ok(4) => return Ok(None),
 | 
					                Ok(0) | Ok(3) | Ok(4) => return Ok(None),
 | 
				
			||||||
                Ok(0x7f) => { buf.pop(); },
 | 
					                Ok(0x7f) => {
 | 
				
			||||||
 | 
					                    buf.pop();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                Ok(b'\n') | Ok(b'\r') => break,
 | 
					                Ok(b'\n') | Ok(b'\r') => break,
 | 
				
			||||||
                Ok(c) => buf.push(c),
 | 
					                Ok(c) => buf.push(c),
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let string = try!(String::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)));
 | 
					        let string = try!(String::from_utf8(buf)
 | 
				
			||||||
 | 
					            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)));
 | 
				
			||||||
        Ok(Some(string))
 | 
					        Ok(Some(string))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -200,18 +217,25 @@ mod test {
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn test_events() {
 | 
					    fn test_events() {
 | 
				
			||||||
        let mut i = b"\x1B[\x00bc\x7F\x1B[D\
 | 
					        let mut i = b"\x1B[\x00bc\x7F\x1B[D\
 | 
				
			||||||
                    \x1B[M\x00\x22\x24\x1B[<0;2;4;M\x1B[32;2;4M\x1B[<0;2;4;m\x1B[35;2;4Mb".events();
 | 
					                    \x1B[M\x00\x22\x24\x1B[<0;2;4;M\x1B[32;2;4M\x1B[<0;2;4;m\x1B[35;2;4Mb"
 | 
				
			||||||
 | 
					            .events();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Unsupported);
 | 
					        assert_eq!(i.next().unwrap().unwrap(),
 | 
				
			||||||
 | 
					                   Event::Unsupported(vec![0x1B, b'[', 0x00]));
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Key(Key::Char('b')));
 | 
					        assert_eq!(i.next().unwrap().unwrap(), Event::Key(Key::Char('b')));
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Key(Key::Char('c')));
 | 
					        assert_eq!(i.next().unwrap().unwrap(), Event::Key(Key::Char('c')));
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Key(Key::Backspace));
 | 
					        assert_eq!(i.next().unwrap().unwrap(), Event::Key(Key::Backspace));
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Key(Key::Left));
 | 
					        assert_eq!(i.next().unwrap().unwrap(), Event::Key(Key::Left));
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Mouse(MouseEvent::Press(MouseButton::WheelUp, 2, 4)));
 | 
					        assert_eq!(i.next().unwrap().unwrap(),
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Mouse(MouseEvent::Press(MouseButton::Left, 2, 4)));
 | 
					                   Event::Mouse(MouseEvent::Press(MouseButton::WheelUp, 2, 4)));
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Mouse(MouseEvent::Press(MouseButton::Left, 2, 4)));
 | 
					        assert_eq!(i.next().unwrap().unwrap(),
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Mouse(MouseEvent::Release(2, 4)));
 | 
					                   Event::Mouse(MouseEvent::Press(MouseButton::Left, 2, 4)));
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Mouse(MouseEvent::Release(2, 4)));
 | 
					        assert_eq!(i.next().unwrap().unwrap(),
 | 
				
			||||||
 | 
					                   Event::Mouse(MouseEvent::Press(MouseButton::Left, 2, 4)));
 | 
				
			||||||
 | 
					        assert_eq!(i.next().unwrap().unwrap(),
 | 
				
			||||||
 | 
					                   Event::Mouse(MouseEvent::Release(2, 4)));
 | 
				
			||||||
 | 
					        assert_eq!(i.next().unwrap().unwrap(),
 | 
				
			||||||
 | 
					                   Event::Mouse(MouseEvent::Release(2, 4)));
 | 
				
			||||||
        assert_eq!(i.next().unwrap().unwrap(), Event::Key(Key::Char('b')));
 | 
					        assert_eq!(i.next().unwrap().unwrap(), Event::Key(Key::Char('b')));
 | 
				
			||||||
        assert!(i.next().is_none());
 | 
					        assert!(i.next().is_none());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -224,7 +248,8 @@ mod test {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut st = b"\x1B[11~\x1B[12~\x1B[13~\x1B[14~\x1B[15~\
 | 
					        let mut st = b"\x1B[11~\x1B[12~\x1B[13~\x1B[14~\x1B[15~\
 | 
				
			||||||
        \x1B[17~\x1B[18~\x1B[19~\x1B[20~\x1B[21~\x1B[23~\x1B[24~".keys();
 | 
					        \x1B[17~\x1B[18~\x1B[19~\x1B[20~\x1B[21~\x1B[23~\x1B[24~"
 | 
				
			||||||
 | 
					            .keys();
 | 
				
			||||||
        for i in 1..13 {
 | 
					        for i in 1..13 {
 | 
				
			||||||
            assert_eq!(st.next().unwrap().unwrap(), Key::F(i));
 | 
					            assert_eq!(st.next().unwrap().unwrap(), Key::F(i));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -279,14 +304,18 @@ mod test {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn test_backspace() {
 | 
					    fn test_backspace() {
 | 
				
			||||||
        line_match("this is the\x7f first\x7f\x7f test", Some("this is th fir test"));
 | 
					        line_match("this is the\x7f first\x7f\x7f test",
 | 
				
			||||||
        line_match("this is the seco\x7fnd test\x7f", Some("this is the secnd tes"));
 | 
					                   Some("this is th fir test"));
 | 
				
			||||||
 | 
					        line_match("this is the seco\x7fnd test\x7f",
 | 
				
			||||||
 | 
					                   Some("this is the secnd tes"));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn test_end() {
 | 
					    fn test_end() {
 | 
				
			||||||
        line_match("abc\nhttps://www.youtube.com/watch?v=dQw4w9WgXcQ", Some("abc"));
 | 
					        line_match("abc\nhttps://www.youtube.com/watch?v=dQw4w9WgXcQ",
 | 
				
			||||||
        line_match("hello\rhttps://www.youtube.com/watch?v=yPYZpwSpKmA", Some("hello"));
 | 
					                   Some("abc"));
 | 
				
			||||||
 | 
					        line_match("hello\rhttps://www.youtube.com/watch?v=yPYZpwSpKmA",
 | 
				
			||||||
 | 
					                   Some("hello"));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue