Expand description
The derives of winnow-args: Args, Subcommand, ValueEnum and Occurrence.
Each is documented with every attribute it accepts. #[winnow_args(...)] is
#[arg(...)] under another name, for a type whose other derives claim arg.
What #[derive(Args)] generates is one loop:
- read the next item of the command line (a flag, a word,
--); matchits name against the struct’s flags, and store the value in a local variable for that field;- give a plain word to the next positional field, in declaration order, unless it names a subcommand, which then parses the rest;
- when the words run out, apply defaults, check the rules, build the struct.
The names are patterns of a match, which rustc compiles: no list of
parsers is walked, whatever the number of flags.
§Documentation
When the environment variable WINNOW_ARGS_SPEC holds the absolute path of
a directory, each derive also writes CRATE/FILE/Type.toml under it,
FILE being the type’s source file: what help knows of the type, with a
flatten or a subcommand as the other type’s path, as it is written. A
binary or an example writes under CRATE-bin, apart from the library of
its package. winnow-args-spec reads them back, for winnow-args-man and
winnow-args-markdown. cargo check is enough, and Cargo compiles the
crate again when the variable changes.
Two types of one name are told apart by their modules, which a fragment
records: those of the source file, then the mod name { } blocks the file
has around the type (the file is read for them). add::Opts is the Opts
of a module add, and a bare Opts what the file’s use lines bring in
under that name, or the one the file declares. Where that
does not say which, winnow-args-spec asks for a name:
#[arg(spec = "AddOpts")] on the type files it under that name, and the
same on a field or a variant that holds the type finds it there. Two types
of one name in one file need it, and the build with the variable set
says so. It also fails where the path a field writes does not lead to its
type (an alias, a module under another name, a spec not repeated), so a
page never describes another type.
Set the variable for the documentation build alone, not in a shell: a test or a doctest would write its types beside the program’s. rust-analyzer’s macro server writes nothing.
A value’s choices are found under the name of its type. Where that name is
an alias, or the type implements FromArg by hand, the build with the
variable set fails at the field until spec = "Name" or choices(...)
states them there, and fails again if the choices stated are not what the
type accepts.
Derive Macros§
- Args
- Derive
Argsfor a struct with named fields: the generated loop parses the whole command line. - Occurrence
- Derive
Occurrencefor an enum: one variant per flag or positional, kept in command-line order by an#[arg(sequence)]field of anArgsstruct. - Subcommand
- Derive
Subcommand(andArgs, so the enum can be the whole command line) for an enum of subcommands. - Value
Enum - Derive
FromArgfor an enum of unit variants, matched on the value’s bytes; help lists them as possible values.