Struct clap::ArgGroup

source ·
pub struct ArgGroup { /* private fields */ }
Expand description

Family of related arguments.

By placing arguments in a logical group, you can create easier requirement and exclusion rules instead of having to list each argument individually, or when you want a rule to apply “any but not all” arguments.

For instance, you can make an entire ArgGroup required. If ArgGroup::multiple(true) is set, this means that at least one argument from that group must be present. If ArgGroup::multiple(false) is set (the default), one and only one must be present.

You can also do things such as name an entire ArgGroup as a conflict or requirement for another argument, meaning any of the arguments that belong to that group will cause a failure if present, or must be present respectively.

Perhaps the most common use of ArgGroups is to require one and only one argument to be present out of a given set. Imagine that you had multiple arguments, and you want one of them to be required, but making all of them required isn’t feasible because perhaps they conflict with each other. For example, lets say that you were building an application where one could set a given version number by supplying a string with an option argument, i.e. --set-ver v1.2.3, you also wanted to support automatically using a previous version number and simply incrementing one of the three numbers. So you create three flags --major, --minor, and --patch. All of these arguments shouldn’t be used at one time but you want to specify that at least one of them is used. For this, you can create a group.

Finally, you may use ArgGroups to pull a value from a group of arguments when you don’t care exactly which argument was actually used at runtime.

Examples

The following example demonstrates using an ArgGroup to ensure that one, and only one, of the arguments from the specified group is present at runtime.

let result = Command::new("cmd")
    .arg(arg!(--"set-ver" <ver> "set the version manually"))
    .arg(arg!(--major           "auto increase major"))
    .arg(arg!(--minor           "auto increase minor"))
    .arg(arg!(--patch           "auto increase patch"))
    .group(ArgGroup::new("vers")
         .args(["set-ver", "major", "minor", "patch"])
         .required(true))
    .try_get_matches_from(vec!["cmd", "--major", "--patch"]);
// Because we used two args in the group it's an error
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);

This next example shows a passing parse of the same scenario

let result = Command::new("cmd")
    .arg(arg!(--"set-ver" <ver> "set the version manually"))
    .arg(arg!(--major           "auto increase major"))
    .arg(arg!(--minor           "auto increase minor"))
    .arg(arg!(--patch           "auto increase patch"))
    .group(ArgGroup::new("vers")
         .args(["set-ver", "major", "minor","patch"])
         .required(true))
    .try_get_matches_from(vec!["cmd", "--major"]);
assert!(result.is_ok());
let matches = result.unwrap();
// We may not know which of the args was used, so we can test for the group...
assert!(matches.contains_id("vers"));
// We can also ask the group which arg was used
assert_eq!(matches
    .get_one::<Id>("vers")
    .expect("`vers` is required")
    .as_str(),
    "major"
);
// we could also alternatively check each arg individually (not shown here)

Implementations§

Create a ArgGroup using a unique name.

The name will be used to get values from the group or refer to the group inside of conflict and requirement rules.

