Nameless provides full-service command-line parsing. This means you just write
a main
function with arguments with the types you want, add a [conventional]
documentation comment, and it takes care of the rest:
```rust use nameless::{InputByteStream, OutputByteStream}; use std::io::{self, Read, Write};
/// A simple program with input and output
///
/// # Arguments
///
/// * input
- Input source
/// * output
- Output sink
fn main(mut input: InputByteStream, mut output: OutputByteStream) -> io::Result<()> { let mut s = String::new(); input.readtostring(&mut s)?; output.writeall(s.asbytes()) } ```
Nameless completely handles "string to stream" translation. And in doing so, it
doesn't just support files, but also gzipped files (\*.gz
),
stdin/stdout (-
), child processes ($(...)
), and URLs, including http:
,
https:
, scp:
(enable the "ssh2" feature), file:
, and data:
. So while
your code is busy doing one thing and doing it well, nameless takes care of
streaming the data in and out. "Everything is a URL, and more", on Linux,
macOS, Windows, and more.
kommand::main
parses the documentation comment to extract the program
description and the arguments. The command-line usage for the example above
looks like this:
``` $ cargo run -- --help simple-filter 0.0.0 A simple program with input and output
USAGE: simple-filter
FLAGS: -h, --help Prints help information -V, --version Prints version information
ARGS: Input source
This library provides:
New stream types, [InputByteStream
], [OutputByteStream
], and
[InteractiveByteStream
] for working with byte streams, and
[InputTextStream
], [OutputTextStream
], and [InteractiveTextStream
]
for working with text streams. These implement [Read
] and [Write
] in
the usual way, so they interoperate with existing Rust code.
You can use all these types in type-aware command-line parsing packages
such as [nameless-clap_derive
] or this library's own [kommand
].
(nameless-clap_derive
is a temporary fork of [clap_derive
]; we are
in the process of upstreaming our patches).
A new command-line parsing package, [kommand
], which is similar to
to [paw
], but uses function argument syntax instead of having an options
struct. Command-line arguments can use any type which implements the standard
FromStr
trait, 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's input stream
instead of creating a temporary file.
It refers to how, from the program's perspective, the string names of the inputs and outputs are hidden by the library.
Of course, sometimes you do want to know the name of an input, such as to
display it in an error message. Nameless's [pseudonym
] mechanism provides
names for [InputByteStream
] and other stream types, which allow the name
to be displayed without exposing it to the application.
And sometimes you want to know an input file's extension, to determine what
type of input it is. [InputByteStream
] and other stream types have a
[type_
] function which returns the [media type] (aka MIME type). If the
input is a file, the type is inferred from the extension; if it's an HTTP
stream, the type is inferred from the Content-Type
header, and so on.
Why is it important to hide the name? On a theoretical level, most computations shouldn't care about where data is coming from or where it's going. This helps separate the concerns of what the program primarily does and how the program interacts with the local organization of resources. On a practical level, this is what makes it possible for nameless to transparently support URLs, child processes, and other things. And, it will support applications which are useful on conventional platforms, but which also work on platforms that lack filesystems, such as embedded systems or systems with new kinds of storage abstractions.
Hiding the names 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.
Nameless is actively evolving! Watch this space for much more to come, and [chat with us in Zulip], if you're interested in where we're going.
‘This must be the wood,’ she said thoughtfully to herself, ‘where things have no names.’
— "Through the Looking Glass", by Lewis Carroll