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