Examples
ArgGroup::new("config")
Examples found in repository?
src/builder/command.rs (line 3869)
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
    pub(crate) fn _build_self(&mut self, expand_help_tree: bool) {
        debug!("Command::_build: name={:?}", self.get_name());
        if !self.settings.is_set(AppSettings::Built) {
            // Make sure all the globally set flags apply to us as well
            self.settings = self.settings | self.g_settings;

            if self.is_multicall_set() {
                self.settings.insert(AppSettings::SubcommandRequired.into());
                self.settings.insert(AppSettings::DisableHelpFlag.into());
                self.settings.insert(AppSettings::DisableVersionFlag.into());
            }
            if !cfg!(feature = "help") && self.get_override_help().is_none() {
                self.settings.insert(AppSettings::DisableHelpFlag.into());
                self.settings
                    .insert(AppSettings::DisableHelpSubcommand.into());
            }
            if self.is_set(AppSettings::ArgsNegateSubcommands) {
                self.settings
                    .insert(AppSettings::SubcommandsNegateReqs.into());
            }
            if self.external_value_parser.is_some() {
                self.settings
                    .insert(AppSettings::AllowExternalSubcommands.into());
            }
            if !self.has_subcommands() {
                self.settings
                    .insert(AppSettings::DisableHelpSubcommand.into());
            }

            self._propagate();
            self._check_help_and_version(expand_help_tree);
            self._propagate_global_args();

            let mut pos_counter = 1;
            let hide_pv = self.is_set(AppSettings::HidePossibleValues);
            for a in self.args.args_mut() {
                // Fill in the groups
                for g in &a.groups {
                    if let Some(ag) = self.groups.iter_mut().find(|grp| grp.id == *g) {
                        ag.args.push(a.get_id().clone());
                    } else {
                        let mut ag = ArgGroup::new(g);
                        ag.args.push(a.get_id().clone());
                        self.groups.push(ag);
                    }
                }

                // Figure out implied settings
                a._build();
                if hide_pv && a.is_takes_value_set() {
                    a.settings.set(ArgSettings::HidePossibleValues);
                }
                if a.is_positional() && a.index.is_none() {
                    a.index = Some(pos_counter);
                    pos_counter += 1;
                }
            }

            self.args._build();

            #[allow(deprecated)]
            {
                let highest_idx = self
                    .get_keymap()
                    .keys()
                    .filter_map(|x| {
                        if let crate::mkeymap::KeyType::Position(n) = x {
                            Some(*n)
                        } else {
                            None
                        }
                    })
                    .max()
                    .unwrap_or(0);
                let is_trailing_var_arg_set = self.is_trailing_var_arg_set();
                let is_allow_hyphen_values_set = self.is_allow_hyphen_values_set();
                let is_allow_negative_numbers_set = self.is_allow_negative_numbers_set();
                for arg in self.args.args_mut() {
                    if is_allow_hyphen_values_set && arg.is_takes_value_set() {
                        arg.settings.insert(ArgSettings::AllowHyphenValues.into());
                    }
                    if is_allow_negative_numbers_set && arg.is_takes_value_set() {
                        arg.settings
                            .insert(ArgSettings::AllowNegativeNumbers.into());
                    }
                    if is_trailing_var_arg_set && arg.get_index() == Some(highest_idx) {
                        arg.settings.insert(ArgSettings::TrailingVarArg.into());
                    }
                }
            }

            #[cfg(debug_assertions)]
            assert_app(self);
            self.settings.set(AppSettings::Built);
        } else {
            debug!("Command::_build: already built");
        }
    }

Sets the group name.

Examples
ArgGroup::default().id("config")
Examples found in repository?
src/builder/arg_group.rs (line 110)
109
110
111
    pub fn new(id: impl Into<Id>) -> Self {
        ArgGroup::default().id(id)
    }

Adds an argument to this group by name

Examples
let m = Command::new("myprog")
    .arg(Arg::new("flag")
        .short('f')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("color")
        .short('c')
        .action(ArgAction::SetTrue))
    .group(ArgGroup::new("req_flags")
        .arg("flag")
        .arg("color"))
    .get_matches_from(vec!["myprog", "-f"]);
// maybe we don't know which of the two flags was used...
assert!(m.contains_id("req_flags"));
// but we can also check individually if needed
assert!(m.contains_id("flag"));
Examples found in repository?
src/builder/arg_group.rs (line 186)
184
185
186
187
188
189
    pub fn args(mut self, ns: impl IntoIterator<Item = impl Into<Id>>) -> Self {
        for n in ns {
            self = self.arg(n);
        }
        self
    }

Adds multiple arguments to this group by name

Examples
let m = Command::new("myprog")
    .arg(Arg::new("flag")
        .short('f')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("color")
        .short('c')
        .action(ArgAction::SetTrue))
    .group(ArgGroup::new("req_flags")
        .args(["flag", "color"]))
    .get_matches_from(vec!["myprog", "-f"]);
// maybe we don't know which of the two flags was used...
assert!(m.contains_id("req_flags"));
// but we can also check individually if needed
assert!(m.contains_id("flag"));

Getters for all args. It will return a vector of Id

Example
let args: Vec<&str> = vec!["a1".into(), "a4".into()];
let grp = ArgGroup::new("program").args(&args);

for (pos, arg) in grp.get_args().enumerate() {
    assert_eq!(*arg, args[pos]);
}

Allows more than one of the Args in this group to be used. (Default: false)

Examples

Notice in this example we use both the -f and -c flags which are both part of the group

