|
|
|
|
@@ -20,22 +20,17 @@ recursively search the current working directory for occurrences of `foo`, but
|
|
|
|
|
|
|
|
|
|
# Coloring and buffering
|
|
|
|
|
|
|
|
|
|
The
|
|
|
|
|
[`stdout`](fn.stdout.html),
|
|
|
|
|
[`stdout_buffered_block`](fn.stdout_buffered_block.html)
|
|
|
|
|
and
|
|
|
|
|
[`stdout_buffered_line`](fn.stdout_buffered_line.html)
|
|
|
|
|
routines are alternative constructors for
|
|
|
|
|
[`StandardStream`](struct.StandardStream.html).
|
|
|
|
|
A `StandardStream` implements `termcolor::WriteColor`, which provides a way
|
|
|
|
|
to emit colors to terminals. Its key use is the encapsulation of buffering
|
|
|
|
|
style. Namely, `stdout` will return a line buffered `StandardStream` if and
|
|
|
|
|
only if stdout is connected to a tty, and will otherwise return a block
|
|
|
|
|
buffered `StandardStream`. Line buffering is important for use with a tty
|
|
|
|
|
because it typically decreases the latency at which the end user sees output.
|
|
|
|
|
Block buffering is used otherwise because it is faster, and redirecting stdout
|
|
|
|
|
to a file typically doesn't benefit from the decreased latency that line
|
|
|
|
|
buffering provides.
|
|
|
|
|
The [`stdout`], [`stdout_buffered_block`] and [`stdout_buffered_line`] routines
|
|
|
|
|
are alternative constructors for [`StandardStream`]. A `StandardStream`
|
|
|
|
|
implements `termcolor::WriteColor`, which provides a way to emit colors to
|
|
|
|
|
terminals. Its key use is the encapsulation of buffering style. Namely,
|
|
|
|
|
`stdout` will return a line buffered `StandardStream` if and only if
|
|
|
|
|
stdout is connected to a tty, and will otherwise return a block buffered
|
|
|
|
|
`StandardStream`. Line buffering is important for use with a tty because it
|
|
|
|
|
typically decreases the latency at which the end user sees output. Block
|
|
|
|
|
buffering is used otherwise because it is faster, and redirecting stdout to a
|
|
|
|
|
file typically doesn't benefit from the decreased latency that line buffering
|
|
|
|
|
provides.
|
|
|
|
|
|
|
|
|
|
The `stdout_buffered_block` and `stdout_buffered_line` can be used to
|
|
|
|
|
explicitly set the buffering strategy regardless of whether stdout is connected
|
|
|
|
|
@@ -44,17 +39,12 @@ to a tty or not.
|
|
|
|
|
|
|
|
|
|
# Escaping
|
|
|
|
|
|
|
|
|
|
The
|
|
|
|
|
[`escape`](fn.escape.html),
|
|
|
|
|
[`escape_os`](fn.escape_os.html),
|
|
|
|
|
[`unescape`](fn.unescape.html)
|
|
|
|
|
and
|
|
|
|
|
[`unescape_os`](fn.unescape_os.html)
|
|
|
|
|
routines provide a user friendly way of dealing with UTF-8 encoded strings that
|
|
|
|
|
can express arbitrary bytes. For example, you might want to accept a string
|
|
|
|
|
containing arbitrary bytes as a command line argument, but most interactive
|
|
|
|
|
shells make such strings difficult to type. Instead, we can ask users to use
|
|
|
|
|
escape sequences.
|
|
|
|
|
The [`escape`](crate::escape()), [`escape_os`], [`unescape`] and
|
|
|
|
|
[`unescape_os`] routines provide a user friendly way of dealing with UTF-8
|
|
|
|
|
encoded strings that can express arbitrary bytes. For example, you might want
|
|
|
|
|
to accept a string containing arbitrary bytes as a command line argument, but
|
|
|
|
|
most interactive shells make such strings difficult to type. Instead, we can
|
|
|
|
|
ask users to use escape sequences.
|
|
|
|
|
|
|
|
|
|
For example, `a\xFFz` is itself a valid UTF-8 string corresponding to the
|
|
|
|
|
following bytes:
|
|
|
|
|
@@ -87,44 +77,36 @@ makes it easy to show user friendly error messages involving arbitrary bytes.
|
|
|
|
|
# Building patterns
|
|
|
|
|
|
|
|
|
|
Typically, regular expression patterns must be valid UTF-8. However, command
|
|
|
|
|
line arguments aren't guaranteed to be valid UTF-8. Unfortunately, the
|
|
|
|
|
standard library's UTF-8 conversion functions from `OsStr`s do not provide
|
|
|
|
|
good error messages. However, the
|
|
|
|
|
[`pattern_from_bytes`](fn.pattern_from_bytes.html)
|
|
|
|
|
and
|
|
|
|
|
[`pattern_from_os`](fn.pattern_from_os.html)
|
|
|
|
|
do, including reporting exactly where the first invalid UTF-8 byte is seen.
|
|
|
|
|
line arguments aren't guaranteed to be valid UTF-8. Unfortunately, the standard
|
|
|
|
|
library's UTF-8 conversion functions from `OsStr`s do not provide good error
|
|
|
|
|
messages. However, the [`pattern_from_bytes`] and [`pattern_from_os`] do,
|
|
|
|
|
including reporting exactly where the first invalid UTF-8 byte is seen.
|
|
|
|
|
|
|
|
|
|
Additionally, it can be useful to read patterns from a file while reporting
|
|
|
|
|
good error messages that include line numbers. The
|
|
|
|
|
[`patterns_from_path`](fn.patterns_from_path.html),
|
|
|
|
|
[`patterns_from_reader`](fn.patterns_from_reader.html)
|
|
|
|
|
and
|
|
|
|
|
[`patterns_from_stdin`](fn.patterns_from_stdin.html)
|
|
|
|
|
routines do just that. If any pattern is found that is invalid UTF-8, then the
|
|
|
|
|
error includes the file path (if available) along with the line number and the
|
|
|
|
|
byte offset at which the first invalid UTF-8 byte was observed.
|
|
|
|
|
good error messages that include line numbers. The [`patterns_from_path`],
|
|
|
|
|
[`patterns_from_reader`] and [`patterns_from_stdin`] routines do just that. If
|
|
|
|
|
any pattern is found that is invalid UTF-8, then the error includes the file
|
|
|
|
|
path (if available) along with the line number and the byte offset at which the
|
|
|
|
|
first invalid UTF-8 byte was observed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Read process output
|
|
|
|
|
|
|
|
|
|
Sometimes a command line application needs to execute other processes and read
|
|
|
|
|
its stdout in a streaming fashion. The
|
|
|
|
|
[`CommandReader`](struct.CommandReader.html)
|
|
|
|
|
provides this functionality with an explicit goal of improving failure modes.
|
|
|
|
|
In particular, if the process exits with an error code, then stderr is read
|
|
|
|
|
and converted into a normal Rust error to show to end users. This makes the
|
|
|
|
|
underlying failure modes explicit and gives more information to end users for
|
|
|
|
|
debugging the problem.
|
|
|
|
|
Sometimes a command line application needs to execute other processes and
|
|
|
|
|
read its stdout in a streaming fashion. The [`CommandReader`] provides this
|
|
|
|
|
functionality with an explicit goal of improving failure modes. In particular,
|
|
|
|
|
if the process exits with an error code, then stderr is read and converted into
|
|
|
|
|
a normal Rust error to show to end users. This makes the underlying failure
|
|
|
|
|
modes explicit and gives more information to end users for debugging the
|
|
|
|
|
problem.
|
|
|
|
|
|
|
|
|
|
As a special case,
|
|
|
|
|
[`DecompressionReader`](struct.DecompressionReader.html)
|
|
|
|
|
provides a way to decompress arbitrary files by matching their file extensions
|
|
|
|
|
up with corresponding decompression programs (such as `gzip` and `xz`). This
|
|
|
|
|
is useful as a means of performing simplistic decompression in a portable
|
|
|
|
|
manner without binding to specific compression libraries. This does come with
|
|
|
|
|
some overhead though, so if you need to decompress lots of small files, this
|
|
|
|
|
may not be an appropriate convenience to use.
|
|
|
|
|
As a special case, [`DecompressionReader`] provides a way to decompress
|
|
|
|
|
arbitrary files by matching their file extensions up with corresponding
|
|
|
|
|
decompression programs (such as `gzip` and `xz`). This is useful as a means of
|
|
|
|
|
performing simplistic decompression in a portable manner without binding to
|
|
|
|
|
specific compression libraries. This does come with some overhead though, so
|
|
|
|
|
if you need to decompress lots of small files, this may not be an appropriate
|
|
|
|
|
convenience to use.
|
|
|
|
|
|
|
|
|
|
Each reader has a corresponding builder for additional configuration, such as
|
|
|
|
|
whether to read stderr asynchronously in order to avoid deadlock (which is
|
|
|
|
|
@@ -133,11 +115,10 @@ enabled by default).
|
|
|
|
|
|
|
|
|
|
# Miscellaneous parsing
|
|
|
|
|
|
|
|
|
|
The
|
|
|
|
|
[`parse_human_readable_size`](fn.parse_human_readable_size.html)
|
|
|
|
|
routine parses strings like `2M` and converts them to the corresponding number
|
|
|
|
|
of bytes (`2 * 1<<20` in this case). If an invalid size is found, then a good
|
|
|
|
|
error message is crafted that typically tells the user how to fix the problem.
|
|
|
|
|
The [`parse_human_readable_size`] routine parses strings like `2M` and converts
|
|
|
|
|
them to the corresponding number of bytes (`2 * 1<<20` in this case). If an
|
|
|
|
|
invalid size is found, then a good error message is crafted that typically
|
|
|
|
|
tells the user how to fix the problem.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#![deny(missing_docs)]
|
|
|
|
|
|