From bb16b12a6acb8600af88f367112dc8562552fea0 Mon Sep 17 00:00:00 2001 From: Katsu Kawakami <kkawa1570@gmail.com> Date: Sun, 12 Jun 2016 22:20:03 -0400 Subject: [PATCH] Adding Window-specific isatty function libc does not define the STDIN_FILENO & STDOUT_FILENO for the windows platform. We instead check whether or not stdin and stdout are TTY by checking the GetConsoleMode output. --- src/lib.rs | 4 ++-- src/tty/mod.rs | 12 ++++++++---- src/tty/unix.rs | 16 +++++++++++++++- src/tty/windows.rs | 18 ++++++++++++++++++ 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d2e60e4e..302ced7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -900,8 +900,8 @@ impl<'completer> Editor<'completer> { // if the number of columns is stored here, we need a SIGWINCH handler... let editor = Editor { unsupported_term: tty::is_unsupported_term(), - stdin_isatty: tty::is_a_tty(libc::STDIN_FILENO), - stdout_isatty: tty::is_a_tty(libc::STDOUT_FILENO), + stdin_isatty: tty::is_a_tty(tty::StandardStream::StdIn), + stdout_isatty: tty::is_a_tty(tty::StandardStream::StdOut), history: History::new(), completer: None, kill_ring: KillRing::new(60), diff --git a/src/tty/mod.rs b/src/tty/mod.rs index ef8a1a0b..72cc3f36 100644 --- a/src/tty/mod.rs +++ b/src/tty/mod.rs @@ -22,8 +22,12 @@ pub trait Terminal { fn disable_raw_mode(&self) -> Result<()>; } -/// Check to see if `fd` is a TTY -pub fn is_a_tty(fd: libc::c_int) -> bool { - unsafe { libc::isatty(fd) != 0 } +/// Enum for Standard Streams +/// +/// libc::STDIN_FILENO/STDOUT_FILENO/STDERR_FILENO is not defined for the +/// Windows platform. We will use this enum instead when calling isatty +/// function +pub enum StandardStream { + StdIn, + StdOut, } - diff --git a/src/tty/unix.rs b/src/tty/unix.rs index fce1b6a0..d3f192df 100644 --- a/src/tty/unix.rs +++ b/src/tty/unix.rs @@ -5,6 +5,7 @@ use std; use nix::sys::termios; use nix::errno::Errno; use super::Terminal; +use super::StandardStream; use ::Result; use ::error; @@ -65,6 +66,19 @@ pub fn is_unsupported_term() -> bool { } } + +/// Return whether or not STDIN, STDOUT or STDERR is a TTY +pub fn is_a_tty(stream: StandardStream) -> bool { + extern crate libc; + + let fd = match stream { + StandardStream::StdIn => libc::STDIN_FILENO, + StandardStream::StdOut => libc::STDOUT_FILENO, + }; + + unsafe { libc::isatty(fd) != 0 } +} + /// Structure that will contain the original termios before enabling RAW mode pub struct UnixTerminal { original_termios: Option<termios::Termios> @@ -75,7 +89,7 @@ impl Terminal for UnixTerminal { fn enable_raw_mode(&mut self) -> Result<()> { use nix::sys::termios::{BRKINT, CS8, ECHO, ICANON, ICRNL, IEXTEN, INPCK, ISIG, ISTRIP, IXON, OPOST, VMIN, VTIME}; - if !super::is_a_tty(libc::STDIN_FILENO) { + if !is_a_tty(StandardStream::StdIn) { return Err(error::ReadlineError::from_errno(Errno::ENOTTY)); } let original_termios = try!(termios::tcgetattr(libc::STDIN_FILENO)); diff --git a/src/tty/windows.rs b/src/tty/windows.rs index 3a9772b1..b661d2f1 100644 --- a/src/tty/windows.rs +++ b/src/tty/windows.rs @@ -1,3 +1,21 @@ +extern crate kernel32; +extern crate winapi; + +use super::StandardStream; + +/// Return whether or not STDIN, STDOUT or STDERR is a TTY +fn is_a_tty(stream: StandardStream) -> bool { + let handle = match stream { + StandardStream::StdIn => winapi::winbase::STD_INPUT_HANDLE, + StandardStream::Stdout => winapi::winbase::STD_OUTPUT_HANDLE, + }; + + unsafe { + let handle = kernel32::GetStdHandle(handle); + let mut out = 0; + kernel32::GetConsoleMode(handle, &mut out) != 0 + } +} /// Checking for an unsupported TERM in windows is a no-op pub fn is_unsupported_term() -> bool { -- GitLab