Skip to main content

Crate winnow_args_derive

Crate winnow_args_derive 

Source
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:

  1. read the next item of the command line (a flag, a word, --);
  2. match its name against the struct’s flags, and store the value in a local variable for that field;
  3. give a plain word to the next positional field, in declaration order, unless it names a subcommand, which then parses the rest;
  4. 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 Args for a struct with named fields: the generated loop parses the whole command line.
Occurrence
Derive Occurrence for an enum: one variant per flag or positional, kept in command-line order by an #[arg(sequence)] field of an Args struct.
Subcommand
Derive Subcommand (and Args, so the enum can be the whole command line) for an enum of subcommands.
ValueEnum
Derive FromArg for an enum of unit variants, matched on the value’s bytes; help lists them as possible values.