diff --git a/examples/keys.rs b/examples/keys.rs index 06d88a7..55d2f83 100644 --- a/examples/keys.rs +++ b/examples/keys.rs @@ -1,6 +1,5 @@ extern crate termion; - #[cfg(feature = "nightly")] fn main() { use termion::{TermRead, TermWrite, IntoRawMode, Key}; @@ -18,7 +17,7 @@ fn main() { for c in stdin.keys() { stdout.goto(5, 5).unwrap(); stdout.clear_line().unwrap(); - match c { + match c.unwrap() { Key::Char('q') => break, Key::Char(c) => println!("{}", c), Key::Alt(c) => println!("^{}", c), @@ -29,7 +28,6 @@ fn main() { Key::Down => println!("↓"), Key::Backspace => println!("×"), Key::Invalid => println!("???"), - Key::Error(_) => println!("ERROR"), _ => {}, } stdout.flush().unwrap(); @@ -37,6 +35,7 @@ fn main() { stdout.show_cursor().unwrap(); } + #[cfg(not(feature = "nightly"))] fn main() { println!("To run this example, you need to enable the `nightly` feature. Use Rust nightly and compile with `--features nightly`.") diff --git a/src/control.rs b/src/control.rs index 24a68d2..9281dff 100644 --- a/src/control.rs +++ b/src/control.rs @@ -156,6 +156,7 @@ mod test { buf.csi(b"blah").unwrap(); assert_eq!(buf.get_ref(), b"\x1B[bluh\x1B[blah"); } + #[test] fn test_csi_partial() { let mut buf = [0; 3]; @@ -164,6 +165,7 @@ mod test { assert_eq!(buf.csi(b"").unwrap(), 0); assert_eq!(buf.csi(b"nooooo").unwrap(), 0); } + #[test] fn test_osc() { let mut buf = Cursor::new(Vec::new()); @@ -174,6 +176,7 @@ mod test { buf.osc(b"blah").unwrap(); assert_eq!(buf.get_ref(), b"\x1B]bluh\x1B]blah"); } + #[test] fn test_osc_partial() { let mut buf = [0; 3]; @@ -182,6 +185,7 @@ mod test { assert_eq!(buf.osc(b"").unwrap(), 0); assert_eq!(buf.osc(b"nooooo").unwrap(), 0); } + #[test] fn test_dsc() { let mut buf = Cursor::new(Vec::new()); @@ -192,6 +196,7 @@ mod test { buf.dsc(b"blah").unwrap(); assert_eq!(buf.get_ref(), b"\x1BPbluh\x1BPblah"); } + #[test] fn test_dsc_partial() { let mut buf = [0; 3]; @@ -200,6 +205,7 @@ mod test { assert_eq!(buf.dsc(b"").unwrap(), 0); assert_eq!(buf.dsc(b"nooooo").unwrap(), 0); } + #[test] fn test_clear() { let mut buf = Cursor::new(Vec::new()); @@ -208,6 +214,7 @@ mod test { buf.clear().unwrap(); assert_eq!(buf.get_ref(), b"\x1B[2J\x1B[2J"); } + #[test] fn test_goto() { let mut buf = Cursor::new(Vec::new()); @@ -216,6 +223,7 @@ mod test { buf.goto(24, 45).unwrap(); assert_eq!(buf.get_ref(), b"\x1B[00044;00035H\x1B[00046;00025H"); } + #[test] fn test_style() { use Style; diff --git a/src/input.rs b/src/input.rs index 263c1ae..7258d34 100644 --- a/src/input.rs +++ b/src/input.rs @@ -2,11 +2,8 @@ use std::io::{self, Read, Write}; use IntoRawMode; -#[cfg(feature = "nightly")] -use std::io::{Chars, CharsError}; - /// A key. -#[derive(Debug)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Key { /// Backspace. Backspace, @@ -28,8 +25,6 @@ pub enum Key { Ctrl(char), /// Invalid character code. Invalid, - /// IO error. - Error(io::Error), /// Null byte. Null, @@ -45,12 +40,12 @@ pub struct Keys { } #[cfg(feature = "nightly")] -impl>> Iterator for Keys { - type Item = Key; +impl>> Iterator for Keys { + type Item = Result; - fn next(&mut self) -> Option { - match self.chars.next() { - Some(Ok('\x1B')) => Some(match self.chars.next() { + fn next(&mut self) -> Option> { + Some(match self.chars.next() { + Some(Ok('\x1B')) => Ok(match self.chars.next() { Some(Ok('[')) => match self.chars.next() { Some(Ok('D')) => Key::Left, Some(Ok('C')) => Key::Right, @@ -61,16 +56,16 @@ impl>> Iterator for Keys { Some(Ok(c)) => Key::Alt(c), Some(Err(_)) | None => Key::Invalid, }), - Some(Ok('\n')) | Some(Ok('\r')) => Some(Key::Char('\n')), - Some(Ok('\t')) => Some(Key::Char('\t')), - Some(Ok('\x7F')) => Some(Key::Backspace), - Some(Ok(c @ '\x01' ... '\x1A')) => Some(Key::Ctrl((c as u8 - 0x1 + b'a') as char)), - Some(Ok(c @ '\x1C' ... '\x1F')) => Some(Key::Ctrl((c as u8 - 0x1C + b'4') as char)), - None => None, - Some(Ok('\0')) => Some(Key::Null), - Some(Ok(c)) => Some(Key::Char(c)), - Some(Err(e)) => Some(Key::Error(io::Error::new(io::ErrorKind::InvalidData, e))), - } + Some(Ok('\n')) | Some(Ok('\r')) => Ok(Key::Char('\n')), + Some(Ok('\t')) => Ok(Key::Char('\t')), + Some(Ok('\x7F')) => Ok(Key::Backspace), + Some(Ok(c @ '\x01' ... '\x1A')) => Ok(Key::Ctrl((c as u8 - 0x1 + b'a') as char)), + Some(Ok(c @ '\x1C' ... '\x1F')) => Ok(Key::Ctrl((c as u8 - 0x1C + b'4') as char)), + Some(Ok('\0')) => Ok(Key::Null), + Some(Ok(c)) => Ok(Key::Char(c)), + Some(Err(e)) => Err(e), + None => return None, + }) } } @@ -78,7 +73,7 @@ impl>> Iterator for Keys { pub trait TermRead { /// An iterator over key inputs. #[cfg(feature = "nightly")] - fn keys(self) -> Keys> where Self: Sized; + fn keys(self) -> Keys> where Self: Sized; /// Read a line. /// @@ -99,7 +94,7 @@ pub trait TermRead { impl TermRead for R { #[cfg(feature = "nightly")] - fn keys(self) -> Keys> { + fn keys(self) -> Keys> { Keys { chars: self.chars(), } @@ -133,12 +128,12 @@ mod test { fn test_keys() { let mut i = b"\x1Bayo\x7F\x1B[D".keys(); - assert_eq!(i.next(), Some(Key::Alt('a'))); - assert_eq!(i.next(), Some(Key::Char('y'))); - assert_eq!(i.next(), Some(Key::Char('o'))); - assert_eq!(i.next(), Some(Key::Backspace)); - assert_eq!(i.next(), Some(Key::Left)); - assert_eq!(i.next(), None); + assert_eq!(i.next().unwrap().unwrap(), Key::Alt('a')); + assert_eq!(i.next().unwrap().unwrap(), Key::Char('y')); + assert_eq!(i.next().unwrap().unwrap(), Key::Char('o')); + assert_eq!(i.next().unwrap().unwrap(), Key::Backspace); + assert_eq!(i.next().unwrap().unwrap(), Key::Left); + assert!(i.next().is_none()); } fn line_match(a: &str, b: Option<&str>) { diff --git a/src/raw.rs b/src/raw.rs index 97ab850..6aa8406 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -12,7 +12,7 @@ pub struct RawTerminal { impl Drop for RawTerminal { fn drop(&mut self) { use control::TermWrite; - let _ = self.csi(b"R"); + self.csi(b"R").unwrap(); } }