mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-06-25 14:22:54 +02:00
cli: clean-up crate
This does a variety of polishing. 1. Deprecate the tty methods in favor of std's IsTerminal trait. 2. Trim down un-needed dependencies. 3. Use bstr to implement escaping. 4. Various aesthetic polishing. I'm doing this as prep work before adding more to this crate. And as part of a general effort toward reducing ripgrep's dependencies.
This commit is contained in:
@ -11,27 +11,11 @@ and Linux.
|
||||
|
||||
# Standard I/O
|
||||
|
||||
The
|
||||
[`is_readable_stdin`](fn.is_readable_stdin.html),
|
||||
[`is_tty_stderr`](fn.is_tty_stderr.html),
|
||||
[`is_tty_stdin`](fn.is_tty_stdin.html)
|
||||
and
|
||||
[`is_tty_stdout`](fn.is_tty_stdout.html)
|
||||
routines query aspects of standard I/O. `is_readable_stdin` determines whether
|
||||
stdin can be usefully read from, while the `tty` methods determine whether a
|
||||
tty is attached to stdin/stdout/stderr.
|
||||
|
||||
`is_readable_stdin` is useful when writing an application that changes behavior
|
||||
based on whether the application was invoked with data on stdin. For example,
|
||||
`rg foo` might recursively search the current working directory for
|
||||
occurrences of `foo`, but `rg foo < file` might only search the contents of
|
||||
`file`.
|
||||
|
||||
The `tty` methods are useful for similar reasons. Namely, commands like `ls`
|
||||
will change their output depending on whether they are printing to a terminal
|
||||
or not. For example, `ls` shows a file on each line when stdout is redirected
|
||||
to a file or a pipe, but condenses the output to show possibly many files on
|
||||
each line when stdout is connected to a tty.
|
||||
[`is_readable_stdin`] determines whether stdin can be usefully read from. It
|
||||
is useful when writing an application that changes behavior based on whether
|
||||
the application was invoked with data on stdin. For example, `rg foo` might
|
||||
recursively search the current working directory for occurrences of `foo`, but
|
||||
`rg foo < file` might only search the contents of `file`.
|
||||
|
||||
|
||||
# Coloring and buffering
|
||||
@ -165,21 +149,21 @@ mod pattern;
|
||||
mod process;
|
||||
mod wtr;
|
||||
|
||||
use std::io::IsTerminal;
|
||||
|
||||
pub use crate::decompress::{
|
||||
resolve_binary, DecompressionMatcher, DecompressionMatcherBuilder,
|
||||
DecompressionReader, DecompressionReaderBuilder,
|
||||
};
|
||||
pub use crate::escape::{escape, escape_os, unescape, unescape_os};
|
||||
pub use crate::human::{parse_human_readable_size, ParseSizeError};
|
||||
pub use crate::pattern::{
|
||||
pattern_from_bytes, pattern_from_os, patterns_from_path,
|
||||
patterns_from_reader, patterns_from_stdin, InvalidPatternError,
|
||||
};
|
||||
pub use crate::process::{CommandError, CommandReader, CommandReaderBuilder};
|
||||
pub use crate::wtr::{
|
||||
stdout, stdout_buffered_block, stdout_buffered_line, StandardStream,
|
||||
pub use crate::{
|
||||
decompress::{
|
||||
resolve_binary, DecompressionMatcher, DecompressionMatcherBuilder,
|
||||
DecompressionReader, DecompressionReaderBuilder,
|
||||
},
|
||||
escape::{escape, escape_os, unescape, unescape_os},
|
||||
human::{parse_human_readable_size, ParseSizeError},
|
||||
pattern::{
|
||||
pattern_from_bytes, pattern_from_os, patterns_from_path,
|
||||
patterns_from_reader, patterns_from_stdin, InvalidPatternError,
|
||||
},
|
||||
process::{CommandError, CommandReader, CommandReaderBuilder},
|
||||
wtr::{
|
||||
stdout, stdout_buffered_block, stdout_buffered_line, StandardStream,
|
||||
},
|
||||
};
|
||||
|
||||
/// Returns true if and only if stdin is believed to be readable.
|
||||
@ -189,34 +173,60 @@ pub use crate::wtr::{
|
||||
/// might search the current directory for occurrences of `foo` where as
|
||||
/// `command foo < some-file` or `cat some-file | command foo` might instead
|
||||
/// only search stdin for occurrences of `foo`.
|
||||
///
|
||||
/// Note that this isn't perfect and essentially corresponds to a heuristic.
|
||||
/// When things are unclear (such as if an error occurs during introspection to
|
||||
/// determine whether stdin is readable), this prefers to return `false`. That
|
||||
/// means it's possible for an end user to pipe something into your program and
|
||||
/// have this return `false` and thus potentially lead to ignoring the user's
|
||||
/// stdin data. While not ideal, this is perhaps better than falsely assuming
|
||||
/// stdin is readable, which would result in blocking forever on reading stdin.
|
||||
/// Regardless, commands should always provide explicit fallbacks to override
|
||||
/// behavior. For example, `rg foo -` will explicitly search stdin and `rg foo
|
||||
/// ./` will explicitly search the current working directory.
|
||||
pub fn is_readable_stdin() -> bool {
|
||||
use std::io::IsTerminal;
|
||||
|
||||
#[cfg(unix)]
|
||||
fn imp() -> bool {
|
||||
use same_file::Handle;
|
||||
use std::os::unix::fs::FileTypeExt;
|
||||
|
||||
let ft = match Handle::stdin().and_then(|h| h.as_file().metadata()) {
|
||||
Err(_) => return false,
|
||||
Ok(md) => md.file_type(),
|
||||
use std::{
|
||||
fs::File,
|
||||
os::{fd::AsFd, unix::fs::FileTypeExt},
|
||||
};
|
||||
|
||||
let stdin = std::io::stdin();
|
||||
let Ok(fd) = stdin.as_fd().try_clone_to_owned() else { return false };
|
||||
let file = File::from(fd);
|
||||
let Ok(md) = file.metadata() else { return false };
|
||||
let ft = md.file_type();
|
||||
ft.is_file() || ft.is_fifo() || ft.is_socket()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn imp() -> bool {
|
||||
use winapi_util as winutil;
|
||||
|
||||
winutil::file::typ(winutil::HandleRef::stdin())
|
||||
winapi_util::file::typ(winapi_util::HandleRef::stdin())
|
||||
.map(|t| t.is_disk() || t.is_pipe())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
!is_tty_stdin() && imp()
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
fn imp() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
!std::io::stdin().is_terminal() && imp()
|
||||
}
|
||||
|
||||
/// Returns true if and only if stdin is believed to be connected to a tty
|
||||
/// or a console.
|
||||
///
|
||||
/// Note that this is now just a wrapper around
|
||||
/// [`std::io::IsTerminal`](https://doc.rust-lang.org/std/io/trait.IsTerminal.html).
|
||||
/// Callers should prefer using the `IsTerminal` trait directly. This routine
|
||||
/// is deprecated and will be removed in the next semver incompatible release.
|
||||
#[deprecated(since = "0.1.10", note = "use std::io::IsTerminal instead")]
|
||||
pub fn is_tty_stdin() -> bool {
|
||||
use std::io::IsTerminal;
|
||||
std::io::stdin().is_terminal()
|
||||
}
|
||||
|
||||
@ -228,12 +238,26 @@ pub fn is_tty_stdin() -> bool {
|
||||
/// terminal or whether it's being redirected somewhere else. For example,
|
||||
/// implementations of `ls` will often show one item per line when stdout is
|
||||
/// redirected, but will condensed output when printing to a tty.
|
||||
///
|
||||
/// Note that this is now just a wrapper around
|
||||
/// [`std::io::IsTerminal`](https://doc.rust-lang.org/std/io/trait.IsTerminal.html).
|
||||
/// Callers should prefer using the `IsTerminal` trait directly. This routine
|
||||
/// is deprecated and will be removed in the next semver incompatible release.
|
||||
#[deprecated(since = "0.1.10", note = "use std::io::IsTerminal instead")]
|
||||
pub fn is_tty_stdout() -> bool {
|
||||
use std::io::IsTerminal;
|
||||
std::io::stdout().is_terminal()
|
||||
}
|
||||
|
||||
/// Returns true if and only if stderr is believed to be connected to a tty
|
||||
/// or a console.
|
||||
///
|
||||
/// Note that this is now just a wrapper around
|
||||
/// [`std::io::IsTerminal`](https://doc.rust-lang.org/std/io/trait.IsTerminal.html).
|
||||
/// Callers should prefer using the `IsTerminal` trait directly. This routine
|
||||
/// is deprecated and will be removed in the next semver incompatible release.
|
||||
#[deprecated(since = "0.1.10", note = "use std::io::IsTerminal instead")]
|
||||
pub fn is_tty_stderr() -> bool {
|
||||
use std::io::IsTerminal;
|
||||
std::io::stderr().is_terminal()
|
||||
}
|
||||
|
Reference in New Issue
Block a user