Expand description
§Flattened Structs
Like Clap, a field marked #[command(flatten)] takes its arguments from another struct deriving GetArgs. The flattened struct’s options
and positional arguments are parsed as if they were declared in the parent, which makes it easy to share groups of arguments between
programs:
use getargs_derive::GetArgs;
#[derive(Debug, GetArgs)]
struct Verbosity {
/// More output.
#[arg(short, long, action = Count)]
verbose: u8,
/// Less output.
#[arg(short, long, conflicts_with = "verbose")]
quiet: bool,
}
/// Copy files around.
#[derive(Debug, GetArgs)]
#[command(name = "copy")]
struct Cli<'a> {
/// Input file.
input: &'a str,
#[command(flatten)]
verbosity: Verbosity,
}
let cli = Cli::from_args(["-vv", "notes.txt"].into_iter()).unwrap();
assert_eq!(cli.input, "notes.txt");
assert_eq!(cli.verbosity.verbose, 2);
assert_eq!(
Cli::HELP,
"\
Copy files around
Usage: copy [OPTIONS] <INPUT>
Arguments:
<INPUT> Input file
Options:
-v, --verbose... More output
-q, --quiet Less output
-h, --help Print help"
);Flattened structs can themselves flatten other structs, and may borrow from the command line (Network<'a>) like any other struct.
§Behaviour
- Options of a flattened struct are accepted anywhere on the command line, like the parent’s own options.
- Positional arguments are filled in field order, as in Clap: the positional arguments of a flattened struct take the place of the
#[command(flatten)]field among the parent’s positional fields. A struct with the fieldssource(flattened, one positional),mode(positional) andtarget(flattened, one positional) fillssource, thenmode, thentarget. - Defaults, required arguments and relations of a flattened struct are handled by that struct. Relations cannot cross struct
boundaries:
conflicts_with,requires,required_unless_presentandgrouponly reference fields of the struct declaring them, and a flattened field is not an argument that relations can reference. - Attributes of the fields of a flattened struct keep their meaning: aliases, value validation,
value enums, environment variables and parsing modes work as if the fields were
declared in the parent, and the parent’s
#[command(allow_negative_numbers)]also applies to them. - Help: the parent’s
HELPandLONG_HELPlist the arguments of flattened structs in field order, within the parent’s sections and aligned with the parent’s own arguments, exactly as if they were declared in the parent:hide,help_heading,display_order,long_helpand multi-paragraph doc comments of flattened fields apply,display_ordercounts positions in the merged field list, and the parent’smax_term_widthwraps them.HELPandLONG_HELPremain&'static strconstants computed at compile time. - Environment variables: a struct that flattens other structs also gets
parse_with_envandfrom_args_with_env, since its flattened structs may read environment variables. Itsparseandfrom_argsread the process environment for them, which needs thestdfeature of this crate: without it, usingparseorfrom_argsis a compile error when a flattened struct hasenvfields. lastpositionals: alastpositional must be the final positional argument, flattened structs included. A parent’slastpositional receives the arguments given after--, skipping the positionals of flattened structs, as it skips the parent’s own.-h/--helpand-V/--versionare handled by the parent only, according to its own#[command(...)]attributes. The#[command(...)]attributes of a flattened struct (name,about,version,disable_help_flag,group) only apply when that struct is parsed on its own;groupdeclarations still apply to its own fields.- Errors of a flattened struct use the names of its own arguments, e.g.
--port <PORT>. Unknown long options are matched against all long names, flattened ones included, for “did you mean” suggestions.
§Differences From Clap
This is a Clap-inspired subset. Flattening Option<T> fields, field-level #[command(...)] keys other than flatten and subcommand
(such as next_help_heading), #[group] on flattened structs, flattening a struct with a #[command(subcommand)] field, and flattening
in structs with type or const parameters are not supported.
Flattened arguments do not get their own help heading. A short option of the parent is matched before the argument is offered to its
flattened structs, so it takes precedence over a negative number expected by a flattened positional, while within one struct a negative
number takes precedence over a short option with the same name.
§Compile-Time Diagnostics
The macro reports a compile error for:
#[command(flatten)]on anOption<T>field;#[command(flatten)]with a value, an unknown field-level#[command(...)]key,flattenrepeated, orflattencombined withsubcommand;- a flattened struct that has a
#[command(subcommand)]field; #[arg(...)]on a flattened field;- a flattened field whose type does not derive
GetArgs; #[command(flatten)]in a struct with type or const parameters;- a short or long name of a flattened struct that is already used by a field of the parent, by another flattened field, or by the
parent’s generated
-h/--helpor-V/--versionflags; - a required positional argument following an optional one, across flattened structs;
- a
lastpositional argument followed by another positional argument, across flattened structs; parseorfrom_argswithout thestdfeature when a flattened struct hasenvfields.
Name and positional checks across struct boundaries are compile-time constant assertions: they are reported as evaluation panicked
errors pointing at the #[command(flatten)] attribute or at the offending field, and name the conflicting option when it belongs to
the parent. Conflicts between two flattened structs name both fields but not the option.