clap_builder/builder/arg.rs
1// Std
2#[cfg(feature = "env")]
3use std::env;
4#[cfg(feature = "env")]
5use std::ffi::OsString;
6use std::{
7 cmp::{Ord, Ordering},
8 fmt::{self, Display, Formatter},
9 str,
10};
11
12// Internal
13use super::{ArgFlags, ArgSettings};
14#[cfg(feature = "unstable-ext")]
15use crate::builder::ext::Extension;
16use crate::builder::ext::Extensions;
17use crate::builder::ArgPredicate;
18use crate::builder::IntoResettable;
19use crate::builder::OsStr;
20use crate::builder::PossibleValue;
21use crate::builder::Str;
22use crate::builder::StyledStr;
23use crate::builder::Styles;
24use crate::builder::ValueRange;
25use crate::util::AnyValueId;
26use crate::ArgAction;
27use crate::Id;
28use crate::ValueHint;
29use crate::INTERNAL_ERROR_MSG;
30
31/// The abstract representation of a command line argument. Used to set all the options and
32/// relationships that define a valid argument for the program.
33///
34/// There are two methods for constructing [`Arg`]s, using the builder pattern and setting options
35/// manually, or using a usage string which is far less verbose but has fewer options. You can also
36/// use a combination of the two methods to achieve the best of both worlds.
37///
38/// - [Basic API][crate::Arg#basic-api]
39/// - [Value Handling][crate::Arg#value-handling]
40/// - [Help][crate::Arg#help-1]
41/// - [Advanced Argument Relations][crate::Arg#advanced-argument-relations]
42/// - [Reflection][crate::Arg#reflection]
43///
44/// # Examples
45///
46/// ```rust
47/// # use clap_builder as clap;
48/// # use clap::{Arg, arg, ArgAction};
49/// // Using the traditional builder pattern and setting each option manually
50/// let cfg = Arg::new("config")
51/// .short('c')
52/// .long("config")
53/// .action(ArgAction::Set)
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#[derive(Default, Clone)]
60pub struct Arg {
61 pub(crate) id: Id,
62 pub(crate) help: Option<StyledStr>,
63 pub(crate) long_help: Option<StyledStr>,
64 pub(crate) action: Option<ArgAction>,
65 pub(crate) value_parser: Option<super::ValueParser>,
66 pub(crate) blacklist: Vec<Id>,
67 pub(crate) settings: ArgFlags,
68 pub(crate) overrides: Vec<Id>,
69 pub(crate) groups: Vec<Id>,
70 pub(crate) requires: Vec<(ArgPredicate, Id)>,
71 pub(crate) r_ifs: Vec<(Id, OsStr)>,
72 pub(crate) r_ifs_all: Vec<(Id, OsStr)>,
73 pub(crate) r_unless: Vec<Id>,
74 pub(crate) r_unless_all: Vec<Id>,
75 pub(crate) short: Option<char>,
76 pub(crate) long: Option<Str>,
77 pub(crate) aliases: Vec<(Str, bool)>, // (name, visible)
78 pub(crate) short_aliases: Vec<(char, bool)>, // (name, visible)
79 pub(crate) disp_ord: Option<usize>,
80 pub(crate) val_names: Vec<Str>,
81 pub(crate) num_vals: Option<ValueRange>,
82 pub(crate) val_delim: Option<char>,
83 pub(crate) default_vals: Vec<OsStr>,
84 pub(crate) default_vals_ifs: Vec<(Id, ArgPredicate, Option<OsStr>)>,
85 pub(crate) default_missing_vals: Vec<OsStr>,
86 #[cfg(feature = "env")]
87 pub(crate) env: Option<(OsStr, Option<OsString>)>,
88 pub(crate) terminator: Option<Str>,
89 pub(crate) index: Option<usize>,
90 pub(crate) help_heading: Option<Option<Str>>,
91 pub(crate) ext: Extensions,
92}
93
94/// # Basic API
95impl Arg {
96 /// Create a new [`Arg`] with a unique name.
97 ///
98 /// The name is used to check whether or not the argument was used at
99 /// runtime, get values, set relationships with other args, etc..
100 ///
101 /// **NOTE:** In the case of arguments that take values (i.e. [`Arg::action(ArgAction::Set)`])
102 /// and positional arguments (i.e. those without a preceding `-` or `--`) the name will also
103 /// be displayed when the user prints the usage/help information of the program.
104 ///
105 /// # Examples
106 ///
107 /// ```rust
108 /// # use clap_builder as clap;
109 /// # use clap::{Command, Arg};
110 /// Arg::new("config")
111 /// # ;
112 /// ```
113 /// [`Arg::action(ArgAction::Set)`]: Arg::action()
114 pub fn new(id: impl Into<Id>) -> Self {
115 Arg::default().id(id)
116 }
117
118 /// Set the identifier used for referencing this argument in the clap API.
119 ///
120 /// See [`Arg::new`] for more details.
121 #[must_use]
122 pub fn id(mut self, id: impl Into<Id>) -> Self {
123 self.id = id.into();
124 self
125 }
126
127 /// Sets the short version of the argument without the preceding `-`.
128 ///
129 /// By default `V` and `h` are used by the auto-generated `version` and `help` arguments,
130 /// respectively. You will need to disable the auto-generated flags
131 /// ([`disable_help_flag`][crate::Command::disable_help_flag],
132 /// [`disable_version_flag`][crate::Command::disable_version_flag]) and define your own.
133 ///
134 /// # Examples
135 ///
136 /// When calling `short`, use a single valid UTF-8 character which will allow using the
137 /// argument via a single hyphen (`-`) such as `-c`:
138 ///
139 /// ```rust
140 /// # use clap_builder as clap;
141 /// # use clap::{Command, Arg, ArgAction};
142 /// let m = Command::new("prog")
143 /// .arg(Arg::new("config")
144 /// .short('c')
145 /// .action(ArgAction::Set))
146 /// .get_matches_from(vec![
147 /// "prog", "-c", "file.toml"
148 /// ]);
149 ///
150 /// assert_eq!(m.get_one::<String>("config").map(String::as_str), Some("file.toml"));
151 /// ```
152 ///
153 /// To use `-h` for your own flag and still have help:
154 /// ```rust
155 /// # use clap_builder as clap;
156 /// # use clap::{Command, Arg, ArgAction};
157 /// let m = Command::new("prog")
158 /// .disable_help_flag(true)
159 /// .arg(Arg::new("host")
160 /// .short('h')
161 /// .long("host"))
162 /// .arg(Arg::new("help")
163 /// .long("help")
164 /// .global(true)
165 /// .action(ArgAction::Help))
166 /// .get_matches_from(vec![
167 /// "prog", "-h", "wikipedia.org"
168 /// ]);
169 ///
170 /// assert_eq!(m.get_one::<String>("host").map(String::as_str), Some("wikipedia.org"));
171 /// ```
172 #[inline]
173 #[must_use]
174 pub fn short(mut self, s: impl IntoResettable<char>) -> Self {
175 if let Some(s) = s.into_resettable().into_option() {
176 debug_assert!(s != '-', "short option name cannot be `-`");
177 self.short = Some(s);
178 } else {
179 self.short = None;
180 }
181 self
182 }
183
184 /// Sets the long version of the argument without the preceding `--`.
185 ///
186 /// By default `version` and `help` are used by the auto-generated `version` and `help`
187 /// arguments, respectively. You may use the word `version` or `help` for the long form of your
188 /// own arguments, in which case `clap` simply will not assign those to the auto-generated
189 /// `version` or `help` arguments.
190 ///
191 /// **NOTE:** Any leading `-` characters will be stripped
192 ///
193 /// # Examples
194 ///
195 /// To set `long` use a word containing valid UTF-8. If you supply a double leading
196 /// `--` such as `--config` they will be stripped. Hyphens in the middle of the word, however,
197 /// will *not* be stripped (i.e. `config-file` is allowed).
198 ///
199 /// Setting `long` allows using the argument via a double hyphen (`--`) such as `--config`
200 ///
201 /// ```rust
202 /// # use clap_builder as clap;
203 /// # use clap::{Command, Arg, ArgAction};
204 /// let m = Command::new("prog")
205 /// .arg(Arg::new("cfg")
206 /// .long("config")
207 /// .action(ArgAction::Set))
208 /// .get_matches_from(vec![
209 /// "prog", "--config", "file.toml"
210 /// ]);
211 ///
212 /// assert_eq!(m.get_one::<String>("cfg").map(String::as_str), Some("file.toml"));
213 /// ```
214 #[inline]
215 #[must_use]
216 pub fn long(mut self, l: impl IntoResettable<Str>) -> Self {
217 self.long = l.into_resettable().into_option();
218 self
219 }
220
221 /// Add an alias, which functions as a hidden long flag.
222 ///
223 /// This is more efficient, and easier than creating multiple hidden arguments as one only
224 /// needs to check for the existence of this command, and not all variants.
225 ///
226 /// # Examples
227 ///
228 /// ```rust
229 /// # use clap_builder as clap;
230 /// # use clap::{Command, Arg, ArgAction};
231 /// let m = Command::new("prog")
232 /// .arg(Arg::new("test")
233 /// .long("test")
234 /// .alias("alias")
235 /// .action(ArgAction::Set))
236 /// .get_matches_from(vec![
237 /// "prog", "--alias", "cool"
238 /// ]);
239 /// assert_eq!(m.get_one::<String>("test").unwrap(), "cool");
240 /// ```
241 #[must_use]
242 pub fn alias(mut self, name: impl IntoResettable<Str>) -> Self {
243 if let Some(name) = name.into_resettable().into_option() {
244 self.aliases.push((name, false));
245 } else {
246 self.aliases.clear();
247 }
248 self
249 }
250
251 /// Add an alias, which functions as a hidden short flag.
252 ///
253 /// This is more efficient, and easier than creating multiple hidden arguments as one only
254 /// needs to check for the existence of this command, and not all variants.
255 ///
256 /// # Examples
257 ///
258 /// ```rust
259 /// # use clap_builder as clap;
260 /// # use clap::{Command, Arg, ArgAction};
261 /// let m = Command::new("prog")
262 /// .arg(Arg::new("test")
263 /// .short('t')
264 /// .short_alias('e')
265 /// .action(ArgAction::Set))
266 /// .get_matches_from(vec![
267 /// "prog", "-e", "cool"
268 /// ]);
269 /// assert_eq!(m.get_one::<String>("test").unwrap(), "cool");
270 /// ```
271 #[must_use]
272 pub fn short_alias(mut self, name: impl IntoResettable<char>) -> Self {
273 if let Some(name) = name.into_resettable().into_option() {
274 debug_assert!(name != '-', "short alias name cannot be `-`");
275 self.short_aliases.push((name, false));
276 } else {
277 self.short_aliases.clear();
278 }
279 self
280 }
281
282 /// Add aliases, which function as hidden long flags.
283 ///
284 /// This is more efficient, and easier than creating multiple hidden subcommands as one only
285 /// needs to check for the existence of this command, and not all variants.
286 ///
287 /// # Examples
288 ///
289 /// ```rust
290 /// # use clap_builder as clap;
291 /// # use clap::{Command, Arg, ArgAction};
292 /// let m = Command::new("prog")
293 /// .arg(Arg::new("test")
294 /// .long("test")
295 /// .aliases(["do-stuff", "do-tests", "tests"])
296 /// .action(ArgAction::SetTrue)
297 /// .help("the file to add")
298 /// .required(false))
299 /// .get_matches_from(vec![
300 /// "prog", "--do-tests"
301 /// ]);
302 /// assert_eq!(m.get_flag("test"), true);
303 /// ```
304 #[must_use]
305 pub fn aliases(mut self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self {
306 self.aliases
307 .extend(names.into_iter().map(|x| (x.into(), 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_builder as clap;
320 /// # use clap::{Command, Arg, ArgAction};
321 /// let m = Command::new("prog")
322 /// .arg(Arg::new("test")
323 /// .short('t')
324 /// .short_aliases(['e', 's'])
325 /// .action(ArgAction::SetTrue)
326 /// .help("the file to add")
327 /// .required(false))
328 /// .get_matches_from(vec![
329 /// "prog", "-s"
330 /// ]);
331 /// assert_eq!(m.get_flag("test"), true);
332 /// ```
333 #[must_use]
334 pub fn short_aliases(mut self, names: impl IntoIterator<Item = char>) -> Self {
335 for s in names {
336 debug_assert!(s != '-', "short alias name cannot be `-`");
337 self.short_aliases.push((s, false));
338 }
339 self
340 }
341
342 /// Add an alias, which functions as a visible long flag.
343 ///
344 /// Like [`Arg::alias`], except that they are visible inside the help message.
345 ///
346 /// # Examples
347 ///
348 /// ```rust
349 /// # use clap_builder as clap;
350 /// # use clap::{Command, Arg, ArgAction};
351 /// let m = Command::new("prog")
352 /// .arg(Arg::new("test")
353 /// .visible_alias("something-awesome")
354 /// .long("test")
355 /// .action(ArgAction::Set))
356 /// .get_matches_from(vec![
357 /// "prog", "--something-awesome", "coffee"
358 /// ]);
359 /// assert_eq!(m.get_one::<String>("test").unwrap(), "coffee");
360 /// ```
361 /// [`Command::alias`]: Arg::alias()
362 #[must_use]
363 pub fn visible_alias(mut self, name: impl IntoResettable<Str>) -> Self {
364 if let Some(name) = name.into_resettable().into_option() {
365 self.aliases.push((name, true));
366 } else {
367 self.aliases.clear();
368 }
369 self
370 }
371
372 /// Add an alias, which functions as a visible short flag.
373 ///
374 /// Like [`Arg::short_alias`], except that they are visible inside the help message.
375 ///
376 /// # Examples
377 ///
378 /// ```rust
379 /// # use clap_builder as clap;
380 /// # use clap::{Command, Arg, ArgAction};
381 /// let m = Command::new("prog")
382 /// .arg(Arg::new("test")
383 /// .long("test")
384 /// .visible_short_alias('t')
385 /// .action(ArgAction::Set))
386 /// .get_matches_from(vec![
387 /// "prog", "-t", "coffee"
388 /// ]);
389 /// assert_eq!(m.get_one::<String>("test").unwrap(), "coffee");
390 /// ```
391 #[must_use]
392 pub fn visible_short_alias(mut self, name: impl IntoResettable<char>) -> Self {
393 if let Some(name) = name.into_resettable().into_option() {
394 debug_assert!(name != '-', "short alias name cannot be `-`");
395 self.short_aliases.push((name, true));
396 } else {
397 self.short_aliases.clear();
398 }
399 self
400 }
401
402 /// Add aliases, which function as visible long flags.
403 ///
404 /// Like [`Arg::aliases`], except that they are visible inside the help message.
405 ///
406 /// # Examples
407 ///
408 /// ```rust
409 /// # use clap_builder as clap;
410 /// # use clap::{Command, Arg, ArgAction};
411 /// let m = Command::new("prog")
412 /// .arg(Arg::new("test")
413 /// .long("test")
414 /// .action(ArgAction::SetTrue)
415 /// .visible_aliases(["something", "awesome", "cool"]))
416 /// .get_matches_from(vec![
417 /// "prog", "--awesome"
418 /// ]);
419 /// assert_eq!(m.get_flag("test"), true);
420 /// ```
421 /// [`Command::aliases`]: Arg::aliases()
422 #[must_use]
423 pub fn visible_aliases(mut self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self {
424 self.aliases
425 .extend(names.into_iter().map(|n| (n.into(), true)));
426 self
427 }
428
429 /// Add aliases, which function as visible short flags.
430 ///
431 /// Like [`Arg::short_aliases`], except that they are visible inside the help message.
432 ///
433 /// # Examples
434 ///
435 /// ```rust
436 /// # use clap_builder as clap;
437 /// # use clap::{Command, Arg, ArgAction};
438 /// let m = Command::new("prog")
439 /// .arg(Arg::new("test")
440 /// .long("test")
441 /// .action(ArgAction::SetTrue)
442 /// .visible_short_aliases(['t', 'e']))
443 /// .get_matches_from(vec![
444 /// "prog", "-t"
445 /// ]);
446 /// assert_eq!(m.get_flag("test"), true);
447 /// ```
448 #[must_use]
449 pub fn visible_short_aliases(mut self, names: impl IntoIterator<Item = char>) -> Self {
450 for n in names {
451 debug_assert!(n != '-', "short alias name cannot be `-`");
452 self.short_aliases.push((n, true));
453 }
454 self
455 }
456
457 /// Specifies the index of a positional argument **starting at** 1.
458 ///
459 /// **NOTE:** The index refers to position according to **other positional argument**. It does
460 /// not define position in the argument list as a whole.
461 ///
462 /// **NOTE:** You can optionally leave off the `index` method, and the index will be
463 /// assigned in order of evaluation. Utilizing the `index` method allows for setting
464 /// indexes out of order
465 ///
466 /// **NOTE:** This is only meant to be used for positional arguments and shouldn't to be used
467 /// with [`Arg::short`] or [`Arg::long`].
468 ///
469 /// **NOTE:** When utilized with [`Arg::num_args(1..)`], only the **last** positional argument
470 /// may be defined as having a variable number of arguments (i.e. with the highest index)
471 ///
472 /// # Panics
473 ///
474 /// [`Command`] will [`panic!`] if indexes are skipped (such as defining `index(1)` and `index(3)`
475 /// but not `index(2)`, or a positional argument is defined as multiple and is not the highest
476 /// index (debug builds)
477 ///
478 /// # Examples
479 ///
480 /// ```rust
481 /// # use clap_builder as clap;
482 /// # use clap::{Command, Arg};
483 /// Arg::new("config")
484 /// .index(1)
485 /// # ;
486 /// ```
487 ///
488 /// ```rust
489 /// # use clap_builder as clap;
490 /// # use clap::{Command, Arg, ArgAction};
491 /// let m = Command::new("prog")
492 /// .arg(Arg::new("mode")
493 /// .index(1))
494 /// .arg(Arg::new("debug")
495 /// .long("debug")
496 /// .action(ArgAction::SetTrue))
497 /// .get_matches_from(vec![
498 /// "prog", "--debug", "fast"
499 /// ]);
500 ///
501 /// assert!(m.contains_id("mode"));
502 /// assert_eq!(m.get_one::<String>("mode").unwrap(), "fast"); // notice index(1) means "first positional"
503 /// // *not* first argument
504 /// ```
505 /// [`Arg::short`]: Arg::short()
506 /// [`Arg::long`]: Arg::long()
507 /// [`Arg::num_args(true)`]: Arg::num_args()
508 /// [`Command`]: crate::Command
509 #[inline]
510 #[must_use]
511 pub fn index(mut self, idx: impl IntoResettable<usize>) -> Self {
512 self.index = idx.into_resettable().into_option();
513 self
514 }
515
516 /// This is a "var arg" and everything that follows should be captured by it, as if the user had
517 /// used a `--`.
518 ///
519 /// **NOTE:** To start the trailing "var arg" on unknown flags (and not just a positional
520 /// value), set [`allow_hyphen_values`][Arg::allow_hyphen_values]. Either way, users still
521 /// have the option to explicitly escape ambiguous arguments with `--`.
522 ///
523 /// **NOTE:** [`Arg::value_delimiter`] still applies if set.
524 ///
525 /// **NOTE:** Setting this requires [`Arg::num_args(..)`].
526 ///
527 /// # Examples
528 ///
529 /// ```rust
530 /// # use clap_builder as clap;
531 /// # use clap::{Command, arg};
532 /// let m = Command::new("myprog")
533 /// .arg(arg!(<cmd> ... "commands to run").trailing_var_arg(true))
534 /// .get_matches_from(vec!["myprog", "arg1", "-r", "val1"]);
535 ///
536 /// let trail: Vec<_> = m.get_many::<String>("cmd").unwrap().collect();
537 /// assert_eq!(trail, ["arg1", "-r", "val1"]);
538 /// ```
539 /// [`Arg::num_args(..)`]: crate::Arg::num_args()
540 pub fn trailing_var_arg(self, yes: bool) -> Self {
541 if yes {
542 self.setting(ArgSettings::TrailingVarArg)
543 } else {
544 self.unset_setting(ArgSettings::TrailingVarArg)
545 }
546 }
547
548 /// This arg is the last, or final, positional argument (i.e. has the highest
549 /// index) and is *only* able to be accessed via the `--` syntax (i.e. `$ prog args --
550 /// last_arg`).
551 ///
552 /// Even, if no other arguments are left to parse, if the user omits the `--` syntax
553 /// they will receive an [`UnknownArgument`] error. Setting an argument to `.last(true)` also
554 /// allows one to access this arg early using the `--` syntax. Accessing an arg early, even with
555 /// the `--` syntax is otherwise not possible.
556 ///
557 /// **NOTE:** This will change the usage string to look like `$ prog [OPTIONS] [-- <ARG>]` if
558 /// `ARG` is marked as `.last(true)`.
559 ///
560 /// **NOTE:** This setting will imply [`crate::Command::dont_collapse_args_in_usage`] because failing
561 /// to set this can make the usage string very confusing.
562 ///
563 /// **NOTE**: This setting only applies to positional arguments, and has no effect on OPTIONS
564 ///
565 /// **NOTE:** Setting this requires [taking values][Arg::num_args]
566 ///
567 /// **CAUTION:** Using this setting *and* having child subcommands is not
568 /// recommended with the exception of *also* using
569 /// [`crate::Command::args_conflicts_with_subcommands`]
570 /// (or [`crate::Command::subcommand_negates_reqs`] if the argument marked `Last` is also
571 /// marked [`Arg::required`])
572 ///
573 /// # Examples
574 ///
575 /// ```rust
576 /// # use clap_builder as clap;
577 /// # use clap::{Arg, ArgAction};
578 /// Arg::new("args")
579 /// .action(ArgAction::Set)
580 /// .last(true)
581 /// # ;
582 /// ```
583 ///
584 /// Setting `last` ensures the arg has the highest [index] of all positional args
585 /// and requires that the `--` syntax be used to access it early.
586 ///
587 /// ```rust
588 /// # use clap_builder as clap;
589 /// # use clap::{Command, Arg, ArgAction};
590 /// let res = Command::new("prog")
591 /// .arg(Arg::new("first"))
592 /// .arg(Arg::new("second"))
593 /// .arg(Arg::new("third")
594 /// .action(ArgAction::Set)
595 /// .last(true))
596 /// .try_get_matches_from(vec![
597 /// "prog", "one", "--", "three"
598 /// ]);
599 ///
600 /// assert!(res.is_ok());
601 /// let m = res.unwrap();
602 /// assert_eq!(m.get_one::<String>("third").unwrap(), "three");
603 /// assert_eq!(m.get_one::<String>("second"), None);
604 /// ```
605 ///
606 /// Even if the positional argument marked `Last` is the only argument left to parse,
607 /// failing to use the `--` syntax results in an error.
608 ///
609 /// ```rust
610 /// # use clap_builder as clap;
611 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
612 /// let res = Command::new("prog")
613 /// .arg(Arg::new("first"))
614 /// .arg(Arg::new("second"))
615 /// .arg(Arg::new("third")
616 /// .action(ArgAction::Set)
617 /// .last(true))
618 /// .try_get_matches_from(vec![
619 /// "prog", "one", "two", "three"
620 /// ]);
621 ///
622 /// assert!(res.is_err());
623 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
624 /// ```
625 /// [index]: Arg::index()
626 /// [`UnknownArgument`]: crate::error::ErrorKind::UnknownArgument
627 #[inline]
628 #[must_use]
629 pub fn last(self, yes: bool) -> Self {
630 if yes {
631 self.setting(ArgSettings::Last)
632 } else {
633 self.unset_setting(ArgSettings::Last)
634 }
635 }
636
637 /// Specifies that the argument must be present.
638 ///
639 /// Required by default means it is required, when no other conflicting rules or overrides have
640 /// been evaluated. Conflicting rules take precedence over being required.
641 ///
642 /// **Pro tip:** Flags (i.e. not positional, or arguments that take values) shouldn't be
643 /// required by default. This is because if a flag were to be required, it should simply be
644 /// implied. No additional information is required from user. Flags by their very nature are
645 /// simply boolean on/off switches. The only time a user *should* be required to use a flag
646 /// is if the operation is destructive in nature, and the user is essentially proving to you,
647 /// "Yes, I know what I'm doing."
648 ///
649 /// # Examples
650 ///
651 /// ```rust
652 /// # use clap_builder as clap;
653 /// # use clap::Arg;
654 /// Arg::new("config")
655 /// .required(true)
656 /// # ;
657 /// ```
658 ///
659 /// Setting required requires that the argument be used at runtime.
660 ///
661 /// ```rust
662 /// # use clap_builder as clap;
663 /// # use clap::{Command, Arg, ArgAction};
664 /// let res = Command::new("prog")
665 /// .arg(Arg::new("cfg")
666 /// .required(true)
667 /// .action(ArgAction::Set)
668 /// .long("config"))
669 /// .try_get_matches_from(vec![
670 /// "prog", "--config", "file.conf",
671 /// ]);
672 ///
673 /// assert!(res.is_ok());
674 /// ```
675 ///
676 /// Setting required and then *not* supplying that argument at runtime is an error.
677 ///
678 /// ```rust
679 /// # use clap_builder as clap;
680 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
681 /// let res = Command::new("prog")
682 /// .arg(Arg::new("cfg")
683 /// .required(true)
684 /// .action(ArgAction::Set)
685 /// .long("config"))
686 /// .try_get_matches_from(vec![
687 /// "prog"
688 /// ]);
689 ///
690 /// assert!(res.is_err());
691 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
692 /// ```
693 #[inline]
694 #[must_use]
695 pub fn required(self, yes: bool) -> Self {
696 if yes {
697 self.setting(ArgSettings::Required)
698 } else {
699 self.unset_setting(ArgSettings::Required)
700 }
701 }
702
703 /// Sets an argument that is required when this one is present
704 ///
705 /// i.e. when using this argument, the following argument *must* be present.
706 ///
707 /// **NOTE:** [Conflicting] rules and [override] rules take precedence over being required
708 ///
709 /// # Examples
710 ///
711 /// ```rust
712 /// # use clap_builder as clap;
713 /// # use clap::Arg;
714 /// Arg::new("config")
715 /// .requires("input")
716 /// # ;
717 /// ```
718 ///
719 /// Setting [`Arg::requires(name)`] requires that the argument be used at runtime if the
720 /// defining argument is used. If the defining argument isn't used, the other argument isn't
721 /// required
722 ///
723 /// ```rust
724 /// # use clap_builder as clap;
725 /// # use clap::{Command, Arg, ArgAction};
726 /// let res = Command::new("prog")
727 /// .arg(Arg::new("cfg")
728 /// .action(ArgAction::Set)
729 /// .requires("input")
730 /// .long("config"))
731 /// .arg(Arg::new("input"))
732 /// .try_get_matches_from(vec![
733 /// "prog"
734 /// ]);
735 ///
736 /// assert!(res.is_ok()); // We didn't use cfg, so input wasn't required
737 /// ```
738 ///
739 /// Setting [`Arg::requires(name)`] and *not* supplying that argument is an error.
740 ///
741 /// ```rust
742 /// # use clap_builder as clap;
743 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
744 /// let res = Command::new("prog")
745 /// .arg(Arg::new("cfg")
746 /// .action(ArgAction::Set)
747 /// .requires("input")
748 /// .long("config"))
749 /// .arg(Arg::new("input"))
750 /// .try_get_matches_from(vec![
751 /// "prog", "--config", "file.conf"
752 /// ]);
753 ///
754 /// assert!(res.is_err());
755 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
756 /// ```
757 /// [`Arg::requires(name)`]: Arg::requires()
758 /// [Conflicting]: Arg::conflicts_with()
759 /// [override]: Arg::overrides_with()
760 #[must_use]
761 pub fn requires(mut self, arg_id: impl IntoResettable<Id>) -> Self {
762 if let Some(arg_id) = arg_id.into_resettable().into_option() {
763 self.requires.push((ArgPredicate::IsPresent, arg_id));
764 } else {
765 self.requires.clear();
766 }
767 self
768 }
769
770 /// This argument must be passed alone; it conflicts with all other arguments.
771 ///
772 /// # Examples
773 ///
774 /// ```rust
775 /// # use clap_builder as clap;
776 /// # use clap::Arg;
777 /// Arg::new("config")
778 /// .exclusive(true)
779 /// # ;
780 /// ```
781 ///
782 /// Setting an exclusive argument and having any other arguments present at runtime
783 /// is an error.
784 ///
785 /// ```rust
786 /// # use clap_builder as clap;
787 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
788 /// let res = Command::new("prog")
789 /// .arg(Arg::new("exclusive")
790 /// .action(ArgAction::Set)
791 /// .exclusive(true)
792 /// .long("exclusive"))
793 /// .arg(Arg::new("debug")
794 /// .long("debug"))
795 /// .arg(Arg::new("input"))
796 /// .try_get_matches_from(vec![
797 /// "prog", "--exclusive", "file.conf", "file.txt"
798 /// ]);
799 ///
800 /// assert!(res.is_err());
801 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::ArgumentConflict);
802 /// ```
803 #[inline]
804 #[must_use]
805 pub fn exclusive(self, yes: bool) -> Self {
806 if yes {
807 self.setting(ArgSettings::Exclusive)
808 } else {
809 self.unset_setting(ArgSettings::Exclusive)
810 }
811 }
812
813 /// Specifies that an argument can be matched to all child [`Subcommand`]s.
814 ///
815 /// **NOTE:** Global arguments *only* propagate down, **not** up (to parent commands), however
816 /// their values once a user uses them will be propagated back up to parents. In effect, this
817 /// means one should *define* all global arguments at the top level, however it doesn't matter
818 /// where the user *uses* the global argument.
819 ///
820 /// # Examples
821 ///
822 /// Assume an application with two subcommands, and you'd like to define a
823 /// `--verbose` flag that can be called on any of the subcommands and parent, but you don't
824 /// want to clutter the source with three duplicate [`Arg`] definitions.
825 ///
826 /// ```rust
827 /// # use clap_builder as clap;
828 /// # use clap::{Command, Arg, ArgAction};
829 /// let m = Command::new("prog")
830 /// .arg(Arg::new("verb")
831 /// .long("verbose")
832 /// .short('v')
833 /// .action(ArgAction::SetTrue)
834 /// .global(true))
835 /// .subcommand(Command::new("test"))
836 /// .subcommand(Command::new("do-stuff"))
837 /// .get_matches_from(vec![
838 /// "prog", "do-stuff", "--verbose"
839 /// ]);
840 ///
841 /// assert_eq!(m.subcommand_name(), Some("do-stuff"));
842 /// let sub_m = m.subcommand_matches("do-stuff").unwrap();
843 /// assert_eq!(sub_m.get_flag("verb"), true);
844 /// ```
845 ///
846 /// [`Subcommand`]: crate::Subcommand
847 #[inline]
848 #[must_use]
849 pub fn global(self, yes: bool) -> Self {
850 if yes {
851 self.setting(ArgSettings::Global)
852 } else {
853 self.unset_setting(ArgSettings::Global)
854 }
855 }
856
857 #[inline]
858 pub(crate) fn is_set(&self, s: ArgSettings) -> bool {
859 self.settings.is_set(s)
860 }
861
862 #[inline]
863 #[must_use]
864 pub(crate) fn setting(mut self, setting: ArgSettings) -> Self {
865 self.settings.set(setting);
866 self
867 }
868
869 #[inline]
870 #[must_use]
871 pub(crate) fn unset_setting(mut self, setting: ArgSettings) -> Self {
872 self.settings.unset(setting);
873 self
874 }
875
876 /// Extend [`Arg`] with [`ArgExt`] data
877 #[cfg(feature = "unstable-ext")]
878 #[allow(clippy::should_implement_trait)]
879 pub fn add<T: ArgExt + Extension>(mut self, tagged: T) -> Self {
880 self.ext.set(tagged);
881 self
882 }
883}
884
885/// # Value Handling
886impl Arg {
887 /// Specify how to react to an argument when parsing it.
888 ///
889 /// [`ArgAction`] controls things like
890 /// - Overwriting previous values with new ones
891 /// - Appending new values to all previous ones
892 /// - Counting how many times a flag occurs
893 ///
894 /// The default action is `ArgAction::Set`
895 ///
896 /// # Examples
897 ///
898 /// ```rust
899 /// # use clap_builder as clap;
900 /// # use clap::Command;
901 /// # use clap::Arg;
902 /// let cmd = Command::new("mycmd")
903 /// .arg(
904 /// Arg::new("flag")
905 /// .long("flag")
906 /// .action(clap::ArgAction::Append)
907 /// );
908 ///
909 /// let matches = cmd.try_get_matches_from(["mycmd", "--flag", "value"]).unwrap();
910 /// assert!(matches.contains_id("flag"));
911 /// assert_eq!(
912 /// matches.get_many::<String>("flag").unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(),
913 /// vec!["value"]
914 /// );
915 /// ```
916 #[inline]
917 #[must_use]
918 pub fn action(mut self, action: impl IntoResettable<ArgAction>) -> Self {
919 self.action = action.into_resettable().into_option();
920 self
921 }
922
923 /// Specify the typed behavior of the argument.
924 ///
925 /// This allows parsing and validating a value before storing it into
926 /// [`ArgMatches`][crate::ArgMatches] as the given type.
927 ///
928 /// Possible value parsers include:
929 /// - [`value_parser!(T)`][crate::value_parser!] for auto-selecting a value parser for a given type
930 /// - Or [range expressions like `0..=1`][std::ops::RangeBounds] as a shorthand for [`RangedI64ValueParser`][crate::builder::RangedI64ValueParser]
931 /// - `Fn(&str) -> Result<T, E>`
932 /// - `[&str]` and [`PossibleValuesParser`][crate::builder::PossibleValuesParser] for static enumerated values
933 /// - [`BoolishValueParser`][crate::builder::BoolishValueParser], and [`FalseyValueParser`][crate::builder::FalseyValueParser] for alternative `bool` implementations
934 /// - [`NonEmptyStringValueParser`][crate::builder::NonEmptyStringValueParser] for basic validation for strings
935 /// - or any other [`TypedValueParser`][crate::builder::TypedValueParser] implementation
936 ///
937 /// The default value is [`ValueParser::string`][crate::builder::ValueParser::string].
938 ///
939 /// ```rust
940 /// # use clap_builder as clap;
941 /// # use clap::ArgAction;
942 /// let mut cmd = clap::Command::new("raw")
943 /// .arg(
944 /// clap::Arg::new("color")
945 /// .long("color")
946 /// .value_parser(["always", "auto", "never"])
947 /// .default_value("auto")
948 /// )
949 /// .arg(
950 /// clap::Arg::new("hostname")
951 /// .long("hostname")
952 /// .value_parser(clap::builder::NonEmptyStringValueParser::new())
953 /// .action(ArgAction::Set)
954 /// .required(true)
955 /// )
956 /// .arg(
957 /// clap::Arg::new("port")
958 /// .long("port")
959 /// .value_parser(clap::value_parser!(u16).range(3000..))
960 /// .action(ArgAction::Set)
961 /// .required(true)
962 /// );
963 ///
964 /// let m = cmd.try_get_matches_from_mut(
965 /// ["cmd", "--hostname", "rust-lang.org", "--port", "3001"]
966 /// ).unwrap();
967 ///
968 /// let color: &String = m.get_one("color")
969 /// .expect("default");
970 /// assert_eq!(color, "auto");
971 ///
972 /// let hostname: &String = m.get_one("hostname")
973 /// .expect("required");
974 /// assert_eq!(hostname, "rust-lang.org");
975 ///
976 /// let port: u16 = *m.get_one("port")
977 /// .expect("required");
978 /// assert_eq!(port, 3001);
979 /// ```
980 pub fn value_parser(mut self, parser: impl IntoResettable<super::ValueParser>) -> Self {
981 self.value_parser = parser.into_resettable().into_option();
982 self
983 }
984
985 /// Specifies the number of arguments parsed per occurrence
986 ///
987 /// For example, if you had a `-f <file>` argument where you wanted exactly 3 'files' you would
988 /// set `.num_args(3)`, and this argument wouldn't be satisfied unless the user
989 /// provided 3 and only 3 values.
990 ///
991 /// Users may specify values for arguments in any of the following methods
992 ///
993 /// - Using a space such as `-o value` or `--option value`
994 /// - Using an equals and no space such as `-o=value` or `--option=value`
995 /// - Use a short and no space such as `-ovalue`
996 ///
997 /// **WARNING:**
998 ///
999 /// Setting a variable number of values (e.g. `1..=10`) for an argument without
1000 /// other details can be dangerous in some circumstances. Because multiple values are
1001 /// allowed, `--option val1 val2 val3` is perfectly valid. Be careful when designing a CLI
1002 /// where **positional arguments** or **subcommands** are *also* expected as `clap` will continue
1003 /// parsing *values* until one of the following happens:
1004 ///
1005 /// - It reaches the maximum number of values
1006 /// - It reaches a specific number of values
1007 /// - It finds another flag or option (i.e. something that starts with a `-`)
1008 /// - It reaches the [`Arg::value_terminator`] if set
1009 ///
1010 /// Alternatively,
1011 /// - Use a delimiter between values with [`Arg::value_delimiter`]
1012 /// - Require a flag occurrence per value with [`ArgAction::Append`]
1013 /// - Require positional arguments to appear after `--` with [`Arg::last`]
1014 ///
1015 /// # Examples
1016 ///
1017 /// Option:
1018 /// ```rust
1019 /// # use clap_builder as clap;
1020 /// # use clap::{Command, Arg};
1021 /// let m = Command::new("prog")
1022 /// .arg(Arg::new("mode")
1023 /// .long("mode")
1024 /// .num_args(1))
1025 /// .get_matches_from(vec![
1026 /// "prog", "--mode", "fast"
1027 /// ]);
1028 ///
1029 /// assert_eq!(m.get_one::<String>("mode").unwrap(), "fast");
1030 /// ```
1031 ///
1032 /// Flag/option hybrid (see also [`default_missing_value`][Arg::default_missing_value])
1033 /// ```rust
1034 /// # use clap_builder as clap;
1035 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
1036 /// let cmd = Command::new("prog")
1037 /// .arg(Arg::new("mode")
1038 /// .long("mode")
1039 /// .default_missing_value("slow")
1040 /// .default_value("plaid")
1041 /// .num_args(0..=1));
1042 ///
1043 /// let m = cmd.clone()
1044 /// .get_matches_from(vec![
1045 /// "prog", "--mode", "fast"
1046 /// ]);
1047 /// assert_eq!(m.get_one::<String>("mode").unwrap(), "fast");
1048 ///
1049 /// let m = cmd.clone()
1050 /// .get_matches_from(vec![
1051 /// "prog", "--mode",
1052 /// ]);
1053 /// assert_eq!(m.get_one::<String>("mode").unwrap(), "slow");
1054 ///
1055 /// let m = cmd.clone()
1056 /// .get_matches_from(vec![
1057 /// "prog",
1058 /// ]);
1059 /// assert_eq!(m.get_one::<String>("mode").unwrap(), "plaid");
1060 /// ```
1061 ///
1062 /// Tuples
1063 /// ```rust
1064 /// # use clap_builder as clap;
1065 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
1066 /// let cmd = Command::new("prog")
1067 /// .arg(Arg::new("file")
1068 /// .action(ArgAction::Set)
1069 /// .num_args(2)
1070 /// .short('F'));
1071 ///
1072 /// let m = cmd.clone()
1073 /// .get_matches_from(vec![
1074 /// "prog", "-F", "in-file", "out-file"
1075 /// ]);
1076 /// assert_eq!(
1077 /// m.get_many::<String>("file").unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(),
1078 /// vec!["in-file", "out-file"]
1079 /// );
1080 ///
1081 /// let res = cmd.clone()
1082 /// .try_get_matches_from(vec![
1083 /// "prog", "-F", "file1"
1084 /// ]);
1085 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
1086 /// ```
1087 ///
1088 /// A common mistake is to define an option which allows multiple values and a positional
1089 /// argument.
1090 /// ```rust
1091 /// # use clap_builder as clap;
1092 /// # use clap::{Command, Arg, ArgAction};
1093 /// let cmd = Command::new("prog")
1094 /// .arg(Arg::new("file")
1095 /// .action(ArgAction::Set)
1096 /// .num_args(0..)
1097 /// .short('F'))
1098 /// .arg(Arg::new("word"));
1099 ///
1100 /// let m = cmd.clone().get_matches_from(vec![
1101 /// "prog", "-F", "file1", "file2", "file3", "word"
1102 /// ]);
1103 /// let files: Vec<_> = m.get_many::<String>("file").unwrap().collect();
1104 /// assert_eq!(files, ["file1", "file2", "file3", "word"]); // wait...what?!
1105 /// assert!(!m.contains_id("word")); // but we clearly used word!
1106 ///
1107 /// // but this works
1108 /// let m = cmd.clone().get_matches_from(vec![
1109 /// "prog", "word", "-F", "file1", "file2", "file3",
1110 /// ]);
1111 /// let files: Vec<_> = m.get_many::<String>("file").unwrap().collect();
1112 /// assert_eq!(files, ["file1", "file2", "file3"]);
1113 /// assert_eq!(m.get_one::<String>("word").unwrap(), "word");
1114 /// ```
1115 /// The problem is `clap` doesn't know when to stop parsing values for "file".
1116 ///
1117 /// A solution for the example above is to limit how many values with a maximum, or specific
1118 /// number, or to say [`ArgAction::Append`] is ok, but multiple values are not.
1119 /// ```rust
1120 /// # use clap_builder as clap;
1121 /// # use clap::{Command, Arg, ArgAction};
1122 /// let m = Command::new("prog")
1123 /// .arg(Arg::new("file")
1124 /// .action(ArgAction::Append)
1125 /// .short('F'))
1126 /// .arg(Arg::new("word"))
1127 /// .get_matches_from(vec![
1128 /// "prog", "-F", "file1", "-F", "file2", "-F", "file3", "word"
1129 /// ]);
1130 ///
1131 /// let files: Vec<_> = m.get_many::<String>("file").unwrap().collect();
1132 /// assert_eq!(files, ["file1", "file2", "file3"]);
1133 /// assert_eq!(m.get_one::<String>("word").unwrap(), "word");
1134 /// ```
1135 #[inline]
1136 #[must_use]
1137 pub fn num_args(mut self, qty: impl IntoResettable<ValueRange>) -> Self {
1138 self.num_vals = qty.into_resettable().into_option();
1139 self
1140 }
1141
1142 #[doc(hidden)]
1143 #[cfg_attr(
1144 feature = "deprecated",
1145 deprecated(since = "4.0.0", note = "Replaced with `Arg::num_args`")
1146 )]
1147 pub fn number_of_values(self, qty: usize) -> Self {
1148 self.num_args(qty)
1149 }
1150
1151 /// Placeholder for the argument's value in the help message / usage.
1152 ///
1153 /// This name is cosmetic only; the name is **not** used to access arguments.
1154 /// This setting can be very helpful when describing the type of input the user should be
1155 /// using, such as `FILE`, `INTERFACE`, etc. Although not required, it's somewhat convention to
1156 /// use all capital letters for the value name.
1157 ///
1158 /// **NOTE:** implicitly sets [`Arg::action(ArgAction::Set)`]
1159 ///
1160 /// # Examples
1161 ///
1162 /// ```rust
1163 /// # use clap_builder as clap;
1164 /// # use clap::{Command, Arg};
1165 /// Arg::new("cfg")
1166 /// .long("config")
1167 /// .value_name("FILE")
1168 /// # ;
1169 /// ```
1170 ///
1171 /// ```rust
1172 /// # use clap_builder as clap;
1173 /// # #[cfg(feature = "help")] {
1174 /// # use clap::{Command, Arg};
1175 /// let m = Command::new("prog")
1176 /// .arg(Arg::new("config")
1177 /// .long("config")
1178 /// .value_name("FILE")
1179 /// .help("Some help text"))
1180 /// .get_matches_from(vec![
1181 /// "prog", "--help"
1182 /// ]);
1183 /// # }
1184 /// ```
1185 /// Running the above program produces the following output
1186 ///
1187 /// ```text
1188 /// valnames
1189 ///
1190 /// Usage: valnames [OPTIONS]
1191 ///
1192 /// Options:
1193 /// --config <FILE> Some help text
1194 /// -h, --help Print help information
1195 /// -V, --version Print version information
1196 /// ```
1197 /// [positional]: Arg::index()
1198 /// [`Arg::action(ArgAction::Set)`]: Arg::action()
1199 #[inline]
1200 #[must_use]
1201 pub fn value_name(mut self, name: impl IntoResettable<Str>) -> Self {
1202 if let Some(name) = name.into_resettable().into_option() {
1203 self.value_names([name])
1204 } else {
1205 self.val_names.clear();
1206 self
1207 }
1208 }
1209
1210 /// Placeholders for the argument's values in the help message / usage.
1211 ///
1212 /// These names are cosmetic only, used for help and usage strings only. The names are **not**
1213 /// used to access arguments. The values of the arguments are accessed in numeric order (i.e.
1214 /// if you specify two names `one` and `two` `one` will be the first matched value, `two` will
1215 /// be the second).
1216 ///
1217 /// This setting can be very helpful when describing the type of input the user should be
1218 /// using, such as `FILE`, `INTERFACE`, etc. Although not required, it's somewhat convention to
1219 /// use all capital letters for the value name.
1220 ///
1221 /// **Pro Tip:** It may help to use [`Arg::next_line_help(true)`] if there are long, or
1222 /// multiple value names in order to not throw off the help text alignment of all options.
1223 ///
1224 /// **NOTE:** implicitly sets [`Arg::action(ArgAction::Set)`] and [`Arg::num_args(1..)`].
1225 ///
1226 /// # Examples
1227 ///
1228 /// ```rust
1229 /// # use clap_builder as clap;
1230 /// # use clap::{Command, Arg};
1231 /// Arg::new("speed")
1232 /// .short('s')
1233 /// .value_names(["fast", "slow"]);
1234 /// ```
1235 ///
1236 /// ```rust
1237 /// # use clap_builder as clap;
1238 /// # #[cfg(feature = "help")] {
1239 /// # use clap::{Command, Arg};
1240 /// let m = Command::new("prog")
1241 /// .arg(Arg::new("io")
1242 /// .long("io-files")
1243 /// .value_names(["INFILE", "OUTFILE"]))
1244 /// .get_matches_from(vec![
1245 /// "prog", "--help"
1246 /// ]);
1247 /// # }
1248 /// ```
1249 ///
1250 /// Running the above program produces the following output
1251 ///
1252 /// ```text
1253 /// valnames
1254 ///
1255 /// Usage: valnames [OPTIONS]
1256 ///
1257 /// Options:
1258 /// -h, --help Print help information
1259 /// --io-files <INFILE> <OUTFILE> Some help text
1260 /// -V, --version Print version information
1261 /// ```
1262 /// [`Arg::next_line_help(true)`]: Arg::next_line_help()
1263 /// [`Arg::num_args`]: Arg::num_args()
1264 /// [`Arg::action(ArgAction::Set)`]: Arg::action()
1265 /// [`Arg::num_args(1..)`]: Arg::num_args()
1266 #[must_use]
1267 pub fn value_names(mut self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self {
1268 self.val_names = names.into_iter().map(|s| s.into()).collect();
1269 self
1270 }
1271
1272 /// Provide the shell a hint about how to complete this argument.
1273 ///
1274 /// See [`ValueHint`] for more information.
1275 ///
1276 /// **NOTE:** implicitly sets [`Arg::action(ArgAction::Set)`].
1277 ///
1278 /// For example, to take a username as argument:
1279 ///
1280 /// ```rust
1281 /// # use clap_builder as clap;
1282 /// # use clap::{Arg, ValueHint};
1283 /// Arg::new("user")
1284 /// .short('u')
1285 /// .long("user")
1286 /// .value_hint(ValueHint::Username);
1287 /// ```
1288 ///
1289 /// To take a full command line and its arguments (for example, when writing a command wrapper):
1290 ///
1291 /// ```rust
1292 /// # use clap_builder as clap;
1293 /// # use clap::{Command, Arg, ValueHint, ArgAction};
1294 /// Command::new("prog")
1295 /// .trailing_var_arg(true)
1296 /// .arg(
1297 /// Arg::new("command")
1298 /// .action(ArgAction::Set)
1299 /// .num_args(1..)
1300 /// .value_hint(ValueHint::CommandWithArguments)
1301 /// );
1302 /// ```
1303 #[must_use]
1304 pub fn value_hint(mut self, value_hint: impl IntoResettable<ValueHint>) -> Self {
1305 // HACK: we should use `Self::add` and `Self::remove` to type-check that `ArgExt` is used
1306 match value_hint.into_resettable().into_option() {
1307 Some(value_hint) => {
1308 self.ext.set(value_hint);
1309 }
1310 None => {
1311 self.ext.remove::<ValueHint>();
1312 }
1313 }
1314 self
1315 }
1316
1317 /// Match values against [`PossibleValuesParser`][crate::builder::PossibleValuesParser] without matching case.
1318 ///
1319 /// When other arguments are conditionally required based on the
1320 /// value of a case-insensitive argument, the equality check done
1321 /// by [`Arg::required_if_eq`], [`Arg::required_if_eq_any`], or
1322 /// [`Arg::required_if_eq_all`] is case-insensitive.
1323 ///
1324 ///
1325 /// **NOTE:** Setting this requires [taking values][Arg::num_args]
1326 ///
1327 /// **NOTE:** To do unicode case folding, enable the `unicode` feature flag.
1328 ///
1329 /// # Examples
1330 ///
1331 /// ```rust
1332 /// # use clap_builder as clap;
1333 /// # use clap::{Command, Arg, ArgAction};
1334 /// let m = Command::new("pv")
1335 /// .arg(Arg::new("option")
1336 /// .long("option")
1337 /// .action(ArgAction::Set)
1338 /// .ignore_case(true)
1339 /// .value_parser(["test123"]))
1340 /// .get_matches_from(vec![
1341 /// "pv", "--option", "TeSt123",
1342 /// ]);
1343 ///
1344 /// assert!(m.get_one::<String>("option").unwrap().eq_ignore_ascii_case("test123"));
1345 /// ```
1346 ///
1347 /// This setting also works when multiple values can be defined:
1348 ///
1349 /// ```rust
1350 /// # use clap_builder as clap;
1351 /// # use clap::{Command, Arg, ArgAction};
1352 /// let m = Command::new("pv")
1353 /// .arg(Arg::new("option")
1354 /// .short('o')
1355 /// .long("option")
1356 /// .action(ArgAction::Set)
1357 /// .ignore_case(true)
1358 /// .num_args(1..)
1359 /// .value_parser(["test123", "test321"]))
1360 /// .get_matches_from(vec![
1361 /// "pv", "--option", "TeSt123", "teST123", "tESt321"
1362 /// ]);
1363 ///
1364 /// let matched_vals = m.get_many::<String>("option").unwrap().collect::<Vec<_>>();
1365 /// assert_eq!(&*matched_vals, &["TeSt123", "teST123", "tESt321"]);
1366 /// ```
1367 #[inline]
1368 #[must_use]
1369 pub fn ignore_case(self, yes: bool) -> Self {
1370 if yes {
1371 self.setting(ArgSettings::IgnoreCase)
1372 } else {
1373 self.unset_setting(ArgSettings::IgnoreCase)
1374 }
1375 }
1376
1377 /// Allows values which start with a leading hyphen (`-`)
1378 ///
1379 /// To limit values to just numbers, see
1380 /// [`allow_negative_numbers`][Arg::allow_negative_numbers].
1381 ///
1382 /// See also [`trailing_var_arg`][Arg::trailing_var_arg].
1383 ///
1384 /// **NOTE:** Setting this requires [taking values][Arg::num_args]
1385 ///
1386 /// **WARNING:** Prior arguments with `allow_hyphen_values(true)` get precedence over known
1387 /// flags but known flags get precedence over the next possible positional argument with
1388 /// `allow_hyphen_values(true)`. When combined with [`Arg::num_args(..)`],
1389 /// [`Arg::value_terminator`] is one way to ensure processing stops.
1390 ///
1391 /// **WARNING**: Take caution when using this setting combined with another argument using
1392 /// [`Arg::num_args`], as this becomes ambiguous `$ prog --arg -- -- val`. All
1393 /// three `--, --, val` will be values when the user may have thought the second `--` would
1394 /// constitute the normal, "Only positional args follow" idiom.
1395 ///
1396 /// # Examples
1397 ///
1398 /// ```rust
1399 /// # use clap_builder as clap;
1400 /// # use clap::{Command, Arg, ArgAction};
1401 /// let m = Command::new("prog")
1402 /// .arg(Arg::new("pat")
1403 /// .action(ArgAction::Set)
1404 /// .allow_hyphen_values(true)
1405 /// .long("pattern"))
1406 /// .get_matches_from(vec![
1407 /// "prog", "--pattern", "-file"
1408 /// ]);
1409 ///
1410 /// assert_eq!(m.get_one::<String>("pat").unwrap(), "-file");
1411 /// ```
1412 ///
1413 /// Not setting `Arg::allow_hyphen_values(true)` and supplying a value which starts with a
1414 /// hyphen is an error.
1415 ///
1416 /// ```rust
1417 /// # use clap_builder as clap;
1418 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
1419 /// let res = Command::new("prog")
1420 /// .arg(Arg::new("pat")
1421 /// .action(ArgAction::Set)
1422 /// .long("pattern"))
1423 /// .try_get_matches_from(vec![
1424 /// "prog", "--pattern", "-file"
1425 /// ]);
1426 ///
1427 /// assert!(res.is_err());
1428 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
1429 /// ```
1430 /// [`Arg::num_args(1)`]: Arg::num_args()
1431 #[inline]
1432 #[must_use]
1433 pub fn allow_hyphen_values(self, yes: bool) -> Self {
1434 if yes {
1435 self.setting(ArgSettings::AllowHyphenValues)
1436 } else {
1437 self.unset_setting(ArgSettings::AllowHyphenValues)
1438 }
1439 }
1440
1441 /// Allows negative numbers to pass as values.
1442 ///
1443 /// This is similar to [`Arg::allow_hyphen_values`] except that it only allows numbers,
1444 /// all other undefined leading hyphens will fail to parse.
1445 ///
1446 /// **NOTE:** Setting this requires [taking values][Arg::num_args]
1447 ///
1448 /// # Examples
1449 ///
1450 /// ```rust
1451 /// # use clap_builder as clap;
1452 /// # use clap::{Command, Arg};
1453 /// let res = Command::new("myprog")
1454 /// .arg(Arg::new("num").allow_negative_numbers(true))
1455 /// .try_get_matches_from(vec![
1456 /// "myprog", "-20"
1457 /// ]);
1458 /// assert!(res.is_ok());
1459 /// let m = res.unwrap();
1460 /// assert_eq!(m.get_one::<String>("num").unwrap(), "-20");
1461 /// ```
1462 #[inline]
1463 pub fn allow_negative_numbers(self, yes: bool) -> Self {
1464 if yes {
1465 self.setting(ArgSettings::AllowNegativeNumbers)
1466 } else {
1467 self.unset_setting(ArgSettings::AllowNegativeNumbers)
1468 }
1469 }
1470
1471 /// Requires that options use the `--option=val` syntax
1472 ///
1473 /// i.e. an equals between the option and associated value.
1474 ///
1475 /// **NOTE:** Setting this requires [taking values][Arg::num_args]
1476 ///
1477 /// # Examples
1478 ///
1479 /// Setting `require_equals` requires that the option have an equals sign between
1480 /// it and the associated value.
1481 ///
1482 /// ```rust
1483 /// # use clap_builder as clap;
1484 /// # use clap::{Command, Arg, ArgAction};
1485 /// let res = Command::new("prog")
1486 /// .arg(Arg::new("cfg")
1487 /// .action(ArgAction::Set)
1488 /// .require_equals(true)
1489 /// .long("config"))
1490 /// .try_get_matches_from(vec![
1491 /// "prog", "--config=file.conf"
1492 /// ]);
1493 ///
1494 /// assert!(res.is_ok());
1495 /// ```
1496 ///
1497 /// Setting `require_equals` and *not* supplying the equals will cause an
1498 /// error.
1499 ///
1500 /// ```rust
1501 /// # use clap_builder as clap;
1502 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
1503 /// let res = Command::new("prog")
1504 /// .arg(Arg::new("cfg")
1505 /// .action(ArgAction::Set)
1506 /// .require_equals(true)
1507 /// .long("config"))
1508 /// .try_get_matches_from(vec![
1509 /// "prog", "--config", "file.conf"
1510 /// ]);
1511 ///
1512 /// assert!(res.is_err());
1513 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::NoEquals);
1514 /// ```
1515 #[inline]
1516 #[must_use]
1517 pub fn require_equals(self, yes: bool) -> Self {
1518 if yes {
1519 self.setting(ArgSettings::RequireEquals)
1520 } else {
1521 self.unset_setting(ArgSettings::RequireEquals)
1522 }
1523 }
1524
1525 #[doc(hidden)]
1526 #[cfg_attr(
1527 feature = "deprecated",
1528 deprecated(since = "4.0.0", note = "Replaced with `Arg::value_delimiter`")
1529 )]
1530 pub fn use_value_delimiter(mut self, yes: bool) -> Self {
1531 if yes {
1532 self.val_delim.get_or_insert(',');
1533 } else {
1534 self.val_delim = None;
1535 }
1536 self
1537 }
1538
1539 /// Allow grouping of multiple values via a delimiter.
1540 ///
1541 /// i.e. allow values (`val1,val2,val3`) to be parsed as three values (`val1`, `val2`,
1542 /// and `val3`) instead of one value (`val1,val2,val3`).
1543 ///
1544 /// # Examples
1545 ///
1546 /// ```rust
1547 /// # use clap_builder as clap;
1548 /// # use clap::{Command, Arg};
1549 /// let m = Command::new("prog")
1550 /// .arg(Arg::new("config")
1551 /// .short('c')
1552 /// .long("config")
1553 /// .value_delimiter(','))
1554 /// .get_matches_from(vec![
1555 /// "prog", "--config=val1,val2,val3"
1556 /// ]);
1557 ///
1558 /// assert_eq!(m.get_many::<String>("config").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"])
1559 /// ```
1560 /// [`Arg::value_delimiter(',')`]: Arg::value_delimiter()
1561 /// [`Arg::action(ArgAction::Set)`]: Arg::action()
1562 #[inline]
1563 #[must_use]
1564 pub fn value_delimiter(mut self, d: impl IntoResettable<char>) -> Self {
1565 self.val_delim = d.into_resettable().into_option();
1566 self
1567 }
1568
1569 /// Sentinel to **stop** parsing multiple values of a given argument.
1570 ///
1571 /// By default when
1572 /// one sets [`num_args(1..)`] on an argument, clap will continue parsing values for that
1573 /// argument until it reaches another valid argument, or one of the other more specific settings
1574 /// for multiple values is used (such as [`num_args`]).
1575 ///
1576 /// **NOTE:** This setting only applies to [options] and [positional arguments]
1577 ///
1578 /// **NOTE:** When the terminator is passed in on the command line, it is **not** stored as one
1579 /// of the values
1580 ///
1581 /// # Examples
1582 ///
1583 /// ```rust
1584 /// # use clap_builder as clap;
1585 /// # use clap::{Command, Arg, ArgAction};
1586 /// Arg::new("vals")
1587 /// .action(ArgAction::Set)
1588 /// .num_args(1..)
1589 /// .value_terminator(";")
1590 /// # ;
1591 /// ```
1592 ///
1593 /// The following example uses two arguments, a sequence of commands, and the location in which
1594 /// to perform them
1595 ///
1596 /// ```rust
1597 /// # use clap_builder as clap;
1598 /// # use clap::{Command, Arg, ArgAction};
1599 /// let m = Command::new("prog")
1600 /// .arg(Arg::new("cmds")
1601 /// .action(ArgAction::Set)
1602 /// .num_args(1..)
1603 /// .allow_hyphen_values(true)
1604 /// .value_terminator(";"))
1605 /// .arg(Arg::new("location"))
1606 /// .get_matches_from(vec![
1607 /// "prog", "find", "-type", "f", "-name", "special", ";", "/home/clap"
1608 /// ]);
1609 /// let cmds: Vec<_> = m.get_many::<String>("cmds").unwrap().collect();
1610 /// assert_eq!(&cmds, &["find", "-type", "f", "-name", "special"]);
1611 /// assert_eq!(m.get_one::<String>("location").unwrap(), "/home/clap");
1612 /// ```
1613 /// [options]: Arg::action
1614 /// [positional arguments]: Arg::index()
1615 /// [`num_args(1..)`]: Arg::num_args()
1616 /// [`num_args`]: Arg::num_args()
1617 #[inline]
1618 #[must_use]
1619 pub fn value_terminator(mut self, term: impl IntoResettable<Str>) -> Self {
1620 self.terminator = term.into_resettable().into_option();
1621 self
1622 }
1623
1624 /// Consume all following arguments.
1625 ///
1626 /// Do not parse them individually, but rather pass them in entirety.
1627 ///
1628 /// It is worth noting that setting this requires all values to come after a `--` to indicate
1629 /// they should all be captured. For example:
1630 ///
1631 /// ```text
1632 /// --foo something -- -v -v -v -b -b -b --baz -q -u -x
1633 /// ```
1634 ///
1635 /// Will result in everything after `--` to be considered one raw argument. This behavior
1636 /// may not be exactly what you are expecting and using [`Arg::trailing_var_arg`]
1637 /// may be more appropriate.
1638 ///
1639 /// **NOTE:** Implicitly sets [`Arg::action(ArgAction::Set)`] [`Arg::num_args(1..)`],
1640 /// [`Arg::allow_hyphen_values(true)`], and [`Arg::last(true)`] when set to `true`.
1641 ///
1642 /// [`Arg::action(ArgAction::Set)`]: Arg::action()
1643 /// [`Arg::num_args(1..)`]: Arg::num_args()
1644 /// [`Arg::allow_hyphen_values(true)`]: Arg::allow_hyphen_values()
1645 /// [`Arg::last(true)`]: Arg::last()
1646 #[inline]
1647 #[must_use]
1648 pub fn raw(mut self, yes: bool) -> Self {
1649 if yes {
1650 self.num_vals.get_or_insert_with(|| (1..).into());
1651 }
1652 self.allow_hyphen_values(yes).last(yes)
1653 }
1654
1655 /// Value for the argument when not present.
1656 ///
1657 /// **NOTE:** If the user *does not* use this argument at runtime [`ArgMatches::contains_id`] will
1658 /// still return `true`. If you wish to determine whether the argument was used at runtime or
1659 /// not, consider [`ArgMatches::value_source`][crate::ArgMatches::value_source].
1660 ///
1661 /// **NOTE:** This setting is perfectly compatible with [`Arg::default_value_if`] but slightly
1662 /// different. `Arg::default_value` *only* takes effect when the user has not provided this arg
1663 /// at runtime. `Arg::default_value_if` however only takes effect when the user has not provided
1664 /// a value at runtime **and** these other conditions are met as well. If you have set
1665 /// `Arg::default_value` and `Arg::default_value_if`, and the user **did not** provide this arg
1666 /// at runtime, nor were the conditions met for `Arg::default_value_if`, the `Arg::default_value`
1667 /// will be applied.
1668 ///
1669 /// Like with command-line values, this will be split by [`Arg::value_delimiter`].
1670 ///
1671 /// # Examples
1672 ///
1673 /// First we use the default value without providing any value at runtime.
1674 ///
1675 /// ```rust
1676 /// # use clap_builder as clap;
1677 /// # use clap::{Command, Arg, parser::ValueSource};
1678 /// let m = Command::new("prog")
1679 /// .arg(Arg::new("opt")
1680 /// .long("myopt")
1681 /// .default_value("myval"))
1682 /// .get_matches_from(vec![
1683 /// "prog"
1684 /// ]);
1685 ///
1686 /// assert_eq!(m.get_one::<String>("opt").unwrap(), "myval");
1687 /// assert!(m.contains_id("opt"));
1688 /// assert_eq!(m.value_source("opt"), Some(ValueSource::DefaultValue));
1689 /// ```
1690 ///
1691 /// Next we provide a value at runtime to override the default.
1692 ///
1693 /// ```rust
1694 /// # use clap_builder as clap;
1695 /// # use clap::{Command, Arg, parser::ValueSource};
1696 /// let m = Command::new("prog")
1697 /// .arg(Arg::new("opt")
1698 /// .long("myopt")
1699 /// .default_value("myval"))
1700 /// .get_matches_from(vec![
1701 /// "prog", "--myopt=non_default"
1702 /// ]);
1703 ///
1704 /// assert_eq!(m.get_one::<String>("opt").unwrap(), "non_default");
1705 /// assert!(m.contains_id("opt"));
1706 /// assert_eq!(m.value_source("opt"), Some(ValueSource::CommandLine));
1707 /// ```
1708 /// [`Arg::action(ArgAction::Set)`]: Arg::action()
1709 /// [`ArgMatches::contains_id`]: crate::ArgMatches::contains_id()
1710 /// [`Arg::default_value_if`]: Arg::default_value_if()
1711 #[inline]
1712 #[must_use]
1713 pub fn default_value(mut self, val: impl IntoResettable<OsStr>) -> Self {
1714 if let Some(val) = val.into_resettable().into_option() {
1715 self.default_values([val])
1716 } else {
1717 self.default_vals.clear();
1718 self
1719 }
1720 }
1721
1722 #[inline]
1723 #[must_use]
1724 #[doc(hidden)]
1725 #[cfg_attr(
1726 feature = "deprecated",
1727 deprecated(since = "4.0.0", note = "Replaced with `Arg::default_value`")
1728 )]
1729 pub fn default_value_os(self, val: impl Into<OsStr>) -> Self {
1730 self.default_values([val])
1731 }
1732
1733 /// Value for the argument when not present.
1734 ///
1735 /// See [`Arg::default_value`].
1736 ///
1737 /// [`Arg::default_value`]: Arg::default_value()
1738 #[inline]
1739 #[must_use]
1740 pub fn default_values(mut self, vals: impl IntoIterator<Item = impl Into<OsStr>>) -> Self {
1741 self.default_vals = vals.into_iter().map(|s| s.into()).collect();
1742 self
1743 }
1744
1745 #[inline]
1746 #[must_use]
1747 #[doc(hidden)]
1748 #[cfg_attr(
1749 feature = "deprecated",
1750 deprecated(since = "4.0.0", note = "Replaced with `Arg::default_values`")
1751 )]
1752 pub fn default_values_os(self, vals: impl IntoIterator<Item = impl Into<OsStr>>) -> Self {
1753 self.default_values(vals)
1754 }
1755
1756 /// Value for the argument when the flag is present but no value is specified.
1757 ///
1758 /// This configuration option is often used to give the user a shortcut and allow them to
1759 /// efficiently specify an option argument without requiring an explicitly value. The `--color`
1760 /// argument is a common example. By supplying a default, such as `default_missing_value("always")`,
1761 /// the user can quickly just add `--color` to the command line to produce the desired color output.
1762 ///
1763 /// **NOTE:** using this configuration option requires the use of the
1764 /// [`.num_args(0..N)`][Arg::num_args] and the
1765 /// [`.require_equals(true)`][Arg::require_equals] configuration option. These are required in
1766 /// order to unambiguously determine what, if any, value was supplied for the argument.
1767 ///
1768 /// Like with command-line values, this will be split by [`Arg::value_delimiter`].
1769 ///
1770 /// # Examples
1771 ///
1772 /// For POSIX style `--color`:
1773 /// ```rust
1774 /// # use clap_builder as clap;
1775 /// # use clap::{Command, Arg, parser::ValueSource};
1776 /// fn cli() -> Command {
1777 /// Command::new("prog")
1778 /// .arg(Arg::new("color").long("color")
1779 /// .value_name("WHEN")
1780 /// .value_parser(["always", "auto", "never"])
1781 /// .default_value("auto")
1782 /// .num_args(0..=1)
1783 /// .require_equals(true)
1784 /// .default_missing_value("always")
1785 /// .help("Specify WHEN to colorize output.")
1786 /// )
1787 /// }
1788 ///
1789 /// // first, we'll provide no arguments
1790 /// let m = cli().get_matches_from(vec![
1791 /// "prog"
1792 /// ]);
1793 /// assert_eq!(m.get_one::<String>("color").unwrap(), "auto");
1794 /// assert_eq!(m.value_source("color"), Some(ValueSource::DefaultValue));
1795 ///
1796 /// // next, we'll provide a runtime value to override the default (as usually done).
1797 /// let m = cli().get_matches_from(vec![
1798 /// "prog", "--color=never"
1799 /// ]);
1800 /// assert_eq!(m.get_one::<String>("color").unwrap(), "never");
1801 /// assert_eq!(m.value_source("color"), Some(ValueSource::CommandLine));
1802 ///
1803 /// // finally, we will use the shortcut and only provide the argument without a value.
1804 /// let m = cli().get_matches_from(vec![
1805 /// "prog", "--color"
1806 /// ]);
1807 /// assert_eq!(m.get_one::<String>("color").unwrap(), "always");
1808 /// assert_eq!(m.value_source("color"), Some(ValueSource::CommandLine));
1809 /// ```
1810 ///
1811 /// For bool literals:
1812 /// ```rust
1813 /// # use clap_builder as clap;
1814 /// # use clap::{Command, Arg, parser::ValueSource, value_parser};
1815 /// fn cli() -> Command {
1816 /// Command::new("prog")
1817 /// .arg(Arg::new("create").long("create")
1818 /// .value_name("BOOL")
1819 /// .value_parser(value_parser!(bool))
1820 /// .num_args(0..=1)
1821 /// .require_equals(true)
1822 /// .default_missing_value("true")
1823 /// )
1824 /// }
1825 ///
1826 /// // first, we'll provide no arguments
1827 /// let m = cli().get_matches_from(vec![
1828 /// "prog"
1829 /// ]);
1830 /// assert_eq!(m.get_one::<bool>("create").copied(), None);
1831 ///
1832 /// // next, we'll provide a runtime value to override the default (as usually done).
1833 /// let m = cli().get_matches_from(vec![
1834 /// "prog", "--create=false"
1835 /// ]);
1836 /// assert_eq!(m.get_one::<bool>("create").copied(), Some(false));
1837 /// assert_eq!(m.value_source("create"), Some(ValueSource::CommandLine));
1838 ///
1839 /// // finally, we will use the shortcut and only provide the argument without a value.
1840 /// let m = cli().get_matches_from(vec![
1841 /// "prog", "--create"
1842 /// ]);
1843 /// assert_eq!(m.get_one::<bool>("create").copied(), Some(true));
1844 /// assert_eq!(m.value_source("create"), Some(ValueSource::CommandLine));
1845 /// ```
1846 ///
1847 /// [`Arg::action(ArgAction::Set)`]: Arg::action()
1848 /// [`Arg::default_value`]: Arg::default_value()
1849 #[inline]
1850 #[must_use]
1851 pub fn default_missing_value(mut self, val: impl IntoResettable<OsStr>) -> Self {
1852 if let Some(val) = val.into_resettable().into_option() {
1853 self.default_missing_values_os([val])
1854 } else {
1855 self.default_missing_vals.clear();
1856 self
1857 }
1858 }
1859
1860 /// Value for the argument when the flag is present but no value is specified.
1861 ///
1862 /// See [`Arg::default_missing_value`].
1863 ///
1864 /// [`Arg::default_missing_value`]: Arg::default_missing_value()
1865 /// [`OsStr`]: std::ffi::OsStr
1866 #[inline]
1867 #[must_use]
1868 pub fn default_missing_value_os(self, val: impl Into<OsStr>) -> Self {
1869 self.default_missing_values_os([val])
1870 }
1871
1872 /// Value for the argument when the flag is present but no value is specified.
1873 ///
1874 /// See [`Arg::default_missing_value`].
1875 ///
1876 /// [`Arg::default_missing_value`]: Arg::default_missing_value()
1877 #[inline]
1878 #[must_use]
1879 pub fn default_missing_values(self, vals: impl IntoIterator<Item = impl Into<OsStr>>) -> Self {
1880 self.default_missing_values_os(vals)
1881 }
1882
1883 /// Value for the argument when the flag is present but no value is specified.
1884 ///
1885 /// See [`Arg::default_missing_values`].
1886 ///
1887 /// [`Arg::default_missing_values`]: Arg::default_missing_values()
1888 /// [`OsStr`]: std::ffi::OsStr
1889 #[inline]
1890 #[must_use]
1891 pub fn default_missing_values_os(
1892 mut self,
1893 vals: impl IntoIterator<Item = impl Into<OsStr>>,
1894 ) -> Self {
1895 self.default_missing_vals = vals.into_iter().map(|s| s.into()).collect();
1896 self
1897 }
1898
1899 /// Read from `name` environment variable when argument is not present.
1900 ///
1901 /// If it is not present in the environment, then default
1902 /// rules will apply.
1903 ///
1904 /// If user sets the argument in the environment:
1905 /// - When [`Arg::action(ArgAction::Set)`] is not set, the flag is considered raised.
1906 /// - When [`Arg::action(ArgAction::Set)`] is set,
1907 /// [`ArgMatches::get_one`][crate::ArgMatches::get_one] will
1908 /// return value of the environment variable.
1909 ///
1910 /// If user doesn't set the argument in the environment:
1911 /// - When [`Arg::action(ArgAction::Set)`] is not set, the flag is considered off.
1912 /// - When [`Arg::action(ArgAction::Set)`] is set,
1913 /// [`ArgMatches::get_one`][crate::ArgMatches::get_one] will
1914 /// return the default specified.
1915 ///
1916 /// Like with command-line values, this will be split by [`Arg::value_delimiter`].
1917 ///
1918 /// # Examples
1919 ///
1920 /// In this example, we show the variable coming from the environment:
1921 ///
1922 /// ```rust
1923 /// # use clap_builder as clap;
1924 /// # use std::env;
1925 /// # use clap::{Command, Arg, ArgAction};
1926 ///
1927 /// env::set_var("MY_FLAG", "env");
1928 ///
1929 /// let m = Command::new("prog")
1930 /// .arg(Arg::new("flag")
1931 /// .long("flag")
1932 /// .env("MY_FLAG")
1933 /// .action(ArgAction::Set))
1934 /// .get_matches_from(vec![
1935 /// "prog"
1936 /// ]);
1937 ///
1938 /// assert_eq!(m.get_one::<String>("flag").unwrap(), "env");
1939 /// ```
1940 ///
1941 /// In this example, because `prog` is a flag that accepts an optional, case-insensitive
1942 /// boolean literal.
1943 ///
1944 /// Note that the value parser controls how flags are parsed. In this case we've selected
1945 /// [`FalseyValueParser`][crate::builder::FalseyValueParser]. A `false` literal is `n`, `no`,
1946 /// `f`, `false`, `off` or `0`. An absent environment variable will also be considered as
1947 /// `false`. Anything else will considered as `true`.
1948 ///
1949 /// ```rust
1950 /// # use clap_builder as clap;
1951 /// # use std::env;
1952 /// # use clap::{Command, Arg, ArgAction};
1953 /// # use clap::builder::FalseyValueParser;
1954 ///
1955 /// env::set_var("TRUE_FLAG", "true");
1956 /// env::set_var("FALSE_FLAG", "0");
1957 ///
1958 /// let m = Command::new("prog")
1959 /// .arg(Arg::new("true_flag")
1960 /// .long("true_flag")
1961 /// .action(ArgAction::SetTrue)
1962 /// .value_parser(FalseyValueParser::new())
1963 /// .env("TRUE_FLAG"))
1964 /// .arg(Arg::new("false_flag")
1965 /// .long("false_flag")
1966 /// .action(ArgAction::SetTrue)
1967 /// .value_parser(FalseyValueParser::new())
1968 /// .env("FALSE_FLAG"))
1969 /// .arg(Arg::new("absent_flag")
1970 /// .long("absent_flag")
1971 /// .action(ArgAction::SetTrue)
1972 /// .value_parser(FalseyValueParser::new())
1973 /// .env("ABSENT_FLAG"))
1974 /// .get_matches_from(vec![
1975 /// "prog"
1976 /// ]);
1977 ///
1978 /// assert!(m.get_flag("true_flag"));
1979 /// assert!(!m.get_flag("false_flag"));
1980 /// assert!(!m.get_flag("absent_flag"));
1981 /// ```
1982 ///
1983 /// In this example, we show the variable coming from an option on the CLI:
1984 ///
1985 /// ```rust
1986 /// # use clap_builder as clap;
1987 /// # use std::env;
1988 /// # use clap::{Command, Arg, ArgAction};
1989 ///
1990 /// env::set_var("MY_FLAG", "env");
1991 ///
1992 /// let m = Command::new("prog")
1993 /// .arg(Arg::new("flag")
1994 /// .long("flag")
1995 /// .env("MY_FLAG")
1996 /// .action(ArgAction::Set))
1997 /// .get_matches_from(vec![
1998 /// "prog", "--flag", "opt"
1999 /// ]);
2000 ///
2001 /// assert_eq!(m.get_one::<String>("flag").unwrap(), "opt");
2002 /// ```
2003 ///
2004 /// In this example, we show the variable coming from the environment even with the
2005 /// presence of a default:
2006 ///
2007 /// ```rust
2008 /// # use clap_builder as clap;
2009 /// # use std::env;
2010 /// # use clap::{Command, Arg, ArgAction};
2011 ///
2012 /// env::set_var("MY_FLAG", "env");
2013 ///
2014 /// let m = Command::new("prog")
2015 /// .arg(Arg::new("flag")
2016 /// .long("flag")
2017 /// .env("MY_FLAG")
2018 /// .action(ArgAction::Set)
2019 /// .default_value("default"))
2020 /// .get_matches_from(vec![
2021 /// "prog"
2022 /// ]);
2023 ///
2024 /// assert_eq!(m.get_one::<String>("flag").unwrap(), "env");
2025 /// ```
2026 ///
2027 /// In this example, we show the use of multiple values in a single environment variable:
2028 ///
2029 /// ```rust
2030 /// # use clap_builder as clap;
2031 /// # use std::env;
2032 /// # use clap::{Command, Arg, ArgAction};
2033 ///
2034 /// env::set_var("MY_FLAG_MULTI", "env1,env2");
2035 ///
2036 /// let m = Command::new("prog")
2037 /// .arg(Arg::new("flag")
2038 /// .long("flag")
2039 /// .env("MY_FLAG_MULTI")
2040 /// .action(ArgAction::Set)
2041 /// .num_args(1..)
2042 /// .value_delimiter(','))
2043 /// .get_matches_from(vec![
2044 /// "prog"
2045 /// ]);
2046 ///
2047 /// assert_eq!(m.get_many::<String>("flag").unwrap().collect::<Vec<_>>(), vec!["env1", "env2"]);
2048 /// ```
2049 /// [`Arg::action(ArgAction::Set)`]: Arg::action()
2050 /// [`Arg::value_delimiter(',')`]: Arg::value_delimiter()
2051 #[cfg(feature = "env")]
2052 #[inline]
2053 #[must_use]
2054 pub fn env(mut self, name: impl IntoResettable<OsStr>) -> Self {
2055 if let Some(name) = name.into_resettable().into_option() {
2056 let value = env::var_os(&name);
2057 self.env = Some((name, value));
2058 } else {
2059 self.env = None;
2060 }
2061 self
2062 }
2063
2064 #[cfg(feature = "env")]
2065 #[doc(hidden)]
2066 #[cfg_attr(
2067 feature = "deprecated",
2068 deprecated(since = "4.0.0", note = "Replaced with `Arg::env`")
2069 )]
2070 pub fn env_os(self, name: impl Into<OsStr>) -> Self {
2071 self.env(name)
2072 }
2073}
2074
2075/// # Help
2076impl Arg {
2077 /// Sets the description of the argument for short help (`-h`).
2078 ///
2079 /// Typically, this is a short (one line) description of the arg.
2080 ///
2081 /// If [`Arg::long_help`] is not specified, this message will be displayed for `--help`.
2082 ///
2083 /// **NOTE:** Only `Arg::help` is used in completion script generation in order to be concise
2084 ///
2085 /// # Examples
2086 ///
2087 /// Any valid UTF-8 is allowed in the help text. The one exception is when one wishes to
2088 /// include a newline in the help text and have the following text be properly aligned with all
2089 /// the other help text.
2090 ///
2091 /// Setting `help` displays a short message to the side of the argument when the user passes
2092 /// `-h` or `--help` (by default).
2093 ///
2094 /// ```rust
2095 /// # #[cfg(feature = "help")] {
2096 /// # use clap_builder as clap;
2097 /// # use clap::{Command, Arg};
2098 /// let m = Command::new("prog")
2099 /// .arg(Arg::new("cfg")
2100 /// .long("config")
2101 /// .help("Some help text describing the --config arg"))
2102 /// .get_matches_from(vec![
2103 /// "prog", "--help"
2104 /// ]);
2105 /// # }
2106 /// ```
2107 ///
2108 /// The above example displays
2109 ///
2110 /// ```notrust
2111 /// helptest
2112 ///
2113 /// Usage: helptest [OPTIONS]
2114 ///
2115 /// Options:
2116 /// --config Some help text describing the --config arg
2117 /// -h, --help Print help information
2118 /// -V, --version Print version information
2119 /// ```
2120 /// [`Arg::long_help`]: Arg::long_help()
2121 #[inline]
2122 #[must_use]
2123 pub fn help(mut self, h: impl IntoResettable<StyledStr>) -> Self {
2124 self.help = h.into_resettable().into_option();
2125 self
2126 }
2127
2128 /// Sets the description of the argument for long help (`--help`).
2129 ///
2130 /// Typically this a more detailed (multi-line) message
2131 /// that describes the arg.
2132 ///
2133 /// If [`Arg::help`] is not specified, this message will be displayed for `-h`.
2134 ///
2135 /// **NOTE:** Only [`Arg::help`] is used in completion script generation in order to be concise
2136 ///
2137 /// # Examples
2138 ///
2139 /// Any valid UTF-8 is allowed in the help text. The one exception is when one wishes to
2140 /// include a newline in the help text and have the following text be properly aligned with all
2141 /// the other help text.
2142 ///
2143 /// Setting `help` displays a short message to the side of the argument when the user passes
2144 /// `-h` or `--help` (by default).
2145 ///
2146 /// ```rust
2147 /// # #[cfg(feature = "help")] {
2148 /// # use clap_builder as clap;
2149 /// # use clap::{Command, Arg};
2150 /// let m = Command::new("prog")
2151 /// .arg(Arg::new("cfg")
2152 /// .long("config")
2153 /// .long_help(
2154 /// "The config file used by the myprog must be in JSON format
2155 /// with only valid keys and may not contain other nonsense
2156 /// that cannot be read by this program. Obviously I'm going on
2157 /// and on, so I'll stop now."))
2158 /// .get_matches_from(vec![
2159 /// "prog", "--help"
2160 /// ]);
2161 /// # }
2162 /// ```
2163 ///
2164 /// The above example displays
2165 ///
2166 /// ```text
2167 /// prog
2168 ///
2169 /// Usage: prog [OPTIONS]
2170 ///
2171 /// Options:
2172 /// --config
2173 /// The config file used by the myprog must be in JSON format
2174 /// with only valid keys and may not contain other nonsense
2175 /// that cannot be read by this program. Obviously I'm going on
2176 /// and on, so I'll stop now.
2177 ///
2178 /// -h, --help
2179 /// Print help information
2180 ///
2181 /// -V, --version
2182 /// Print version information
2183 /// ```
2184 /// [`Arg::help`]: Arg::help()
2185 #[inline]
2186 #[must_use]
2187 pub fn long_help(mut self, h: impl IntoResettable<StyledStr>) -> Self {
2188 self.long_help = h.into_resettable().into_option();
2189 self
2190 }
2191
2192 /// Allows custom ordering of args within the help message.
2193 ///
2194 /// `Arg`s with a lower value will be displayed first in the help message.
2195 /// Those with the same display order will be sorted.
2196 ///
2197 /// `Arg`s are automatically assigned a display order based on the order they are added to the
2198 /// [`Command`][crate::Command].
2199 /// Overriding this is helpful when the order arguments are added in isn't the same as the
2200 /// display order, whether in one-off cases or to automatically sort arguments.
2201 ///
2202 /// To change, see [`Command::next_display_order`][crate::Command::next_display_order].
2203 ///
2204 /// **NOTE:** This setting is ignored for [positional arguments] which are always displayed in
2205 /// [index] order.
2206 ///
2207 /// # Examples
2208 ///
2209 /// ```rust
2210 /// # #[cfg(feature = "help")] {
2211 /// # use clap_builder as clap;
2212 /// # use clap::{Command, Arg, ArgAction};
2213 /// let m = Command::new("prog")
2214 /// .arg(Arg::new("boat")
2215 /// .short('b')
2216 /// .long("boat")
2217 /// .action(ArgAction::Set)
2218 /// .display_order(0) // Sort
2219 /// .help("Some help and text"))
2220 /// .arg(Arg::new("airplane")
2221 /// .short('a')
2222 /// .long("airplane")
2223 /// .action(ArgAction::Set)
2224 /// .display_order(0) // Sort
2225 /// .help("I should be first!"))
2226 /// .arg(Arg::new("custom-help")
2227 /// .short('?')
2228 /// .action(ArgAction::Help)
2229 /// .display_order(100) // Don't sort
2230 /// .help("Alt help"))
2231 /// .get_matches_from(vec![
2232 /// "prog", "--help"
2233 /// ]);
2234 /// # }
2235 /// ```
2236 ///
2237 /// The above example displays the following help message
2238 ///
2239 /// ```text
2240 /// cust-ord
2241 ///
2242 /// Usage: cust-ord [OPTIONS]
2243 ///
2244 /// Options:
2245 /// -a, --airplane <airplane> I should be first!
2246 /// -b, --boat <boar> Some help and text
2247 /// -h, --help Print help information
2248 /// -? Alt help
2249 /// ```
2250 /// [positional arguments]: Arg::index()
2251 /// [index]: Arg::index()
2252 #[inline]
2253 #[must_use]
2254 pub fn display_order(mut self, ord: impl IntoResettable<usize>) -> Self {
2255 self.disp_ord = ord.into_resettable().into_option();
2256 self
2257 }
2258
2259 /// Override the [current] help section.
2260 ///
2261 /// [current]: crate::Command::next_help_heading
2262 #[inline]
2263 #[must_use]
2264 pub fn help_heading(mut self, heading: impl IntoResettable<Str>) -> Self {
2265 self.help_heading = Some(heading.into_resettable().into_option());
2266 self
2267 }
2268
2269 /// Render the [help][Arg::help] on the line after the argument.
2270 ///
2271 /// This can be helpful for arguments with very long or complex help messages.
2272 /// This can also be helpful for arguments with very long flag names, or many/long value names.
2273 ///
2274 /// **NOTE:** To apply this setting to all arguments and subcommands, consider using
2275 /// [`crate::Command::next_line_help`]
2276 ///
2277 /// # Examples
2278 ///
2279 /// ```rust
2280 /// # #[cfg(feature = "help")] {
2281 /// # use clap_builder as clap;
2282 /// # use clap::{Command, Arg, ArgAction};
2283 /// let m = Command::new("prog")
2284 /// .arg(Arg::new("opt")
2285 /// .long("long-option-flag")
2286 /// .short('o')
2287 /// .action(ArgAction::Set)
2288 /// .next_line_help(true)
2289 /// .value_names(["value1", "value2"])
2290 /// .help("Some really long help and complex\n\
2291 /// help that makes more sense to be\n\
2292 /// on a line after the option"))
2293 /// .get_matches_from(vec![
2294 /// "prog", "--help"
2295 /// ]);
2296 /// # }
2297 /// ```
2298 ///
2299 /// The above example displays the following help message
2300 ///
2301 /// ```text
2302 /// nlh
2303 ///
2304 /// Usage: nlh [OPTIONS]
2305 ///
2306 /// Options:
2307 /// -h, --help Print help information
2308 /// -V, --version Print version information
2309 /// -o, --long-option-flag <value1> <value2>
2310 /// Some really long help and complex
2311 /// help that makes more sense to be
2312 /// on a line after the option
2313 /// ```
2314 #[inline]
2315 #[must_use]
2316 pub fn next_line_help(self, yes: bool) -> Self {
2317 if yes {
2318 self.setting(ArgSettings::NextLineHelp)
2319 } else {
2320 self.unset_setting(ArgSettings::NextLineHelp)
2321 }
2322 }
2323
2324 /// Do not display the argument in help message.
2325 ///
2326 /// **NOTE:** This does **not** hide the argument from usage strings on error
2327 ///
2328 /// # Examples
2329 ///
2330 /// Setting `Hidden` will hide the argument when displaying help text
2331 ///
2332 /// ```rust
2333 /// # #[cfg(feature = "help")] {
2334 /// # use clap_builder as clap;
2335 /// # use clap::{Command, Arg};
2336 /// let m = Command::new("prog")
2337 /// .arg(Arg::new("cfg")
2338 /// .long("config")
2339 /// .hide(true)
2340 /// .help("Some help text describing the --config arg"))
2341 /// .get_matches_from(vec![
2342 /// "prog", "--help"
2343 /// ]);
2344 /// # }
2345 /// ```
2346 ///
2347 /// The above example displays
2348 ///
2349 /// ```text
2350 /// helptest
2351 ///
2352 /// Usage: helptest [OPTIONS]
2353 ///
2354 /// Options:
2355 /// -h, --help Print help information
2356 /// -V, --version Print version information
2357 /// ```
2358 #[inline]
2359 #[must_use]
2360 pub fn hide(self, yes: bool) -> Self {
2361 if yes {
2362 self.setting(ArgSettings::Hidden)
2363 } else {
2364 self.unset_setting(ArgSettings::Hidden)
2365 }
2366 }
2367
2368 /// Do not display the [possible values][crate::builder::ValueParser::possible_values] in the help message.
2369 ///
2370 /// This is useful for args with many values, or ones which are explained elsewhere in the
2371 /// help text.
2372 ///
2373 /// **NOTE:** Setting this requires [taking values][Arg::num_args]
2374 ///
2375 /// To set this for all arguments, see
2376 /// [`Command::hide_possible_values`][crate::Command::hide_possible_values].
2377 ///
2378 /// # Examples
2379 ///
2380 /// ```rust
2381 /// # use clap_builder as clap;
2382 /// # use clap::{Command, Arg, ArgAction};
2383 /// let m = Command::new("prog")
2384 /// .arg(Arg::new("mode")
2385 /// .long("mode")
2386 /// .value_parser(["fast", "slow"])
2387 /// .action(ArgAction::Set)
2388 /// .hide_possible_values(true));
2389 /// ```
2390 /// If we were to run the above program with `--help` the `[values: fast, slow]` portion of
2391 /// the help text would be omitted.
2392 #[inline]
2393 #[must_use]
2394 pub fn hide_possible_values(self, yes: bool) -> Self {
2395 if yes {
2396 self.setting(ArgSettings::HidePossibleValues)
2397 } else {
2398 self.unset_setting(ArgSettings::HidePossibleValues)
2399 }
2400 }
2401
2402 /// Do not display the default value of the argument in the help message.
2403 ///
2404 /// This is useful when default behavior of an arg is explained elsewhere in the help text.
2405 ///
2406 /// **NOTE:** Setting this requires [taking values][Arg::num_args]
2407 ///
2408 /// # Examples
2409 ///
2410 /// ```rust
2411 /// # use clap_builder as clap;
2412 /// # use clap::{Command, Arg, ArgAction};
2413 /// let m = Command::new("connect")
2414 /// .arg(Arg::new("host")
2415 /// .long("host")
2416 /// .default_value("localhost")
2417 /// .action(ArgAction::Set)
2418 /// .hide_default_value(true));
2419 ///
2420 /// ```
2421 ///
2422 /// If we were to run the above program with `--help` the `[default: localhost]` portion of
2423 /// the help text would be omitted.
2424 #[inline]
2425 #[must_use]
2426 pub fn hide_default_value(self, yes: bool) -> Self {
2427 if yes {
2428 self.setting(ArgSettings::HideDefaultValue)
2429 } else {
2430 self.unset_setting(ArgSettings::HideDefaultValue)
2431 }
2432 }
2433
2434 /// Do not display in help the environment variable name.
2435 ///
2436 /// This is useful when the variable option is explained elsewhere in the help text.
2437 ///
2438 /// # Examples
2439 ///
2440 /// ```rust
2441 /// # use clap_builder as clap;
2442 /// # use clap::{Command, Arg, ArgAction};
2443 /// let m = Command::new("prog")
2444 /// .arg(Arg::new("mode")
2445 /// .long("mode")
2446 /// .env("MODE")
2447 /// .action(ArgAction::Set)
2448 /// .hide_env(true));
2449 /// ```
2450 ///
2451 /// If we were to run the above program with `--help` the `[env: MODE]` portion of the help
2452 /// text would be omitted.
2453 #[cfg(feature = "env")]
2454 #[inline]
2455 #[must_use]
2456 pub fn hide_env(self, yes: bool) -> Self {
2457 if yes {
2458 self.setting(ArgSettings::HideEnv)
2459 } else {
2460 self.unset_setting(ArgSettings::HideEnv)
2461 }
2462 }
2463
2464 /// Do not display in help any values inside the associated ENV variables for the argument.
2465 ///
2466 /// This is useful when ENV vars contain sensitive values.
2467 ///
2468 /// # Examples
2469 ///
2470 /// ```rust
2471 /// # use clap_builder as clap;
2472 /// # use clap::{Command, Arg, ArgAction};
2473 /// let m = Command::new("connect")
2474 /// .arg(Arg::new("host")
2475 /// .long("host")
2476 /// .env("CONNECT")
2477 /// .action(ArgAction::Set)
2478 /// .hide_env_values(true));
2479 ///
2480 /// ```
2481 ///
2482 /// If we were to run the above program with `$ CONNECT=super_secret connect --help` the
2483 /// `[default: CONNECT=super_secret]` portion of the help text would be omitted.
2484 #[cfg(feature = "env")]
2485 #[inline]
2486 #[must_use]
2487 pub fn hide_env_values(self, yes: bool) -> Self {
2488 if yes {
2489 self.setting(ArgSettings::HideEnvValues)
2490 } else {
2491 self.unset_setting(ArgSettings::HideEnvValues)
2492 }
2493 }
2494
2495 /// Hides an argument from short help (`-h`).
2496 ///
2497 /// **NOTE:** This does **not** hide the argument from usage strings on error
2498 ///
2499 /// **NOTE:** Setting this option will cause next-line-help output style to be used
2500 /// when long help (`--help`) is called.
2501 ///
2502 /// # Examples
2503 ///
2504 /// ```rust
2505 /// # use clap_builder as clap;
2506 /// # use clap::{Command, Arg};
2507 /// Arg::new("debug")
2508 /// .hide_short_help(true);
2509 /// ```
2510 ///
2511 /// Setting `hide_short_help(true)` will hide the argument when displaying short help text
2512 ///
2513 /// ```rust
2514 /// # #[cfg(feature = "help")] {
2515 /// # use clap_builder as clap;
2516 /// # use clap::{Command, Arg};
2517 /// let m = Command::new("prog")
2518 /// .arg(Arg::new("cfg")
2519 /// .long("config")
2520 /// .hide_short_help(true)
2521 /// .help("Some help text describing the --config arg"))
2522 /// .get_matches_from(vec![
2523 /// "prog", "-h"
2524 /// ]);
2525 /// # }
2526 /// ```
2527 ///
2528 /// The above example displays
2529 ///
2530 /// ```text
2531 /// helptest
2532 ///
2533 /// Usage: helptest [OPTIONS]
2534 ///
2535 /// Options:
2536 /// -h, --help Print help information
2537 /// -V, --version Print version information
2538 /// ```
2539 ///
2540 /// However, when --help is called
2541 ///
2542 /// ```rust
2543 /// # #[cfg(feature = "help")] {
2544 /// # use clap_builder as clap;
2545 /// # use clap::{Command, Arg};
2546 /// let m = Command::new("prog")
2547 /// .arg(Arg::new("cfg")
2548 /// .long("config")
2549 /// .hide_short_help(true)
2550 /// .help("Some help text describing the --config arg"))
2551 /// .get_matches_from(vec![
2552 /// "prog", "--help"
2553 /// ]);
2554 /// # }
2555 /// ```
2556 ///
2557 /// Then the following would be displayed
2558 ///
2559 /// ```text
2560 /// helptest
2561 ///
2562 /// Usage: helptest [OPTIONS]
2563 ///
2564 /// Options:
2565 /// --config Some help text describing the --config arg
2566 /// -h, --help Print help information
2567 /// -V, --version Print version information
2568 /// ```
2569 #[inline]
2570 #[must_use]
2571 pub fn hide_short_help(self, yes: bool) -> Self {
2572 if yes {
2573 self.setting(ArgSettings::HiddenShortHelp)
2574 } else {
2575 self.unset_setting(ArgSettings::HiddenShortHelp)
2576 }
2577 }
2578
2579 /// Hides an argument from long help (`--help`).
2580 ///
2581 /// **NOTE:** This does **not** hide the argument from usage strings on error
2582 ///
2583 /// **NOTE:** Setting this option will cause next-line-help output style to be used
2584 /// when long help (`--help`) is called.
2585 ///
2586 /// # Examples
2587 ///
2588 /// Setting `hide_long_help(true)` will hide the argument when displaying long help text
2589 ///
2590 /// ```rust
2591 /// # #[cfg(feature = "help")] {
2592 /// # use clap_builder as clap;
2593 /// # use clap::{Command, Arg};
2594 /// let m = Command::new("prog")
2595 /// .arg(Arg::new("cfg")
2596 /// .long("config")
2597 /// .hide_long_help(true)
2598 /// .help("Some help text describing the --config arg"))
2599 /// .get_matches_from(vec![
2600 /// "prog", "--help"
2601 /// ]);
2602 /// # }
2603 /// ```
2604 ///
2605 /// The above example displays
2606 ///
2607 /// ```text
2608 /// helptest
2609 ///
2610 /// Usage: helptest [OPTIONS]
2611 ///
2612 /// Options:
2613 /// -h, --help Print help information
2614 /// -V, --version Print version information
2615 /// ```
2616 ///
2617 /// However, when -h is called
2618 ///
2619 /// ```rust
2620 /// # #[cfg(feature = "help")] {
2621 /// # use clap_builder as clap;
2622 /// # use clap::{Command, Arg};
2623 /// let m = Command::new("prog")
2624 /// .arg(Arg::new("cfg")
2625 /// .long("config")
2626 /// .hide_long_help(true)
2627 /// .help("Some help text describing the --config arg"))
2628 /// .get_matches_from(vec![
2629 /// "prog", "-h"
2630 /// ]);
2631 /// # }
2632 /// ```
2633 ///
2634 /// Then the following would be displayed
2635 ///
2636 /// ```text
2637 /// helptest
2638 ///
2639 /// Usage: helptest [OPTIONS]
2640 ///
2641 /// OPTIONS:
2642 /// --config Some help text describing the --config arg
2643 /// -h, --help Print help information
2644 /// -V, --version Print version information
2645 /// ```
2646 #[inline]
2647 #[must_use]
2648 pub fn hide_long_help(self, yes: bool) -> Self {
2649 if yes {
2650 self.setting(ArgSettings::HiddenLongHelp)
2651 } else {
2652 self.unset_setting(ArgSettings::HiddenLongHelp)
2653 }
2654 }
2655}
2656
2657/// # Advanced Argument Relations
2658impl Arg {
2659 /// The name of the [`ArgGroup`] the argument belongs to.
2660 ///
2661 /// # Examples
2662 ///
2663 /// ```rust
2664 /// # use clap_builder as clap;
2665 /// # use clap::{Command, Arg, ArgAction};
2666 /// Arg::new("debug")
2667 /// .long("debug")
2668 /// .action(ArgAction::SetTrue)
2669 /// .group("mode")
2670 /// # ;
2671 /// ```
2672 ///
2673 /// Multiple arguments can be a member of a single group and then the group checked as if it
2674 /// was one of said arguments.
2675 ///
2676 /// ```rust
2677 /// # use clap_builder as clap;
2678 /// # use clap::{Command, Arg, ArgAction};
2679 /// let m = Command::new("prog")
2680 /// .arg(Arg::new("debug")
2681 /// .long("debug")
2682 /// .action(ArgAction::SetTrue)
2683 /// .group("mode"))
2684 /// .arg(Arg::new("verbose")
2685 /// .long("verbose")
2686 /// .action(ArgAction::SetTrue)
2687 /// .group("mode"))
2688 /// .get_matches_from(vec![
2689 /// "prog", "--debug"
2690 /// ]);
2691 /// assert!(m.contains_id("mode"));
2692 /// ```
2693 ///
2694 /// [`ArgGroup`]: crate::ArgGroup
2695 #[must_use]
2696 pub fn group(mut self, group_id: impl IntoResettable<Id>) -> Self {
2697 if let Some(group_id) = group_id.into_resettable().into_option() {
2698 self.groups.push(group_id);
2699 } else {
2700 self.groups.clear();
2701 }
2702 self
2703 }
2704
2705 /// The names of [`ArgGroup`]'s the argument belongs to.
2706 ///
2707 /// # Examples
2708 ///
2709 /// ```rust
2710 /// # use clap_builder as clap;
2711 /// # use clap::{Command, Arg, ArgAction};
2712 /// Arg::new("debug")
2713 /// .long("debug")
2714 /// .action(ArgAction::SetTrue)
2715 /// .groups(["mode", "verbosity"])
2716 /// # ;
2717 /// ```
2718 ///
2719 /// Arguments can be members of multiple groups and then the group checked as if it
2720 /// was one of said arguments.
2721 ///
2722 /// ```rust
2723 /// # use clap_builder as clap;
2724 /// # use clap::{Command, Arg, ArgAction};
2725 /// let m = Command::new("prog")
2726 /// .arg(Arg::new("debug")
2727 /// .long("debug")
2728 /// .action(ArgAction::SetTrue)
2729 /// .groups(["mode", "verbosity"]))
2730 /// .arg(Arg::new("verbose")
2731 /// .long("verbose")
2732 /// .action(ArgAction::SetTrue)
2733 /// .groups(["mode", "verbosity"]))
2734 /// .get_matches_from(vec![
2735 /// "prog", "--debug"
2736 /// ]);
2737 /// assert!(m.contains_id("mode"));
2738 /// assert!(m.contains_id("verbosity"));
2739 /// ```
2740 ///
2741 /// [`ArgGroup`]: crate::ArgGroup
2742 #[must_use]
2743 pub fn groups(mut self, group_ids: impl IntoIterator<Item = impl Into<Id>>) -> Self {
2744 self.groups.extend(group_ids.into_iter().map(Into::into));
2745 self
2746 }
2747
2748 /// Specifies the value of the argument if `arg` has been used at runtime.
2749 ///
2750 /// If `default` is set to `None`, `default_value` will be removed.
2751 ///
2752 /// **NOTE:** This setting is perfectly compatible with [`Arg::default_value`] but slightly
2753 /// different. `Arg::default_value` *only* takes effect when the user has not provided this arg
2754 /// at runtime. This setting however only takes effect when the user has not provided a value at
2755 /// runtime **and** these other conditions are met as well. If you have set `Arg::default_value`
2756 /// and `Arg::default_value_if`, and the user **did not** provide this arg at runtime, nor were
2757 /// the conditions met for `Arg::default_value_if`, the `Arg::default_value` will be applied.
2758 ///
2759 /// Like with command-line values, this will be split by [`Arg::value_delimiter`].
2760 ///
2761 /// # Examples
2762 ///
2763 /// First we use the default value only if another arg is present at runtime.
2764 ///
2765 /// ```rust
2766 /// # use clap_builder as clap;
2767 /// # use clap::{Command, Arg, ArgAction};
2768 /// # use clap::builder::{ArgPredicate};
2769 /// let m = Command::new("prog")
2770 /// .arg(Arg::new("flag")
2771 /// .long("flag")
2772 /// .action(ArgAction::SetTrue))
2773 /// .arg(Arg::new("other")
2774 /// .long("other")
2775 /// .default_value_if("flag", ArgPredicate::IsPresent, Some("default")))
2776 /// .get_matches_from(vec![
2777 /// "prog", "--flag"
2778 /// ]);
2779 ///
2780 /// assert_eq!(m.get_one::<String>("other").unwrap(), "default");
2781 /// ```
2782 ///
2783 /// Next we run the same test, but without providing `--flag`.
2784 ///
2785 /// ```rust
2786 /// # use clap_builder as clap;
2787 /// # use clap::{Command, Arg, ArgAction};
2788 /// let m = Command::new("prog")
2789 /// .arg(Arg::new("flag")
2790 /// .long("flag")
2791 /// .action(ArgAction::SetTrue))
2792 /// .arg(Arg::new("other")
2793 /// .long("other")
2794 /// .default_value_if("flag", "true", Some("default")))
2795 /// .get_matches_from(vec![
2796 /// "prog"
2797 /// ]);
2798 ///
2799 /// assert_eq!(m.get_one::<String>("other"), None);
2800 /// ```
2801 ///
2802 /// Now lets only use the default value if `--opt` contains the value `special`.
2803 ///
2804 /// ```rust
2805 /// # use clap_builder as clap;
2806 /// # use clap::{Command, Arg, ArgAction};
2807 /// let m = Command::new("prog")
2808 /// .arg(Arg::new("opt")
2809 /// .action(ArgAction::Set)
2810 /// .long("opt"))
2811 /// .arg(Arg::new("other")
2812 /// .long("other")
2813 /// .default_value_if("opt", "special", Some("default")))
2814 /// .get_matches_from(vec![
2815 /// "prog", "--opt", "special"
2816 /// ]);
2817 ///
2818 /// assert_eq!(m.get_one::<String>("other").unwrap(), "default");
2819 /// ```
2820 ///
2821 /// We can run the same test and provide any value *other than* `special` and we won't get a
2822 /// default value.
2823 ///
2824 /// ```rust
2825 /// # use clap_builder as clap;
2826 /// # use clap::{Command, Arg, ArgAction};
2827 /// let m = Command::new("prog")
2828 /// .arg(Arg::new("opt")
2829 /// .action(ArgAction::Set)
2830 /// .long("opt"))
2831 /// .arg(Arg::new("other")
2832 /// .long("other")
2833 /// .default_value_if("opt", "special", Some("default")))
2834 /// .get_matches_from(vec![
2835 /// "prog", "--opt", "hahaha"
2836 /// ]);
2837 ///
2838 /// assert_eq!(m.get_one::<String>("other"), None);
2839 /// ```
2840 ///
2841 /// If we want to unset the default value for an Arg based on the presence or
2842 /// value of some other Arg.
2843 ///
2844 /// ```rust
2845 /// # use clap_builder as clap;
2846 /// # use clap::{Command, Arg, ArgAction};
2847 /// let m = Command::new("prog")
2848 /// .arg(Arg::new("flag")
2849 /// .long("flag")
2850 /// .action(ArgAction::SetTrue))
2851 /// .arg(Arg::new("other")
2852 /// .long("other")
2853 /// .default_value("default")
2854 /// .default_value_if("flag", "true", None))
2855 /// .get_matches_from(vec![
2856 /// "prog", "--flag"
2857 /// ]);
2858 ///
2859 /// assert_eq!(m.get_one::<String>("other"), None);
2860 /// ```
2861 /// [`Arg::action(ArgAction::Set)`]: Arg::action()
2862 /// [`Arg::default_value`]: Arg::default_value()
2863 #[must_use]
2864 pub fn default_value_if(
2865 mut self,
2866 arg_id: impl Into<Id>,
2867 predicate: impl Into<ArgPredicate>,
2868 default: impl IntoResettable<OsStr>,
2869 ) -> Self {
2870 self.default_vals_ifs.push((
2871 arg_id.into(),
2872 predicate.into(),
2873 default.into_resettable().into_option(),
2874 ));
2875 self
2876 }
2877
2878 #[must_use]
2879 #[doc(hidden)]
2880 #[cfg_attr(
2881 feature = "deprecated",
2882 deprecated(since = "4.0.0", note = "Replaced with `Arg::default_value_if`")
2883 )]
2884 pub fn default_value_if_os(
2885 self,
2886 arg_id: impl Into<Id>,
2887 predicate: impl Into<ArgPredicate>,
2888 default: impl IntoResettable<OsStr>,
2889 ) -> Self {
2890 self.default_value_if(arg_id, predicate, default)
2891 }
2892
2893 /// Specifies multiple values and conditions in the same manner as [`Arg::default_value_if`].
2894 ///
2895 /// The method takes a slice of tuples in the `(arg, predicate, default)` format.
2896 ///
2897 /// **NOTE**: The conditions are stored in order and evaluated in the same order. I.e. the first
2898 /// if multiple conditions are true, the first one found will be applied and the ultimate value.
2899 ///
2900 /// Like with command-line values, this will be split by [`Arg::value_delimiter`].
2901 ///
2902 /// # Examples
2903 ///
2904 /// First we use the default value only if another arg is present at runtime.
2905 ///
2906 /// ```rust
2907 /// # use clap_builder as clap;
2908 /// # use clap::{Command, Arg, ArgAction};
2909 /// let m = Command::new("prog")
2910 /// .arg(Arg::new("flag")
2911 /// .long("flag")
2912 /// .action(ArgAction::SetTrue))
2913 /// .arg(Arg::new("opt")
2914 /// .long("opt")
2915 /// .action(ArgAction::Set))
2916 /// .arg(Arg::new("other")
2917 /// .long("other")
2918 /// .default_value_ifs([
2919 /// ("flag", "true", Some("default")),
2920 /// ("opt", "channal", Some("chan")),
2921 /// ]))
2922 /// .get_matches_from(vec![
2923 /// "prog", "--opt", "channal"
2924 /// ]);
2925 ///
2926 /// assert_eq!(m.get_one::<String>("other").unwrap(), "chan");
2927 /// ```
2928 ///
2929 /// Next we run the same test, but without providing `--flag`.
2930 ///
2931 /// ```rust
2932 /// # use clap_builder as clap;
2933 /// # use clap::{Command, Arg, ArgAction};
2934 /// let m = Command::new("prog")
2935 /// .arg(Arg::new("flag")
2936 /// .long("flag")
2937 /// .action(ArgAction::SetTrue))
2938 /// .arg(Arg::new("other")
2939 /// .long("other")
2940 /// .default_value_ifs([
2941 /// ("flag", "true", Some("default")),
2942 /// ("opt", "channal", Some("chan")),
2943 /// ]))
2944 /// .get_matches_from(vec![
2945 /// "prog"
2946 /// ]);
2947 ///
2948 /// assert_eq!(m.get_one::<String>("other"), None);
2949 /// ```
2950 ///
2951 /// We can also see that these values are applied in order, and if more than one condition is
2952 /// true, only the first evaluated "wins"
2953 ///
2954 /// ```rust
2955 /// # use clap_builder as clap;
2956 /// # use clap::{Command, Arg, ArgAction};
2957 /// # use clap::builder::ArgPredicate;
2958 /// let m = Command::new("prog")
2959 /// .arg(Arg::new("flag")
2960 /// .long("flag")
2961 /// .action(ArgAction::SetTrue))
2962 /// .arg(Arg::new("opt")
2963 /// .long("opt")
2964 /// .action(ArgAction::Set))
2965 /// .arg(Arg::new("other")
2966 /// .long("other")
2967 /// .default_value_ifs([
2968 /// ("flag", ArgPredicate::IsPresent, Some("default")),
2969 /// ("opt", ArgPredicate::Equals("channal".into()), Some("chan")),
2970 /// ]))
2971 /// .get_matches_from(vec![
2972 /// "prog", "--opt", "channal", "--flag"
2973 /// ]);
2974 ///
2975 /// assert_eq!(m.get_one::<String>("other").unwrap(), "default");
2976 /// ```
2977 /// [`Arg::action(ArgAction::Set)`]: Arg::action()
2978 /// [`Arg::default_value_if`]: Arg::default_value_if()
2979 #[must_use]
2980 pub fn default_value_ifs(
2981 mut self,
2982 ifs: impl IntoIterator<
2983 Item = (
2984 impl Into<Id>,
2985 impl Into<ArgPredicate>,
2986 impl IntoResettable<OsStr>,
2987 ),
2988 >,
2989 ) -> Self {
2990 for (arg, predicate, default) in ifs {
2991 self = self.default_value_if(arg, predicate, default);
2992 }
2993 self
2994 }
2995
2996 #[must_use]
2997 #[doc(hidden)]
2998 #[cfg_attr(
2999 feature = "deprecated",
3000 deprecated(since = "4.0.0", note = "Replaced with `Arg::default_value_ifs`")
3001 )]
3002 pub fn default_value_ifs_os(
3003 self,
3004 ifs: impl IntoIterator<
3005 Item = (
3006 impl Into<Id>,
3007 impl Into<ArgPredicate>,
3008 impl IntoResettable<OsStr>,
3009 ),
3010 >,
3011 ) -> Self {
3012 self.default_value_ifs(ifs)
3013 }
3014
3015 /// Set this arg as [required] as long as the specified argument is not present at runtime.
3016 ///
3017 /// **Pro Tip:** Using `Arg::required_unless_present` implies [`Arg::required`] and is therefore not
3018 /// mandatory to also set.
3019 ///
3020 /// # Examples
3021 ///
3022 /// ```rust
3023 /// # use clap_builder as clap;
3024 /// # use clap::Arg;
3025 /// Arg::new("config")
3026 /// .required_unless_present("debug")
3027 /// # ;
3028 /// ```
3029 ///
3030 /// In the following example, the required argument is *not* provided,
3031 /// but it's not an error because the `unless` arg has been supplied.
3032 ///
3033 /// ```rust
3034 /// # use clap_builder as clap;
3035 /// # use clap::{Command, Arg, ArgAction};
3036 /// let res = Command::new("prog")
3037 /// .arg(Arg::new("cfg")
3038 /// .required_unless_present("dbg")
3039 /// .action(ArgAction::Set)
3040 /// .long("config"))
3041 /// .arg(Arg::new("dbg")
3042 /// .long("debug")
3043 /// .action(ArgAction::SetTrue))
3044 /// .try_get_matches_from(vec![
3045 /// "prog", "--debug"
3046 /// ]);
3047 ///
3048 /// assert!(res.is_ok());
3049 /// ```
3050 ///
3051 /// Setting `Arg::required_unless_present(name)` and *not* supplying `name` or this arg is an error.
3052 ///
3053 /// ```rust
3054 /// # use clap_builder as clap;
3055 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
3056 /// let res = Command::new("prog")
3057 /// .arg(Arg::new("cfg")
3058 /// .required_unless_present("dbg")
3059 /// .action(ArgAction::Set)
3060 /// .long("config"))
3061 /// .arg(Arg::new("dbg")
3062 /// .long("debug"))
3063 /// .try_get_matches_from(vec![
3064 /// "prog"
3065 /// ]);
3066 ///
3067 /// assert!(res.is_err());
3068 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3069 /// ```
3070 /// [required]: Arg::required()
3071 #[must_use]
3072 pub fn required_unless_present(mut self, arg_id: impl IntoResettable<Id>) -> Self {
3073 if let Some(arg_id) = arg_id.into_resettable().into_option() {
3074 self.r_unless.push(arg_id);
3075 } else {
3076 self.r_unless.clear();
3077 }
3078 self
3079 }
3080
3081 /// Sets this arg as [required] unless *all* of the specified arguments are present at runtime.
3082 ///
3083 /// In other words, parsing will succeed only if user either
3084 /// * supplies the `self` arg.
3085 /// * supplies *all* of the `names` arguments.
3086 ///
3087 /// **NOTE:** If you wish for this argument to only be required unless *any of* these args are
3088 /// present see [`Arg::required_unless_present_any`]
3089 ///
3090 /// # Examples
3091 ///
3092 /// ```rust
3093 /// # use clap_builder as clap;
3094 /// # use clap::Arg;
3095 /// Arg::new("config")
3096 /// .required_unless_present_all(["cfg", "dbg"])
3097 /// # ;
3098 /// ```
3099 ///
3100 /// In the following example, the required argument is *not* provided, but it's not an error
3101 /// because *all* of the `names` args have been supplied.
3102 ///
3103 /// ```rust
3104 /// # use clap_builder as clap;
3105 /// # use clap::{Command, Arg, ArgAction};
3106 /// let res = Command::new("prog")
3107 /// .arg(Arg::new("cfg")
3108 /// .required_unless_present_all(["dbg", "infile"])
3109 /// .action(ArgAction::Set)
3110 /// .long("config"))
3111 /// .arg(Arg::new("dbg")
3112 /// .long("debug")
3113 /// .action(ArgAction::SetTrue))
3114 /// .arg(Arg::new("infile")
3115 /// .short('i')
3116 /// .action(ArgAction::Set))
3117 /// .try_get_matches_from(vec![
3118 /// "prog", "--debug", "-i", "file"
3119 /// ]);
3120 ///
3121 /// assert!(res.is_ok());
3122 /// ```
3123 ///
3124 /// Setting [`Arg::required_unless_present_all(names)`] and *not* supplying
3125 /// either *all* of `unless` args or the `self` arg is an error.
3126 ///
3127 /// ```rust
3128 /// # use clap_builder as clap;
3129 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
3130 /// let res = Command::new("prog")
3131 /// .arg(Arg::new("cfg")
3132 /// .required_unless_present_all(["dbg", "infile"])
3133 /// .action(ArgAction::Set)
3134 /// .long("config"))
3135 /// .arg(Arg::new("dbg")
3136 /// .long("debug")
3137 /// .action(ArgAction::SetTrue))
3138 /// .arg(Arg::new("infile")
3139 /// .short('i')
3140 /// .action(ArgAction::Set))
3141 /// .try_get_matches_from(vec![
3142 /// "prog"
3143 /// ]);
3144 ///
3145 /// assert!(res.is_err());
3146 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3147 /// ```
3148 /// [required]: Arg::required()
3149 /// [`Arg::required_unless_present_any`]: Arg::required_unless_present_any()
3150 /// [`Arg::required_unless_present_all(names)`]: Arg::required_unless_present_all()
3151 #[must_use]
3152 pub fn required_unless_present_all(
3153 mut self,
3154 names: impl IntoIterator<Item = impl Into<Id>>,
3155 ) -> Self {
3156 self.r_unless_all.extend(names.into_iter().map(Into::into));
3157 self
3158 }
3159
3160 /// Sets this arg as [required] unless *any* of the specified arguments are present at runtime.
3161 ///
3162 /// In other words, parsing will succeed only if user either
3163 /// * supplies the `self` arg.
3164 /// * supplies *one or more* of the `unless` arguments.
3165 ///
3166 /// **NOTE:** If you wish for this argument to be required unless *all of* these args are
3167 /// present see [`Arg::required_unless_present_all`]
3168 ///
3169 /// # Examples
3170 ///
3171 /// ```rust
3172 /// # use clap_builder as clap;
3173 /// # use clap::Arg;
3174 /// Arg::new("config")
3175 /// .required_unless_present_any(["cfg", "dbg"])
3176 /// # ;
3177 /// ```
3178 ///
3179 /// Setting [`Arg::required_unless_present_any(names)`] requires that the argument be used at runtime
3180 /// *unless* *at least one of* the args in `names` are present. In the following example, the
3181 /// required argument is *not* provided, but it's not an error because one the `unless` args
3182 /// have been supplied.
3183 ///
3184 /// ```rust
3185 /// # use clap_builder as clap;
3186 /// # use clap::{Command, Arg, ArgAction};
3187 /// let res = Command::new("prog")
3188 /// .arg(Arg::new("cfg")
3189 /// .required_unless_present_any(["dbg", "infile"])
3190 /// .action(ArgAction::Set)
3191 /// .long("config"))
3192 /// .arg(Arg::new("dbg")
3193 /// .long("debug")
3194 /// .action(ArgAction::SetTrue))
3195 /// .arg(Arg::new("infile")
3196 /// .short('i')
3197 /// .action(ArgAction::Set))
3198 /// .try_get_matches_from(vec![
3199 /// "prog", "--debug"
3200 /// ]);
3201 ///
3202 /// assert!(res.is_ok());
3203 /// ```
3204 ///
3205 /// Setting [`Arg::required_unless_present_any(names)`] and *not* supplying *at least one of* `names`
3206 /// or this arg is an error.
3207 ///
3208 /// ```rust
3209 /// # use clap_builder as clap;
3210 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
3211 /// let res = Command::new("prog")
3212 /// .arg(Arg::new("cfg")
3213 /// .required_unless_present_any(["dbg", "infile"])
3214 /// .action(ArgAction::Set)
3215 /// .long("config"))
3216 /// .arg(Arg::new("dbg")
3217 /// .long("debug")
3218 /// .action(ArgAction::SetTrue))
3219 /// .arg(Arg::new("infile")
3220 /// .short('i')
3221 /// .action(ArgAction::Set))
3222 /// .try_get_matches_from(vec![
3223 /// "prog"
3224 /// ]);
3225 ///
3226 /// assert!(res.is_err());
3227 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3228 /// ```
3229 /// [required]: Arg::required()
3230 /// [`Arg::required_unless_present_any(names)`]: Arg::required_unless_present_any()
3231 /// [`Arg::required_unless_present_all`]: Arg::required_unless_present_all()
3232 #[must_use]
3233 pub fn required_unless_present_any(
3234 mut self,
3235 names: impl IntoIterator<Item = impl Into<Id>>,
3236 ) -> Self {
3237 self.r_unless.extend(names.into_iter().map(Into::into));
3238 self
3239 }
3240
3241 /// This argument is [required] only if the specified `arg` is present at runtime and its value
3242 /// equals `val`.
3243 ///
3244 /// # Examples
3245 ///
3246 /// ```rust
3247 /// # use clap_builder as clap;
3248 /// # use clap::Arg;
3249 /// Arg::new("config")
3250 /// .required_if_eq("other_arg", "value")
3251 /// # ;
3252 /// ```
3253 ///
3254 /// ```rust
3255 /// # use clap_builder as clap;
3256 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
3257 /// let res = Command::new("prog")
3258 /// .arg(Arg::new("cfg")
3259 /// .action(ArgAction::Set)
3260 /// .required_if_eq("other", "special")
3261 /// .long("config"))
3262 /// .arg(Arg::new("other")
3263 /// .long("other")
3264 /// .action(ArgAction::Set))
3265 /// .try_get_matches_from(vec![
3266 /// "prog", "--other", "not-special"
3267 /// ]);
3268 ///
3269 /// assert!(res.is_ok()); // We didn't use --other=special, so "cfg" wasn't required
3270 ///
3271 /// let res = Command::new("prog")
3272 /// .arg(Arg::new("cfg")
3273 /// .action(ArgAction::Set)
3274 /// .required_if_eq("other", "special")
3275 /// .long("config"))
3276 /// .arg(Arg::new("other")
3277 /// .long("other")
3278 /// .action(ArgAction::Set))
3279 /// .try_get_matches_from(vec![
3280 /// "prog", "--other", "special"
3281 /// ]);
3282 ///
3283 /// // We did use --other=special so "cfg" had become required but was missing.
3284 /// assert!(res.is_err());
3285 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3286 ///
3287 /// let res = Command::new("prog")
3288 /// .arg(Arg::new("cfg")
3289 /// .action(ArgAction::Set)
3290 /// .required_if_eq("other", "special")
3291 /// .long("config"))
3292 /// .arg(Arg::new("other")
3293 /// .long("other")
3294 /// .action(ArgAction::Set))
3295 /// .try_get_matches_from(vec![
3296 /// "prog", "--other", "SPECIAL"
3297 /// ]);
3298 ///
3299 /// // By default, the comparison is case-sensitive, so "cfg" wasn't required
3300 /// assert!(res.is_ok());
3301 ///
3302 /// let res = Command::new("prog")
3303 /// .arg(Arg::new("cfg")
3304 /// .action(ArgAction::Set)
3305 /// .required_if_eq("other", "special")
3306 /// .long("config"))
3307 /// .arg(Arg::new("other")
3308 /// .long("other")
3309 /// .ignore_case(true)
3310 /// .action(ArgAction::Set))
3311 /// .try_get_matches_from(vec![
3312 /// "prog", "--other", "SPECIAL"
3313 /// ]);
3314 ///
3315 /// // However, case-insensitive comparisons can be enabled. This typically occurs when using Arg::possible_values().
3316 /// assert!(res.is_err());
3317 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3318 /// ```
3319 /// [`Arg::requires(name)`]: Arg::requires()
3320 /// [Conflicting]: Arg::conflicts_with()
3321 /// [required]: Arg::required()
3322 #[must_use]
3323 pub fn required_if_eq(mut self, arg_id: impl Into<Id>, val: impl Into<OsStr>) -> Self {
3324 self.r_ifs.push((arg_id.into(), val.into()));
3325 self
3326 }
3327
3328 /// Specify this argument is [required] based on multiple conditions.
3329 ///
3330 /// The conditions are set up in a `(arg, val)` style tuple. The requirement will only become
3331 /// valid if one of the specified `arg`'s value equals its corresponding `val`.
3332 ///
3333 /// # Examples
3334 ///
3335 /// ```rust
3336 /// # use clap_builder as clap;
3337 /// # use clap::Arg;
3338 /// Arg::new("config")
3339 /// .required_if_eq_any([
3340 /// ("extra", "val"),
3341 /// ("option", "spec")
3342 /// ])
3343 /// # ;
3344 /// ```
3345 ///
3346 /// Setting `Arg::required_if_eq_any([(arg, val)])` makes this arg required if any of the `arg`s
3347 /// are used at runtime and it's corresponding value is equal to `val`. If the `arg`'s value is
3348 /// anything other than `val`, this argument isn't required.
3349 ///
3350 /// ```rust
3351 /// # use clap_builder as clap;
3352 /// # use clap::{Command, Arg, ArgAction};
3353 /// let res = Command::new("prog")
3354 /// .arg(Arg::new("cfg")
3355 /// .required_if_eq_any([
3356 /// ("extra", "val"),
3357 /// ("option", "spec")
3358 /// ])
3359 /// .action(ArgAction::Set)
3360 /// .long("config"))
3361 /// .arg(Arg::new("extra")
3362 /// .action(ArgAction::Set)
3363 /// .long("extra"))
3364 /// .arg(Arg::new("option")
3365 /// .action(ArgAction::Set)
3366 /// .long("option"))
3367 /// .try_get_matches_from(vec![
3368 /// "prog", "--option", "other"
3369 /// ]);
3370 ///
3371 /// assert!(res.is_ok()); // We didn't use --option=spec, or --extra=val so "cfg" isn't required
3372 /// ```
3373 ///
3374 /// Setting `Arg::required_if_eq_any([(arg, val)])` and having any of the `arg`s used with its
3375 /// value of `val` but *not* using this arg is an error.
3376 ///
3377 /// ```rust
3378 /// # use clap_builder as clap;
3379 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
3380 /// let res = Command::new("prog")
3381 /// .arg(Arg::new("cfg")
3382 /// .required_if_eq_any([
3383 /// ("extra", "val"),
3384 /// ("option", "spec")
3385 /// ])
3386 /// .action(ArgAction::Set)
3387 /// .long("config"))
3388 /// .arg(Arg::new("extra")
3389 /// .action(ArgAction::Set)
3390 /// .long("extra"))
3391 /// .arg(Arg::new("option")
3392 /// .action(ArgAction::Set)
3393 /// .long("option"))
3394 /// .try_get_matches_from(vec![
3395 /// "prog", "--option", "spec"
3396 /// ]);
3397 ///
3398 /// assert!(res.is_err());
3399 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3400 /// ```
3401 /// [`Arg::requires(name)`]: Arg::requires()
3402 /// [Conflicting]: Arg::conflicts_with()
3403 /// [required]: Arg::required()
3404 #[must_use]
3405 pub fn required_if_eq_any(
3406 mut self,
3407 ifs: impl IntoIterator<Item = (impl Into<Id>, impl Into<OsStr>)>,
3408 ) -> Self {
3409 self.r_ifs
3410 .extend(ifs.into_iter().map(|(id, val)| (id.into(), val.into())));
3411 self
3412 }
3413
3414 /// Specify this argument is [required] based on multiple conditions.
3415 ///
3416 /// The conditions are set up in a `(arg, val)` style tuple. The requirement will only become
3417 /// valid if every one of the specified `arg`'s value equals its corresponding `val`.
3418 ///
3419 /// # Examples
3420 ///
3421 /// ```rust
3422 /// # use clap_builder as clap;
3423 /// # use clap::Arg;
3424 /// Arg::new("config")
3425 /// .required_if_eq_all([
3426 /// ("extra", "val"),
3427 /// ("option", "spec")
3428 /// ])
3429 /// # ;
3430 /// ```
3431 ///
3432 /// Setting `Arg::required_if_eq_all([(arg, val)])` makes this arg required if all of the `arg`s
3433 /// are used at runtime and every value is equal to its corresponding `val`. If the `arg`'s value is
3434 /// anything other than `val`, this argument isn't required.
3435 ///
3436 /// ```rust
3437 /// # use clap_builder as clap;
3438 /// # use clap::{Command, Arg, ArgAction};
3439 /// let res = Command::new("prog")
3440 /// .arg(Arg::new("cfg")
3441 /// .required_if_eq_all([
3442 /// ("extra", "val"),
3443 /// ("option", "spec")
3444 /// ])
3445 /// .action(ArgAction::Set)
3446 /// .long("config"))
3447 /// .arg(Arg::new("extra")
3448 /// .action(ArgAction::Set)
3449 /// .long("extra"))
3450 /// .arg(Arg::new("option")
3451 /// .action(ArgAction::Set)
3452 /// .long("option"))
3453 /// .try_get_matches_from(vec![
3454 /// "prog", "--option", "spec"
3455 /// ]);
3456 ///
3457 /// assert!(res.is_ok()); // We didn't use --option=spec --extra=val so "cfg" isn't required
3458 /// ```
3459 ///
3460 /// Setting `Arg::required_if_eq_all([(arg, val)])` and having all of the `arg`s used with its
3461 /// value of `val` but *not* using this arg is an error.
3462 ///
3463 /// ```rust
3464 /// # use clap_builder as clap;
3465 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
3466 /// let res = Command::new("prog")
3467 /// .arg(Arg::new("cfg")
3468 /// .required_if_eq_all([
3469 /// ("extra", "val"),
3470 /// ("option", "spec")
3471 /// ])
3472 /// .action(ArgAction::Set)
3473 /// .long("config"))
3474 /// .arg(Arg::new("extra")
3475 /// .action(ArgAction::Set)
3476 /// .long("extra"))
3477 /// .arg(Arg::new("option")
3478 /// .action(ArgAction::Set)
3479 /// .long("option"))
3480 /// .try_get_matches_from(vec![
3481 /// "prog", "--extra", "val", "--option", "spec"
3482 /// ]);
3483 ///
3484 /// assert!(res.is_err());
3485 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3486 /// ```
3487 /// [required]: Arg::required()
3488 #[must_use]
3489 pub fn required_if_eq_all(
3490 mut self,
3491 ifs: impl IntoIterator<Item = (impl Into<Id>, impl Into<OsStr>)>,
3492 ) -> Self {
3493 self.r_ifs_all
3494 .extend(ifs.into_iter().map(|(id, val)| (id.into(), val.into())));
3495 self
3496 }
3497
3498 /// Require another argument if this arg matches the [`ArgPredicate`]
3499 ///
3500 /// This method takes `value, another_arg` pair. At runtime, clap will check
3501 /// if this arg (`self`) matches the [`ArgPredicate`].
3502 /// If it does, `another_arg` will be marked as required.
3503 ///
3504 /// # Examples
3505 ///
3506 /// ```rust
3507 /// # use clap_builder as clap;
3508 /// # use clap::Arg;
3509 /// Arg::new("config")
3510 /// .requires_if("val", "arg")
3511 /// # ;
3512 /// ```
3513 ///
3514 /// Setting `Arg::requires_if(val, arg)` requires that the `arg` be used at runtime if the
3515 /// defining argument's value is equal to `val`. If the defining argument is anything other than
3516 /// `val`, the other argument isn't required.
3517 ///
3518 /// ```rust
3519 /// # use clap_builder as clap;
3520 /// # use clap::{Command, Arg, ArgAction};
3521 /// let res = Command::new("prog")
3522 /// .arg(Arg::new("cfg")
3523 /// .action(ArgAction::Set)
3524 /// .requires_if("my.cfg", "other")
3525 /// .long("config"))
3526 /// .arg(Arg::new("other"))
3527 /// .try_get_matches_from(vec![
3528 /// "prog", "--config", "some.cfg"
3529 /// ]);
3530 ///
3531 /// assert!(res.is_ok()); // We didn't use --config=my.cfg, so other wasn't required
3532 /// ```
3533 ///
3534 /// Setting `Arg::requires_if(val, arg)` and setting the value to `val` but *not* supplying
3535 /// `arg` is an error.
3536 ///
3537 /// ```rust
3538 /// # use clap_builder as clap;
3539 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
3540 /// let res = Command::new("prog")
3541 /// .arg(Arg::new("cfg")
3542 /// .action(ArgAction::Set)
3543 /// .requires_if("my.cfg", "input")
3544 /// .long("config"))
3545 /// .arg(Arg::new("input"))
3546 /// .try_get_matches_from(vec![
3547 /// "prog", "--config", "my.cfg"
3548 /// ]);
3549 ///
3550 /// assert!(res.is_err());
3551 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3552 /// ```
3553 /// [`Arg::requires(name)`]: Arg::requires()
3554 /// [Conflicting]: Arg::conflicts_with()
3555 /// [override]: Arg::overrides_with()
3556 #[must_use]
3557 pub fn requires_if(mut self, val: impl Into<ArgPredicate>, arg_id: impl Into<Id>) -> Self {
3558 self.requires.push((val.into(), arg_id.into()));
3559 self
3560 }
3561
3562 /// Allows multiple conditional requirements.
3563 ///
3564 /// The requirement will only become valid if this arg's value matches the
3565 /// [`ArgPredicate`].
3566 ///
3567 /// # Examples
3568 ///
3569 /// ```rust
3570 /// # use clap_builder as clap;
3571 /// # use clap::Arg;
3572 /// Arg::new("config")
3573 /// .requires_ifs([
3574 /// ("val", "arg"),
3575 /// ("other_val", "arg2"),
3576 /// ])
3577 /// # ;
3578 /// ```
3579 ///
3580 /// Setting `Arg::requires_ifs(["val", "arg"])` requires that the `arg` be used at runtime if the
3581 /// defining argument's value is equal to `val`. If the defining argument's value is anything other
3582 /// than `val`, `arg` isn't required.
3583 ///
3584 /// ```rust
3585 /// # use clap_builder as clap;
3586 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
3587 /// let res = Command::new("prog")
3588 /// .arg(Arg::new("cfg")
3589 /// .action(ArgAction::Set)
3590 /// .requires_ifs([
3591 /// ("special.conf", "opt"),
3592 /// ("other.conf", "other"),
3593 /// ])
3594 /// .long("config"))
3595 /// .arg(Arg::new("opt")
3596 /// .long("option")
3597 /// .action(ArgAction::Set))
3598 /// .arg(Arg::new("other"))
3599 /// .try_get_matches_from(vec![
3600 /// "prog", "--config", "special.conf"
3601 /// ]);
3602 ///
3603 /// assert!(res.is_err()); // We used --config=special.conf so --option <val> is required
3604 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3605 /// ```
3606 ///
3607 /// Setting `Arg::requires_ifs` with [`ArgPredicate::IsPresent`] and *not* supplying all the
3608 /// arguments is an error.
3609 ///
3610 /// ```rust
3611 /// # use clap_builder as clap;
3612 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction, builder::ArgPredicate};
3613 /// let res = Command::new("prog")
3614 /// .arg(Arg::new("cfg")
3615 /// .action(ArgAction::Set)
3616 /// .requires_ifs([
3617 /// (ArgPredicate::IsPresent, "input"),
3618 /// (ArgPredicate::IsPresent, "output"),
3619 /// ])
3620 /// .long("config"))
3621 /// .arg(Arg::new("input"))
3622 /// .arg(Arg::new("output"))
3623 /// .try_get_matches_from(vec![
3624 /// "prog", "--config", "file.conf", "in.txt"
3625 /// ]);
3626 ///
3627 /// assert!(res.is_err());
3628 /// // We didn't use output
3629 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
3630 /// ```
3631 ///
3632 /// [`Arg::requires(name)`]: Arg::requires()
3633 /// [Conflicting]: Arg::conflicts_with()
3634 /// [override]: Arg::overrides_with()
3635 #[must_use]
3636 pub fn requires_ifs(
3637 mut self,
3638 ifs: impl IntoIterator<Item = (impl Into<ArgPredicate>, impl Into<Id>)>,
3639 ) -> Self {
3640 self.requires
3641 .extend(ifs.into_iter().map(|(val, arg)| (val.into(), arg.into())));
3642 self
3643 }
3644
3645 #[doc(hidden)]
3646 #[cfg_attr(
3647 feature = "deprecated",
3648 deprecated(since = "4.0.0", note = "Replaced with `Arg::requires_ifs`")
3649 )]
3650 pub fn requires_all(self, ids: impl IntoIterator<Item = impl Into<Id>>) -> Self {
3651 self.requires_ifs(ids.into_iter().map(|id| (ArgPredicate::IsPresent, id)))
3652 }
3653
3654 /// This argument is mutually exclusive with the specified argument.
3655 ///
3656 /// **NOTE:** Conflicting rules take precedence over being required by default. Conflict rules
3657 /// only need to be set for one of the two arguments, they do not need to be set for each.
3658 ///
3659 /// **NOTE:** Defining a conflict is two-way, but does *not* need to defined for both arguments
3660 /// (i.e. if A conflicts with B, defining `A.conflicts_with(B)` is sufficient. You do not
3661 /// need to also do `B.conflicts_with(A)`)
3662 ///
3663 /// **NOTE:** [`Arg::conflicts_with_all(names)`] allows specifying an argument which conflicts with more than one argument.
3664 ///
3665 /// **NOTE** [`Arg::exclusive(true)`] allows specifying an argument which conflicts with every other argument.
3666 ///
3667 /// **NOTE:** All arguments implicitly conflict with themselves.
3668 ///
3669 /// # Examples
3670 ///
3671 /// ```rust
3672 /// # use clap_builder as clap;
3673 /// # use clap::Arg;
3674 /// Arg::new("config")
3675 /// .conflicts_with("debug")
3676 /// # ;
3677 /// ```
3678 ///
3679 /// Setting conflicting argument, and having both arguments present at runtime is an error.
3680 ///
3681 /// ```rust
3682 /// # use clap_builder as clap;
3683 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
3684 /// let res = Command::new("prog")
3685 /// .arg(Arg::new("cfg")
3686 /// .action(ArgAction::Set)
3687 /// .conflicts_with("debug")
3688 /// .long("config"))
3689 /// .arg(Arg::new("debug")
3690 /// .long("debug")
3691 /// .action(ArgAction::SetTrue))
3692 /// .try_get_matches_from(vec![
3693 /// "prog", "--debug", "--config", "file.conf"
3694 /// ]);
3695 ///
3696 /// assert!(res.is_err());
3697 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::ArgumentConflict);
3698 /// ```
3699 ///
3700 /// [`Arg::conflicts_with_all(names)`]: Arg::conflicts_with_all()
3701 /// [`Arg::exclusive(true)`]: Arg::exclusive()
3702 #[must_use]
3703 pub fn conflicts_with(mut self, arg_id: impl IntoResettable<Id>) -> Self {
3704 if let Some(arg_id) = arg_id.into_resettable().into_option() {
3705 self.blacklist.push(arg_id);
3706 } else {
3707 self.blacklist.clear();
3708 }
3709 self
3710 }
3711
3712 /// This argument is mutually exclusive with the specified arguments.
3713 ///
3714 /// See [`Arg::conflicts_with`].
3715 ///
3716 /// **NOTE:** Conflicting rules take precedence over being required by default. Conflict rules
3717 /// only need to be set for one of the two arguments, they do not need to be set for each.
3718 ///
3719 /// **NOTE:** Defining a conflict is two-way, but does *not* need to defined for both arguments
3720 /// (i.e. if A conflicts with B, defining `A.conflicts_with(B)` is sufficient. You do not need
3721 /// need to also do `B.conflicts_with(A)`)
3722 ///
3723 /// **NOTE:** [`Arg::exclusive(true)`] allows specifying an argument which conflicts with every other argument.
3724 ///
3725 /// # Examples
3726 ///
3727 /// ```rust
3728 /// # use clap_builder as clap;
3729 /// # use clap::Arg;
3730 /// Arg::new("config")
3731 /// .conflicts_with_all(["debug", "input"])
3732 /// # ;
3733 /// ```
3734 ///
3735 /// Setting conflicting argument, and having any of the arguments present at runtime with a
3736 /// conflicting argument is an error.
3737 ///
3738 /// ```rust
3739 /// # use clap_builder as clap;
3740 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
3741 /// let res = Command::new("prog")
3742 /// .arg(Arg::new("cfg")
3743 /// .action(ArgAction::Set)
3744 /// .conflicts_with_all(["debug", "input"])
3745 /// .long("config"))
3746 /// .arg(Arg::new("debug")
3747 /// .long("debug"))
3748 /// .arg(Arg::new("input"))
3749 /// .try_get_matches_from(vec![
3750 /// "prog", "--config", "file.conf", "file.txt"
3751 /// ]);
3752 ///
3753 /// assert!(res.is_err());
3754 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::ArgumentConflict);
3755 /// ```
3756 /// [`Arg::conflicts_with`]: Arg::conflicts_with()
3757 /// [`Arg::exclusive(true)`]: Arg::exclusive()
3758 #[must_use]
3759 pub fn conflicts_with_all(mut self, names: impl IntoIterator<Item = impl Into<Id>>) -> Self {
3760 self.blacklist.extend(names.into_iter().map(Into::into));
3761 self
3762 }
3763
3764 /// Sets an overridable argument.
3765 ///
3766 /// i.e. this argument and the following argument
3767 /// will override each other in POSIX style (whichever argument was specified at runtime
3768 /// **last** "wins")
3769 ///
3770 /// **NOTE:** When an argument is overridden it is essentially as if it never was used, any
3771 /// conflicts, requirements, etc. are evaluated **after** all "overrides" have been removed
3772 ///
3773 /// **NOTE:** Overriding an argument implies they [conflict][Arg::conflicts_with`].
3774 ///
3775 /// # Examples
3776 ///
3777 /// ```rust
3778 /// # use clap_builder as clap;
3779 /// # use clap::{Command, arg};
3780 /// let m = Command::new("prog")
3781 /// .arg(arg!(-f --flag "some flag")
3782 /// .conflicts_with("debug"))
3783 /// .arg(arg!(-d --debug "other flag"))
3784 /// .arg(arg!(-c --color "third flag")
3785 /// .overrides_with("flag"))
3786 /// .get_matches_from(vec![
3787 /// "prog", "-f", "-d", "-c"]);
3788 /// // ^~~~~~~~~~~~^~~~~ flag is overridden by color
3789 ///
3790 /// assert!(m.get_flag("color"));
3791 /// assert!(m.get_flag("debug")); // even though flag conflicts with debug, it's as if flag
3792 /// // was never used because it was overridden with color
3793 /// assert!(!m.get_flag("flag"));
3794 /// ```
3795 #[must_use]
3796 pub fn overrides_with(mut self, arg_id: impl IntoResettable<Id>) -> Self {
3797 if let Some(arg_id) = arg_id.into_resettable().into_option() {
3798 self.overrides.push(arg_id);
3799 } else {
3800 self.overrides.clear();
3801 }
3802 self
3803 }
3804
3805 /// Sets multiple mutually overridable arguments by name.
3806 ///
3807 /// i.e. this argument and the following argument will override each other in POSIX style
3808 /// (whichever argument was specified at runtime **last** "wins")
3809 ///
3810 /// **NOTE:** When an argument is overridden it is essentially as if it never was used, any
3811 /// conflicts, requirements, etc. are evaluated **after** all "overrides" have been removed
3812 ///
3813 /// **NOTE:** Overriding an argument implies they [conflict][Arg::conflicts_with_all`].
3814 ///
3815 /// # Examples
3816 ///
3817 /// ```rust
3818 /// # use clap_builder as clap;
3819 /// # use clap::{Command, arg};
3820 /// let m = Command::new("prog")
3821 /// .arg(arg!(-f --flag "some flag")
3822 /// .conflicts_with("color"))
3823 /// .arg(arg!(-d --debug "other flag"))
3824 /// .arg(arg!(-c --color "third flag")
3825 /// .overrides_with_all(["flag", "debug"]))
3826 /// .get_matches_from(vec![
3827 /// "prog", "-f", "-d", "-c"]);
3828 /// // ^~~~~~^~~~~~~~~ flag and debug are overridden by color
3829 ///
3830 /// assert!(m.get_flag("color")); // even though flag conflicts with color, it's as if flag
3831 /// // and debug were never used because they were overridden
3832 /// // with color
3833 /// assert!(!m.get_flag("debug"));
3834 /// assert!(!m.get_flag("flag"));
3835 /// ```
3836 #[must_use]
3837 pub fn overrides_with_all(mut self, names: impl IntoIterator<Item = impl Into<Id>>) -> Self {
3838 self.overrides.extend(names.into_iter().map(Into::into));
3839 self
3840 }
3841}
3842
3843/// # Reflection
3844impl Arg {
3845 /// Get the name of the argument
3846 #[inline]
3847 pub fn get_id(&self) -> &Id {
3848 &self.id
3849 }
3850
3851 /// Get the help specified for this argument, if any
3852 #[inline]
3853 pub fn get_help(&self) -> Option<&StyledStr> {
3854 self.help.as_ref()
3855 }
3856
3857 /// Get the long help specified for this argument, if any
3858 ///
3859 /// # Examples
3860 ///
3861 /// ```rust
3862 /// # use clap_builder as clap;
3863 /// # use clap::Arg;
3864 /// let arg = Arg::new("foo").long_help("long help");
3865 /// assert_eq!(Some("long help".to_owned()), arg.get_long_help().map(|s| s.to_string()));
3866 /// ```
3867 ///
3868 #[inline]
3869 pub fn get_long_help(&self) -> Option<&StyledStr> {
3870 self.long_help.as_ref()
3871 }
3872
3873 /// Get the placement within help
3874 #[inline]
3875 pub fn get_display_order(&self) -> usize {
3876 self.disp_ord.unwrap_or(999)
3877 }
3878
3879 /// Get the help heading specified for this argument, if any
3880 #[inline]
3881 pub fn get_help_heading(&self) -> Option<&str> {
3882 self.help_heading
3883 .as_ref()
3884 .map(|s| s.as_deref())
3885 .unwrap_or_default()
3886 }
3887
3888 /// Get the short option name for this argument, if any
3889 #[inline]
3890 pub fn get_short(&self) -> Option<char> {
3891 self.short
3892 }
3893
3894 /// Get visible short aliases for this argument, if any
3895 #[inline]
3896 pub fn get_visible_short_aliases(&self) -> Option<Vec<char>> {
3897 if self.short_aliases.is_empty() {
3898 None
3899 } else {
3900 Some(
3901 self.short_aliases
3902 .iter()
3903 .filter_map(|(c, v)| if *v { Some(c) } else { None })
3904 .copied()
3905 .collect(),
3906 )
3907 }
3908 }
3909
3910 /// Get *all* short aliases for this argument, if any, both visible and hidden.
3911 #[inline]
3912 pub fn get_all_short_aliases(&self) -> Option<Vec<char>> {
3913 if self.short_aliases.is_empty() {
3914 None
3915 } else {
3916 Some(self.short_aliases.iter().map(|(s, _)| s).copied().collect())
3917 }
3918 }
3919
3920 /// Get the short option name and its visible aliases, if any
3921 #[inline]
3922 pub fn get_short_and_visible_aliases(&self) -> Option<Vec<char>> {
3923 let mut shorts = match self.short {
3924 Some(short) => vec![short],
3925 None => return None,
3926 };
3927 if let Some(aliases) = self.get_visible_short_aliases() {
3928 shorts.extend(aliases);
3929 }
3930 Some(shorts)
3931 }
3932
3933 /// Get the long option name for this argument, if any
3934 #[inline]
3935 pub fn get_long(&self) -> Option<&str> {
3936 self.long.as_deref()
3937 }
3938
3939 /// Get visible aliases for this argument, if any
3940 #[inline]
3941 pub fn get_visible_aliases(&self) -> Option<Vec<&str>> {
3942 if self.aliases.is_empty() {
3943 None
3944 } else {
3945 Some(
3946 self.aliases
3947 .iter()
3948 .filter_map(|(s, v)| if *v { Some(s.as_str()) } else { None })
3949 .collect(),
3950 )
3951 }
3952 }
3953
3954 /// Get *all* aliases for this argument, if any, both visible and hidden.
3955 #[inline]
3956 pub fn get_all_aliases(&self) -> Option<Vec<&str>> {
3957 if self.aliases.is_empty() {
3958 None
3959 } else {
3960 Some(self.aliases.iter().map(|(s, _)| s.as_str()).collect())
3961 }
3962 }
3963
3964 /// Get the long option name and its visible aliases, if any
3965 #[inline]
3966 pub fn get_long_and_visible_aliases(&self) -> Option<Vec<&str>> {
3967 let mut longs = match self.get_long() {
3968 Some(long) => vec![long],
3969 None => return None,
3970 };
3971 if let Some(aliases) = self.get_visible_aliases() {
3972 longs.extend(aliases);
3973 }
3974 Some(longs)
3975 }
3976
3977 /// Get hidden aliases for this argument, if any
3978 #[inline]
3979 pub fn get_aliases(&self) -> Option<Vec<&str>> {
3980 if self.aliases.is_empty() {
3981 None
3982 } else {
3983 Some(
3984 self.aliases
3985 .iter()
3986 .filter_map(|(s, v)| if !*v { Some(s.as_str()) } else { None })
3987 .collect(),
3988 )
3989 }
3990 }
3991
3992 /// Get the names of possible values for this argument. Only useful for user
3993 /// facing applications, such as building help messages or man files
3994 pub fn get_possible_values(&self) -> Vec<PossibleValue> {
3995 if !self.is_takes_value_set() {
3996 vec![]
3997 } else {
3998 self.get_value_parser()
3999 .possible_values()
4000 .map(|pvs| pvs.collect())
4001 .unwrap_or_default()
4002 }
4003 }
4004
4005 /// Get the names of values for this argument.
4006 #[inline]
4007 pub fn get_value_names(&self) -> Option<&[Str]> {
4008 if self.val_names.is_empty() {
4009 None
4010 } else {
4011 Some(&self.val_names)
4012 }
4013 }
4014
4015 /// Get the number of values for this argument.
4016 #[inline]
4017 pub fn get_num_args(&self) -> Option<ValueRange> {
4018 self.num_vals
4019 }
4020
4021 #[inline]
4022 pub(crate) fn get_min_vals(&self) -> usize {
4023 self.get_num_args().expect(INTERNAL_ERROR_MSG).min_values()
4024 }
4025
4026 /// Get the delimiter between multiple values
4027 #[inline]
4028 pub fn get_value_delimiter(&self) -> Option<char> {
4029 self.val_delim
4030 }
4031
4032 /// Get the value terminator for this argument. The `value_terminator` is a value
4033 /// that terminates parsing of multi-valued arguments.
4034 #[inline]
4035 pub fn get_value_terminator(&self) -> Option<&Str> {
4036 self.terminator.as_ref()
4037 }
4038
4039 /// Get the index of this argument, if any
4040 #[inline]
4041 pub fn get_index(&self) -> Option<usize> {
4042 self.index
4043 }
4044
4045 /// Get the value hint of this argument
4046 pub fn get_value_hint(&self) -> ValueHint {
4047 // HACK: we should use `Self::add` and `Self::remove` to type-check that `ArgExt` is used
4048 self.ext.get::<ValueHint>().copied().unwrap_or_else(|| {
4049 if self.is_takes_value_set() {
4050 let type_id = self.get_value_parser().type_id();
4051 if type_id == AnyValueId::of::<std::path::PathBuf>() {
4052 ValueHint::AnyPath
4053 } else {
4054 ValueHint::default()
4055 }
4056 } else {
4057 ValueHint::default()
4058 }
4059 })
4060 }
4061
4062 /// Get the environment variable name specified for this argument, if any
4063 ///
4064 /// # Examples
4065 ///
4066 /// ```rust
4067 /// # use clap_builder as clap;
4068 /// # use std::ffi::OsStr;
4069 /// # use clap::Arg;
4070 /// let arg = Arg::new("foo").env("ENVIRONMENT");
4071 /// assert_eq!(arg.get_env(), Some(OsStr::new("ENVIRONMENT")));
4072 /// ```
4073 #[cfg(feature = "env")]
4074 pub fn get_env(&self) -> Option<&std::ffi::OsStr> {
4075 self.env.as_ref().map(|x| x.0.as_os_str())
4076 }
4077
4078 /// Get the default values specified for this argument, if any
4079 ///
4080 /// # Examples
4081 ///
4082 /// ```rust
4083 /// # use clap_builder as clap;
4084 /// # use clap::Arg;
4085 /// let arg = Arg::new("foo").default_value("default value");
4086 /// assert_eq!(arg.get_default_values(), &["default value"]);
4087 /// ```
4088 pub fn get_default_values(&self) -> &[OsStr] {
4089 &self.default_vals
4090 }
4091
4092 /// Checks whether this argument is a positional or not.
4093 ///
4094 /// # Examples
4095 ///
4096 /// ```rust
4097 /// # use clap_builder as clap;
4098 /// # use clap::Arg;
4099 /// let arg = Arg::new("foo");
4100 /// assert_eq!(arg.is_positional(), true);
4101 ///
4102 /// let arg = Arg::new("foo").long("foo");
4103 /// assert_eq!(arg.is_positional(), false);
4104 /// ```
4105 pub fn is_positional(&self) -> bool {
4106 self.get_long().is_none() && self.get_short().is_none()
4107 }
4108
4109 /// Reports whether [`Arg::required`] is set
4110 pub fn is_required_set(&self) -> bool {
4111 self.is_set(ArgSettings::Required)
4112 }
4113
4114 pub(crate) fn is_multiple_values_set(&self) -> bool {
4115 self.get_num_args().unwrap_or_default().is_multiple()
4116 }
4117
4118 pub(crate) fn is_takes_value_set(&self) -> bool {
4119 self.get_num_args()
4120 .unwrap_or_else(|| 1.into())
4121 .takes_values()
4122 }
4123
4124 /// Report whether [`Arg::allow_hyphen_values`] is set
4125 pub fn is_allow_hyphen_values_set(&self) -> bool {
4126 self.is_set(ArgSettings::AllowHyphenValues)
4127 }
4128
4129 /// Report whether [`Arg::allow_negative_numbers`] is set
4130 pub fn is_allow_negative_numbers_set(&self) -> bool {
4131 self.is_set(ArgSettings::AllowNegativeNumbers)
4132 }
4133
4134 /// Behavior when parsing the argument
4135 pub fn get_action(&self) -> &ArgAction {
4136 const DEFAULT: ArgAction = ArgAction::Set;
4137 self.action.as_ref().unwrap_or(&DEFAULT)
4138 }
4139
4140 /// Configured parser for argument values
4141 ///
4142 /// # Example
4143 ///
4144 /// ```rust
4145 /// # use clap_builder as clap;
4146 /// let cmd = clap::Command::new("raw")
4147 /// .arg(
4148 /// clap::Arg::new("port")
4149 /// .value_parser(clap::value_parser!(usize))
4150 /// );
4151 /// let value_parser = cmd.get_arguments()
4152 /// .find(|a| a.get_id() == "port").unwrap()
4153 /// .get_value_parser();
4154 /// println!("{value_parser:?}");
4155 /// ```
4156 pub fn get_value_parser(&self) -> &super::ValueParser {
4157 if let Some(value_parser) = self.value_parser.as_ref() {
4158 value_parser
4159 } else {
4160 static DEFAULT: super::ValueParser = super::ValueParser::string();
4161 &DEFAULT
4162 }
4163 }
4164
4165 /// Report whether [`Arg::global`] is set
4166 pub fn is_global_set(&self) -> bool {
4167 self.is_set(ArgSettings::Global)
4168 }
4169
4170 /// Report whether [`Arg::next_line_help`] is set
4171 pub fn is_next_line_help_set(&self) -> bool {
4172 self.is_set(ArgSettings::NextLineHelp)
4173 }
4174
4175 /// Report whether [`Arg::hide`] is set
4176 pub fn is_hide_set(&self) -> bool {
4177 self.is_set(ArgSettings::Hidden)
4178 }
4179
4180 /// Report whether [`Arg::hide_default_value`] is set
4181 pub fn is_hide_default_value_set(&self) -> bool {
4182 self.is_set(ArgSettings::HideDefaultValue)
4183 }
4184
4185 /// Report whether [`Arg::hide_possible_values`] is set
4186 pub fn is_hide_possible_values_set(&self) -> bool {
4187 self.is_set(ArgSettings::HidePossibleValues)
4188 }
4189
4190 /// Report whether [`Arg::hide_env`] is set
4191 #[cfg(feature = "env")]
4192 pub fn is_hide_env_set(&self) -> bool {
4193 self.is_set(ArgSettings::HideEnv)
4194 }
4195
4196 /// Report whether [`Arg::hide_env_values`] is set
4197 #[cfg(feature = "env")]
4198 pub fn is_hide_env_values_set(&self) -> bool {
4199 self.is_set(ArgSettings::HideEnvValues)
4200 }
4201
4202 /// Report whether [`Arg::hide_short_help`] is set
4203 pub fn is_hide_short_help_set(&self) -> bool {
4204 self.is_set(ArgSettings::HiddenShortHelp)
4205 }
4206
4207 /// Report whether [`Arg::hide_long_help`] is set
4208 pub fn is_hide_long_help_set(&self) -> bool {
4209 self.is_set(ArgSettings::HiddenLongHelp)
4210 }
4211
4212 /// Report whether [`Arg::require_equals`] is set
4213 pub fn is_require_equals_set(&self) -> bool {
4214 self.is_set(ArgSettings::RequireEquals)
4215 }
4216
4217 /// Reports whether [`Arg::exclusive`] is set
4218 pub fn is_exclusive_set(&self) -> bool {
4219 self.is_set(ArgSettings::Exclusive)
4220 }
4221
4222 /// Report whether [`Arg::trailing_var_arg`] is set
4223 pub fn is_trailing_var_arg_set(&self) -> bool {
4224 self.is_set(ArgSettings::TrailingVarArg)
4225 }
4226
4227 /// Reports whether [`Arg::last`] is set
4228 pub fn is_last_set(&self) -> bool {
4229 self.is_set(ArgSettings::Last)
4230 }
4231
4232 /// Reports whether [`Arg::ignore_case`] is set
4233 pub fn is_ignore_case_set(&self) -> bool {
4234 self.is_set(ArgSettings::IgnoreCase)
4235 }
4236
4237 /// Access an [`ArgExt`]
4238 #[cfg(feature = "unstable-ext")]
4239 pub fn get<T: ArgExt + Extension>(&self) -> Option<&T> {
4240 self.ext.get::<T>()
4241 }
4242
4243 /// Remove an [`ArgExt`]
4244 #[cfg(feature = "unstable-ext")]
4245 pub fn remove<T: ArgExt + Extension>(mut self) -> Option<T> {
4246 self.ext.remove::<T>()
4247 }
4248}
4249
4250/// # Internally used only
4251impl Arg {
4252 pub(crate) fn _build(&mut self) {
4253 if self.action.is_none() {
4254 if self.num_vals == Some(ValueRange::EMPTY) {
4255 let action = ArgAction::SetTrue;
4256 self.action = Some(action);
4257 } else {
4258 let action =
4259 if self.is_positional() && self.num_vals.unwrap_or_default().is_unbounded() {
4260 // Allow collecting arguments interleaved with flags
4261 //
4262 // Bounded values are probably a group and the user should explicitly opt-in to
4263 // Append
4264 ArgAction::Append
4265 } else {
4266 ArgAction::Set
4267 };
4268 self.action = Some(action);
4269 }
4270 }
4271 if let Some(action) = self.action.as_ref() {
4272 if let Some(default_value) = action.default_value() {
4273 if self.default_vals.is_empty() {
4274 self.default_vals = vec![default_value.into()];
4275 }
4276 }
4277 if let Some(default_value) = action.default_missing_value() {
4278 if self.default_missing_vals.is_empty() {
4279 self.default_missing_vals = vec![default_value.into()];
4280 }
4281 }
4282 }
4283
4284 if self.value_parser.is_none() {
4285 if let Some(default) = self.action.as_ref().and_then(|a| a.default_value_parser()) {
4286 self.value_parser = Some(default);
4287 } else {
4288 self.value_parser = Some(super::ValueParser::string());
4289 }
4290 }
4291
4292 let val_names_len = self.val_names.len();
4293 if val_names_len > 1 {
4294 self.num_vals.get_or_insert(val_names_len.into());
4295 } else {
4296 let nargs = if self.get_action().takes_values() {
4297 ValueRange::SINGLE
4298 } else {
4299 ValueRange::EMPTY
4300 };
4301 self.num_vals.get_or_insert(nargs);
4302 }
4303 }
4304
4305 // Used for positionals when printing
4306 pub(crate) fn name_no_brackets(&self) -> String {
4307 debug!("Arg::name_no_brackets:{}", self.get_id());
4308 let delim = " ";
4309 if !self.val_names.is_empty() {
4310 debug!("Arg::name_no_brackets: val_names={:#?}", self.val_names);
4311
4312 if self.val_names.len() > 1 {
4313 self.val_names
4314 .iter()
4315 .map(|n| format!("<{n}>"))
4316 .collect::<Vec<_>>()
4317 .join(delim)
4318 } else {
4319 self.val_names
4320 .first()
4321 .expect(INTERNAL_ERROR_MSG)
4322 .as_str()
4323 .to_owned()
4324 }
4325 } else {
4326 debug!("Arg::name_no_brackets: just name");
4327 self.get_id().as_str().to_owned()
4328 }
4329 }
4330
4331 pub(crate) fn stylized(&self, styles: &Styles, required: Option<bool>) -> StyledStr {
4332 use std::fmt::Write as _;
4333 let literal = styles.get_literal();
4334
4335 let mut styled = StyledStr::new();
4336 // Write the name such --long or -l
4337 if let Some(l) = self.get_long() {
4338 let _ = write!(styled, "{literal}--{l}{literal:#}",);
4339 } else if let Some(s) = self.get_short() {
4340 let _ = write!(styled, "{literal}-{s}{literal:#}");
4341 }
4342 styled.push_styled(&self.stylize_arg_suffix(styles, required));
4343 styled
4344 }
4345
4346 pub(crate) fn stylize_arg_suffix(&self, styles: &Styles, required: Option<bool>) -> StyledStr {
4347 use std::fmt::Write as _;
4348 let literal = styles.get_literal();
4349 let placeholder = styles.get_placeholder();
4350 let mut styled = StyledStr::new();
4351
4352 let mut need_closing_bracket = false;
4353 if self.is_takes_value_set() && !self.is_positional() {
4354 let is_optional_val = self.get_min_vals() == 0;
4355 let (style, start) = if self.is_require_equals_set() {
4356 if is_optional_val {
4357 need_closing_bracket = true;
4358 (placeholder, "[=")
4359 } else {
4360 (literal, "=")
4361 }
4362 } else if is_optional_val {
4363 need_closing_bracket = true;
4364 (placeholder, " [")
4365 } else {
4366 (placeholder, " ")
4367 };
4368 let _ = write!(styled, "{style}{start}{style:#}");
4369 }
4370 if self.is_takes_value_set() || self.is_positional() {
4371 let required = required.unwrap_or_else(|| self.is_required_set());
4372 let arg_val = self.render_arg_val(required);
4373 let _ = write!(styled, "{placeholder}{arg_val}{placeholder:#}",);
4374 } else if matches!(*self.get_action(), ArgAction::Count) {
4375 let _ = write!(styled, "{placeholder}...{placeholder:#}",);
4376 }
4377 if need_closing_bracket {
4378 let _ = write!(styled, "{placeholder}]{placeholder:#}",);
4379 }
4380
4381 styled
4382 }
4383
4384 /// Write the values such as `<name1> <name2>`
4385 fn render_arg_val(&self, required: bool) -> String {
4386 let mut rendered = String::new();
4387
4388 let num_vals = self.get_num_args().unwrap_or_else(|| 1.into());
4389
4390 let mut val_names = if self.val_names.is_empty() {
4391 vec![self.id.as_internal_str().to_owned()]
4392 } else {
4393 self.val_names.clone()
4394 };
4395 if val_names.len() == 1 {
4396 let min = num_vals.min_values().max(1);
4397 let val_name = val_names.pop().unwrap();
4398 val_names = vec![val_name; min];
4399 }
4400
4401 debug_assert!(self.is_takes_value_set());
4402 for (n, val_name) in val_names.iter().enumerate() {
4403 let arg_name = if self.is_positional() && (num_vals.min_values() == 0 || !required) {
4404 format!("[{val_name}]")
4405 } else {
4406 format!("<{val_name}>")
4407 };
4408
4409 if n != 0 {
4410 rendered.push(' ');
4411 }
4412 rendered.push_str(&arg_name);
4413 }
4414
4415 let mut extra_values = false;
4416 extra_values |= val_names.len() < num_vals.max_values();
4417 if self.is_positional() && matches!(*self.get_action(), ArgAction::Append) {
4418 extra_values = true;
4419 }
4420 if extra_values {
4421 rendered.push_str("...");
4422 }
4423
4424 rendered
4425 }
4426
4427 /// Either multiple values or occurrences
4428 pub(crate) fn is_multiple(&self) -> bool {
4429 self.is_multiple_values_set() || matches!(*self.get_action(), ArgAction::Append)
4430 }
4431}
4432
4433impl From<&'_ Arg> for Arg {
4434 fn from(a: &Arg) -> Self {
4435 a.clone()
4436 }
4437}
4438
4439impl PartialEq for Arg {
4440 fn eq(&self, other: &Arg) -> bool {
4441 self.get_id() == other.get_id()
4442 }
4443}
4444
4445impl PartialOrd for Arg {
4446 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
4447 Some(self.cmp(other))
4448 }
4449}
4450
4451impl Ord for Arg {
4452 fn cmp(&self, other: &Arg) -> Ordering {
4453 self.get_id().cmp(other.get_id())
4454 }
4455}
4456
4457impl Eq for Arg {}
4458
4459impl Display for Arg {
4460 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
4461 let plain = Styles::plain();
4462 self.stylized(&plain, None).fmt(f)
4463 }
4464}
4465
4466impl fmt::Debug for Arg {
4467 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
4468 let mut ds = f.debug_struct("Arg");
4469
4470 #[allow(unused_mut)]
4471 let mut ds = ds
4472 .field("id", &self.id)
4473 .field("help", &self.help)
4474 .field("long_help", &self.long_help)
4475 .field("action", &self.action)
4476 .field("value_parser", &self.value_parser)
4477 .field("blacklist", &self.blacklist)
4478 .field("settings", &self.settings)
4479 .field("overrides", &self.overrides)
4480 .field("groups", &self.groups)
4481 .field("requires", &self.requires)
4482 .field("r_ifs", &self.r_ifs)
4483 .field("r_unless", &self.r_unless)
4484 .field("short", &self.short)
4485 .field("long", &self.long)
4486 .field("aliases", &self.aliases)
4487 .field("short_aliases", &self.short_aliases)
4488 .field("disp_ord", &self.disp_ord)
4489 .field("val_names", &self.val_names)
4490 .field("num_vals", &self.num_vals)
4491 .field("val_delim", &self.val_delim)
4492 .field("default_vals", &self.default_vals)
4493 .field("default_vals_ifs", &self.default_vals_ifs)
4494 .field("terminator", &self.terminator)
4495 .field("index", &self.index)
4496 .field("help_heading", &self.help_heading)
4497 .field("default_missing_vals", &self.default_missing_vals)
4498 .field("ext", &self.ext);
4499
4500 #[cfg(feature = "env")]
4501 {
4502 ds = ds.field("env", &self.env);
4503 }
4504
4505 ds.finish()
4506 }
4507}
4508
4509/// User-provided data that can be attached to an [`Arg`]
4510#[cfg(feature = "unstable-ext")]
4511pub trait ArgExt: Extension {}
4512
4513// Flags
4514#[cfg(test)]
4515mod test {
4516 use super::Arg;
4517 use super::ArgAction;
4518
4519 #[test]
4520 fn flag_display_long() {
4521 let mut f = Arg::new("flg").long("flag").action(ArgAction::SetTrue);
4522 f._build();
4523
4524 assert_eq!(f.to_string(), "--flag");
4525 }
4526
4527 #[test]
4528 fn flag_display_short() {
4529 let mut f2 = Arg::new("flg").short('f').action(ArgAction::SetTrue);
4530 f2._build();
4531
4532 assert_eq!(f2.to_string(), "-f");
4533 }
4534
4535 #[test]
4536 fn flag_display_count() {
4537 let mut f2 = Arg::new("flg").long("flag").action(ArgAction::Count);
4538 f2._build();
4539
4540 assert_eq!(f2.to_string(), "--flag...");
4541 }
4542
4543 #[test]
4544 fn flag_display_single_alias() {
4545 let mut f = Arg::new("flg")
4546 .long("flag")
4547 .visible_alias("als")
4548 .action(ArgAction::SetTrue);
4549 f._build();
4550
4551 assert_eq!(f.to_string(), "--flag");
4552 }
4553
4554 #[test]
4555 fn flag_display_multiple_aliases() {
4556 let mut f = Arg::new("flg").short('f').action(ArgAction::SetTrue);
4557 f.aliases = vec![
4558 ("alias_not_visible".into(), false),
4559 ("f2".into(), true),
4560 ("f3".into(), true),
4561 ("f4".into(), true),
4562 ];
4563 f._build();
4564
4565 assert_eq!(f.to_string(), "-f");
4566 }
4567
4568 #[test]
4569 fn flag_display_single_short_alias() {
4570 let mut f = Arg::new("flg").short('a').action(ArgAction::SetTrue);
4571 f.short_aliases = vec![('b', true)];
4572 f._build();
4573
4574 assert_eq!(f.to_string(), "-a");
4575 }
4576
4577 #[test]
4578 fn flag_display_multiple_short_aliases() {
4579 let mut f = Arg::new("flg").short('a').action(ArgAction::SetTrue);
4580 f.short_aliases = vec![('b', false), ('c', true), ('d', true), ('e', true)];
4581 f._build();
4582
4583 assert_eq!(f.to_string(), "-a");
4584 }
4585
4586 // Options
4587
4588 #[test]
4589 fn option_display_multiple_occurrences() {
4590 let mut o = Arg::new("opt").long("option").action(ArgAction::Append);
4591 o._build();
4592
4593 assert_eq!(o.to_string(), "--option <opt>");
4594 }
4595
4596 #[test]
4597 fn option_display_multiple_values() {
4598 let mut o = Arg::new("opt")
4599 .long("option")
4600 .action(ArgAction::Set)
4601 .num_args(1..);
4602 o._build();
4603
4604 assert_eq!(o.to_string(), "--option <opt>...");
4605 }
4606
4607 #[test]
4608 fn option_display_zero_or_more_values() {
4609 let mut o = Arg::new("opt")
4610 .long("option")
4611 .action(ArgAction::Set)
4612 .num_args(0..);
4613 o._build();
4614
4615 assert_eq!(o.to_string(), "--option [<opt>...]");
4616 }
4617
4618 #[test]
4619 fn option_display_one_or_more_values() {
4620 let mut o = Arg::new("opt")
4621 .long("option")
4622 .action(ArgAction::Set)
4623 .num_args(1..);
4624 o._build();
4625
4626 assert_eq!(o.to_string(), "--option <opt>...");
4627 }
4628
4629 #[test]
4630 fn option_display_zero_or_more_values_with_value_name() {
4631 let mut o = Arg::new("opt")
4632 .short('o')
4633 .action(ArgAction::Set)
4634 .num_args(0..)
4635 .value_names(["file"]);
4636 o._build();
4637
4638 assert_eq!(o.to_string(), "-o [<file>...]");
4639 }
4640
4641 #[test]
4642 fn option_display_one_or_more_values_with_value_name() {
4643 let mut o = Arg::new("opt")
4644 .short('o')
4645 .action(ArgAction::Set)
4646 .num_args(1..)
4647 .value_names(["file"]);
4648 o._build();
4649
4650 assert_eq!(o.to_string(), "-o <file>...");
4651 }
4652
4653 #[test]
4654 fn option_display_optional_value() {
4655 let mut o = Arg::new("opt")
4656 .long("option")
4657 .action(ArgAction::Set)
4658 .num_args(0..=1);
4659 o._build();
4660
4661 assert_eq!(o.to_string(), "--option [<opt>]");
4662 }
4663
4664 #[test]
4665 fn option_display_value_names() {
4666 let mut o = Arg::new("opt")
4667 .short('o')
4668 .action(ArgAction::Set)
4669 .value_names(["file", "name"]);
4670 o._build();
4671
4672 assert_eq!(o.to_string(), "-o <file> <name>");
4673 }
4674
4675 #[test]
4676 fn option_display3() {
4677 let mut o = Arg::new("opt")
4678 .short('o')
4679 .num_args(1..)
4680 .action(ArgAction::Set)
4681 .value_names(["file", "name"]);
4682 o._build();
4683
4684 assert_eq!(o.to_string(), "-o <file> <name>...");
4685 }
4686
4687 #[test]
4688 fn option_display_single_alias() {
4689 let mut o = Arg::new("opt")
4690 .long("option")
4691 .action(ArgAction::Set)
4692 .visible_alias("als");
4693 o._build();
4694
4695 assert_eq!(o.to_string(), "--option <opt>");
4696 }
4697
4698 #[test]
4699 fn option_display_multiple_aliases() {
4700 let mut o = Arg::new("opt")
4701 .long("option")
4702 .action(ArgAction::Set)
4703 .visible_aliases(["als2", "als3", "als4"])
4704 .alias("als_not_visible");
4705 o._build();
4706
4707 assert_eq!(o.to_string(), "--option <opt>");
4708 }
4709
4710 #[test]
4711 fn option_display_single_short_alias() {
4712 let mut o = Arg::new("opt")
4713 .short('a')
4714 .action(ArgAction::Set)
4715 .visible_short_alias('b');
4716 o._build();
4717
4718 assert_eq!(o.to_string(), "-a <opt>");
4719 }
4720
4721 #[test]
4722 fn option_display_multiple_short_aliases() {
4723 let mut o = Arg::new("opt")
4724 .short('a')
4725 .action(ArgAction::Set)
4726 .visible_short_aliases(['b', 'c', 'd'])
4727 .short_alias('e');
4728 o._build();
4729
4730 assert_eq!(o.to_string(), "-a <opt>");
4731 }
4732
4733 // Positionals
4734
4735 #[test]
4736 fn positional_display_multiple_values() {
4737 let mut p = Arg::new("pos").index(1).num_args(1..);
4738 p._build();
4739
4740 assert_eq!(p.to_string(), "[pos]...");
4741 }
4742
4743 #[test]
4744 fn positional_display_multiple_values_required() {
4745 let mut p = Arg::new("pos").index(1).num_args(1..).required(true);
4746 p._build();
4747
4748 assert_eq!(p.to_string(), "<pos>...");
4749 }
4750
4751 #[test]
4752 fn positional_display_zero_or_more_values() {
4753 let mut p = Arg::new("pos").index(1).num_args(0..);
4754 p._build();
4755
4756 assert_eq!(p.to_string(), "[pos]...");
4757 }
4758
4759 #[test]
4760 fn positional_display_one_or_more_values() {
4761 let mut p = Arg::new("pos").index(1).num_args(1..);
4762 p._build();
4763
4764 assert_eq!(p.to_string(), "[pos]...");
4765 }
4766
4767 #[test]
4768 fn positional_display_one_or_more_values_required() {
4769 let mut p = Arg::new("pos").index(1).num_args(1..).required(true);
4770 p._build();
4771
4772 assert_eq!(p.to_string(), "<pos>...");
4773 }
4774
4775 #[test]
4776 fn positional_display_optional_value() {
4777 let mut p = Arg::new("pos")
4778 .index(1)
4779 .num_args(0..=1)
4780 .action(ArgAction::Set);
4781 p._build();
4782
4783 assert_eq!(p.to_string(), "[pos]");
4784 }
4785
4786 #[test]
4787 fn positional_display_multiple_occurrences() {
4788 let mut p = Arg::new("pos").index(1).action(ArgAction::Append);
4789 p._build();
4790
4791 assert_eq!(p.to_string(), "[pos]...");
4792 }
4793
4794 #[test]
4795 fn positional_display_multiple_occurrences_required() {
4796 let mut p = Arg::new("pos")
4797 .index(1)
4798 .action(ArgAction::Append)
4799 .required(true);
4800 p._build();
4801
4802 assert_eq!(p.to_string(), "<pos>...");
4803 }
4804
4805 #[test]
4806 fn positional_display_required() {
4807 let mut p = Arg::new("pos").index(1).required(true);
4808 p._build();
4809
4810 assert_eq!(p.to_string(), "<pos>");
4811 }
4812
4813 #[test]
4814 fn positional_display_val_names() {
4815 let mut p = Arg::new("pos").index(1).value_names(["file1", "file2"]);
4816 p._build();
4817
4818 assert_eq!(p.to_string(), "[file1] [file2]");
4819 }
4820
4821 #[test]
4822 fn positional_display_val_names_required() {
4823 let mut p = Arg::new("pos")
4824 .index(1)
4825 .value_names(["file1", "file2"])
4826 .required(true);
4827 p._build();
4828
4829 assert_eq!(p.to_string(), "<file1> <file2>");
4830 }
4831}