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