let m = Command::new("myprog")
    .arg(Arg::new("flag")
        .short('f')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("color")
        .short('c')
        .action(ArgAction::SetTrue))
    .group(ArgGroup::new("req_flags")
        .args(["flag", "color"])
        .multiple(true))
    .get_matches_from(vec!["myprog", "-f", "-c"]);
// maybe we don't know which of the two flags was used...
assert!(m.contains_id("req_flags"));

In this next example, we show the default behavior (i.e. `multiple(false)) which will throw an error if more than one of the args in the group was used.

let result = Command::new("myprog")
    .arg(Arg::new("flag")
        .short('f')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("color")
        .short('c')
        .action(ArgAction::SetTrue))
    .group(ArgGroup::new("req_flags")
        .args(["flag", "color"]))
    .try_get_matches_from(vec!["myprog", "-f", "-c"]);
// Because we used both args in the group it's an error
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);

Return true if the group allows more than one of the arguments in this group to be used. (Default: false)

Example
let mut group = ArgGroup::new("myprog")
    .args(["f", "c"])
    .multiple(true);

assert!(group.is_multiple());

Require an argument from the group to be present when parsing.

This is unless conflicting with another argument. A required group will be displayed in the usage string of the application in the format <arg|arg2|arg3>.

NOTE: This setting only applies to the current Command / Subcommands, and not globally.

NOTE: By default, ArgGroup::multiple is set to false which when combined with ArgGroup::required(true) states, “One and only one arg must be used from this group. Use of more than one arg is an error.” Vice setting ArgGroup::multiple(true) which states, ’At least one arg from this group must be used. Using multiple is OK.“

Examples
let result = Command::new("myprog")
    .arg(Arg::new("flag")
        .short('f')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("color")
        .short('c')
        .action(ArgAction::SetTrue))
    .group(ArgGroup::new("req_flags")
        .args(["flag", "color"])
        .required(true))
    .try_get_matches_from(vec!["myprog"]);
// Because we didn't use any of the args in the group, it's an error
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);

Specify an argument or group that must be present when this group is.

This is not to be confused with a required group. Requirement rules function just like argument requirement rules, you can name other arguments or groups that must be present when any one of the arguments from this group is used.

NOTE: The name provided may be an argument or group name

Examples
let result = Command::new("myprog")
    .arg(Arg::new("flag")
        .short('f')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("color")
        .short('c')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("debug")
        .short('d')
        .action(ArgAction::SetTrue))
    .group(ArgGroup::new("req_flags")
        .args(["flag", "color"])
        .requires("debug"))
    .try_get_matches_from(vec!["myprog", "-c"]);
// because we used an arg from the group, and the group requires "-d" to be used, it's an
// error
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
Examples found in repository?
src/builder/arg_group.rs (line 405)
403
404
405
406
407
408
    pub fn requires_all(mut self, ns: impl IntoIterator<Item = impl Into<Id>>) -> Self {
        for n in ns {
            self = self.requires(n);
        }
        self
    }

Specify arguments or groups that must be present when this group is.

This is not to be confused with a required group. Requirement rules function just like argument requirement rules, you can name other arguments or groups that must be present when one of the arguments from this group is used.

NOTE: The names provided may be an argument or group name

Examples
let result = Command::new("myprog")
    .arg(Arg::new("flag")
        .short('f')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("color")
        .short('c')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("debug")
        .short('d')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("verb")
        .short('v')
        .action(ArgAction::SetTrue))
    .group(ArgGroup::new("req_flags")
        .args(["flag", "color"])
        .requires_all(["debug", "verb"]))
    .try_get_matches_from(vec!["myprog", "-c", "-d"]);
// because we used an arg from the group, and the group requires "-d" and "-v" to be used,
// yet we only used "-d" it's an error
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);

Specify an argument or group that must not be present when this group is.

Exclusion (aka conflict) rules function just like argument exclusion rules, you can name other arguments or groups that must not be present when one of the arguments from this group are used.

NOTE: The name provided may be an argument, or group name

Examples
let result = Command::new("myprog")
    .arg(Arg::new("flag")
        .short('f')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("color")
        .short('c')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("debug")
        .short('d')
        .action(ArgAction::SetTrue))
    .group(ArgGroup::new("req_flags")
        .args(["flag", "color"])
        .conflicts_with("debug"))
    .try_get_matches_from(vec!["myprog", "-c", "-d"]);
// because we used an arg from the group, and the group conflicts with "-d", it's an error
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
Examples found in repository?
src/builder/arg_group.rs (line 491)
489
490
491
492
493
494
    pub fn conflicts_with_all(mut self, ns: impl IntoIterator<Item = impl Into<Id>>) -> Self {
        for n in ns {
            self = self.conflicts_with(n);
        }
        self
    }

Specify arguments or groups that must not be present when this group is.

Exclusion rules function just like argument exclusion rules, you can name other arguments or groups that must not be present when one of the arguments from this group are used.

NOTE: The names provided may be an argument, or group name

Examples
let result = Command::new("myprog")
    .arg(Arg::new("flag")
        .short('f')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("color")
        .short('c')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("debug")
        .short('d')
        .action(ArgAction::SetTrue))
    .arg(Arg::new("verb")
        .short('v')
        .action(ArgAction::SetTrue))
    .group(ArgGroup::new("req_flags")
        .args(["flag", "color"])
        .conflicts_with_all(["debug", "verb"]))
    .try_get_matches_from(vec!["myprog", "-c", "-v"]);
// because we used an arg from the group, and the group conflicts with either "-v" or "-d"
// it's an error
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);

Get the name of the group

Examples found in repository?
src/parser/arg_matcher.rs (line 29)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    pub(crate) fn new(_cmd: &Command) -> Self {
        ArgMatcher {
            matches: ArgMatches {
                #[cfg(debug_assertions)]
                valid_args: {
                    let args = _cmd.get_arguments().map(|a| a.get_id().clone());
                    let groups = _cmd.get_groups().map(|g| g.get_id().clone());
                    args.chain(groups).collect()
                },
                #[cfg(debug_assertions)]
                valid_subcommands: _cmd
                    .get_subcommands()
                    .map(|sc| sc.get_name_str().clone())
                    .collect(),
                ..Default::default()
            },
            pending: None,
        }
    }
More examples
Hide additional examples
src/parser/validator.rs (line 301)
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
    fn validate_required(
        &mut self,
        matcher: &ArgMatcher,
        conflicts: &mut Conflicts,
    ) -> ClapResult<()> {
        debug!("Validator::validate_required: required={:?}", self.required);
        self.gather_requires(matcher);

        let mut missing_required = Vec::new();
        let mut highest_index = 0;

        let is_exclusive_present = matcher
            .arg_ids()
            .filter(|arg_id| matcher.check_explicit(arg_id, &ArgPredicate::IsPresent))
            .any(|id| {
                self.cmd
                    .find(id)
                    .map(|arg| arg.is_exclusive_set())
                    .unwrap_or_default()
            });
        debug!(
            "Validator::validate_required: is_exclusive_present={}",
            is_exclusive_present
        );

        for arg_or_group in self
            .required
            .iter()
            .filter(|r| !matcher.check_explicit(r, &ArgPredicate::IsPresent))
        {
            debug!("Validator::validate_required:iter:aog={:?}", arg_or_group);
            if let Some(arg) = self.cmd.find(arg_or_group) {
                debug!("Validator::validate_required:iter: This is an arg");
                if !is_exclusive_present && !self.is_missing_required_ok(arg, matcher, conflicts) {
                    debug!(
                        "Validator::validate_required:iter: Missing {:?}",
                        arg.get_id()
                    );
                    missing_required.push(arg.get_id().clone());
                    if !arg.is_last_set() {
                        highest_index = highest_index.max(arg.get_index().unwrap_or(0));
                    }
                }
            } else if let Some(group) = self.cmd.find_group(arg_or_group) {
                debug!("Validator::validate_required:iter: This is a group");
                if !self
                    .cmd
                    .unroll_args_in_group(&group.id)
                    .iter()
                    .any(|a| matcher.check_explicit(a, &ArgPredicate::IsPresent))
                {
                    debug!(
                        "Validator::validate_required:iter: Missing {:?}",
                        group.get_id()
                    );
                    missing_required.push(group.get_id().clone());
                }
            }
        }

        // Validate the conditionally required args
        for a in self
            .cmd
            .get_arguments()
            .filter(|a| !matcher.check_explicit(a.get_id(), &ArgPredicate::IsPresent))
        {
            let mut required = false;

            for (other, val) in &a.r_ifs {
                if matcher.check_explicit(other, &ArgPredicate::Equals(val.into())) {
                    debug!(
                        "Validator::validate_required:iter: Missing {:?}",
                        a.get_id()
                    );
                    required = true;
                }
            }

            let match_all = a.r_ifs_all.iter().all(|(other, val)| {
                matcher.check_explicit(other, &ArgPredicate::Equals(val.into()))
            });
            if match_all && !a.r_ifs_all.is_empty() {
                debug!(
                    "Validator::validate_required:iter: Missing {:?}",
                    a.get_id()
                );
                required = true;
            }

            if (!a.r_unless.is_empty() || !a.r_unless_all.is_empty())
                && self.fails_arg_required_unless(a, matcher)
            {
                debug!(
                    "Validator::validate_required:iter: Missing {:?}",
                    a.get_id()
                );
                required = true;
            }

            if required {
                missing_required.push(a.get_id().clone());
                if !a.is_last_set() {
                    highest_index = highest_index.max(a.get_index().unwrap_or(0));
                }
            }
        }

        // For display purposes, include all of the preceding positional arguments
        if !self.cmd.is_allow_missing_positional_set() {
            for pos in self
                .cmd
                .get_positionals()
                .filter(|a| !matcher.check_explicit(a.get_id(), &ArgPredicate::IsPresent))
            {
                if pos.get_index() < Some(highest_index) {
                    debug!(
                        "Validator::validate_required:iter: Missing {:?}",
                        pos.get_id()
                    );
                    missing_required.push(pos.get_id().clone());
                }
            }
        }

        if !missing_required.is_empty() {
            ok!(self.missing_required_error(matcher, missing_required));
        }

        Ok(())
    }
src/builder/debug_asserts.rs (line 294)
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
pub(crate) fn assert_app(cmd: &Command) {
    debug!("Command::_debug_asserts");

    let mut short_flags = vec![];
    let mut long_flags = vec![];

    // Invalid version flag settings
    if cmd.get_version().is_none() && cmd.get_long_version().is_none() {
        // PropagateVersion is meaningless if there is no version
        assert!(
            !cmd.is_propagate_version_set(),
            "Command {}: No version information via Command::version or Command::long_version to propagate",
            cmd.get_name(),
        );

        // Used `Command::mut_arg("version", ..) but did not provide any version information to display
        let version_needed = cmd
            .get_arguments()
            .filter(|x| matches!(x.get_action(), ArgAction::Version))
            .map(|x| x.get_id())
            .collect::<Vec<_>>();

        assert_eq!(version_needed, Vec::<&str>::new(), "Command {}: `ArgAction::Version` used without providing Command::version or Command::long_version"
            ,cmd.get_name()
        );
    }

    for sc in cmd.get_subcommands() {
        if let Some(s) = sc.get_short_flag().as_ref() {
            short_flags.push(Flag::Command(format!("-{}", s), sc.get_name()));
        }

        for short_alias in sc.get_all_short_flag_aliases() {
            short_flags.push(Flag::Command(format!("-{}", short_alias), sc.get_name()));
        }

        if let Some(l) = sc.get_long_flag().as_ref() {
            assert!(!l.starts_with('-'), "Command {}: long_flag {:?} must not start with a `-`, that will be handled by the parser", sc.get_name(), l);
            long_flags.push(Flag::Command(format!("--{}", l), sc.get_name()));
        }

        for long_alias in sc.get_all_long_flag_aliases() {
            long_flags.push(Flag::Command(format!("--{}", long_alias), sc.get_name()));
        }
    }

    for arg in cmd.get_arguments() {
        assert_arg(arg);

        assert!(
            !cmd.is_multicall_set(),
            "Command {}: Arguments like {} cannot be set on a multicall command",
            cmd.get_name(),
            arg.get_id()
        );

        if let Some(s) = arg.get_short() {
            short_flags.push(Flag::Arg(format!("-{}", s), arg.get_id().as_str()));
        }

        for (short_alias, _) in &arg.short_aliases {
            short_flags.push(Flag::Arg(
                format!("-{}", short_alias),
                arg.get_id().as_str(),
            ));
        }

        if let Some(l) = arg.get_long() {
            assert!(!l.starts_with('-'), "Argument {}: long {:?} must not start with a `-`, that will be handled by the parser", arg.get_id(), l);
            long_flags.push(Flag::Arg(format!("--{}", l), arg.get_id().as_str()));
        }

        for (long_alias, _) in &arg.aliases {
            long_flags.push(Flag::Arg(
                format!("--{}", long_alias),
                arg.get_id().as_str(),
            ));
        }

        // Name conflicts
        if let Some((first, second)) = cmd.two_args_of(|x| x.get_id() == arg.get_id()) {
            panic!(
            "Command {}: Argument names must be unique, but '{}' is in use by more than one argument or group{}",
            cmd.get_name(),
            arg.get_id(),
            duplicate_tip(cmd, first, second),
        );
        }

        // Long conflicts
        if let Some(l) = arg.get_long() {
            if let Some((first, second)) = cmd.two_args_of(|x| x.get_long() == Some(l)) {
                panic!(
                    "Command {}: Long option names must be unique for each argument, \
                            but '--{}' is in use by both '{}' and '{}'{}",
                    cmd.get_name(),
                    l,
                    first.get_id(),
                    second.get_id(),
                    duplicate_tip(cmd, first, second)
                )
            }
        }

        // Short conflicts
        if let Some(s) = arg.get_short() {
            if let Some((first, second)) = cmd.two_args_of(|x| x.get_short() == Some(s)) {
                panic!(
                    "Command {}: Short option names must be unique for each argument, \
                            but '-{}' is in use by both '{}' and '{}'{}",
                    cmd.get_name(),
                    s,
                    first.get_id(),
                    second.get_id(),
                    duplicate_tip(cmd, first, second),
                )
            }
        }

        // Index conflicts
        if let Some(idx) = arg.index {
            if let Some((first, second)) =
                cmd.two_args_of(|x| x.is_positional() && x.get_index() == Some(idx))
            {
                panic!(
                    "Command {}: Argument '{}' has the same index as '{}' \
                    and they are both positional arguments\n\n\t \
                    Use `Arg::num_args(1..)` to allow one \
                    positional argument to take multiple values",
                    cmd.get_name(),
                    first.get_id(),
                    second.get_id()
                )
            }
        }

        // requires, r_if, r_unless
        for req in &arg.requires {
            assert!(
                cmd.id_exists(&req.1),
                "Command {}: Argument or group '{}' specified in 'requires*' for '{}' does not exist",
                cmd.get_name(),
                req.1,
                arg.get_id(),
            );
        }

        for req in &arg.r_ifs {
            assert!(
                !arg.is_required_set(),
                "Argument {}: `required` conflicts with `required_if_eq*`",
                arg.get_id()
            );
            assert!(
                cmd.id_exists(&req.0),
                "Command {}: Argument or group '{}' specified in 'required_if_eq*' for '{}' does not exist",
                    cmd.get_name(),
                req.0,
                arg.get_id()
            );
        }

        for req in &arg.r_ifs_all {
            assert!(
                !arg.is_required_set(),
                "Argument {}: `required` conflicts with `required_if_eq_all`",
                arg.get_id()
            );
            assert!(
                cmd.id_exists(&req.0),
                "Command {}: Argument or group '{}' specified in 'required_if_eq_all' for '{}' does not exist",
                    cmd.get_name(),
                req.0,
                arg.get_id()
            );
        }

        for req in &arg.r_unless {
            assert!(
                !arg.is_required_set(),
                "Argument {}: `required` conflicts with `required_unless*`",
                arg.get_id()
            );
            assert!(
                cmd.id_exists(req),
                "Command {}: Argument or group '{}' specified in 'required_unless*' for '{}' does not exist",
                    cmd.get_name(),
                req,
                arg.get_id(),
            );
        }

        for req in &arg.r_unless_all {
            assert!(
                !arg.is_required_set(),
                "Argument {}: `required` conflicts with `required_unless*`",
                arg.get_id()
            );
            assert!(
                cmd.id_exists(req),
                "Command {}: Argument or group '{}' specified in 'required_unless*' for '{}' does not exist",
                    cmd.get_name(),
                req,
                arg.get_id(),
            );
        }

        // blacklist
        for req in &arg.blacklist {
            assert!(
                cmd.id_exists(req),
                "Command {}: Argument or group '{}' specified in 'conflicts_with*' for '{}' does not exist",
                    cmd.get_name(),
                req,
                arg.get_id(),
            );
        }

        // overrides
        for req in &arg.overrides {
            assert!(
                cmd.id_exists(req),
                "Command {}: Argument or group '{}' specified in 'overrides_with*' for '{}' does not exist",
                    cmd.get_name(),
                req,
                arg.get_id(),
            );
        }

        if arg.is_last_set() {
            assert!(
                arg.get_long().is_none(),
                "Command {}: Flags or Options cannot have last(true) set. '{}' has both a long and last(true) set.",
                    cmd.get_name(),
                arg.get_id()
            );
            assert!(
                arg.get_short().is_none(),
                "Command {}: Flags or Options cannot have last(true) set. '{}' has both a short and last(true) set.",
                    cmd.get_name(),
                arg.get_id()
            );
        }

        assert!(
            !(arg.is_required_set() && arg.is_global_set()),
            "Command {}: Global arguments cannot be required.\n\n\t'{}' is marked as both global and required",
                    cmd.get_name(),
            arg.get_id()
        );

        if arg.get_value_hint() == ValueHint::CommandWithArguments {
            assert!(
                arg.is_positional(),
                "Command {}: Argument '{}' has hint CommandWithArguments and must be positional.",
                cmd.get_name(),
                arg.get_id()
            );

            assert!(
                arg.is_trailing_var_arg_set() || arg.is_last_set(),
                "Command {}: Positional argument '{}' has hint CommandWithArguments, so Command must have `trailing_var_arg(true)` or `last(true)` set.",
                    cmd.get_name(),
                arg.get_id()
            );
        }
    }

    for group in cmd.get_groups() {
        let derive_hint = if cfg!(feature = "derive") {
            " (note: `Args` implicitly creates `ArgGroup`s; disable with `#[group(skip)]`"
        } else {
            ""
        };

        // Name conflicts
        assert!(
            cmd.get_groups().filter(|x| x.id == group.id).count() < 2,
            "Command {}: Argument group name must be unique\n\n\t'{}' is already in use{}",
            cmd.get_name(),
            group.get_id(),
            derive_hint
        );

        // Groups should not have naming conflicts with Args
        assert!(
            !cmd.get_arguments().any(|x| x.get_id() == group.get_id()),
            "Command {}: Argument group name '{}' must not conflict with argument name{}",
            cmd.get_name(),
            group.get_id(),
            derive_hint
        );

        for arg in &group.args {
            // Args listed inside groups should exist
            assert!(
                cmd.get_arguments().any(|x| x.get_id() == arg),
                "Command {}: Argument group '{}' contains non-existent argument '{}'",
                cmd.get_name(),
                group.get_id(),
                arg
            );
        }
    }

    // Conflicts between flags and subcommands

    long_flags.sort_unstable();
    short_flags.sort_unstable();

    detect_duplicate_flags(&long_flags, "long");
    detect_duplicate_flags(&short_flags, "short");

    let mut subs = FlatSet::new();
    for sc in cmd.get_subcommands() {
        assert!(
            subs.insert(sc.get_name()),
            "Command {}: command name `{}` is duplicated",
            cmd.get_name(),
            sc.get_name()
        );
        for alias in sc.get_all_aliases() {
            assert!(
                subs.insert(alias),
                "Command {}: command `{}` alias `{}` is duplicated",
                cmd.get_name(),
                sc.get_name(),
                alias
            );
        }
    }

    _verify_positionals(cmd);

    #[cfg(feature = "help")]
    if let Some(help_template) = cmd.get_help_template() {
        assert!(
            !help_template.to_string().contains("{flags}"),
            "Command {}: {}",
                    cmd.get_name(),
            "`{flags}` template variable was removed in clap3, they are now included in `{options}`",
        );
        assert!(
            !help_template.to_string().contains("{unified}"),
            "Command {}: {}",
            cmd.get_name(),
            "`{unified}` template variable was removed in clap3, use `{options}` instead"
        );
    }

    cmd._panic_on_missing_help(cmd.is_help_expected_set());
    assert_app_flags(cmd);
}

Reports whether ArgGroup::required is set

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.