Expand description
A zero-allocation argv parser for usage specs.
This crate implements the binding rules of the argv grammar: which token becomes which flag or argument, when a word selects a subcommand, and what is an error. It does so without building a command tree, without allocating, and in one pass.
It is the runtime half of a compiled parser. The tables it reads are meant to
be emitted by a derive macro as static data, so that starting a parse costs
nothing at all: there is no construction step to pay for, only the walk over
argv.
§Shape of the API
Parsing yields Events rather than a map. A map would have to allocate,
and would then have to be read back out again — whereas generated code can
assign an event straight into a struct field. This is the same reason serde
deserializes into your type instead of into a Value.
use usage_argv::{Arg, Command, Event, Flag, Parser};
static FORCE: Flag = Flag { key: 0, longs: &["force"], shorts: b"f", ..Flag::BOOL };
static FILE: Arg = Arg { key: 1, ..Arg::REQUIRED };
static ROOT: Command = Command {
name: "ex",
flags: &[&FORCE],
args: &[&FILE],
..Command::EMPTY
};
let argv = ["--force", "a.txt"].map(std::ffi::OsStr::new);
let mut parser = Parser::new(&ROOT, &argv);
let mut force = false;
let mut file = None;
while let Some(event) = parser.next_event() {
match event.expect("valid command line") {
Event::Flag { flag, .. } if flag.key == 0 => force = true,
Event::Arg { value, .. } => file = Some(value),
_ => {}
}
}
assert!(force);
assert_eq!(file, Some(&b"a.txt"[..]));§Values are bytes
An Event carries &[u8], borrowed from argv. Converting to &str is
the caller’s step (as_str), and it is the right place for the only
failure a value can have: a command line that is not valid UTF-8 still
parses — flags match, subcommands route — and only the values that are
actually looked at can fail to convert.
Slicing an OsStr into &str pieces safely is not possible without
allocating or unsafe. Bytes are what is left, and they turn out to be the
honest interface anyway.
The reverse conversion is os_string_from_bytes, which lets a PathBuf
field hold a filename that is not UTF-8 rather than a mangled copy of one. On
Unix that is lossless and safe; on Windows, where WTF-8 makes it partial, a
value that will not convert is reported. Either way this crate contains no
unsafe, which a conversion that guessed would have cost.
§What this crate does not do
Only binding. Required-ness, choices, env fallback, defaults, var_min
and var_max are all decided after the last token is read, and they need to
know a value’s type, so they belong to the layer that owns the target struct.
Keeping them out is what makes this loop small.
§Features
spec— a parallel tree of cold metadata (help text, choices, defaults, effects) and a writer that emits it as a usage spec. Off by default: a successful parse never reads any of it, so a CLI that only wants a parser should not compile it.complete— answering a partial command line ([complete]), the shell scripts that ask ([script]), and putting one of those scripts where its shell will look for it ([install]). Installing ships with the scripts rather than behind a gate of its own: a script a CLI still has to tell its users to redirect by hand is the unfinished half of shipping one.
Re-exports§
pub use run::Run;pub use run::RunAsync;pub use run::RunAsyncWith;pub use run::RunWith;
Modules§
- run
- Dispatch: handing a parsed command to the code that carries it out.
Macros§
Structs§
- Arg
- A positional argument.
- Binding
Type - Resolved identity of a derive-generated binding type.
- Clause
- A separator-delimited positional group.
- Command
- A command: its flags, its positional arguments, and its subcommands.
- Flag
- A flag, addressed by any of its long or short forms.
- Invalid
Value - Why a value would not convert into the type its field holds.
- Parser
- A single-pass parse over
argv. - Validation
Error - A command-wide validation or finalization failure.
Enums§
- ArgAction
- What supplying a declared flag does.
- Double
Dash - How an argument relates to the
--separator. - Error
- A binding failure.
- Event
- Something the parser bound.
- Unknown
Flags - What to do with a flag-like token that names no flag in scope.
- Value
Hint - A value’s shell-native completion class for
#[usage(value_hint = ...)].
Constants§
- HELP_
LONG_ KEY - The key
--helpanswers to, and the one-hdoes. - HELP_
SHORT_ KEY - See
HELP_LONG_KEY. - MAX_
DEPTH - How deep a command tree this parser will descend.
- SPEC_
REQUEST - The word a tool sends to ask a binary for its own spec.
- VERSION_
LONG_ KEY - See
HELP_LONG_KEY. - VERSION_
SHORT_ KEY - See
HELP_LONG_KEY.
Statics§
- HELP_
LONG --help, which every command answers to.- HELP_
SHORT -h, which prints the shorter form.- VERSION_
LONG --version, where the CLI declared one.- VERSION_
SHORT -V, which clap also supplies.
Functions§
- as_str
- Interpret a value as UTF-8.
- assert_
unique_ subcommand_ names - Refuse two subcommands that answer to the same name, aliases included.
- concat_
args - Join groups of argument tables into one, at compile time.
- concat_
flags - Join groups of flag tables into one, at compile time.
- find_
subcommand - Resolve a subcommand by name or alias, at compile time.
- invalid_
choice_ value - One
Error::InvalidValuefor a word that is not one of a value enum’s choices. - invalid_
os_ value - One
Error::InvalidValuefor bytes the platform cannot hold in a path. - invalid_
parsed_ value - One
Error::InvalidValuefor a value whose type would not build from it. - invalid_
utf8_ value - One
Error::InvalidValuefor a word that was not UTF-8. - is_
help_ flag - Whether a flag is one of the two the parser supplies rather than the CLI declaring it.
- is_
spec_ request - Whether this argv asks for the spec rather than for the CLI to run.
- is_
version_ arg - Whether one exact root argument selects a declared or synthesized version action.
- is_
version_ flag - Whether a flag is one of the two the parser supplies for
--version. - key_
base - The high half of every key one declaration’s items get.
- multicall_
applet - The applet name to parse as the first word, when argv[0] is not the dispatcher.
- multicall_
basename - Basename of argv[0] for a multicall CLI: last path component, with a trailing
.exestripped so Windows and Unix agree. - os_
string_ from_ bytes - Rebuild an
OsStringfrom bytes the parser handed back. - os_
values - Convert every repeated value of one path-like field, reporting
namefor the first the platform cannot hold. - parsed_
values - Convert every repeated value of one field through
FromStr, reportingnamefor the first that fails. - table_
len - How many entries a group of tables holds in total.
- utf8_
values - Convert every repeated value of one text field, reporting
namefor the first that is not UTF-8.