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 alphabetical order. 2115 /// 2116 /// **NOTE:** The default is 999 for all arguments. 2117 /// 2118 /// **NOTE:** This setting is ignored for [positional arguments] which are always displayed in 2119 /// [index] order. 2120 /// 2121 /// # Examples 2122 /// 2123 #[cfg_attr(not(feature = "help"), doc = " ```ignore")] 2124 #[cfg_attr(feature = "help", doc = " ```")] 2125 /// # use clap::{Command, Arg, ArgAction}; 2126 /// let m = Command::new("prog") 2127 /// .arg(Arg::new("a") // Typically args are grouped alphabetically by name. 2128 /// // Args without a display_order have a value of 999 and are 2129 /// // displayed alphabetically with all other 999 valued args. 2130 /// .long("long-option") 2131 /// .short('o') 2132 /// .action(ArgAction::Set) 2133 /// .help("Some help and text")) 2134 /// .arg(Arg::new("b") 2135 /// .long("other-option") 2136 /// .short('O') 2137 /// .action(ArgAction::Set) 2138 /// .display_order(1) // In order to force this arg to appear *first* 2139 /// // all we have to do is give it a value lower than 999. 2140 /// // Any other args with a value of 1 will be displayed 2141 /// // alphabetically with this one...then 2 values, then 3, etc. 2142 /// .help("I should be first!")) 2143 /// .get_matches_from(vec![ 2144 /// "prog", "--help" 2145 /// ]); 2146 /// ``` 2147 /// 2148 /// The above example displays the following help message 2149 /// 2150 /// ```text 2151 /// cust-ord 2152 /// 2153 /// Usage: cust-ord [OPTIONS] 2154 /// 2155 /// Options: 2156 /// -h, --help Print help information 2157 /// -V, --version Print version information 2158 /// -O, --other-option <b> I should be first! 2159 /// -o, --long-option <a> Some help and text 2160 /// ``` 2161 /// [positional arguments]: Arg::index() 2162 /// [index]: Arg::index() 2163 #[inline] 2164 #[must_use] display_order(mut self, ord: impl IntoResettable<usize>) -> Self2165 pub fn display_order(mut self, ord: impl IntoResettable<usize>) -> Self { 2166 self.disp_ord = ord.into_resettable().into_option(); 2167 self 2168 } 2169 2170 /// Override the [current] help section. 2171 /// 2172 /// [current]: crate::Command::next_help_heading 2173 #[inline] 2174 #[must_use] help_heading(mut self, heading: impl IntoResettable<Str>) -> Self2175 pub fn help_heading(mut self, heading: impl IntoResettable<Str>) -> Self { 2176 self.help_heading = Some(heading.into_resettable().into_option()); 2177 self 2178 } 2179 2180 /// Render the [help][Arg::help] on the line after the argument. 2181 /// 2182 /// This can be helpful for arguments with very long or complex help messages. 2183 /// This can also be helpful for arguments with very long flag names, or many/long value names. 2184 /// 2185 /// **NOTE:** To apply this setting to all arguments and subcommands, consider using 2186 /// [`crate::Command::next_line_help`] 2187 /// 2188 /// # Examples 2189 /// 2190 #[cfg_attr(not(feature = "help"), doc = " ```ignore")] 2191 #[cfg_attr(feature = "help", doc = " ```")] 2192 /// # use clap::{Command, Arg, ArgAction}; 2193 /// let m = Command::new("prog") 2194 /// .arg(Arg::new("opt") 2195 /// .long("long-option-flag") 2196 /// .short('o') 2197 /// .action(ArgAction::Set) 2198 /// .next_line_help(true) 2199 /// .value_names(["value1", "value2"]) 2200 /// .help("Some really long help and complex\n\ 2201 /// help that makes more sense to be\n\ 2202 /// on a line after the option")) 2203 /// .get_matches_from(vec![ 2204 /// "prog", "--help" 2205 /// ]); 2206 /// ``` 2207 /// 2208 /// The above example displays the following help message 2209 /// 2210 /// ```text 2211 /// nlh 2212 /// 2213 /// Usage: nlh [OPTIONS] 2214 /// 2215 /// Options: 2216 /// -h, --help Print help information 2217 /// -V, --version Print version information 2218 /// -o, --long-option-flag <value1> <value2> 2219 /// Some really long help and complex 2220 /// help that makes more sense to be 2221 /// on a line after the option 2222 /// ``` 2223 #[inline] 2224 #[must_use] next_line_help(self, yes: bool) -> Self2225 pub fn next_line_help(self, yes: bool) -> Self { 2226 if yes { 2227 self.setting(ArgSettings::NextLineHelp) 2228 } else { 2229 self.unset_setting(ArgSettings::NextLineHelp) 2230 } 2231 } 2232 2233 /// Do not display the argument in help message. 2234 /// 2235 /// **NOTE:** This does **not** hide the argument from usage strings on error 2236 /// 2237 /// # Examples 2238 /// 2239 /// Setting `Hidden` will hide the argument when displaying help text 2240 /// 2241 #[cfg_attr(not(feature = "help"), doc = " ```ignore")] 2242 #[cfg_attr(feature = "help", doc = " ```")] 2243 /// # use clap::{Command, Arg}; 2244 /// let m = Command::new("prog") 2245 /// .arg(Arg::new("cfg") 2246 /// .long("config") 2247 /// .hide(true) 2248 /// .help("Some help text describing the --config arg")) 2249 /// .get_matches_from(vec![ 2250 /// "prog", "--help" 2251 /// ]); 2252 /// ``` 2253 /// 2254 /// The above example displays 2255 /// 2256 /// ```text 2257 /// helptest 2258 /// 2259 /// Usage: helptest [OPTIONS] 2260 /// 2261 /// Options: 2262 /// -h, --help Print help information 2263 /// -V, --version Print version information 2264 /// ``` 2265 #[inline] 2266 #[must_use] hide(self, yes: bool) -> Self2267 pub fn hide(self, yes: bool) -> Self { 2268 if yes { 2269 self.setting(ArgSettings::Hidden) 2270 } else { 2271 self.unset_setting(ArgSettings::Hidden) 2272 } 2273 } 2274 2275 /// Do not display the [possible values][crate::builder::ValueParser::possible_values] in the help message. 2276 /// 2277 /// This is useful for args with many values, or ones which are explained elsewhere in the 2278 /// help text. 2279 /// 2280 /// **NOTE:** Setting this requires [taking values][Arg::num_args] 2281 /// 2282 /// To set this for all arguments, see 2283 /// [`Command::hide_possible_values`][crate::Command::hide_possible_values]. 2284 /// 2285 /// # Examples 2286 /// 2287 /// ```rust 2288 /// # use clap::{Command, Arg, ArgAction}; 2289 /// let m = Command::new("prog") 2290 /// .arg(Arg::new("mode") 2291 /// .long("mode") 2292 /// .value_parser(["fast", "slow"]) 2293 /// .action(ArgAction::Set) 2294 /// .hide_possible_values(true)); 2295 /// ``` 2296 /// If we were to run the above program with `--help` the `[values: fast, slow]` portion of 2297 /// the help text would be omitted. 2298 #[inline] 2299 #[must_use] hide_possible_values(self, yes: bool) -> Self2300 pub fn hide_possible_values(self, yes: bool) -> Self { 2301 if yes { 2302 self.setting(ArgSettings::HidePossibleValues) 2303 } else { 2304 self.unset_setting(ArgSettings::HidePossibleValues) 2305 } 2306 } 2307 2308 /// Do not display the default value of the argument in the help message. 2309 /// 2310 /// This is useful when default behavior of an arg is explained elsewhere in the help text. 2311 /// 2312 /// **NOTE:** Setting this requires [taking values][Arg::num_args] 2313 /// 2314 /// # Examples 2315 /// 2316 /// ```rust 2317 /// # use clap::{Command, Arg, ArgAction}; 2318 /// let m = Command::new("connect") 2319 /// .arg(Arg::new("host") 2320 /// .long("host") 2321 /// .default_value("localhost") 2322 /// .action(ArgAction::Set) 2323 /// .hide_default_value(true)); 2324 /// 2325 /// ``` 2326 /// 2327 /// If we were to run the above program with `--help` the `[default: localhost]` portion of 2328 /// the help text would be omitted. 2329 #[inline] 2330 #[must_use] hide_default_value(self, yes: bool) -> Self2331 pub fn hide_default_value(self, yes: bool) -> Self { 2332 if yes { 2333 self.setting(ArgSettings::HideDefaultValue) 2334 } else { 2335 self.unset_setting(ArgSettings::HideDefaultValue) 2336 } 2337 } 2338 2339 /// Do not display in help the environment variable name. 2340 /// 2341 /// This is useful when the variable option is explained elsewhere in the help text. 2342 /// 2343 /// # Examples 2344 /// 2345 /// ```rust 2346 /// # use clap::{Command, Arg, ArgAction}; 2347 /// let m = Command::new("prog") 2348 /// .arg(Arg::new("mode") 2349 /// .long("mode") 2350 /// .env("MODE") 2351 /// .action(ArgAction::Set) 2352 /// .hide_env(true)); 2353 /// ``` 2354 /// 2355 /// If we were to run the above program with `--help` the `[env: MODE]` portion of the help 2356 /// text would be omitted. 2357 #[cfg(feature = "env")] 2358 #[inline] 2359 #[must_use] hide_env(self, yes: bool) -> Self2360 pub fn hide_env(self, yes: bool) -> Self { 2361 if yes { 2362 self.setting(ArgSettings::HideEnv) 2363 } else { 2364 self.unset_setting(ArgSettings::HideEnv) 2365 } 2366 } 2367 2368 /// Do not display in help any values inside the associated ENV variables for the argument. 2369 /// 2370 /// This is useful when ENV vars contain sensitive values. 2371 /// 2372 /// # Examples 2373 /// 2374 /// ```rust 2375 /// # use clap::{Command, Arg, ArgAction}; 2376 /// let m = Command::new("connect") 2377 /// .arg(Arg::new("host") 2378 /// .long("host") 2379 /// .env("CONNECT") 2380 /// .action(ArgAction::Set) 2381 /// .hide_env_values(true)); 2382 /// 2383 /// ``` 2384 /// 2385 /// If we were to run the above program with `$ CONNECT=super_secret connect --help` the 2386 /// `[default: CONNECT=super_secret]` portion of the help text would be omitted. 2387 #[cfg(feature = "env")] 2388 #[inline] 2389 #[must_use] hide_env_values(self, yes: bool) -> Self2390 pub fn hide_env_values(self, yes: bool) -> Self { 2391 if yes { 2392 self.setting(ArgSettings::HideEnvValues) 2393 } else { 2394 self.unset_setting(ArgSettings::HideEnvValues) 2395 } 2396 } 2397 2398 /// Hides an argument from short help (`-h`). 2399 /// 2400 /// **NOTE:** This does **not** hide the argument from usage strings on error 2401 /// 2402 /// **NOTE:** Setting this option will cause next-line-help output style to be used 2403 /// when long help (`--help`) is called. 2404 /// 2405 /// # Examples 2406 /// 2407 /// ```rust 2408 /// # use clap::{Command, Arg}; 2409 /// Arg::new("debug") 2410 /// .hide_short_help(true); 2411 /// ``` 2412 /// 2413 /// Setting `hide_short_help(true)` will hide the argument when displaying short help text 2414 /// 2415 #[cfg_attr(not(feature = "help"), doc = " ```ignore")] 2416 #[cfg_attr(feature = "help", doc = " ```")] 2417 /// # use clap::{Command, Arg}; 2418 /// let m = Command::new("prog") 2419 /// .arg(Arg::new("cfg") 2420 /// .long("config") 2421 /// .hide_short_help(true) 2422 /// .help("Some help text describing the --config arg")) 2423 /// .get_matches_from(vec![ 2424 /// "prog", "-h" 2425 /// ]); 2426 /// ``` 2427 /// 2428 /// The above example displays 2429 /// 2430 /// ```text 2431 /// helptest 2432 /// 2433 /// Usage: helptest [OPTIONS] 2434 /// 2435 /// Options: 2436 /// -h, --help Print help information 2437 /// -V, --version Print version information 2438 /// ``` 2439 /// 2440 /// However, when --help is called 2441 /// 2442 #[cfg_attr(not(feature = "help"), doc = " ```ignore")] 2443 #[cfg_attr(feature = "help", doc = " ```")] 2444 /// # use clap::{Command, Arg}; 2445 /// let m = Command::new("prog") 2446 /// .arg(Arg::new("cfg") 2447 /// .long("config") 2448 /// .hide_short_help(true) 2449 /// .help("Some help text describing the --config arg")) 2450 /// .get_matches_from(vec![ 2451 /// "prog", "--help" 2452 /// ]); 2453 /// ``` 2454 /// 2455 /// Then the following would be displayed 2456 /// 2457 /// ```text 2458 /// helptest 2459 /// 2460 /// Usage: helptest [OPTIONS] 2461 /// 2462 /// Options: 2463 /// --config Some help text describing the --config arg 2464 /// -h, --help Print help information 2465 /// -V, --version Print version information 2466 /// ``` 2467 #[inline] 2468 #[must_use] hide_short_help(self, yes: bool) -> Self2469 pub fn hide_short_help(self, yes: bool) -> Self { 2470 if yes { 2471 self.setting(ArgSettings::HiddenShortHelp) 2472 } else { 2473 self.unset_setting(ArgSettings::HiddenShortHelp) 2474 } 2475 } 2476 2477 /// Hides an argument from long help (`--help`). 2478 /// 2479 /// **NOTE:** This does **not** hide the argument from usage strings on error 2480 /// 2481 /// **NOTE:** Setting this option will cause next-line-help output style to be used 2482 /// when long help (`--help`) is called. 2483 /// 2484 /// # Examples 2485 /// 2486 /// Setting `hide_long_help(true)` will hide the argument when displaying long help text 2487 /// 2488 #[cfg_attr(not(feature = "help"), doc = " ```ignore")] 2489 #[cfg_attr(feature = "help", doc = " ```")] 2490 /// # use clap::{Command, Arg}; 2491 /// let m = Command::new("prog") 2492 /// .arg(Arg::new("cfg") 2493 /// .long("config") 2494 /// .hide_long_help(true) 2495 /// .help("Some help text describing the --config arg")) 2496 /// .get_matches_from(vec![ 2497 /// "prog", "--help" 2498 /// ]); 2499 /// ``` 2500 /// 2501 /// The above example displays 2502 /// 2503 /// ```text 2504 /// helptest 2505 /// 2506 /// Usage: helptest [OPTIONS] 2507 /// 2508 /// Options: 2509 /// -h, --help Print help information 2510 /// -V, --version Print version information 2511 /// ``` 2512 /// 2513 /// However, when -h is called 2514 /// 2515 #[cfg_attr(not(feature = "help"), doc = " ```ignore")] 2516 #[cfg_attr(feature = "help", doc = " ```")] 2517 /// # use clap::{Command, Arg}; 2518 /// let m = Command::new("prog") 2519 /// .arg(Arg::new("cfg") 2520 /// .long("config") 2521 /// .hide_long_help(true) 2522 /// .help("Some help text describing the --config arg")) 2523 /// .get_matches_from(vec![ 2524 /// "prog", "-h" 2525 /// ]); 2526 /// ``` 2527 /// 2528 /// Then the following would be displayed 2529 /// 2530 /// ```text 2531 /// helptest 2532 /// 2533 /// Usage: helptest [OPTIONS] 2534 /// 2535 /// OPTIONS: 2536 /// --config Some help text describing the --config arg 2537 /// -h, --help Print help information 2538 /// -V, --version Print version information 2539 /// ``` 2540 #[inline] 2541 #[must_use] hide_long_help(self, yes: bool) -> Self2542 pub fn hide_long_help(self, yes: bool) -> Self { 2543 if yes { 2544 self.setting(ArgSettings::HiddenLongHelp) 2545 } else { 2546 self.unset_setting(ArgSettings::HiddenLongHelp) 2547 } 2548 } 2549 } 2550 2551 /// # Advanced Argument Relations 2552 impl Arg { 2553 /// The name of the [`ArgGroup`] the argument belongs to. 2554 /// 2555 /// # Examples 2556 /// 2557 /// ```rust 2558 /// # use clap::{Command, Arg, ArgAction}; 2559 /// Arg::new("debug") 2560 /// .long("debug") 2561 /// .action(ArgAction::SetTrue) 2562 /// .group("mode") 2563 /// # ; 2564 /// ``` 2565 /// 2566 /// Multiple arguments can be a member of a single group and then the group checked as if it 2567 /// was one of said arguments. 2568 /// 2569 /// ```rust 2570 /// # use clap::{Command, Arg, ArgAction}; 2571 /// let m = Command::new("prog") 2572 /// .arg(Arg::new("debug") 2573 /// .long("debug") 2574 /// .action(ArgAction::SetTrue) 2575 /// .group("mode")) 2576 /// .arg(Arg::new("verbose") 2577 /// .long("verbose") 2578 /// .action(ArgAction::SetTrue) 2579 /// .group("mode")) 2580 /// .get_matches_from(vec![ 2581 /// "prog", "--debug" 2582 /// ]); 2583 /// assert!(m.contains_id("mode")); 2584 /// ``` 2585 /// 2586 /// [`ArgGroup`]: crate::ArgGroup 2587 #[must_use] group(mut self, group_id: impl IntoResettable<Id>) -> Self2588 pub fn group(mut self, group_id: impl IntoResettable<Id>) -> Self { 2589 if let Some(group_id) = group_id.into_resettable().into_option() { 2590 self.groups.push(group_id); 2591 } else { 2592 self.groups.clear(); 2593 } 2594 self 2595 } 2596 2597 /// The names of [`ArgGroup`]'s the argument belongs to. 2598 /// 2599 /// # Examples 2600 /// 2601 /// ```rust 2602 /// # use clap::{Command, Arg, ArgAction}; 2603 /// Arg::new("debug") 2604 /// .long("debug") 2605 /// .action(ArgAction::SetTrue) 2606 /// .groups(["mode", "verbosity"]) 2607 /// # ; 2608 /// ``` 2609 /// 2610 /// Arguments can be members of multiple groups and then the group checked as if it 2611 /// was one of said arguments. 2612 /// 2613 /// ```rust 2614 /// # use clap::{Command, Arg, ArgAction}; 2615 /// let m = Command::new("prog") 2616 /// .arg(Arg::new("debug") 2617 /// .long("debug") 2618 /// .action(ArgAction::SetTrue) 2619 /// .groups(["mode", "verbosity"])) 2620 /// .arg(Arg::new("verbose") 2621 /// .long("verbose") 2622 /// .action(ArgAction::SetTrue) 2623 /// .groups(["mode", "verbosity"])) 2624 /// .get_matches_from(vec![ 2625 /// "prog", "--debug" 2626 /// ]); 2627 /// assert!(m.contains_id("mode")); 2628 /// assert!(m.contains_id("verbosity")); 2629 /// ``` 2630 /// 2631 /// [`ArgGroup`]: crate::ArgGroup 2632 #[must_use] groups(mut self, group_ids: impl IntoIterator<Item = impl Into<Id>>) -> Self2633 pub fn groups(mut self, group_ids: impl IntoIterator<Item = impl Into<Id>>) -> Self { 2634 self.groups.extend(group_ids.into_iter().map(Into::into)); 2635 self 2636 } 2637 2638 /// Specifies the value of the argument if `arg` has been used at runtime. 2639 /// 2640 /// If `default` is set to `None`, `default_value` will be removed. 2641 /// 2642 /// **NOTE:** This setting is perfectly compatible with [`Arg::default_value`] but slightly 2643 /// different. `Arg::default_value` *only* takes effect when the user has not provided this arg 2644 /// at runtime. This setting however only takes effect when the user has not provided a value at 2645 /// runtime **and** these other conditions are met as well. If you have set `Arg::default_value` 2646 /// and `Arg::default_value_if`, and the user **did not** provide this arg at runtime, nor were 2647 /// the conditions met for `Arg::default_value_if`, the `Arg::default_value` will be applied. 2648 /// 2649 /// **NOTE:** This implicitly sets [`Arg::action(ArgAction::Set)`]. 2650 /// 2651 /// # Examples 2652 /// 2653 /// First we use the default value only if another arg is present at runtime. 2654 /// 2655 /// ```rust 2656 /// # use clap::{Command, Arg, ArgAction}; 2657 /// # use clap::builder::{ArgPredicate}; 2658 /// let m = Command::new("prog") 2659 /// .arg(Arg::new("flag") 2660 /// .long("flag") 2661 /// .action(ArgAction::SetTrue)) 2662 /// .arg(Arg::new("other") 2663 /// .long("other") 2664 /// .default_value_if("flag", ArgPredicate::IsPresent, Some("default"))) 2665 /// .get_matches_from(vec![ 2666 /// "prog", "--flag" 2667 /// ]); 2668 /// 2669 /// assert_eq!(m.get_one::<String>("other").unwrap(), "default"); 2670 /// ``` 2671 /// 2672 /// Next we run the same test, but without providing `--flag`. 2673 /// 2674 /// ```rust 2675 /// # use clap::{Command, Arg, ArgAction}; 2676 /// let m = Command::new("prog") 2677 /// .arg(Arg::new("flag") 2678 /// .long("flag") 2679 /// .action(ArgAction::SetTrue)) 2680 /// .arg(Arg::new("other") 2681 /// .long("other") 2682 /// .default_value_if("flag", "true", Some("default"))) 2683 /// .get_matches_from(vec![ 2684 /// "prog" 2685 /// ]); 2686 /// 2687 /// assert_eq!(m.get_one::<String>("other"), None); 2688 /// ``` 2689 /// 2690 /// Now lets only use the default value if `--opt` contains the value `special`. 2691 /// 2692 /// ```rust 2693 /// # use clap::{Command, Arg, ArgAction}; 2694 /// let m = Command::new("prog") 2695 /// .arg(Arg::new("opt") 2696 /// .action(ArgAction::Set) 2697 /// .long("opt")) 2698 /// .arg(Arg::new("other") 2699 /// .long("other") 2700 /// .default_value_if("opt", "special", Some("default"))) 2701 /// .get_matches_from(vec![ 2702 /// "prog", "--opt", "special" 2703 /// ]); 2704 /// 2705 /// assert_eq!(m.get_one::<String>("other").unwrap(), "default"); 2706 /// ``` 2707 /// 2708 /// We can run the same test and provide any value *other than* `special` and we won't get a 2709 /// default value. 2710 /// 2711 /// ```rust 2712 /// # use clap::{Command, Arg, ArgAction}; 2713 /// let m = Command::new("prog") 2714 /// .arg(Arg::new("opt") 2715 /// .action(ArgAction::Set) 2716 /// .long("opt")) 2717 /// .arg(Arg::new("other") 2718 /// .long("other") 2719 /// .default_value_if("opt", "special", Some("default"))) 2720 /// .get_matches_from(vec![ 2721 /// "prog", "--opt", "hahaha" 2722 /// ]); 2723 /// 2724 /// assert_eq!(m.get_one::<String>("other"), None); 2725 /// ``` 2726 /// 2727 /// If we want to unset the default value for an Arg based on the presence or 2728 /// value of some other Arg. 2729 /// 2730 /// ```rust 2731 /// # use clap::{Command, Arg, ArgAction}; 2732 /// let m = Command::new("prog") 2733 /// .arg(Arg::new("flag") 2734 /// .long("flag") 2735 /// .action(ArgAction::SetTrue)) 2736 /// .arg(Arg::new("other") 2737 /// .long("other") 2738 /// .default_value("default") 2739 /// .default_value_if("flag", "true", None)) 2740 /// .get_matches_from(vec![ 2741 /// "prog", "--flag" 2742 /// ]); 2743 /// 2744 /// assert_eq!(m.get_one::<String>("other"), None); 2745 /// ``` 2746 /// [`Arg::action(ArgAction::Set)`]: Arg::action() 2747 /// [`Arg::default_value`]: Arg::default_value() 2748 #[must_use] default_value_if( mut self, arg_id: impl Into<Id>, predicate: impl Into<ArgPredicate>, default: impl IntoResettable<OsStr>, ) -> Self2749 pub fn default_value_if( 2750 mut self, 2751 arg_id: impl Into<Id>, 2752 predicate: impl Into<ArgPredicate>, 2753 default: impl IntoResettable<OsStr>, 2754 ) -> Self { 2755 self.default_vals_ifs.push(( 2756 arg_id.into(), 2757 predicate.into(), 2758 default.into_resettable().into_option(), 2759 )); 2760 self 2761 } 2762 2763 #[must_use] 2764 #[doc(hidden)] 2765 #[cfg_attr( 2766 feature = "deprecated", 2767 deprecated(since = "4.0.0", note = "Replaced with `Arg::default_value_if`") 2768 )] default_value_if_os( self, arg_id: impl Into<Id>, predicate: impl Into<ArgPredicate>, default: impl IntoResettable<OsStr>, ) -> Self2769 pub fn default_value_if_os( 2770 self, 2771 arg_id: impl Into<Id>, 2772 predicate: impl Into<ArgPredicate>, 2773 default: impl IntoResettable<OsStr>, 2774 ) -> Self { 2775 self.default_value_if(arg_id, predicate, default) 2776 } 2777 2778 /// Specifies multiple values and conditions in the same manner as [`Arg::default_value_if`]. 2779 /// 2780 /// The method takes a slice of tuples in the `(arg, predicate, default)` format. 2781 /// 2782 /// **NOTE**: The conditions are stored in order and evaluated in the same order. I.e. the first 2783 /// if multiple conditions are true, the first one found will be applied and the ultimate value. 2784 /// 2785 /// # Examples 2786 /// 2787 /// First we use the default value only if another arg is present at runtime. 2788 /// 2789 /// ```rust 2790 /// # use clap::{Command, Arg, ArgAction}; 2791 /// let m = Command::new("prog") 2792 /// .arg(Arg::new("flag") 2793 /// .long("flag") 2794 /// .action(ArgAction::SetTrue)) 2795 /// .arg(Arg::new("opt") 2796 /// .long("opt") 2797 /// .action(ArgAction::Set)) 2798 /// .arg(Arg::new("other") 2799 /// .long("other") 2800 /// .default_value_ifs([ 2801 /// ("flag", "true", Some("default")), 2802 /// ("opt", "channal", Some("chan")), 2803 /// ])) 2804 /// .get_matches_from(vec![ 2805 /// "prog", "--opt", "channal" 2806 /// ]); 2807 /// 2808 /// assert_eq!(m.get_one::<String>("other").unwrap(), "chan"); 2809 /// ``` 2810 /// 2811 /// Next we run the same test, but without providing `--flag`. 2812 /// 2813 /// ```rust 2814 /// # use clap::{Command, Arg, ArgAction}; 2815 /// let m = Command::new("prog") 2816 /// .arg(Arg::new("flag") 2817 /// .long("flag") 2818 /// .action(ArgAction::SetTrue)) 2819 /// .arg(Arg::new("other") 2820 /// .long("other") 2821 /// .default_value_ifs([ 2822 /// ("flag", "true", Some("default")), 2823 /// ("opt", "channal", Some("chan")), 2824 /// ])) 2825 /// .get_matches_from(vec![ 2826 /// "prog" 2827 /// ]); 2828 /// 2829 /// assert_eq!(m.get_one::<String>("other"), None); 2830 /// ``` 2831 /// 2832 /// We can also see that these values are applied in order, and if more than one condition is 2833 /// true, only the first evaluated "wins" 2834 /// 2835 /// ```rust 2836 /// # use clap::{Command, Arg, ArgAction}; 2837 /// # use clap::builder::ArgPredicate; 2838 /// let m = Command::new("prog") 2839 /// .arg(Arg::new("flag") 2840 /// .long("flag") 2841 /// .action(ArgAction::SetTrue)) 2842 /// .arg(Arg::new("opt") 2843 /// .long("opt") 2844 /// .action(ArgAction::Set)) 2845 /// .arg(Arg::new("other") 2846 /// .long("other") 2847 /// .default_value_ifs([ 2848 /// ("flag", ArgPredicate::IsPresent, Some("default")), 2849 /// ("opt", ArgPredicate::Equals("channal".into()), Some("chan")), 2850 /// ])) 2851 /// .get_matches_from(vec![ 2852 /// "prog", "--opt", "channal", "--flag" 2853 /// ]); 2854 /// 2855 /// assert_eq!(m.get_one::<String>("other").unwrap(), "default"); 2856 /// ``` 2857 /// [`Arg::action(ArgAction::Set)`]: Arg::action() 2858 /// [`Arg::default_value_if`]: Arg::default_value_if() 2859 #[must_use] default_value_ifs( mut self, ifs: impl IntoIterator< Item = ( impl Into<Id>, impl Into<ArgPredicate>, impl IntoResettable<OsStr>, ), >, ) -> Self2860 pub fn default_value_ifs( 2861 mut self, 2862 ifs: impl IntoIterator< 2863 Item = ( 2864 impl Into<Id>, 2865 impl Into<ArgPredicate>, 2866 impl IntoResettable<OsStr>, 2867 ), 2868 >, 2869 ) -> Self { 2870 for (arg, predicate, default) in ifs { 2871 self = self.default_value_if(arg, predicate, default); 2872 } 2873 self 2874 } 2875 2876 #[must_use] 2877 #[doc(hidden)] 2878 #[cfg_attr( 2879 feature = "deprecated", 2880 deprecated(since = "4.0.0", note = "Replaced with `Arg::default_value_ifs`") 2881 )] default_value_ifs_os( self, ifs: impl IntoIterator< Item = ( impl Into<Id>, impl Into<ArgPredicate>, impl IntoResettable<OsStr>, ), >, ) -> Self2882 pub fn default_value_ifs_os( 2883 self, 2884 ifs: impl IntoIterator< 2885 Item = ( 2886 impl Into<Id>, 2887 impl Into<ArgPredicate>, 2888 impl IntoResettable<OsStr>, 2889 ), 2890 >, 2891 ) -> Self { 2892 self.default_value_ifs(ifs) 2893 } 2894 2895 /// Set this arg as [required] as long as the specified argument is not present at runtime. 2896 /// 2897 /// **Pro Tip:** Using `Arg::required_unless_present` implies [`Arg::required`] and is therefore not 2898 /// mandatory to also set. 2899 /// 2900 /// # Examples 2901 /// 2902 /// ```rust 2903 /// # use clap::Arg; 2904 /// Arg::new("config") 2905 /// .required_unless_present("debug") 2906 /// # ; 2907 /// ``` 2908 /// 2909 /// In the following example, the required argument is *not* provided, 2910 /// but it's not an error because the `unless` arg has been supplied. 2911 /// 2912 /// ```rust 2913 /// # use clap::{Command, Arg, ArgAction}; 2914 /// let res = Command::new("prog") 2915 /// .arg(Arg::new("cfg") 2916 /// .required_unless_present("dbg") 2917 /// .action(ArgAction::Set) 2918 /// .long("config")) 2919 /// .arg(Arg::new("dbg") 2920 /// .long("debug") 2921 /// .action(ArgAction::SetTrue)) 2922 /// .try_get_matches_from(vec![ 2923 /// "prog", "--debug" 2924 /// ]); 2925 /// 2926 /// assert!(res.is_ok()); 2927 /// ``` 2928 /// 2929 /// Setting `Arg::required_unless_present(name)` and *not* supplying `name` or this arg is an error. 2930 /// 2931 /// ```rust 2932 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; 2933 /// let res = Command::new("prog") 2934 /// .arg(Arg::new("cfg") 2935 /// .required_unless_present("dbg") 2936 /// .action(ArgAction::Set) 2937 /// .long("config")) 2938 /// .arg(Arg::new("dbg") 2939 /// .long("debug")) 2940 /// .try_get_matches_from(vec![ 2941 /// "prog" 2942 /// ]); 2943 /// 2944 /// assert!(res.is_err()); 2945 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); 2946 /// ``` 2947 /// [required]: Arg::required() 2948 #[must_use] required_unless_present(mut self, arg_id: impl IntoResettable<Id>) -> Self2949 pub fn required_unless_present(mut self, arg_id: impl IntoResettable<Id>) -> Self { 2950 if let Some(arg_id) = arg_id.into_resettable().into_option() { 2951 self.r_unless.push(arg_id); 2952 } else { 2953 self.r_unless.clear(); 2954 } 2955 self 2956 } 2957 2958 /// Sets this arg as [required] unless *all* of the specified arguments are present at runtime. 2959 /// 2960 /// In other words, parsing will succeed only if user either 2961 /// * supplies the `self` arg. 2962 /// * supplies *all* of the `names` arguments. 2963 /// 2964 /// **NOTE:** If you wish for this argument to only be required unless *any of* these args are 2965 /// present see [`Arg::required_unless_present_any`] 2966 /// 2967 /// # Examples 2968 /// 2969 /// ```rust 2970 /// # use clap::Arg; 2971 /// Arg::new("config") 2972 /// .required_unless_present_all(["cfg", "dbg"]) 2973 /// # ; 2974 /// ``` 2975 /// 2976 /// In the following example, the required argument is *not* provided, but it's not an error 2977 /// because *all* of the `names` args have been supplied. 2978 /// 2979 /// ```rust 2980 /// # use clap::{Command, Arg, ArgAction}; 2981 /// let res = Command::new("prog") 2982 /// .arg(Arg::new("cfg") 2983 /// .required_unless_present_all(["dbg", "infile"]) 2984 /// .action(ArgAction::Set) 2985 /// .long("config")) 2986 /// .arg(Arg::new("dbg") 2987 /// .long("debug") 2988 /// .action(ArgAction::SetTrue)) 2989 /// .arg(Arg::new("infile") 2990 /// .short('i') 2991 /// .action(ArgAction::Set)) 2992 /// .try_get_matches_from(vec![ 2993 /// "prog", "--debug", "-i", "file" 2994 /// ]); 2995 /// 2996 /// assert!(res.is_ok()); 2997 /// ``` 2998 /// 2999 /// Setting [`Arg::required_unless_present_all(names)`] and *not* supplying 3000 /// either *all* of `unless` args or the `self` arg is an error. 3001 /// 3002 /// ```rust 3003 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; 3004 /// let res = Command::new("prog") 3005 /// .arg(Arg::new("cfg") 3006 /// .required_unless_present_all(["dbg", "infile"]) 3007 /// .action(ArgAction::Set) 3008 /// .long("config")) 3009 /// .arg(Arg::new("dbg") 3010 /// .long("debug") 3011 /// .action(ArgAction::SetTrue)) 3012 /// .arg(Arg::new("infile") 3013 /// .short('i') 3014 /// .action(ArgAction::Set)) 3015 /// .try_get_matches_from(vec![ 3016 /// "prog" 3017 /// ]); 3018 /// 3019 /// assert!(res.is_err()); 3020 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); 3021 /// ``` 3022 /// [required]: Arg::required() 3023 /// [`Arg::required_unless_present_any`]: Arg::required_unless_present_any() 3024 /// [`Arg::required_unless_present_all(names)`]: Arg::required_unless_present_all() 3025 #[must_use] required_unless_present_all( mut self, names: impl IntoIterator<Item = impl Into<Id>>, ) -> Self3026 pub fn required_unless_present_all( 3027 mut self, 3028 names: impl IntoIterator<Item = impl Into<Id>>, 3029 ) -> Self { 3030 self.r_unless_all.extend(names.into_iter().map(Into::into)); 3031 self 3032 } 3033 3034 /// Sets this arg as [required] unless *any* of the specified arguments are present at runtime. 3035 /// 3036 /// In other words, parsing will succeed only if user either 3037 /// * supplies the `self` arg. 3038 /// * supplies *one or more* of the `unless` arguments. 3039 /// 3040 /// **NOTE:** If you wish for this argument to be required unless *all of* these args are 3041 /// present see [`Arg::required_unless_present_all`] 3042 /// 3043 /// # Examples 3044 /// 3045 /// ```rust 3046 /// # use clap::Arg; 3047 /// Arg::new("config") 3048 /// .required_unless_present_any(["cfg", "dbg"]) 3049 /// # ; 3050 /// ``` 3051 /// 3052 /// Setting [`Arg::required_unless_present_any(names)`] requires that the argument be used at runtime 3053 /// *unless* *at least one of* the args in `names` are present. In the following example, the 3054 /// required argument is *not* provided, but it's not an error because one the `unless` args 3055 /// have been supplied. 3056 /// 3057 /// ```rust 3058 /// # use clap::{Command, Arg, ArgAction}; 3059 /// let res = Command::new("prog") 3060 /// .arg(Arg::new("cfg") 3061 /// .required_unless_present_any(["dbg", "infile"]) 3062 /// .action(ArgAction::Set) 3063 /// .long("config")) 3064 /// .arg(Arg::new("dbg") 3065 /// .long("debug") 3066 /// .action(ArgAction::SetTrue)) 3067 /// .arg(Arg::new("infile") 3068 /// .short('i') 3069 /// .action(ArgAction::Set)) 3070 /// .try_get_matches_from(vec![ 3071 /// "prog", "--debug" 3072 /// ]); 3073 /// 3074 /// assert!(res.is_ok()); 3075 /// ``` 3076 /// 3077 /// Setting [`Arg::required_unless_present_any(names)`] and *not* supplying *at least one of* `names` 3078 /// or this arg is an error. 3079 /// 3080 /// ```rust 3081 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; 3082 /// let res = Command::new("prog") 3083 /// .arg(Arg::new("cfg") 3084 /// .required_unless_present_any(["dbg", "infile"]) 3085 /// .action(ArgAction::Set) 3086 /// .long("config")) 3087 /// .arg(Arg::new("dbg") 3088 /// .long("debug") 3089 /// .action(ArgAction::SetTrue)) 3090 /// .arg(Arg::new("infile") 3091 /// .short('i') 3092 /// .action(ArgAction::Set)) 3093 /// .try_get_matches_from(vec![ 3094 /// "prog" 3095 /// ]); 3096 /// 3097 /// assert!(res.is_err()); 3098 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); 3099 /// ``` 3100 /// [required]: Arg::required() 3101 /// [`Arg::required_unless_present_any(names)`]: Arg::required_unless_present_any() 3102 /// [`Arg::required_unless_present_all`]: Arg::required_unless_present_all() 3103 #[must_use] required_unless_present_any( mut self, names: impl IntoIterator<Item = impl Into<Id>>, ) -> Self3104 pub fn required_unless_present_any( 3105 mut self, 3106 names: impl IntoIterator<Item = impl Into<Id>>, 3107 ) -> Self { 3108 self.r_unless.extend(names.into_iter().map(Into::into)); 3109 self 3110 } 3111 3112 /// This argument is [required] only if the specified `arg` is present at runtime and its value 3113 /// equals `val`. 3114 /// 3115 /// # Examples 3116 /// 3117 /// ```rust 3118 /// # use clap::Arg; 3119 /// Arg::new("config") 3120 /// .required_if_eq("other_arg", "value") 3121 /// # ; 3122 /// ``` 3123 /// 3124 /// ```rust 3125 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; 3126 /// let res = Command::new("prog") 3127 /// .arg(Arg::new("cfg") 3128 /// .action(ArgAction::Set) 3129 /// .required_if_eq("other", "special") 3130 /// .long("config")) 3131 /// .arg(Arg::new("other") 3132 /// .long("other") 3133 /// .action(ArgAction::Set)) 3134 /// .try_get_matches_from(vec![ 3135 /// "prog", "--other", "not-special" 3136 /// ]); 3137 /// 3138 /// assert!(res.is_ok()); // We didn't use --other=special, so "cfg" wasn't required 3139 /// 3140 /// let res = Command::new("prog") 3141 /// .arg(Arg::new("cfg") 3142 /// .action(ArgAction::Set) 3143 /// .required_if_eq("other", "special") 3144 /// .long("config")) 3145 /// .arg(Arg::new("other") 3146 /// .long("other") 3147 /// .action(ArgAction::Set)) 3148 /// .try_get_matches_from(vec![ 3149 /// "prog", "--other", "special" 3150 /// ]); 3151 /// 3152 /// // We did use --other=special so "cfg" had become required but was missing. 3153 /// assert!(res.is_err()); 3154 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); 3155 /// 3156 /// let res = Command::new("prog") 3157 /// .arg(Arg::new("cfg") 3158 /// .action(ArgAction::Set) 3159 /// .required_if_eq("other", "special") 3160 /// .long("config")) 3161 /// .arg(Arg::new("other") 3162 /// .long("other") 3163 /// .action(ArgAction::Set)) 3164 /// .try_get_matches_from(vec![ 3165 /// "prog", "--other", "SPECIAL" 3166 /// ]); 3167 /// 3168 /// // By default, the comparison is case-sensitive, so "cfg" wasn't required 3169 /// assert!(res.is_ok()); 3170 /// 3171 /// let res = Command::new("prog") 3172 /// .arg(Arg::new("cfg") 3173 /// .action(ArgAction::Set) 3174 /// .required_if_eq("other", "special") 3175 /// .long("config")) 3176 /// .arg(Arg::new("other") 3177 /// .long("other") 3178 /// .ignore_case(true) 3179 /// .action(ArgAction::Set)) 3180 /// .try_get_matches_from(vec![ 3181 /// "prog", "--other", "SPECIAL" 3182 /// ]); 3183 /// 3184 /// // However, case-insensitive comparisons can be enabled. This typically occurs when using Arg::possible_values(). 3185 /// assert!(res.is_err()); 3186 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); 3187 /// ``` 3188 /// [`Arg::requires(name)`]: Arg::requires() 3189 /// [Conflicting]: Arg::conflicts_with() 3190 /// [required]: Arg::required() 3191 #[must_use] required_if_eq(mut self, arg_id: impl Into<Id>, val: impl Into<OsStr>) -> Self3192 pub fn required_if_eq(mut self, arg_id: impl Into<Id>, val: impl Into<OsStr>) -> Self { 3193 self.r_ifs.push((arg_id.into(), val.into())); 3194 self 3195 } 3196 3197 /// Specify this argument is [required] based on multiple conditions. 3198 /// 3199 /// The conditions are set up in a `(arg, val)` style tuple. The requirement will only become 3200 /// valid if one of the specified `arg`'s value equals its corresponding `val`. 3201 /// 3202 /// # Examples 3203 /// 3204 /// ```rust 3205 /// # use clap::Arg; 3206 /// Arg::new("config") 3207 /// .required_if_eq_any([ 3208 /// ("extra", "val"), 3209 /// ("option", "spec") 3210 /// ]) 3211 /// # ; 3212 /// ``` 3213 /// 3214 /// Setting `Arg::required_if_eq_any([(arg, val)])` makes this arg required if any of the `arg`s 3215 /// are used at runtime and it's corresponding value is equal to `val`. If the `arg`'s value is 3216 /// anything other than `val`, this argument isn't required. 3217 /// 3218 /// ```rust 3219 /// # use clap::{Command, Arg, ArgAction}; 3220 /// let res = Command::new("prog") 3221 /// .arg(Arg::new("cfg") 3222 /// .required_if_eq_any([ 3223 /// ("extra", "val"), 3224 /// ("option", "spec") 3225 /// ]) 3226 /// .action(ArgAction::Set) 3227 /// .long("config")) 3228 /// .arg(Arg::new("extra") 3229 /// .action(ArgAction::Set) 3230 /// .long("extra")) 3231 /// .arg(Arg::new("option") 3232 /// .action(ArgAction::Set) 3233 /// .long("option")) 3234 /// .try_get_matches_from(vec![ 3235 /// "prog", "--option", "other" 3236 /// ]); 3237 /// 3238 /// assert!(res.is_ok()); // We didn't use --option=spec, or --extra=val so "cfg" isn't required 3239 /// ``` 3240 /// 3241 /// Setting `Arg::required_if_eq_any([(arg, val)])` and having any of the `arg`s used with its 3242 /// value of `val` but *not* using this arg is an error. 3243 /// 3244 /// ```rust 3245 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; 3246 /// let res = Command::new("prog") 3247 /// .arg(Arg::new("cfg") 3248 /// .required_if_eq_any([ 3249 /// ("extra", "val"), 3250 /// ("option", "spec") 3251 /// ]) 3252 /// .action(ArgAction::Set) 3253 /// .long("config")) 3254 /// .arg(Arg::new("extra") 3255 /// .action(ArgAction::Set) 3256 /// .long("extra")) 3257 /// .arg(Arg::new("option") 3258 /// .action(ArgAction::Set) 3259 /// .long("option")) 3260 /// .try_get_matches_from(vec![ 3261 /// "prog", "--option", "spec" 3262 /// ]); 3263 /// 3264 /// assert!(res.is_err()); 3265 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); 3266 /// ``` 3267 /// [`Arg::requires(name)`]: Arg::requires() 3268 /// [Conflicting]: Arg::conflicts_with() 3269 /// [required]: Arg::required() 3270 #[must_use] required_if_eq_any( mut self, ifs: impl IntoIterator<Item = (impl Into<Id>, impl Into<OsStr>)>, ) -> Self3271 pub fn required_if_eq_any( 3272 mut self, 3273 ifs: impl IntoIterator<Item = (impl Into<Id>, impl Into<OsStr>)>, 3274 ) -> Self { 3275 self.r_ifs 3276 .extend(ifs.into_iter().map(|(id, val)| (id.into(), val.into()))); 3277 self 3278 } 3279 3280 /// Specify this argument is [required] based on multiple conditions. 3281 /// 3282 /// The conditions are set up in a `(arg, val)` style tuple. The requirement will only become 3283 /// valid if every one of the specified `arg`'s value equals its corresponding `val`. 3284 /// 3285 /// # Examples 3286 /// 3287 /// ```rust 3288 /// # use clap::Arg; 3289 /// Arg::new("config") 3290 /// .required_if_eq_all([ 3291 /// ("extra", "val"), 3292 /// ("option", "spec") 3293 /// ]) 3294 /// # ; 3295 /// ``` 3296 /// 3297 /// Setting `Arg::required_if_eq_all([(arg, val)])` makes this arg required if all of the `arg`s 3298 /// are used at runtime and every value is equal to its corresponding `val`. If the `arg`'s value is 3299 /// anything other than `val`, this argument isn't required. 3300 /// 3301 /// ```rust 3302 /// # use clap::{Command, Arg, ArgAction}; 3303 /// let res = Command::new("prog") 3304 /// .arg(Arg::new("cfg") 3305 /// .required_if_eq_all([ 3306 /// ("extra", "val"), 3307 /// ("option", "spec") 3308 /// ]) 3309 /// .action(ArgAction::Set) 3310 /// .long("config")) 3311 /// .arg(Arg::new("extra") 3312 /// .action(ArgAction::Set) 3313 /// .long("extra")) 3314 /// .arg(Arg::new("option") 3315 /// .action(ArgAction::Set) 3316 /// .long("option")) 3317 /// .try_get_matches_from(vec![ 3318 /// "prog", "--option", "spec" 3319 /// ]); 3320 /// 3321 /// assert!(res.is_ok()); // We didn't use --option=spec --extra=val so "cfg" isn't required 3322 /// ``` 3323 /// 3324 /// Setting `Arg::required_if_eq_all([(arg, val)])` and having all of the `arg`s used with its 3325 /// value of `val` but *not* using this arg is an error. 3326 /// 3327 /// ```rust 3328 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; 3329 /// let res = Command::new("prog") 3330 /// .arg(Arg::new("cfg") 3331 /// .required_if_eq_all([ 3332 /// ("extra", "val"), 3333 /// ("option", "spec") 3334 /// ]) 3335 /// .action(ArgAction::Set) 3336 /// .long("config")) 3337 /// .arg(Arg::new("extra") 3338 /// .action(ArgAction::Set) 3339 /// .long("extra")) 3340 /// .arg(Arg::new("option") 3341 /// .action(ArgAction::Set) 3342 /// .long("option")) 3343 /// .try_get_matches_from(vec![ 3344 /// "prog", "--extra", "val", "--option", "spec" 3345 /// ]); 3346 /// 3347 /// assert!(res.is_err()); 3348 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); 3349 /// ``` 3350 /// [required]: Arg::required() 3351 #[must_use] required_if_eq_all( mut self, ifs: impl IntoIterator<Item = (impl Into<Id>, impl Into<OsStr>)>, ) -> Self3352 pub fn required_if_eq_all( 3353 mut self, 3354 ifs: impl IntoIterator<Item = (impl Into<Id>, impl Into<OsStr>)>, 3355 ) -> Self { 3356 self.r_ifs_all 3357 .extend(ifs.into_iter().map(|(id, val)| (id.into(), val.into()))); 3358 self 3359 } 3360 3361 /// Require another argument if this arg matches the [`ArgPredicate`] 3362 /// 3363 /// This method takes `value, another_arg` pair. At runtime, clap will check 3364 /// if this arg (`self`) matches the [`ArgPredicate`]. 3365 /// If it does, `another_arg` will be marked as required. 3366 /// 3367 /// # Examples 3368 /// 3369 /// ```rust 3370 /// # use clap::Arg; 3371 /// Arg::new("config") 3372 /// .requires_if("val", "arg") 3373 /// # ; 3374 /// ``` 3375 /// 3376 /// Setting `Arg::requires_if(val, arg)` requires that the `arg` be used at runtime if the 3377 /// defining argument's value is equal to `val`. If the defining argument is anything other than 3378 /// `val`, the other argument isn't required. 3379 /// 3380 /// ```rust 3381 /// # use clap::{Command, Arg, ArgAction}; 3382 /// let res = Command::new("prog") 3383 /// .arg(Arg::new("cfg") 3384 /// .action(ArgAction::Set) 3385 /// .requires_if("my.cfg", "other") 3386 /// .long("config")) 3387 /// .arg(Arg::new("other")) 3388 /// .try_get_matches_from(vec![ 3389 /// "prog", "--config", "some.cfg" 3390 /// ]); 3391 /// 3392 /// assert!(res.is_ok()); // We didn't use --config=my.cfg, so other wasn't required 3393 /// ``` 3394 /// 3395 /// Setting `Arg::requires_if(val, arg)` and setting the value to `val` but *not* supplying 3396 /// `arg` is an error. 3397 /// 3398 /// ```rust 3399 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; 3400 /// let res = Command::new("prog") 3401 /// .arg(Arg::new("cfg") 3402 /// .action(ArgAction::Set) 3403 /// .requires_if("my.cfg", "input") 3404 /// .long("config")) 3405 /// .arg(Arg::new("input")) 3406 /// .try_get_matches_from(vec![ 3407 /// "prog", "--config", "my.cfg" 3408 /// ]); 3409 /// 3410 /// assert!(res.is_err()); 3411 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); 3412 /// ``` 3413 /// [`Arg::requires(name)`]: Arg::requires() 3414 /// [Conflicting]: Arg::conflicts_with() 3415 /// [override]: Arg::overrides_with() 3416 #[must_use] requires_if(mut self, val: impl Into<ArgPredicate>, arg_id: impl Into<Id>) -> Self3417 pub fn requires_if(mut self, val: impl Into<ArgPredicate>, arg_id: impl Into<Id>) -> Self { 3418 self.requires.push((val.into(), arg_id.into())); 3419 self 3420 } 3421 3422 /// Allows multiple conditional requirements. 3423 /// 3424 /// The requirement will only become valid if this arg's value matches the 3425 /// [`ArgPredicate`]. 3426 /// 3427 /// # Examples 3428 /// 3429 /// ```rust 3430 /// # use clap::Arg; 3431 /// Arg::new("config") 3432 /// .requires_ifs([ 3433 /// ("val", "arg"), 3434 /// ("other_val", "arg2"), 3435 /// ]) 3436 /// # ; 3437 /// ``` 3438 /// 3439 /// Setting `Arg::requires_ifs(["val", "arg"])` requires that the `arg` be used at runtime if the 3440 /// defining argument's value is equal to `val`. If the defining argument's value is anything other 3441 /// than `val`, `arg` isn't required. 3442 /// 3443 /// ```rust 3444 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; 3445 /// let res = Command::new("prog") 3446 /// .arg(Arg::new("cfg") 3447 /// .action(ArgAction::Set) 3448 /// .requires_ifs([ 3449 /// ("special.conf", "opt"), 3450 /// ("other.conf", "other"), 3451 /// ]) 3452 /// .long("config")) 3453 /// .arg(Arg::new("opt") 3454 /// .long("option") 3455 /// .action(ArgAction::Set)) 3456 /// .arg(Arg::new("other")) 3457 /// .try_get_matches_from(vec![ 3458 /// "prog", "--config", "special.conf" 3459 /// ]); 3460 /// 3461 /// assert!(res.is_err()); // We used --config=special.conf so --option <val> is required 3462 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); 3463 /// ``` 3464 /// 3465 /// Setting `Arg::requires_ifs` with [`ArgPredicate::IsPresent`] and *not* supplying all the 3466 /// arguments is an error. 3467 /// 3468 /// ```rust 3469 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction, builder::ArgPredicate}; 3470 /// let res = Command::new("prog") 3471 /// .arg(Arg::new("cfg") 3472 /// .action(ArgAction::Set) 3473 /// .requires_ifs([ 3474 /// (ArgPredicate::IsPresent, "input"), 3475 /// (ArgPredicate::IsPresent, "output"), 3476 /// ]) 3477 /// .long("config")) 3478 /// .arg(Arg::new("input")) 3479 /// .arg(Arg::new("output")) 3480 /// .try_get_matches_from(vec![ 3481 /// "prog", "--config", "file.conf", "in.txt" 3482 /// ]); 3483 /// 3484 /// assert!(res.is_err()); 3485 /// // We didn't use output 3486 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); 3487 /// ``` 3488 /// 3489 /// [`Arg::requires(name)`]: Arg::requires() 3490 /// [Conflicting]: Arg::conflicts_with() 3491 /// [override]: Arg::overrides_with() 3492 #[must_use] requires_ifs( mut self, ifs: impl IntoIterator<Item = (impl Into<ArgPredicate>, impl Into<Id>)>, ) -> Self3493 pub fn requires_ifs( 3494 mut self, 3495 ifs: impl IntoIterator<Item = (impl Into<ArgPredicate>, impl Into<Id>)>, 3496 ) -> Self { 3497 self.requires 3498 .extend(ifs.into_iter().map(|(val, arg)| (val.into(), arg.into()))); 3499 self 3500 } 3501 3502 #[doc(hidden)] 3503 #[cfg_attr( 3504 feature = "deprecated", 3505 deprecated(since = "4.0.0", note = "Replaced with `Arg::requires_ifs`") 3506 )] requires_all(self, ids: impl IntoIterator<Item = impl Into<Id>>) -> Self3507 pub fn requires_all(self, ids: impl IntoIterator<Item = impl Into<Id>>) -> Self { 3508 self.requires_ifs(ids.into_iter().map(|id| (ArgPredicate::IsPresent, id))) 3509 } 3510 3511 /// This argument is mutually exclusive with the specified argument. 3512 /// 3513 /// **NOTE:** Conflicting rules take precedence over being required by default. Conflict rules 3514 /// only need to be set for one of the two arguments, they do not need to be set for each. 3515 /// 3516 /// **NOTE:** Defining a conflict is two-way, but does *not* need to defined for both arguments 3517 /// (i.e. if A conflicts with B, defining A.conflicts_with(B) is sufficient. You do not 3518 /// need to also do B.conflicts_with(A)) 3519 /// 3520 /// **NOTE:** [`Arg::conflicts_with_all(names)`] allows specifying an argument which conflicts with more than one argument. 3521 /// 3522 /// **NOTE** [`Arg::exclusive(true)`] allows specifying an argument which conflicts with every other argument. 3523 /// 3524 /// **NOTE:** All arguments implicitly conflict with themselves. 3525 /// 3526 /// # Examples 3527 /// 3528 /// ```rust 3529 /// # use clap::Arg; 3530 /// Arg::new("config") 3531 /// .conflicts_with("debug") 3532 /// # ; 3533 /// ``` 3534 /// 3535 /// Setting conflicting argument, and having both arguments present at runtime is an error. 3536 /// 3537 /// ```rust 3538 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; 3539 /// let res = Command::new("prog") 3540 /// .arg(Arg::new("cfg") 3541 /// .action(ArgAction::Set) 3542 /// .conflicts_with("debug") 3543 /// .long("config")) 3544 /// .arg(Arg::new("debug") 3545 /// .long("debug") 3546 /// .action(ArgAction::SetTrue)) 3547 /// .try_get_matches_from(vec![ 3548 /// "prog", "--debug", "--config", "file.conf" 3549 /// ]); 3550 /// 3551 /// assert!(res.is_err()); 3552 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::ArgumentConflict); 3553 /// ``` 3554 /// 3555 /// [`Arg::conflicts_with_all(names)`]: Arg::conflicts_with_all() 3556 /// [`Arg::exclusive(true)`]: Arg::exclusive() 3557 #[must_use] conflicts_with(mut self, arg_id: impl IntoResettable<Id>) -> Self3558 pub fn conflicts_with(mut self, arg_id: impl IntoResettable<Id>) -> Self { 3559 if let Some(arg_id) = arg_id.into_resettable().into_option() { 3560 self.blacklist.push(arg_id); 3561 } else { 3562 self.blacklist.clear(); 3563 } 3564 self 3565 } 3566 3567 /// This argument is mutually exclusive with the specified arguments. 3568 /// 3569 /// See [`Arg::conflicts_with`]. 3570 /// 3571 /// **NOTE:** Conflicting rules take precedence over being required by default. Conflict rules 3572 /// only need to be set for one of the two arguments, they do not need to be set for each. 3573 /// 3574 /// **NOTE:** Defining a conflict is two-way, but does *not* need to defined for both arguments 3575 /// (i.e. if A conflicts with B, defining A.conflicts_with(B) is sufficient. You do not need 3576 /// need to also do B.conflicts_with(A)) 3577 /// 3578 /// **NOTE:** [`Arg::exclusive(true)`] allows specifying an argument which conflicts with every other argument. 3579 /// 3580 /// # Examples 3581 /// 3582 /// ```rust 3583 /// # use clap::Arg; 3584 /// Arg::new("config") 3585 /// .conflicts_with_all(["debug", "input"]) 3586 /// # ; 3587 /// ``` 3588 /// 3589 /// Setting conflicting argument, and having any of the arguments present at runtime with a 3590 /// conflicting argument is an error. 3591 /// 3592 /// ```rust 3593 /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; 3594 /// let res = Command::new("prog") 3595 /// .arg(Arg::new("cfg") 3596 /// .action(ArgAction::Set) 3597 /// .conflicts_with_all(["debug", "input"]) 3598 /// .long("config")) 3599 /// .arg(Arg::new("debug") 3600 /// .long("debug")) 3601 /// .arg(Arg::new("input")) 3602 /// .try_get_matches_from(vec![ 3603 /// "prog", "--config", "file.conf", "file.txt" 3604 /// ]); 3605 /// 3606 /// assert!(res.is_err()); 3607 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::ArgumentConflict); 3608 /// ``` 3609 /// [`Arg::conflicts_with`]: Arg::conflicts_with() 3610 /// [`Arg::exclusive(true)`]: Arg::exclusive() 3611 #[must_use] conflicts_with_all(mut self, names: impl IntoIterator<Item = impl Into<Id>>) -> Self3612 pub fn conflicts_with_all(mut self, names: impl IntoIterator<Item = impl Into<Id>>) -> Self { 3613 self.blacklist.extend(names.into_iter().map(Into::into)); 3614 self 3615 } 3616 3617 /// Sets an overridable argument. 3618 /// 3619 /// i.e. this argument and the following argument 3620 /// will override each other in POSIX style (whichever argument was specified at runtime 3621 /// **last** "wins") 3622 /// 3623 /// **NOTE:** When an argument is overridden it is essentially as if it never was used, any 3624 /// conflicts, requirements, etc. are evaluated **after** all "overrides" have been removed 3625 /// 3626 /// **NOTE:** Overriding an argument implies they [conflict][Arg::conflicts_with`]. 3627 /// 3628 /// # Examples 3629 /// 3630 /// ```rust 3631 /// # use clap::{Command, arg}; 3632 /// let m = Command::new("prog") 3633 /// .arg(arg!(-f --flag "some flag") 3634 /// .conflicts_with("debug")) 3635 /// .arg(arg!(-d --debug "other flag")) 3636 /// .arg(arg!(-c --color "third flag") 3637 /// .overrides_with("flag")) 3638 /// .get_matches_from(vec![ 3639 /// "prog", "-f", "-d", "-c"]); 3640 /// // ^~~~~~~~~~~~^~~~~ flag is overridden by color 3641 /// 3642 /// assert!(m.get_flag("color")); 3643 /// assert!(m.get_flag("debug")); // even though flag conflicts with debug, it's as if flag 3644 /// // was never used because it was overridden with color 3645 /// assert!(!m.get_flag("flag")); 3646 /// ``` 3647 #[must_use] overrides_with(mut self, arg_id: impl IntoResettable<Id>) -> Self3648 pub fn overrides_with(mut self, arg_id: impl IntoResettable<Id>) -> Self { 3649 if let Some(arg_id) = arg_id.into_resettable().into_option() { 3650 self.overrides.push(arg_id); 3651 } else { 3652 self.overrides.clear(); 3653 } 3654 self 3655 } 3656 3657 /// Sets multiple mutually overridable arguments by name. 3658 /// 3659 /// i.e. this argument and the following argument will override each other in POSIX style 3660 /// (whichever argument was specified at runtime **last** "wins") 3661 /// 3662 /// **NOTE:** When an argument is overridden it is essentially as if it never was used, any 3663 /// conflicts, requirements, etc. are evaluated **after** all "overrides" have been removed 3664 /// 3665 /// **NOTE:** Overriding an argument implies they [conflict][Arg::conflicts_with_all`]. 3666 /// 3667 /// # Examples 3668 /// 3669 /// ```rust 3670 /// # use clap::{Command, arg}; 3671 /// let m = Command::new("prog") 3672 /// .arg(arg!(-f --flag "some flag") 3673 /// .conflicts_with("color")) 3674 /// .arg(arg!(-d --debug "other flag")) 3675 /// .arg(arg!(-c --color "third flag") 3676 /// .overrides_with_all(["flag", "debug"])) 3677 /// .get_matches_from(vec![ 3678 /// "prog", "-f", "-d", "-c"]); 3679 /// // ^~~~~~^~~~~~~~~ flag and debug are overridden by color 3680 /// 3681 /// assert!(m.get_flag("color")); // even though flag conflicts with color, it's as if flag 3682 /// // and debug were never used because they were overridden 3683 /// // with color 3684 /// assert!(!m.get_flag("debug")); 3685 /// assert!(!m.get_flag("flag")); 3686 /// ``` 3687 #[must_use] overrides_with_all(mut self, names: impl IntoIterator<Item = impl Into<Id>>) -> Self3688 pub fn overrides_with_all(mut self, names: impl IntoIterator<Item = impl Into<Id>>) -> Self { 3689 self.overrides.extend(names.into_iter().map(Into::into)); 3690 self 3691 } 3692 } 3693 3694 /// # Reflection 3695 impl Arg { 3696 /// Get the name of the argument 3697 #[inline] get_id(&self) -> &Id3698 pub fn get_id(&self) -> &Id { 3699 &self.id 3700 } 3701 3702 /// Get the help specified for this argument, if any 3703 #[inline] get_help(&self) -> Option<&StyledStr>3704 pub fn get_help(&self) -> Option<&StyledStr> { 3705 self.help.as_ref() 3706 } 3707 3708 /// Get the long help specified for this argument, if any 3709 /// 3710 /// # Examples 3711 /// 3712 /// ```rust 3713 /// # use clap::Arg; 3714 /// let arg = Arg::new("foo").long_help("long help"); 3715 /// assert_eq!(Some("long help".to_owned()), arg.get_long_help().map(|s| s.to_string())); 3716 /// ``` 3717 /// 3718 #[inline] get_long_help(&self) -> Option<&StyledStr>3719 pub fn get_long_help(&self) -> Option<&StyledStr> { 3720 self.long_help.as_ref() 3721 } 3722 3723 /// Get the help heading specified for this argument, if any 3724 #[inline] get_help_heading(&self) -> Option<&str>3725 pub fn get_help_heading(&self) -> Option<&str> { 3726 self.help_heading 3727 .as_ref() 3728 .map(|s| s.as_deref()) 3729 .unwrap_or_default() 3730 } 3731 3732 /// Get the short option name for this argument, if any 3733 #[inline] get_short(&self) -> Option<char>3734 pub fn get_short(&self) -> Option<char> { 3735 self.short 3736 } 3737 3738 /// Get visible short aliases for this argument, if any 3739 #[inline] get_visible_short_aliases(&self) -> Option<Vec<char>>3740 pub fn get_visible_short_aliases(&self) -> Option<Vec<char>> { 3741 if self.short_aliases.is_empty() { 3742 None 3743 } else { 3744 Some( 3745 self.short_aliases 3746 .iter() 3747 .filter_map(|(c, v)| if *v { Some(c) } else { None }) 3748 .copied() 3749 .collect(), 3750 ) 3751 } 3752 } 3753 3754 /// Get *all* short aliases for this argument, if any, both visible and hidden. 3755 #[inline] get_all_short_aliases(&self) -> Option<Vec<char>>3756 pub fn get_all_short_aliases(&self) -> Option<Vec<char>> { 3757 if self.short_aliases.is_empty() { 3758 None 3759 } else { 3760 Some(self.short_aliases.iter().map(|(s, _)| s).copied().collect()) 3761 } 3762 } 3763 3764 /// Get the short option name and its visible aliases, if any 3765 #[inline] get_short_and_visible_aliases(&self) -> Option<Vec<char>>3766 pub fn get_short_and_visible_aliases(&self) -> Option<Vec<char>> { 3767 let mut shorts = match self.short { 3768 Some(short) => vec![short], 3769 None => return None, 3770 }; 3771 if let Some(aliases) = self.get_visible_short_aliases() { 3772 shorts.extend(aliases); 3773 } 3774 Some(shorts) 3775 } 3776 3777 /// Get the long option name for this argument, if any 3778 #[inline] get_long(&self) -> Option<&str>3779 pub fn get_long(&self) -> Option<&str> { 3780 self.long.as_deref() 3781 } 3782 3783 /// Get visible aliases for this argument, if any 3784 #[inline] get_visible_aliases(&self) -> Option<Vec<&str>>3785 pub fn get_visible_aliases(&self) -> Option<Vec<&str>> { 3786 if self.aliases.is_empty() { 3787 None 3788 } else { 3789 Some( 3790 self.aliases 3791 .iter() 3792 .filter_map(|(s, v)| if *v { Some(s.as_str()) } else { None }) 3793 .collect(), 3794 ) 3795 } 3796 } 3797 3798 /// Get *all* aliases for this argument, if any, both visible and hidden. 3799 #[inline] get_all_aliases(&self) -> Option<Vec<&str>>3800 pub fn get_all_aliases(&self) -> Option<Vec<&str>> { 3801 if self.aliases.is_empty() { 3802 None 3803 } else { 3804 Some(self.aliases.iter().map(|(s, _)| s.as_str()).collect()) 3805 } 3806 } 3807 3808 /// Get the long option name and its visible aliases, if any 3809 #[inline] get_long_and_visible_aliases(&self) -> Option<Vec<&str>>3810 pub fn get_long_and_visible_aliases(&self) -> Option<Vec<&str>> { 3811 let mut longs = match self.get_long() { 3812 Some(long) => vec![long], 3813 None => return None, 3814 }; 3815 if let Some(aliases) = self.get_visible_aliases() { 3816 longs.extend(aliases); 3817 } 3818 Some(longs) 3819 } 3820 3821 /// Get the names of possible values for this argument. Only useful for user 3822 /// facing applications, such as building help messages or man files get_possible_values(&self) -> Vec<PossibleValue>3823 pub fn get_possible_values(&self) -> Vec<PossibleValue> { 3824 if !self.is_takes_value_set() { 3825 vec![] 3826 } else { 3827 self.get_value_parser() 3828 .possible_values() 3829 .map(|pvs| pvs.collect()) 3830 .unwrap_or_default() 3831 } 3832 } 3833 3834 /// Get the names of values for this argument. 3835 #[inline] get_value_names(&self) -> Option<&[Str]>3836 pub fn get_value_names(&self) -> Option<&[Str]> { 3837 if self.val_names.is_empty() { 3838 None 3839 } else { 3840 Some(&self.val_names) 3841 } 3842 } 3843 3844 /// Get the number of values for this argument. 3845 #[inline] get_num_args(&self) -> Option<ValueRange>3846 pub fn get_num_args(&self) -> Option<ValueRange> { 3847 self.num_vals 3848 } 3849 3850 #[inline] get_min_vals(&self) -> usize3851 pub(crate) fn get_min_vals(&self) -> usize { 3852 self.get_num_args().expect(INTERNAL_ERROR_MSG).min_values() 3853 } 3854 3855 /// Get the delimiter between multiple values 3856 #[inline] get_value_delimiter(&self) -> Option<char>3857 pub fn get_value_delimiter(&self) -> Option<char> { 3858 self.val_delim 3859 } 3860 3861 /// Get the value terminator for this argument. The value_terminator is a value 3862 /// that terminates parsing of multi-valued arguments. 3863 #[inline] get_value_terminator(&self) -> Option<&Str>3864 pub fn get_value_terminator(&self) -> Option<&Str> { 3865 self.terminator.as_ref() 3866 } 3867 3868 /// Get the index of this argument, if any 3869 #[inline] get_index(&self) -> Option<usize>3870 pub fn get_index(&self) -> Option<usize> { 3871 self.index 3872 } 3873 3874 /// Get the value hint of this argument get_value_hint(&self) -> ValueHint3875 pub fn get_value_hint(&self) -> ValueHint { 3876 self.value_hint.unwrap_or_else(|| { 3877 if self.is_takes_value_set() { 3878 let type_id = self.get_value_parser().type_id(); 3879 if type_id == crate::parser::AnyValueId::of::<std::path::PathBuf>() { 3880 ValueHint::AnyPath 3881 } else { 3882 ValueHint::default() 3883 } 3884 } else { 3885 ValueHint::default() 3886 } 3887 }) 3888 } 3889 3890 /// Get the environment variable name specified for this argument, if any 3891 /// 3892 /// # Examples 3893 /// 3894 /// ```rust 3895 /// # use std::ffi::OsStr; 3896 /// # use clap::Arg; 3897 /// let arg = Arg::new("foo").env("ENVIRONMENT"); 3898 /// assert_eq!(arg.get_env(), Some(OsStr::new("ENVIRONMENT"))); 3899 /// ``` 3900 #[cfg(feature = "env")] get_env(&self) -> Option<&std::ffi::OsStr>3901 pub fn get_env(&self) -> Option<&std::ffi::OsStr> { 3902 self.env.as_ref().map(|x| x.0.as_os_str()) 3903 } 3904 3905 /// Get the default values specified for this argument, if any 3906 /// 3907 /// # Examples 3908 /// 3909 /// ```rust 3910 /// # use clap::Arg; 3911 /// let arg = Arg::new("foo").default_value("default value"); 3912 /// assert_eq!(arg.get_default_values(), &["default value"]); 3913 /// ``` get_default_values(&self) -> &[OsStr]3914 pub fn get_default_values(&self) -> &[OsStr] { 3915 &self.default_vals 3916 } 3917 3918 /// Checks whether this argument is a positional or not. 3919 /// 3920 /// # Examples 3921 /// 3922 /// ``` 3923 /// # use clap::Arg; 3924 /// let arg = Arg::new("foo"); 3925 /// assert_eq!(arg.is_positional(), true); 3926 /// 3927 /// let arg = Arg::new("foo").long("foo"); 3928 /// assert_eq!(arg.is_positional(), false); 3929 /// ``` is_positional(&self) -> bool3930 pub fn is_positional(&self) -> bool { 3931 self.get_long().is_none() && self.get_short().is_none() 3932 } 3933 3934 /// Reports whether [`Arg::required`] is set is_required_set(&self) -> bool3935 pub fn is_required_set(&self) -> bool { 3936 self.is_set(ArgSettings::Required) 3937 } 3938 is_multiple_values_set(&self) -> bool3939 pub(crate) fn is_multiple_values_set(&self) -> bool { 3940 self.get_num_args().unwrap_or_default().is_multiple() 3941 } 3942 is_takes_value_set(&self) -> bool3943 pub(crate) fn is_takes_value_set(&self) -> bool { 3944 self.get_action().takes_values() 3945 } 3946 3947 /// Report whether [`Arg::allow_hyphen_values`] is set is_allow_hyphen_values_set(&self) -> bool3948 pub fn is_allow_hyphen_values_set(&self) -> bool { 3949 self.is_set(ArgSettings::AllowHyphenValues) 3950 } 3951 3952 /// Report whether [`Arg::allow_negative_numbers`] is set is_allow_negative_numbers_set(&self) -> bool3953 pub fn is_allow_negative_numbers_set(&self) -> bool { 3954 self.is_set(ArgSettings::AllowNegativeNumbers) 3955 } 3956 3957 /// Behavior when parsing the argument get_action(&self) -> &super::ArgAction3958 pub fn get_action(&self) -> &super::ArgAction { 3959 const DEFAULT: super::ArgAction = super::ArgAction::Set; 3960 self.action.as_ref().unwrap_or(&DEFAULT) 3961 } 3962 3963 /// Configured parser for argument values 3964 /// 3965 /// # Example 3966 /// 3967 /// ```rust 3968 /// let cmd = clap::Command::new("raw") 3969 /// .arg( 3970 /// clap::Arg::new("port") 3971 /// .value_parser(clap::value_parser!(usize)) 3972 /// ); 3973 /// let value_parser = cmd.get_arguments() 3974 /// .find(|a| a.get_id() == "port").unwrap() 3975 /// .get_value_parser(); 3976 /// println!("{:?}", value_parser); 3977 /// ``` get_value_parser(&self) -> &super::ValueParser3978 pub fn get_value_parser(&self) -> &super::ValueParser { 3979 if let Some(value_parser) = self.value_parser.as_ref() { 3980 value_parser 3981 } else { 3982 static DEFAULT: super::ValueParser = super::ValueParser::string(); 3983 &DEFAULT 3984 } 3985 } 3986 3987 /// Report whether [`Arg::global`] is set is_global_set(&self) -> bool3988 pub fn is_global_set(&self) -> bool { 3989 self.is_set(ArgSettings::Global) 3990 } 3991 3992 /// Report whether [`Arg::next_line_help`] is set is_next_line_help_set(&self) -> bool3993 pub fn is_next_line_help_set(&self) -> bool { 3994 self.is_set(ArgSettings::NextLineHelp) 3995 } 3996 3997 /// Report whether [`Arg::hide`] is set is_hide_set(&self) -> bool3998 pub fn is_hide_set(&self) -> bool { 3999 self.is_set(ArgSettings::Hidden) 4000 } 4001 4002 /// Report whether [`Arg::hide_default_value`] is set is_hide_default_value_set(&self) -> bool4003 pub fn is_hide_default_value_set(&self) -> bool { 4004 self.is_set(ArgSettings::HideDefaultValue) 4005 } 4006 4007 /// Report whether [`Arg::hide_possible_values`] is set is_hide_possible_values_set(&self) -> bool4008 pub fn is_hide_possible_values_set(&self) -> bool { 4009 self.is_set(ArgSettings::HidePossibleValues) 4010 } 4011 4012 /// Report whether [`Arg::hide_env`] is set 4013 #[cfg(feature = "env")] is_hide_env_set(&self) -> bool4014 pub fn is_hide_env_set(&self) -> bool { 4015 self.is_set(ArgSettings::HideEnv) 4016 } 4017 4018 /// Report whether [`Arg::hide_env_values`] is set 4019 #[cfg(feature = "env")] is_hide_env_values_set(&self) -> bool4020 pub fn is_hide_env_values_set(&self) -> bool { 4021 self.is_set(ArgSettings::HideEnvValues) 4022 } 4023 4024 /// Report whether [`Arg::hide_short_help`] is set is_hide_short_help_set(&self) -> bool4025 pub fn is_hide_short_help_set(&self) -> bool { 4026 self.is_set(ArgSettings::HiddenShortHelp) 4027 } 4028 4029 /// Report whether [`Arg::hide_long_help`] is set is_hide_long_help_set(&self) -> bool4030 pub fn is_hide_long_help_set(&self) -> bool { 4031 self.is_set(ArgSettings::HiddenLongHelp) 4032 } 4033 4034 /// Report whether [`Arg::require_equals`] is set is_require_equals_set(&self) -> bool4035 pub fn is_require_equals_set(&self) -> bool { 4036 self.is_set(ArgSettings::RequireEquals) 4037 } 4038 4039 /// Reports whether [`Arg::exclusive`] is set is_exclusive_set(&self) -> bool4040 pub fn is_exclusive_set(&self) -> bool { 4041 self.is_set(ArgSettings::Exclusive) 4042 } 4043 4044 /// Report whether [`Arg::trailing_var_arg`] is set is_trailing_var_arg_set(&self) -> bool4045 pub fn is_trailing_var_arg_set(&self) -> bool { 4046 self.is_set(ArgSettings::TrailingVarArg) 4047 } 4048 4049 /// Reports whether [`Arg::last`] is set is_last_set(&self) -> bool4050 pub fn is_last_set(&self) -> bool { 4051 self.is_set(ArgSettings::Last) 4052 } 4053 4054 /// Reports whether [`Arg::ignore_case`] is set is_ignore_case_set(&self) -> bool4055 pub fn is_ignore_case_set(&self) -> bool { 4056 self.is_set(ArgSettings::IgnoreCase) 4057 } 4058 } 4059 4060 /// # Internally used only 4061 impl Arg { _build(&mut self)4062 pub(crate) fn _build(&mut self) { 4063 if self.action.is_none() { 4064 if self.num_vals == Some(ValueRange::EMPTY) { 4065 let action = super::ArgAction::SetTrue; 4066 self.action = Some(action); 4067 } else { 4068 let action = 4069 if self.is_positional() && self.num_vals.unwrap_or_default().is_unbounded() { 4070 // Allow collecting arguments interleaved with flags 4071 // 4072 // Bounded values are probably a group and the user should explicitly opt-in to 4073 // Append 4074 super::ArgAction::Append 4075 } else { 4076 super::ArgAction::Set 4077 }; 4078 self.action = Some(action); 4079 } 4080 } 4081 if let Some(action) = self.action.as_ref() { 4082 if let Some(default_value) = action.default_value() { 4083 if self.default_vals.is_empty() { 4084 self.default_vals = vec![default_value.into()]; 4085 } 4086 } 4087 if let Some(default_value) = action.default_missing_value() { 4088 if self.default_missing_vals.is_empty() { 4089 self.default_missing_vals = vec![default_value.into()]; 4090 } 4091 } 4092 } 4093 4094 if self.value_parser.is_none() { 4095 if let Some(default) = self.action.as_ref().and_then(|a| a.default_value_parser()) { 4096 self.value_parser = Some(default); 4097 } else { 4098 self.value_parser = Some(super::ValueParser::string()); 4099 } 4100 } 4101 4102 let val_names_len = self.val_names.len(); 4103 if val_names_len > 1 { 4104 self.num_vals.get_or_insert(val_names_len.into()); 4105 } else { 4106 let nargs = if self.get_action().takes_values() { 4107 ValueRange::SINGLE 4108 } else { 4109 ValueRange::EMPTY 4110 }; 4111 self.num_vals.get_or_insert(nargs); 4112 } 4113 } 4114 4115 // Used for positionals when printing name_no_brackets(&self) -> String4116 pub(crate) fn name_no_brackets(&self) -> String { 4117 debug!("Arg::name_no_brackets:{}", self.get_id()); 4118 let delim = " "; 4119 if !self.val_names.is_empty() { 4120 debug!("Arg::name_no_brackets: val_names={:#?}", self.val_names); 4121 4122 if self.val_names.len() > 1 { 4123 self.val_names 4124 .iter() 4125 .map(|n| format!("<{}>", n)) 4126 .collect::<Vec<_>>() 4127 .join(delim) 4128 } else { 4129 self.val_names 4130 .first() 4131 .expect(INTERNAL_ERROR_MSG) 4132 .as_str() 4133 .to_owned() 4134 } 4135 } else { 4136 debug!("Arg::name_no_brackets: just name"); 4137 self.get_id().as_str().to_owned() 4138 } 4139 } 4140 stylized(&self, required: Option<bool>) -> StyledStr4141 pub(crate) fn stylized(&self, required: Option<bool>) -> StyledStr { 4142 let mut styled = StyledStr::new(); 4143 // Write the name such --long or -l 4144 if let Some(l) = self.get_long() { 4145 styled.literal("--"); 4146 styled.literal(l); 4147 } else if let Some(s) = self.get_short() { 4148 styled.literal("-"); 4149 styled.literal(s); 4150 } 4151 styled.extend(self.stylize_arg_suffix(required).into_iter()); 4152 styled 4153 } 4154 stylize_arg_suffix(&self, required: Option<bool>) -> StyledStr4155 pub(crate) fn stylize_arg_suffix(&self, required: Option<bool>) -> StyledStr { 4156 let mut styled = StyledStr::new(); 4157 4158 let mut need_closing_bracket = false; 4159 if self.is_takes_value_set() && !self.is_positional() { 4160 let is_optional_val = self.get_min_vals() == 0; 4161 if self.is_require_equals_set() { 4162 if is_optional_val { 4163 need_closing_bracket = true; 4164 styled.placeholder("[="); 4165 } else { 4166 styled.literal("="); 4167 } 4168 } else if is_optional_val { 4169 need_closing_bracket = true; 4170 styled.placeholder(" ["); 4171 } else { 4172 styled.placeholder(" "); 4173 } 4174 } 4175 if self.is_takes_value_set() || self.is_positional() { 4176 let required = required.unwrap_or_else(|| self.is_required_set()); 4177 let arg_val = self.render_arg_val(required); 4178 styled.placeholder(arg_val); 4179 } else if matches!(*self.get_action(), ArgAction::Count) { 4180 styled.placeholder("..."); 4181 } 4182 if need_closing_bracket { 4183 styled.placeholder("]"); 4184 } 4185 4186 styled 4187 } 4188 4189 /// Write the values such as `<name1> <name2>` render_arg_val(&self, required: bool) -> String4190 fn render_arg_val(&self, required: bool) -> String { 4191 let mut rendered = String::new(); 4192 4193 let num_vals = self.get_num_args().unwrap_or_else(|| 1.into()); 4194 4195 let mut val_names = if self.val_names.is_empty() { 4196 vec![self.id.as_internal_str().to_owned()] 4197 } else { 4198 self.val_names.clone() 4199 }; 4200 if val_names.len() == 1 { 4201 let min = num_vals.min_values().max(1); 4202 let val_name = val_names.pop().unwrap(); 4203 val_names = vec![val_name; min]; 4204 } 4205 4206 debug_assert!(self.is_takes_value_set()); 4207 for (n, val_name) in val_names.iter().enumerate() { 4208 let arg_name = if self.is_positional() && (num_vals.min_values() == 0 || !required) { 4209 format!("[{}]", val_name) 4210 } else { 4211 format!("<{}>", val_name) 4212 }; 4213 4214 if n != 0 { 4215 rendered.push(' '); 4216 } 4217 rendered.push_str(&arg_name); 4218 } 4219 4220 let mut extra_values = false; 4221 extra_values |= val_names.len() < num_vals.max_values(); 4222 if self.is_positional() && matches!(*self.get_action(), ArgAction::Append) { 4223 extra_values = true; 4224 } 4225 if extra_values { 4226 rendered.push_str("..."); 4227 } 4228 4229 rendered 4230 } 4231 4232 /// Either multiple values or occurrences is_multiple(&self) -> bool4233 pub(crate) fn is_multiple(&self) -> bool { 4234 self.is_multiple_values_set() || matches!(*self.get_action(), ArgAction::Append) 4235 } 4236 4237 #[cfg(feature = "help")] get_display_order(&self) -> usize4238 pub(crate) fn get_display_order(&self) -> usize { 4239 self.disp_ord.unwrap_or(999) 4240 } 4241 } 4242 4243 impl From<&'_ Arg> for Arg { from(a: &Arg) -> Self4244 fn from(a: &Arg) -> Self { 4245 a.clone() 4246 } 4247 } 4248 4249 impl PartialEq for Arg { eq(&self, other: &Arg) -> bool4250 fn eq(&self, other: &Arg) -> bool { 4251 self.get_id() == other.get_id() 4252 } 4253 } 4254 4255 impl PartialOrd for Arg { partial_cmp(&self, other: &Self) -> Option<Ordering>4256 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 4257 Some(self.cmp(other)) 4258 } 4259 } 4260 4261 impl Ord for Arg { cmp(&self, other: &Arg) -> Ordering4262 fn cmp(&self, other: &Arg) -> Ordering { 4263 self.get_id().cmp(other.get_id()) 4264 } 4265 } 4266 4267 impl Eq for Arg {} 4268 4269 impl Display for Arg { fmt(&self, f: &mut Formatter) -> fmt::Result4270 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 4271 self.stylized(None).fmt(f) 4272 } 4273 } 4274 4275 impl fmt::Debug for Arg { fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error>4276 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { 4277 let mut ds = f.debug_struct("Arg"); 4278 4279 #[allow(unused_mut)] 4280 let mut ds = ds 4281 .field("id", &self.id) 4282 .field("help", &self.help) 4283 .field("long_help", &self.long_help) 4284 .field("action", &self.action) 4285 .field("value_parser", &self.value_parser) 4286 .field("blacklist", &self.blacklist) 4287 .field("settings", &self.settings) 4288 .field("overrides", &self.overrides) 4289 .field("groups", &self.groups) 4290 .field("requires", &self.requires) 4291 .field("r_ifs", &self.r_ifs) 4292 .field("r_unless", &self.r_unless) 4293 .field("short", &self.short) 4294 .field("long", &self.long) 4295 .field("aliases", &self.aliases) 4296 .field("short_aliases", &self.short_aliases) 4297 .field("disp_ord", &self.disp_ord) 4298 .field("val_names", &self.val_names) 4299 .field("num_vals", &self.num_vals) 4300 .field("val_delim", &self.val_delim) 4301 .field("default_vals", &self.default_vals) 4302 .field("default_vals_ifs", &self.default_vals_ifs) 4303 .field("terminator", &self.terminator) 4304 .field("index", &self.index) 4305 .field("help_heading", &self.help_heading) 4306 .field("value_hint", &self.value_hint) 4307 .field("default_missing_vals", &self.default_missing_vals); 4308 4309 #[cfg(feature = "env")] 4310 { 4311 ds = ds.field("env", &self.env); 4312 } 4313 4314 ds.finish() 4315 } 4316 } 4317 4318 // Flags 4319 #[cfg(test)] 4320 mod test { 4321 use super::Arg; 4322 use super::ArgAction; 4323 4324 #[test] flag_display_long()4325 fn flag_display_long() { 4326 let mut f = Arg::new("flg").long("flag").action(ArgAction::SetTrue); 4327 f._build(); 4328 4329 assert_eq!(f.to_string(), "--flag"); 4330 } 4331 4332 #[test] flag_display_short()4333 fn flag_display_short() { 4334 let mut f2 = Arg::new("flg").short('f').action(ArgAction::SetTrue); 4335 f2._build(); 4336 4337 assert_eq!(f2.to_string(), "-f"); 4338 } 4339 4340 #[test] flag_display_count()4341 fn flag_display_count() { 4342 let mut f2 = Arg::new("flg").long("flag").action(ArgAction::Count); 4343 f2._build(); 4344 4345 assert_eq!(f2.to_string(), "--flag..."); 4346 } 4347 4348 #[test] flag_display_single_alias()4349 fn flag_display_single_alias() { 4350 let mut f = Arg::new("flg") 4351 .long("flag") 4352 .visible_alias("als") 4353 .action(ArgAction::SetTrue); 4354 f._build(); 4355 4356 assert_eq!(f.to_string(), "--flag") 4357 } 4358 4359 #[test] flag_display_multiple_aliases()4360 fn flag_display_multiple_aliases() { 4361 let mut f = Arg::new("flg").short('f').action(ArgAction::SetTrue); 4362 f.aliases = vec![ 4363 ("alias_not_visible".into(), false), 4364 ("f2".into(), true), 4365 ("f3".into(), true), 4366 ("f4".into(), true), 4367 ]; 4368 f._build(); 4369 4370 assert_eq!(f.to_string(), "-f"); 4371 } 4372 4373 #[test] flag_display_single_short_alias()4374 fn flag_display_single_short_alias() { 4375 let mut f = Arg::new("flg").short('a').action(ArgAction::SetTrue); 4376 f.short_aliases = vec![('b', true)]; 4377 f._build(); 4378 4379 assert_eq!(f.to_string(), "-a") 4380 } 4381 4382 #[test] flag_display_multiple_short_aliases()4383 fn flag_display_multiple_short_aliases() { 4384 let mut f = Arg::new("flg").short('a').action(ArgAction::SetTrue); 4385 f.short_aliases = vec![('b', false), ('c', true), ('d', true), ('e', true)]; 4386 f._build(); 4387 4388 assert_eq!(f.to_string(), "-a"); 4389 } 4390 4391 // Options 4392 4393 #[test] option_display_multiple_occurrences()4394 fn option_display_multiple_occurrences() { 4395 let mut o = Arg::new("opt").long("option").action(ArgAction::Append); 4396 o._build(); 4397 4398 assert_eq!(o.to_string(), "--option <opt>"); 4399 } 4400 4401 #[test] option_display_multiple_values()4402 fn option_display_multiple_values() { 4403 let mut o = Arg::new("opt") 4404 .long("option") 4405 .action(ArgAction::Set) 4406 .num_args(1..); 4407 o._build(); 4408 4409 assert_eq!(o.to_string(), "--option <opt>..."); 4410 } 4411 4412 #[test] option_display_zero_or_more_values()4413 fn option_display_zero_or_more_values() { 4414 let mut o = Arg::new("opt") 4415 .long("option") 4416 .action(ArgAction::Set) 4417 .num_args(0..); 4418 o._build(); 4419 4420 assert_eq!(o.to_string(), "--option [<opt>...]"); 4421 } 4422 4423 #[test] option_display_one_or_more_values()4424 fn option_display_one_or_more_values() { 4425 let mut o = Arg::new("opt") 4426 .long("option") 4427 .action(ArgAction::Set) 4428 .num_args(1..); 4429 o._build(); 4430 4431 assert_eq!(o.to_string(), "--option <opt>..."); 4432 } 4433 4434 #[test] option_display_zero_or_more_values_with_value_name()4435 fn option_display_zero_or_more_values_with_value_name() { 4436 let mut o = Arg::new("opt") 4437 .short('o') 4438 .action(ArgAction::Set) 4439 .num_args(0..) 4440 .value_names(["file"]); 4441 o._build(); 4442 4443 assert_eq!(o.to_string(), "-o [<file>...]"); 4444 } 4445 4446 #[test] option_display_one_or_more_values_with_value_name()4447 fn option_display_one_or_more_values_with_value_name() { 4448 let mut o = Arg::new("opt") 4449 .short('o') 4450 .action(ArgAction::Set) 4451 .num_args(1..) 4452 .value_names(["file"]); 4453 o._build(); 4454 4455 assert_eq!(o.to_string(), "-o <file>..."); 4456 } 4457 4458 #[test] option_display_optional_value()4459 fn option_display_optional_value() { 4460 let mut o = Arg::new("opt") 4461 .long("option") 4462 .action(ArgAction::Set) 4463 .num_args(0..=1); 4464 o._build(); 4465 4466 assert_eq!(o.to_string(), "--option [<opt>]"); 4467 } 4468 4469 #[test] option_display_value_names()4470 fn option_display_value_names() { 4471 let mut o = Arg::new("opt") 4472 .short('o') 4473 .action(ArgAction::Set) 4474 .value_names(["file", "name"]); 4475 o._build(); 4476 4477 assert_eq!(o.to_string(), "-o <file> <name>"); 4478 } 4479 4480 #[test] option_display3()4481 fn option_display3() { 4482 let mut o = Arg::new("opt") 4483 .short('o') 4484 .num_args(1..) 4485 .action(ArgAction::Set) 4486 .value_names(["file", "name"]); 4487 o._build(); 4488 4489 assert_eq!(o.to_string(), "-o <file> <name>..."); 4490 } 4491 4492 #[test] option_display_single_alias()4493 fn option_display_single_alias() { 4494 let mut o = Arg::new("opt") 4495 .long("option") 4496 .action(ArgAction::Set) 4497 .visible_alias("als"); 4498 o._build(); 4499 4500 assert_eq!(o.to_string(), "--option <opt>"); 4501 } 4502 4503 #[test] option_display_multiple_aliases()4504 fn option_display_multiple_aliases() { 4505 let mut o = Arg::new("opt") 4506 .long("option") 4507 .action(ArgAction::Set) 4508 .visible_aliases(["als2", "als3", "als4"]) 4509 .alias("als_not_visible"); 4510 o._build(); 4511 4512 assert_eq!(o.to_string(), "--option <opt>"); 4513 } 4514 4515 #[test] option_display_single_short_alias()4516 fn option_display_single_short_alias() { 4517 let mut o = Arg::new("opt") 4518 .short('a') 4519 .action(ArgAction::Set) 4520 .visible_short_alias('b'); 4521 o._build(); 4522 4523 assert_eq!(o.to_string(), "-a <opt>"); 4524 } 4525 4526 #[test] option_display_multiple_short_aliases()4527 fn option_display_multiple_short_aliases() { 4528 let mut o = Arg::new("opt") 4529 .short('a') 4530 .action(ArgAction::Set) 4531 .visible_short_aliases(['b', 'c', 'd']) 4532 .short_alias('e'); 4533 o._build(); 4534 4535 assert_eq!(o.to_string(), "-a <opt>"); 4536 } 4537 4538 // Positionals 4539 4540 #[test] positional_display_multiple_values()4541 fn positional_display_multiple_values() { 4542 let mut p = Arg::new("pos").index(1).num_args(1..); 4543 p._build(); 4544 4545 assert_eq!(p.to_string(), "[pos]..."); 4546 } 4547 4548 #[test] positional_display_multiple_values_required()4549 fn positional_display_multiple_values_required() { 4550 let mut p = Arg::new("pos").index(1).num_args(1..).required(true); 4551 p._build(); 4552 4553 assert_eq!(p.to_string(), "<pos>..."); 4554 } 4555 4556 #[test] positional_display_zero_or_more_values()4557 fn positional_display_zero_or_more_values() { 4558 let mut p = Arg::new("pos").index(1).num_args(0..); 4559 p._build(); 4560 4561 assert_eq!(p.to_string(), "[pos]..."); 4562 } 4563 4564 #[test] positional_display_one_or_more_values()4565 fn positional_display_one_or_more_values() { 4566 let mut p = Arg::new("pos").index(1).num_args(1..); 4567 p._build(); 4568 4569 assert_eq!(p.to_string(), "[pos]..."); 4570 } 4571 4572 #[test] positional_display_one_or_more_values_required()4573 fn positional_display_one_or_more_values_required() { 4574 let mut p = Arg::new("pos").index(1).num_args(1..).required(true); 4575 p._build(); 4576 4577 assert_eq!(p.to_string(), "<pos>..."); 4578 } 4579 4580 #[test] positional_display_optional_value()4581 fn positional_display_optional_value() { 4582 let mut p = Arg::new("pos") 4583 .index(1) 4584 .num_args(0..=1) 4585 .action(ArgAction::Set); 4586 p._build(); 4587 4588 assert_eq!(p.to_string(), "[pos]"); 4589 } 4590 4591 #[test] positional_display_multiple_occurrences()4592 fn positional_display_multiple_occurrences() { 4593 let mut p = Arg::new("pos").index(1).action(ArgAction::Append); 4594 p._build(); 4595 4596 assert_eq!(p.to_string(), "[pos]..."); 4597 } 4598 4599 #[test] positional_display_multiple_occurrences_required()4600 fn positional_display_multiple_occurrences_required() { 4601 let mut p = Arg::new("pos") 4602 .index(1) 4603 .action(ArgAction::Append) 4604 .required(true); 4605 p._build(); 4606 4607 assert_eq!(p.to_string(), "<pos>..."); 4608 } 4609 4610 #[test] positional_display_required()4611 fn positional_display_required() { 4612 let mut p = Arg::new("pos").index(1).required(true); 4613 p._build(); 4614 4615 assert_eq!(p.to_string(), "<pos>"); 4616 } 4617 4618 #[test] positional_display_val_names()4619 fn positional_display_val_names() { 4620 let mut p = Arg::new("pos").index(1).value_names(["file1", "file2"]); 4621 p._build(); 4622 4623 assert_eq!(p.to_string(), "[file1] [file2]"); 4624 } 4625 4626 #[test] positional_display_val_names_required()4627 fn positional_display_val_names_required() { 4628 let mut p = Arg::new("pos") 4629 .index(1) 4630 .value_names(["file1", "file2"]) 4631 .required(true); 4632 p._build(); 4633 4634 assert_eq!(p.to_string(), "<file1> <file2>"); 4635 } 4636 4637 #[test] positional_display_val_names_req()4638 fn positional_display_val_names_req() { 4639 let mut p = Arg::new("pos") 4640 .index(1) 4641 .required(true) 4642 .value_names(["file1", "file2"]); 4643 p._build(); 4644 4645 assert_eq!(p.to_string(), "<file1> <file2>"); 4646 } 4647 } 4648