From b7646b2d791cf10bd604aaee830fe22598b7d10d Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Mon, 1 Apr 2013 02:06:35 -0500 Subject: provide a timeout for reads when trying to match an escape --- src/io_helper.c | 38 ++++++++++++++++++++++++++++++++++++++ src/term.rs | 23 +++++++++++++++-------- src/util.rs | 27 +++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 src/io_helper.c (limited to 'src') diff --git a/src/io_helper.c b/src/io_helper.c new file mode 100644 index 0000000..f4fa088 --- /dev/null +++ b/src/io_helper.c @@ -0,0 +1,38 @@ +#include +#include + +int timed_read(int timeout) +{ + char byte; + + if (timeout >= 0) { + fd_set readfds; + struct timeval t; + + FD_ZERO(&readfds); + FD_SET(0, &readfds); + + t.tv_sec = timeout / 1000000; + t.tv_usec = timeout % 1000000; + + if (select(1, &readfds, NULL, NULL, &t) == 1) { + if (read(0, &byte, 1) == 1) { + return byte; + } + else { + return -1; + } + } + else { + return -1; + } + } + else { + if (read(0, &byte, 1) == 1) { + return byte; + } + else { + return -1; + } + } +} diff --git a/src/term.rs b/src/term.rs index 001138f..bb29025 100644 --- a/src/term.rs +++ b/src/term.rs @@ -93,15 +93,13 @@ impl Reader { return Some(KeyCharacter(str::shift_char(&mut self.buf))); } - let mut buf = ~""; - loop { - let c = io::stdin().read_char(); - if c as int == -1 { - return None; - } - - str::push_char(&mut buf, c); + let first = util::timed_read(-1); + if first.is_none() { + return None; + } + let mut buf = str::from_char(*first.get_ref()); + loop { if !self.escapes.has_prefix(buf) { return match self.escapes.find(buf) { &Some(k) => { Some(k) } @@ -112,6 +110,15 @@ impl Reader { } } } + + match util::timed_read(1000000) { + Some(next) => { str::push_char(&mut buf, next) } + None => { + str::push_str(&mut self.buf, buf); + let next = str::shift_char(&mut self.buf); + return Some(KeyCharacter(next)); + } + } } } } diff --git a/src/util.rs b/src/util.rs index 7ea5389..8ed877a 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,3 +1,5 @@ +use core::libc::c_int; + pub fn guard (finally: ~fn (), body: &fn () -> T) -> T { let _guard = Guard { finally: finally }; body() @@ -218,3 +220,28 @@ fn check_has_prefix (trie: &Trie, find: &str) { fn check_not_has_prefix (trie: &Trie, find: &str) { fail_unless!(!trie.has_prefix(find)); } + +// XXX huge hack until there's a better built-in way to do this +pub fn timed_read (timeout: int) -> Option { + let first = unsafe { io_helper::timed_read(timeout as c_int) }; + if first < 0 { + return None; + } + + let mut buf = ~[first as u8]; + let nbytes = str::utf8_char_width(first as u8); + + for uint::range(0, nbytes - 1) |_| { + let next = unsafe { io_helper::timed_read(-1 as c_int) }; + if next < 0 { + return None; + } + vec::push(&mut buf, next as u8); + } + + Some(str::char_at(unsafe { str::raw::from_bytes(buf) }, 0)) +} + +extern mod io_helper { + fn timed_read (timeout: c_int) -> c_int; +} -- cgit v1.2.3-54-g00ecf