diff --git a/Cargo.lock b/Cargo.lock index 703b8c88..b768d505 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,7 @@ name = "ripgrep" version = "0.4.0" dependencies = [ + "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -33,6 +34,16 @@ name = "ansi_term" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "atty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "0.7.0" @@ -313,6 +324,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f660b942762979b56c9f07b4b36bb559776fbad102f05d6771e1b629e8fd5bf" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" +"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bytecount 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1e8f09fbc8c6726a4b616dcfbd4f54491068d6bb1b93ac03c78ac18ff9a5924a" "checksum clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95b78f3fe0fc94c13c731714363260e04b557a637166f33a4570d3189d642374" diff --git a/Cargo.toml b/Cargo.toml index b65e1368..da1c9d2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ name = "integration" path = "tests/tests.rs" [dependencies] +atty = "0.2.2" bytecount = "0.1.4" clap = "2.19.0" env_logger = { version = "0.3", default-features = false } diff --git a/src/args.rs b/src/args.rs index eeccb184..15184d4e 100644 --- a/src/args.rs +++ b/src/args.rs @@ -394,8 +394,8 @@ impl<'a> ArgMatches<'a> { self.values_of_os("file").map_or(false, |mut files| { files.any(|f| f == "-") }); - let search_cwd = atty::on_stdin() - || !atty::stdin_is_readable() + let search_cwd = atty::is(atty::Stream::Stdin) + || !stdin_is_readable() || (self.is_present("file") && file_is_stdin) || self.is_present("files") || self.is_present("type-list"); @@ -584,7 +584,7 @@ impl<'a> ArgMatches<'a> { } else { self.is_present("line-number") || self.is_present("column") - || atty::on_stdout() + || atty::is(atty::Stream::Stdout) || self.is_present("pretty") || self.is_present("vimgrep") } @@ -602,7 +602,7 @@ impl<'a> ArgMatches<'a> { false } else { self.is_present("heading") - || atty::on_stdout() + || atty::is(atty::Stream::Stdout) || self.is_present("pretty") } } @@ -667,7 +667,7 @@ impl<'a> ArgMatches<'a> { } else if self.is_present("vimgrep") { false } else if preference == "auto" { - atty::on_stdout() || self.is_present("pretty") + atty::is(atty::Stream::Stdout) || self.is_present("pretty") } else { false } @@ -687,7 +687,7 @@ impl<'a> ArgMatches<'a> { } else if self.is_present("vimgrep") { termcolor::ColorChoice::Never } else if preference == "auto" { - if atty::on_stdout() || self.is_present("pretty") { + if atty::is(atty::Stream::Stdout) || self.is_present("pretty") { termcolor::ColorChoice::Auto } else { termcolor::ColorChoice::Never @@ -869,3 +869,24 @@ impl QuietMatched { } } } + +/// Returns true if and only if stdin is deemed searchable. +#[cfg(unix)] +fn stdin_is_readable() -> bool { + use std::os::unix::fs::FileTypeExt; + use same_file::Handle; + + let ft = match Handle::stdin().and_then(|h| h.as_file().metadata()) { + Err(_) => return false, + Ok(md) => md.file_type(), + }; + ft.is_file() || ft.is_fifo() +} + +/// Returns true if and only if stdin is deemed searchable. +#[cfg(windows)] +fn stdin_is_readable() -> bool { + // On Windows, it's not clear what the possibilities are to me, so just + // always return true. + true +} diff --git a/src/atty.rs b/src/atty.rs deleted file mode 100644 index cb10c1dc..00000000 --- a/src/atty.rs +++ /dev/null @@ -1,145 +0,0 @@ -/*! -This atty module contains functions for detecting whether ripgrep is being fed -from (or to) a terminal. Windows and Unix do this differently, so implement -both here. -*/ - -#[cfg(windows)] -use winapi::minwindef::DWORD; -#[cfg(windows)] -use winapi::winnt::HANDLE; - -#[cfg(unix)] -pub fn stdin_is_readable() -> bool { - use std::os::unix::fs::FileTypeExt; - use same_file::Handle; - - let ft = match Handle::stdin().and_then(|h| h.as_file().metadata()) { - Err(_) => return false, - Ok(md) => md.file_type(), - }; - ft.is_file() || ft.is_fifo() -} - -#[cfg(windows)] -pub fn stdin_is_readable() -> bool { - // ??? - true -} - -/// Returns true if there is a tty on stdin. -#[cfg(unix)] -pub fn on_stdin() -> bool { - use libc; - 0 < unsafe { libc::isatty(libc::STDIN_FILENO) } -} - -/// Returns true if there is a tty on stdout. -#[cfg(unix)] -pub fn on_stdout() -> bool { - use libc; - 0 < unsafe { libc::isatty(libc::STDOUT_FILENO) } -} - -/// Returns true if there is a tty on stdin. -#[cfg(windows)] -pub fn on_stdin() -> bool { - use kernel32::GetStdHandle; - use winapi::winbase::{ - STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE, - }; - - unsafe { - let stdin = GetStdHandle(STD_INPUT_HANDLE); - if console_on_handle(stdin) { - // False positives aren't possible. If we got a console then - // we definitely have a tty on stdin. - return true; - } - // Otherwise, it's possible to get a false negative. If we know that - // there's a console on stdout or stderr however, then this is a true - // negative. - if console_on_fd(STD_OUTPUT_HANDLE) - || console_on_fd(STD_ERROR_HANDLE) { - return false; - } - // Otherwise, we can't really tell, so we do a weird hack. - msys_tty_on_handle(stdin) - } -} - -/// Returns true if there is a tty on stdout. -#[cfg(windows)] -pub fn on_stdout() -> bool { - use kernel32::GetStdHandle; - use winapi::winbase::{ - STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE, - }; - - unsafe { - let stdout = GetStdHandle(STD_OUTPUT_HANDLE); - if console_on_handle(stdout) { - // False positives aren't possible. If we got a console then - // we definitely have a tty on stdout. - return true; - } - // Otherwise, it's possible to get a false negative. If we know that - // there's a console on stdin or stderr however, then this is a true - // negative. - if console_on_fd(STD_INPUT_HANDLE) || console_on_fd(STD_ERROR_HANDLE) { - return false; - } - // Otherwise, we can't really tell, so we do a weird hack. - msys_tty_on_handle(stdout) - } -} - -/// Returns true if there is an MSYS tty on the given handle. -#[cfg(windows)] -unsafe fn msys_tty_on_handle(handle: HANDLE) -> bool { - use std::ffi::OsString; - use std::mem; - use std::os::raw::c_void; - use std::os::windows::ffi::OsStringExt; - use std::slice; - - use kernel32::{GetFileInformationByHandleEx}; - use winapi::fileapi::FILE_NAME_INFO; - use winapi::minwinbase::FileNameInfo; - use winapi::minwindef::MAX_PATH; - - let size = mem::size_of::(); - let mut name_info_bytes = vec![0u8; size + MAX_PATH]; - let res = GetFileInformationByHandleEx( - handle, - FileNameInfo, - &mut *name_info_bytes as *mut _ as *mut c_void, - name_info_bytes.len() as u32); - if res == 0 { - return true; - } - let name_info: FILE_NAME_INFO = - *(name_info_bytes[0..size].as_ptr() as *const FILE_NAME_INFO); - let name_bytes = - &name_info_bytes[size..size + name_info.FileNameLength as usize]; - let name_u16 = slice::from_raw_parts( - name_bytes.as_ptr() as *const u16, name_bytes.len() / 2); - let name = OsString::from_wide(name_u16) - .as_os_str().to_string_lossy().into_owned(); - name.contains("msys-") || name.contains("-pty") -} - -/// Returns true if there is a console on the given file descriptor. -#[cfg(windows)] -unsafe fn console_on_fd(fd: DWORD) -> bool { - use kernel32::GetStdHandle; - console_on_handle(GetStdHandle(fd)) -} - -/// Returns true if there is a console on the given handle. -#[cfg(windows)] -unsafe fn console_on_handle(handle: HANDLE) -> bool { - use kernel32::GetConsoleMode; - let mut out = 0; - GetConsoleMode(handle, &mut out) != 0 -} diff --git a/src/main.rs b/src/main.rs index 735298f9..66860d14 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +extern crate atty; extern crate bytecount; #[macro_use] extern crate clap; @@ -46,7 +47,6 @@ macro_rules! eprintln { mod app; mod args; -mod atty; mod pathutil; mod printer; mod search_buffer;