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