diff options
author | Jesse Luehrs <doy@tozt.net> | 2013-03-29 01:21:45 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2013-03-29 01:21:45 -0500 |
commit | 896887e9abb3dd6c704ad5aab99db93f05e1492e (patch) | |
tree | 303e8de8a060b27ba969fb3db7ffdfe71b70350e /src | |
parent | 4cd87702004fca9e05e7c5bb899f366caf632842 (diff) | |
download | rust-term-896887e9abb3dd6c704ad5aab99db93f05e1492e.tar.gz rust-term-896887e9abb3dd6c704ad5aab99db93f05e1492e.zip |
use the trie to implement reading with escape codes
Diffstat (limited to 'src')
-rw-r--r-- | src/term.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/term.rs b/src/term.rs index 27fc8c9..ae21cc0 100644 --- a/src/term.rs +++ b/src/term.rs @@ -3,9 +3,12 @@ #[crate_type = "lib"]; use core::libc::c_int; +use core::option::{Option,Some,None}; +use core::io::ReaderUtil; pub use ios::{cooked,cbreak,raw,echo,size}; use info::{init,escape,escape2}; +use util::Trie; struct Writer { priv cleanup: bool, @@ -59,6 +62,99 @@ impl Drop for Writer { } } +enum Keypress { + KeyCharacter(char), + KeyBackspace, + KeyReturn, + KeyTab, + KeyCtrl(char), + KeyF(int), + KeyUp, + KeyDown, + KeyLeft, + KeyRight, + KeyHome, + KeyEnd, + KeyInsert, + KeyDelete, + KeyEscape, +} + +struct Reader { + priv escapes: ~Trie<Keypress>, +} + +pub fn Reader () -> Reader { + Reader { escapes: build_escapes_trie() } +} + +impl Reader { + pub fn read (&self) -> Option<Keypress> { + let mut buf = ~""; + loop { + let c = io::stdin().read_char(); + if c as int == -1 { + return None; + } + + str::push_char(&mut buf, c); + io::print(str::escape_default(buf)); + + if !self.escapes.has_prefix(buf) { + match self.escapes.find(buf) { + &Some(k) => { return Some(k) } + &None => { + if str::len(buf) == 1 { + return Some(KeyCharacter(str::char_at(buf, 0))); + } + else { + // XXX this is... suboptimal + // really, we need to do an ungetc sort of thing + // with the characters in buf, and then just + // return the first character as a KeyCharacter + fail!("unknown escape"); + } + } + } + } + } + } +} + +// XXX this whole thing needs to be able to deal with caps that don't exist +fn build_escapes_trie () -> ~Trie<Keypress> { + let mut trie = ~Trie(); + + trie.insert(escape("kbs"), KeyBackspace); + trie.insert(escape("cr"), KeyReturn); + trie.insert(escape("ht"), KeyTab); + + trie.insert(escape("kcuu1"), KeyUp); + trie.insert(escape("kcud1"), KeyDown); + trie.insert(escape("kcub1"), KeyLeft); + trie.insert(escape("kcuf1"), KeyRight); + + trie.insert(escape("khome"), KeyHome); + trie.insert(escape("kend"), KeyEnd); + trie.insert(escape("kich1"), KeyInsert); + trie.insert(escape("kdch1"), KeyDelete); + + for uint::range(1, 12) |i| { + trie.insert(escape(fmt!("kf%d", i as int)), KeyF(i as int)); + } + + for uint::range(1, 26) |i| { + let s = str::from_char(i as char); + if (trie.find(s).is_none()) { + trie.insert(s, KeyCtrl(i as char)); + } + } + + trie.insert(str::from_char(27 as char), KeyEscape); + + trie +} + pub fn isatty() -> bool { unsafe { c_isatty(0) as bool } } |