1 #![allow(deprecated)]
2
3 // Std
4 use std::{
5 borrow::Cow,
6 cmp::{Ord, Ordering},
7 error::Error,
8 ffi::OsStr,
9 fmt::{self, Display, Formatter},
10 str,
11 sync::{Arc, Mutex},
12 };
13 #[cfg(feature = "env")]
14 use std::{env, ffi::OsString};
15
16 #[cfg(feature = "yaml")]
17 use yaml_rust::Yaml;
18
19 // Internal
20 use crate::builder::usage_parser::UsageParser;
21 use crate::builder::ArgPredicate;
22 use crate::util::{Id, Key};
23 use crate::ArgAction;
24 use crate::PossibleValue;
25 use crate::ValueHint;
26 use crate::INTERNAL_ERROR_MSG;
27 use crate::{ArgFlags, ArgSettings};
28
29 #[cfg(feature = "regex")]
30 use crate::builder::RegexRef;
31
32 /// The abstract representation of a command line argument. Used to set all the options and
33 /// relationships that define a valid argument for the program.
34 ///
35 /// There are two methods for constructing [`Arg`]s, using the builder pattern and setting options
36 /// manually, or using a usage string which is far less verbose but has fewer options. You can also
37 /// use a combination of the two methods to achieve the best of both worlds.
38 ///
39 /// - [Basic API][crate::Arg#basic-api]
40 /// - [Value Handling][crate::Arg#value-handling]
41 /// - [Help][crate::Arg#help-1]
42 /// - [Advanced Argument Relations][crate::Arg#advanced-argument-relations]
43 /// - [Reflection][crate::Arg#reflection]
44 ///
45 /// # Examples
46 ///
47 /// ```rust
48 /// # use clap::{Arg, arg};
49 /// // Using the traditional builder pattern and setting each option manually
50 /// let cfg = Arg::new("config")
51 /// .short('c')
52 /// .long("config")
53 /// .takes_value(true)
54 /// .value_name("FILE")
55 /// .help("Provides a config file to myprog");
56 /// // Using a usage string (setting a similar argument to the one above)
57 /// let input = arg!(-i --input <FILE> "Provides an input file to the program");
58 /// ```
59 #[allow(missing_debug_implementations)]
60 #[derive(Default, Clone)]
61 pub struct Arg<'help> {
62 pub(crate) id: Id,
63 pub(crate) provider: ArgProvider,
64 pub(crate) name: &'help str,
65 pub(crate) help: Option<&'help str>,
66 pub(crate) long_help: Option<&'help str>,
67 pub(crate) action: Option<ArgAction>,
68 pub(crate) value_parser: Option<super::ValueParser>,
69 pub(crate) blacklist: Vec<Id>,
70 pub(crate) settings: ArgFlags,
71 pub(crate) overrides: Vec<Id>,
72 pub(crate) groups: Vec<Id>,
73 pub(crate) requires: Vec<(ArgPredicate<'help>, Id)>,
74 pub(crate) r_ifs: Vec<(Id, &'help str)>,
75 pub(crate) r_ifs_all: Vec<(Id, &'help str)>,
76 pub(crate) r_unless: Vec<Id>,
77 pub(crate) r_unless_all: Vec<Id>,
78 pub(crate) short: Option<char>,
79 pub(crate) long: Option<&'help str>,
80 pub(crate) aliases: Vec<(&'help str, bool)>, // (name, visible)
81 pub(crate) short_aliases: Vec<(char, bool)>, // (name, visible)
82 pub(crate) disp_ord: DisplayOrder,
83 pub(crate) possible_vals: Vec<PossibleValue<'help>>,
84 pub(crate) val_names: Vec<&'help str>,
85 pub(crate) num_vals: Option<usize>,
86 pub(crate) max_occurs: Option<usize>,
87 pub(crate) max_vals: Option<usize>,
88 pub(crate) min_vals: Option<usize>,
89 pub(crate) validator: Option<Arc<Mutex<Validator<'help>>>>,
90 pub(crate) validator_os: Option<Arc<Mutex<ValidatorOs<'help>>>>,
91 pub(crate) val_delim: Option<char>,
92 pub(crate) default_vals: Vec<&'help OsStr>,
93 pub(crate) default_vals_ifs: Vec<(Id, ArgPredicate<'help>, Option<&'help OsStr>)>,
94 pub(crate) default_missing_vals: Vec<&'help OsStr>,
95 #[cfg(feature = "env")]
96 pub(crate) env: Option<(&'help OsStr, Option<OsString>)>,
97 pub(crate) terminator: Option<&'help str>,
98 pub(crate) index: Option<usize>,
99 pub(crate) help_heading: Option<Option<&'help str>>,
100 pub(crate) value_hint: Option<ValueHint>,
101 }
102
103 /// # Basic API
104 impl<'help> Arg<'help> {
105 /// Create a new [`Arg`] with a unique name.
106 ///
107 /// The name is used to check whether or not the argument was used at
108 /// runtime, get values, set relationships with other args, etc..
109 ///
110 /// **NOTE:** In the case of arguments that take values (i.e. [`Arg::takes_value(true)`])
111 /// and positional arguments (i.e. those without a preceding `-` or `--`) the name will also
112 /// be displayed when the user prints the usage/help information of the program.
113 ///
114 /// # Examples
115 ///
116 /// ```rust
117 /// # use clap::{Command, Arg};
118 /// Arg::new("config")
119 /// # ;
120 /// ```
121 /// [`Arg::takes_value(true)`]: Arg::takes_value()
new<S: Into<&'help str>>(n: S) -> Self122 pub fn new<S: Into<&'help str>>(n: S) -> Self {
123 Arg::default().name(n)
124 }
125
126 /// Set the identifier used for referencing this argument in the clap API.
127 ///
128 /// See [`Arg::new`] for more details.
129 #[must_use]
id<S: Into<&'help str>>(mut self, n: S) -> Self130 pub fn id<S: Into<&'help str>>(mut self, n: S) -> Self {
131 let name = n.into();
132 self.id = Id::from(&*name);
133 self.name = name;
134 self
135 }
136
137 /// Deprecated, replaced with [`Arg::id`] to avoid confusion with [`Arg::value_name`]
138 ///
139 /// Builder: replaced `arg.name(...)` with `arg.id(...)`
140 #[cfg_attr(
141 feature = "deprecated",
142 deprecated(
143 since = "3.1.0",
144 note = "Replaced with `Arg::id` to avoid confusion with `Arg::value_name`
145
146 Builder: replaced `arg.name(...)` with `arg.id(...)`
147 "
148 )
149 )]
name<S: Into<&'help str>>(self, n: S) -> Self150 pub fn name<S: Into<&'help str>>(self, n: S) -> Self {
151 self.id(n)
152 }
153
154 /// Sets the short version of the argument without the preceding `-`.
155 ///
156 /// By default `V` and `h` are used by the auto-generated `version` and `help` arguments,
157 /// respectively. You may use the uppercase `V` or lowercase `h` for your own arguments, in
158 /// which case `clap` simply will not assign those to the auto-generated
159 /// `version` or `help` arguments.
160 ///
161 /// # Examples
162 ///
163 /// When calling `short`, use a single valid UTF-8 character which will allow using the
164 /// argument via a single hyphen (`-`) such as `-c`:
165 ///
166 /// ```rust
167 /// # use clap::{Command, Arg};
168 /// let m = Command::new("prog")
169 /// .arg(Arg::new("config")
170 /// .short('c')
171 /// .takes_value(true))
172 /// .get_matches_from(vec![
173 /// "prog", "-c", "file.toml"
174 /// ]);
175 ///
176 /// assert_eq!(m.get_one::<String>("config").map(String::as_str), Some("file.toml"));
177 /// ```
178 #[inline]
179 #[must_use]
short(mut self, s: char) -> Self180 pub fn short(mut self, s: char) -> Self {
181 assert!(s != '-', "short option name cannot be `-`");
182
183 self.short = Some(s);
184 self
185 }
186
187 /// Sets the long version of the argument without the preceding `--`.
188 ///
189 /// By default `version` and `help` are used by the auto-generated `version` and `help`
190 /// arguments, respectively. You may use the word `version` or `help` for the long form of your
191 /// own arguments, in which case `clap` simply will not assign those to the auto-generated
192 /// `version` or `help` arguments.
193 ///
194 /// **NOTE:** Any leading `-` characters will be stripped
195 ///
196 /// # Examples
197 ///
198 /// To set `long` use a word containing valid UTF-8. If you supply a double leading
199 /// `--` such as `--config` they will be stripped. Hyphens in the middle of the word, however,
200 /// will *not* be stripped (i.e. `config-file` is allowed).
201 ///
202 /// Setting `long` allows using the argument via a double hyphen (`--`) such as `--config`
203 ///
204 /// ```rust
205 /// # use clap::{Command, Arg};
206 /// let m = Command::new("prog")
207 /// .arg(Arg::new("cfg")
208 /// .long("config")
209 /// .takes_value(true))
210 /// .get_matches_from(vec![
211 /// "prog", "--config", "file.toml"
212 /// ]);
213 ///
214 /// assert_eq!(m.get_one::<String>("cfg").map(String::as_str), Some("file.toml"));
215 /// ```
216 #[inline]
217 #[must_use]
long(mut self, l: &'help str) -> Self218 pub fn long(mut self, l: &'help str) -> Self {
219 #[cfg(feature = "unstable-v4")]
220 {
221 self.long = Some(l);
222 }
223 #[cfg(not(feature = "unstable-v4"))]
224 {
225 self.long = Some(l.trim_start_matches(|c| c == '-'));
226 }
227 self
228 }
229
230 /// Add an alias, which functions as a hidden long flag.
231 ///
232 /// This is more efficient, and easier than creating multiple hidden arguments as one only
233 /// needs to check for the existence of this command, and not all variants.
234 ///
235 /// # Examples
236 ///
237 /// ```rust
238 /// # use clap::{Command, Arg};
239 /// let m = Command::new("prog")
240 /// .arg(Arg::new("test")
241 /// .long("test")
242 /// .alias("alias")
243 /// .takes_value(true))
244 /// .get_matches_from(vec![
245 /// "prog", "--alias", "cool"
246 /// ]);
247 /// assert!(m.contains_id("test"));
248 /// assert_eq!(m.value_of("test"), Some("cool"));
249 /// ```
250 #[must_use]
alias<S: Into<&'help str>>(mut self, name: S) -> Self251 pub fn alias<S: Into<&'help str>>(mut self, name: S) -> Self {
252 self.aliases.push((name.into(), false));
253 self
254 }
255
256 /// Add an alias, which functions as a hidden short flag.
257 ///
258 /// This is more efficient, and easier than creating multiple hidden arguments as one only
259 /// needs to check for the existence of this command, and not all variants.
260 ///
261 /// # Examples
262 ///
263 /// ```rust
264 /// # use clap::{Command, Arg};
265 /// let m = Command::new("prog")
266 /// .arg(Arg::new("test")
267 /// .short('t')
268 /// .short_alias('e')
269 /// .takes_value(true))
270 /// .get_matches_from(vec![
271 /// "prog", "-e", "cool"
272 /// ]);
273 /// assert!(m.contains_id("test"));
274 /// assert_eq!(m.value_of("test"), Some("cool"));
275 /// ```
276 #[must_use]
short_alias(mut self, name: char) -> Self277 pub fn short_alias(mut self, name: char) -> Self {
278 assert!(name != '-', "short alias name cannot be `-`");
279
280 self.short_aliases.push((name, false));
281 self
282 }
283
284 /// Add aliases, which function as hidden long flags.
285 ///
286 /// This is more efficient, and easier than creating multiple hidden subcommands as one only
287 /// needs to check for the existence of this command, and not all variants.
288 ///
289 /// # Examples
290 ///
291 /// ```rust
292 /// # use clap::{Command, Arg, ArgAction};
293 /// let m = Command::new("prog")
294 /// .arg(Arg::new("test")
295 /// .long("test")
296 /// .aliases(&["do-stuff", "do-tests", "tests"])
297 /// .action(ArgAction::SetTrue)
298 /// .help("the file to add")
299 /// .required(false))
300 /// .get_matches_from(vec![
301 /// "prog", "--do-tests"
302 /// ]);
303 /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
304 /// ```
305 #[must_use]
aliases(mut self, names: &[&'help str]) -> Self306 pub fn aliases(mut self, names: &[&'help str]) -> Self {
307 self.aliases.extend(names.iter().map(|&x| (x, false)));
308 self
309 }
310
311 /// Add aliases, which functions as a hidden short flag.
312 ///
313 /// This is more efficient, and easier than creating multiple hidden subcommands as one only
314 /// needs to check for the existence of this command, and not all variants.
315 ///
316 /// # Examples
317 ///
318 /// ```rust
319 /// # use clap::{Command, Arg, ArgAction};
320 /// let m = Command::new("prog")
321 /// .arg(Arg::new("test")
322 /// .short('t')
323 /// .short_aliases(&['e', 's'])
324 /// .action(ArgAction::SetTrue)
325 /// .help("the file to add")
326 /// .required(false))
327 /// .get_matches_from(vec![
328 /// "prog", "-s"
329 /// ]);
330 /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
331 /// ```
332 #[must_use]
short_aliases(mut self, names: &[char]) -> Self333 pub fn short_aliases(mut self, names: &[char]) -> Self {
334 for s in names {
335 assert!(s != &'-', "short alias name cannot be `-`");
336 self.short_aliases.push((*s, false));
337 }
338 self
339 }
340
341 /// Add an alias, which functions as a visible long flag.
342 ///
343 /// Like [`Arg::alias`], except that they are visible inside the help message.
344 ///
345 /// # Examples
346 ///
347 /// ```rust
348 /// # use clap::{Command, Arg};
349 /// let m = Command::new("prog")
350 /// .arg(Arg::new("test")
351 /// .visible_alias("something-awesome")
352 /// .long("test")
353 /// .takes_value(true))
354 /// .get_matches_from(vec![
355 /// "prog", "--something-awesome", "coffee"
356 /// ]);
357 /// assert!(m.contains_id("test"));
358 /// assert_eq!(m.value_of("test"), Some("coffee"));
359 /// ```
360 /// [`Command::alias`]: Arg::alias()
361 #[must_use]
visible_alias<S: Into<&'help str>>(mut self, name: S) -> Self362 pub fn visible_alias<S: Into<&'help str>>(mut self, name: S) -> Self {
363 self.aliases.push((name.into(), true));
364 self
365 }
366
367 /// Add an alias, which functions as a visible short flag.
368 ///
369 /// Like [`Arg::short_alias`], except that they are visible inside the help message.
370 ///
371 /// # Examples
372 ///
373 /// ```rust
374 /// # use clap::{Command, Arg};
375 /// let m = Command::new("prog")
376 /// .arg(Arg::new("test")
377 /// .long("test")
378 /// .visible_short_alias('t')
379 /// .takes_value(true))
380 /// .get_matches_from(vec![
381 /// "prog", "-t", "coffee"
382 /// ]);
383 /// assert!(m.contains_id("test"));
384 /// assert_eq!(m.value_of("test"), Some("coffee"));
385 /// ```
386 #[must_use]
visible_short_alias(mut self, name: char) -> Self387 pub fn visible_short_alias(mut self, name: char) -> Self {
388 assert!(name != '-', "short alias name cannot be `-`");
389
390 self.short_aliases.push((name, true));
391 self
392 }
393
394 /// Add aliases, which function as visible long flags.
395 ///
396 /// Like [`Arg::aliases`], except that they are visible inside the help message.
397 ///
398 /// # Examples
399 ///
400 /// ```rust
401 /// # use clap::{Command, Arg, ArgAction};
402 /// let m = Command::new("prog")
403 /// .arg(Arg::new("test")
404 /// .long("test")
405 /// .action(ArgAction::SetTrue)
406 /// .visible_aliases(&["something", "awesome", "cool"]))
407 /// .get_matches_from(vec![
408 /// "prog", "--awesome"
409 /// ]);
410 /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
411 /// ```
412 /// [`Command::aliases`]: Arg::aliases()
413 #[must_use]
visible_aliases(mut self, names: &[&'help str]) -> Self414 pub fn visible_aliases(mut self, names: &[&'help str]) -> Self {
415 self.aliases.extend(names.iter().map(|n| (*n, true)));
416 self
417 }
418
419 /// Add aliases, which function as visible short flags.
420 ///
421 /// Like [`Arg::short_aliases`], except that they are visible inside the help message.
422 ///
423 /// # Examples
424 ///
425 /// ```rust
426 /// # use clap::{Command, Arg, ArgAction};
427 /// let m = Command::new("prog")
428 /// .arg(Arg::new("test")
429 /// .long("test")
430 /// .action(ArgAction::SetTrue)
431 /// .visible_short_aliases(&['t', 'e']))
432 /// .get_matches_from(vec![
433 /// "prog", "-t"
434 /// ]);
435 /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
436 /// ```
437 #[must_use]
visible_short_aliases(mut self, names: &[char]) -> Self438 pub fn visible_short_aliases(mut self, names: &[char]) -> Self {
439 for n in names {
440 assert!(n != &'-', "short alias name cannot be `-`");
441 self.short_aliases.push((*n, true));
442 }
443 self
444 }
445
446 /// Specifies the index of a positional argument **starting at** 1.
447 ///
448 /// **NOTE:** The index refers to position according to **other positional argument**. It does
449 /// not define position in the argument list as a whole.
450 ///
451 /// **NOTE:** You can optionally leave off the `index` method, and the index will be
452 /// assigned in order of evaluation. Utilizing the `index` method allows for setting
453 /// indexes out of order
454 ///
455 /// **NOTE:** This is only meant to be used for positional arguments and shouldn't to be used
456 /// with [`Arg::short`] or [`Arg::long`].
457 ///
458 /// **NOTE:** When utilized with [`Arg::multiple_values(true)`], only the **last** positional argument
459 /// may be defined as multiple (i.e. with the highest index)
460 ///
461 /// # Panics
462 ///
463 /// [`Command`] will [`panic!`] if indexes are skipped (such as defining `index(1)` and `index(3)`
464 /// but not `index(2)`, or a positional argument is defined as multiple and is not the highest
465 /// index
466 ///
467 /// # Examples
468 ///
469 /// ```rust
470 /// # use clap::{Command, Arg};
471 /// Arg::new("config")
472 /// .index(1)
473 /// # ;
474 /// ```
475 ///
476 /// ```rust
477 /// # use clap::{Command, Arg};
478 /// let m = Command::new("prog")
479 /// .arg(Arg::new("mode")
480 /// .index(1))
481 /// .arg(Arg::new("debug")
482 /// .long("debug"))
483 /// .get_matches_from(vec![
484 /// "prog", "--debug", "fast"
485 /// ]);
486 ///
487 /// assert!(m.contains_id("mode"));
488 /// assert_eq!(m.value_of("mode"), Some("fast")); // notice index(1) means "first positional"
489 /// // *not* first argument
490 /// ```
491 /// [`Arg::short`]: Arg::short()
492 /// [`Arg::long`]: Arg::long()
493 /// [`Arg::multiple_values(true)`]: Arg::multiple_values()
494 /// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html
495 /// [`Command`]: crate::Command
496 #[inline]
497 #[must_use]
index(mut self, idx: usize) -> Self498 pub fn index(mut self, idx: usize) -> Self {
499 self.index = Some(idx);
500 self
501 }
502
503 /// This arg is the last, or final, positional argument (i.e. has the highest
504 /// index) and is *only* able to be accessed via the `--` syntax (i.e. `$ prog args --
505 /// last_arg`).
506 ///
507 /// Even, if no other arguments are left to parse, if the user omits the `--` syntax
508 /// they will receive an [`UnknownArgument`] error. Setting an argument to `.last(true)` also
509 /// allows one to access this arg early using the `--` syntax. Accessing an arg early, even with
510 /// the `--` syntax is otherwise not possible.
511 ///
512 /// **NOTE:** This will change the usage string to look like `$ prog [OPTIONS] [-- <ARG>]` if
513 /// `ARG` is marked as `.last(true)`.
514 ///
515 /// **NOTE:** This setting will imply [`crate::Command::dont_collapse_args_in_usage`] because failing
516 /// to set this can make the usage string very confusing.
517 ///
518 /// **NOTE**: This setting only applies to positional arguments, and has no effect on OPTIONS
519 ///
520 /// **NOTE:** Setting this requires [`Arg::takes_value`]
521 ///
522 /// **CAUTION:** Using this setting *and* having child subcommands is not
523 /// recommended with the exception of *also* using
524 /// [`crate::Command::args_conflicts_with_subcommands`]
525 /// (or [`crate::Command::subcommand_negates_reqs`] if the argument marked `Last` is also
526 /// marked [`Arg::required`])
527 ///
528 /// # Examples
529 ///
530 /// ```rust
531 /// # use clap::Arg;
532 /// Arg::new("args")
533 /// .takes_value(true)
534 /// .last(true)
535 /// # ;
536 /// ```
537 ///
538 /// Setting `last` ensures the arg has the highest [index] of all positional args
539 /// and requires that the `--` syntax be used to access it early.
540 ///
541 /// ```rust
542 /// # use clap::{Command, Arg};
543 /// let res = Command::new("prog")
544 /// .arg(Arg::new("first"))
545 /// .arg(Arg::new("second"))
546 /// .arg(Arg::new("third")
547 /// .takes_value(true)
548 /// .last(true))
549 /// .try_get_matches_from(vec![
550 /// "prog", "one", "--", "three"
551 /// ]);
552 ///
553 /// assert!(res.is_ok());
554 /// let m = res.unwrap();
555 /// assert_eq!(m.value_of("third"), Some("three"));
556 /// assert!(m.value_of("second").is_none());
557 /// ```
558 ///
559 /// Even if the positional argument marked `Last` is the only argument left to parse,
560 /// failing to use the `--` syntax results in an error.
561 ///
562 /// ```rust
563 /// # use clap::{Command, Arg, ErrorKind};
564 /// let res = Command::new("prog")
565 /// .arg(Arg::new("first"))
566 /// .arg(Arg::new("second"))
567 /// .arg(Arg::new("third")
568 /// .takes_value(true)
569 /// .last(true))
570 /// .try_get_matches_from(vec![
571 /// "prog", "one", "two", "three"
572 /// ]);
573 ///
574 /// assert!(res.is_err());
575 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
576 /// ```
577 /// [index]: Arg::index()
578 /// [`UnknownArgument`]: crate::ErrorKind::UnknownArgument
579 #[inline]
580 #[must_use]
last(self, yes: bool) -> Self581 pub fn last(self, yes: bool) -> Self {
582 if yes {
583 self.setting(ArgSettings::Last)
584 } else {
585 self.unset_setting(ArgSettings::Last)
586 }
587 }
588
589 /// Specifies that the argument must be present.
590 ///
591 /// Required by default means it is required, when no other conflicting rules or overrides have
592 /// been evaluated. Conflicting rules take precedence over being required.
593 ///
594 /// **Pro tip:** Flags (i.e. not positional, or arguments that take values) shouldn't be
595 /// required by default. This is because if a flag were to be required, it should simply be
596 /// implied. No additional information is required from user. Flags by their very nature are
597 /// simply boolean on/off switches. The only time a user *should* be required to use a flag
598 /// is if the operation is destructive in nature, and the user is essentially proving to you,
599 /// "Yes, I know what I'm doing."
600 ///
601 /// # Examples
602 ///
603 /// ```rust
604 /// # use clap::Arg;
605 /// Arg::new("config")
606 /// .required(true)
607 /// # ;
608 /// ```
609 ///
610 /// Setting required requires that the argument be used at runtime.
611 ///
612 /// ```rust
613 /// # use clap::{Command, Arg};
614 /// let res = Command::new("prog")
615 /// .arg(Arg::new("cfg")
616 /// .required(true)
617 /// .takes_value(true)
618 /// .long("config"))
619 /// .try_get_matches_from(vec![
620 /// "prog", "--config", "file.conf",
621 /// ]);
622 ///
623 /// assert!(res.is_ok());
624 /// ```
625 ///
626 /// Setting required and then *not* supplying that argument at runtime is an error.
627 ///
628 /// ```rust
629 /// # use clap::{Command, Arg, ErrorKind};
630 /// let res = Command::new("prog")
631 /// .arg(Arg::new("cfg")
632 /// .required(true)
633 /// .takes_value(true)
634 /// .long("config"))
635 /// .try_get_matches_from(vec![
636 /// "prog"
637 /// ]);
638 ///
639 /// assert!(res.is_err());
640 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
641 /// ```
642 #[inline]
643 #[must_use]
required(self, yes: bool) -> Self644 pub fn required(self, yes: bool) -> Self {
645 if yes {
646 self.setting(ArgSettings::Required)
647 } else {
648 self.unset_setting(ArgSettings::Required)
649 }
650 }
651
652 /// Sets an argument that is required when this one is present
653 ///
654 /// i.e. when using this argument, the following argument *must* be present.
655 ///
656 /// **NOTE:** [Conflicting] rules and [override] rules take precedence over being required
657 ///
658 /// # Examples
659 ///
660 /// ```rust
661 /// # use clap::Arg;
662 /// Arg::new("config")
663 /// .requires("input")
664 /// # ;
665 /// ```
666 ///
667 /// Setting [`Arg::requires(name)`] requires that the argument be used at runtime if the
668 /// defining argument is used. If the defining argument isn't used, the other argument isn't
669 /// required
670 ///
671 /// ```rust
672 /// # use clap::{Command, Arg};
673 /// let res = Command::new("prog")
674 /// .arg(Arg::new("cfg")
675 /// .takes_value(true)
676 /// .requires("input")
677 /// .long("config"))
678 /// .arg(Arg::new("input"))
679 /// .try_get_matches_from(vec![
680 /// "prog"
681 /// ]);
682 ///
683 /// assert!(res.is_ok()); // We didn't use cfg, so input wasn't required
684 /// ```
685 ///
686 /// Setting [`Arg::requires(name)`] and *not* supplying that argument is an error.
687 ///
688 /// ```rust
689 /// # use clap::{Command, Arg, ErrorKind};
690 /// let res = Command::new("prog")
691 /// .arg(Arg::new("cfg")
692 /// .takes_value(true)
693 /// .requires("input")
694 /// .long("config"))
695 /// .arg(Arg::new("input"))
696 /// .try_get_matches_from(vec![
697 /// "prog", "--config", "file.conf"
698 /// ]);
699 ///
700 /// assert!(res.is_err());
701 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
702 /// ```
703 /// [`Arg::requires(name)`]: Arg::requires()
704 /// [Conflicting]: Arg::conflicts_with()
705 /// [override]: Arg::overrides_with()
706 #[must_use]
requires<T: Key>(mut self, arg_id: T) -> Self707 pub fn requires<T: Key>(mut self, arg_id: T) -> Self {
708 self.requires.push((ArgPredicate::IsPresent, arg_id.into()));
709 self
710 }
711
712 /// This argument must be passed alone; it conflicts with all other arguments.
713 ///
714 /// # Examples
715 ///
716 /// ```rust
717 /// # use clap::Arg;
718 /// Arg::new("config")
719 /// .exclusive(true)
720 /// # ;
721 /// ```
722 ///
723 /// Setting an exclusive argument and having any other arguments present at runtime
724 /// is an error.
725 ///
726 /// ```rust
727 /// # use clap::{Command, Arg, ErrorKind};
728 /// let res = Command::new("prog")
729 /// .arg(Arg::new("exclusive")
730 /// .takes_value(true)
731 /// .exclusive(true)
732 /// .long("exclusive"))
733 /// .arg(Arg::new("debug")
734 /// .long("debug"))
735 /// .arg(Arg::new("input"))
736 /// .try_get_matches_from(vec![
737 /// "prog", "--exclusive", "file.conf", "file.txt"
738 /// ]);
739 ///
740 /// assert!(res.is_err());
741 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::ArgumentConflict);
742 /// ```
743 #[inline]
744 #[must_use]
exclusive(self, yes: bool) -> Self745 pub fn exclusive(self, yes: bool) -> Self {
746 if yes {
747 self.setting(ArgSettings::Exclusive)
748 } else {
749 self.unset_setting(ArgSettings::Exclusive)
750 }
751 }
752
753 /// Specifies that an argument can be matched to all child [`Subcommand`]s.
754 ///
755 /// **NOTE:** Global arguments *only* propagate down, **not** up (to parent commands), however
756 /// their values once a user uses them will be propagated back up to parents. In effect, this
757 /// means one should *define* all global arguments at the top level, however it doesn't matter
758 /// where the user *uses* the global argument.
759 ///
760 /// # Examples
761 ///
762 /// Assume an application with two subcommands, and you'd like to define a
763 /// `--verbose` flag that can be called on any of the subcommands and parent, but you don't
764 /// want to clutter the source with three duplicate [`Arg`] definitions.
765 ///
766 /// ```rust
767 /// # use clap::{Command, Arg, ArgAction};
768 /// let m = Command::new("prog")
769 /// .arg(Arg::new("verb")
770 /// .long("verbose")
771 /// .short('v')
772 /// .action(ArgAction::SetTrue)
773 /// .global(true))
774 /// .subcommand(Command::new("test"))
775 /// .subcommand(Command::new("do-stuff"))
776 /// .get_matches_from(vec![
777 /// "prog", "do-stuff", "--verbose"
778 /// ]);
779 ///
780 /// assert_eq!(m.subcommand_name(), Some("do-stuff"));
781 /// let sub_m = m.subcommand_matches("do-stuff").unwrap();
782 /// assert_eq!(*sub_m.get_one::<bool>("verb").expect("defaulted by clap"), true);
783 /// ```
784 ///
785 /// [`Subcommand`]: crate::Subcommand
786 #[inline]
787 #[must_use]
global(self, yes: bool) -> Self788 pub fn global(self, yes: bool) -> Self {
789 if yes {
790 self.setting(ArgSettings::Global)
791 } else {
792 self.unset_setting(ArgSettings::Global)
793 }
794 }
795
796 /// Deprecated, replaced with [`Arg::action`] ([Issue #3772](https://github.com/clap-rs/clap/issues/3772))
797 #[inline]
798 #[must_use]
799 #[cfg_attr(
800 feature = "deprecated",
801 deprecated(
802 since = "3.2.0",
803 note = "Replaced with `Arg::action` (Issue #3772)
804
805 Builder: replace `arg.multiple_occurrences(true)` with `arg.action(ArgAction::Append)` when taking a value and `arg.action(ArgAction::Count)` with `matches.get_count` when not
806 "
807 )
808 )]
multiple_occurrences(self, yes: bool) -> Self809 pub fn multiple_occurrences(self, yes: bool) -> Self {
810 if yes {
811 self.setting(ArgSettings::MultipleOccurrences)
812 } else {
813 self.unset_setting(ArgSettings::MultipleOccurrences)
814 }
815 }
816
817 /// Deprecated, for flags, this is replaced with `RangedI64ValueParser::range`
818 ///
819 /// Derive: `#[clap(action = ArgAction::Count, value_parser = value_parser!(u8).range(..max))]`
820 ///
821 /// Builder: `arg.action(ArgAction::Count).value_parser(value_parser!(u8).range(..max))`
822 #[inline]
823 #[must_use]
824 #[cfg_attr(
825 feature = "deprecated",
826 deprecated(
827 since = "3.2.0",
828 note = "For flags, this is replaced with `RangedI64ValueParser::range`
829
830 Derive: `#[clap(action = ArgAction::Count, value_parser = value_parser!(u8).range(..max))]`
831
832 Builder: `arg.action(ArgAction::Count).value_parser(value_parser!(u8).range(..max))`
833 "
834 )
835 )]
max_occurrences(mut self, qty: usize) -> Self836 pub fn max_occurrences(mut self, qty: usize) -> Self {
837 self.max_occurs = Some(qty);
838 if qty > 1 {
839 self.multiple_occurrences(true)
840 } else {
841 self
842 }
843 }
844
845 /// Check if the [`ArgSettings`] variant is currently set on the argument.
846 ///
847 /// [`ArgSettings`]: crate::ArgSettings
848 #[inline]
is_set(&self, s: ArgSettings) -> bool849 pub fn is_set(&self, s: ArgSettings) -> bool {
850 self.settings.is_set(s)
851 }
852
853 /// Apply a setting to the argument.
854 ///
855 /// See [`ArgSettings`] for a full list of possibilities and examples.
856 ///
857 /// # Examples
858 ///
859 /// ```no_run
860 /// # use clap::{Arg, ArgSettings};
861 /// Arg::new("config")
862 /// .setting(ArgSettings::Required)
863 /// .setting(ArgSettings::TakesValue)
864 /// # ;
865 /// ```
866 ///
867 /// ```no_run
868 /// # use clap::{Arg, ArgSettings};
869 /// Arg::new("config")
870 /// .setting(ArgSettings::Required | ArgSettings::TakesValue)
871 /// # ;
872 /// ```
873 #[inline]
874 #[must_use]
setting<F>(mut self, setting: F) -> Self where F: Into<ArgFlags>,875 pub fn setting<F>(mut self, setting: F) -> Self
876 where
877 F: Into<ArgFlags>,
878 {
879 self.settings.insert(setting.into());
880 self
881 }
882
883 /// Remove a setting from the argument.
884 ///
885 /// See [`ArgSettings`] for a full list of possibilities and examples.
886 ///
887 /// # Examples
888 ///
889 /// ```no_run
890 /// # use clap::{Arg, ArgSettings};
891 /// Arg::new("config")
892 /// .unset_setting(ArgSettings::Required)
893 /// .unset_setting(ArgSettings::TakesValue)
894 /// # ;
895 /// ```
896 ///
897 /// ```no_run
898 /// # use clap::{Arg, ArgSettings};
899 /// Arg::new("config")
900 /// .unset_setting(ArgSettings::Required | ArgSettings::TakesValue)
901 /// # ;
902 /// ```
903 #[inline]
904 #[must_use]
unset_setting<F>(mut self, setting: F) -> Self where F: Into<ArgFlags>,905 pub fn unset_setting<F>(mut self, setting: F) -> Self
906 where
907 F: Into<ArgFlags>,
908 {
909 self.settings.remove(setting.into());
910 self
911 }
912 }
913
914 /// # Value Handling
915 impl<'help> Arg<'help> {
916 /// Specifies that the argument takes a value at run time.
917 ///
918 /// **NOTE:** values for arguments may be specified in any of the following methods
919 ///
920 /// - Using a space such as `-o value` or `--option value`
921 /// - Using an equals and no space such as `-o=value` or `--option=value`
922 /// - Use a short and no space such as `-ovalue`
923 ///
924 /// **NOTE:** By default, args which allow [multiple values] are delimited by commas, meaning
925 /// `--option=val1,val2,val3` is three values for the `--option` argument. If you wish to
926 /// change the delimiter to another character you can use [`Arg::value_delimiter(char)`],
927 /// alternatively you can turn delimiting values **OFF** by using
928 /// [`Arg::use_value_delimiter(false)`][Arg::use_value_delimiter]
929 ///
930 /// # Examples
931 ///
932 /// ```rust
933 /// # use clap::{Command, Arg};
934 /// let m = Command::new("prog")
935 /// .arg(Arg::new("mode")
936 /// .long("mode")
937 /// .takes_value(true))
938 /// .get_matches_from(vec![
939 /// "prog", "--mode", "fast"
940 /// ]);
941 ///
942 /// assert!(m.contains_id("mode"));
943 /// assert_eq!(m.value_of("mode"), Some("fast"));
944 /// ```
945 /// [`Arg::value_delimiter(char)`]: Arg::value_delimiter()
946 /// [multiple values]: Arg::multiple_values
947 #[inline]
948 #[must_use]
takes_value(self, yes: bool) -> Self949 pub fn takes_value(self, yes: bool) -> Self {
950 if yes {
951 self.setting(ArgSettings::TakesValue)
952 } else {
953 self.unset_setting(ArgSettings::TakesValue)
954 }
955 }
956
957 /// Specify the behavior when parsing an argument
958 ///
959 /// # Examples
960 ///
961 /// ```rust
962 /// # use clap::Command;
963 /// # use clap::Arg;
964 /// let cmd = Command::new("mycmd")
965 /// .arg(
966 /// Arg::new("flag")
967 /// .long("flag")
968 /// .action(clap::ArgAction::Set)
969 /// );
970 ///
971 /// let matches = cmd.try_get_matches_from(["mycmd", "--flag", "value"]).unwrap();
972 /// assert!(matches.contains_id("flag"));
973 /// assert_eq!(matches.occurrences_of("flag"), 0);
974 /// assert_eq!(
975 /// matches.get_many::<String>("flag").unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(),
976 /// vec!["value"]
977 /// );
978 /// ```
979 #[inline]
980 #[must_use]
action(mut self, action: ArgAction) -> Self981 pub fn action(mut self, action: ArgAction) -> Self {
982 self.action = Some(action);
983 self
984 }
985
986 /// Specify the type of the argument.
987 ///
988 /// This allows parsing and validating a value before storing it into
989 /// [`ArgMatches`][crate::ArgMatches].
990 ///
991 /// See also
992 /// - [`value_parser!`][crate::value_parser!] for auto-selecting a value parser for a given type
993 /// - [`BoolishValueParser`][crate::builder::BoolishValueParser], and [`FalseyValueParser`][crate::builder::FalseyValueParser] for alternative `bool` implementations
994 /// - [`NonEmptyStringValueParser`][crate::builder::NonEmptyStringValueParser] for basic validation for strings
995 /// - [`RangedI64ValueParser`][crate::builder::RangedI64ValueParser] and [`RangedU64ValueParser`][crate::builder::RangedU64ValueParser] for numeric ranges
996 /// - [`EnumValueParser`][crate::builder::EnumValueParser] and [`PossibleValuesParser`][crate::builder::PossibleValuesParser] for static enumerated values
997 /// - or any other [`TypedValueParser`][crate::builder::TypedValueParser] implementation
998 ///
999 /// ```rust
1000 /// let mut cmd = clap::Command::new("raw")
1001 /// .arg(
1002 /// clap::Arg::new("color")
1003 /// .long("color")
1004 /// .value_parser(["always", "auto", "never"])
1005 /// .default_value("auto")
1006 /// )
1007 /// .arg(
1008 /// clap::Arg::new("hostname")
1009 /// .long("hostname")
1010 /// .value_parser(clap::builder::NonEmptyStringValueParser::new())
1011 /// .takes_value(true)
1012 /// .required(true)
1013 /// )
1014 /// .arg(
1015 /// clap::Arg::new("port")
1016 /// .long("port")
1017 /// .value_parser(clap::value_parser!(u16).range(3000..))
1018 /// .takes_value(true)
1019 /// .required(true)
1020 /// );
1021 ///
1022 /// let m = cmd.try_get_matches_from_mut(
1023 /// ["cmd", "--hostname", "rust-lang.org", "--port", "3001"]
1024 /// ).unwrap();
1025 ///
1026 /// let color: &String = m.get_one("color")
1027 /// .expect("default");
1028 /// assert_eq!(color, "auto");
1029 ///
1030 /// let hostname: &String = m.get_one("hostname")
1031 /// .expect("required");
1032 /// assert_eq!(hostname, "rust-lang.org");
1033 ///
1034 /// let port: u16 = *m.get_one("port")
1035 /// .expect("required");
1036 /// assert_eq!(port, 3001);
1037 /// ```
value_parser(mut self, parser: impl Into<super::ValueParser>) -> Self1038 pub fn value_parser(mut self, parser: impl Into<super::ValueParser>) -> Self {
1039 self.value_parser = Some(parser.into());
1040 self
1041 }
1042
1043 /// Specifies that the argument may have an unknown number of values
1044 ///
1045 /// Without any other settings, this argument may appear only *once*.
1046 ///
1047 /// For example, `--opt val1 val2` is allowed, but `--opt val1 val2 --opt val3` is not.
1048 ///
1049 /// **NOTE:** Setting this requires [`Arg::takes_value`].
1050 ///
1051 /// **WARNING:**
1052 ///
1053 /// Setting `multiple_values` for an argument that takes a value, but with no other details can
1054 /// be dangerous in some circumstances. Because multiple values are allowed,
1055 /// `--option val1 val2 val3` is perfectly valid. Be careful when designing a CLI where
1056 /// positional arguments are *also* expected as `clap` will continue parsing *values* until one
1057 /// of the following happens:
1058 ///
1059 /// - It reaches the [maximum number of values]
1060 /// - It reaches a [specific number of values]
1061 /// - It finds another flag or option (i.e. something that starts with a `-`)
1062 /// - It reaches a [value terminator][Arg::value_terminator] is reached
1063 ///
1064 /// Alternatively, [require a delimiter between values][Arg::require_delimiter].
1065 ///
1066 /// **WARNING:**
1067 ///
1068 /// When using args with `multiple_values` and [`subcommands`], one needs to consider the
1069 /// possibility of an argument value being the same as a valid subcommand. By default `clap` will
1070 /// parse the argument in question as a value *only if* a value is possible at that moment.
1071 /// Otherwise it will be parsed as a subcommand. In effect, this means using `multiple_values` with no
1072 /// additional parameters and a value that coincides with a subcommand name, the subcommand
1073 /// cannot be called unless another argument is passed between them.
1074 ///
1075 /// As an example, consider a CLI with an option `--ui-paths=<paths>...` and subcommand `signer`
1076 ///
1077 /// The following would be parsed as values to `--ui-paths`.
1078 ///
1079 /// ```text
1080 /// $ program --ui-paths path1 path2 signer
1081 /// ```
1082 ///
1083 /// This is because `--ui-paths` accepts multiple values. `clap` will continue parsing values
1084 /// until another argument is reached and it knows `--ui-paths` is done parsing.
1085 ///
1086 /// By adding additional parameters to `--ui-paths` we can solve this issue. Consider adding
1087 /// [`Arg::number_of_values(1)`] or using *only* [`ArgAction::Append`]. The following are all
1088 /// valid, and `signer` is parsed as a subcommand in the first case, but a value in the second
1089 /// case.
1090 ///
1091 /// ```text
1092 /// $ program --ui-paths path1 signer
1093 /// $ program --ui-paths path1 --ui-paths signer signer
1094 /// ```
1095 ///
1096 /// # Examples
1097 ///
1098 /// An example with options
1099 ///
1100 /// ```rust
1101 /// # use clap::{Command, Arg};
1102 /// let m = Command::new("prog")
1103 /// .arg(Arg::new("file")
1104 /// .takes_value(true)
1105 /// .multiple_values(true)
1106 /// .short('F'))
1107 /// .get_matches_from(vec![
1108 /// "prog", "-F", "file1", "file2", "file3"
1109 /// ]);
1110 ///
1111 /// assert!(m.contains_id("file"));
1112 /// let files: Vec<_> = m.values_of("file").unwrap().collect();
1113 /// assert_eq!(files, ["file1", "file2", "file3"]);
1114 /// ```
1115 ///
1116 /// Although `multiple_values` has been specified, we cannot use the argument more than once.
1117 ///
1118 /// ```rust
1119 /// # use clap::{Command, Arg, ErrorKind};
1120 /// let res = Command::new("prog")
1121 /// .arg(Arg::new("file")
1122 /// .takes_value(true)
1123 /// .multiple_values(true)
1124 /// .short('F'))
1125 /// .try_get_matches_from(vec![
1126 /// "prog", "-F", "file1", "-F", "file2", "-F", "file3"
1127 /// ]);
1128 ///
1129 /// assert!(res.is_err());
1130 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnexpectedMultipleUsage)
1131 /// ```
1132 ///
1133 /// A common mistake is to define an option which allows multiple values, and a positional
1134 /// argument.
1135 ///
1136 /// ```rust
1137 /// # use clap::{Command, Arg};
1138 /// let m = Command::new("prog")
1139 /// .arg(Arg::new("file")
1140 /// .takes_value(true)
1141 /// .multiple_values(true)
1142 /// .short('F'))
1143 /// .arg(Arg::new("word"))
1144 /// .get_matches_from(vec![
1145 /// "prog", "-F", "file1", "file2", "file3", "word"
1146 /// ]);
1147 ///
1148 /// assert!(m.contains_id("file"));
1149 /// let files: Vec<_> = m.values_of("file").unwrap().collect();
1150 /// assert_eq!(files, ["file1", "file2", "file3", "word"]); // wait...what?!
1151 /// assert!(!m.contains_id("word")); // but we clearly used word!
1152 /// ```
1153 ///
1154 /// The problem is `clap` doesn't know when to stop parsing values for "files". This is further
1155 /// compounded by if we'd said `word -F file1 file2` it would have worked fine, so it would
1156 /// appear to only fail sometimes...not good!
1157 ///
1158 /// A solution for the example above is to limit how many values with a [maximum], or [specific]
1159 /// number, or to say [`ArgAction::Append`] is ok, but multiple values is not.
1160 ///
1161 /// ```rust
1162 /// # use clap::{Command, Arg, ArgAction};
1163 /// let m = Command::new("prog")
1164 /// .arg(Arg::new("file")
1165 /// .takes_value(true)
1166 /// .action(ArgAction::Append)
1167 /// .short('F'))
1168 /// .arg(Arg::new("word"))
1169 /// .get_matches_from(vec![
1170 /// "prog", "-F", "file1", "-F", "file2", "-F", "file3", "word"
1171 /// ]);
1172 ///
1173 /// assert!(m.contains_id("file"));
1174 /// let files: Vec<_> = m.values_of("file").unwrap().collect();
1175 /// assert_eq!(files, ["file1", "file2", "file3"]);
1176 /// assert!(m.contains_id("word"));
1177 /// assert_eq!(m.value_of("word"), Some("word"));
1178 /// ```
1179 ///
1180 /// As a final example, let's fix the above error and get a pretty message to the user :)
1181 ///
1182 /// ```rust
1183 /// # use clap::{Command, Arg, ErrorKind, ArgAction};
1184 /// let res = Command::new("prog")
1185 /// .arg(Arg::new("file")
1186 /// .takes_value(true)
1187 /// .action(ArgAction::Append)
1188 /// .short('F'))
1189 /// .arg(Arg::new("word"))
1190 /// .try_get_matches_from(vec![
1191 /// "prog", "-F", "file1", "file2", "file3", "word"
1192 /// ]);
1193 ///
1194 /// assert!(res.is_err());
1195 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
1196 /// ```
1197 ///
1198 /// [`subcommands`]: crate::Command::subcommand()
1199 /// [`Arg::number_of_values(1)`]: Arg::number_of_values()
1200 /// [maximum number of values]: Arg::max_values()
1201 /// [specific number of values]: Arg::number_of_values()
1202 /// [maximum]: Arg::max_values()
1203 /// [specific]: Arg::number_of_values()
1204 #[inline]
1205 #[must_use]
multiple_values(self, yes: bool) -> Self1206 pub fn multiple_values(self, yes: bool) -> Self {
1207 if yes {
1208 self.setting(ArgSettings::MultipleValues)
1209 } else {
1210 self.unset_setting(ArgSettings::MultipleValues)
1211 }
1212 }
1213
1214 /// The number of values allowed for this argument.
1215 ///
1216 /// For example, if you had a
1217 /// `-f <file>` argument where you wanted exactly 3 'files' you would set
1218 /// `.number_of_values(3)`, and this argument wouldn't be satisfied unless the user provided
1219 /// 3 and only 3 values.
1220 ///
1221 /// **NOTE:** Does *not* require [`Arg::multiple_occurrences(true)`] to be set. Setting
1222 /// [`Arg::multiple_occurrences(true)`] would allow `-f <file> <file> <file> -f <file> <file> <file>` where
1223 /// as *not* setting it would only allow one occurrence of this argument.
1224 ///
1225 /// **NOTE:** implicitly sets [`Arg::takes_value(true)`] and [`Arg::multiple_values(true)`].
1226 ///
1227 /// # Examples
1228 ///
1229 /// ```rust
1230 /// # use clap::{Command, Arg};
1231 /// Arg::new("file")
1232 /// .short('f')
1233 /// .number_of_values(3);
1234 /// ```
1235 ///
1236 /// Not supplying the correct number of values is an error
1237 ///
1238 /// ```rust
1239 /// # use clap::{Command, Arg, ErrorKind};
1240 /// let res = Command::new("prog")
1241 /// .arg(Arg::new("file")
1242 /// .takes_value(true)
1243 /// .number_of_values(2)
1244 /// .short('F'))
1245 /// .try_get_matches_from(vec![
1246 /// "prog", "-F", "file1"
1247 /// ]);
1248 ///
1249 /// assert!(res.is_err());
1250 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
1251 /// ```
1252 /// [`Arg::multiple_occurrences(true)`]: Arg::multiple_occurrences()
1253 #[inline]
1254 #[must_use]
number_of_values(mut self, qty: usize) -> Self1255 pub fn number_of_values(mut self, qty: usize) -> Self {
1256 self.num_vals = Some(qty);
1257 self.takes_value(true).multiple_values(true)
1258 }
1259
1260 /// The *maximum* number of values are for this argument.
1261 ///
1262 /// For example, if you had a
1263 /// `-f <file>` argument where you wanted up to 3 'files' you would set `.max_values(3)`, and
1264 /// this argument would be satisfied if the user provided, 1, 2, or 3 values.
1265 ///
1266 /// **NOTE:** This does *not* implicitly set [`Arg::multiple_occurrences(true)`]. This is because
1267 /// `-o val -o val` is multiple occurrences but a single value and `-o val1 val2` is a single
1268 /// occurrence with multiple values. For positional arguments this **does** set
1269 /// [`Arg::multiple_occurrences(true)`] because there is no way to determine the difference between multiple
1270 /// occurrences and multiple values.
1271 ///
1272 /// # Examples
1273 ///
1274 /// ```rust
1275 /// # use clap::{Command, Arg};
1276 /// Arg::new("file")
1277 /// .short('f')
1278 /// .max_values(3);
1279 /// ```
1280 ///
1281 /// Supplying less than the maximum number of values is allowed
1282 ///
1283 /// ```rust
1284 /// # use clap::{Command, Arg};
1285 /// let res = Command::new("prog")
1286 /// .arg(Arg::new("file")
1287 /// .takes_value(true)
1288 /// .max_values(3)
1289 /// .short('F'))
1290 /// .try_get_matches_from(vec![
1291 /// "prog", "-F", "file1", "file2"
1292 /// ]);
1293 ///
1294 /// assert!(res.is_ok());
1295 /// let m = res.unwrap();
1296 /// let files: Vec<_> = m.values_of("file").unwrap().collect();
1297 /// assert_eq!(files, ["file1", "file2"]);
1298 /// ```
1299 ///
1300 /// Supplying more than the maximum number of values is an error
1301 ///
1302 /// ```rust
1303 /// # use clap::{Command, Arg, ErrorKind};
1304 /// let res = Command::new("prog")
1305 /// .arg(Arg::new("file")
1306 /// .takes_value(true)
1307 /// .max_values(2)
1308 /// .short('F'))
1309 /// .try_get_matches_from(vec![
1310 /// "prog", "-F", "file1", "file2", "file3"
1311 /// ]);
1312 ///
1313 /// assert!(res.is_err());
1314 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
1315 /// ```
1316 /// [`Arg::multiple_occurrences(true)`]: Arg::multiple_occurrences()
1317 #[inline]
1318 #[must_use]
max_values(mut self, qty: usize) -> Self1319 pub fn max_values(mut self, qty: usize) -> Self {
1320 self.max_vals = Some(qty);
1321 self.takes_value(true).multiple_values(true)
1322 }
1323
1324 /// The *minimum* number of values for this argument.
1325 ///
1326 /// For example, if you had a
1327 /// `-f <file>` argument where you wanted at least 2 'files' you would set
1328 /// `.min_values(2)`, and this argument would be satisfied if the user provided, 2 or more
1329 /// values.
1330 ///
1331 /// **NOTE:** This does not implicitly set [`Arg::multiple_occurrences(true)`]. This is because
1332 /// `-o val -o val` is multiple occurrences but a single value and `-o val1 val2` is a single
1333 /// occurrence with multiple values. For positional arguments this **does** set
1334 /// [`Arg::multiple_occurrences(true)`] because there is no way to determine the difference between multiple
1335 /// occurrences and multiple values.
1336 ///
1337 /// **NOTE:** Passing a non-zero value is not the same as specifying [`Arg::required(true)`].
1338 /// This is due to min and max validation only being performed for present arguments,
1339 /// marking them as required will thus perform validation and a min value of 1
1340 /// is unnecessary, ignored if not required.
1341 ///
1342 /// # Examples
1343 ///
1344 /// ```rust
1345 /// # use clap::{Command, Arg};
1346 /// Arg::new("file")
1347 /// .short('f')
1348 /// .min_values(3);
1349 /// ```
1350 ///
1351 /// Supplying more than the minimum number of values is allowed
1352 ///
1353 /// ```rust
1354 /// # use clap::{Command, Arg};
1355 /// let res = Command::new("prog")
1356 /// .arg(Arg::new("file")
1357 /// .takes_value(true)
1358 /// .min_values(2)
1359 /// .short('F'))
1360 /// .try_get_matches_from(vec![
1361 /// "prog", "-F", "file1", "file2", "file3"
1362 /// ]);
1363 ///
1364 /// assert!(res.is_ok());
1365 /// let m = res.unwrap();
1366 /// let files: Vec<_> = m.values_of("file").unwrap().collect();
1367 /// assert_eq!(files, ["file1", "file2", "file3"]);
1368 /// ```
1369 ///
1370 /// Supplying less than the minimum number of values is an error
1371 ///
1372 /// ```rust
1373 /// # use clap::{Command, Arg, ErrorKind};
1374 /// let res = Command::new("prog")
1375 /// .arg(Arg::new("file")
1376 /// .takes_value(true)
1377 /// .min_values(2)
1378 /// .short('F'))
1379 /// .try_get_matches_from(vec![
1380 /// "prog", "-F", "file1"
1381 /// ]);
1382 ///
1383 /// assert!(res.is_err());
1384 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::TooFewValues);
1385 /// ```
1386 /// [`Arg::multiple_occurrences(true)`]: Arg::multiple_occurrences()
1387 /// [`Arg::required(true)`]: Arg::required()
1388 #[inline]
1389 #[must_use]
min_values(mut self, qty: usize) -> Self1390 pub fn min_values(mut self, qty: usize) -> Self {
1391 self.min_vals = Some(qty);
1392 self.takes_value(true).multiple_values(true)
1393 }
1394
1395 /// Placeholder for the argument's value in the help message / usage.
1396 ///
1397 /// This name is cosmetic only; the name is **not** used to access arguments.
1398 /// This setting can be very helpful when describing the type of input the user should be
1399 /// using, such as `FILE`, `INTERFACE`, etc. Although not required, it's somewhat convention to
1400 /// use all capital letters for the value name.
1401 ///
1402 /// **NOTE:** implicitly sets [`Arg::takes_value(true)`]
1403 ///
1404 /// # Examples
1405 ///
1406 /// ```rust
1407 /// # use clap::{Command, Arg};
1408 /// Arg::new("cfg")
1409 /// .long("config")
1410 /// .value_name("FILE")
1411 /// # ;
1412 /// ```
1413 ///
1414 /// ```rust
1415 /// # use clap::{Command, Arg};
1416 /// let m = Command::new("prog")
1417 /// .arg(Arg::new("config")
1418 /// .long("config")
1419 /// .value_name("FILE")
1420 /// .help("Some help text"))
1421 /// .get_matches_from(vec![
1422 /// "prog", "--help"
1423 /// ]);
1424 /// ```
1425 /// Running the above program produces the following output
1426 ///
1427 /// ```text
1428 /// valnames
1429 ///
1430 /// USAGE:
1431 /// valnames [OPTIONS]
1432 ///
1433 /// OPTIONS:
1434 /// --config <FILE> Some help text
1435 /// -h, --help Print help information
1436 /// -V, --version Print version information
1437 /// ```
1438 /// [option]: Arg::takes_value()
1439 /// [positional]: Arg::index()
1440 /// [`Arg::takes_value(true)`]: Arg::takes_value()
1441 #[inline]
1442 #[must_use]
value_name(self, name: &'help str) -> Self1443 pub fn value_name(self, name: &'help str) -> Self {
1444 self.value_names(&[name])
1445 }
1446
1447 /// Placeholders for the argument's values in the help message / usage.
1448 ///
1449 /// These names are cosmetic only, used for help and usage strings only. The names are **not**
1450 /// used to access arguments. The values of the arguments are accessed in numeric order (i.e.
1451 /// if you specify two names `one` and `two` `one` will be the first matched value, `two` will
1452 /// be the second).
1453 ///
1454 /// This setting can be very helpful when describing the type of input the user should be
1455 /// using, such as `FILE`, `INTERFACE`, etc. Although not required, it's somewhat convention to
1456 /// use all capital letters for the value name.
1457 ///
1458 /// **Pro Tip:** It may help to use [`Arg::next_line_help(true)`] if there are long, or
1459 /// multiple value names in order to not throw off the help text alignment of all options.
1460 ///
1461 /// **NOTE:** implicitly sets [`Arg::takes_value(true)`] and [`Arg::multiple_values(true)`].
1462 ///
1463 /// # Examples
1464 ///
1465 /// ```rust
1466 /// # use clap::{Command, Arg};
1467 /// Arg::new("speed")
1468 /// .short('s')
1469 /// .value_names(&["fast", "slow"]);
1470 /// ```
1471 ///
1472 /// ```rust
1473 /// # use clap::{Command, Arg};
1474 /// let m = Command::new("prog")
1475 /// .arg(Arg::new("io")
1476 /// .long("io-files")
1477 /// .value_names(&["INFILE", "OUTFILE"]))
1478 /// .get_matches_from(vec![
1479 /// "prog", "--help"
1480 /// ]);
1481 /// ```
1482 ///
1483 /// Running the above program produces the following output
1484 ///
1485 /// ```text
1486 /// valnames
1487 ///
1488 /// USAGE:
1489 /// valnames [OPTIONS]
1490 ///
1491 /// OPTIONS:
1492 /// -h, --help Print help information
1493 /// --io-files <INFILE> <OUTFILE> Some help text
1494 /// -V, --version Print version information
1495 /// ```
1496 /// [`Arg::next_line_help(true)`]: Arg::next_line_help()
1497 /// [`Arg::number_of_values`]: Arg::number_of_values()
1498 /// [`Arg::takes_value(true)`]: Arg::takes_value()
1499 /// [`Arg::multiple_values(true)`]: Arg::multiple_values()
1500 #[must_use]
value_names(mut self, names: &[&'help str]) -> Self1501 pub fn value_names(mut self, names: &[&'help str]) -> Self {
1502 self.val_names = names.to_vec();
1503 self.takes_value(true)
1504 }
1505
1506 /// Provide the shell a hint about how to complete this argument.
1507 ///
1508 /// See [`ValueHint`][crate::ValueHint] for more information.
1509 ///
1510 /// **NOTE:** implicitly sets [`Arg::takes_value(true)`].
1511 ///
1512 /// For example, to take a username as argument:
1513 ///
1514 /// ```
1515 /// # use clap::{Arg, ValueHint};
1516 /// Arg::new("user")
1517 /// .short('u')
1518 /// .long("user")
1519 /// .value_hint(ValueHint::Username);
1520 /// ```
1521 ///
1522 /// To take a full command line and its arguments (for example, when writing a command wrapper):
1523 ///
1524 /// ```
1525 /// # use clap::{Command, Arg, ValueHint};
1526 /// Command::new("prog")
1527 /// .trailing_var_arg(true)
1528 /// .arg(
1529 /// Arg::new("command")
1530 /// .takes_value(true)
1531 /// .multiple_values(true)
1532 /// .value_hint(ValueHint::CommandWithArguments)
1533 /// );
1534 /// ```
1535 #[must_use]
value_hint(mut self, value_hint: ValueHint) -> Self1536 pub fn value_hint(mut self, value_hint: ValueHint) -> Self {
1537 self.value_hint = Some(value_hint);
1538 self.takes_value(true)
1539 }
1540
1541 /// Deprecated, replaced with [`Arg::value_parser(...)`]
1542 ///
1543 /// Derive: replace `#[clap(validator = ...)]` with `#[clap(value_parser = ...)]`
1544 ///
1545 /// Builder: replace `arg.validator(...)` with `arg.value_parser(...)` and `matches.value_of` with
1546 /// `matches.get_one::<T>` or `matches.values_of` with `matches.get_many::<T>`
1547 #[inline]
1548 #[must_use]
1549 #[cfg_attr(
1550 feature = "deprecated",
1551 deprecated(
1552 since = "3.2.0",
1553 note = "Replaced with `Arg::value_parser(...)`
1554
1555 Derive: replace `#[clap(validator = <fn>)]` with `#[clap(value_parser = <fn>)]`
1556
1557 Builder: replace `arg.validator(<fn>)` with `arg.value_parser(<fn>)` and `matches.value_of` with
1558 `matches.get_one::<T>` or `matches.values_of` with `matches.get_many::<T>`
1559 "
1560 )
1561 )]
validator<F, O, E>(mut self, mut f: F) -> Self where F: FnMut(&str) -> Result<O, E> + Send + 'help, E: Into<Box<dyn Error + Send + Sync + 'static>>,1562 pub fn validator<F, O, E>(mut self, mut f: F) -> Self
1563 where
1564 F: FnMut(&str) -> Result<O, E> + Send + 'help,
1565 E: Into<Box<dyn Error + Send + Sync + 'static>>,
1566 {
1567 self.validator = Some(Arc::new(Mutex::new(move |s: &str| {
1568 f(s).map(|_| ()).map_err(|e| e.into())
1569 })));
1570 self
1571 }
1572
1573 /// Deprecated, replaced with [`Arg::value_parser(...)`]
1574 #[must_use]
1575 #[cfg_attr(
1576 feature = "deprecated",
1577 deprecated(
1578 since = "3.2.0",
1579 note = "Replaced with `Arg::value_parser(...)`
1580
1581 Derive: replace `#[clap(validator = <fn>)]` with `#[clap(value_parser = <TypedValueParser>)]`
1582
1583 Builder: replace `arg.validator(<fn>)` with `arg.value_parser(<TypedValueParser>)` and `matches.value_of_os` with
1584 `matches.get_one::<T>` or `matches.values_of_os` with `matches.get_many::<T>`
1585 "
1586 )
1587 )]
validator_os<F, O, E>(mut self, mut f: F) -> Self where F: FnMut(&OsStr) -> Result<O, E> + Send + 'help, E: Into<Box<dyn Error + Send + Sync + 'static>>,1588 pub fn validator_os<F, O, E>(mut self, mut f: F) -> Self
1589 where
1590 F: FnMut(&OsStr) -> Result<O, E> + Send + 'help,
1591 E: Into<Box<dyn Error + Send + Sync + 'static>>,
1592 {
1593 self.validator_os = Some(Arc::new(Mutex::new(move |s: &OsStr| {
1594 f(s).map(|_| ()).map_err(|e| e.into())
1595 })));
1596 self
1597 }
1598
1599 /// Deprecated in [Issue #3743](https://github.com/clap-rs/clap/issues/3743), replaced with [`Arg::value_parser(...)`]
1600 ///
1601 /// Derive: replace `#[clap(validator_regex = ...)]` with `#[clap(value_parser = |s: &str| regex.is_match(s).then(|| s.to_owned()).ok_or_else(|| ...))]`
1602 ///
1603 /// Builder: replace `arg.validator_regex(...)` with `arg.value_parser(|s: &str| regex.is_match(s).then(|| s.to_owned()).ok_or_else(|| ...))`
1604 #[cfg_attr(
1605 feature = "deprecated",
1606 deprecated(
1607 since = "3.2.0",
1608 note = "Deprecated in Issue #3743; replaced with `Arg::value_parser(...)`
1609
1610 Derive: replace `#[clap(validator_regex = ...)]` with `#[clap(value_parser = |s: &str| regex.is_match(s).then(|| s.to_owned()).ok_or_else(|| ...))]`
1611
1612 Builder: replace `arg.validator_regex(...)` with `arg.value_parser(|s: &str| regex.is_match(s).then(|| s.to_owned()).ok_or_else(|| ...))`
1613 "
1614 )
1615 )]
1616 #[cfg(feature = "regex")]
1617 #[must_use]
validator_regex( self, regex: impl Into<RegexRef<'help>>, err_message: &'help str, ) -> Self1618 pub fn validator_regex(
1619 self,
1620 regex: impl Into<RegexRef<'help>>,
1621 err_message: &'help str,
1622 ) -> Self {
1623 let regex = regex.into();
1624 self.validator(move |s: &str| {
1625 if regex.is_match(s) {
1626 Ok(())
1627 } else {
1628 Err(err_message)
1629 }
1630 })
1631 }
1632
1633 /// Deprecated, replaced with [`Arg::value_parser(PossibleValuesParser::new(...))`]
1634 ///
1635 /// Derive: replace `#[clap(possible_value = <1>, possible_value = <2>, ...)]` with `#[clap(value_parser = [<1>, <2>])]`.
1636 /// If the field is not a `String`, instead do `#[clap(value_parser = PossibleValueParser::new([<1>, <2>]).map(T::from_str))]`
1637 ///
1638 /// Builder: replace `arg.possible_value(<1>).possible_value(<2>) with `arg.value_parser([<1>, <2>])`
1639 #[cfg_attr(
1640 feature = "deprecated",
1641 deprecated(
1642 since = "3.2.0",
1643 note = "Replaced with `Arg::value_parser(PossibleValuesParser::new(...)).takes_value(true)`
1644
1645 Derive: replace `#[clap(possible_value = <1>, possible_value = <2>, ...)]` with `#[clap(value_parser = [<1>, <2>])]`.
1646 If the field is not a `String`, instead do `#[clap(value_parser = PossibleValueParser::new([<1>, <2>]).map(T::from_str))]`
1647
1648 Builder: replace `arg.possible_value(<1>).possible_value(<2>) with `arg.value_parser([<1>, <2>])`
1649 "
1650 )
1651 )]
1652 #[must_use]
possible_value<T>(mut self, value: T) -> Self where T: Into<PossibleValue<'help>>,1653 pub fn possible_value<T>(mut self, value: T) -> Self
1654 where
1655 T: Into<PossibleValue<'help>>,
1656 {
1657 self.possible_vals.push(value.into());
1658 self.takes_value(true)
1659 }
1660
1661 /// Deprecated, replaced with [`Arg::value_parser(PossibleValuesParser::new(...))`]
1662 ///
1663 /// Derive: replace `#[clap(possible_values = [<1>, <2>])]` with `#[clap(value_parser = [<1>, <2>])]`.
1664 /// If the field is not a `String`, instead do `#[clap(value_parser = PossibleValueParser::new([<1>, <2>]).map(T::from_str))]`
1665 ///
1666 /// Builder: replace `arg.possible_values([<1>, <2>) with `arg.value_parser([<1>, <2>])`
1667 #[cfg_attr(
1668 feature = "deprecated",
1669 deprecated(
1670 since = "3.2.0",
1671 note = "Replaced with `Arg::value_parser(PossibleValuesParser::new(...)).takes_value(true)`
1672
1673 Derive: replace `#[clap(possible_values = [<1>, <2>])]` with `#[clap(value_parser = [<1>, <2>])]`.
1674 If the field is not a `String`, instead do `#[clap(value_parser = PossibleValueParser::new([<1>, <2>]).map(T::from_str))]`
1675
1676 Builder: replace `arg.possible_values([<1>, <2>) with `arg.value_parser([<1>, <2>])`
1677 "
1678 )
1679 )]
1680 #[must_use]
possible_values<I, T>(mut self, values: I) -> Self where I: IntoIterator<Item = T>, T: Into<PossibleValue<'help>>,1681 pub fn possible_values<I, T>(mut self, values: I) -> Self
1682 where
1683 I: IntoIterator<Item = T>,
1684 T: Into<PossibleValue<'help>>,
1685 {
1686 self.possible_vals
1687 .extend(values.into_iter().map(|value| value.into()));
1688 self.takes_value(true)
1689 }
1690
1691 /// Match values against [`Arg::possible_values`] without matching case.
1692 ///
1693 /// When other arguments are conditionally required based on the
1694 /// value of a case-insensitive argument, the equality check done
1695 /// by [`Arg::required_if_eq`], [`Arg::required_if_eq_any`], or
1696 /// [`Arg::required_if_eq_all`] is case-insensitive.
1697 ///
1698 ///
1699 /// **NOTE:** Setting this requires [`Arg::takes_value`]
1700 ///
1701 /// **NOTE:** To do unicode case folding, enable the `unicode` feature flag.
1702 ///
1703 /// # Examples
1704 ///
1705 /// ```rust
1706 /// # use clap::{Command, Arg};
1707 /// let m = Command::new("pv")
1708 /// .arg(Arg::new("option")
1709 /// .long("option")
1710 /// .takes_value(true)
1711 /// .ignore_case(true)
1712 /// .value_parser(["test123"]))
1713 /// .get_matches_from(vec![
1714 /// "pv", "--option", "TeSt123",
1715 /// ]);
1716 ///
1717 /// assert!(m.value_of("option").unwrap().eq_ignore_ascii_case("test123"));
1718 /// ```
1719 ///
1720 /// This setting also works when multiple values can be defined:
1721 ///
1722 /// ```rust
1723 /// # use clap::{Command, Arg};
1724 /// let m = Command::new("pv")
1725 /// .arg(Arg::new("option")
1726 /// .short('o')
1727 /// .long("option")
1728 /// .takes_value(true)
1729 /// .ignore_case(true)
1730 /// .multiple_values(true)
1731 /// .value_parser(["test123", "test321"]))
1732 /// .get_matches_from(vec![
1733 /// "pv", "--option", "TeSt123", "teST123", "tESt321"
1734 /// ]);
1735 ///
1736 /// let matched_vals = m.values_of("option").unwrap().collect::<Vec<_>>();
1737 /// assert_eq!(&*matched_vals, &["TeSt123", "teST123", "tESt321"]);
1738 /// ```
1739 #[inline]
1740 #[must_use]
ignore_case(self, yes: bool) -> Self1741 pub fn ignore_case(self, yes: bool) -> Self {
1742 if yes {
1743 self.setting(ArgSettings::IgnoreCase)
1744 } else {
1745 self.unset_setting(ArgSettings::IgnoreCase)
1746 }
1747 }
1748
1749 /// Allows values which start with a leading hyphen (`-`)
1750 ///
1751 /// **NOTE:** Setting this requires [`Arg::takes_value`]
1752 ///
1753 /// **WARNING**: Take caution when using this setting combined with
1754 /// [`Arg::multiple_values`], as this becomes ambiguous `$ prog --arg -- -- val`. All
1755 /// three `--, --, val` will be values when the user may have thought the second `--` would
1756 /// constitute the normal, "Only positional args follow" idiom. To fix this, consider using
1757 /// [`Arg::multiple_occurrences`] which only allows a single value at a time.
1758 ///
1759 /// **WARNING**: When building your CLIs, consider the effects of allowing leading hyphens and
1760 /// the user passing in a value that matches a valid short. For example, `prog -opt -F` where
1761 /// `-F` is supposed to be a value, yet `-F` is *also* a valid short for another arg.
1762 /// Care should be taken when designing these args. This is compounded by the ability to "stack"
1763 /// short args. I.e. if `-val` is supposed to be a value, but `-v`, `-a`, and `-l` are all valid
1764 /// shorts.
1765 ///
1766 /// # Examples
1767 ///
1768 /// ```rust
1769 /// # use clap::{Command, Arg};
1770 /// let m = Command::new("prog")
1771 /// .arg(Arg::new("pat")
1772 /// .takes_value(true)
1773 /// .allow_hyphen_values(true)
1774 /// .long("pattern"))
1775 /// .get_matches_from(vec![
1776 /// "prog", "--pattern", "-file"
1777 /// ]);
1778 ///
1779 /// assert_eq!(m.value_of("pat"), Some("-file"));
1780 /// ```
1781 ///
1782 /// Not setting `Arg::allow_hyphen_values(true)` and supplying a value which starts with a
1783 /// hyphen is an error.
1784 ///
1785 /// ```rust
1786 /// # use clap::{Command, Arg, ErrorKind};
1787 /// let res = Command::new("prog")
1788 /// .arg(Arg::new("pat")
1789 /// .takes_value(true)
1790 /// .long("pattern"))
1791 /// .try_get_matches_from(vec![
1792 /// "prog", "--pattern", "-file"
1793 /// ]);
1794 ///
1795 /// assert!(res.is_err());
1796 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
1797 /// ```
1798 /// [`Arg::number_of_values(1)`]: Arg::number_of_values()
1799 #[inline]
1800 #[must_use]
allow_hyphen_values(self, yes: bool) -> Self1801 pub fn allow_hyphen_values(self, yes: bool) -> Self {
1802 if yes {
1803 self.setting(ArgSettings::AllowHyphenValues)
1804 } else {
1805 self.unset_setting(ArgSettings::AllowHyphenValues)
1806 }
1807 }
1808
1809 /// Deprecated, replaced with [`value_parser`][Arg::value_parser]
1810 ///
1811 /// Derive: replace `#[clap(allow_invalid_utf8 = true)]` with `#[clap(action)]` (which opts-in to the
1812 /// new clap v4 behavior which gets the type via `value_parser!`)
1813 ///
1814 /// Builder: replace `arg.allow_invalid_utf8(true)` with `arg.value_parser(value_parser!(T))` where
1815 /// `T` is the type of interest, like `OsString` or `PathBuf`, and `matches.value_of_os` with
1816 /// `matches.get_one::<T>` or `matches.values_of_os` with `matches.get_many::<T>`
1817 #[inline]
1818 #[must_use]
1819 #[cfg_attr(
1820 feature = "deprecated",
1821 deprecated(
1822 since = "3.2.0",
1823 note = "Replaced with `value_parser`
1824
1825 Derive: replace `#[clap(allow_invalid_utf8 = true)]` with `#[clap(action)]` (which opts-in to the
1826 new clap v4 behavior which gets the type via `value_parser!`)
1827
1828 Builder: replace `arg.allow_invalid_utf8(true)` with `arg.value_parser(value_parser!(T))` where
1829 `T` is the type of interest, like `OsString` or `PathBuf`, and `matches.value_of_os` with
1830 `matches.get_one::<T>` or `matches.values_of_os` with `matches.get_many::<T>`
1831 "
1832 )
1833 )]
allow_invalid_utf8(self, yes: bool) -> Self1834 pub fn allow_invalid_utf8(self, yes: bool) -> Self {
1835 if yes {
1836 self.setting(ArgSettings::AllowInvalidUtf8)
1837 } else {
1838 self.unset_setting(ArgSettings::AllowInvalidUtf8)
1839 }
1840 }
1841
1842 /// Deprecated, replaced with [`Arg::value_parser(NonEmptyStringValueParser::new())`]
1843 ///
1844 /// Derive: replace `#[clap(forbid_empty_values = true)]` with `#[clap(value_parser = NonEmptyStringValueParser::new())]`
1845 ///
1846 /// Builder: replace `arg.forbid_empty_values(true)` with `arg.value_parser(NonEmptyStringValueParser::new())`
1847 #[inline]
1848 #[must_use]
1849 #[cfg_attr(
1850 feature = "deprecated",
1851 deprecated(
1852 since = "3.2.0",
1853 note = "Replaced with `Arg::value_parser(NonEmptyStringValueParser::new())`
1854
1855 Derive: replace `#[clap(forbid_empty_values = true)]` with `#[clap(value_parser = NonEmptyStringValueParser::new())]`
1856
1857 Builder: replace `arg.forbid_empty_values(true)` with `arg.value_parser(NonEmptyStringValueParser::new())`
1858 "
1859 )
1860 )]
forbid_empty_values(self, yes: bool) -> Self1861 pub fn forbid_empty_values(self, yes: bool) -> Self {
1862 if yes {
1863 self.setting(ArgSettings::ForbidEmptyValues)
1864 } else {
1865 self.unset_setting(ArgSettings::ForbidEmptyValues)
1866 }
1867 }
1868
1869 /// Requires that options use the `--option=val` syntax
1870 ///
1871 /// i.e. an equals between the option and associated value.
1872 ///
1873 /// **NOTE:** Setting this requires [`Arg::takes_value`]
1874 ///
1875 /// # Examples
1876 ///
1877 /// Setting `require_equals` requires that the option have an equals sign between
1878 /// it and the associated value.
1879 ///
1880 /// ```rust
1881 /// # use clap::{Command, Arg};
1882 /// let res = Command::new("prog")
1883 /// .arg(Arg::new("cfg")
1884 /// .takes_value(true)
1885 /// .require_equals(true)
1886 /// .long("config"))
1887 /// .try_get_matches_from(vec![
1888 /// "prog", "--config=file.conf"
1889 /// ]);
1890 ///
1891 /// assert!(res.is_ok());
1892 /// ```
1893 ///
1894 /// Setting `require_equals` and *not* supplying the equals will cause an
1895 /// error.
1896 ///
1897 /// ```rust
1898 /// # use clap::{Command, Arg, ErrorKind};
1899 /// let res = Command::new("prog")
1900 /// .arg(Arg::new("cfg")
1901 /// .takes_value(true)
1902 /// .require_equals(true)
1903 /// .long("config"))
1904 /// .try_get_matches_from(vec![
1905 /// "prog", "--config", "file.conf"
1906 /// ]);
1907 ///
1908 /// assert!(res.is_err());
1909 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::NoEquals);
1910 /// ```
1911 #[inline]
1912 #[must_use]
require_equals(self, yes: bool) -> Self1913 pub fn require_equals(self, yes: bool) -> Self {
1914 if yes {
1915 self.setting(ArgSettings::RequireEquals)
1916 } else {
1917 self.unset_setting(ArgSettings::RequireEquals)
1918 }
1919 }
1920
1921 /// Specifies that an argument should allow grouping of multiple values via a
1922 /// delimiter.
1923 ///
1924 /// i.e. should `--option=val1,val2,val3` be parsed as three values (`val1`, `val2`,
1925 /// and `val3`) or as a single value (`val1,val2,val3`). Defaults to using `,` (comma) as the
1926 /// value delimiter for all arguments that accept values (options and positional arguments)
1927 ///
1928 /// **NOTE:** When this setting is used, it will default [`Arg::value_delimiter`]
1929 /// to the comma `,`.
1930 ///
1931 /// **NOTE:** Implicitly sets [`Arg::takes_value`]
1932 ///
1933 /// # Examples
1934 ///
1935 /// The following example shows the default behavior.
1936 ///
1937 /// ```rust
1938 /// # use clap::{Command, Arg};
1939 /// let delims = Command::new("prog")
1940 /// .arg(Arg::new("option")
1941 /// .long("option")
1942 /// .use_value_delimiter(true)
1943 /// .takes_value(true))
1944 /// .get_matches_from(vec![
1945 /// "prog", "--option=val1,val2,val3",
1946 /// ]);
1947 ///
1948 /// assert!(delims.contains_id("option"));
1949 /// assert_eq!(delims.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
1950 /// ```
1951 /// The next example shows the difference when turning delimiters off. This is the default
1952 /// behavior
1953 ///
1954 /// ```rust
1955 /// # use clap::{Command, Arg};
1956 /// let nodelims = Command::new("prog")
1957 /// .arg(Arg::new("option")
1958 /// .long("option")
1959 /// .takes_value(true))
1960 /// .get_matches_from(vec![
1961 /// "prog", "--option=val1,val2,val3",
1962 /// ]);
1963 ///
1964 /// assert!(nodelims.contains_id("option"));
1965 /// assert_eq!(nodelims.value_of("option").unwrap(), "val1,val2,val3");
1966 /// ```
1967 /// [`Arg::value_delimiter`]: Arg::value_delimiter()
1968 #[inline]
1969 #[must_use]
use_value_delimiter(mut self, yes: bool) -> Self1970 pub fn use_value_delimiter(mut self, yes: bool) -> Self {
1971 if yes {
1972 if self.val_delim.is_none() {
1973 self.val_delim = Some(',');
1974 }
1975 self.takes_value(true)
1976 .setting(ArgSettings::UseValueDelimiter)
1977 } else {
1978 self.val_delim = None;
1979 self.unset_setting(ArgSettings::UseValueDelimiter)
1980 }
1981 }
1982
1983 /// Deprecated, replaced with [`Arg::use_value_delimiter`]
1984 ///
1985 /// Derive: replace `#[clap(use_delimiter = true)]` with `#[clap(use_value_delimiter = true)]`
1986 ///
1987 /// Builder: replace `arg.use_delimiter(true)` with `arg.use_value_delimiter(true)`
1988 #[inline]
1989 #[must_use]
1990 #[cfg_attr(
1991 feature = "deprecated",
1992 deprecated(
1993 since = "3.1.0",
1994 note = "Replaced with `Arg::use_value_delimiter`
1995
1996 Derive: replace `#[clap(use_delimiter = true)]` with `#[clap(use_value_delimiter = true)]`
1997
1998 Builder: replace `arg.use_delimiter(true)` with `arg.use_value_delimiter(true)`
1999 "
2000 )
2001 )]
use_delimiter(self, yes: bool) -> Self2002 pub fn use_delimiter(self, yes: bool) -> Self {
2003 self.use_value_delimiter(yes)
2004 }
2005
2006 /// Separator between the arguments values, defaults to `,` (comma).
2007 ///
2008 /// **NOTE:** implicitly sets [`Arg::use_value_delimiter(true)`]
2009 ///
2010 /// **NOTE:** implicitly sets [`Arg::takes_value(true)`]
2011 ///
2012 /// # Examples
2013 ///
2014 /// ```rust
2015 /// # use clap::{Command, Arg};
2016 /// let m = Command::new("prog")
2017 /// .arg(Arg::new("config")
2018 /// .short('c')
2019 /// .long("config")
2020 /// .value_delimiter(';'))
2021 /// .get_matches_from(vec![
2022 /// "prog", "--config=val1;val2;val3"
2023 /// ]);
2024 ///
2025 /// assert_eq!(m.values_of("config").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"])
2026 /// ```
2027 /// [`Arg::use_value_delimiter(true)`]: Arg::use_value_delimiter()
2028 /// [`Arg::takes_value(true)`]: Arg::takes_value()
2029 #[inline]
2030 #[must_use]
value_delimiter(mut self, d: char) -> Self2031 pub fn value_delimiter(mut self, d: char) -> Self {
2032 self.val_delim = Some(d);
2033 self.takes_value(true).use_value_delimiter(true)
2034 }
2035
2036 /// Specifies that *multiple values* may only be set using the delimiter.
2037 ///
2038 /// This means if an option is encountered, and no delimiter is found, it is assumed that no
2039 /// additional values for that option follow. This is unlike the default, where it is generally
2040 /// assumed that more values will follow regardless of whether or not a delimiter is used.
2041 ///
2042 /// **NOTE:** The default is `false`.
2043 ///
2044 /// **NOTE:** Setting this requires [`Arg::use_value_delimiter`] and
2045 /// [`Arg::takes_value`]
2046 ///
2047 /// **NOTE:** It's a good idea to inform the user that use of a delimiter is required, either
2048 /// through help text or other means.
2049 ///
2050 /// # Examples
2051 ///
2052 /// These examples demonstrate what happens when `require_delimiter(true)` is used. Notice
2053 /// everything works in this first example, as we use a delimiter, as expected.
2054 ///
2055 /// ```rust
2056 /// # use clap::{Command, Arg};
2057 /// let delims = Command::new("prog")
2058 /// .arg(Arg::new("opt")
2059 /// .short('o')
2060 /// .takes_value(true)
2061 /// .use_value_delimiter(true)
2062 /// .require_delimiter(true)
2063 /// .multiple_values(true))
2064 /// .get_matches_from(vec![
2065 /// "prog", "-o", "val1,val2,val3",
2066 /// ]);
2067 ///
2068 /// assert!(delims.contains_id("opt"));
2069 /// assert_eq!(delims.values_of("opt").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
2070 /// ```
2071 ///
2072 /// In this next example, we will *not* use a delimiter. Notice it's now an error.
2073 ///
2074 /// ```rust
2075 /// # use clap::{Command, Arg, ErrorKind};
2076 /// let res = Command::new("prog")
2077 /// .arg(Arg::new("opt")
2078 /// .short('o')
2079 /// .takes_value(true)
2080 /// .use_value_delimiter(true)
2081 /// .require_delimiter(true))
2082 /// .try_get_matches_from(vec![
2083 /// "prog", "-o", "val1", "val2", "val3",
2084 /// ]);
2085 ///
2086 /// assert!(res.is_err());
2087 /// let err = res.unwrap_err();
2088 /// assert_eq!(err.kind(), ErrorKind::UnknownArgument);
2089 /// ```
2090 ///
2091 /// What's happening is `-o` is getting `val1`, and because delimiters are required yet none
2092 /// were present, it stops parsing `-o`. At this point it reaches `val2` and because no
2093 /// positional arguments have been defined, it's an error of an unexpected argument.
2094 ///
2095 /// In this final example, we contrast the above with `clap`'s default behavior where the above
2096 /// is *not* an error.
2097 ///
2098 /// ```rust
2099 /// # use clap::{Command, Arg};
2100 /// let delims = Command::new("prog")
2101 /// .arg(Arg::new("opt")
2102 /// .short('o')
2103 /// .takes_value(true)
2104 /// .multiple_values(true))
2105 /// .get_matches_from(vec![
2106 /// "prog", "-o", "val1", "val2", "val3",
2107 /// ]);
2108 ///
2109 /// assert!(delims.contains_id("opt"));
2110 /// assert_eq!(delims.values_of("opt").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
2111 /// ```
2112 #[inline]
2113 #[must_use]
require_value_delimiter(self, yes: bool) -> Self2114 pub fn require_value_delimiter(self, yes: bool) -> Self {
2115 if yes {
2116 self.setting(ArgSettings::RequireDelimiter)
2117 } else {
2118 self.unset_setting(ArgSettings::RequireDelimiter)
2119 }
2120 }
2121
2122 /// Deprecated, replaced with [`Arg::require_value_delimiter`]
2123 ///
2124 /// Derive: replace `#[clap(require_delimiter = true)]` with `#[clap(require_value_delimiter = true)]`
2125 ///
2126 /// Builder: replace `arg.require_delimiter(true)` with `arg.require_value_delimiter(true)`
2127 #[inline]
2128 #[must_use]
2129 #[cfg_attr(
2130 feature = "deprecated",
2131 deprecated(
2132 since = "3.1.0",
2133 note = "Replaced with `Arg::require_value_delimiter`
2134
2135 Derive: replace `#[clap(require_delimiter = true)]` with `#[clap(require_value_delimiter = true)]`
2136
2137 Builder: replace `arg.require_delimiter(true)` with `arg.require_value_delimiter(true)`
2138 "
2139 )
2140 )]
require_delimiter(self, yes: bool) -> Self2141 pub fn require_delimiter(self, yes: bool) -> Self {
2142 self.require_value_delimiter(yes)
2143 }
2144
2145 /// Sentinel to **stop** parsing multiple values of a give argument.
2146 ///
2147 /// By default when
2148 /// one sets [`multiple_values(true)`] on an argument, clap will continue parsing values for that
2149 /// argument until it reaches another valid argument, or one of the other more specific settings
2150 /// for multiple values is used (such as [`min_values`], [`max_values`] or
2151 /// [`number_of_values`]).
2152 ///
2153 /// **NOTE:** This setting only applies to [options] and [positional arguments]
2154 ///
2155 /// **NOTE:** When the terminator is passed in on the command line, it is **not** stored as one
2156 /// of the values
2157 ///
2158 /// # Examples
2159 ///
2160 /// ```rust
2161 /// # use clap::{Command, Arg};
2162 /// Arg::new("vals")
2163 /// .takes_value(true)
2164 /// .multiple_values(true)
2165 /// .value_terminator(";")
2166 /// # ;
2167 /// ```
2168 ///
2169 /// The following example uses two arguments, a sequence of commands, and the location in which
2170 /// to perform them
2171 ///
2172 /// ```rust
2173 /// # use clap::{Command, Arg};
2174 /// let m = Command::new("prog")
2175 /// .arg(Arg::new("cmds")
2176 /// .takes_value(true)
2177 /// .multiple_values(true)
2178 /// .allow_hyphen_values(true)
2179 /// .value_terminator(";"))
2180 /// .arg(Arg::new("location"))
2181 /// .get_matches_from(vec![
2182 /// "prog", "find", "-type", "f", "-name", "special", ";", "/home/clap"
2183 /// ]);
2184 /// let cmds: Vec<_> = m.values_of("cmds").unwrap().collect();
2185 /// assert_eq!(&cmds, &["find", "-type", "f", "-name", "special"]);
2186 /// assert_eq!(m.value_of("location"), Some("/home/clap"));
2187 /// ```
2188 /// [options]: Arg::takes_value()
2189 /// [positional arguments]: Arg::index()
2190 /// [`multiple_values(true)`]: Arg::multiple_values()
2191 /// [`min_values`]: Arg::min_values()
2192 /// [`number_of_values`]: Arg::number_of_values()
2193 /// [`max_values`]: Arg::max_values()
2194 #[inline]
2195 #[must_use]
value_terminator(mut self, term: &'help str) -> Self2196 pub fn value_terminator(mut self, term: &'help str) -> Self {
2197 self.terminator = Some(term);
2198 self.takes_value(true)
2199 }
2200
2201 /// Consume all following arguments.
2202 ///
2203 /// Do not be parse them individually, but rather pass them in entirety.
2204 ///
2205 /// It is worth noting that setting this requires all values to come after a `--` to indicate
2206 /// they should all be captured. For example:
2207 ///
2208 /// ```text
2209 /// --foo something -- -v -v -v -b -b -b --baz -q -u -x
2210 /// ```
2211 ///
2212 /// Will result in everything after `--` to be considered one raw argument. This behavior
2213 /// may not be exactly what you are expecting and using [`crate::Command::trailing_var_arg`]
2214 /// may be more appropriate.
2215 ///
2216 /// **NOTE:** Implicitly sets [`Arg::takes_value(true)`] [`Arg::multiple_values(true)`],
2217 /// [`Arg::allow_hyphen_values(true)`], and [`Arg::last(true)`] when set to `true`.
2218 ///
2219 /// [`Arg::takes_value(true)`]: Arg::takes_value()
2220 /// [`Arg::multiple_values(true)`]: Arg::multiple_values()
2221 /// [`Arg::allow_hyphen_values(true)`]: Arg::allow_hyphen_values()
2222 /// [`Arg::last(true)`]: Arg::last()
2223 #[inline]
2224 #[must_use]
raw(self, yes: bool) -> Self2225 pub fn raw(self, yes: bool) -> Self {
2226 self.takes_value(yes)
2227 .multiple_values(yes)
2228 .allow_hyphen_values(yes)
2229 .last(yes)
2230 }
2231
2232 /// Value for the argument when not present.
2233 ///
2234 /// **NOTE:** If the user *does not* use this argument at runtime, [`ArgMatches::occurrences_of`]
2235 /// will return `0` even though the [`ArgMatches::value_of`] will return the default specified.
2236 ///
2237 /// **NOTE:** If the user *does not* use this argument at runtime [`ArgMatches::contains_id`] will
2238 /// still return `true`. If you wish to determine whether the argument was used at runtime or
2239 /// not, consider [`ArgMatches::value_source`][crate::ArgMatches::value_source].
2240 ///
2241 /// **NOTE:** This setting is perfectly compatible with [`Arg::default_value_if`] but slightly
2242 /// different. `Arg::default_value` *only* takes effect when the user has not provided this arg
2243 /// at runtime. `Arg::default_value_if` however only takes effect when the user has not provided
2244 /// a value at runtime **and** these other conditions are met as well. If you have set
2245 /// `Arg::default_value` and `Arg::default_value_if`, and the user **did not** provide this arg
2246 /// at runtime, nor were the conditions met for `Arg::default_value_if`, the `Arg::default_value`
2247 /// will be applied.
2248 ///
2249 /// **NOTE:** This implicitly sets [`Arg::takes_value(true)`].
2250 ///
2251 /// # Examples
2252 ///
2253 /// First we use the default value without providing any value at runtime.
2254 ///
2255 /// ```rust
2256 /// # use clap::{Command, Arg, ValueSource};
2257 /// let m = Command::new("prog")
2258 /// .arg(Arg::new("opt")
2259 /// .long("myopt")
2260 /// .default_value("myval"))
2261 /// .get_matches_from(vec![
2262 /// "prog"
2263 /// ]);
2264 ///
2265 /// assert_eq!(m.value_of("opt"), Some("myval"));
2266 /// assert!(m.contains_id("opt"));
2267 /// assert_eq!(m.value_source("opt"), Some(ValueSource::DefaultValue));
2268 /// ```
2269 ///
2270 /// Next we provide a value at runtime to override the default.
2271 ///
2272 /// ```rust
2273 /// # use clap::{Command, Arg, ValueSource};
2274 /// let m = Command::new("prog")
2275 /// .arg(Arg::new("opt")
2276 /// .long("myopt")
2277 /// .default_value("myval"))
2278 /// .get_matches_from(vec![
2279 /// "prog", "--myopt=non_default"
2280 /// ]);
2281 ///
2282 /// assert_eq!(m.value_of("opt"), Some("non_default"));
2283 /// assert!(m.contains_id("opt"));
2284 /// assert_eq!(m.value_source("opt"), Some(ValueSource::CommandLine));
2285 /// ```
2286 /// [`ArgMatches::occurrences_of`]: crate::ArgMatches::occurrences_of()
2287 /// [`ArgMatches::value_of`]: crate::ArgMatches::value_of()
2288 /// [`Arg::takes_value(true)`]: Arg::takes_value()
2289 /// [`ArgMatches::contains_id`]: crate::ArgMatches::contains_id()
2290 /// [`Arg::default_value_if`]: Arg::default_value_if()
2291 #[inline]
2292 #[must_use]
default_value(self, val: &'help str) -> Self2293 pub fn default_value(self, val: &'help str) -> Self {
2294 self.default_values_os(&[OsStr::new(val)])
2295 }
2296
2297 /// Value for the argument when not present.
2298 ///
2299 /// See [`Arg::default_value`].
2300 ///
2301 /// [`Arg::default_value`]: Arg::default_value()
2302 /// [`OsStr`]: std::ffi::OsStr
2303 #[inline]
2304 #[must_use]
default_value_os(self, val: &'help OsStr) -> Self2305 pub fn default_value_os(self, val: &'help OsStr) -> Self {
2306 self.default_values_os(&[val])
2307 }
2308
2309 /// Value for the argument when not present.
2310 ///
2311 /// See [`Arg::default_value`].
2312 ///
2313 /// [`Arg::default_value`]: Arg::default_value()
2314 #[inline]
2315 #[must_use]
default_values(self, vals: &[&'help str]) -> Self2316 pub fn default_values(self, vals: &[&'help str]) -> Self {
2317 let vals_vec: Vec<_> = vals.iter().map(|val| OsStr::new(*val)).collect();
2318 self.default_values_os(&vals_vec[..])
2319 }
2320
2321 /// Value for the argument when not present.
2322 ///
2323 /// See [`Arg::default_values`].
2324 ///
2325 /// [`Arg::default_values`]: Arg::default_values()
2326 /// [`OsStr`]: std::ffi::OsStr
2327 #[inline]
2328 #[must_use]
default_values_os(mut self, vals: &[&'help OsStr]) -> Self2329 pub fn default_values_os(mut self, vals: &[&'help OsStr]) -> Self {
2330 self.default_vals = vals.to_vec();
2331 self.takes_value(true)
2332 }
2333
2334 /// Value for the argument when the flag is present but no value is specified.
2335 ///
2336 /// This configuration option is often used to give the user a shortcut and allow them to
2337 /// efficiently specify an option argument without requiring an explicitly value. The `--color`
2338 /// argument is a common example. By, supplying an default, such as `default_missing_value("always")`,
2339 /// the user can quickly just add `--color` to the command line to produce the desired color output.
2340 ///
2341 /// **NOTE:** using this configuration option requires the use of the `.min_values(0)` and the
2342 /// `.require_equals(true)` configuration option. These are required in order to unambiguously
2343 /// determine what, if any, value was supplied for the argument.
2344 ///
2345 /// # Examples
2346 ///
2347 /// For POSIX style `--color`:
2348 /// ```rust
2349 /// # use clap::{Command, Arg, ValueSource};
2350 /// fn cli() -> Command<'static> {
2351 /// Command::new("prog")
2352 /// .arg(Arg::new("color").long("color")
2353 /// .value_name("WHEN")
2354 /// .value_parser(["always", "auto", "never"])
2355 /// .default_value("auto")
2356 /// .min_values(0)
2357 /// .require_equals(true)
2358 /// .default_missing_value("always")
2359 /// .help("Specify WHEN to colorize output.")
2360 /// )
2361 /// }
2362 ///
2363 /// // first, we'll provide no arguments
2364 /// let m = cli().get_matches_from(vec![
2365 /// "prog"
2366 /// ]);
2367 /// assert_eq!(m.value_of("color"), Some("auto"));
2368 /// assert_eq!(m.value_source("color"), Some(ValueSource::DefaultValue));
2369 ///
2370 /// // next, we'll provide a runtime value to override the default (as usually done).
2371 /// let m = cli().get_matches_from(vec![
2372 /// "prog", "--color=never"
2373 /// ]);
2374 /// assert_eq!(m.value_of("color"), Some("never"));
2375 /// assert_eq!(m.value_source("color"), Some(ValueSource::CommandLine));
2376 ///
2377 /// // finally, we will use the shortcut and only provide the argument without a value.
2378 /// let m = cli().get_matches_from(vec![
2379 /// "prog", "--color"
2380 /// ]);
2381 /// assert_eq!(m.value_of("color"), Some("always"));
2382 /// assert_eq!(m.value_source("color"), Some(ValueSource::CommandLine));
2383 /// ```
2384 ///
2385 /// For bool literals:
2386 /// ```rust
2387 /// # use clap::{Command, Arg, ValueSource, value_parser};
2388 /// fn cli() -> Command<'static> {
2389 /// Command::new("prog")
2390 /// .arg(Arg::new("create").long("create")
2391 /// .value_name("BOOL")
2392 /// .value_parser(value_parser!(bool))
2393 /// .min_values(0)
2394 /// .require_equals(true)
2395 /// .default_missing_value("true")
2396 /// )
2397 /// }
2398 ///
2399 /// // first, we'll provide no arguments
2400 /// let m = cli().get_matches_from(vec![
2401 /// "prog"
2402 /// ]);
2403 /// assert_eq!(m.get_one::<bool>("create").copied(), None);
2404 ///
2405 /// // next, we'll provide a runtime value to override the default (as usually done).
2406 /// let m = cli().get_matches_from(vec![
2407 /// "prog", "--create=false"
2408 /// ]);
2409 /// assert_eq!(m.get_one::<bool>("create").copied(), Some(false));
2410 /// assert_eq!(m.value_source("create"), Some(ValueSource::CommandLine));
2411 ///
2412 /// // finally, we will use the shortcut and only provide the argument without a value.
2413 /// let m = cli().get_matches_from(vec![
2414 /// "prog", "--create"
2415 /// ]);
2416 /// assert_eq!(m.get_one::<bool>("create").copied(), Some(true));
2417 /// assert_eq!(m.value_source("create"), Some(ValueSource::CommandLine));
2418 /// ```
2419 ///
2420 /// [`ArgMatches::value_of`]: ArgMatches::value_of()
2421 /// [`Arg::takes_value(true)`]: Arg::takes_value()
2422 /// [`Arg::default_value`]: Arg::default_value()
2423 #[inline]
2424 #[must_use]
default_missing_value(self, val: &'help str) -> Self2425 pub fn default_missing_value(self, val: &'help str) -> Self {
2426 self.default_missing_values_os(&[OsStr::new(val)])
2427 }
2428
2429 /// Value for the argument when the flag is present but no value is specified.
2430 ///
2431 /// See [`Arg::default_missing_value`].
2432 ///
2433 /// [`Arg::default_missing_value`]: Arg::default_missing_value()
2434 /// [`OsStr`]: std::ffi::OsStr
2435 #[inline]
2436 #[must_use]
default_missing_value_os(self, val: &'help OsStr) -> Self2437 pub fn default_missing_value_os(self, val: &'help OsStr) -> Self {
2438 self.default_missing_values_os(&[val])
2439 }
2440
2441 /// Value for the argument when the flag is present but no value is specified.
2442 ///
2443 /// See [`Arg::default_missing_value`].
2444 ///
2445 /// [`Arg::default_missing_value`]: Arg::default_missing_value()
2446 #[inline]
2447 #[must_use]
default_missing_values(self, vals: &[&'help str]) -> Self2448 pub fn default_missing_values(self, vals: &[&'help str]) -> Self {
2449 let vals_vec: Vec<_> = vals.iter().map(|val| OsStr::new(*val)).collect();
2450 self.default_missing_values_os(&vals_vec[..])
2451 }
2452
2453 /// Value for the argument when the flag is present but no value is specified.
2454 ///
2455 /// See [`Arg::default_missing_values`].
2456 ///
2457 /// [`Arg::default_missing_values`]: Arg::default_missing_values()
2458 /// [`OsStr`]: std::ffi::OsStr
2459 #[inline]
2460 #[must_use]
default_missing_values_os(mut self, vals: &[&'help OsStr]) -> Self2461 pub fn default_missing_values_os(mut self, vals: &[&'help OsStr]) -> Self {
2462 self.default_missing_vals = vals.to_vec();
2463 self.takes_value(true)
2464 }
2465
2466 /// Read from `name` environment variable when argument is not present.
2467 ///
2468 /// If it is not present in the environment, then default
2469 /// rules will apply.
2470 ///
2471 /// If user sets the argument in the environment:
2472 /// - When [`Arg::takes_value(true)`] is not set, the flag is considered raised.
2473 /// - When [`Arg::takes_value(true)`] is set, [`ArgMatches::value_of`] will
2474 /// return value of the environment variable.
2475 ///
2476 /// If user doesn't set the argument in the environment:
2477 /// - When [`Arg::takes_value(true)`] is not set, the flag is considered off.
2478 /// - When [`Arg::takes_value(true)`] is set, [`ArgMatches::value_of`] will
2479 /// return the default specified.
2480 ///
2481 /// # Examples
2482 ///
2483 /// In this example, we show the variable coming from the environment:
2484 ///
2485 /// ```rust
2486 /// # use std::env;
2487 /// # use clap::{Command, Arg};
2488 ///
2489 /// env::set_var("MY_FLAG", "env");
2490 ///
2491 /// let m = Command::new("prog")
2492 /// .arg(Arg::new("flag")
2493 /// .long("flag")
2494 /// .env("MY_FLAG")
2495 /// .takes_value(true))
2496 /// .get_matches_from(vec![
2497 /// "prog"
2498 /// ]);
2499 ///
2500 /// assert_eq!(m.value_of("flag"), Some("env"));
2501 /// ```
2502 ///
2503 /// In this example, because [`Arg::takes_value(false)`] (by default),
2504 /// `prog` is a flag that accepts an optional, case-insensitive boolean literal.
2505 /// A `false` literal is `n`, `no`, `f`, `false`, `off` or `0`.
2506 /// An absent environment variable will also be considered as `false`.
2507 /// Anything else will considered as `true`.
2508 ///
2509 /// ```rust
2510 /// # use std::env;
2511 /// # use clap::{Command, Arg};
2512 ///
2513 /// env::set_var("TRUE_FLAG", "true");
2514 /// env::set_var("FALSE_FLAG", "0");
2515 ///
2516 /// let m = Command::new("prog")
2517 /// .arg(Arg::new("true_flag")
2518 /// .long("true_flag")
2519 /// .env("TRUE_FLAG"))
2520 /// .arg(Arg::new("false_flag")
2521 /// .long("false_flag")
2522 /// .env("FALSE_FLAG"))
2523 /// .arg(Arg::new("absent_flag")
2524 /// .long("absent_flag")
2525 /// .env("ABSENT_FLAG"))
2526 /// .get_matches_from(vec![
2527 /// "prog"
2528 /// ]);
2529 ///
2530 /// assert!(m.is_present("true_flag"));
2531 /// assert_eq!(m.value_of("true_flag"), None);
2532 /// assert!(!m.is_present("false_flag"));
2533 /// assert!(!m.is_present("absent_flag"));
2534 /// ```
2535 ///
2536 /// In this example, we show the variable coming from an option on the CLI:
2537 ///
2538 /// ```rust
2539 /// # use std::env;
2540 /// # use clap::{Command, Arg};
2541 ///
2542 /// env::set_var("MY_FLAG", "env");
2543 ///
2544 /// let m = Command::new("prog")
2545 /// .arg(Arg::new("flag")
2546 /// .long("flag")
2547 /// .env("MY_FLAG")
2548 /// .takes_value(true))
2549 /// .get_matches_from(vec![
2550 /// "prog", "--flag", "opt"
2551 /// ]);
2552 ///
2553 /// assert_eq!(m.value_of("flag"), Some("opt"));
2554 /// ```
2555 ///
2556 /// In this example, we show the variable coming from the environment even with the
2557 /// presence of a default:
2558 ///
2559 /// ```rust
2560 /// # use std::env;
2561 /// # use clap::{Command, Arg};
2562 ///
2563 /// env::set_var("MY_FLAG", "env");
2564 ///
2565 /// let m = Command::new("prog")
2566 /// .arg(Arg::new("flag")
2567 /// .long("flag")
2568 /// .env("MY_FLAG")
2569 /// .takes_value(true)
2570 /// .default_value("default"))
2571 /// .get_matches_from(vec![
2572 /// "prog"
2573 /// ]);
2574 ///
2575 /// assert_eq!(m.value_of("flag"), Some("env"));
2576 /// ```
2577 ///
2578 /// In this example, we show the use of multiple values in a single environment variable:
2579 ///
2580 /// ```rust
2581 /// # use std::env;
2582 /// # use clap::{Command, Arg};
2583 ///
2584 /// env::set_var("MY_FLAG_MULTI", "env1,env2");
2585 ///
2586 /// let m = Command::new("prog")
2587 /// .arg(Arg::new("flag")
2588 /// .long("flag")
2589 /// .env("MY_FLAG_MULTI")
2590 /// .takes_value(true)
2591 /// .multiple_values(true)
2592 /// .use_value_delimiter(true))
2593 /// .get_matches_from(vec![
2594 /// "prog"
2595 /// ]);
2596 ///
2597 /// assert_eq!(m.values_of("flag").unwrap().collect::<Vec<_>>(), vec!["env1", "env2"]);
2598 /// ```
2599 /// [`ArgMatches::value_of`]: crate::ArgMatches::value_of()
2600 /// [`Arg::takes_value(true)`]: Arg::takes_value()
2601 /// [`Arg::use_value_delimiter(true)`]: Arg::use_value_delimiter()
2602 #[cfg(feature = "env")]
2603 #[inline]
2604 #[must_use]
env(self, name: &'help str) -> Self2605 pub fn env(self, name: &'help str) -> Self {
2606 self.env_os(OsStr::new(name))
2607 }
2608
2609 /// Read from `name` environment variable when argument is not present.
2610 ///
2611 /// See [`Arg::env`].
2612 #[cfg(feature = "env")]
2613 #[inline]
2614 #[must_use]
env_os(mut self, name: &'help OsStr) -> Self2615 pub fn env_os(mut self, name: &'help OsStr) -> Self {
2616 self.env = Some((name, env::var_os(name)));
2617 self
2618 }
2619 }
2620
2621 /// # Help
2622 impl<'help> Arg<'help> {
2623 /// Sets the description of the argument for short help (`-h`).
2624 ///
2625 /// Typically, this is a short (one line) description of the arg.
2626 ///
2627 /// If [`Arg::long_help`] is not specified, this message will be displayed for `--help`.
2628 ///
2629 /// **NOTE:** Only `Arg::help` is used in completion script generation in order to be concise
2630 ///
2631 /// # Examples
2632 ///
2633 /// Any valid UTF-8 is allowed in the help text. The one exception is when one wishes to
2634 /// include a newline in the help text and have the following text be properly aligned with all
2635 /// the other help text.
2636 ///
2637 /// Setting `help` displays a short message to the side of the argument when the user passes
2638 /// `-h` or `--help` (by default).
2639 ///
2640 /// ```rust
2641 /// # use clap::{Command, Arg};
2642 /// let m = Command::new("prog")
2643 /// .arg(Arg::new("cfg")
2644 /// .long("config")
2645 /// .help("Some help text describing the --config arg"))
2646 /// .get_matches_from(vec![
2647 /// "prog", "--help"
2648 /// ]);
2649 /// ```
2650 ///
2651 /// The above example displays
2652 ///
2653 /// ```notrust
2654 /// helptest
2655 ///
2656 /// USAGE:
2657 /// helptest [OPTIONS]
2658 ///
2659 /// OPTIONS:
2660 /// --config Some help text describing the --config arg
2661 /// -h, --help Print help information
2662 /// -V, --version Print version information
2663 /// ```
2664 /// [`Arg::long_help`]: Arg::long_help()
2665 #[inline]
2666 #[must_use]
help(mut self, h: impl Into<Option<&'help str>>) -> Self2667 pub fn help(mut self, h: impl Into<Option<&'help str>>) -> Self {
2668 self.help = h.into();
2669 self
2670 }
2671
2672 /// Sets the description of the argument for long help (`--help`).
2673 ///
2674 /// Typically this a more detailed (multi-line) message
2675 /// that describes the arg.
2676 ///
2677 /// If [`Arg::help`] is not specified, this message will be displayed for `-h`.
2678 ///
2679 /// **NOTE:** Only [`Arg::help`] is used in completion script generation in order to be concise
2680 ///
2681 /// # Examples
2682 ///
2683 /// Any valid UTF-8 is allowed in the help text. The one exception is when one wishes to
2684 /// include a newline in the help text and have the following text be properly aligned with all
2685 /// the other help text.
2686 ///
2687 /// Setting `help` displays a short message to the side of the argument when the user passes
2688 /// `-h` or `--help` (by default).
2689 ///
2690 /// ```rust
2691 /// # use clap::{Command, Arg};
2692 /// let m = Command::new("prog")
2693 /// .arg(Arg::new("cfg")
2694 /// .long("config")
2695 /// .long_help(
2696 /// "The config file used by the myprog must be in JSON format
2697 /// with only valid keys and may not contain other nonsense
2698 /// that cannot be read by this program. Obviously I'm going on
2699 /// and on, so I'll stop now."))
2700 /// .get_matches_from(vec![
2701 /// "prog", "--help"
2702 /// ]);
2703 /// ```
2704 ///
2705 /// The above example displays
2706 ///
2707 /// ```text
2708 /// prog
2709 ///
2710 /// USAGE:
2711 /// prog [OPTIONS]
2712 ///
2713 /// OPTIONS:
2714 /// --config
2715 /// The config file used by the myprog must be in JSON format
2716 /// with only valid keys and may not contain other nonsense
2717 /// that cannot be read by this program. Obviously I'm going on
2718 /// and on, so I'll stop now.
2719 ///
2720 /// -h, --help
2721 /// Print help information
2722 ///
2723 /// -V, --version
2724 /// Print version information
2725 /// ```
2726 /// [`Arg::help`]: Arg::help()
2727 #[inline]
2728 #[must_use]
long_help(mut self, h: impl Into<Option<&'help str>>) -> Self2729 pub fn long_help(mut self, h: impl Into<Option<&'help str>>) -> Self {
2730 self.long_help = h.into();
2731 self
2732 }
2733
2734 /// Allows custom ordering of args within the help message.
2735 ///
2736 /// Args with a lower value will be displayed first in the help message. This is helpful when
2737 /// one would like to emphasise frequently used args, or prioritize those towards the top of
2738 /// the list. Args with duplicate display orders will be displayed in alphabetical order.
2739 ///
2740 /// **NOTE:** The default is 999 for all arguments.
2741 ///
2742 /// **NOTE:** This setting is ignored for [positional arguments] which are always displayed in
2743 /// [index] order.
2744 ///
2745 /// # Examples
2746 ///
2747 /// ```rust
2748 /// # use clap::{Command, Arg};
2749 /// let m = Command::new("prog")
2750 /// .arg(Arg::new("a") // Typically args are grouped alphabetically by name.
2751 /// // Args without a display_order have a value of 999 and are
2752 /// // displayed alphabetically with all other 999 valued args.
2753 /// .long("long-option")
2754 /// .short('o')
2755 /// .takes_value(true)
2756 /// .help("Some help and text"))
2757 /// .arg(Arg::new("b")
2758 /// .long("other-option")
2759 /// .short('O')
2760 /// .takes_value(true)
2761 /// .display_order(1) // In order to force this arg to appear *first*
2762 /// // all we have to do is give it a value lower than 999.
2763 /// // Any other args with a value of 1 will be displayed
2764 /// // alphabetically with this one...then 2 values, then 3, etc.
2765 /// .help("I should be first!"))
2766 /// .get_matches_from(vec![
2767 /// "prog", "--help"
2768 /// ]);
2769 /// ```
2770 ///
2771 /// The above example displays the following help message
2772 ///
2773 /// ```text
2774 /// cust-ord
2775 ///
2776 /// USAGE:
2777 /// cust-ord [OPTIONS]
2778 ///
2779 /// OPTIONS:
2780 /// -h, --help Print help information
2781 /// -V, --version Print version information
2782 /// -O, --other-option <b> I should be first!
2783 /// -o, --long-option <a> Some help and text
2784 /// ```
2785 /// [positional arguments]: Arg::index()
2786 /// [index]: Arg::index()
2787 #[inline]
2788 #[must_use]
display_order(mut self, ord: usize) -> Self2789 pub fn display_order(mut self, ord: usize) -> Self {
2790 self.disp_ord.set_explicit(ord);
2791 self
2792 }
2793
2794 /// Override the [current] help section.
2795 ///
2796 /// [current]: crate::Command::help_heading
2797 #[inline]
2798 #[must_use]
help_heading<O>(mut self, heading: O) -> Self where O: Into<Option<&'help str>>,2799 pub fn help_heading<O>(mut self, heading: O) -> Self
2800 where
2801 O: Into<Option<&'help str>>,
2802 {
2803 self.help_heading = Some(heading.into());
2804 self
2805 }
2806
2807 /// Render the [help][Arg::help] on the line after the argument.
2808 ///
2809 /// This can be helpful for arguments with very long or complex help messages.
2810 /// This can also be helpful for arguments with very long flag names, or many/long value names.
2811 ///
2812 /// **NOTE:** To apply this setting to all arguments and subcommands, consider using
2813 /// [`crate::Command::next_line_help`]
2814 ///
2815 /// # Examples
2816 ///
2817 /// ```rust
2818 /// # use clap::{Command, Arg};
2819 /// let m = Command::new("prog")
2820 /// .arg(Arg::new("opt")
2821 /// .long("long-option-flag")
2822 /// .short('o')
2823 /// .takes_value(true)
2824 /// .next_line_help(true)
2825 /// .value_names(&["value1", "value2"])
2826 /// .help("Some really long help and complex\n\
2827 /// help that makes more sense to be\n\
2828 /// on a line after the option"))
2829 /// .get_matches_from(vec![
2830 /// "prog", "--help"
2831 /// ]);
2832 /// ```
2833 ///
2834 /// The above example displays the following help message
2835 ///
2836 /// ```text
2837 /// nlh
2838 ///
2839 /// USAGE:
2840 /// nlh [OPTIONS]
2841 ///
2842 /// OPTIONS:
2843 /// -h, --help Print help information
2844 /// -V, --version Print version information
2845 /// -o, --long-option-flag <value1> <value2>
2846 /// Some really long help and complex
2847 /// help that makes more sense to be
2848 /// on a line after the option
2849 /// ```
2850 #[inline]
2851 #[must_use]
next_line_help(self, yes: bool) -> Self2852 pub fn next_line_help(self, yes: bool) -> Self {
2853 if yes {
2854 self.setting(ArgSettings::NextLineHelp)
2855 } else {
2856 self.unset_setting(ArgSettings::NextLineHelp)
2857 }
2858 }
2859
2860 /// Do not display the argument in help message.
2861 ///
2862 /// **NOTE:** This does **not** hide the argument from usage strings on error
2863 ///
2864 /// # Examples
2865 ///
2866 /// Setting `Hidden` will hide the argument when displaying help text
2867 ///
2868 /// ```rust
2869 /// # use clap::{Command, Arg};
2870 /// let m = Command::new("prog")
2871 /// .arg(Arg::new("cfg")
2872 /// .long("config")
2873 /// .hide(true)
2874 /// .help("Some help text describing the --config arg"))
2875 /// .get_matches_from(vec![
2876 /// "prog", "--help"
2877 /// ]);
2878 /// ```
2879 ///
2880 /// The above example displays
2881 ///
2882 /// ```text
2883 /// helptest
2884 ///
2885 /// USAGE:
2886 /// helptest [OPTIONS]
2887 ///
2888 /// OPTIONS:
2889 /// -h, --help Print help information
2890 /// -V, --version Print version information
2891 /// ```
2892 #[inline]
2893 #[must_use]
hide(self, yes: bool) -> Self2894 pub fn hide(self, yes: bool) -> Self {
2895 if yes {
2896 self.setting(ArgSettings::Hidden)
2897 } else {
2898 self.unset_setting(ArgSettings::Hidden)
2899 }
2900 }
2901
2902 /// Do not display the [possible values][crate::builder::ValueParser::possible_values] in the help message.
2903 ///
2904 /// This is useful for args with many values, or ones which are explained elsewhere in the
2905 /// help text.
2906 ///
2907 /// **NOTE:** Setting this requires [`Arg::takes_value`]
2908 ///
2909 /// To set this for all arguments, see
2910 /// [`Command::hide_possible_values`][crate::Command::hide_possible_values].
2911 ///
2912 /// # Examples
2913 ///
2914 /// ```rust
2915 /// # use clap::{Command, Arg};
2916 /// let m = Command::new("prog")
2917 /// .arg(Arg::new("mode")
2918 /// .long("mode")
2919 /// .value_parser(["fast", "slow"])
2920 /// .takes_value(true)
2921 /// .hide_possible_values(true));
2922 /// ```
2923 /// If we were to run the above program with `--help` the `[values: fast, slow]` portion of
2924 /// the help text would be omitted.
2925 #[inline]
2926 #[must_use]
hide_possible_values(self, yes: bool) -> Self2927 pub fn hide_possible_values(self, yes: bool) -> Self {
2928 if yes {
2929 self.setting(ArgSettings::HidePossibleValues)
2930 } else {
2931 self.unset_setting(ArgSettings::HidePossibleValues)
2932 }
2933 }
2934
2935 /// Do not display the default value of the argument in the help message.
2936 ///
2937 /// This is useful when default behavior of an arg is explained elsewhere in the help text.
2938 ///
2939 /// **NOTE:** Setting this requires [`Arg::takes_value`]
2940 ///
2941 /// # Examples
2942 ///
2943 /// ```rust
2944 /// # use clap::{Command, Arg};
2945 /// let m = Command::new("connect")
2946 /// .arg(Arg::new("host")
2947 /// .long("host")
2948 /// .default_value("localhost")
2949 /// .takes_value(true)
2950 /// .hide_default_value(true));
2951 ///
2952 /// ```
2953 ///
2954 /// If we were to run the above program with `--help` the `[default: localhost]` portion of
2955 /// the help text would be omitted.
2956 #[inline]
2957 #[must_use]
hide_default_value(self, yes: bool) -> Self2958 pub fn hide_default_value(self, yes: bool) -> Self {
2959 if yes {
2960 self.setting(ArgSettings::HideDefaultValue)
2961 } else {
2962 self.unset_setting(ArgSettings::HideDefaultValue)
2963 }
2964 }
2965
2966 /// Do not display in help the environment variable name.
2967 ///
2968 /// This is useful when the variable option is explained elsewhere in the help text.
2969 ///
2970 /// # Examples
2971 ///
2972 /// ```rust
2973 /// # use clap::{Command, Arg};
2974 /// let m = Command::new("prog")
2975 /// .arg(Arg::new("mode")
2976 /// .long("mode")
2977 /// .env("MODE")
2978 /// .takes_value(true)
2979 /// .hide_env(true));
2980 /// ```
2981 ///
2982 /// If we were to run the above program with `--help` the `[env: MODE]` portion of the help
2983 /// text would be omitted.
2984 #[cfg(feature = "env")]
2985 #[inline]
2986 #[must_use]
hide_env(self, yes: bool) -> Self2987 pub fn hide_env(self, yes: bool) -> Self {
2988 if yes {
2989 self.setting(ArgSettings::HideEnv)
2990 } else {
2991 self.unset_setting(ArgSettings::HideEnv)
2992 }
2993 }
2994
2995 /// Do not display in help any values inside the associated ENV variables for the argument.
2996 ///
2997 /// This is useful when ENV vars contain sensitive values.
2998 ///
2999 /// # Examples
3000 ///
3001 /// ```rust
3002 /// # use clap::{Command, Arg};
3003 /// let m = Command::new("connect")
3004 /// .arg(Arg::new("host")
3005 /// .long("host")
3006 /// .env("CONNECT")
3007 /// .takes_value(true)
3008 /// .hide_env_values(true));
3009 ///
3010 /// ```
3011 ///
3012 /// If we were to run the above program with `$ CONNECT=super_secret connect --help` the
3013 /// `[default: CONNECT=super_secret]` portion of the help text would be omitted.
3014 #[cfg(feature = "env")]
3015 #[inline]
3016 #[must_use]
hide_env_values(self, yes: bool) -> Self3017 pub fn hide_env_values(self, yes: bool) -> Self {
3018 if yes {
3019 self.setting(ArgSettings::HideEnvValues)
3020 } else {
3021 self.unset_setting(ArgSettings::HideEnvValues)
3022 }
3023 }
3024
3025 /// Hides an argument from short help (`-h`).
3026 ///
3027 /// **NOTE:** This does **not** hide the argument from usage strings on error
3028 ///
3029 /// **NOTE:** Setting this option will cause next-line-help output style to be used
3030 /// when long help (`--help`) is called.
3031 ///
3032 /// # Examples
3033 ///
3034 /// ```rust
3035 /// # use clap::{Command, Arg};
3036 /// Arg::new("debug")
3037 /// .hide_short_help(true);
3038 /// ```
3039 ///
3040 /// Setting `hide_short_help(true)` will hide the argument when displaying short help text
3041 ///
3042 /// ```rust
3043 /// # use clap::{Command, Arg};
3044 /// let m = Command::new("prog")
3045 /// .arg(Arg::new("cfg")
3046 /// .long("config")
3047 /// .hide_short_help(true)
3048 /// .help("Some help text describing the --config arg"))
3049 /// .get_matches_from(vec![
3050 /// "prog", "-h"
3051 /// ]);
3052 /// ```
3053 ///
3054 /// The above example displays
3055 ///
3056 /// ```text
3057 /// helptest
3058 ///
3059 /// USAGE:
3060 /// helptest [OPTIONS]
3061 ///
3062 /// OPTIONS:
3063 /// -h, --help Print help information
3064 /// -V, --version Print version information
3065 /// ```
3066 ///
3067 /// However, when --help is called
3068 ///
3069 /// ```rust
3070 /// # use clap::{Command, Arg};
3071 /// let m = Command::new("prog")
3072 /// .arg(Arg::new("cfg")
3073 /// .long("config")
3074 /// .hide_short_help(true)
3075 /// .help("Some help text describing the --config arg"))
3076 /// .get_matches_from(vec![
3077 /// "prog", "--help"
3078 /// ]);
3079 /// ```
3080 ///
3081 /// Then the following would be displayed
3082 ///
3083 /// ```text
3084 /// helptest
3085 ///
3086 /// USAGE:
3087 /// helptest [OPTIONS]
3088 ///
3089 /// OPTIONS:
3090 /// --config Some help text describing the --config arg
3091 /// -h, --help Print help information
3092 /// -V, --version Print version information
3093 /// ```
3094 #[inline]
3095 #[must_use]
hide_short_help(self, yes: bool) -> Self3096 pub fn hide_short_help(self, yes: bool) -> Self {
3097 if yes {
3098 self.setting(ArgSettings::HiddenShortHelp)
3099 } else {
3100 self.unset_setting(ArgSettings::HiddenShortHelp)
3101 }
3102 }
3103
3104 /// Hides an argument from long help (`--help`).
3105 ///
3106 /// **NOTE:** This does **not** hide the argument from usage strings on error
3107 ///
3108 /// **NOTE:** Setting this option will cause next-line-help output style to be used
3109 /// when long help (`--help`) is called.
3110 ///
3111 /// # Examples
3112 ///
3113 /// Setting `hide_long_help(true)` will hide the argument when displaying long help text
3114 ///
3115 /// ```rust
3116 /// # use clap::{Command, Arg};
3117 /// let m = Command::new("prog")
3118 /// .arg(Arg::new("cfg")
3119 /// .long("config")
3120 /// .hide_long_help(true)
3121 /// .help("Some help text describing the --config arg"))
3122 /// .get_matches_from(vec![
3123 /// "prog", "--help"
3124 /// ]);
3125 /// ```
3126 ///
3127 /// The above example displays
3128 ///
3129 /// ```text
3130 /// helptest
3131 ///
3132 /// USAGE:
3133 /// helptest [OPTIONS]
3134 ///
3135 /// OPTIONS:
3136 /// -h, --help Print help information
3137 /// -V, --version Print version information
3138 /// ```
3139 ///
3140 /// However, when -h is called
3141 ///
3142 /// ```rust
3143 /// # use clap::{Command, Arg};
3144 /// let m = Command::new("prog")
3145 /// .arg(Arg::new("cfg")
3146 /// .long("config")
3147 /// .hide_long_help(true)
3148 /// .help("Some help text describing the --config arg"))
3149 /// .get_matches_from(vec![
3150 /// "prog", "-h"
3151 /// ]);
3152 /// ```
3153 ///
3154 /// Then the following would be displayed
3155 ///
3156 /// ```text
3157 /// helptest
3158 ///
3159 /// USAGE:
3160 /// helptest [OPTIONS]
3161 ///
3162 /// OPTIONS:
3163 /// --config Some help text describing the --config arg
3164 /// -h, --help Print help information
3165 /// -V, --version Print version information
3166 /// ```
3167 #[inline]
3168 #[must_use]
hide_long_help(self, yes: bool) -> Self3169 pub fn hide_long_help(self, yes: bool) -> Self {
3170 if yes {
3171 self.setting(ArgSettings::HiddenLongHelp)
3172 } else {
3173 self.unset_setting(ArgSettings::HiddenLongHelp)
3174 }
3175 }
3176 }
3177
3178 /// # Advanced Argument Relations
3179 impl<'help> Arg<'help> {
3180 /// The name of the [`ArgGroup`] the argument belongs to.
3181 ///
3182 /// # Examples
3183 ///
3184 /// ```rust
3185 /// # use clap::{Command, Arg};
3186 /// Arg::new("debug")
3187 /// .long("debug")
3188 /// .group("mode")
3189 /// # ;
3190 /// ```
3191 ///
3192 /// Multiple arguments can be a member of a single group and then the group checked as if it
3193 /// was one of said arguments.
3194 ///
3195 /// ```rust
3196 /// # use clap::{Command, Arg};
3197 /// let m = Command::new("prog")
3198 /// .arg(Arg::new("debug")
3199 /// .long("debug")
3200 /// .group("mode"))
3201 /// .arg(Arg::new("verbose")
3202 /// .long("verbose")
3203 /// .group("mode"))
3204 /// .get_matches_from(vec![
3205 /// "prog", "--debug"
3206 /// ]);
3207 /// assert!(m.contains_id("mode"));
3208 /// ```
3209 ///
3210 /// [`ArgGroup`]: crate::ArgGroup
3211 #[must_use]
group<T: Key>(mut self, group_id: T) -> Self3212 pub fn group<T: Key>(mut self, group_id: T) -> Self {
3213 self.groups.push(group_id.into());
3214 self
3215 }
3216
3217 /// The names of [`ArgGroup`]'s the argument belongs to.
3218 ///
3219 /// # Examples
3220 ///
3221 /// ```rust
3222 /// # use clap::{Command, Arg};
3223 /// Arg::new("debug")
3224 /// .long("debug")
3225 /// .groups(&["mode", "verbosity"])
3226 /// # ;
3227 /// ```
3228 ///
3229 /// Arguments can be members of multiple groups and then the group checked as if it
3230 /// was one of said arguments.
3231 ///
3232 /// ```rust
3233 /// # use clap::{Command, Arg};
3234 /// let m = Command::new("prog")
3235 /// .arg(Arg::new("debug")
3236 /// .long("debug")
3237 /// .groups(&["mode", "verbosity"]))
3238 /// .arg(Arg::new("verbose")
3239 /// .long("verbose")
3240 /// .groups(&["mode", "verbosity"]))
3241 /// .get_matches_from(vec![
3242 /// "prog", "--debug"
3243 /// ]);
3244 /// assert!(m.contains_id("mode"));
3245 /// assert!(m.contains_id("verbosity"));
3246 /// ```
3247 ///
3248 /// [`ArgGroup`]: crate::ArgGroup
3249 #[must_use]
groups<T: Key>(mut self, group_ids: &[T]) -> Self3250 pub fn groups<T: Key>(mut self, group_ids: &[T]) -> Self {
3251 self.groups.extend(group_ids.iter().map(Id::from));
3252 self
3253 }
3254
3255 /// Specifies the value of the argument if `arg` has been used at runtime.
3256 ///
3257 /// If `val` is set to `None`, `arg` only needs to be present. If `val` is set to `"some-val"`
3258 /// then `arg` must be present at runtime **and** have the value `val`.
3259 ///
3260 /// If `default` is set to `None`, `default_value` will be removed.
3261 ///
3262 /// **NOTE:** This setting is perfectly compatible with [`Arg::default_value`] but slightly
3263 /// different. `Arg::default_value` *only* takes effect when the user has not provided this arg
3264 /// at runtime. This setting however only takes effect when the user has not provided a value at
3265 /// runtime **and** these other conditions are met as well. If you have set `Arg::default_value`
3266 /// and `Arg::default_value_if`, and the user **did not** provide this arg at runtime, nor were
3267 /// the conditions met for `Arg::default_value_if`, the `Arg::default_value` will be applied.
3268 ///
3269 /// **NOTE:** This implicitly sets [`Arg::takes_value(true)`].
3270 ///
3271 /// # Examples
3272 ///
3273 /// First we use the default value only if another arg is present at runtime.
3274 ///
3275 /// ```rust
3276 /// # use clap::{Command, Arg};
3277 /// let m = Command::new("prog")
3278 /// .arg(Arg::new("flag")
3279 /// .long("flag"))
3280 /// .arg(Arg::new("other")
3281 /// .long("other")
3282 /// .default_value_if("flag", None, Some("default")))
3283 /// .get_matches_from(vec![
3284 /// "prog", "--flag"
3285 /// ]);
3286 ///
3287 /// assert_eq!(m.value_of("other"), Some("default"));
3288 /// ```
3289 ///
3290 /// Next we run the same test, but without providing `--flag`.
3291 ///
3292 /// ```rust
3293 /// # use clap::{Command, Arg};
3294 /// let m = Command::new("prog")
3295 /// .arg(Arg::new("flag")
3296 /// .long("flag"))
3297 /// .arg(Arg::new("other")
3298 /// .long("other")
3299 /// .default_value_if("flag", None, Some("default")))
3300 /// .get_matches_from(vec![
3301 /// "prog"
3302 /// ]);
3303 ///
3304 /// assert_eq!(m.value_of("other"), None);
3305 /// ```
3306 ///
3307 /// Now lets only use the default value if `--opt` contains the value `special`.
3308 ///
3309 /// ```rust
3310 /// # use clap::{Command, Arg};
3311 /// let m = Command::new("prog")
3312 /// .arg(Arg::new("opt")
3313 /// .takes_value(true)
3314 /// .long("opt"))
3315 /// .arg(Arg::new("other")
3316 /// .long("other")
3317 /// .default_value_if("opt", Some("special"), Some("default")))
3318 /// .get_matches_from(vec![
3319 /// "prog", "--opt", "special"
3320 /// ]);
3321 ///
3322 /// assert_eq!(m.value_of("other"), Some("default"));
3323 /// ```
3324 ///
3325 /// We can run the same test and provide any value *other than* `special` and we won't get a
3326 /// default value.
3327 ///
3328 /// ```rust
3329 /// # use clap::{Command, Arg};
3330 /// let m = Command::new("prog")
3331 /// .arg(Arg::new("opt")
3332 /// .takes_value(true)
3333 /// .long("opt"))
3334 /// .arg(Arg::new("other")
3335 /// .long("other")
3336 /// .default_value_if("opt", Some("special"), Some("default")))
3337 /// .get_matches_from(vec![
3338 /// "prog", "--opt", "hahaha"
3339 /// ]);
3340 ///
3341 /// assert_eq!(m.value_of("other"), None);
3342 /// ```
3343 ///
3344 /// If we want to unset the default value for an Arg based on the presence or
3345 /// value of some other Arg.
3346 ///
3347 /// ```rust
3348 /// # use clap::{Command, Arg};
3349 /// let m = Command::new("prog")
3350 /// .arg(Arg::new("flag")
3351 /// .long("flag"))
3352 /// .arg(Arg::new("other")
3353 /// .long("other")
3354 /// .default_value("default")
3355 /// .default_value_if("flag", None, None))
3356 /// .get_matches_from(vec![
3357 /// "prog", "--flag"
3358 /// ]);
3359 ///
3360 /// assert_eq!(m.value_of("other"), None);
3361 /// ```
3362 /// [`Arg::takes_value(true)`]: Arg::takes_value()
3363 /// [`Arg::default_value`]: Arg::default_value()
3364 #[must_use]
default_value_if<T: Key>( self, arg_id: T, val: Option<&'help str>, default: Option<&'help str>, ) -> Self3365 pub fn default_value_if<T: Key>(
3366 self,
3367 arg_id: T,
3368 val: Option<&'help str>,
3369 default: Option<&'help str>,
3370 ) -> Self {
3371 self.default_value_if_os(arg_id, val.map(OsStr::new), default.map(OsStr::new))
3372 }
3373
3374 /// Provides a conditional default value in the exact same manner as [`Arg::default_value_if`]
3375 /// only using [`OsStr`]s instead.
3376 ///
3377 /// [`Arg::default_value_if`]: Arg::default_value_if()
3378 /// [`OsStr`]: std::ffi::OsStr
3379 #[must_use]
default_value_if_os<T: Key>( mut self, arg_id: T, val: Option<&'help OsStr>, default: Option<&'help OsStr>, ) -> Self3380 pub fn default_value_if_os<T: Key>(
3381 mut self,
3382 arg_id: T,
3383 val: Option<&'help OsStr>,
3384 default: Option<&'help OsStr>,
3385 ) -> Self {
3386 self.default_vals_ifs
3387 .push((arg_id.into(), val.into(), default));
3388 self.takes_value(true)
3389 }
3390
3391 /// Specifies multiple values and conditions in the same manner as [`Arg::default_value_if`].
3392 ///
3393 /// The method takes a slice of tuples in the `(arg, Option<val>, default)` format.
3394 ///
3395 /// **NOTE**: The conditions are stored in order and evaluated in the same order. I.e. the first
3396 /// if multiple conditions are true, the first one found will be applied and the ultimate value.
3397 ///
3398 /// # Examples
3399 ///
3400 /// First we use the default value only if another arg is present at runtime.
3401 ///
3402 /// ```rust
3403 /// # use clap::{Command, Arg};
3404 /// let m = Command::new("prog")
3405 /// .arg(Arg::new("flag")
3406 /// .long("flag"))
3407 /// .arg(Arg::new("opt")
3408 /// .long("opt")
3409 /// .takes_value(true))
3410 /// .arg(Arg::new("other")
3411 /// .long("other")
3412 /// .default_value_ifs(&[
3413 /// ("flag", None, Some("default")),
3414 /// ("opt", Some("channal"), Some("chan")),
3415 /// ]))
3416 /// .get_matches_from(vec![
3417 /// "prog", "--opt", "channal"
3418 /// ]);
3419 ///
3420 /// assert_eq!(m.value_of("other"), Some("chan"));
3421 /// ```
3422 ///
3423 /// Next we run the same test, but without providing `--flag`.
3424 ///
3425 /// ```rust
3426 /// # use clap::{Command, Arg};
3427 /// let m = Command::new("prog")
3428 /// .arg(Arg::new("flag")
3429 /// .long("flag"))
3430 /// .arg(Arg::new("other")
3431 /// .long("other")
3432 /// .default_value_ifs(&[
3433 /// ("flag", None, Some("default")),
3434 /// ("opt", Some("channal"), Some("chan")),
3435 /// ]))
3436 /// .get_matches_from(vec![
3437 /// "prog"
3438 /// ]);
3439 ///
3440 /// assert_eq!(m.value_of("other"), None);
3441 /// ```
3442 ///
3443 /// We can also see that these values are applied in order, and if more than one condition is
3444 /// true, only the first evaluated "wins"
3445 ///
3446 /// ```rust
3447 /// # use clap::{Command, Arg};
3448 /// let m = Command::new("prog")
3449 /// .arg(Arg::new("flag")
3450 /// .long("flag"))
3451 /// .arg(Arg::new("opt")
3452 /// .long("opt")
3453 /// .takes_value(true))
3454 /// .arg(Arg::new("other")
3455 /// .long("other")
3456 /// .default_value_ifs(&[
3457 /// ("flag", None, Some("default")),
3458 /// ("opt", Some("channal"), Some("chan")),
3459 /// ]))
3460 /// .get_matches_from(vec![
3461 /// "prog", "--opt", "channal", "--flag"
3462 /// ]);
3463 ///
3464 /// assert_eq!(m.value_of("other"), Some("default"));
3465 /// ```
3466 /// [`Arg::takes_value(true)`]: Arg::takes_value()
3467 /// [`Arg::default_value_if`]: Arg::default_value_if()
3468 #[must_use]
default_value_ifs<T: Key>( mut self, ifs: &[(T, Option<&'help str>, Option<&'help str>)], ) -> Self3469 pub fn default_value_ifs<T: Key>(
3470 mut self,
3471 ifs: &[(T, Option<&'help str>, Option<&'help str>)],
3472 ) -> Self {
3473 for (arg, val, default) in ifs {
3474 self = self.default_value_if_os(arg, val.map(OsStr::new), default.map(OsStr::new));
3475 }
3476 self
3477 }
3478
3479 /// Provides multiple conditional default values in the exact same manner as
3480 /// [`Arg::default_value_ifs`] only using [`OsStr`]s instead.
3481 ///
3482 /// [`Arg::default_value_ifs`]: Arg::default_value_ifs()
3483 /// [`OsStr`]: std::ffi::OsStr
3484 #[must_use]
default_value_ifs_os<T: Key>( mut self, ifs: &[(T, Option<&'help OsStr>, Option<&'help OsStr>)], ) -> Self3485 pub fn default_value_ifs_os<T: Key>(
3486 mut self,
3487 ifs: &[(T, Option<&'help OsStr>, Option<&'help OsStr>)],
3488 ) -> Self {
3489 for (arg, val, default) in ifs {
3490 self = self.default_value_if_os(arg, *val, *default);
3491 }
3492 self
3493 }
3494
3495 /// Set this arg as [required] as long as the specified argument is not present at runtime.
3496 ///
3497 /// **Pro Tip:** Using `Arg::required_unless_present` implies [`Arg::required`] and is therefore not
3498 /// mandatory to also set.
3499 ///
3500 /// # Examples
3501 ///
3502 /// ```rust
3503 /// # use clap::Arg;
3504 /// Arg::new("config")
3505 /// .required_unless_present("debug")
3506 /// # ;
3507 /// ```
3508 ///
3509 /// In the following example, the required argument is *not* provided,
3510 /// but it's not an error because the `unless` arg has been supplied.
3511 ///
3512 /// ```rust
3513 /// # use clap::{Command, Arg};
3514 /// let res = Command::new("prog")
3515 /// .arg(Arg::new("cfg")
3516 /// .required_unless_present("dbg")
3517 /// .takes_value(true)
3518 /// .long("config"))
3519 /// .arg(Arg::new("dbg")
3520 /// .long("debug"))
3521 /// .try_get_matches_from(vec![
3522 /// "prog", "--debug"
3523 /// ]);
3524 ///
3525 /// assert!(res.is_ok());
3526 /// ```
3527 ///
3528 /// Setting `Arg::required_unless_present(name)` and *not* supplying `name` or this arg is an error.
3529 ///
3530 /// ```rust
3531 /// # use clap::{Command, Arg, ErrorKind};
3532 /// let res = Command::new("prog")
3533 /// .arg(Arg::new("cfg")
3534 /// .required_unless_present("dbg")
3535 /// .takes_value(true)
3536 /// .long("config"))
3537 /// .arg(Arg::new("dbg")
3538 /// .long("debug"))
3539 /// .try_get_matches_from(vec![
3540 /// "prog"
3541 /// ]);
3542 ///
3543 /// assert!(res.is_err());
3544 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3545 /// ```
3546 /// [required]: Arg::required()
3547 #[must_use]
required_unless_present<T: Key>(mut self, arg_id: T) -> Self3548 pub fn required_unless_present<T: Key>(mut self, arg_id: T) -> Self {
3549 self.r_unless.push(arg_id.into());
3550 self
3551 }
3552
3553 /// Sets this arg as [required] unless *all* of the specified arguments are present at runtime.
3554 ///
3555 /// In other words, parsing will succeed only if user either
3556 /// * supplies the `self` arg.
3557 /// * supplies *all* of the `names` arguments.
3558 ///
3559 /// **NOTE:** If you wish for this argument to only be required unless *any of* these args are
3560 /// present see [`Arg::required_unless_present_any`]
3561 ///
3562 /// # Examples
3563 ///
3564 /// ```rust
3565 /// # use clap::Arg;
3566 /// Arg::new("config")
3567 /// .required_unless_present_all(&["cfg", "dbg"])
3568 /// # ;
3569 /// ```
3570 ///
3571 /// In the following example, the required argument is *not* provided, but it's not an error
3572 /// because *all* of the `names` args have been supplied.
3573 ///
3574 /// ```rust
3575 /// # use clap::{Command, Arg};
3576 /// let res = Command::new("prog")
3577 /// .arg(Arg::new("cfg")
3578 /// .required_unless_present_all(&["dbg", "infile"])
3579 /// .takes_value(true)
3580 /// .long("config"))
3581 /// .arg(Arg::new("dbg")
3582 /// .long("debug"))
3583 /// .arg(Arg::new("infile")
3584 /// .short('i')
3585 /// .takes_value(true))
3586 /// .try_get_matches_from(vec![
3587 /// "prog", "--debug", "-i", "file"
3588 /// ]);
3589 ///
3590 /// assert!(res.is_ok());
3591 /// ```
3592 ///
3593 /// Setting [`Arg::required_unless_present_all(names)`] and *not* supplying
3594 /// either *all* of `unless` args or the `self` arg is an error.
3595 ///
3596 /// ```rust
3597 /// # use clap::{Command, Arg, ErrorKind};
3598 /// let res = Command::new("prog")
3599 /// .arg(Arg::new("cfg")
3600 /// .required_unless_present_all(&["dbg", "infile"])
3601 /// .takes_value(true)
3602 /// .long("config"))
3603 /// .arg(Arg::new("dbg")
3604 /// .long("debug"))
3605 /// .arg(Arg::new("infile")
3606 /// .short('i')
3607 /// .takes_value(true))
3608 /// .try_get_matches_from(vec![
3609 /// "prog"
3610 /// ]);
3611 ///
3612 /// assert!(res.is_err());
3613 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3614 /// ```
3615 /// [required]: Arg::required()
3616 /// [`Arg::required_unless_present_any`]: Arg::required_unless_present_any()
3617 /// [`Arg::required_unless_present_all(names)`]: Arg::required_unless_present_all()
3618 #[must_use]
required_unless_present_all<T, I>(mut self, names: I) -> Self where I: IntoIterator<Item = T>, T: Key,3619 pub fn required_unless_present_all<T, I>(mut self, names: I) -> Self
3620 where
3621 I: IntoIterator<Item = T>,
3622 T: Key,
3623 {
3624 self.r_unless_all.extend(names.into_iter().map(Id::from));
3625 self
3626 }
3627
3628 /// Sets this arg as [required] unless *any* of the specified arguments are present at runtime.
3629 ///
3630 /// In other words, parsing will succeed only if user either
3631 /// * supplies the `self` arg.
3632 /// * supplies *one or more* of the `unless` arguments.
3633 ///
3634 /// **NOTE:** If you wish for this argument to be required unless *all of* these args are
3635 /// present see [`Arg::required_unless_present_all`]
3636 ///
3637 /// # Examples
3638 ///
3639 /// ```rust
3640 /// # use clap::Arg;
3641 /// Arg::new("config")
3642 /// .required_unless_present_any(&["cfg", "dbg"])
3643 /// # ;
3644 /// ```
3645 ///
3646 /// Setting [`Arg::required_unless_present_any(names)`] requires that the argument be used at runtime
3647 /// *unless* *at least one of* the args in `names` are present. In the following example, the
3648 /// required argument is *not* provided, but it's not an error because one the `unless` args
3649 /// have been supplied.
3650 ///
3651 /// ```rust
3652 /// # use clap::{Command, Arg};
3653 /// let res = Command::new("prog")
3654 /// .arg(Arg::new("cfg")
3655 /// .required_unless_present_any(&["dbg", "infile"])
3656 /// .takes_value(true)
3657 /// .long("config"))
3658 /// .arg(Arg::new("dbg")
3659 /// .long("debug"))
3660 /// .arg(Arg::new("infile")
3661 /// .short('i')
3662 /// .takes_value(true))
3663 /// .try_get_matches_from(vec![
3664 /// "prog", "--debug"
3665 /// ]);
3666 ///
3667 /// assert!(res.is_ok());
3668 /// ```
3669 ///
3670 /// Setting [`Arg::required_unless_present_any(names)`] and *not* supplying *at least one of* `names`
3671 /// or this arg is an error.
3672 ///
3673 /// ```rust
3674 /// # use clap::{Command, Arg, ErrorKind};
3675 /// let res = Command::new("prog")
3676 /// .arg(Arg::new("cfg")
3677 /// .required_unless_present_any(&["dbg", "infile"])
3678 /// .takes_value(true)
3679 /// .long("config"))
3680 /// .arg(Arg::new("dbg")
3681 /// .long("debug"))
3682 /// .arg(Arg::new("infile")
3683 /// .short('i')
3684 /// .takes_value(true))
3685 /// .try_get_matches_from(vec![
3686 /// "prog"
3687 /// ]);
3688 ///
3689 /// assert!(res.is_err());
3690 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3691 /// ```
3692 /// [required]: Arg::required()
3693 /// [`Arg::required_unless_present_any(names)`]: Arg::required_unless_present_any()
3694 /// [`Arg::required_unless_present_all`]: Arg::required_unless_present_all()
3695 #[must_use]
required_unless_present_any<T, I>(mut self, names: I) -> Self where I: IntoIterator<Item = T>, T: Key,3696 pub fn required_unless_present_any<T, I>(mut self, names: I) -> Self
3697 where
3698 I: IntoIterator<Item = T>,
3699 T: Key,
3700 {
3701 self.r_unless.extend(names.into_iter().map(Id::from));
3702 self
3703 }
3704
3705 /// This argument is [required] only if the specified `arg` is present at runtime and its value
3706 /// equals `val`.
3707 ///
3708 /// # Examples
3709 ///
3710 /// ```rust
3711 /// # use clap::Arg;
3712 /// Arg::new("config")
3713 /// .required_if_eq("other_arg", "value")
3714 /// # ;
3715 /// ```
3716 ///
3717 /// ```rust
3718 /// # use clap::{Command, Arg, ErrorKind};
3719 /// let res = Command::new("prog")
3720 /// .arg(Arg::new("cfg")
3721 /// .takes_value(true)
3722 /// .required_if_eq("other", "special")
3723 /// .long("config"))
3724 /// .arg(Arg::new("other")
3725 /// .long("other")
3726 /// .takes_value(true))
3727 /// .try_get_matches_from(vec![
3728 /// "prog", "--other", "not-special"
3729 /// ]);
3730 ///
3731 /// assert!(res.is_ok()); // We didn't use --other=special, so "cfg" wasn't required
3732 ///
3733 /// let res = Command::new("prog")
3734 /// .arg(Arg::new("cfg")
3735 /// .takes_value(true)
3736 /// .required_if_eq("other", "special")
3737 /// .long("config"))
3738 /// .arg(Arg::new("other")
3739 /// .long("other")
3740 /// .takes_value(true))
3741 /// .try_get_matches_from(vec![
3742 /// "prog", "--other", "special"
3743 /// ]);
3744 ///
3745 /// // We did use --other=special so "cfg" had become required but was missing.
3746 /// assert!(res.is_err());
3747 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3748 ///
3749 /// let res = Command::new("prog")
3750 /// .arg(Arg::new("cfg")
3751 /// .takes_value(true)
3752 /// .required_if_eq("other", "special")
3753 /// .long("config"))
3754 /// .arg(Arg::new("other")
3755 /// .long("other")
3756 /// .takes_value(true))
3757 /// .try_get_matches_from(vec![
3758 /// "prog", "--other", "SPECIAL"
3759 /// ]);
3760 ///
3761 /// // By default, the comparison is case-sensitive, so "cfg" wasn't required
3762 /// assert!(res.is_ok());
3763 ///
3764 /// let res = Command::new("prog")
3765 /// .arg(Arg::new("cfg")
3766 /// .takes_value(true)
3767 /// .required_if_eq("other", "special")
3768 /// .long("config"))
3769 /// .arg(Arg::new("other")
3770 /// .long("other")
3771 /// .ignore_case(true)
3772 /// .takes_value(true))
3773 /// .try_get_matches_from(vec![
3774 /// "prog", "--other", "SPECIAL"
3775 /// ]);
3776 ///
3777 /// // However, case-insensitive comparisons can be enabled. This typically occurs when using Arg::possible_values().
3778 /// assert!(res.is_err());
3779 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3780 /// ```
3781 /// [`Arg::requires(name)`]: Arg::requires()
3782 /// [Conflicting]: Arg::conflicts_with()
3783 /// [required]: Arg::required()
3784 #[must_use]
required_if_eq<T: Key>(mut self, arg_id: T, val: &'help str) -> Self3785 pub fn required_if_eq<T: Key>(mut self, arg_id: T, val: &'help str) -> Self {
3786 self.r_ifs.push((arg_id.into(), val));
3787 self
3788 }
3789
3790 /// Specify this argument is [required] based on multiple conditions.
3791 ///
3792 /// The conditions are set up in a `(arg, val)` style tuple. The requirement will only become
3793 /// valid if one of the specified `arg`'s value equals its corresponding `val`.
3794 ///
3795 /// # Examples
3796 ///
3797 /// ```rust
3798 /// # use clap::Arg;
3799 /// Arg::new("config")
3800 /// .required_if_eq_any(&[
3801 /// ("extra", "val"),
3802 /// ("option", "spec")
3803 /// ])
3804 /// # ;
3805 /// ```
3806 ///
3807 /// Setting `Arg::required_if_eq_any(&[(arg, val)])` makes this arg required if any of the `arg`s
3808 /// are used at runtime and it's corresponding value is equal to `val`. If the `arg`'s value is
3809 /// anything other than `val`, this argument isn't required.
3810 ///
3811 /// ```rust
3812 /// # use clap::{Command, Arg};
3813 /// let res = Command::new("prog")
3814 /// .arg(Arg::new("cfg")
3815 /// .required_if_eq_any(&[
3816 /// ("extra", "val"),
3817 /// ("option", "spec")
3818 /// ])
3819 /// .takes_value(true)
3820 /// .long("config"))
3821 /// .arg(Arg::new("extra")
3822 /// .takes_value(true)
3823 /// .long("extra"))
3824 /// .arg(Arg::new("option")
3825 /// .takes_value(true)
3826 /// .long("option"))
3827 /// .try_get_matches_from(vec![
3828 /// "prog", "--option", "other"
3829 /// ]);
3830 ///
3831 /// assert!(res.is_ok()); // We didn't use --option=spec, or --extra=val so "cfg" isn't required
3832 /// ```
3833 ///
3834 /// Setting `Arg::required_if_eq_any(&[(arg, val)])` and having any of the `arg`s used with its
3835 /// value of `val` but *not* using this arg is an error.
3836 ///
3837 /// ```rust
3838 /// # use clap::{Command, Arg, ErrorKind};
3839 /// let res = Command::new("prog")
3840 /// .arg(Arg::new("cfg")
3841 /// .required_if_eq_any(&[
3842 /// ("extra", "val"),
3843 /// ("option", "spec")
3844 /// ])
3845 /// .takes_value(true)
3846 /// .long("config"))
3847 /// .arg(Arg::new("extra")
3848 /// .takes_value(true)
3849 /// .long("extra"))
3850 /// .arg(Arg::new("option")
3851 /// .takes_value(true)
3852 /// .long("option"))
3853 /// .try_get_matches_from(vec![
3854 /// "prog", "--option", "spec"
3855 /// ]);
3856 ///
3857 /// assert!(res.is_err());
3858 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3859 /// ```
3860 /// [`Arg::requires(name)`]: Arg::requires()
3861 /// [Conflicting]: Arg::conflicts_with()
3862 /// [required]: Arg::required()
3863 #[must_use]
required_if_eq_any<T: Key>(mut self, ifs: &[(T, &'help str)]) -> Self3864 pub fn required_if_eq_any<T: Key>(mut self, ifs: &[(T, &'help str)]) -> Self {
3865 self.r_ifs
3866 .extend(ifs.iter().map(|(id, val)| (Id::from_ref(id), *val)));
3867 self
3868 }
3869
3870 /// Specify this argument is [required] based on multiple conditions.
3871 ///
3872 /// The conditions are set up in a `(arg, val)` style tuple. The requirement will only become
3873 /// valid if every one of the specified `arg`'s value equals its corresponding `val`.
3874 ///
3875 /// # Examples
3876 ///
3877 /// ```rust
3878 /// # use clap::Arg;
3879 /// Arg::new("config")
3880 /// .required_if_eq_all(&[
3881 /// ("extra", "val"),
3882 /// ("option", "spec")
3883 /// ])
3884 /// # ;
3885 /// ```
3886 ///
3887 /// Setting `Arg::required_if_eq_all(&[(arg, val)])` makes this arg required if all of the `arg`s
3888 /// are used at runtime and every value is equal to its corresponding `val`. If the `arg`'s value is
3889 /// anything other than `val`, this argument isn't required.
3890 ///
3891 /// ```rust
3892 /// # use clap::{Command, Arg};
3893 /// let res = Command::new("prog")
3894 /// .arg(Arg::new("cfg")
3895 /// .required_if_eq_all(&[
3896 /// ("extra", "val"),
3897 /// ("option", "spec")
3898 /// ])
3899 /// .takes_value(true)
3900 /// .long("config"))
3901 /// .arg(Arg::new("extra")
3902 /// .takes_value(true)
3903 /// .long("extra"))
3904 /// .arg(Arg::new("option")
3905 /// .takes_value(true)
3906 /// .long("option"))
3907 /// .try_get_matches_from(vec![
3908 /// "prog", "--option", "spec"
3909 /// ]);
3910 ///
3911 /// assert!(res.is_ok()); // We didn't use --option=spec --extra=val so "cfg" isn't required
3912 /// ```
3913 ///
3914 /// Setting `Arg::required_if_eq_all(&[(arg, val)])` and having all of the `arg`s used with its
3915 /// value of `val` but *not* using this arg is an error.
3916 ///
3917 /// ```rust
3918 /// # use clap::{Command, Arg, ErrorKind};
3919 /// let res = Command::new("prog")
3920 /// .arg(Arg::new("cfg")
3921 /// .required_if_eq_all(&[
3922 /// ("extra", "val"),
3923 /// ("option", "spec")
3924 /// ])
3925 /// .takes_value(true)
3926 /// .long("config"))
3927 /// .arg(Arg::new("extra")
3928 /// .takes_value(true)
3929 /// .long("extra"))
3930 /// .arg(Arg::new("option")
3931 /// .takes_value(true)
3932 /// .long("option"))
3933 /// .try_get_matches_from(vec![
3934 /// "prog", "--extra", "val", "--option", "spec"
3935 /// ]);
3936 ///
3937 /// assert!(res.is_err());
3938 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3939 /// ```
3940 /// [required]: Arg::required()
3941 #[must_use]
required_if_eq_all<T: Key>(mut self, ifs: &[(T, &'help str)]) -> Self3942 pub fn required_if_eq_all<T: Key>(mut self, ifs: &[(T, &'help str)]) -> Self {
3943 self.r_ifs_all
3944 .extend(ifs.iter().map(|(id, val)| (Id::from_ref(id), *val)));
3945 self
3946 }
3947
3948 /// Require another argument if this arg was present at runtime and its value equals to `val`.
3949 ///
3950 /// This method takes `value, another_arg` pair. At runtime, clap will check
3951 /// if this arg (`self`) is present and its value equals to `val`.
3952 /// If it does, `another_arg` will be marked as required.
3953 ///
3954 /// # Examples
3955 ///
3956 /// ```rust
3957 /// # use clap::Arg;
3958 /// Arg::new("config")
3959 /// .requires_if("val", "arg")
3960 /// # ;
3961 /// ```
3962 ///
3963 /// Setting `Arg::requires_if(val, arg)` requires that the `arg` be used at runtime if the
3964 /// defining argument's value is equal to `val`. If the defining argument is anything other than
3965 /// `val`, the other argument isn't required.
3966 ///
3967 /// ```rust
3968 /// # use clap::{Command, Arg};
3969 /// let res = Command::new("prog")
3970 /// .arg(Arg::new("cfg")
3971 /// .takes_value(true)
3972 /// .requires_if("my.cfg", "other")
3973 /// .long("config"))
3974 /// .arg(Arg::new("other"))
3975 /// .try_get_matches_from(vec![
3976 /// "prog", "--config", "some.cfg"
3977 /// ]);
3978 ///
3979 /// assert!(res.is_ok()); // We didn't use --config=my.cfg, so other wasn't required
3980 /// ```
3981 ///
3982 /// Setting `Arg::requires_if(val, arg)` and setting the value to `val` but *not* supplying
3983 /// `arg` is an error.
3984 ///
3985 /// ```rust
3986 /// # use clap::{Command, Arg, ErrorKind};
3987 /// let res = Command::new("prog")
3988 /// .arg(Arg::new("cfg")
3989 /// .takes_value(true)
3990 /// .requires_if("my.cfg", "input")
3991 /// .long("config"))
3992 /// .arg(Arg::new("input"))
3993 /// .try_get_matches_from(vec![
3994 /// "prog", "--config", "my.cfg"
3995 /// ]);
3996 ///
3997 /// assert!(res.is_err());
3998 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3999 /// ```
4000 /// [`Arg::requires(name)`]: Arg::requires()
4001 /// [Conflicting]: Arg::conflicts_with()
4002 /// [override]: Arg::overrides_with()
4003 #[must_use]
requires_if<T: Key>(mut self, val: &'help str, arg_id: T) -> Self4004 pub fn requires_if<T: Key>(mut self, val: &'help str, arg_id: T) -> Self {
4005 self.requires
4006 .push((ArgPredicate::Equals(OsStr::new(val)), arg_id.into()));
4007 self
4008 }
4009
4010 /// Allows multiple conditional requirements.
4011 ///
4012 /// The requirement will only become valid if this arg's value equals `val`.
4013 ///
4014 /// # Examples
4015 ///
4016 /// ```rust
4017 /// # use clap::Arg;
4018 /// Arg::new("config")
4019 /// .requires_ifs(&[
4020 /// ("val", "arg"),
4021 /// ("other_val", "arg2"),
4022 /// ])
4023 /// # ;
4024 /// ```
4025 ///
4026 /// Setting `Arg::requires_ifs(&["val", "arg"])` requires that the `arg` be used at runtime if the
4027 /// defining argument's value is equal to `val`. If the defining argument's value is anything other
4028 /// than `val`, `arg` isn't required.
4029 ///
4030 /// ```rust
4031 /// # use clap::{Command, Arg, ErrorKind};
4032 /// let res = Command::new("prog")
4033 /// .arg(Arg::new("cfg")
4034 /// .takes_value(true)
4035 /// .requires_ifs(&[
4036 /// ("special.conf", "opt"),
4037 /// ("other.conf", "other"),
4038 /// ])
4039 /// .long("config"))
4040 /// .arg(Arg::new("opt")
4041 /// .long("option")
4042 /// .takes_value(true))
4043 /// .arg(Arg::new("other"))
4044 /// .try_get_matches_from(vec![
4045 /// "prog", "--config", "special.conf"
4046 /// ]);
4047 ///
4048 /// assert!(res.is_err()); // We used --config=special.conf so --option <val> is required
4049 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
4050 /// ```
4051 /// [`Arg::requires(name)`]: Arg::requires()
4052 /// [Conflicting]: Arg::conflicts_with()
4053 /// [override]: Arg::overrides_with()
4054 #[must_use]
requires_ifs<T: Key>(mut self, ifs: &[(&'help str, T)]) -> Self4055 pub fn requires_ifs<T: Key>(mut self, ifs: &[(&'help str, T)]) -> Self {
4056 self.requires.extend(
4057 ifs.iter()
4058 .map(|(val, arg)| (ArgPredicate::Equals(OsStr::new(*val)), Id::from(arg))),
4059 );
4060 self
4061 }
4062
4063 /// Require these arguments names when this one is presen
4064 ///
4065 /// i.e. when using this argument, the following arguments *must* be present.
4066 ///
4067 /// **NOTE:** [Conflicting] rules and [override] rules take precedence over being required
4068 /// by default.
4069 ///
4070 /// # Examples
4071 ///
4072 /// ```rust
4073 /// # use clap::Arg;
4074 /// Arg::new("config")
4075 /// .requires_all(&["input", "output"])
4076 /// # ;
4077 /// ```
4078 ///
4079 /// Setting `Arg::requires_all(&[arg, arg2])` requires that all the arguments be used at
4080 /// runtime if the defining argument is used. If the defining argument isn't used, the other
4081 /// argument isn't required
4082 ///
4083 /// ```rust
4084 /// # use clap::{Command, Arg};
4085 /// let res = Command::new("prog")
4086 /// .arg(Arg::new("cfg")
4087 /// .takes_value(true)
4088 /// .requires("input")
4089 /// .long("config"))
4090 /// .arg(Arg::new("input"))
4091 /// .arg(Arg::new("output"))
4092 /// .try_get_matches_from(vec![
4093 /// "prog"
4094 /// ]);
4095 ///
4096 /// assert!(res.is_ok()); // We didn't use cfg, so input and output weren't required
4097 /// ```
4098 ///
4099 /// Setting `Arg::requires_all(&[arg, arg2])` and *not* supplying all the arguments is an
4100 /// error.
4101 ///
4102 /// ```rust
4103 /// # use clap::{Command, Arg, ErrorKind};
4104 /// let res = Command::new("prog")
4105 /// .arg(Arg::new("cfg")
4106 /// .takes_value(true)
4107 /// .requires_all(&["input", "output"])
4108 /// .long("config"))
4109 /// .arg(Arg::new("input"))
4110 /// .arg(Arg::new("output"))
4111 /// .try_get_matches_from(vec![
4112 /// "prog", "--config", "file.conf", "in.txt"
4113 /// ]);
4114 ///
4115 /// assert!(res.is_err());
4116 /// // We didn't use output
4117 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
4118 /// ```
4119 /// [Conflicting]: Arg::conflicts_with()
4120 /// [override]: Arg::overrides_with()
4121 #[must_use]
requires_all<T: Key>(mut self, names: &[T]) -> Self4122 pub fn requires_all<T: Key>(mut self, names: &[T]) -> Self {
4123 self.requires
4124 .extend(names.iter().map(|s| (ArgPredicate::IsPresent, s.into())));
4125 self
4126 }
4127
4128 /// This argument is mutually exclusive with the specified argument.
4129 ///
4130 /// **NOTE:** Conflicting rules take precedence over being required by default. Conflict rules
4131 /// only need to be set for one of the two arguments, they do not need to be set for each.
4132 ///
4133 /// **NOTE:** Defining a conflict is two-way, but does *not* need to defined for both arguments
4134 /// (i.e. if A conflicts with B, defining A.conflicts_with(B) is sufficient. You do not
4135 /// need to also do B.conflicts_with(A))
4136 ///
4137 /// **NOTE:** [`Arg::conflicts_with_all(names)`] allows specifying an argument which conflicts with more than one argument.
4138 ///
4139 /// **NOTE** [`Arg::exclusive(true)`] allows specifying an argument which conflicts with every other argument.
4140 ///
4141 /// # Examples
4142 ///
4143 /// ```rust
4144 /// # use clap::Arg;
4145 /// Arg::new("config")
4146 /// .conflicts_with("debug")
4147 /// # ;
4148 /// ```
4149 ///
4150 /// Setting conflicting argument, and having both arguments present at runtime is an error.
4151 ///
4152 /// ```rust
4153 /// # use clap::{Command, Arg, ErrorKind};
4154 /// let res = Command::new("prog")
4155 /// .arg(Arg::new("cfg")
4156 /// .takes_value(true)
4157 /// .conflicts_with("debug")
4158 /// .long("config"))
4159 /// .arg(Arg::new("debug")
4160 /// .long("debug"))
4161 /// .try_get_matches_from(vec![
4162 /// "prog", "--debug", "--config", "file.conf"
4163 /// ]);
4164 ///
4165 /// assert!(res.is_err());
4166 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::ArgumentConflict);
4167 /// ```
4168 ///
4169 /// [`Arg::conflicts_with_all(names)`]: Arg::conflicts_with_all()
4170 /// [`Arg::exclusive(true)`]: Arg::exclusive()
4171 #[must_use]
conflicts_with<T: Key>(mut self, arg_id: T) -> Self4172 pub fn conflicts_with<T: Key>(mut self, arg_id: T) -> Self {
4173 self.blacklist.push(arg_id.into());
4174 self
4175 }
4176
4177 /// This argument is mutually exclusive with the specified arguments.
4178 ///
4179 /// See [`Arg::conflicts_with`].
4180 ///
4181 /// **NOTE:** Conflicting rules take precedence over being required by default. Conflict rules
4182 /// only need to be set for one of the two arguments, they do not need to be set for each.
4183 ///
4184 /// **NOTE:** Defining a conflict is two-way, but does *not* need to defined for both arguments
4185 /// (i.e. if A conflicts with B, defining A.conflicts_with(B) is sufficient. You do not need
4186 /// need to also do B.conflicts_with(A))
4187 ///
4188 /// **NOTE:** [`Arg::exclusive(true)`] allows specifying an argument which conflicts with every other argument.
4189 ///
4190 /// # Examples
4191 ///
4192 /// ```rust
4193 /// # use clap::Arg;
4194 /// Arg::new("config")
4195 /// .conflicts_with_all(&["debug", "input"])
4196 /// # ;
4197 /// ```
4198 ///
4199 /// Setting conflicting argument, and having any of the arguments present at runtime with a
4200 /// conflicting argument is an error.
4201 ///
4202 /// ```rust
4203 /// # use clap::{Command, Arg, ErrorKind};
4204 /// let res = Command::new("prog")
4205 /// .arg(Arg::new("cfg")
4206 /// .takes_value(true)
4207 /// .conflicts_with_all(&["debug", "input"])
4208 /// .long("config"))
4209 /// .arg(Arg::new("debug")
4210 /// .long("debug"))
4211 /// .arg(Arg::new("input"))
4212 /// .try_get_matches_from(vec![
4213 /// "prog", "--config", "file.conf", "file.txt"
4214 /// ]);
4215 ///
4216 /// assert!(res.is_err());
4217 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::ArgumentConflict);
4218 /// ```
4219 /// [`Arg::conflicts_with`]: Arg::conflicts_with()
4220 /// [`Arg::exclusive(true)`]: Arg::exclusive()
4221 #[must_use]
conflicts_with_all(mut self, names: &[&str]) -> Self4222 pub fn conflicts_with_all(mut self, names: &[&str]) -> Self {
4223 self.blacklist.extend(names.iter().copied().map(Id::from));
4224 self
4225 }
4226
4227 /// Sets an overridable argument.
4228 ///
4229 /// i.e. this argument and the following argument
4230 /// will override each other in POSIX style (whichever argument was specified at runtime
4231 /// **last** "wins")
4232 ///
4233 /// **NOTE:** When an argument is overridden it is essentially as if it never was used, any
4234 /// conflicts, requirements, etc. are evaluated **after** all "overrides" have been removed
4235 ///
4236 /// **NOTE:** Overriding an argument implies they [conflict][Arg::conflicts_with`].
4237 ///
4238 /// **WARNING:** Positional arguments and options which accept
4239 /// [`Arg::multiple_occurrences`] cannot override themselves (or we
4240 /// would never be able to advance to the next positional). If a positional
4241 /// argument or option with one of the [`Arg::multiple_occurrences`]
4242 /// settings lists itself as an override, it is simply ignored.
4243 ///
4244 /// # Examples
4245 ///
4246 /// ```rust
4247 /// # use clap::{Command, arg};
4248 /// let m = Command::new("prog")
4249 /// .arg(arg!(-f --flag "some flag")
4250 /// .conflicts_with("debug"))
4251 /// .arg(arg!(-d --debug "other flag"))
4252 /// .arg(arg!(-c --color "third flag")
4253 /// .overrides_with("flag"))
4254 /// .get_matches_from(vec![
4255 /// "prog", "-f", "-d", "-c"]);
4256 /// // ^~~~~~~~~~~~^~~~~ flag is overridden by color
4257 ///
4258 /// assert!(m.is_present("color"));
4259 /// assert!(m.is_present("debug")); // even though flag conflicts with debug, it's as if flag
4260 /// // was never used because it was overridden with color
4261 /// assert!(!m.is_present("flag"));
4262 /// ```
4263 /// Care must be taken when using this setting, and having an arg override with itself. This
4264 /// is common practice when supporting things like shell aliases, config files, etc.
4265 /// However, when combined with multiple values, it can get dicy.
4266 /// Here is how clap handles such situations:
4267 ///
4268 /// When a flag overrides itself, it's as if the flag was only ever used once (essentially
4269 /// preventing a "Unexpected multiple usage" error):
4270 ///
4271 /// ```rust
4272 /// # use clap::{Command, arg};
4273 /// let m = Command::new("posix")
4274 /// .arg(arg!(--flag "some flag").overrides_with("flag"))
4275 /// .get_matches_from(vec!["posix", "--flag", "--flag"]);
4276 /// assert!(m.is_present("flag"));
4277 /// ```
4278 ///
4279 /// Making an arg [`Arg::multiple_occurrences`] and override itself
4280 /// is essentially meaningless. Therefore clap ignores an override of self
4281 /// if it's a flag and it already accepts multiple occurrences.
4282 ///
4283 /// ```
4284 /// # use clap::{Command, arg};
4285 /// let m = Command::new("posix")
4286 /// .arg(arg!(--flag ... "some flag").overrides_with("flag"))
4287 /// .get_matches_from(vec!["", "--flag", "--flag", "--flag", "--flag"]);
4288 /// assert!(m.is_present("flag"));
4289 /// ```
4290 ///
4291 /// Now notice with options (which *do not* set
4292 /// [`Arg::multiple_occurrences`]), it's as if only the last
4293 /// occurrence happened.
4294 ///
4295 /// ```
4296 /// # use clap::{Command, arg};
4297 /// let m = Command::new("posix")
4298 /// .arg(arg!(--opt <val> "some option").overrides_with("opt"))
4299 /// .get_matches_from(vec!["", "--opt=some", "--opt=other"]);
4300 /// assert!(m.is_present("opt"));
4301 /// assert_eq!(m.value_of("opt"), Some("other"));
4302 /// ```
4303 ///
4304 /// This will also work when [`Arg::multiple_values`] is enabled:
4305 ///
4306 /// ```
4307 /// # use clap::{Command, Arg};
4308 /// let m = Command::new("posix")
4309 /// .arg(
4310 /// Arg::new("opt")
4311 /// .long("opt")
4312 /// .takes_value(true)
4313 /// .multiple_values(true)
4314 /// .overrides_with("opt")
4315 /// )
4316 /// .get_matches_from(vec!["", "--opt", "1", "2", "--opt", "3", "4", "5"]);
4317 /// assert!(m.is_present("opt"));
4318 /// assert_eq!(m.values_of("opt").unwrap().collect::<Vec<_>>(), &["3", "4", "5"]);
4319 /// ```
4320 ///
4321 /// Just like flags, options with [`Arg::multiple_occurrences`] set
4322 /// will ignore the "override self" setting.
4323 ///
4324 /// ```
4325 /// # use clap::{Command, arg};
4326 /// let m = Command::new("posix")
4327 /// .arg(arg!(--opt <val> ... "some option")
4328 /// .multiple_values(true)
4329 /// .overrides_with("opt"))
4330 /// .get_matches_from(vec!["", "--opt", "first", "over", "--opt", "other", "val"]);
4331 /// assert!(m.is_present("opt"));
4332 /// assert_eq!(m.values_of("opt").unwrap().collect::<Vec<_>>(), &["first", "over", "other", "val"]);
4333 /// ```
4334 #[must_use]
overrides_with<T: Key>(mut self, arg_id: T) -> Self4335 pub fn overrides_with<T: Key>(mut self, arg_id: T) -> Self {
4336 self.overrides.push(arg_id.into());
4337 self
4338 }
4339
4340 /// Sets multiple mutually overridable arguments by name.
4341 ///
4342 /// i.e. this argument and the following argument will override each other in POSIX style
4343 /// (whichever argument was specified at runtime **last** "wins")
4344 ///
4345 /// **NOTE:** When an argument is overridden it is essentially as if it never was used, any
4346 /// conflicts, requirements, etc. are evaluated **after** all "overrides" have been removed
4347 ///
4348 /// **NOTE:** Overriding an argument implies they [conflict][Arg::conflicts_with_all`].
4349 ///
4350 /// # Examples
4351 ///
4352 /// ```rust
4353 /// # use clap::{Command, arg};
4354 /// let m = Command::new("prog")
4355 /// .arg(arg!(-f --flag "some flag")
4356 /// .conflicts_with("color"))
4357 /// .arg(arg!(-d --debug "other flag"))
4358 /// .arg(arg!(-c --color "third flag")
4359 /// .overrides_with_all(&["flag", "debug"]))
4360 /// .get_matches_from(vec![
4361 /// "prog", "-f", "-d", "-c"]);
4362 /// // ^~~~~~^~~~~~~~~ flag and debug are overridden by color
4363 ///
4364 /// assert!(m.is_present("color")); // even though flag conflicts with color, it's as if flag
4365 /// // and debug were never used because they were overridden
4366 /// // with color
4367 /// assert!(!m.is_present("debug"));
4368 /// assert!(!m.is_present("flag"));
4369 /// ```
4370 #[must_use]
overrides_with_all<T: Key>(mut self, names: &[T]) -> Self4371 pub fn overrides_with_all<T: Key>(mut self, names: &[T]) -> Self {
4372 self.overrides.extend(names.iter().map(Id::from));
4373 self
4374 }
4375 }
4376
4377 /// # Reflection
4378 impl<'help> Arg<'help> {
4379 /// Get the name of the argument
4380 #[inline]
get_id(&self) -> &'help str4381 pub fn get_id(&self) -> &'help str {
4382 self.name
4383 }
4384
4385 /// Deprecated, replaced with [`Arg::get_id`]
4386 #[cfg_attr(
4387 feature = "deprecated",
4388 deprecated(since = "3.1.0", note = "Replaced with `Arg::get_id`")
4389 )]
get_name(&self) -> &'help str4390 pub fn get_name(&self) -> &'help str {
4391 self.get_id()
4392 }
4393
4394 /// Get the help specified for this argument, if any
4395 #[inline]
get_help(&self) -> Option<&'help str>4396 pub fn get_help(&self) -> Option<&'help str> {
4397 self.help
4398 }
4399
4400 /// Get the long help specified for this argument, if any
4401 ///
4402 /// # Examples
4403 ///
4404 /// ```rust
4405 /// # use clap::Arg;
4406 /// let arg = Arg::new("foo").long_help("long help");
4407 /// assert_eq!(Some("long help"), arg.get_long_help());
4408 /// ```
4409 ///
4410 #[inline]
get_long_help(&self) -> Option<&'help str>4411 pub fn get_long_help(&self) -> Option<&'help str> {
4412 self.long_help
4413 }
4414
4415 /// Get the help heading specified for this argument, if any
4416 #[inline]
get_help_heading(&self) -> Option<&'help str>4417 pub fn get_help_heading(&self) -> Option<&'help str> {
4418 self.help_heading.unwrap_or_default()
4419 }
4420
4421 /// Get the short option name for this argument, if any
4422 #[inline]
get_short(&self) -> Option<char>4423 pub fn get_short(&self) -> Option<char> {
4424 self.short
4425 }
4426
4427 /// Get visible short aliases for this argument, if any
4428 #[inline]
get_visible_short_aliases(&self) -> Option<Vec<char>>4429 pub fn get_visible_short_aliases(&self) -> Option<Vec<char>> {
4430 if self.short_aliases.is_empty() {
4431 None
4432 } else {
4433 Some(
4434 self.short_aliases
4435 .iter()
4436 .filter_map(|(c, v)| if *v { Some(c) } else { None })
4437 .copied()
4438 .collect(),
4439 )
4440 }
4441 }
4442
4443 /// Get *all* short aliases for this argument, if any, both visible and hidden.
4444 #[inline]
get_all_short_aliases(&self) -> Option<Vec<char>>4445 pub fn get_all_short_aliases(&self) -> Option<Vec<char>> {
4446 if self.short_aliases.is_empty() {
4447 None
4448 } else {
4449 Some(self.short_aliases.iter().map(|(s, _)| s).copied().collect())
4450 }
4451 }
4452
4453 /// Get the short option name and its visible aliases, if any
4454 #[inline]
get_short_and_visible_aliases(&self) -> Option<Vec<char>>4455 pub fn get_short_and_visible_aliases(&self) -> Option<Vec<char>> {
4456 let mut shorts = match self.short {
4457 Some(short) => vec![short],
4458 None => return None,
4459 };
4460 if let Some(aliases) = self.get_visible_short_aliases() {
4461 shorts.extend(aliases);
4462 }
4463 Some(shorts)
4464 }
4465
4466 /// Get the long option name for this argument, if any
4467 #[inline]
get_long(&self) -> Option<&'help str>4468 pub fn get_long(&self) -> Option<&'help str> {
4469 self.long
4470 }
4471
4472 /// Get visible aliases for this argument, if any
4473 #[inline]
get_visible_aliases(&self) -> Option<Vec<&'help str>>4474 pub fn get_visible_aliases(&self) -> Option<Vec<&'help str>> {
4475 if self.aliases.is_empty() {
4476 None
4477 } else {
4478 Some(
4479 self.aliases
4480 .iter()
4481 .filter_map(|(s, v)| if *v { Some(s) } else { None })
4482 .copied()
4483 .collect(),
4484 )
4485 }
4486 }
4487
4488 /// Get *all* aliases for this argument, if any, both visible and hidden.
4489 #[inline]
get_all_aliases(&self) -> Option<Vec<&'help str>>4490 pub fn get_all_aliases(&self) -> Option<Vec<&'help str>> {
4491 if self.aliases.is_empty() {
4492 None
4493 } else {
4494 Some(self.aliases.iter().map(|(s, _)| s).copied().collect())
4495 }
4496 }
4497
4498 /// Get the long option name and its visible aliases, if any
4499 #[inline]
get_long_and_visible_aliases(&self) -> Option<Vec<&'help str>>4500 pub fn get_long_and_visible_aliases(&self) -> Option<Vec<&'help str>> {
4501 let mut longs = match self.long {
4502 Some(long) => vec![long],
4503 None => return None,
4504 };
4505 if let Some(aliases) = self.get_visible_aliases() {
4506 longs.extend(aliases);
4507 }
4508 Some(longs)
4509 }
4510
4511 /// Deprecated, replaced with [`Arg::get_value_parser().possible_values()`]
4512 #[cfg_attr(
4513 feature = "deprecated",
4514 deprecated(
4515 since = "3.2.0",
4516 note = "Replaced with `Arg::get_value_parser().possible_values()`"
4517 )
4518 )]
get_possible_values(&self) -> Option<&[PossibleValue<'help>]>4519 pub fn get_possible_values(&self) -> Option<&[PossibleValue<'help>]> {
4520 if self.possible_vals.is_empty() {
4521 None
4522 } else {
4523 Some(&self.possible_vals)
4524 }
4525 }
4526
get_possible_values2(&self) -> Vec<PossibleValue<'help>>4527 pub(crate) fn get_possible_values2(&self) -> Vec<PossibleValue<'help>> {
4528 #![allow(deprecated)]
4529 if !self.is_takes_value_set() {
4530 vec![]
4531 } else if let Some(pvs) = self.get_possible_values() {
4532 // Check old first in case the user explicitly set possible values and the derive inferred
4533 // a `ValueParser` with some.
4534 pvs.to_vec()
4535 } else {
4536 self.get_value_parser()
4537 .possible_values()
4538 .map(|pvs| pvs.collect())
4539 .unwrap_or_default()
4540 }
4541 }
4542
4543 /// Get the names of values for this argument.
4544 #[inline]
get_value_names(&self) -> Option<&[&'help str]>4545 pub fn get_value_names(&self) -> Option<&[&'help str]> {
4546 if self.val_names.is_empty() {
4547 None
4548 } else {
4549 Some(&self.val_names)
4550 }
4551 }
4552
4553 /// Get the number of values for this argument.
4554 #[inline]
get_num_vals(&self) -> Option<usize>4555 pub fn get_num_vals(&self) -> Option<usize> {
4556 self.num_vals
4557 }
4558
4559 /// Get the delimiter between multiple values
4560 #[inline]
get_value_delimiter(&self) -> Option<char>4561 pub fn get_value_delimiter(&self) -> Option<char> {
4562 self.val_delim
4563 }
4564
4565 /// Get the index of this argument, if any
4566 #[inline]
get_index(&self) -> Option<usize>4567 pub fn get_index(&self) -> Option<usize> {
4568 self.index
4569 }
4570
4571 /// Get the value hint of this argument
get_value_hint(&self) -> ValueHint4572 pub fn get_value_hint(&self) -> ValueHint {
4573 self.value_hint.unwrap_or_else(|| {
4574 if self.is_takes_value_set() {
4575 let type_id = self.get_value_parser().type_id();
4576 if type_id == crate::parser::AnyValueId::of::<std::path::PathBuf>() {
4577 ValueHint::AnyPath
4578 } else {
4579 ValueHint::default()
4580 }
4581 } else {
4582 ValueHint::default()
4583 }
4584 })
4585 }
4586
4587 /// Deprecated, replaced with [`Arg::is_global_set`]
4588 #[cfg_attr(
4589 feature = "deprecated",
4590 deprecated(since = "3.1.0", note = "Replaced with `Arg::is_global_set`")
4591 )]
get_global(&self) -> bool4592 pub fn get_global(&self) -> bool {
4593 self.is_global_set()
4594 }
4595
4596 /// Get the environment variable name specified for this argument, if any
4597 ///
4598 /// # Examples
4599 ///
4600 /// ```rust
4601 /// # use std::ffi::OsStr;
4602 /// # use clap::Arg;
4603 /// let arg = Arg::new("foo").env("ENVIRONMENT");
4604 /// assert_eq!(Some(OsStr::new("ENVIRONMENT")), arg.get_env());
4605 /// ```
4606 #[cfg(feature = "env")]
get_env(&self) -> Option<&OsStr>4607 pub fn get_env(&self) -> Option<&OsStr> {
4608 self.env.as_ref().map(|x| x.0)
4609 }
4610
4611 /// Get the default values specified for this argument, if any
4612 ///
4613 /// # Examples
4614 ///
4615 /// ```rust
4616 /// # use clap::Arg;
4617 /// let arg = Arg::new("foo").default_value("default value");
4618 /// assert_eq!(&["default value"], arg.get_default_values());
4619 /// ```
get_default_values(&self) -> &[&OsStr]4620 pub fn get_default_values(&self) -> &[&OsStr] {
4621 &self.default_vals
4622 }
4623
4624 /// Checks whether this argument is a positional or not.
4625 ///
4626 /// # Examples
4627 ///
4628 /// ```
4629 /// # use clap::Arg;
4630 /// let arg = Arg::new("foo");
4631 /// assert_eq!(true, arg.is_positional());
4632 ///
4633 /// let arg = Arg::new("foo").long("foo");
4634 /// assert_eq!(false, arg.is_positional());
4635 /// ```
is_positional(&self) -> bool4636 pub fn is_positional(&self) -> bool {
4637 self.long.is_none() && self.short.is_none()
4638 }
4639
4640 /// Reports whether [`Arg::required`] is set
is_required_set(&self) -> bool4641 pub fn is_required_set(&self) -> bool {
4642 self.is_set(ArgSettings::Required)
4643 }
4644
4645 /// Report whether [`Arg::multiple_values`] is set
is_multiple_values_set(&self) -> bool4646 pub fn is_multiple_values_set(&self) -> bool {
4647 self.is_set(ArgSettings::MultipleValues)
4648 }
4649
4650 /// [`Arg::multiple_occurrences`] is going away ([Issue #3772](https://github.com/clap-rs/clap/issues/3772))
4651 #[cfg_attr(
4652 feature = "deprecated",
4653 deprecated(since = "3.2.0", note = "`multiple_occurrences` away (Issue #3772)")
4654 )]
is_multiple_occurrences_set(&self) -> bool4655 pub fn is_multiple_occurrences_set(&self) -> bool {
4656 self.is_set(ArgSettings::MultipleOccurrences)
4657 }
4658
4659 /// Report whether [`Arg::is_takes_value_set`] is set
is_takes_value_set(&self) -> bool4660 pub fn is_takes_value_set(&self) -> bool {
4661 self.is_set(ArgSettings::TakesValue)
4662 }
4663
4664 /// Report whether [`Arg::allow_hyphen_values`] is set
is_allow_hyphen_values_set(&self) -> bool4665 pub fn is_allow_hyphen_values_set(&self) -> bool {
4666 self.is_set(ArgSettings::AllowHyphenValues)
4667 }
4668
4669 /// Deprecated, replaced with [`Arg::get_value_parser()`]
4670 #[cfg_attr(
4671 feature = "deprecated",
4672 deprecated(since = "3.2.0", note = "Replaced with `Arg::get_value_parser()`")
4673 )]
is_forbid_empty_values_set(&self) -> bool4674 pub fn is_forbid_empty_values_set(&self) -> bool {
4675 self.is_set(ArgSettings::ForbidEmptyValues)
4676 }
4677
4678 /// Deprecated, replaced with [`Arg::get_value_parser()`
4679 #[cfg_attr(
4680 feature = "deprecated",
4681 deprecated(since = "3.2.0", note = "Replaced with `Arg::get_value_parser()`")
4682 )]
is_allow_invalid_utf8_set(&self) -> bool4683 pub fn is_allow_invalid_utf8_set(&self) -> bool {
4684 self.is_set(ArgSettings::AllowInvalidUtf8)
4685 }
4686
4687 /// Behavior when parsing the argument
get_action(&self) -> &super::ArgAction4688 pub fn get_action(&self) -> &super::ArgAction {
4689 const DEFAULT: super::ArgAction = super::ArgAction::StoreValue;
4690 self.action.as_ref().unwrap_or(&DEFAULT)
4691 }
4692
4693 /// Configured parser for argument values
4694 ///
4695 /// # Example
4696 ///
4697 /// ```rust
4698 /// let cmd = clap::Command::new("raw")
4699 /// .arg(
4700 /// clap::Arg::new("port")
4701 /// .value_parser(clap::value_parser!(usize))
4702 /// );
4703 /// let value_parser = cmd.get_arguments()
4704 /// .find(|a| a.get_id() == "port").unwrap()
4705 /// .get_value_parser();
4706 /// println!("{:?}", value_parser);
4707 /// ```
get_value_parser(&self) -> &super::ValueParser4708 pub fn get_value_parser(&self) -> &super::ValueParser {
4709 if let Some(value_parser) = self.value_parser.as_ref() {
4710 value_parser
4711 } else if self.is_allow_invalid_utf8_set() {
4712 static DEFAULT: super::ValueParser = super::ValueParser::os_string();
4713 &DEFAULT
4714 } else {
4715 static DEFAULT: super::ValueParser = super::ValueParser::string();
4716 &DEFAULT
4717 }
4718 }
4719
4720 /// Report whether [`Arg::global`] is set
is_global_set(&self) -> bool4721 pub fn is_global_set(&self) -> bool {
4722 self.is_set(ArgSettings::Global)
4723 }
4724
4725 /// Report whether [`Arg::next_line_help`] is set
is_next_line_help_set(&self) -> bool4726 pub fn is_next_line_help_set(&self) -> bool {
4727 self.is_set(ArgSettings::NextLineHelp)
4728 }
4729
4730 /// Report whether [`Arg::hide`] is set
is_hide_set(&self) -> bool4731 pub fn is_hide_set(&self) -> bool {
4732 self.is_set(ArgSettings::Hidden)
4733 }
4734
4735 /// Report whether [`Arg::hide_default_value`] is set
is_hide_default_value_set(&self) -> bool4736 pub fn is_hide_default_value_set(&self) -> bool {
4737 self.is_set(ArgSettings::HideDefaultValue)
4738 }
4739
4740 /// Report whether [`Arg::hide_possible_values`] is set
is_hide_possible_values_set(&self) -> bool4741 pub fn is_hide_possible_values_set(&self) -> bool {
4742 self.is_set(ArgSettings::HidePossibleValues)
4743 }
4744
4745 /// Report whether [`Arg::hide_env`] is set
4746 #[cfg(feature = "env")]
is_hide_env_set(&self) -> bool4747 pub fn is_hide_env_set(&self) -> bool {
4748 self.is_set(ArgSettings::HideEnv)
4749 }
4750
4751 /// Report whether [`Arg::hide_env_values`] is set
4752 #[cfg(feature = "env")]
is_hide_env_values_set(&self) -> bool4753 pub fn is_hide_env_values_set(&self) -> bool {
4754 self.is_set(ArgSettings::HideEnvValues)
4755 }
4756
4757 /// Report whether [`Arg::hide_short_help`] is set
is_hide_short_help_set(&self) -> bool4758 pub fn is_hide_short_help_set(&self) -> bool {
4759 self.is_set(ArgSettings::HiddenShortHelp)
4760 }
4761
4762 /// Report whether [`Arg::hide_long_help`] is set
is_hide_long_help_set(&self) -> bool4763 pub fn is_hide_long_help_set(&self) -> bool {
4764 self.is_set(ArgSettings::HiddenLongHelp)
4765 }
4766
4767 /// Report whether [`Arg::use_value_delimiter`] is set
is_use_value_delimiter_set(&self) -> bool4768 pub fn is_use_value_delimiter_set(&self) -> bool {
4769 self.is_set(ArgSettings::UseValueDelimiter)
4770 }
4771
4772 /// Report whether [`Arg::require_value_delimiter`] is set
is_require_value_delimiter_set(&self) -> bool4773 pub fn is_require_value_delimiter_set(&self) -> bool {
4774 self.is_set(ArgSettings::RequireDelimiter)
4775 }
4776
4777 /// Report whether [`Arg::require_equals`] is set
is_require_equals_set(&self) -> bool4778 pub fn is_require_equals_set(&self) -> bool {
4779 self.is_set(ArgSettings::RequireEquals)
4780 }
4781
4782 /// Reports whether [`Arg::exclusive`] is set
is_exclusive_set(&self) -> bool4783 pub fn is_exclusive_set(&self) -> bool {
4784 self.is_set(ArgSettings::Exclusive)
4785 }
4786
4787 /// Reports whether [`Arg::last`] is set
is_last_set(&self) -> bool4788 pub fn is_last_set(&self) -> bool {
4789 self.is_set(ArgSettings::Last)
4790 }
4791
4792 /// Reports whether [`Arg::ignore_case`] is set
is_ignore_case_set(&self) -> bool4793 pub fn is_ignore_case_set(&self) -> bool {
4794 self.is_set(ArgSettings::IgnoreCase)
4795 }
4796 }
4797
4798 /// # Deprecated
4799 impl<'help> Arg<'help> {
4800 /// Deprecated, replaced with [`Arg::new`]
4801 #[cfg_attr(
4802 feature = "deprecated",
4803 deprecated(since = "3.0.0", note = "Replaced with `Arg::new`")
4804 )]
4805 #[doc(hidden)]
with_name<S: Into<&'help str>>(n: S) -> Self4806 pub fn with_name<S: Into<&'help str>>(n: S) -> Self {
4807 Self::new(n)
4808 }
4809
4810 /// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case?
4811 #[cfg(feature = "yaml")]
4812 #[cfg_attr(
4813 feature = "deprecated",
4814 deprecated(
4815 since = "3.0.0",
4816 note = "Deprecated in Issue #3087, maybe clap::Parser would fit your use case?"
4817 )
4818 )]
4819 #[doc(hidden)]
from_yaml(y: &'help Yaml) -> Self4820 pub fn from_yaml(y: &'help Yaml) -> Self {
4821 #![allow(deprecated)]
4822 let yaml_file_hash = y.as_hash().expect("YAML file must be a hash");
4823 // We WANT this to panic on error...so expect() is good.
4824 let (name_yaml, yaml) = yaml_file_hash
4825 .iter()
4826 .next()
4827 .expect("There must be one arg in the YAML file");
4828 let name_str = name_yaml.as_str().expect("Arg name must be a string");
4829 let mut a = Arg::new(name_str);
4830
4831 for (k, v) in yaml.as_hash().expect("Arg must be a hash") {
4832 a = match k.as_str().expect("Arg fields must be strings") {
4833 "short" => yaml_to_char!(a, v, short),
4834 "long" => yaml_to_str!(a, v, long),
4835 "aliases" => yaml_vec_or_str!(a, v, alias),
4836 "help" => yaml_to_str!(a, v, help),
4837 "long_help" => yaml_to_str!(a, v, long_help),
4838 "required" => yaml_to_bool!(a, v, required),
4839 "required_if" => yaml_tuple2!(a, v, required_if_eq),
4840 "required_ifs" => yaml_tuple2!(a, v, required_if_eq),
4841 "takes_value" => yaml_to_bool!(a, v, takes_value),
4842 "index" => yaml_to_usize!(a, v, index),
4843 "global" => yaml_to_bool!(a, v, global),
4844 "multiple" => yaml_to_bool!(a, v, multiple),
4845 "hidden" => yaml_to_bool!(a, v, hide),
4846 "next_line_help" => yaml_to_bool!(a, v, next_line_help),
4847 "group" => yaml_to_str!(a, v, group),
4848 "number_of_values" => yaml_to_usize!(a, v, number_of_values),
4849 "max_values" => yaml_to_usize!(a, v, max_values),
4850 "min_values" => yaml_to_usize!(a, v, min_values),
4851 "value_name" => yaml_to_str!(a, v, value_name),
4852 "use_delimiter" => yaml_to_bool!(a, v, use_delimiter),
4853 "allow_hyphen_values" => yaml_to_bool!(a, v, allow_hyphen_values),
4854 "last" => yaml_to_bool!(a, v, last),
4855 "require_delimiter" => yaml_to_bool!(a, v, require_delimiter),
4856 "value_delimiter" => yaml_to_char!(a, v, value_delimiter),
4857 "required_unless" => yaml_to_str!(a, v, required_unless_present),
4858 "display_order" => yaml_to_usize!(a, v, display_order),
4859 "default_value" => yaml_to_str!(a, v, default_value),
4860 "default_value_if" => yaml_tuple3!(a, v, default_value_if),
4861 "default_value_ifs" => yaml_tuple3!(a, v, default_value_if),
4862 #[cfg(feature = "env")]
4863 "env" => yaml_to_str!(a, v, env),
4864 "value_names" => yaml_vec_or_str!(a, v, value_name),
4865 "groups" => yaml_vec_or_str!(a, v, group),
4866 "requires" => yaml_vec_or_str!(a, v, requires),
4867 "requires_if" => yaml_tuple2!(a, v, requires_if),
4868 "requires_ifs" => yaml_tuple2!(a, v, requires_if),
4869 "conflicts_with" => yaml_vec_or_str!(a, v, conflicts_with),
4870 "overrides_with" => yaml_to_str!(a, v, overrides_with),
4871 "possible_values" => yaml_vec_or_str!(a, v, possible_value),
4872 "case_insensitive" => yaml_to_bool!(a, v, ignore_case),
4873 "required_unless_one" => yaml_vec!(a, v, required_unless_present_any),
4874 "required_unless_all" => yaml_vec!(a, v, required_unless_present_all),
4875 s => {
4876 panic!(
4877 "Unknown setting '{}' in YAML file for arg '{}'",
4878 s, name_str
4879 )
4880 }
4881 }
4882 }
4883
4884 a
4885 }
4886
4887 /// Deprecated in [Issue #3086](https://github.com/clap-rs/clap/issues/3086), see [`arg!`][crate::arg!].
4888 #[cfg_attr(
4889 feature = "deprecated",
4890 deprecated(since = "3.0.0", note = "Deprecated in Issue #3086, see `clap::arg!")
4891 )]
4892 #[doc(hidden)]
from_usage(u: &'help str) -> Self4893 pub fn from_usage(u: &'help str) -> Self {
4894 UsageParser::from_usage(u).parse()
4895 }
4896
4897 /// Deprecated, replaced with [`Arg::required_unless_present`]
4898 #[cfg_attr(
4899 feature = "deprecated",
4900 deprecated(since = "3.0.0", note = "Replaced with `Arg::required_unless_present`")
4901 )]
4902 #[doc(hidden)]
4903 #[must_use]
required_unless<T: Key>(self, arg_id: T) -> Self4904 pub fn required_unless<T: Key>(self, arg_id: T) -> Self {
4905 self.required_unless_present(arg_id)
4906 }
4907
4908 /// Deprecated, replaced with [`Arg::required_unless_present_all`]
4909 #[cfg_attr(
4910 feature = "deprecated",
4911 deprecated(
4912 since = "3.0.0",
4913 note = "Replaced with `Arg::required_unless_present_all`"
4914 )
4915 )]
4916 #[doc(hidden)]
4917 #[must_use]
required_unless_all<T, I>(self, names: I) -> Self where I: IntoIterator<Item = T>, T: Key,4918 pub fn required_unless_all<T, I>(self, names: I) -> Self
4919 where
4920 I: IntoIterator<Item = T>,
4921 T: Key,
4922 {
4923 self.required_unless_present_all(names)
4924 }
4925
4926 /// Deprecated, replaced with [`Arg::required_unless_present_any`]
4927 #[cfg_attr(
4928 feature = "deprecated",
4929 deprecated(
4930 since = "3.0.0",
4931 note = "Replaced with `Arg::required_unless_present_any`"
4932 )
4933 )]
4934 #[doc(hidden)]
4935 #[must_use]
required_unless_one<T, I>(self, names: I) -> Self where I: IntoIterator<Item = T>, T: Key,4936 pub fn required_unless_one<T, I>(self, names: I) -> Self
4937 where
4938 I: IntoIterator<Item = T>,
4939 T: Key,
4940 {
4941 self.required_unless_present_any(names)
4942 }
4943
4944 /// Deprecated, replaced with [`Arg::required_if_eq`]
4945 #[cfg_attr(
4946 feature = "deprecated",
4947 deprecated(since = "3.0.0", note = "Replaced with `Arg::required_if_eq`")
4948 )]
4949 #[doc(hidden)]
4950 #[must_use]
required_if<T: Key>(self, arg_id: T, val: &'help str) -> Self4951 pub fn required_if<T: Key>(self, arg_id: T, val: &'help str) -> Self {
4952 self.required_if_eq(arg_id, val)
4953 }
4954
4955 /// Deprecated, replaced with [`Arg::required_if_eq_any`]
4956 #[cfg_attr(
4957 feature = "deprecated",
4958 deprecated(since = "3.0.0", note = "Replaced with `Arg::required_if_eq_any`")
4959 )]
4960 #[doc(hidden)]
4961 #[must_use]
required_ifs<T: Key>(self, ifs: &[(T, &'help str)]) -> Self4962 pub fn required_ifs<T: Key>(self, ifs: &[(T, &'help str)]) -> Self {
4963 self.required_if_eq_any(ifs)
4964 }
4965
4966 /// Deprecated, replaced with [`Arg::hide`]
4967 #[cfg_attr(
4968 feature = "deprecated",
4969 deprecated(since = "3.0.0", note = "Replaced with `Arg::hide`")
4970 )]
4971 #[doc(hidden)]
4972 #[inline]
4973 #[must_use]
hidden(self, yes: bool) -> Self4974 pub fn hidden(self, yes: bool) -> Self {
4975 self.hide(yes)
4976 }
4977
4978 /// Deprecated, replaced with [`Arg::ignore_case`]
4979 #[cfg_attr(
4980 feature = "deprecated",
4981 deprecated(since = "3.0.0", note = "Replaced with `Arg::ignore_case`")
4982 )]
4983 #[doc(hidden)]
4984 #[inline]
4985 #[must_use]
case_insensitive(self, yes: bool) -> Self4986 pub fn case_insensitive(self, yes: bool) -> Self {
4987 self.ignore_case(yes)
4988 }
4989
4990 /// Deprecated, replaced with [`Arg::forbid_empty_values`]
4991 #[cfg_attr(
4992 feature = "deprecated",
4993 deprecated(since = "3.0.0", note = "Replaced with `Arg::forbid_empty_values`")
4994 )]
4995 #[doc(hidden)]
4996 #[must_use]
empty_values(self, yes: bool) -> Self4997 pub fn empty_values(self, yes: bool) -> Self {
4998 self.forbid_empty_values(!yes)
4999 }
5000
5001 /// Deprecated, replaced with [`Arg::multiple_occurrences`] (most likely what you want) and
5002 /// [`Arg::multiple_values`]
5003 #[cfg_attr(
5004 feature = "deprecated",
5005 deprecated(
5006 since = "3.0.0",
5007 note = "Split into `Arg::multiple_occurrences` (most likely what you want) and `Arg::multiple_values`"
5008 )
5009 )]
5010 #[doc(hidden)]
5011 #[must_use]
multiple(self, yes: bool) -> Self5012 pub fn multiple(self, yes: bool) -> Self {
5013 self.multiple_occurrences(yes).multiple_values(yes)
5014 }
5015
5016 /// Deprecated, replaced with [`Arg::hide_short_help`]
5017 #[cfg_attr(
5018 feature = "deprecated",
5019 deprecated(since = "3.0.0", note = "Replaced with `Arg::hide_short_help`")
5020 )]
5021 #[doc(hidden)]
5022 #[inline]
5023 #[must_use]
hidden_short_help(self, yes: bool) -> Self5024 pub fn hidden_short_help(self, yes: bool) -> Self {
5025 self.hide_short_help(yes)
5026 }
5027
5028 /// Deprecated, replaced with [`Arg::hide_long_help`]
5029 #[cfg_attr(
5030 feature = "deprecated",
5031 deprecated(since = "3.0.0", note = "Replaced with `Arg::hide_long_help`")
5032 )]
5033 #[doc(hidden)]
5034 #[inline]
5035 #[must_use]
hidden_long_help(self, yes: bool) -> Self5036 pub fn hidden_long_help(self, yes: bool) -> Self {
5037 self.hide_long_help(yes)
5038 }
5039
5040 /// Deprecated, replaced with [`Arg::setting`]
5041 #[cfg_attr(
5042 feature = "deprecated",
5043 deprecated(since = "3.0.0", note = "Replaced with `Arg::setting`")
5044 )]
5045 #[doc(hidden)]
5046 #[must_use]
set(self, s: ArgSettings) -> Self5047 pub fn set(self, s: ArgSettings) -> Self {
5048 self.setting(s)
5049 }
5050
5051 /// Deprecated, replaced with [`Arg::unset_setting`]
5052 #[cfg_attr(
5053 feature = "deprecated",
5054 deprecated(since = "3.0.0", note = "Replaced with `Arg::unset_setting`")
5055 )]
5056 #[doc(hidden)]
5057 #[must_use]
unset(self, s: ArgSettings) -> Self5058 pub fn unset(self, s: ArgSettings) -> Self {
5059 self.unset_setting(s)
5060 }
5061 }
5062
5063 /// # Internally used only
5064 impl<'help> Arg<'help> {
_build(&mut self)5065 pub(crate) fn _build(&mut self) {
5066 if self.is_positional() {
5067 self.settings.set(ArgSettings::TakesValue);
5068 }
5069 if let Some(action) = self.action.as_ref() {
5070 if let Some(default_value) = action.default_value() {
5071 if self.default_vals.is_empty() {
5072 self.default_vals = vec![default_value];
5073 }
5074 }
5075 if action.takes_values() {
5076 self.settings.set(ArgSettings::TakesValue);
5077 } else {
5078 self.settings.unset(ArgSettings::TakesValue);
5079 }
5080 match action {
5081 ArgAction::StoreValue
5082 | ArgAction::IncOccurrence
5083 | ArgAction::Help
5084 | ArgAction::Version => {}
5085 ArgAction::Set
5086 | ArgAction::Append
5087 | ArgAction::SetTrue
5088 | ArgAction::SetFalse
5089 | ArgAction::Count => {
5090 if !self.is_positional() {
5091 self.settings.set(ArgSettings::MultipleOccurrences);
5092 }
5093 }
5094 }
5095 }
5096
5097 if self.value_parser.is_none() {
5098 if let Some(default) = self.action.as_ref().and_then(|a| a.default_value_parser()) {
5099 self.value_parser = Some(default);
5100 } else if self.is_allow_invalid_utf8_set() {
5101 self.value_parser = Some(super::ValueParser::os_string());
5102 } else {
5103 self.value_parser = Some(super::ValueParser::string());
5104 }
5105 }
5106
5107 if (self.is_use_value_delimiter_set() || self.is_require_value_delimiter_set())
5108 && self.val_delim.is_none()
5109 {
5110 self.val_delim = Some(',');
5111 }
5112
5113 let val_names_len = self.val_names.len();
5114
5115 if val_names_len > 1 {
5116 self.settings.set(ArgSettings::MultipleValues);
5117
5118 if self.num_vals.is_none() {
5119 self.num_vals = Some(val_names_len);
5120 }
5121 }
5122
5123 let self_id = self.id.clone();
5124 if self.is_positional() || self.is_multiple_occurrences_set() {
5125 // Remove self-overrides where they don't make sense.
5126 //
5127 // We can evaluate switching this to a debug assert at a later time (though it will
5128 // require changing propagation of `AllArgsOverrideSelf`). Being conservative for now
5129 // due to where we are at in the release.
5130 self.overrides.retain(|e| *e != self_id);
5131 }
5132 }
5133
generated(mut self) -> Self5134 pub(crate) fn generated(mut self) -> Self {
5135 self.provider = ArgProvider::Generated;
5136 self
5137 }
5138
longest_filter(&self) -> bool5139 pub(crate) fn longest_filter(&self) -> bool {
5140 self.is_takes_value_set() || self.long.is_some() || self.short.is_none()
5141 }
5142
5143 // Used for positionals when printing
multiple_str(&self) -> &str5144 pub(crate) fn multiple_str(&self) -> &str {
5145 let mult_vals = self.val_names.len() > 1;
5146 if (self.is_multiple_values_set() || self.is_multiple_occurrences_set()) && !mult_vals {
5147 "..."
5148 } else {
5149 ""
5150 }
5151 }
5152
5153 // Used for positionals when printing
name_no_brackets(&self) -> Cow<str>5154 pub(crate) fn name_no_brackets(&self) -> Cow<str> {
5155 debug!("Arg::name_no_brackets:{}", self.name);
5156 let delim = if self.is_require_value_delimiter_set() {
5157 self.val_delim.expect(INTERNAL_ERROR_MSG)
5158 } else {
5159 ' '
5160 }
5161 .to_string();
5162 if !self.val_names.is_empty() {
5163 debug!("Arg::name_no_brackets: val_names={:#?}", self.val_names);
5164
5165 if self.val_names.len() > 1 {
5166 Cow::Owned(
5167 self.val_names
5168 .iter()
5169 .map(|n| format!("<{}>", n))
5170 .collect::<Vec<_>>()
5171 .join(&*delim),
5172 )
5173 } else {
5174 Cow::Borrowed(self.val_names.get(0).expect(INTERNAL_ERROR_MSG))
5175 }
5176 } else {
5177 debug!("Arg::name_no_brackets: just name");
5178 Cow::Borrowed(self.name)
5179 }
5180 }
5181
5182 /// Either multiple values or occurrences
is_multiple(&self) -> bool5183 pub(crate) fn is_multiple(&self) -> bool {
5184 self.is_multiple_values_set() | self.is_multiple_occurrences_set()
5185 }
5186
get_display_order(&self) -> usize5187 pub(crate) fn get_display_order(&self) -> usize {
5188 self.disp_ord.get_explicit()
5189 }
5190 }
5191
5192 impl<'help> From<&'_ Arg<'help>> for Arg<'help> {
from(a: &Arg<'help>) -> Self5193 fn from(a: &Arg<'help>) -> Self {
5194 a.clone()
5195 }
5196 }
5197
5198 impl<'help> PartialEq for Arg<'help> {
eq(&self, other: &Arg<'help>) -> bool5199 fn eq(&self, other: &Arg<'help>) -> bool {
5200 self.name == other.name
5201 }
5202 }
5203
5204 impl<'help> PartialOrd for Arg<'help> {
partial_cmp(&self, other: &Self) -> Option<Ordering>5205 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
5206 Some(self.cmp(other))
5207 }
5208 }
5209
5210 impl<'help> Ord for Arg<'help> {
cmp(&self, other: &Arg) -> Ordering5211 fn cmp(&self, other: &Arg) -> Ordering {
5212 self.name.cmp(other.name)
5213 }
5214 }
5215
5216 impl<'help> Eq for Arg<'help> {}
5217
5218 impl<'help> Display for Arg<'help> {
fmt(&self, f: &mut Formatter) -> fmt::Result5219 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
5220 // Write the name such --long or -l
5221 if let Some(l) = self.long {
5222 write!(f, "--{}", l)?;
5223 } else if let Some(s) = self.short {
5224 write!(f, "-{}", s)?;
5225 }
5226 let mut need_closing_bracket = false;
5227 if !self.is_positional() && self.is_takes_value_set() {
5228 let is_optional_val = self.min_vals == Some(0);
5229 let sep = if self.is_require_equals_set() {
5230 if is_optional_val {
5231 need_closing_bracket = true;
5232 "[="
5233 } else {
5234 "="
5235 }
5236 } else if is_optional_val {
5237 need_closing_bracket = true;
5238 " ["
5239 } else {
5240 " "
5241 };
5242 f.write_str(sep)?;
5243 }
5244 if self.is_takes_value_set() || self.is_positional() {
5245 display_arg_val(self, |s, _| f.write_str(s))?;
5246 }
5247 if need_closing_bracket {
5248 f.write_str("]")?;
5249 }
5250
5251 Ok(())
5252 }
5253 }
5254
5255 impl<'help> fmt::Debug for Arg<'help> {
fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error>5256 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
5257 let mut ds = f.debug_struct("Arg");
5258
5259 #[allow(unused_mut)]
5260 let mut ds = ds
5261 .field("id", &self.id)
5262 .field("provider", &self.provider)
5263 .field("name", &self.name)
5264 .field("help", &self.help)
5265 .field("long_help", &self.long_help)
5266 .field("action", &self.action)
5267 .field("value_parser", &self.value_parser)
5268 .field("blacklist", &self.blacklist)
5269 .field("settings", &self.settings)
5270 .field("overrides", &self.overrides)
5271 .field("groups", &self.groups)
5272 .field("requires", &self.requires)
5273 .field("r_ifs", &self.r_ifs)
5274 .field("r_unless", &self.r_unless)
5275 .field("short", &self.short)
5276 .field("long", &self.long)
5277 .field("aliases", &self.aliases)
5278 .field("short_aliases", &self.short_aliases)
5279 .field("disp_ord", &self.disp_ord)
5280 .field("possible_vals", &self.possible_vals)
5281 .field("val_names", &self.val_names)
5282 .field("num_vals", &self.num_vals)
5283 .field("max_vals", &self.max_vals)
5284 .field("min_vals", &self.min_vals)
5285 .field(
5286 "validator",
5287 &self.validator.as_ref().map_or("None", |_| "Some(FnMut)"),
5288 )
5289 .field(
5290 "validator_os",
5291 &self.validator_os.as_ref().map_or("None", |_| "Some(FnMut)"),
5292 )
5293 .field("val_delim", &self.val_delim)
5294 .field("default_vals", &self.default_vals)
5295 .field("default_vals_ifs", &self.default_vals_ifs)
5296 .field("terminator", &self.terminator)
5297 .field("index", &self.index)
5298 .field("help_heading", &self.help_heading)
5299 .field("value_hint", &self.value_hint)
5300 .field("default_missing_vals", &self.default_missing_vals);
5301
5302 #[cfg(feature = "env")]
5303 {
5304 ds = ds.field("env", &self.env);
5305 }
5306
5307 ds.finish()
5308 }
5309 }
5310
5311 type Validator<'a> = dyn FnMut(&str) -> Result<(), Box<dyn Error + Send + Sync>> + Send + 'a;
5312 type ValidatorOs<'a> = dyn FnMut(&OsStr) -> Result<(), Box<dyn Error + Send + Sync>> + Send + 'a;
5313
5314 #[derive(Debug, Clone, Eq, PartialEq)]
5315 pub(crate) enum ArgProvider {
5316 Generated,
5317 GeneratedMutated,
5318 User,
5319 }
5320
5321 impl Default for ArgProvider {
default() -> Self5322 fn default() -> Self {
5323 ArgProvider::User
5324 }
5325 }
5326
5327 /// Write the values such as <name1> <name2>
display_arg_val<F, T, E>(arg: &Arg, mut write: F) -> Result<(), E> where F: FnMut(&str, bool) -> Result<T, E>,5328 pub(crate) fn display_arg_val<F, T, E>(arg: &Arg, mut write: F) -> Result<(), E>
5329 where
5330 F: FnMut(&str, bool) -> Result<T, E>,
5331 {
5332 let mult_val = arg.is_multiple_values_set();
5333 let mult_occ = arg.is_multiple_occurrences_set();
5334 let delim = if arg.is_require_value_delimiter_set() {
5335 arg.val_delim.expect(INTERNAL_ERROR_MSG)
5336 } else {
5337 ' '
5338 }
5339 .to_string();
5340 if !arg.val_names.is_empty() {
5341 // If have val_name.
5342 match (arg.val_names.len(), arg.num_vals) {
5343 (1, Some(num_vals)) => {
5344 // If single value name with multiple num_of_vals, display all
5345 // the values with the single value name.
5346 let arg_name = format!("<{}>", arg.val_names.get(0).unwrap());
5347 for n in 1..=num_vals {
5348 write(&arg_name, true)?;
5349 if n != num_vals {
5350 write(&delim, false)?;
5351 }
5352 }
5353 }
5354 (num_val_names, _) => {
5355 // If multiple value names, display them sequentially(ignore num of vals).
5356 let mut it = arg.val_names.iter().peekable();
5357 while let Some(val) = it.next() {
5358 write(&format!("<{}>", val), true)?;
5359 if it.peek().is_some() {
5360 write(&delim, false)?;
5361 }
5362 }
5363 if (num_val_names == 1 && mult_val)
5364 || (arg.is_positional() && mult_occ)
5365 || num_val_names < arg.num_vals.unwrap_or(0)
5366 {
5367 write("...", true)?;
5368 }
5369 }
5370 }
5371 } else if let Some(num_vals) = arg.num_vals {
5372 // If number_of_values is specified, display the value multiple times.
5373 let arg_name = format!("<{}>", arg.name);
5374 for n in 1..=num_vals {
5375 write(&arg_name, true)?;
5376 if n != num_vals {
5377 write(&delim, false)?;
5378 }
5379 }
5380 } else if arg.is_positional() {
5381 // Value of positional argument with no num_vals and val_names.
5382 write(&format!("<{}>", arg.name), true)?;
5383
5384 if mult_val || mult_occ {
5385 write("...", true)?;
5386 }
5387 } else {
5388 // value of flag argument with no num_vals and val_names.
5389 write(&format!("<{}>", arg.name), true)?;
5390 if mult_val {
5391 write("...", true)?;
5392 }
5393 }
5394 Ok(())
5395 }
5396
5397 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
5398 pub(crate) enum DisplayOrder {
5399 None,
5400 Implicit(usize),
5401 Explicit(usize),
5402 }
5403
5404 impl DisplayOrder {
set_explicit(&mut self, explicit: usize)5405 pub(crate) fn set_explicit(&mut self, explicit: usize) {
5406 *self = Self::Explicit(explicit)
5407 }
5408
set_implicit(&mut self, implicit: usize)5409 pub(crate) fn set_implicit(&mut self, implicit: usize) {
5410 *self = (*self).max(Self::Implicit(implicit))
5411 }
5412
make_explicit(&mut self)5413 pub(crate) fn make_explicit(&mut self) {
5414 match *self {
5415 Self::None | Self::Explicit(_) => {}
5416 Self::Implicit(disp) => self.set_explicit(disp),
5417 }
5418 }
5419
get_explicit(self) -> usize5420 pub(crate) fn get_explicit(self) -> usize {
5421 match self {
5422 Self::None | Self::Implicit(_) => 999,
5423 Self::Explicit(disp) => disp,
5424 }
5425 }
5426 }
5427
5428 impl Default for DisplayOrder {
default() -> Self5429 fn default() -> Self {
5430 Self::None
5431 }
5432 }
5433
5434 // Flags
5435 #[cfg(test)]
5436 mod test {
5437 use super::Arg;
5438
5439 #[test]
flag_display()5440 fn flag_display() {
5441 let mut f = Arg::new("flg").multiple_occurrences(true);
5442 f.long = Some("flag");
5443
5444 assert_eq!(f.to_string(), "--flag");
5445
5446 let mut f2 = Arg::new("flg");
5447 f2.short = Some('f');
5448
5449 assert_eq!(f2.to_string(), "-f");
5450 }
5451
5452 #[test]
flag_display_single_alias()5453 fn flag_display_single_alias() {
5454 let mut f = Arg::new("flg");
5455 f.long = Some("flag");
5456 f.aliases = vec![("als", true)];
5457
5458 assert_eq!(f.to_string(), "--flag")
5459 }
5460
5461 #[test]
flag_display_multiple_aliases()5462 fn flag_display_multiple_aliases() {
5463 let mut f = Arg::new("flg");
5464 f.short = Some('f');
5465 f.aliases = vec![
5466 ("alias_not_visible", false),
5467 ("f2", true),
5468 ("f3", true),
5469 ("f4", true),
5470 ];
5471 assert_eq!(f.to_string(), "-f");
5472 }
5473
5474 #[test]
flag_display_single_short_alias()5475 fn flag_display_single_short_alias() {
5476 let mut f = Arg::new("flg");
5477 f.short = Some('a');
5478 f.short_aliases = vec![('b', true)];
5479
5480 assert_eq!(f.to_string(), "-a")
5481 }
5482
5483 #[test]
flag_display_multiple_short_aliases()5484 fn flag_display_multiple_short_aliases() {
5485 let mut f = Arg::new("flg");
5486 f.short = Some('a');
5487 f.short_aliases = vec![('b', false), ('c', true), ('d', true), ('e', true)];
5488 assert_eq!(f.to_string(), "-a");
5489 }
5490
5491 // Options
5492
5493 #[test]
option_display_multiple_occurrences()5494 fn option_display_multiple_occurrences() {
5495 let o = Arg::new("opt")
5496 .long("option")
5497 .takes_value(true)
5498 .multiple_occurrences(true);
5499
5500 assert_eq!(o.to_string(), "--option <opt>");
5501 }
5502
5503 #[test]
option_display_multiple_values()5504 fn option_display_multiple_values() {
5505 let o = Arg::new("opt")
5506 .long("option")
5507 .takes_value(true)
5508 .multiple_values(true);
5509
5510 assert_eq!(o.to_string(), "--option <opt>...");
5511 }
5512
5513 #[test]
option_display2()5514 fn option_display2() {
5515 let o2 = Arg::new("opt").short('o').value_names(&["file", "name"]);
5516
5517 assert_eq!(o2.to_string(), "-o <file> <name>");
5518 }
5519
5520 #[test]
option_display3()5521 fn option_display3() {
5522 let o2 = Arg::new("opt")
5523 .short('o')
5524 .takes_value(true)
5525 .multiple_values(true)
5526 .value_names(&["file", "name"]);
5527
5528 assert_eq!(o2.to_string(), "-o <file> <name>");
5529 }
5530
5531 #[test]
option_display_single_alias()5532 fn option_display_single_alias() {
5533 let o = Arg::new("opt")
5534 .takes_value(true)
5535 .long("option")
5536 .visible_alias("als");
5537
5538 assert_eq!(o.to_string(), "--option <opt>");
5539 }
5540
5541 #[test]
option_display_multiple_aliases()5542 fn option_display_multiple_aliases() {
5543 let o = Arg::new("opt")
5544 .long("option")
5545 .takes_value(true)
5546 .visible_aliases(&["als2", "als3", "als4"])
5547 .alias("als_not_visible");
5548
5549 assert_eq!(o.to_string(), "--option <opt>");
5550 }
5551
5552 #[test]
option_display_single_short_alias()5553 fn option_display_single_short_alias() {
5554 let o = Arg::new("opt")
5555 .takes_value(true)
5556 .short('a')
5557 .visible_short_alias('b');
5558
5559 assert_eq!(o.to_string(), "-a <opt>");
5560 }
5561
5562 #[test]
option_display_multiple_short_aliases()5563 fn option_display_multiple_short_aliases() {
5564 let o = Arg::new("opt")
5565 .short('a')
5566 .takes_value(true)
5567 .visible_short_aliases(&['b', 'c', 'd'])
5568 .short_alias('e');
5569
5570 assert_eq!(o.to_string(), "-a <opt>");
5571 }
5572
5573 // Positionals
5574
5575 #[test]
positional_display_multiple_values()5576 fn positional_display_multiple_values() {
5577 let p = Arg::new("pos")
5578 .index(1)
5579 .takes_value(true)
5580 .multiple_values(true);
5581
5582 assert_eq!(p.to_string(), "<pos>...");
5583 }
5584
5585 #[test]
positional_display_multiple_occurrences()5586 fn positional_display_multiple_occurrences() {
5587 let p = Arg::new("pos")
5588 .index(1)
5589 .takes_value(true)
5590 .multiple_occurrences(true);
5591
5592 assert_eq!(p.to_string(), "<pos>...");
5593 }
5594
5595 #[test]
positional_display_required()5596 fn positional_display_required() {
5597 let p2 = Arg::new("pos").index(1).required(true);
5598
5599 assert_eq!(p2.to_string(), "<pos>");
5600 }
5601
5602 #[test]
positional_display_val_names()5603 fn positional_display_val_names() {
5604 let p2 = Arg::new("pos").index(1).value_names(&["file1", "file2"]);
5605
5606 assert_eq!(p2.to_string(), "<file1> <file2>");
5607 }
5608
5609 #[test]
positional_display_val_names_req()5610 fn positional_display_val_names_req() {
5611 let p2 = Arg::new("pos")
5612 .index(1)
5613 .required(true)
5614 .value_names(&["file1", "file2"]);
5615
5616 assert_eq!(p2.to_string(), "<file1> <file2>");
5617 }
5618 }
5619