diff --git a/src/async.rs b/src/async.rs index f58b044..94e8d81 100644 --- a/src/async.rs +++ b/src/async.rs @@ -1,9 +1,34 @@ use std::io::{self, Read}; use std::sync::mpsc; use std::thread; +use std::io::BufReader; +use std::io::BufRead; use sys::tty::get_tty; +/// Construct an asynchronous handle to the TTY standard input, with a delimiter byte. +/// +/// This has the same advantages as async_stdin(), but also allows specifying a delimiter byte. The +/// reader will stop reading after consuming the delimiter byte. +pub fn async_stdin_until(delimiter: u8) -> AsyncReader { + let (send, recv) = mpsc::channel(); + + thread::spawn(move || for i in get_tty().unwrap().bytes() { + + match i { + Ok(byte) => { + let end_of_stream = &byte == &delimiter; + let send_error = send.send(Ok(byte)).is_err(); + + if end_of_stream || send_error { return; } + }, + Err(e) => { return; } + } + }); + + AsyncReader { recv: recv } +} + /// Construct an asynchronous handle to the TTY standard input. /// /// This allows you to read from standard input _without blocking_ the current thread. diff --git a/src/cursor.rs b/src/cursor.rs index 6296da9..cf8dc86 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -2,7 +2,7 @@ use std::fmt; use std::io::{self, Write, Error, ErrorKind, Read}; -use async::async_stdin; +use async::async_stdin_until; use std::time::{SystemTime, Duration}; use raw::CONTROL_SEQUENCE_TIMEOUT; @@ -94,7 +94,8 @@ pub trait DetectCursorPos { impl DetectCursorPos for W { fn cursor_pos(&mut self) -> io::Result<(u16, u16)> { - let mut stdin = async_stdin(); + let delimiter = b'R'; + let mut stdin = async_stdin_until(delimiter); // Where is the cursor? // Use `ESC [ 6 n`. @@ -108,7 +109,7 @@ impl DetectCursorPos for W { let now = SystemTime::now(); // Either consume all data up to R or wait for a timeout. - while buf[0] != b'R' && now.elapsed().unwrap() < timeout { + while buf[0] != delimiter && now.elapsed().unwrap() < timeout { if stdin.read(&mut buf)? > 0 { read_chars.push(buf[0]); }