1// Std 2use std::any::Any; 3use std::ffi::{OsStr, OsString}; 4use std::fmt::Debug; 5use std::iter::{Cloned, Flatten, Map}; 6use std::slice::Iter; 7 8// Internal 9#[cfg(debug_assertions)] 10use crate::builder::Str; 11use crate::parser::AnyValue; 12use crate::parser::AnyValueId; 13use crate::parser::MatchedArg; 14use crate::parser::MatchesError; 15use crate::parser::ValueSource; 16use crate::util::FlatMap; 17use crate::util::Id; 18use crate::INTERNAL_ERROR_MSG; 19 20/// Container for parse results. 21/// 22/// Used to get information about the arguments that were supplied to the program at runtime by 23/// the user. New instances of this struct are obtained by using the [`Command::get_matches`] family of 24/// methods. 25/// 26/// # Examples 27/// 28/// ```no_run 29/// # use clap::{Command, Arg, ArgAction}; 30/// # use clap::parser::ValueSource; 31/// let matches = Command::new("MyApp") 32/// .arg(Arg::new("out") 33/// .long("output") 34/// .required(true) 35/// .action(ArgAction::Set) 36/// .default_value("-")) 37/// .arg(Arg::new("cfg") 38/// .short('c') 39/// .action(ArgAction::Set)) 40/// .get_matches(); // builds the instance of ArgMatches 41/// 42/// // to get information about the "cfg" argument we created, such as the value supplied we use 43/// // various ArgMatches methods, such as [ArgMatches::get_one] 44/// if let Some(c) = matches.get_one::<String>("cfg") { 45/// println!("Value for -c: {}", c); 46/// } 47/// 48/// // The ArgMatches::get_one method returns an Option because the user may not have supplied 49/// // that argument at runtime. But if we specified that the argument was "required" as we did 50/// // with the "out" argument, we can safely unwrap because `clap` verifies that was actually 51/// // used at runtime. 52/// println!("Value for --output: {}", matches.get_one::<String>("out").unwrap()); 53/// 54/// // You can check the presence of an argument's values 55/// if matches.contains_id("out") { 56/// // However, if you want to know where the value came from 57/// if matches.value_source("out").expect("checked contains_id") == ValueSource::CommandLine { 58/// println!("`out` set by user"); 59/// } else { 60/// println!("`out` is defaulted"); 61/// } 62/// } 63/// ``` 64/// [`Command::get_matches`]: crate::Command::get_matches() 65#[derive(Debug, Clone, Default, PartialEq, Eq)] 66pub struct ArgMatches { 67 #[cfg(debug_assertions)] 68 pub(crate) valid_args: Vec<Id>, 69 #[cfg(debug_assertions)] 70 pub(crate) valid_subcommands: Vec<Str>, 71 pub(crate) args: FlatMap<Id, MatchedArg>, 72 pub(crate) subcommand: Option<Box<SubCommand>>, 73} 74 75/// # Arguments 76impl ArgMatches { 77 /// Gets the value of a specific option or positional argument. 78 /// 79 /// i.e. an argument that [takes an additional value][crate::Arg::num_args] at runtime. 80 /// 81 /// Returns an error if the wrong type was used. 82 /// 83 /// Returns `None` if the option wasn't present. 84 /// 85 /// *NOTE:* This will always return `Some(value)` if [`default_value`] has been set. 86 /// [`ArgMatches::value_source`] can be used to check if a value is present at runtime. 87 /// 88 /// # Panic 89 /// 90 /// If the argument definition and access mismatch. To handle this case programmatically, see 91 /// [`ArgMatches::try_get_one`]. 92 /// 93 /// # Examples 94 /// 95 /// ```rust 96 /// # use clap::{Command, Arg, value_parser, ArgAction}; 97 /// let m = Command::new("myapp") 98 /// .arg(Arg::new("port") 99 /// .value_parser(value_parser!(usize)) 100 /// .action(ArgAction::Set) 101 /// .required(true)) 102 /// .get_matches_from(vec!["myapp", "2020"]); 103 /// 104 /// let port: usize = *m 105 /// .get_one("port") 106 /// .expect("`port`is required"); 107 /// assert_eq!(port, 2020); 108 /// ``` 109 /// [positional]: crate::Arg::index() 110 /// [`default_value`]: crate::Arg::default_value() 111 #[cfg_attr(debug_assertions, track_caller)] 112 pub fn get_one<T: Any + Clone + Send + Sync + 'static>(&self, id: &str) -> Option<&T> { 113 MatchesError::unwrap(id, self.try_get_one(id)) 114 } 115 116 /// Gets the value of a specific [`ArgAction::Count`][crate::ArgAction::Count] flag 117 /// 118 /// # Panic 119 /// 120 /// If the argument's action is not [`ArgAction::Count`][crate::ArgAction::Count] 121 /// 122 /// # Examples 123 /// 124 /// ```rust 125 /// # use clap::Command; 126 /// # use clap::Arg; 127 /// let cmd = Command::new("mycmd") 128 /// .arg( 129 /// Arg::new("flag") 130 /// .long("flag") 131 /// .action(clap::ArgAction::Count) 132 /// ); 133 /// 134 /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag", "--flag"]).unwrap(); 135 /// assert_eq!( 136 /// matches.get_count("flag"), 137 /// 2 138 /// ); 139 /// ``` 140 #[cfg_attr(debug_assertions, track_caller)] 141 pub fn get_count(&self, id: &str) -> u8 { 142 *self.get_one::<u8>(id).unwrap_or_else(|| { 143 panic!( 144 "arg `{}`'s `ArgAction` should be `Count` which should provide a default", 145 id 146 ) 147 }) 148 } 149 150 /// Gets the value of a specific [`ArgAction::SetTrue`][crate::ArgAction::SetTrue] or [`ArgAction::SetFalse`][crate::ArgAction::SetFalse] flag 151 /// 152 /// # Panic 153 /// 154 /// If the argument's action is not [`ArgAction::SetTrue`][crate::ArgAction::SetTrue] or [`ArgAction::SetFalse`][crate::ArgAction::SetFalse] 155 /// 156 /// # Examples 157 /// 158 /// ```rust 159 /// # use clap::Command; 160 /// # use clap::Arg; 161 /// let cmd = Command::new("mycmd") 162 /// .arg( 163 /// Arg::new("flag") 164 /// .long("flag") 165 /// .action(clap::ArgAction::SetTrue) 166 /// ); 167 /// 168 /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap(); 169 /// assert!(matches.contains_id("flag")); 170 /// assert_eq!( 171 /// matches.get_flag("flag"), 172 /// true 173 /// ); 174 /// ``` 175 #[cfg_attr(debug_assertions, track_caller)] 176 pub fn get_flag(&self, id: &str) -> bool { 177 *self 178 .get_one::<bool>(id) 179 .unwrap_or_else(|| { 180 panic!( 181 "arg `{}`'s `ArgAction` should be one of `SetTrue`, `SetFalse` which should provide a default", 182 id 183 ) 184 }) 185 } 186 187 /// Iterate over values of a specific option or positional argument. 188 /// 189 /// i.e. an argument that takes multiple values at runtime. 190 /// 191 /// Returns an error if the wrong type was used. 192 /// 193 /// Returns `None` if the option wasn't present. 194 /// 195 /// # Panic 196 /// 197 /// If the argument definition and access mismatch. To handle this case programmatically, see 198 /// [`ArgMatches::try_get_many`]. 199 /// 200 /// # Examples 201 /// 202 /// ```rust 203 /// # use clap::{Command, Arg, value_parser, ArgAction}; 204 /// let m = Command::new("myprog") 205 /// .arg(Arg::new("ports") 206 /// .action(ArgAction::Append) 207 /// .value_parser(value_parser!(usize)) 208 /// .short('p') 209 /// .required(true)) 210 /// .get_matches_from(vec![ 211 /// "myprog", "-p", "22", "-p", "80", "-p", "2020" 212 /// ]); 213 /// let vals: Vec<usize> = m.get_many("ports") 214 /// .expect("`port`is required") 215 /// .copied() 216 /// .collect(); 217 /// assert_eq!(vals, [22, 80, 2020]); 218 /// ``` 219 #[cfg_attr(debug_assertions, track_caller)] 220 pub fn get_many<T: Any + Clone + Send + Sync + 'static>( 221 &self, 222 id: &str, 223 ) -> Option<ValuesRef<T>> { 224 MatchesError::unwrap(id, self.try_get_many(id)) 225 } 226 227 /// Iterate over the values passed to each occurrence of an option. 228 /// 229 /// Each item is itself an iterator containing the arguments passed to a single occurrence 230 /// of the option. 231 /// 232 /// If the option doesn't support multiple occurrences, or there was only a single occurrence, 233 /// the iterator will only contain a single item. 234 /// 235 /// Returns `None` if the option wasn't present. 236 /// 237 /// # Panics 238 /// 239 /// If the argument definition and access mismatch. To handle this case programmatically, see 240 /// [`ArgMatches::try_get_occurrences`]. 241 /// 242 /// # Examples 243 /// ```rust 244 /// # use clap::{Command,Arg, ArgAction, value_parser}; 245 /// let m = Command::new("myprog") 246 /// .arg(Arg::new("x") 247 /// .short('x') 248 /// .num_args(2) 249 /// .action(ArgAction::Append) 250 /// .value_parser(value_parser!(String))) 251 /// .get_matches_from(vec![ 252 /// "myprog", "-x", "a", "b", "-x", "c", "d"]); 253 /// let vals: Vec<Vec<&String>> = m.get_occurrences("x").unwrap().map(Iterator::collect).collect(); 254 /// assert_eq!(vals, [["a", "b"], ["c", "d"]]); 255 /// ``` 256 #[cfg_attr(debug_assertions, track_caller)] 257 pub fn get_occurrences<T: Any + Clone + Send + Sync + 'static>( 258 &self, 259 id: &str, 260 ) -> Option<OccurrencesRef<T>> { 261 MatchesError::unwrap(id, self.try_get_occurrences(id)) 262 } 263 264 /// Iterate over the original argument values. 265 /// 266 /// An `OsStr` on Unix-like systems is any series of bytes, regardless of whether or not they 267 /// contain valid UTF-8. Since [`String`]s in Rust are guaranteed to be valid UTF-8, a valid 268 /// filename on a Unix system as an argument value may contain invalid UTF-8. 269 /// 270 /// Returns `None` if the option wasn't present. 271 /// 272 /// # Panic 273 /// 274 /// If the argument definition and access mismatch. To handle this case programmatically, see 275 /// [`ArgMatches::try_get_raw`]. 276 /// 277 /// # Examples 278 /// 279 #[cfg_attr(not(unix), doc = " ```ignore")] 280 #[cfg_attr(unix, doc = " ```")] 281 /// # use clap::{Command, arg, value_parser}; 282 /// # use std::ffi::{OsStr,OsString}; 283 /// # use std::os::unix::ffi::{OsStrExt,OsStringExt}; 284 /// use std::path::PathBuf; 285 /// 286 /// let m = Command::new("utf8") 287 /// .arg(arg!(<arg> ... "some arg").value_parser(value_parser!(PathBuf))) 288 /// .get_matches_from(vec![OsString::from("myprog"), 289 /// // "Hi" 290 /// OsString::from_vec(vec![b'H', b'i']), 291 /// // "{0xe9}!" 292 /// OsString::from_vec(vec![0xe9, b'!'])]); 293 /// 294 /// let mut itr = m.get_raw("arg") 295 /// .expect("`port`is required") 296 /// .into_iter(); 297 /// assert_eq!(itr.next(), Some(OsStr::new("Hi"))); 298 /// assert_eq!(itr.next(), Some(OsStr::from_bytes(&[0xe9, b'!']))); 299 /// assert_eq!(itr.next(), None); 300 /// ``` 301 /// [`Iterator`]: std::iter::Iterator 302 /// [`OsSt`]: std::ffi::OsStr 303 /// [values]: OsValues 304 /// [`String`]: std::string::String 305 #[cfg_attr(debug_assertions, track_caller)] 306 pub fn get_raw(&self, id: &str) -> Option<RawValues<'_>> { 307 MatchesError::unwrap(id, self.try_get_raw(id)) 308 } 309 310 /// Iterate over the original values for each occurrence of an option. 311 /// 312 /// Similar to [`ArgMatches::get_occurrences`] but returns raw values. 313 /// 314 /// An `OsStr` on Unix-like systems is any series of bytes, regardless of whether or not they 315 /// contain valid UTF-8. Since [`String`]s in Rust are guaranteed to be valid UTF-8, a valid 316 /// filename on a Unix system as an argument value may contain invalid UTF-8. 317 /// 318 /// Returns `None` if the option wasn't present. 319 /// 320 /// # Panic 321 /// 322 /// If the argument definition and access mismatch. To handle this case programmatically, see 323 /// [`ArgMatches::try_get_raw_occurrences`]. 324 /// 325 /// # Examples 326 /// 327 #[cfg_attr(not(unix), doc = " ```ignore")] 328 #[cfg_attr(unix, doc = " ```")] 329 /// # use clap::{Command, arg, value_parser, ArgAction, Arg}; 330 /// # use std::ffi::{OsStr,OsString}; 331 /// # use std::os::unix::ffi::{OsStrExt,OsStringExt}; 332 /// use std::path::PathBuf; 333 /// 334 /// let m = Command::new("myprog") 335 /// .arg(Arg::new("x") 336 /// .short('x') 337 /// .num_args(2) 338 /// .action(ArgAction::Append) 339 /// .value_parser(value_parser!(PathBuf))) 340 /// .get_matches_from(vec![OsString::from("myprog"), 341 /// OsString::from("-x"), 342 /// OsString::from("a"), OsString::from("b"), 343 /// OsString::from("-x"), 344 /// OsString::from("c"), 345 /// // "{0xe9}!" 346 /// OsString::from_vec(vec![0xe9, b'!'])]); 347 /// let mut itr = m.get_raw_occurrences("x") 348 /// .expect("`-x`is required") 349 /// .map(Iterator::collect::<Vec<_>>); 350 /// assert_eq!(itr.next(), Some(vec![OsStr::new("a"), OsStr::new("b")])); 351 /// assert_eq!(itr.next(), Some(vec![OsStr::new("c"), OsStr::from_bytes(&[0xe9, b'!'])])); 352 /// assert_eq!(itr.next(), None); 353 /// ``` 354 /// [`Iterator`]: std::iter::Iterator 355 /// [`OsStr`]: std::ffi::OsStr 356 /// [values]: OsValues 357 /// [`String`]: std::string::String 358 #[cfg_attr(debug_assertions, track_caller)] 359 pub fn get_raw_occurrences(&self, id: &str) -> Option<RawOccurrences<'_>> { 360 MatchesError::unwrap(id, self.try_get_raw_occurrences(id)) 361 } 362 363 /// Returns the value of a specific option or positional argument. 364 /// 365 /// i.e. an argument that [takes an additional value][crate::Arg::num_args] at runtime. 366 /// 367 /// Returns an error if the wrong type was used. No item will have been removed. 368 /// 369 /// Returns `None` if the option wasn't present. 370 /// 371 /// *NOTE:* This will always return `Some(value)` if [`default_value`] has been set. 372 /// [`ArgMatches::value_source`] can be used to check if a value is present at runtime. 373 /// 374 /// # Panic 375 /// 376 /// If the argument definition and access mismatch. To handle this case programmatically, see 377 /// [`ArgMatches::try_remove_one`]. 378 /// 379 /// # Examples 380 /// 381 /// ```rust 382 /// # use clap::{Command, Arg, value_parser, ArgAction}; 383 /// let mut m = Command::new("myprog") 384 /// .arg(Arg::new("file") 385 /// .required(true) 386 /// .action(ArgAction::Set)) 387 /// .get_matches_from(vec![ 388 /// "myprog", "file.txt", 389 /// ]); 390 /// let vals: String = m.remove_one("file") 391 /// .expect("`file`is required"); 392 /// assert_eq!(vals, "file.txt"); 393 /// ``` 394 /// [positional]: crate::Arg::index() 395 /// [`default_value`]: crate::Arg::default_value() 396 #[cfg_attr(debug_assertions, track_caller)] 397 pub fn remove_one<T: Any + Clone + Send + Sync + 'static>(&mut self, id: &str) -> Option<T> { 398 MatchesError::unwrap(id, self.try_remove_one(id)) 399 } 400 401 /// Return values of a specific option or positional argument. 402 /// 403 /// i.e. an argument that takes multiple values at runtime. 404 /// 405 /// Returns an error if the wrong type was used. No item will have been removed. 406 /// 407 /// Returns `None` if the option wasn't present. 408 /// 409 /// # Panic 410 /// 411 /// If the argument definition and access mismatch. To handle this case programmatically, see 412 /// [`ArgMatches::try_remove_many`]. 413 /// 414 /// # Examples 415 /// 416 /// ```rust 417 /// # use clap::{Command, Arg, value_parser, ArgAction}; 418 /// let mut m = Command::new("myprog") 419 /// .arg(Arg::new("file") 420 /// .action(ArgAction::Append) 421 /// .num_args(1..) 422 /// .required(true)) 423 /// .get_matches_from(vec![ 424 /// "myprog", "file1.txt", "file2.txt", "file3.txt", "file4.txt", 425 /// ]); 426 /// let vals: Vec<String> = m.remove_many("file") 427 /// .expect("`file`is required") 428 /// .collect(); 429 /// assert_eq!(vals, ["file1.txt", "file2.txt", "file3.txt", "file4.txt"]); 430 /// ``` 431 #[cfg_attr(debug_assertions, track_caller)] 432 pub fn remove_many<T: Any + Clone + Send + Sync + 'static>( 433 &mut self, 434 id: &str, 435 ) -> Option<Values<T>> { 436 MatchesError::unwrap(id, self.try_remove_many(id)) 437 } 438 439 /// Return values for each occurrence of an option. 440 /// 441 /// Each item is itself an iterator containing the arguments passed to a single occurrence of 442 /// the option. 443 /// 444 /// If the option doesn't support multiple occurrences, or there was only a single occurrence, 445 /// the iterator will only contain a single item. 446 /// 447 /// Returns `None` if the option wasn't present. 448 /// 449 /// # Panic 450 /// 451 /// If the argument definition and access mismatch. To handle this case programmatically, see 452 /// [`ArgMatches::try_remove_occurrences`]. 453 /// 454 /// # Examples 455 /// 456 /// ```rust 457 /// # use clap::{Command, Arg, value_parser, ArgAction}; 458 /// let mut m = Command::new("myprog") 459 /// .arg(Arg::new("x") 460 /// .short('x') 461 /// .num_args(2) 462 /// .action(ArgAction::Append) 463 /// .value_parser(value_parser!(String))) 464 /// .get_matches_from(vec![ 465 /// "myprog", "-x", "a", "b", "-x", "c", "d"]); 466 /// let vals: Vec<Vec<String>> = m.remove_occurrences("x").unwrap().map(Iterator::collect).collect(); 467 /// assert_eq!(vals, [["a", "b"], ["c", "d"]]); 468 /// ``` 469 #[cfg_attr(debug_assertions, track_caller)] 470 pub fn remove_occurrences<T: Any + Clone + Send + Sync + 'static>( 471 &mut self, 472 id: &str, 473 ) -> Option<Occurrences<T>> { 474 MatchesError::unwrap(id, self.try_remove_occurrences(id)) 475 } 476 477 /// Check if values are present for the argument or group id 478 /// 479 /// *NOTE:* This will always return `true` if [`default_value`] has been set. 480 /// [`ArgMatches::value_source`] can be used to check if a value is present at runtime. 481 /// 482 /// # Panics 483 /// 484 /// If `id` is not a valid argument or group name. To handle this case programmatically, see 485 /// [`ArgMatches::try_contains_id`]. 486 /// 487 /// # Examples 488 /// 489 /// ```rust 490 /// # use clap::{Command, Arg, ArgAction}; 491 /// let m = Command::new("myprog") 492 /// .arg(Arg::new("debug") 493 /// .short('d') 494 /// .action(ArgAction::SetTrue)) 495 /// .get_matches_from(vec![ 496 /// "myprog", "-d" 497 /// ]); 498 /// 499 /// assert!(m.contains_id("debug")); 500 /// ``` 501 /// 502 /// [`default_value`]: crate::Arg::default_value() 503 pub fn contains_id(&self, id: &str) -> bool { 504 MatchesError::unwrap(id, self.try_contains_id(id)) 505 } 506 507 /// Iterate over [`Arg`][crate::Arg] and [`ArgGroup`][crate::ArgGroup] [`Id`][crate::Id]s via [`ArgMatches::ids`]. 508 /// 509 /// # Examples 510 /// 511 /// ``` 512 /// # use clap::{Command, arg, value_parser}; 513 /// 514 /// let m = Command::new("myprog") 515 /// .arg(arg!(--color <when>) 516 /// .value_parser(["auto", "always", "never"])) 517 /// .arg(arg!(--config <path>) 518 /// .value_parser(value_parser!(std::path::PathBuf))) 519 /// .get_matches_from(["myprog", "--config=config.toml", "--color=auto"]); 520 /// assert_eq!(m.ids().len(), 2); 521 /// assert_eq!( 522 /// m.ids() 523 /// .map(|id| id.as_str()) 524 /// .collect::<Vec<_>>(), 525 /// ["config", "color"] 526 /// ); 527 /// ``` 528 pub fn ids(&self) -> IdsRef<'_> { 529 IdsRef { 530 iter: self.args.keys(), 531 } 532 } 533 534 /// Check if any args were present on the command line 535 /// 536 /// # Examples 537 /// 538 /// ```rust 539 /// # use clap::{Command, Arg, ArgAction}; 540 /// let mut cmd = Command::new("myapp") 541 /// .arg(Arg::new("output") 542 /// .action(ArgAction::Set)); 543 /// 544 /// let m = cmd 545 /// .try_get_matches_from_mut(vec!["myapp", "something"]) 546 /// .unwrap(); 547 /// assert!(m.args_present()); 548 /// 549 /// let m = cmd 550 /// .try_get_matches_from_mut(vec!["myapp"]) 551 /// .unwrap(); 552 /// assert!(! m.args_present()); 553 pub fn args_present(&self) -> bool { 554 !self.args.is_empty() 555 } 556 557 /// Get an [`Iterator`] over groups of values of a specific option. 558 /// 559 /// specifically grouped by the occurrences of the options. 560 /// 561 /// Each group is a `Vec<&str>` containing the arguments passed to a single occurrence 562 /// of the option. 563 /// 564 /// If the option doesn't support multiple occurrences, or there was only a single occurrence, 565 /// the iterator will only contain a single item. 566 /// 567 /// Returns `None` if the option wasn't present. 568 /// 569 /// # Panics 570 /// 571 /// If the value is invalid UTF-8. 572 /// 573 /// If `id` is not a valid argument or group id. 574 /// 575 /// # Examples 576 /// ```rust 577 /// # use clap::{Command,Arg, ArgAction}; 578 /// let m = Command::new("myprog") 579 /// .arg(Arg::new("exec") 580 /// .short('x') 581 /// .num_args(1..) 582 /// .action(ArgAction::Append) 583 /// .value_terminator(";")) 584 /// .get_matches_from(vec![ 585 /// "myprog", "-x", "echo", "hi", ";", "-x", "echo", "bye"]); 586 /// let vals: Vec<Vec<&str>> = m.grouped_values_of("exec").unwrap().collect(); 587 /// assert_eq!(vals, [["echo", "hi"], ["echo", "bye"]]); 588 /// ``` 589 /// [`Iterator`]: std::iter::Iterator 590 #[cfg(feature = "unstable-grouped")] 591 #[cfg_attr(debug_assertions, track_caller)] 592 #[deprecated( 593 since = "4.1.0", 594 note = "Use get_occurrences or remove_occurrences instead" 595 )] 596 #[allow(deprecated)] 597 pub fn grouped_values_of(&self, id: &str) -> Option<GroupedValues> { 598 let arg = some!(self.get_arg(id)); 599 let v = GroupedValues { 600 iter: arg.vals().map(|g| g.iter().map(unwrap_string).collect()), 601 len: arg.vals().len(), 602 }; 603 Some(v) 604 } 605 606 /// Report where argument value came from 607 /// 608 /// # Panics 609 /// 610 /// If `id` is not a valid argument or group id. 611 /// 612 /// # Examples 613 /// 614 /// ```rust 615 /// # use clap::{Command, Arg, ArgAction}; 616 /// # use clap::parser::ValueSource; 617 /// let m = Command::new("myprog") 618 /// .arg(Arg::new("debug") 619 /// .short('d') 620 /// .action(ArgAction::SetTrue)) 621 /// .get_matches_from(vec![ 622 /// "myprog", "-d" 623 /// ]); 624 /// 625 /// assert_eq!(m.value_source("debug"), Some(ValueSource::CommandLine)); 626 /// ``` 627 /// 628 /// [`default_value`]: crate::Arg::default_value() 629 #[cfg_attr(debug_assertions, track_caller)] 630 pub fn value_source(&self, id: &str) -> Option<ValueSource> { 631 let value = self.get_arg(id); 632 633 value.and_then(MatchedArg::source) 634 } 635 636 /// The first index of that an argument showed up. 637 /// 638 /// Indices are similar to argv indices, but are not exactly 1:1. 639 /// 640 /// For flags (i.e. those arguments which don't have an associated value), indices refer 641 /// to occurrence of the switch, such as `-f`, or `--flag`. However, for options the indices 642 /// refer to the *values* `-o val` would therefore not represent two distinct indices, only the 643 /// index for `val` would be recorded. This is by design. 644 /// 645 /// Besides the flag/option discrepancy, the primary difference between an argv index and clap 646 /// index, is that clap continues counting once all arguments have properly separated, whereas 647 /// an argv index does not. 648 /// 649 /// The examples should clear this up. 650 /// 651 /// *NOTE:* If an argument is allowed multiple times, this method will only give the *first* 652 /// index. See [`ArgMatches::indices_of`]. 653 /// 654 /// # Panics 655 /// 656 /// If `id` is not a valid argument or group id. 657 /// 658 /// # Examples 659 /// 660 /// The argv indices are listed in the comments below. See how they correspond to the clap 661 /// indices. Note that if it's not listed in a clap index, this is because it's not saved in 662 /// in an `ArgMatches` struct for querying. 663 /// 664 /// ```rust 665 /// # use clap::{Command, Arg, ArgAction}; 666 /// let m = Command::new("myapp") 667 /// .arg(Arg::new("flag") 668 /// .short('f') 669 /// .action(ArgAction::SetTrue)) 670 /// .arg(Arg::new("option") 671 /// .short('o') 672 /// .action(ArgAction::Set)) 673 /// .get_matches_from(vec!["myapp", "-f", "-o", "val"]); 674 /// // ARGV indices: ^0 ^1 ^2 ^3 675 /// // clap indices: ^1 ^3 676 /// 677 /// assert_eq!(m.index_of("flag"), Some(1)); 678 /// assert_eq!(m.index_of("option"), Some(3)); 679 /// ``` 680 /// 681 /// Now notice, if we use one of the other styles of options: 682 /// 683 /// ```rust 684 /// # use clap::{Command, Arg, ArgAction}; 685 /// let m = Command::new("myapp") 686 /// .arg(Arg::new("flag") 687 /// .short('f') 688 /// .action(ArgAction::SetTrue)) 689 /// .arg(Arg::new("option") 690 /// .short('o') 691 /// .action(ArgAction::Set)) 692 /// .get_matches_from(vec!["myapp", "-f", "-o=val"]); 693 /// // ARGV indices: ^0 ^1 ^2 694 /// // clap indices: ^1 ^3 695 /// 696 /// assert_eq!(m.index_of("flag"), Some(1)); 697 /// assert_eq!(m.index_of("option"), Some(3)); 698 /// ``` 699 /// 700 /// Things become much more complicated, or clear if we look at a more complex combination of 701 /// flags. Let's also throw in the final option style for good measure. 702 /// 703 /// ```rust 704 /// # use clap::{Command, Arg, ArgAction}; 705 /// let m = Command::new("myapp") 706 /// .arg(Arg::new("flag") 707 /// .short('f') 708 /// .action(ArgAction::SetTrue)) 709 /// .arg(Arg::new("flag2") 710 /// .short('F') 711 /// .action(ArgAction::SetTrue)) 712 /// .arg(Arg::new("flag3") 713 /// .short('z') 714 /// .action(ArgAction::SetTrue)) 715 /// .arg(Arg::new("option") 716 /// .short('o') 717 /// .action(ArgAction::Set)) 718 /// .get_matches_from(vec!["myapp", "-fzF", "-oval"]); 719 /// // ARGV indices: ^0 ^1 ^2 720 /// // clap indices: ^1,2,3 ^5 721 /// // 722 /// // clap sees the above as 'myapp -f -z -F -o val' 723 /// // ^0 ^1 ^2 ^3 ^4 ^5 724 /// assert_eq!(m.index_of("flag"), Some(1)); 725 /// assert_eq!(m.index_of("flag2"), Some(3)); 726 /// assert_eq!(m.index_of("flag3"), Some(2)); 727 /// assert_eq!(m.index_of("option"), Some(5)); 728 /// ``` 729 /// 730 /// One final combination of flags/options to see how they combine: 731 /// 732 /// ```rust 733 /// # use clap::{Command, Arg, ArgAction}; 734 /// let m = Command::new("myapp") 735 /// .arg(Arg::new("flag") 736 /// .short('f') 737 /// .action(ArgAction::SetTrue)) 738 /// .arg(Arg::new("flag2") 739 /// .short('F') 740 /// .action(ArgAction::SetTrue)) 741 /// .arg(Arg::new("flag3") 742 /// .short('z') 743 /// .action(ArgAction::SetTrue)) 744 /// .arg(Arg::new("option") 745 /// .short('o') 746 /// .action(ArgAction::Set)) 747 /// .get_matches_from(vec!["myapp", "-fzFoval"]); 748 /// // ARGV indices: ^0 ^1 749 /// // clap indices: ^1,2,3^5 750 /// // 751 /// // clap sees the above as 'myapp -f -z -F -o val' 752 /// // ^0 ^1 ^2 ^3 ^4 ^5 753 /// assert_eq!(m.index_of("flag"), Some(1)); 754 /// assert_eq!(m.index_of("flag2"), Some(3)); 755 /// assert_eq!(m.index_of("flag3"), Some(2)); 756 /// assert_eq!(m.index_of("option"), Some(5)); 757 /// ``` 758 /// 759 /// The last part to mention is when values are sent in multiple groups with a [delimiter]. 760 /// 761 /// ```rust 762 /// # use clap::{Command, Arg}; 763 /// let m = Command::new("myapp") 764 /// .arg(Arg::new("option") 765 /// .short('o') 766 /// .value_delimiter(',') 767 /// .num_args(1..)) 768 /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); 769 /// // ARGV indices: ^0 ^1 770 /// // clap indices: ^2 ^3 ^4 771 /// // 772 /// // clap sees the above as 'myapp -o val1 val2 val3' 773 /// // ^0 ^1 ^2 ^3 ^4 774 /// assert_eq!(m.index_of("option"), Some(2)); 775 /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 3, 4]); 776 /// ``` 777 /// [delimiter]: crate::Arg::value_delimiter() 778 #[cfg_attr(debug_assertions, track_caller)] 779 pub fn index_of(&self, id: &str) -> Option<usize> { 780 let arg = some!(self.get_arg(id)); 781 let i = some!(arg.get_index(0)); 782 Some(i) 783 } 784 785 /// All indices an argument appeared at when parsing. 786 /// 787 /// Indices are similar to argv indices, but are not exactly 1:1. 788 /// 789 /// For flags (i.e. those arguments which don't have an associated value), indices refer 790 /// to occurrence of the switch, such as `-f`, or `--flag`. However, for options the indices 791 /// refer to the *values* `-o val` would therefore not represent two distinct indices, only the 792 /// index for `val` would be recorded. This is by design. 793 /// 794 /// *NOTE:* For more information about how clap indices compared to argv indices, see 795 /// [`ArgMatches::index_of`] 796 /// 797 /// # Panics 798 /// 799 /// If `id` is not a valid argument or group id. 800 /// 801 /// # Examples 802 /// 803 /// ```rust 804 /// # use clap::{Command, Arg}; 805 /// let m = Command::new("myapp") 806 /// .arg(Arg::new("option") 807 /// .short('o') 808 /// .value_delimiter(',')) 809 /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); 810 /// // ARGV indices: ^0 ^1 811 /// // clap indices: ^2 ^3 ^4 812 /// // 813 /// // clap sees the above as 'myapp -o val1 val2 val3' 814 /// // ^0 ^1 ^2 ^3 ^4 815 /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 3, 4]); 816 /// ``` 817 /// 818 /// Another quick example is when flags and options are used together 819 /// 820 /// ```rust 821 /// # use clap::{Command, Arg, ArgAction}; 822 /// let m = Command::new("myapp") 823 /// .arg(Arg::new("option") 824 /// .short('o') 825 /// .action(ArgAction::Set) 826 /// .action(ArgAction::Append)) 827 /// .arg(Arg::new("flag") 828 /// .short('f') 829 /// .action(ArgAction::Count)) 830 /// .get_matches_from(vec!["myapp", "-o", "val1", "-f", "-o", "val2", "-f"]); 831 /// // ARGV indices: ^0 ^1 ^2 ^3 ^4 ^5 ^6 832 /// // clap indices: ^2 ^3 ^5 ^6 833 /// 834 /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 5]); 835 /// assert_eq!(m.indices_of("flag").unwrap().collect::<Vec<_>>(), &[6]); 836 /// ``` 837 /// 838 /// One final example, which is an odd case; if we *don't* use value delimiter as we did with 839 /// the first example above instead of `val1`, `val2` and `val3` all being distinc values, they 840 /// would all be a single value of `val1,val2,val3`, in which case they'd only receive a single 841 /// index. 842 /// 843 /// ```rust 844 /// # use clap::{Command, Arg, ArgAction}; 845 /// let m = Command::new("myapp") 846 /// .arg(Arg::new("option") 847 /// .short('o') 848 /// .action(ArgAction::Set) 849 /// .num_args(1..)) 850 /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); 851 /// // ARGV indices: ^0 ^1 852 /// // clap indices: ^2 853 /// // 854 /// // clap sees the above as 'myapp -o "val1,val2,val3"' 855 /// // ^0 ^1 ^2 856 /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2]); 857 /// ``` 858 /// [`ArgMatches::index_of`]: ArgMatches::index_of() 859 /// [delimiter]: Arg::value_delimiter() 860 #[cfg_attr(debug_assertions, track_caller)] 861 pub fn indices_of(&self, id: &str) -> Option<Indices<'_>> { 862 let arg = some!(self.get_arg(id)); 863 let i = Indices { 864 iter: arg.indices(), 865 len: arg.num_vals(), 866 }; 867 Some(i) 868 } 869} 870 871/// # Subcommands 872impl ArgMatches { 873 /// The name and `ArgMatches` of the current [subcommand]. 874 /// 875 /// Subcommand values are put in a child [`ArgMatches`] 876 /// 877 /// Returns `None` if the subcommand wasn't present at runtime, 878 /// 879 /// # Examples 880 /// 881 /// ```no_run 882 /// # use clap::{Command, Arg, }; 883 /// let app_m = Command::new("git") 884 /// .subcommand(Command::new("clone")) 885 /// .subcommand(Command::new("push")) 886 /// .subcommand(Command::new("commit")) 887 /// .get_matches(); 888 /// 889 /// match app_m.subcommand() { 890 /// Some(("clone", sub_m)) => {}, // clone was used 891 /// Some(("push", sub_m)) => {}, // push was used 892 /// Some(("commit", sub_m)) => {}, // commit was used 893 /// _ => {}, // Either no subcommand or one not tested for... 894 /// } 895 /// ``` 896 /// 897 /// Another useful scenario is when you want to support third party, or external, subcommands. 898 /// In these cases you can't know the subcommand name ahead of time, so use a variable instead 899 /// with pattern matching! 900 /// 901 /// ```rust 902 /// # use std::ffi::OsString; 903 /// # use std::ffi::OsStr; 904 /// # use clap::Command; 905 /// // Assume there is an external subcommand named "subcmd" 906 /// let app_m = Command::new("myprog") 907 /// .allow_external_subcommands(true) 908 /// .get_matches_from(vec![ 909 /// "myprog", "subcmd", "--option", "value", "-fff", "--flag" 910 /// ]); 911 /// 912 /// // All trailing arguments will be stored under the subcommand's sub-matches using an empty 913 /// // string argument name 914 /// match app_m.subcommand() { 915 /// Some((external, sub_m)) => { 916 /// let ext_args: Vec<&OsStr> = sub_m.get_many::<OsString>("") 917 /// .unwrap().map(|s| s.as_os_str()).collect(); 918 /// assert_eq!(external, "subcmd"); 919 /// assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]); 920 /// }, 921 /// _ => {}, 922 /// } 923 /// ``` 924 /// [subcommand]: crate::Command::subcommand 925 #[inline] 926 pub fn subcommand(&self) -> Option<(&str, &ArgMatches)> { 927 self.subcommand.as_ref().map(|sc| (&*sc.name, &sc.matches)) 928 } 929 930 /// Return the name and `ArgMatches` of the current [subcommand]. 931 /// 932 /// Subcommand values are put in a child [`ArgMatches`] 933 /// 934 /// Returns `None` if the subcommand wasn't present at runtime, 935 /// 936 /// # Examples 937 /// 938 /// ```no_run 939 /// # use clap::{Command, Arg, }; 940 /// let mut app_m = Command::new("git") 941 /// .subcommand(Command::new("clone")) 942 /// .subcommand(Command::new("push")) 943 /// .subcommand(Command::new("commit")) 944 /// .subcommand_required(true) 945 /// .get_matches(); 946 /// 947 /// let (name, sub_m) = app_m.remove_subcommand().expect("required"); 948 /// match (name.as_str(), sub_m) { 949 /// ("clone", sub_m) => {}, // clone was used 950 /// ("push", sub_m) => {}, // push was used 951 /// ("commit", sub_m) => {}, // commit was used 952 /// (name, _) => unimplemented!("{}", name), 953 /// } 954 /// ``` 955 /// 956 /// Another useful scenario is when you want to support third party, or external, subcommands. 957 /// In these cases you can't know the subcommand name ahead of time, so use a variable instead 958 /// with pattern matching! 959 /// 960 /// ```rust 961 /// # use std::ffi::OsString; 962 /// # use clap::Command; 963 /// // Assume there is an external subcommand named "subcmd" 964 /// let mut app_m = Command::new("myprog") 965 /// .allow_external_subcommands(true) 966 /// .get_matches_from(vec![ 967 /// "myprog", "subcmd", "--option", "value", "-fff", "--flag" 968 /// ]); 969 /// 970 /// // All trailing arguments will be stored under the subcommand's sub-matches using an empty 971 /// // string argument name 972 /// match app_m.remove_subcommand() { 973 /// Some((external, mut sub_m)) => { 974 /// let ext_args: Vec<OsString> = sub_m.remove_many("") 975 /// .expect("`file`is required") 976 /// .collect(); 977 /// assert_eq!(external, "subcmd"); 978 /// assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]); 979 /// }, 980 /// _ => {}, 981 /// } 982 /// ``` 983 /// [subcommand]: crate::Command::subcommand 984 pub fn remove_subcommand(&mut self) -> Option<(String, ArgMatches)> { 985 self.subcommand.take().map(|sc| (sc.name, sc.matches)) 986 } 987 988 /// The `ArgMatches` for the current [subcommand]. 989 /// 990 /// Subcommand values are put in a child [`ArgMatches`] 991 /// 992 /// Returns `None` if the subcommand wasn't present at runtime, 993 /// 994 /// # Panics 995 /// 996 /// If `id` is not a valid subcommand. 997 /// 998 /// # Examples 999 /// 1000 /// ```rust 1001 /// # use clap::{Command, Arg, ArgAction}; 1002 /// let app_m = Command::new("myprog") 1003 /// .arg(Arg::new("debug") 1004 /// .short('d') 1005 /// .action(ArgAction::SetTrue) 1006 /// ) 1007 /// .subcommand(Command::new("test") 1008 /// .arg(Arg::new("opt") 1009 /// .long("option") 1010 /// .action(ArgAction::Set))) 1011 /// .get_matches_from(vec![ 1012 /// "myprog", "-d", "test", "--option", "val" 1013 /// ]); 1014 /// 1015 /// // Both parent commands, and child subcommands can have arguments present at the same times 1016 /// assert!(app_m.get_flag("debug")); 1017 /// 1018 /// // Get the subcommand's ArgMatches instance 1019 /// if let Some(sub_m) = app_m.subcommand_matches("test") { 1020 /// // Use the struct like normal 1021 /// assert_eq!(sub_m.get_one::<String>("opt").map(|s| s.as_str()), Some("val")); 1022 /// } 1023 /// ``` 1024 /// 1025 /// [subcommand]: crate::Command::subcommand 1026 /// [`Command`]: crate::Command 1027 pub fn subcommand_matches(&self, name: &str) -> Option<&ArgMatches> { 1028 self.get_subcommand(name).map(|sc| &sc.matches) 1029 } 1030 1031 /// The name of the current [subcommand]. 1032 /// 1033 /// Returns `None` if the subcommand wasn't present at runtime, 1034 /// 1035 /// # Examples 1036 /// 1037 /// ```no_run 1038 /// # use clap::{Command, Arg, }; 1039 /// let app_m = Command::new("git") 1040 /// .subcommand(Command::new("clone")) 1041 /// .subcommand(Command::new("push")) 1042 /// .subcommand(Command::new("commit")) 1043 /// .get_matches(); 1044 /// 1045 /// match app_m.subcommand_name() { 1046 /// Some("clone") => {}, // clone was used 1047 /// Some("push") => {}, // push was used 1048 /// Some("commit") => {}, // commit was used 1049 /// _ => {}, // Either no subcommand or one not tested for... 1050 /// } 1051 /// ``` 1052 /// [subcommand]: crate::Command::subcommand 1053 /// [`Command`]: crate::Command 1054 #[inline] 1055 pub fn subcommand_name(&self) -> Option<&str> { 1056 self.subcommand.as_ref().map(|sc| &*sc.name) 1057 } 1058 1059 /// Check if a subcommand can be queried 1060 /// 1061 /// By default, `ArgMatches` functions assert on undefined `Id`s to help catch programmer 1062 /// mistakes. In some context, this doesn't work, so users can use this function to check 1063 /// before they do a query on `ArgMatches`. 1064 #[inline] 1065 #[doc(hidden)] 1066 pub fn is_valid_subcommand(&self, _name: &str) -> bool { 1067 #[cfg(debug_assertions)] 1068 { 1069 _name.is_empty() || self.valid_subcommands.iter().any(|s| *s == _name) 1070 } 1071 #[cfg(not(debug_assertions))] 1072 { 1073 true 1074 } 1075 } 1076} 1077 1078/// # Advanced 1079impl ArgMatches { 1080 /// Non-panicking version of [`ArgMatches::get_one`] 1081 pub fn try_get_one<T: Any + Clone + Send + Sync + 'static>( 1082 &self, 1083 id: &str, 1084 ) -> Result<Option<&T>, MatchesError> { 1085 let arg = ok!(self.try_get_arg_t::<T>(id)); 1086 let value = match arg.and_then(|a| a.first()) { 1087 Some(value) => value, 1088 None => { 1089 return Ok(None); 1090 } 1091 }; 1092 Ok(value 1093 .downcast_ref::<T>() 1094 .map(Some) 1095 .expect(INTERNAL_ERROR_MSG)) // enforced by `try_get_arg_t` 1096 } 1097 1098 /// Non-panicking version of [`ArgMatches::get_many`] 1099 pub fn try_get_many<T: Any + Clone + Send + Sync + 'static>( 1100 &self, 1101 id: &str, 1102 ) -> Result<Option<ValuesRef<T>>, MatchesError> { 1103 let arg = match ok!(self.try_get_arg_t::<T>(id)) { 1104 Some(arg) => arg, 1105 None => return Ok(None), 1106 }; 1107 let len = arg.num_vals(); 1108 let values = arg.vals_flatten(); 1109 let values = ValuesRef { 1110 // enforced by `try_get_arg_t` 1111 iter: values.map(unwrap_downcast_ref), 1112 len, 1113 }; 1114 Ok(Some(values)) 1115 } 1116 1117 /// Non-panicking version of [`ArgMatches::get_occurrences`] 1118 pub fn try_get_occurrences<T: Any + Clone + Send + Sync + 'static>( 1119 &self, 1120 id: &str, 1121 ) -> Result<Option<OccurrencesRef<T>>, MatchesError> { 1122 let arg = match ok!(self.try_get_arg_t::<T>(id)) { 1123 Some(arg) => arg, 1124 None => return Ok(None), 1125 }; 1126 let values = arg.vals(); 1127 Ok(Some(OccurrencesRef { 1128 iter: values.map(|g| OccurrenceValuesRef { 1129 iter: g.iter().map(unwrap_downcast_ref), 1130 }), 1131 })) 1132 } 1133 1134 /// Non-panicking version of [`ArgMatches::get_raw`] 1135 pub fn try_get_raw(&self, id: &str) -> Result<Option<RawValues<'_>>, MatchesError> { 1136 let arg = match ok!(self.try_get_arg(id)) { 1137 Some(arg) => arg, 1138 None => return Ok(None), 1139 }; 1140 let len = arg.num_vals(); 1141 let values = arg.raw_vals_flatten(); 1142 let values = RawValues { 1143 iter: values.map(OsString::as_os_str), 1144 len, 1145 }; 1146 Ok(Some(values)) 1147 } 1148 1149 /// Non-panicking version of [`ArgMatches::get_raw_occurrences`] 1150 pub fn try_get_raw_occurrences( 1151 &self, 1152 id: &str, 1153 ) -> Result<Option<RawOccurrences<'_>>, MatchesError> { 1154 let arg = match ok!(self.try_get_arg(id)) { 1155 Some(arg) => arg, 1156 None => return Ok(None), 1157 }; 1158 let values = arg.raw_vals(); 1159 let occurrences = RawOccurrences { 1160 iter: values.map(|g| RawOccurrenceValues { 1161 iter: g.iter().map(OsString::as_os_str), 1162 }), 1163 }; 1164 Ok(Some(occurrences)) 1165 } 1166 1167 /// Non-panicking version of [`ArgMatches::remove_one`] 1168 pub fn try_remove_one<T: Any + Clone + Send + Sync + 'static>( 1169 &mut self, 1170 id: &str, 1171 ) -> Result<Option<T>, MatchesError> { 1172 match ok!(self.try_remove_arg_t::<T>(id)) { 1173 Some(values) => Ok(values 1174 .into_vals_flatten() 1175 // enforced by `try_get_arg_t` 1176 .map(unwrap_downcast_into) 1177 .next()), 1178 None => Ok(None), 1179 } 1180 } 1181 1182 /// Non-panicking version of [`ArgMatches::remove_many`] 1183 pub fn try_remove_many<T: Any + Clone + Send + Sync + 'static>( 1184 &mut self, 1185 id: &str, 1186 ) -> Result<Option<Values<T>>, MatchesError> { 1187 let arg = match ok!(self.try_remove_arg_t::<T>(id)) { 1188 Some(arg) => arg, 1189 None => return Ok(None), 1190 }; 1191 let len = arg.num_vals(); 1192 let values = arg.into_vals_flatten(); 1193 let values = Values { 1194 // enforced by `try_get_arg_t` 1195 iter: values.map(unwrap_downcast_into), 1196 len, 1197 }; 1198 Ok(Some(values)) 1199 } 1200 1201 /// Non-panicking version of [`ArgMatches::remove_occurrences`] 1202 pub fn try_remove_occurrences<T: Any + Clone + Send + Sync + 'static>( 1203 &mut self, 1204 id: &str, 1205 ) -> Result<Option<Occurrences<T>>, MatchesError> { 1206 let arg = match ok!(self.try_remove_arg_t::<T>(id)) { 1207 Some(arg) => arg, 1208 None => return Ok(None), 1209 }; 1210 let values = arg.into_vals(); 1211 let occurrences = Occurrences { 1212 iter: values.into_iter().map(|g| OccurrenceValues { 1213 iter: g.into_iter().map(unwrap_downcast_into), 1214 }), 1215 }; 1216 Ok(Some(occurrences)) 1217 } 1218 1219 /// Non-panicking version of [`ArgMatches::contains_id`] 1220 pub fn try_contains_id(&self, id: &str) -> Result<bool, MatchesError> { 1221 ok!(self.verify_arg(id)); 1222 1223 let presence = self.args.contains_key(id); 1224 Ok(presence) 1225 } 1226} 1227 1228// Private methods 1229impl ArgMatches { 1230 #[inline] 1231 fn try_get_arg(&self, arg: &str) -> Result<Option<&MatchedArg>, MatchesError> { 1232 ok!(self.verify_arg(arg)); 1233 Ok(self.args.get(arg)) 1234 } 1235 1236 #[inline] 1237 fn try_get_arg_t<T: Any + Send + Sync + 'static>( 1238 &self, 1239 arg: &str, 1240 ) -> Result<Option<&MatchedArg>, MatchesError> { 1241 let arg = match ok!(self.try_get_arg(arg)) { 1242 Some(arg) => arg, 1243 None => { 1244 return Ok(None); 1245 } 1246 }; 1247 ok!(self.verify_arg_t::<T>(arg)); 1248 Ok(Some(arg)) 1249 } 1250 1251 #[inline] 1252 fn try_remove_arg_t<T: Any + Send + Sync + 'static>( 1253 &mut self, 1254 arg: &str, 1255 ) -> Result<Option<MatchedArg>, MatchesError> { 1256 ok!(self.verify_arg(arg)); 1257 let (id, matched) = match self.args.remove_entry(arg) { 1258 Some((id, matched)) => (id, matched), 1259 None => { 1260 return Ok(None); 1261 } 1262 }; 1263 1264 let expected = AnyValueId::of::<T>(); 1265 let actual = matched.infer_type_id(expected); 1266 if actual == expected { 1267 Ok(Some(matched)) 1268 } else { 1269 self.args.insert(id, matched); 1270 Err(MatchesError::Downcast { actual, expected }) 1271 } 1272 } 1273 1274 fn verify_arg_t<T: Any + Send + Sync + 'static>( 1275 &self, 1276 arg: &MatchedArg, 1277 ) -> Result<(), MatchesError> { 1278 let expected = AnyValueId::of::<T>(); 1279 let actual = arg.infer_type_id(expected); 1280 if expected == actual { 1281 Ok(()) 1282 } else { 1283 Err(MatchesError::Downcast { actual, expected }) 1284 } 1285 } 1286 1287 #[inline] 1288 fn verify_arg(&self, _arg: &str) -> Result<(), MatchesError> { 1289 #[cfg(debug_assertions)] 1290 { 1291 if _arg == Id::EXTERNAL || self.valid_args.iter().any(|s| *s == _arg) { 1292 } else { 1293 debug!( 1294 "`{:?}` is not an id of an argument or a group.\n\ 1295 Make sure you're using the name of the argument itself \ 1296 and not the name of short or long flags.", 1297 _arg 1298 ); 1299 return Err(MatchesError::UnknownArgument {}); 1300 } 1301 } 1302 Ok(()) 1303 } 1304 1305 #[inline] 1306 #[cfg_attr(debug_assertions, track_caller)] 1307 fn get_arg<'s>(&'s self, arg: &str) -> Option<&'s MatchedArg> { 1308 #[cfg(debug_assertions)] 1309 { 1310 if arg == Id::EXTERNAL || self.valid_args.iter().any(|s| *s == arg) { 1311 } else { 1312 panic!( 1313 "`{arg:?}` is not an id of an argument or a group.\n\ 1314 Make sure you're using the name of the argument itself \ 1315 and not the name of short or long flags." 1316 ); 1317 } 1318 } 1319 1320 self.args.get(arg) 1321 } 1322 1323 #[inline] 1324 #[cfg_attr(debug_assertions, track_caller)] 1325 fn get_subcommand(&self, name: &str) -> Option<&SubCommand> { 1326 #[cfg(debug_assertions)] 1327 { 1328 if name.is_empty() || self.valid_subcommands.iter().any(|s| *s == name) { 1329 } else { 1330 panic!("`{name}` is not a name of a subcommand."); 1331 } 1332 } 1333 1334 if let Some(ref sc) = self.subcommand { 1335 if sc.name == name { 1336 return Some(sc); 1337 } 1338 } 1339 1340 None 1341 } 1342} 1343 1344#[derive(Debug, Clone, PartialEq, Eq)] 1345pub(crate) struct SubCommand { 1346 pub(crate) name: String, 1347 pub(crate) matches: ArgMatches, 1348} 1349 1350/// Iterate over [`Arg`][crate::Arg] and [`ArgGroup`][crate::ArgGroup] [`Id`][crate::Id]s via [`ArgMatches::ids`]. 1351/// 1352/// # Examples 1353/// 1354/// ``` 1355/// # use clap::{Command, arg, value_parser}; 1356/// 1357/// let m = Command::new("myprog") 1358/// .arg(arg!(--color <when>) 1359/// .value_parser(["auto", "always", "never"])) 1360/// .arg(arg!(--config <path>) 1361/// .value_parser(value_parser!(std::path::PathBuf))) 1362/// .get_matches_from(["myprog", "--config=config.toml", "--color=auto"]); 1363/// assert_eq!( 1364/// m.ids() 1365/// .map(|id| id.as_str()) 1366/// .collect::<Vec<_>>(), 1367/// ["config", "color"] 1368/// ); 1369/// ``` 1370#[derive(Clone, Debug)] 1371pub struct IdsRef<'a> { 1372 iter: std::slice::Iter<'a, Id>, 1373} 1374 1375impl<'a> Iterator for IdsRef<'a> { 1376 type Item = &'a Id; 1377 1378 fn next(&mut self) -> Option<&'a Id> { 1379 self.iter.next() 1380 } 1381 fn size_hint(&self) -> (usize, Option<usize>) { 1382 self.iter.size_hint() 1383 } 1384} 1385 1386impl<'a> DoubleEndedIterator for IdsRef<'a> { 1387 fn next_back(&mut self) -> Option<&'a Id> { 1388 self.iter.next_back() 1389 } 1390} 1391 1392impl<'a> ExactSizeIterator for IdsRef<'a> {} 1393 1394/// Iterate over multiple values for an argument via [`ArgMatches::remove_many`]. 1395/// 1396/// # Examples 1397/// 1398/// ```rust 1399/// # use clap::{Command, Arg, ArgAction}; 1400/// let mut m = Command::new("myapp") 1401/// .arg(Arg::new("output") 1402/// .short('o') 1403/// .action(ArgAction::Append)) 1404/// .get_matches_from(vec!["myapp", "-o", "val1", "-o", "val2"]); 1405/// 1406/// let mut values = m.remove_many::<String>("output") 1407/// .unwrap(); 1408/// 1409/// assert_eq!(values.next(), Some(String::from("val1"))); 1410/// assert_eq!(values.next(), Some(String::from("val2"))); 1411/// assert_eq!(values.next(), None); 1412/// ``` 1413#[derive(Clone, Debug)] 1414pub struct Values<T> { 1415 #[allow(clippy::type_complexity)] 1416 iter: Map<Flatten<std::vec::IntoIter<Vec<AnyValue>>>, fn(AnyValue) -> T>, 1417 len: usize, 1418} 1419 1420impl<T> Iterator for Values<T> { 1421 type Item = T; 1422 1423 fn next(&mut self) -> Option<Self::Item> { 1424 self.iter.next() 1425 } 1426 fn size_hint(&self) -> (usize, Option<usize>) { 1427 (self.len, Some(self.len)) 1428 } 1429} 1430 1431impl<T> DoubleEndedIterator for Values<T> { 1432 fn next_back(&mut self) -> Option<Self::Item> { 1433 self.iter.next_back() 1434 } 1435} 1436 1437impl<T> ExactSizeIterator for Values<T> {} 1438 1439/// Creates an empty iterator. 1440impl<T> Default for Values<T> { 1441 fn default() -> Self { 1442 let empty: Vec<Vec<AnyValue>> = Default::default(); 1443 Values { 1444 iter: empty.into_iter().flatten().map(|_| unreachable!()), 1445 len: 0, 1446 } 1447 } 1448} 1449 1450/// Iterate over multiple values for an argument via [`ArgMatches::get_many`]. 1451/// 1452/// # Examples 1453/// 1454/// ```rust 1455/// # use clap::{Command, Arg, ArgAction}; 1456/// let m = Command::new("myapp") 1457/// .arg(Arg::new("output") 1458/// .short('o') 1459/// .action(ArgAction::Append)) 1460/// .get_matches_from(vec!["myapp", "-o", "val1", "-o", "val2"]); 1461/// 1462/// let mut values = m.get_many::<String>("output") 1463/// .unwrap() 1464/// .map(|s| s.as_str()); 1465/// 1466/// assert_eq!(values.next(), Some("val1")); 1467/// assert_eq!(values.next(), Some("val2")); 1468/// assert_eq!(values.next(), None); 1469/// ``` 1470#[derive(Clone, Debug)] 1471pub struct ValuesRef<'a, T> { 1472 #[allow(clippy::type_complexity)] 1473 iter: Map<Flatten<Iter<'a, Vec<AnyValue>>>, fn(&AnyValue) -> &T>, 1474 len: usize, 1475} 1476 1477impl<'a, T: 'a> Iterator for ValuesRef<'a, T> { 1478 type Item = &'a T; 1479 1480 fn next(&mut self) -> Option<Self::Item> { 1481 self.iter.next() 1482 } 1483 fn size_hint(&self) -> (usize, Option<usize>) { 1484 (self.len, Some(self.len)) 1485 } 1486} 1487 1488impl<'a, T: 'a> DoubleEndedIterator for ValuesRef<'a, T> { 1489 fn next_back(&mut self) -> Option<Self::Item> { 1490 self.iter.next_back() 1491 } 1492} 1493 1494impl<'a, T: 'a> ExactSizeIterator for ValuesRef<'a, T> {} 1495 1496/// Creates an empty iterator. 1497impl<'a, T: 'a> Default for ValuesRef<'a, T> { 1498 fn default() -> Self { 1499 static EMPTY: [Vec<AnyValue>; 0] = []; 1500 ValuesRef { 1501 iter: EMPTY[..].iter().flatten().map(|_| unreachable!()), 1502 len: 0, 1503 } 1504 } 1505} 1506 1507/// Iterate over raw argument values via [`ArgMatches::get_raw`]. 1508/// 1509/// # Examples 1510/// 1511#[cfg_attr(not(unix), doc = " ```ignore")] 1512#[cfg_attr(unix, doc = " ```")] 1513/// # use clap::{Command, arg, value_parser}; 1514/// use std::ffi::OsString; 1515/// use std::os::unix::ffi::{OsStrExt,OsStringExt}; 1516/// 1517/// let m = Command::new("utf8") 1518/// .arg(arg!(<arg> "some arg") 1519/// .value_parser(value_parser!(OsString))) 1520/// .get_matches_from(vec![OsString::from("myprog"), 1521/// // "Hi {0xe9}!" 1522/// OsString::from_vec(vec![b'H', b'i', b' ', 0xe9, b'!'])]); 1523/// assert_eq!( 1524/// &*m.get_raw("arg") 1525/// .unwrap() 1526/// .next().unwrap() 1527/// .as_bytes(), 1528/// [b'H', b'i', b' ', 0xe9, b'!'] 1529/// ); 1530/// ``` 1531#[derive(Clone, Debug)] 1532pub struct RawValues<'a> { 1533 #[allow(clippy::type_complexity)] 1534 iter: Map<Flatten<Iter<'a, Vec<OsString>>>, fn(&OsString) -> &OsStr>, 1535 len: usize, 1536} 1537 1538impl<'a> Iterator for RawValues<'a> { 1539 type Item = &'a OsStr; 1540 1541 fn next(&mut self) -> Option<&'a OsStr> { 1542 self.iter.next() 1543 } 1544 fn size_hint(&self) -> (usize, Option<usize>) { 1545 (self.len, Some(self.len)) 1546 } 1547} 1548 1549impl<'a> DoubleEndedIterator for RawValues<'a> { 1550 fn next_back(&mut self) -> Option<&'a OsStr> { 1551 self.iter.next_back() 1552 } 1553} 1554 1555impl<'a> ExactSizeIterator for RawValues<'a> {} 1556 1557/// Creates an empty iterator. 1558impl Default for RawValues<'_> { 1559 fn default() -> Self { 1560 static EMPTY: [Vec<OsString>; 0] = []; 1561 RawValues { 1562 iter: EMPTY[..].iter().flatten().map(|_| unreachable!()), 1563 len: 0, 1564 } 1565 } 1566} 1567 1568// The following were taken and adapted from vec_map source 1569// repo: https://github.com/contain-rs/vec-map 1570// commit: be5e1fa3c26e351761b33010ddbdaf5f05dbcc33 1571// license: MIT - Copyright (c) 2015 The Rust Project Developers 1572 1573#[derive(Clone, Debug)] 1574#[deprecated(since = "4.1.0", note = "Use Occurrences instead")] 1575pub struct GroupedValues<'a> { 1576 #[allow(clippy::type_complexity)] 1577 iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> Vec<&str>>, 1578 len: usize, 1579} 1580 1581#[allow(deprecated)] 1582impl<'a> Iterator for GroupedValues<'a> { 1583 type Item = Vec<&'a str>; 1584 1585 fn next(&mut self) -> Option<Self::Item> { 1586 self.iter.next() 1587 } 1588 fn size_hint(&self) -> (usize, Option<usize>) { 1589 (self.len, Some(self.len)) 1590 } 1591} 1592 1593#[allow(deprecated)] 1594impl<'a> DoubleEndedIterator for GroupedValues<'a> { 1595 fn next_back(&mut self) -> Option<Self::Item> { 1596 self.iter.next_back() 1597 } 1598} 1599 1600#[allow(deprecated)] 1601impl<'a> ExactSizeIterator for GroupedValues<'a> {} 1602 1603/// Creates an empty iterator. Used for `unwrap_or_default()`. 1604#[allow(deprecated)] 1605impl<'a> Default for GroupedValues<'a> { 1606 fn default() -> Self { 1607 static EMPTY: [Vec<AnyValue>; 0] = []; 1608 GroupedValues { 1609 iter: EMPTY[..].iter().map(|_| unreachable!()), 1610 len: 0, 1611 } 1612 } 1613} 1614 1615#[derive(Clone, Debug)] 1616pub struct Occurrences<T> { 1617 #[allow(clippy::type_complexity)] 1618 iter: Map<std::vec::IntoIter<Vec<AnyValue>>, fn(Vec<AnyValue>) -> OccurrenceValues<T>>, 1619} 1620 1621impl<T> Iterator for Occurrences<T> { 1622 type Item = OccurrenceValues<T>; 1623 1624 fn next(&mut self) -> Option<Self::Item> { 1625 self.iter.next() 1626 } 1627 1628 fn size_hint(&self) -> (usize, Option<usize>) { 1629 self.iter.size_hint() 1630 } 1631} 1632 1633impl<T> DoubleEndedIterator for Occurrences<T> { 1634 fn next_back(&mut self) -> Option<Self::Item> { 1635 self.iter.next_back() 1636 } 1637} 1638 1639impl<T> ExactSizeIterator for Occurrences<T> {} 1640 1641impl<T> Default for Occurrences<T> { 1642 fn default() -> Self { 1643 let empty: Vec<Vec<AnyValue>> = Default::default(); 1644 Occurrences { 1645 iter: empty.into_iter().map(|_| unreachable!()), 1646 } 1647 } 1648} 1649 1650#[derive(Clone, Debug)] 1651pub struct OccurrenceValues<T> { 1652 #[allow(clippy::type_complexity)] 1653 iter: Map<std::vec::IntoIter<AnyValue>, fn(AnyValue) -> T>, 1654} 1655 1656impl<T> Iterator for OccurrenceValues<T> { 1657 type Item = T; 1658 1659 fn next(&mut self) -> Option<Self::Item> { 1660 self.iter.next() 1661 } 1662 1663 fn size_hint(&self) -> (usize, Option<usize>) { 1664 self.iter.size_hint() 1665 } 1666} 1667 1668impl<T> DoubleEndedIterator for OccurrenceValues<T> { 1669 fn next_back(&mut self) -> Option<Self::Item> { 1670 self.iter.next_back() 1671 } 1672} 1673 1674impl<T> ExactSizeIterator for OccurrenceValues<T> {} 1675 1676#[derive(Clone, Debug)] 1677pub struct OccurrencesRef<'a, T> { 1678 #[allow(clippy::type_complexity)] 1679 iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> OccurrenceValuesRef<'_, T>>, 1680} 1681 1682impl<'a, T> Iterator for OccurrencesRef<'a, T> 1683where 1684 Self: 'a, 1685{ 1686 type Item = OccurrenceValuesRef<'a, T>; 1687 1688 fn next(&mut self) -> Option<Self::Item> { 1689 self.iter.next() 1690 } 1691 1692 fn size_hint(&self) -> (usize, Option<usize>) { 1693 self.iter.size_hint() 1694 } 1695} 1696 1697impl<'a, T> DoubleEndedIterator for OccurrencesRef<'a, T> 1698where 1699 Self: 'a, 1700{ 1701 fn next_back(&mut self) -> Option<Self::Item> { 1702 self.iter.next_back() 1703 } 1704} 1705 1706impl<'a, T> ExactSizeIterator for OccurrencesRef<'a, T> where Self: 'a {} 1707impl<'a, T> Default for OccurrencesRef<'a, T> { 1708 fn default() -> Self { 1709 static EMPTY: [Vec<AnyValue>; 0] = []; 1710 OccurrencesRef { 1711 iter: EMPTY[..].iter().map(|_| unreachable!()), 1712 } 1713 } 1714} 1715 1716#[derive(Clone, Debug)] 1717pub struct OccurrenceValuesRef<'a, T> { 1718 #[allow(clippy::type_complexity)] 1719 iter: Map<Iter<'a, AnyValue>, fn(&AnyValue) -> &T>, 1720} 1721 1722impl<'a, T> Iterator for OccurrenceValuesRef<'a, T> 1723where 1724 Self: 'a, 1725{ 1726 type Item = &'a T; 1727 1728 fn next(&mut self) -> Option<Self::Item> { 1729 self.iter.next() 1730 } 1731 1732 fn size_hint(&self) -> (usize, Option<usize>) { 1733 self.iter.size_hint() 1734 } 1735} 1736 1737impl<'a, T> DoubleEndedIterator for OccurrenceValuesRef<'a, T> 1738where 1739 Self: 'a, 1740{ 1741 fn next_back(&mut self) -> Option<Self::Item> { 1742 self.iter.next_back() 1743 } 1744} 1745 1746impl<'a, T> ExactSizeIterator for OccurrenceValuesRef<'a, T> where Self: 'a {} 1747 1748#[derive(Clone, Debug)] 1749pub struct RawOccurrences<'a> { 1750 #[allow(clippy::type_complexity)] 1751 iter: Map<Iter<'a, Vec<OsString>>, fn(&Vec<OsString>) -> RawOccurrenceValues<'_>>, 1752} 1753 1754impl<'a> Iterator for RawOccurrences<'a> { 1755 type Item = RawOccurrenceValues<'a>; 1756 1757 fn next(&mut self) -> Option<Self::Item> { 1758 self.iter.next() 1759 } 1760 1761 fn size_hint(&self) -> (usize, Option<usize>) { 1762 self.iter.size_hint() 1763 } 1764} 1765 1766impl<'a> DoubleEndedIterator for RawOccurrences<'a> { 1767 fn next_back(&mut self) -> Option<Self::Item> { 1768 self.iter.next_back() 1769 } 1770} 1771 1772impl<'a> ExactSizeIterator for RawOccurrences<'a> {} 1773 1774impl<'a> Default for RawOccurrences<'a> { 1775 fn default() -> Self { 1776 static EMPTY: [Vec<OsString>; 0] = []; 1777 RawOccurrences { 1778 iter: EMPTY[..].iter().map(|_| unreachable!()), 1779 } 1780 } 1781} 1782 1783#[derive(Clone, Debug)] 1784pub struct RawOccurrenceValues<'a> { 1785 #[allow(clippy::type_complexity)] 1786 iter: Map<Iter<'a, OsString>, fn(&OsString) -> &OsStr>, 1787} 1788 1789impl<'a> Iterator for RawOccurrenceValues<'a> 1790where 1791 Self: 'a, 1792{ 1793 type Item = &'a OsStr; 1794 1795 fn next(&mut self) -> Option<Self::Item> { 1796 self.iter.next() 1797 } 1798 1799 fn size_hint(&self) -> (usize, Option<usize>) { 1800 self.iter.size_hint() 1801 } 1802} 1803 1804impl<'a> DoubleEndedIterator for RawOccurrenceValues<'a> 1805where 1806 Self: 'a, 1807{ 1808 fn next_back(&mut self) -> Option<Self::Item> { 1809 self.iter.next_back() 1810 } 1811} 1812 1813impl<'a> ExactSizeIterator for RawOccurrenceValues<'a> {} 1814 1815/// Iterate over indices for where an argument appeared when parsing, via [`ArgMatches::indices_of`] 1816/// 1817/// # Examples 1818/// 1819/// ```rust 1820/// # use clap::{Command, Arg, ArgAction}; 1821/// let m = Command::new("myapp") 1822/// .arg(Arg::new("output") 1823/// .short('o') 1824/// .num_args(1..) 1825/// .action(ArgAction::Set)) 1826/// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]); 1827/// 1828/// let mut indices = m.indices_of("output").unwrap(); 1829/// 1830/// assert_eq!(indices.next(), Some(2)); 1831/// assert_eq!(indices.next(), Some(3)); 1832/// assert_eq!(indices.next(), None); 1833/// ``` 1834/// [`ArgMatches::indices_of`]: ArgMatches::indices_of() 1835#[derive(Clone, Debug)] 1836pub struct Indices<'a> { 1837 iter: Cloned<Iter<'a, usize>>, 1838 len: usize, 1839} 1840 1841impl<'a> Iterator for Indices<'a> { 1842 type Item = usize; 1843 1844 fn next(&mut self) -> Option<usize> { 1845 self.iter.next() 1846 } 1847 fn size_hint(&self) -> (usize, Option<usize>) { 1848 (self.len, Some(self.len)) 1849 } 1850} 1851 1852impl<'a> DoubleEndedIterator for Indices<'a> { 1853 fn next_back(&mut self) -> Option<usize> { 1854 self.iter.next_back() 1855 } 1856} 1857 1858impl<'a> ExactSizeIterator for Indices<'a> {} 1859 1860/// Creates an empty iterator. 1861impl<'a> Default for Indices<'a> { 1862 fn default() -> Self { 1863 static EMPTY: [usize; 0] = []; 1864 // This is never called because the iterator is empty: 1865 Indices { 1866 iter: EMPTY[..].iter().cloned(), 1867 len: 0, 1868 } 1869 } 1870} 1871 1872#[cfg_attr(debug_assertions, track_caller)] 1873#[inline] 1874#[cfg(feature = "unstable-grouped")] 1875fn unwrap_string(value: &AnyValue) -> &str { 1876 match value.downcast_ref::<String>() { 1877 Some(value) => value, 1878 None => { 1879 panic!("Must use `_os` lookups with `Arg::allow_invalid_utf8`",) 1880 } 1881 } 1882} 1883 1884#[track_caller] 1885fn unwrap_downcast_ref<T: Any + Clone + Send + Sync + 'static>(value: &AnyValue) -> &T { 1886 value.downcast_ref().expect(INTERNAL_ERROR_MSG) 1887} 1888 1889#[track_caller] 1890fn unwrap_downcast_into<T: Any + Clone + Send + Sync + 'static>(value: AnyValue) -> T { 1891 value.downcast_into().expect(INTERNAL_ERROR_MSG) 1892} 1893 1894#[cfg(test)] 1895mod tests { 1896 use super::*; 1897 1898 use crate::ArgAction; 1899 1900 #[test] 1901 fn check_auto_traits() { 1902 static_assertions::assert_impl_all!(ArgMatches: Send, Sync, Unpin); 1903 } 1904 1905 #[test] 1906 fn test_default_raw_values() { 1907 let mut values: RawValues = Default::default(); 1908 assert_eq!(values.next(), None); 1909 } 1910 1911 #[test] 1912 fn test_default_indices() { 1913 let mut indices: Indices = Indices::default(); 1914 assert_eq!(indices.next(), None); 1915 } 1916 1917 #[test] 1918 fn test_default_indices_with_shorter_lifetime() { 1919 let matches = ArgMatches::default(); 1920 let mut indices = matches.indices_of("").unwrap_or_default(); 1921 assert_eq!(indices.next(), None); 1922 } 1923 1924 #[test] 1925 fn values_exact_size() { 1926 let l = crate::Command::new("test") 1927 .arg( 1928 crate::Arg::new("POTATO") 1929 .action(ArgAction::Set) 1930 .num_args(1..) 1931 .required(true), 1932 ) 1933 .try_get_matches_from(["test", "one"]) 1934 .unwrap() 1935 .get_many::<String>("POTATO") 1936 .expect("present") 1937 .count(); 1938 assert_eq!(l, 1); 1939 } 1940 1941 #[test] 1942 fn os_values_exact_size() { 1943 let l = crate::Command::new("test") 1944 .arg( 1945 crate::Arg::new("POTATO") 1946 .action(ArgAction::Set) 1947 .num_args(1..) 1948 .value_parser(crate::builder::ValueParser::os_string()) 1949 .required(true), 1950 ) 1951 .try_get_matches_from(["test", "one"]) 1952 .unwrap() 1953 .get_many::<std::ffi::OsString>("POTATO") 1954 .expect("present") 1955 .count(); 1956 assert_eq!(l, 1); 1957 } 1958 1959 #[test] 1960 fn indices_exact_size() { 1961 let l = crate::Command::new("test") 1962 .arg( 1963 crate::Arg::new("POTATO") 1964 .action(ArgAction::Set) 1965 .num_args(1..) 1966 .required(true), 1967 ) 1968 .try_get_matches_from(["test", "one"]) 1969 .unwrap() 1970 .indices_of("POTATO") 1971 .expect("present") 1972 .len(); 1973 assert_eq!(l, 1); 1974 } 1975} 1976