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