This is currently an early experiment, though a lot of things are working.
Currently, http:
, https:
, file:
, and data:
URLs are supported. Plain
filesystem paths are also accepted, files with names ending with ".gz" are
decompressed on the fly, "-" means stdin or stdout, and "$(...)" means to run
a child process and pipe to its stdin or stdout.
This library provides:
-
New stream types,
InputByteStream
,OutputByteStream
, andInteractiveByteStream
, which implementRead
,Write
, and both, respectively, which you can use in type-aware command-line parsing packages such asstructopt
,clap-v3
,argh
,gumdrop
, or this library's ownkommand
. -
A new command-line parsing package,
kommand
, which is similar to (and built on)structopt
withpaw
support enabled, but which goes a step further and uses function argument syntax instead of having an options struct. -
New buffered I/O helpers,
BufInteractor
andBufReaderLineWriter
, which work likeBufReader
combined withBufWriter
andLineWriter
respectively, and aReadWrite
trait which combinesRead
andWrite
, for working withInteractiveByteStream
s.
When using these features, boilerplate for converting command-line argument strings into open files is abstracted away, allowing this library to transparently provide more features such as URLs, gzip'd files, stdin and stdout, and child processes.
It also helps programs avoid accidentally having behavior that depends on the names of files it accesses, which is a common source of trouble in deterministic-build environments.
Using kommand
:
/// A simple filter program with input and output
///
/// # Arguments
///
/// * `input` - Input source
/// * `output` - Output sink
#[kommand::main]
fn main(mut input: InputByteStream, mut output: OutputByteStream) {
// ... use `input` and `output`
}
Using structopt
:
#[derive(StructOpt)]
#[structopt(about = "A simple filter program with input and output")]
struct Opt {
/// Input source
input: InputByteStream,
/// Output sink
output: OutputByteStream,
}
fn main() {
let mut opt = Opt::from_args();
// ... use `opt.input` and `opt.output`.
}
In both examples, the underlying command-line argument strings are hidden from the main program. Command-line usage for both examples looks like this:
$ cargo run -- --help
simple-filter 0.0.0
A simple filter program with input and output
USAGE:
simple-filter <input> <output>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
ARGS:
<input> Input source
<output> Output sink
The arguments can then be a variety of kinds, including URLs and files:
$ cargo run -- https://example.com out.txt
With either structopt
or kommand
, command-line arguments can
use any type which implements FromStr
, including builtin types like i32
or bool
or library types like Regex
or Duration
. See the examples directory for
more examples.
data:
URLs aren't as widely known, but are cool and deserve special
mention. They carry a payload string in the URL itself which produced as the
input stream. For example, opening data:,Hello%2C%20World!
produces an
input stream that reads the string "Hello, World!". Payloads can also be
base64 encoded, like this: data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==
.
So you can pass a literal string directly into a program instead of creating
a temporary file.
‘This must be the wood,’ she said thoughtfully to herself, ‘where things have no names.’
— "Through the Looking Glass", by Lewis Carroll