This is currently an early experiment, though a lot of things are working.
The kommand
crate and many of the examples in this repository depend on
[a fork of clap]. See the README.md in that repository for details. As a user,
to pull in the requisite support add the following to Cargo.toml:
toml
clap = { git = "https://github.com/sunfishcode/clap", branch = "try-from-os-arg" }
clap_derive = { git = "https://github.com/sunfishcode/clap", branch = "try-from-os-arg" }
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
], and
[InteractiveByteStream
], which implement [Read
], [Write
], and both,
respectively, which you can use in type-aware command-line parsing
packages such as [structopt
], [clap-v3
], [argh
], [gumdrop
], or this
library's own [kommand
].
A new command-line parsing package, [kommand
], which is similar to
(and built on) [structopt
] with [paw
] 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
] and [BufReaderLineWriter
],
which work like [BufReader
] combined with [BufWriter
] and [LineWriter
]
respectively, and a [ReadWrite
] trait which combines [Read
] and [Write
],
for working with [InteractiveByteStream
]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 [structopt
]:
```rust
struct Opt { /// Input source input: InputByteStream,
/// Output sink
output: OutputByteStream,
}
fn main() { let mut opt = Opt::from_args();
// ... use `opt.input` and `opt.output`.
} ```
Using [kommand
]:
```rust /// A simple filter program with input and output
fn main( /// Input source mut input: InputByteStream,
/// Output sink
mut output: OutputByteStream,
) {
// ... use input
and 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
FLAGS: -h, --help Prints help information -V, --version Prints version information
ARGS: Input source
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