diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-10-16 11:47:12 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-10-24 14:21:57 -0700 |
| commit | 35756fbcf6572d588929fde64fb4027f47e9d0af (patch) | |
| tree | 8a2f0ec01c2eb26f5db34887b8b2335a844d5b9d /src/libstd/rt/io/stdio.rs | |
| parent | 32b07c6a40bd7e1874244096f413096a6e059a29 (diff) | |
| download | rust-35756fbcf6572d588929fde64fb4027f47e9d0af.tar.gz rust-35756fbcf6572d588929fde64fb4027f47e9d0af.zip | |
Move rt::io::stdio from FileStream to a TTY
We get a little more functionality from libuv for these kinds of streams (things like terminal dimentions), and it also appears to more gracefully handle the stream being a window. Beforehand, if you used stdio and hit CTRL+d on a process, libuv would continually return 0-length successful reads instead of interpreting that the stream was closed. I was hoping to be able to write tests for this, but currently the testing infrastructure doesn't allow tests with a stdin and a stdout, but this has been manually tested! (not that it means much)
Diffstat (limited to 'src/libstd/rt/io/stdio.rs')
| -rw-r--r-- | src/libstd/rt/io/stdio.rs | 102 |
1 files changed, 88 insertions, 14 deletions
diff --git a/src/libstd/rt/io/stdio.rs b/src/libstd/rt/io/stdio.rs index e6dd9a48099..0bc87c77a9c 100644 --- a/src/libstd/rt/io/stdio.rs +++ b/src/libstd/rt/io/stdio.rs @@ -13,7 +13,7 @@ use libc; use option::{Option, Some, None}; use result::{Ok, Err}; use rt::local::Local; -use rt::rtio::{RtioFileStream, IoFactoryObject, IoFactory}; +use rt::rtio::{IoFactoryObject, IoFactory, RtioTTYObject, RtioTTY}; use super::{Reader, Writer, io_error}; /// Creates a new non-blocking handle to the stdin of the current process. @@ -22,8 +22,8 @@ use super::{Reader, Writer, io_error}; pub fn stdin() -> StdReader { let stream = unsafe { let io: *mut IoFactoryObject = Local::unsafe_borrow(); - (*io).fs_from_raw_fd(libc::STDIN_FILENO, false) - }; + (*io).tty_open(libc::STDIN_FILENO, true, false) + }.unwrap(); StdReader { inner: stream } } @@ -36,8 +36,8 @@ pub fn stdin() -> StdReader { pub fn stdout() -> StdWriter { let stream = unsafe { let io: *mut IoFactoryObject = Local::unsafe_borrow(); - (*io).fs_from_raw_fd(libc::STDOUT_FILENO, false) - }; + (*io).tty_open(libc::STDOUT_FILENO, false, false) + }.unwrap(); StdWriter { inner: stream } } @@ -47,8 +47,8 @@ pub fn stdout() -> StdWriter { pub fn stderr() -> StdWriter { let stream = unsafe { let io: *mut IoFactoryObject = Local::unsafe_borrow(); - (*io).fs_from_raw_fd(libc::STDERR_FILENO, false) - }; + (*io).tty_open(libc::STDERR_FILENO, false, false) + }.unwrap(); StdWriter { inner: stream } } @@ -87,7 +87,30 @@ pub fn println_args(fmt: &fmt::Arguments) { /// Representation of a reader of a standard input stream pub struct StdReader { - priv inner: ~RtioFileStream + priv inner: ~RtioTTYObject +} + +impl StdReader { + /// Controls whether this output stream is a "raw stream" or simply a normal + /// stream. + /// + /// # Failure + /// + /// This function will raise on the `io_error` condition if an error + /// happens. + pub fn set_raw(&mut self, raw: bool) { + match self.inner.set_raw(raw) { + Ok(()) => {}, + Err(e) => io_error::cond.raise(e), + } + } + + /// Resets the mode of this stream back to its original state. + /// + /// # Failure + /// + /// This function cannot fail. + pub fn reset_mode(&mut self) { self.inner.reset_mode(); } } impl Reader for StdReader { @@ -106,7 +129,50 @@ impl Reader for StdReader { /// Representation of a writer to a standard output stream pub struct StdWriter { - priv inner: ~RtioFileStream + priv inner: ~RtioTTYObject +} + +impl StdWriter { + /// Gets the size of this output window, if possible. This is typically used + /// when the writer is attached to something like a terminal, this is used + /// to fetch the dimensions of the terminal. + /// + /// If successful, returns Some((width, height)). + /// + /// # Failure + /// + /// This function will raise on the `io_error` condition if an error + /// happens. + pub fn winsize(&mut self) -> Option<(int, int)> { + match self.inner.get_winsize() { + Ok(p) => Some(p), + Err(e) => { + io_error::cond.raise(e); + None + } + } + } + + /// Controls whether this output stream is a "raw stream" or simply a normal + /// stream. + /// + /// # Failure + /// + /// This function will raise on the `io_error` condition if an error + /// happens. + pub fn set_raw(&mut self, raw: bool) { + match self.inner.set_raw(raw) { + Ok(()) => {}, + Err(e) => io_error::cond.raise(e), + } + } + + /// Resets the mode of this stream back to its original state. + /// + /// # Failure + /// + /// This function cannot fail. + pub fn reset_mode(&mut self) { self.inner.reset_mode(); } } impl Writer for StdWriter { @@ -117,10 +183,18 @@ impl Writer for StdWriter { } } - fn flush(&mut self) { - match self.inner.flush() { - Ok(()) => {} - Err(e) => io_error::cond.raise(e) - } + fn flush(&mut self) { /* nothing to do */ } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn smoke() { + // Just make sure we can acquire handles + stdin(); + stdout(); + stderr(); } } |
