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 [`Arg`][crate::Arg]s were present on the command line
558 ///
559 /// See [`ArgMatches::subcommand_name()`] or [`ArgMatches::subcommand()`] to check if a
560 /// subcommand was present on the command line.
561 ///
562 /// # Examples
563 ///
564 /// ```rust
565 /// # use clap_builder as clap;
566 /// # use clap::{Command, Arg, ArgAction};
567 /// let mut cmd = Command::new("myapp")
568 /// .arg(Arg::new("output")
569 /// .action(ArgAction::Set));
570 ///
571 /// let m = cmd
572 /// .try_get_matches_from_mut(vec!["myapp", "something"])
573 /// .unwrap();
574 /// assert!(m.args_present());
575 ///
576 /// let m = cmd
577 /// .try_get_matches_from_mut(vec!["myapp"])
578 /// .unwrap();
579 /// assert!(! m.args_present());
580 pub fn args_present(&self) -> bool {
581 self.args
582 .values()
583 .any(|v| v.source().map(|s| s.is_explicit()).unwrap_or(false))
584 }
585
586 /// Report where argument value came from
587 ///
588 /// # Panics
589 ///
590 /// If `id` is not a valid argument or group id (debug builds).
591 ///
592 /// # Examples
593 ///
594 /// ```rust
595 /// # use clap_builder as clap;
596 /// # use clap::{Command, Arg, ArgAction};
597 /// # use clap::parser::ValueSource;
598 /// let m = Command::new("myprog")
599 /// .arg(Arg::new("debug")
600 /// .short('d')
601 /// .action(ArgAction::SetTrue))
602 /// .get_matches_from(vec![
603 /// "myprog", "-d"
604 /// ]);
605 ///
606 /// assert_eq!(m.value_source("debug"), Some(ValueSource::CommandLine));
607 /// ```
608 ///
609 /// [`default_value`]: crate::Arg::default_value()
610 #[cfg_attr(debug_assertions, track_caller)]
611 pub fn value_source(&self, id: &str) -> Option<ValueSource> {
612 let value = self.get_arg(id);
613
614 value.and_then(MatchedArg::source)
615 }
616
617 /// The first index of that an argument showed up.
618 ///
619 /// Indices are similar to argv indices, but are not exactly 1:1.
620 ///
621 /// For flags (i.e. those arguments which don't have an associated value), indices refer
622 /// to occurrence of the switch, such as `-f`, or `--flag`. However, for options the indices
623 /// refer to the *values* `-o val` would therefore not represent two distinct indices, only the
624 /// index for `val` would be recorded. This is by design.
625 ///
626 /// Besides the flag/option discrepancy, the primary difference between an argv index and clap
627 /// index, is that clap continues counting once all arguments have properly separated, whereas
628 /// an argv index does not.
629 ///
630 /// The examples should clear this up.
631 ///
632 /// <div class="warning">
633 ///
634 /// *NOTE:* If an argument is allowed multiple times, this method will only give the *first*
635 /// index. See [`ArgMatches::indices_of`].
636 ///
637 /// </div>
638 ///
639 /// # Panics
640 ///
641 /// If `id` is not a valid argument or group id (debug builds).
642 ///
643 /// # Examples
644 ///
645 /// The argv indices are listed in the comments below. See how they correspond to the clap
646 /// indices. Note that if it's not listed in a clap index, this is because it's not saved in
647 /// in an `ArgMatches` struct for querying.
648 ///
649 /// ```rust
650 /// # use clap_builder as clap;
651 /// # use clap::{Command, Arg, ArgAction};
652 /// let m = Command::new("myapp")
653 /// .arg(Arg::new("flag")
654 /// .short('f')
655 /// .action(ArgAction::SetTrue))
656 /// .arg(Arg::new("option")
657 /// .short('o')
658 /// .action(ArgAction::Set))
659 /// .get_matches_from(vec!["myapp", "-f", "-o", "val"]);
660 /// // ARGV indices: ^0 ^1 ^2 ^3
661 /// // clap indices: ^1 ^3
662 ///
663 /// assert_eq!(m.index_of("flag"), Some(1));
664 /// assert_eq!(m.index_of("option"), Some(3));
665 /// ```
666 ///
667 /// Now notice, if we use one of the other styles of options:
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("option")
677 /// .short('o')
678 /// .action(ArgAction::Set))
679 /// .get_matches_from(vec!["myapp", "-f", "-o=val"]);
680 /// // ARGV indices: ^0 ^1 ^2
681 /// // clap indices: ^1 ^3
682 ///
683 /// assert_eq!(m.index_of("flag"), Some(1));
684 /// assert_eq!(m.index_of("option"), Some(3));
685 /// ```
686 ///
687 /// Things become much more complicated, or clear if we look at a more complex combination of
688 /// flags. Let's also throw in the final option style for good measure.
689 ///
690 /// ```rust
691 /// # use clap_builder as clap;
692 /// # use clap::{Command, Arg, ArgAction};
693 /// let m = Command::new("myapp")
694 /// .arg(Arg::new("flag")
695 /// .short('f')
696 /// .action(ArgAction::SetTrue))
697 /// .arg(Arg::new("flag2")
698 /// .short('F')
699 /// .action(ArgAction::SetTrue))
700 /// .arg(Arg::new("flag3")
701 /// .short('z')
702 /// .action(ArgAction::SetTrue))
703 /// .arg(Arg::new("option")
704 /// .short('o')
705 /// .action(ArgAction::Set))
706 /// .get_matches_from(vec!["myapp", "-fzF", "-oval"]);
707 /// // ARGV indices: ^0 ^1 ^2
708 /// // clap indices: ^1,2,3 ^5
709 /// //
710 /// // clap sees the above as 'myapp -f -z -F -o val'
711 /// // ^0 ^1 ^2 ^3 ^4 ^5
712 /// assert_eq!(m.index_of("flag"), Some(1));
713 /// assert_eq!(m.index_of("flag2"), Some(3));
714 /// assert_eq!(m.index_of("flag3"), Some(2));
715 /// assert_eq!(m.index_of("option"), Some(5));
716 /// ```
717 ///
718 /// One final combination of flags/options to see how they combine:
719 ///
720 /// ```rust
721 /// # use clap_builder as clap;
722 /// # use clap::{Command, Arg, ArgAction};
723 /// let m = Command::new("myapp")
724 /// .arg(Arg::new("flag")
725 /// .short('f')
726 /// .action(ArgAction::SetTrue))
727 /// .arg(Arg::new("flag2")
728 /// .short('F')
729 /// .action(ArgAction::SetTrue))
730 /// .arg(Arg::new("flag3")
731 /// .short('z')
732 /// .action(ArgAction::SetTrue))
733 /// .arg(Arg::new("option")
734 /// .short('o')
735 /// .action(ArgAction::Set))
736 /// .get_matches_from(vec!["myapp", "-fzFoval"]);
737 /// // ARGV indices: ^0 ^1
738 /// // clap indices: ^1,2,3^5
739 /// //
740 /// // clap sees the above as 'myapp -f -z -F -o val'
741 /// // ^0 ^1 ^2 ^3 ^4 ^5
742 /// assert_eq!(m.index_of("flag"), Some(1));
743 /// assert_eq!(m.index_of("flag2"), Some(3));
744 /// assert_eq!(m.index_of("flag3"), Some(2));
745 /// assert_eq!(m.index_of("option"), Some(5));
746 /// ```
747 ///
748 /// The last part to mention is when values are sent in multiple groups with a [delimiter].
749 ///
750 /// ```rust
751 /// # use clap_builder as clap;
752 /// # use clap::{Command, Arg};
753 /// let m = Command::new("myapp")
754 /// .arg(Arg::new("option")
755 /// .short('o')
756 /// .value_delimiter(',')
757 /// .num_args(1..))
758 /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
759 /// // ARGV indices: ^0 ^1
760 /// // clap indices: ^2 ^3 ^4
761 /// //
762 /// // clap sees the above as 'myapp -o val1 val2 val3'
763 /// // ^0 ^1 ^2 ^3 ^4
764 /// assert_eq!(m.index_of("option"), Some(2));
765 /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 3, 4]);
766 /// ```
767 /// [delimiter]: crate::Arg::value_delimiter()
768 #[cfg_attr(debug_assertions, track_caller)]
769 pub fn index_of(&self, id: &str) -> Option<usize> {
770 let arg = some!(self.get_arg(id));
771 let i = some!(arg.get_index(0));
772 Some(i)
773 }
774
775 /// All indices an argument appeared at when parsing.
776 ///
777 /// Indices are similar to argv indices, but are not exactly 1:1.
778 ///
779 /// For flags (i.e. those arguments which don't have an associated value), indices refer
780 /// to occurrence of the switch, such as `-f`, or `--flag`. However, for options the indices
781 /// refer to the *values* `-o val` would therefore not represent two distinct indices, only the
782 /// index for `val` would be recorded. This is by design.
783 ///
784 /// <div class="warning">
785 ///
786 /// *NOTE:* For more information about how clap indices compared to argv indices, see
787 /// [`ArgMatches::index_of`]
788 ///
789 /// </div>
790 ///
791 /// # Panics
792 ///
793 /// If `id` is not a valid argument or group id (debug builds).
794 ///
795 /// # Examples
796 ///
797 /// ```rust
798 /// # use clap_builder as clap;
799 /// # use clap::{Command, Arg};
800 /// let m = Command::new("myapp")
801 /// .arg(Arg::new("option")
802 /// .short('o')
803 /// .value_delimiter(','))
804 /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
805 /// // ARGV indices: ^0 ^1
806 /// // clap indices: ^2 ^3 ^4
807 /// //
808 /// // clap sees the above as 'myapp -o val1 val2 val3'
809 /// // ^0 ^1 ^2 ^3 ^4
810 /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 3, 4]);
811 /// ```
812 ///
813 /// Another quick example is when flags and options are used together
814 ///
815 /// ```rust
816 /// # use clap_builder as clap;
817 /// # use clap::{Command, Arg, ArgAction};
818 /// let m = Command::new("myapp")
819 /// .arg(Arg::new("option")
820 /// .short('o')
821 /// .action(ArgAction::Set)
822 /// .action(ArgAction::Append))
823 /// .arg(Arg::new("flag")
824 /// .short('f')
825 /// .action(ArgAction::Count))
826 /// .get_matches_from(vec!["myapp", "-o", "val1", "-f", "-o", "val2", "-f"]);
827 /// // ARGV indices: ^0 ^1 ^2 ^3 ^4 ^5 ^6
828 /// // clap indices: ^2 ^3 ^5 ^6
829 ///
830 /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 5]);
831 /// assert_eq!(m.indices_of("flag").unwrap().collect::<Vec<_>>(), &[6]);
832 /// ```
833 ///
834 /// One final example, which is an odd case; if we *don't* use value delimiter as we did with
835 /// the first example above instead of `val1`, `val2` and `val3` all being distinc values, they
836 /// would all be a single value of `val1,val2,val3`, in which case they'd only receive a single
837 /// index.
838 ///
839 /// ```rust
840 /// # use clap_builder as clap;
841 /// # use clap::{Command, Arg, ArgAction};
842 /// let m = Command::new("myapp")
843 /// .arg(Arg::new("option")
844 /// .short('o')
845 /// .action(ArgAction::Set)
846 /// .num_args(1..))
847 /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
848 /// // ARGV indices: ^0 ^1
849 /// // clap indices: ^2
850 /// //
851 /// // clap sees the above as 'myapp -o "val1,val2,val3"'
852 /// // ^0 ^1 ^2
853 /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2]);
854 /// ```
855 /// [`ArgMatches::index_of`]: ArgMatches::index_of()
856 /// [delimiter]: Arg::value_delimiter()
857 #[cfg_attr(debug_assertions, track_caller)]
858 pub fn indices_of(&self, id: &str) -> Option<Indices<'_>> {
859 let arg = some!(self.get_arg(id));
860 let i = Indices {
861 iter: arg.indices(),
862 len: arg.num_vals(),
863 };
864 Some(i)
865 }
866}
867
868/// # Subcommands
869impl ArgMatches {
870 /// The name and `ArgMatches` of the current [subcommand].
871 ///
872 /// Subcommand values are put in a child [`ArgMatches`]
873 ///
874 /// Returns `None` if the subcommand wasn't present at runtime,
875 ///
876 /// # Examples
877 ///
878 /// ```no_run
879 /// # use clap_builder as clap;
880 /// # use clap::{Command, Arg, };
881 /// let app_m = Command::new("git")
882 /// .subcommand(Command::new("clone"))
883 /// .subcommand(Command::new("push"))
884 /// .subcommand(Command::new("commit"))
885 /// .get_matches();
886 ///
887 /// match app_m.subcommand() {
888 /// Some(("clone", sub_m)) => {}, // clone was used
889 /// Some(("push", sub_m)) => {}, // push was used
890 /// Some(("commit", sub_m)) => {}, // commit was used
891 /// _ => {}, // Either no subcommand or one not tested for...
892 /// }
893 /// ```
894 ///
895 /// Another useful scenario is when you want to support third party, or external, subcommands.
896 /// In these cases you can't know the subcommand name ahead of time, so use a variable instead
897 /// with pattern matching!
898 ///
899 /// ```rust
900 /// # use clap_builder as clap;
901 /// # use std::ffi::OsString;
902 /// # use std::ffi::OsStr;
903 /// # use clap::Command;
904 /// // Assume there is an external subcommand named "subcmd"
905 /// let app_m = Command::new("myprog")
906 /// .allow_external_subcommands(true)
907 /// .get_matches_from(vec![
908 /// "myprog", "subcmd", "--option", "value", "-fff", "--flag"
909 /// ]);
910 ///
911 /// // All trailing arguments will be stored under the subcommand's sub-matches using an empty
912 /// // string argument name
913 /// match app_m.subcommand() {
914 /// Some((external, sub_m)) => {
915 /// let ext_args: Vec<&OsStr> = sub_m.get_many::<OsString>("")
916 /// .unwrap().map(|s| s.as_os_str()).collect();
917 /// assert_eq!(external, "subcmd");
918 /// assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]);
919 /// },
920 /// _ => {},
921 /// }
922 /// ```
923 /// [subcommand]: crate::Command::subcommand
924 #[inline]
925 pub fn subcommand(&self) -> Option<(&str, &ArgMatches)> {
926 self.subcommand.as_ref().map(|sc| (&*sc.name, &sc.matches))
927 }
928
929 /// Return the name and `ArgMatches` of the current [subcommand].
930 ///
931 /// Subcommand values are put in a child [`ArgMatches`]
932 ///
933 /// Returns `None` if the subcommand wasn't present at runtime,
934 ///
935 /// # Examples
936 ///
937 /// ```no_run
938 /// # use clap_builder as clap;
939 /// # use clap::{Command, Arg, };
940 /// let mut app_m = Command::new("git")
941 /// .subcommand(Command::new("clone"))
942 /// .subcommand(Command::new("push"))
943 /// .subcommand(Command::new("commit"))
944 /// .subcommand_required(true)
945 /// .get_matches();
946 ///
947 /// let (name, sub_m) = app_m.remove_subcommand().expect("required");
948 /// match (name.as_str(), sub_m) {
949 /// ("clone", sub_m) => {}, // clone was used
950 /// ("push", sub_m) => {}, // push was used
951 /// ("commit", sub_m) => {}, // commit was used
952 /// (name, _) => unimplemented!("{name}"),
953 /// }
954 /// ```
955 ///
956 /// Another useful scenario is when you want to support third party, or external, subcommands.
957 /// In these cases you can't know the subcommand name ahead of time, so use a variable instead
958 /// with pattern matching!
959 ///
960 /// ```rust
961 /// # use clap_builder as clap;
962 /// # use std::ffi::OsString;
963 /// # use clap::Command;
964 /// // Assume there is an external subcommand named "subcmd"
965 /// let mut app_m = Command::new("myprog")
966 /// .allow_external_subcommands(true)
967 /// .get_matches_from(vec![
968 /// "myprog", "subcmd", "--option", "value", "-fff", "--flag"
969 /// ]);
970 ///
971 /// // All trailing arguments will be stored under the subcommand's sub-matches using an empty
972 /// // string argument name
973 /// match app_m.remove_subcommand() {
974 /// Some((external, mut sub_m)) => {
975 /// let ext_args: Vec<OsString> = sub_m.remove_many("")
976 /// .expect("`file`is required")
977 /// .collect();
978 /// assert_eq!(external, "subcmd");
979 /// assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]);
980 /// },
981 /// _ => {},
982 /// }
983 /// ```
984 /// [subcommand]: crate::Command::subcommand
985 pub fn remove_subcommand(&mut self) -> Option<(String, ArgMatches)> {
986 self.subcommand.take().map(|sc| (sc.name, sc.matches))
987 }
988
989 /// The `ArgMatches` for the current [subcommand].
990 ///
991 /// Subcommand values are put in a child [`ArgMatches`]
992 ///
993 /// Returns `None` if the subcommand wasn't present at runtime,
994 ///
995 /// # Panics
996 ///
997 /// If `id` is not a valid subcommand (debug builds).
998 ///
999 /// # Examples
1000 ///
1001 /// ```rust
1002 /// # use clap_builder as clap;
1003 /// # use clap::{Command, Arg, ArgAction};
1004 /// let app_m = Command::new("myprog")
1005 /// .arg(Arg::new("debug")
1006 /// .short('d')
1007 /// .action(ArgAction::SetTrue)
1008 /// )
1009 /// .subcommand(Command::new("test")
1010 /// .arg(Arg::new("opt")
1011 /// .long("option")
1012 /// .action(ArgAction::Set)))
1013 /// .get_matches_from(vec![
1014 /// "myprog", "-d", "test", "--option", "val"
1015 /// ]);
1016 ///
1017 /// // Both parent commands, and child subcommands can have arguments present at the same times
1018 /// assert!(app_m.get_flag("debug"));
1019 ///
1020 /// // Get the subcommand's ArgMatches instance
1021 /// if let Some(sub_m) = app_m.subcommand_matches("test") {
1022 /// // Use the struct like normal
1023 /// assert_eq!(sub_m.get_one::<String>("opt").map(|s| s.as_str()), Some("val"));
1024 /// }
1025 /// ```
1026 ///
1027 /// [subcommand]: crate::Command::subcommand
1028 /// [`Command`]: crate::Command
1029 pub fn subcommand_matches(&self, name: &str) -> Option<&ArgMatches> {
1030 self.get_subcommand(name).map(|sc| &sc.matches)
1031 }
1032
1033 /// The name of the current [subcommand].
1034 ///
1035 /// Returns `None` if the subcommand wasn't present at runtime,
1036 ///
1037 /// # Examples
1038 ///
1039 /// ```no_run
1040 /// # use clap_builder as clap;
1041 /// # use clap::{Command, Arg, };
1042 /// let app_m = Command::new("git")
1043 /// .subcommand(Command::new("clone"))
1044 /// .subcommand(Command::new("push"))
1045 /// .subcommand(Command::new("commit"))
1046 /// .get_matches();
1047 ///
1048 /// match app_m.subcommand_name() {
1049 /// Some("clone") => {}, // clone was used
1050 /// Some("push") => {}, // push was used
1051 /// Some("commit") => {}, // commit was used
1052 /// _ => {}, // Either no subcommand or one not tested for...
1053 /// }
1054 /// ```
1055 /// [subcommand]: crate::Command::subcommand
1056 /// [`Command`]: crate::Command
1057 #[inline]
1058 pub fn subcommand_name(&self) -> Option<&str> {
1059 self.subcommand.as_ref().map(|sc| &*sc.name)
1060 }
1061
1062 /// Check if a subcommand can be queried
1063 ///
1064 /// By default, `ArgMatches` functions assert on undefined `Id`s to help catch programmer
1065 /// mistakes. In some context, this doesn't work, so users can use this function to check
1066 /// before they do a query on `ArgMatches`.
1067 #[inline]
1068 #[doc(hidden)]
1069 pub fn is_valid_subcommand(&self, _name: &str) -> bool {
1070 #[cfg(debug_assertions)]
1071 {
1072 _name.is_empty() || self.valid_subcommands.iter().any(|s| *s == _name)
1073 }
1074 #[cfg(not(debug_assertions))]
1075 {
1076 true
1077 }
1078 }
1079}
1080
1081/// # Advanced
1082impl ArgMatches {
1083 /// Non-panicking version of [`ArgMatches::get_one`]
1084 pub fn try_get_one<T: Any + Clone + Send + Sync + 'static>(
1085 &self,
1086 id: &str,
1087 ) -> Result<Option<&T>, MatchesError> {
1088 let arg = ok!(self.try_get_arg_t::<T>(id));
1089 let value = match arg.and_then(|a| a.first()) {
1090 Some(value) => value,
1091 None => {
1092 return Ok(None);
1093 }
1094 };
1095 Ok(value
1096 .downcast_ref::<T>()
1097 .map(Some)
1098 .expect(INTERNAL_ERROR_MSG)) // enforced by `try_get_arg_t`
1099 }
1100
1101 /// Non-panicking version of [`ArgMatches::get_many`]
1102 pub fn try_get_many<T: Any + Clone + Send + Sync + 'static>(
1103 &self,
1104 id: &str,
1105 ) -> Result<Option<ValuesRef<'_, T>>, MatchesError> {
1106 let arg = match ok!(self.try_get_arg_t::<T>(id)) {
1107 Some(arg) => arg,
1108 None => return Ok(None),
1109 };
1110 let len = arg.num_vals();
1111 let values = arg.vals_flatten();
1112 let values = ValuesRef {
1113 // enforced by `try_get_arg_t`
1114 iter: values.map(unwrap_downcast_ref),
1115 len,
1116 };
1117 Ok(Some(values))
1118 }
1119
1120 /// Non-panicking version of [`ArgMatches::get_occurrences`]
1121 pub fn try_get_occurrences<T: Any + Clone + Send + Sync + 'static>(
1122 &self,
1123 id: &str,
1124 ) -> Result<Option<OccurrencesRef<'_, T>>, MatchesError> {
1125 let arg = match ok!(self.try_get_arg_t::<T>(id)) {
1126 Some(arg) => arg,
1127 None => return Ok(None),
1128 };
1129 let values = arg.vals();
1130 Ok(Some(OccurrencesRef {
1131 iter: values.map(|g| OccurrenceValuesRef {
1132 iter: g.iter().map(unwrap_downcast_ref),
1133 }),
1134 }))
1135 }
1136
1137 /// Non-panicking version of [`ArgMatches::get_raw`]
1138 pub fn try_get_raw(&self, id: &str) -> Result<Option<RawValues<'_>>, MatchesError> {
1139 let arg = match ok!(self.try_get_arg(id)) {
1140 Some(arg) => arg,
1141 None => return Ok(None),
1142 };
1143 let len = arg.num_vals();
1144 let values = arg.raw_vals_flatten();
1145 let values = RawValues {
1146 iter: values.map(OsString::as_os_str),
1147 len,
1148 };
1149 Ok(Some(values))
1150 }
1151
1152 /// Non-panicking version of [`ArgMatches::get_raw_occurrences`]
1153 pub fn try_get_raw_occurrences(
1154 &self,
1155 id: &str,
1156 ) -> Result<Option<RawOccurrences<'_>>, MatchesError> {
1157 let arg = match ok!(self.try_get_arg(id)) {
1158 Some(arg) => arg,
1159 None => return Ok(None),
1160 };
1161 let values = arg.raw_vals();
1162 let occurrences = RawOccurrences {
1163 iter: values.map(|g| RawOccurrenceValues {
1164 iter: g.iter().map(OsString::as_os_str),
1165 }),
1166 };
1167 Ok(Some(occurrences))
1168 }
1169
1170 /// Non-panicking version of [`ArgMatches::remove_one`]
1171 pub fn try_remove_one<T: Any + Clone + Send + Sync + 'static>(
1172 &mut self,
1173 id: &str,
1174 ) -> Result<Option<T>, MatchesError> {
1175 match ok!(self.try_remove_arg_t::<T>(id)) {
1176 Some(values) => Ok(values
1177 .into_vals_flatten()
1178 // enforced by `try_get_arg_t`
1179 .map(unwrap_downcast_into)
1180 .next()),
1181 None => Ok(None),
1182 }
1183 }
1184
1185 /// Non-panicking version of [`ArgMatches::remove_many`]
1186 pub fn try_remove_many<T: Any + Clone + Send + Sync + 'static>(
1187 &mut self,
1188 id: &str,
1189 ) -> Result<Option<Values<T>>, MatchesError> {
1190 let arg = match ok!(self.try_remove_arg_t::<T>(id)) {
1191 Some(arg) => arg,
1192 None => return Ok(None),
1193 };
1194 let len = arg.num_vals();
1195 let values = arg.into_vals_flatten();
1196 let values = Values {
1197 // enforced by `try_get_arg_t`
1198 iter: values.map(unwrap_downcast_into),
1199 len,
1200 };
1201 Ok(Some(values))
1202 }
1203
1204 /// Non-panicking version of [`ArgMatches::remove_occurrences`]
1205 pub fn try_remove_occurrences<T: Any + Clone + Send + Sync + 'static>(
1206 &mut self,
1207 id: &str,
1208 ) -> Result<Option<Occurrences<T>>, MatchesError> {
1209 let arg = match ok!(self.try_remove_arg_t::<T>(id)) {
1210 Some(arg) => arg,
1211 None => return Ok(None),
1212 };
1213 let values = arg.into_vals();
1214 let occurrences = Occurrences {
1215 iter: values.into_iter().map(|g| OccurrenceValues {
1216 iter: g.into_iter().map(unwrap_downcast_into),
1217 }),
1218 };
1219 Ok(Some(occurrences))
1220 }
1221
1222 /// Non-panicking version of [`ArgMatches::contains_id`]
1223 pub fn try_contains_id(&self, id: &str) -> Result<bool, MatchesError> {
1224 ok!(self.verify_arg(id));
1225
1226 let presence = self.args.contains_key(id);
1227 Ok(presence)
1228 }
1229}
1230
1231// Private methods
1232impl ArgMatches {
1233 #[inline]
1234 fn try_get_arg(&self, arg: &str) -> Result<Option<&MatchedArg>, MatchesError> {
1235 ok!(self.verify_arg(arg));
1236 Ok(self.args.get(arg))
1237 }
1238
1239 #[inline]
1240 fn try_get_arg_t<T: Any + Send + Sync + 'static>(
1241 &self,
1242 arg: &str,
1243 ) -> Result<Option<&MatchedArg>, MatchesError> {
1244 let arg = match ok!(self.try_get_arg(arg)) {
1245 Some(arg) => arg,
1246 None => {
1247 return Ok(None);
1248 }
1249 };
1250 ok!(self.verify_arg_t::<T>(arg));
1251 Ok(Some(arg))
1252 }
1253
1254 #[inline]
1255 fn try_remove_arg_t<T: Any + Send + Sync + 'static>(
1256 &mut self,
1257 arg: &str,
1258 ) -> Result<Option<MatchedArg>, MatchesError> {
1259 ok!(self.verify_arg(arg));
1260 let (id, matched) = match self.args.remove_entry(arg) {
1261 Some((id, matched)) => (id, matched),
1262 None => {
1263 return Ok(None);
1264 }
1265 };
1266
1267 let expected = AnyValueId::of::<T>();
1268 let actual = matched.infer_type_id(expected);
1269 if actual == expected {
1270 Ok(Some(matched))
1271 } else {
1272 self.args.insert(id, matched);
1273 Err(MatchesError::Downcast { actual, expected })
1274 }
1275 }
1276
1277 fn verify_arg_t<T: Any + Send + Sync + 'static>(
1278 &self,
1279 arg: &MatchedArg,
1280 ) -> Result<(), MatchesError> {
1281 let expected = AnyValueId::of::<T>();
1282 let actual = arg.infer_type_id(expected);
1283 if expected == actual {
1284 Ok(())
1285 } else {
1286 Err(MatchesError::Downcast { actual, expected })
1287 }
1288 }
1289
1290 #[inline]
1291 fn verify_arg(&self, _arg: &str) -> Result<(), MatchesError> {
1292 #[cfg(debug_assertions)]
1293 {
1294 if _arg == Id::EXTERNAL || self.valid_args.iter().any(|s| *s == _arg) {
1295 } else {
1296 debug!(
1297 "`{:?}` is not an id of an argument or a group.\n\
1298 Make sure you're using the name of the argument itself \
1299 and not the name of short or long flags.",
1300 _arg
1301 );
1302 return Err(MatchesError::UnknownArgument {});
1303 }
1304 }
1305 Ok(())
1306 }
1307
1308 #[inline]
1309 #[cfg_attr(debug_assertions, track_caller)]
1310 fn get_arg<'s>(&'s self, arg: &str) -> Option<&'s MatchedArg> {
1311 #[cfg(debug_assertions)]
1312 {
1313 if arg == Id::EXTERNAL || self.valid_args.iter().any(|s| *s == arg) {
1314 } else {
1315 panic!(
1316 "`{arg:?}` is not an id of an argument or a group.\n\
1317 Make sure you're using the name of the argument itself \
1318 and not the name of short or long flags."
1319 );
1320 }
1321 }
1322
1323 self.args.get(arg)
1324 }
1325
1326 #[inline]
1327 #[cfg_attr(debug_assertions, track_caller)]
1328 fn get_subcommand(&self, name: &str) -> Option<&SubCommand> {
1329 #[cfg(debug_assertions)]
1330 {
1331 if name.is_empty() || self.valid_subcommands.iter().any(|s| *s == name) {
1332 } else {
1333 panic!("`{name}` is not a name of a subcommand.");
1334 }
1335 }
1336
1337 if let Some(ref sc) = self.subcommand {
1338 if sc.name == name {
1339 return Some(sc);
1340 }
1341 }
1342
1343 None
1344 }
1345}
1346
1347#[derive(Debug, Clone, PartialEq, Eq)]
1348pub(crate) struct SubCommand {
1349 pub(crate) name: String,
1350 pub(crate) matches: ArgMatches,
1351}
1352
1353/// Iterate over [`Arg`][crate::Arg] and [`ArgGroup`][crate::ArgGroup] [`Id`]s via [`ArgMatches::ids`].
1354///
1355/// # Examples
1356///
1357/// ```rust
1358/// # use clap_builder as clap;
1359/// # use clap::{Command, arg, value_parser};
1360///
1361/// let m = Command::new("myprog")
1362/// .arg(arg!(--color <when>)
1363/// .value_parser(["auto", "always", "never"]))
1364/// .arg(arg!(--config <path>)
1365/// .value_parser(value_parser!(std::path::PathBuf)))
1366/// .get_matches_from(["myprog", "--config=config.toml", "--color=auto"]);
1367/// assert_eq!(
1368/// m.ids()
1369/// .map(|id| id.as_str())
1370/// .collect::<Vec<_>>(),
1371/// ["config", "color"]
1372/// );
1373/// ```
1374#[derive(Clone, Debug)]
1375pub struct IdsRef<'a> {
1376 iter: Iter<'a, Id>,
1377}
1378
1379impl<'a> Iterator for IdsRef<'a> {
1380 type Item = &'a Id;
1381
1382 fn next(&mut self) -> Option<&'a Id> {
1383 self.iter.next()
1384 }
1385 fn size_hint(&self) -> (usize, Option<usize>) {
1386 self.iter.size_hint()
1387 }
1388}
1389
1390impl<'a> DoubleEndedIterator for IdsRef<'a> {
1391 fn next_back(&mut self) -> Option<&'a Id> {
1392 self.iter.next_back()
1393 }
1394}
1395
1396impl ExactSizeIterator for IdsRef<'_> {}
1397
1398/// Iterate over multiple values for an argument via [`ArgMatches::remove_many`].
1399///
1400/// # Examples
1401///
1402/// ```rust
1403/// # use clap_builder as clap;
1404/// # use clap::{Command, Arg, ArgAction};
1405/// let mut m = Command::new("myapp")
1406/// .arg(Arg::new("output")
1407/// .short('o')
1408/// .action(ArgAction::Append))
1409/// .get_matches_from(vec!["myapp", "-o", "val1", "-o", "val2"]);
1410///
1411/// let mut values = m.remove_many::<String>("output")
1412/// .unwrap();
1413///
1414/// assert_eq!(values.next(), Some(String::from("val1")));
1415/// assert_eq!(values.next(), Some(String::from("val2")));
1416/// assert_eq!(values.next(), None);
1417/// ```
1418#[derive(Clone, Debug)]
1419pub struct Values<T> {
1420 #[allow(clippy::type_complexity)]
1421 iter: Map<Flatten<std::vec::IntoIter<Vec<AnyValue>>>, fn(AnyValue) -> T>,
1422 len: usize,
1423}
1424
1425impl<T> Iterator for Values<T> {
1426 type Item = T;
1427
1428 fn next(&mut self) -> Option<Self::Item> {
1429 if let Some(next) = self.iter.next() {
1430 self.len -= 1;
1431 Some(next)
1432 } else {
1433 None
1434 }
1435 }
1436 fn size_hint(&self) -> (usize, Option<usize>) {
1437 (self.len, Some(self.len))
1438 }
1439}
1440
1441impl<T> DoubleEndedIterator for Values<T> {
1442 fn next_back(&mut self) -> Option<Self::Item> {
1443 if let Some(next) = self.iter.next_back() {
1444 self.len -= 1;
1445 Some(next)
1446 } else {
1447 None
1448 }
1449 }
1450}
1451
1452impl<T> ExactSizeIterator for Values<T> {}
1453
1454/// Creates an empty iterator.
1455impl<T> Default for Values<T> {
1456 fn default() -> Self {
1457 let empty: Vec<Vec<AnyValue>> = Default::default();
1458 Values {
1459 iter: empty.into_iter().flatten().map(|_| unreachable!()),
1460 len: 0,
1461 }
1462 }
1463}
1464
1465/// Iterate over multiple values for an argument via [`ArgMatches::get_many`].
1466///
1467/// # Examples
1468///
1469/// ```rust
1470/// # use clap_builder as clap;
1471/// # use clap::{Command, Arg, ArgAction};
1472/// let m = Command::new("myapp")
1473/// .arg(Arg::new("output")
1474/// .short('o')
1475/// .action(ArgAction::Append))
1476/// .get_matches_from(vec!["myapp", "-o", "val1", "-o", "val2"]);
1477///
1478/// let mut values = m.get_many::<String>("output")
1479/// .unwrap()
1480/// .map(|s| s.as_str());
1481///
1482/// assert_eq!(values.next(), Some("val1"));
1483/// assert_eq!(values.next(), Some("val2"));
1484/// assert_eq!(values.next(), None);
1485/// ```
1486#[derive(Clone, Debug)]
1487pub struct ValuesRef<'a, T> {
1488 #[allow(clippy::type_complexity)]
1489 iter: Map<Flatten<Iter<'a, Vec<AnyValue>>>, fn(&AnyValue) -> &T>,
1490 len: usize,
1491}
1492
1493impl<'a, T: 'a> Iterator for ValuesRef<'a, T> {
1494 type Item = &'a T;
1495
1496 fn next(&mut self) -> Option<Self::Item> {
1497 if let Some(next) = self.iter.next() {
1498 self.len -= 1;
1499 Some(next)
1500 } else {
1501 None
1502 }
1503 }
1504 fn size_hint(&self) -> (usize, Option<usize>) {
1505 (self.len, Some(self.len))
1506 }
1507}
1508
1509impl<'a, T: 'a> DoubleEndedIterator for ValuesRef<'a, T> {
1510 fn next_back(&mut self) -> Option<Self::Item> {
1511 if let Some(next) = self.iter.next_back() {
1512 self.len -= 1;
1513 Some(next)
1514 } else {
1515 None
1516 }
1517 }
1518}
1519
1520impl<'a, T: 'a> ExactSizeIterator for ValuesRef<'a, T> {}
1521
1522/// Creates an empty iterator.
1523impl<'a, T: 'a> Default for ValuesRef<'a, T> {
1524 fn default() -> Self {
1525 static EMPTY: [Vec<AnyValue>; 0] = [];
1526 ValuesRef {
1527 iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
1528 len: 0,
1529 }
1530 }
1531}
1532
1533/// Iterate over raw argument values via [`ArgMatches::get_raw`].
1534///
1535/// # Examples
1536///
1537/// ```rust
1538/// # #[cfg(unix)] {
1539/// # use clap_builder as clap;
1540/// # use clap::{Command, arg, value_parser};
1541/// use std::ffi::OsString;
1542/// use std::os::unix::ffi::{OsStrExt,OsStringExt};
1543///
1544/// let m = Command::new("utf8")
1545/// .arg(arg!(<arg> "some arg")
1546/// .value_parser(value_parser!(OsString)))
1547/// .get_matches_from(vec![OsString::from("myprog"),
1548/// // "Hi {0xe9}!"
1549/// OsString::from_vec(vec![b'H', b'i', b' ', 0xe9, b'!'])]);
1550/// assert_eq!(
1551/// &*m.get_raw("arg")
1552/// .unwrap()
1553/// .next().unwrap()
1554/// .as_bytes(),
1555/// [b'H', b'i', b' ', 0xe9, b'!']
1556/// );
1557/// # }
1558/// ```
1559#[derive(Clone, Debug)]
1560pub struct RawValues<'a> {
1561 #[allow(clippy::type_complexity)]
1562 iter: Map<Flatten<Iter<'a, Vec<OsString>>>, fn(&OsString) -> &OsStr>,
1563 len: usize,
1564}
1565
1566impl<'a> Iterator for RawValues<'a> {
1567 type Item = &'a OsStr;
1568
1569 fn next(&mut self) -> Option<&'a OsStr> {
1570 if let Some(next) = self.iter.next() {
1571 self.len -= 1;
1572 Some(next)
1573 } else {
1574 None
1575 }
1576 }
1577 fn size_hint(&self) -> (usize, Option<usize>) {
1578 (self.len, Some(self.len))
1579 }
1580}
1581
1582impl<'a> DoubleEndedIterator for RawValues<'a> {
1583 fn next_back(&mut self) -> Option<&'a OsStr> {
1584 if let Some(next) = self.iter.next_back() {
1585 self.len -= 1;
1586 Some(next)
1587 } else {
1588 None
1589 }
1590 }
1591}
1592
1593impl ExactSizeIterator for RawValues<'_> {}
1594
1595/// Creates an empty iterator.
1596impl Default for RawValues<'_> {
1597 fn default() -> Self {
1598 static EMPTY: [Vec<OsString>; 0] = [];
1599 RawValues {
1600 iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
1601 len: 0,
1602 }
1603 }
1604}
1605
1606// The following were taken and adapted from vec_map source
1607// repo: https://github.com/contain-rs/vec-map
1608// commit: be5e1fa3c26e351761b33010ddbdaf5f05dbcc33
1609// license: MIT - Copyright (c) 2015 The Rust Project Developers
1610
1611#[derive(Clone, Debug)]
1612#[deprecated(since = "4.1.0", note = "Use Occurrences instead")]
1613pub(crate) struct GroupedValues<'a> {
1614 #[allow(clippy::type_complexity)]
1615 iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> Vec<&str>>,
1616 len: usize,
1617}
1618
1619#[allow(deprecated)]
1620impl<'a> Iterator for GroupedValues<'a> {
1621 type Item = Vec<&'a str>;
1622
1623 fn next(&mut self) -> Option<Self::Item> {
1624 if let Some(next) = self.iter.next() {
1625 self.len -= 1;
1626 Some(next)
1627 } else {
1628 None
1629 }
1630 }
1631 fn size_hint(&self) -> (usize, Option<usize>) {
1632 (self.len, Some(self.len))
1633 }
1634}
1635
1636#[allow(deprecated)]
1637impl DoubleEndedIterator for GroupedValues<'_> {
1638 fn next_back(&mut self) -> Option<Self::Item> {
1639 if let Some(next) = self.iter.next_back() {
1640 self.len -= 1;
1641 Some(next)
1642 } else {
1643 None
1644 }
1645 }
1646}
1647
1648#[allow(deprecated)]
1649impl ExactSizeIterator for GroupedValues<'_> {}
1650
1651/// Creates an empty iterator. Used for `unwrap_or_default()`.
1652#[allow(deprecated)]
1653impl Default for GroupedValues<'_> {
1654 fn default() -> Self {
1655 static EMPTY: [Vec<AnyValue>; 0] = [];
1656 GroupedValues {
1657 iter: EMPTY[..].iter().map(|_| unreachable!()),
1658 len: 0,
1659 }
1660 }
1661}
1662
1663#[derive(Clone, Debug)]
1664pub struct Occurrences<T> {
1665 #[allow(clippy::type_complexity)]
1666 iter: Map<std::vec::IntoIter<Vec<AnyValue>>, fn(Vec<AnyValue>) -> OccurrenceValues<T>>,
1667}
1668
1669impl<T> Iterator for Occurrences<T> {
1670 type Item = OccurrenceValues<T>;
1671
1672 fn next(&mut self) -> Option<Self::Item> {
1673 self.iter.next()
1674 }
1675
1676 fn size_hint(&self) -> (usize, Option<usize>) {
1677 self.iter.size_hint()
1678 }
1679}
1680
1681impl<T> DoubleEndedIterator for Occurrences<T> {
1682 fn next_back(&mut self) -> Option<Self::Item> {
1683 self.iter.next_back()
1684 }
1685}
1686
1687impl<T> ExactSizeIterator for Occurrences<T> {}
1688
1689impl<T> Default for Occurrences<T> {
1690 fn default() -> Self {
1691 let empty: Vec<Vec<AnyValue>> = Default::default();
1692 Occurrences {
1693 iter: empty.into_iter().map(|_| unreachable!()),
1694 }
1695 }
1696}
1697
1698#[derive(Clone, Debug)]
1699pub struct OccurrenceValues<T> {
1700 #[allow(clippy::type_complexity)]
1701 iter: Map<std::vec::IntoIter<AnyValue>, fn(AnyValue) -> T>,
1702}
1703
1704impl<T> Iterator for OccurrenceValues<T> {
1705 type Item = T;
1706
1707 fn next(&mut self) -> Option<Self::Item> {
1708 self.iter.next()
1709 }
1710
1711 fn size_hint(&self) -> (usize, Option<usize>) {
1712 self.iter.size_hint()
1713 }
1714}
1715
1716impl<T> DoubleEndedIterator for OccurrenceValues<T> {
1717 fn next_back(&mut self) -> Option<Self::Item> {
1718 self.iter.next_back()
1719 }
1720}
1721
1722impl<T> ExactSizeIterator for OccurrenceValues<T> {}
1723
1724#[derive(Clone, Debug)]
1725pub struct OccurrencesRef<'a, T> {
1726 #[allow(clippy::type_complexity)]
1727 iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> OccurrenceValuesRef<'_, T>>,
1728}
1729
1730impl<'a, T> Iterator for OccurrencesRef<'a, T>
1731where
1732 Self: 'a,
1733{
1734 type Item = OccurrenceValuesRef<'a, T>;
1735
1736 fn next(&mut self) -> Option<Self::Item> {
1737 self.iter.next()
1738 }
1739
1740 fn size_hint(&self) -> (usize, Option<usize>) {
1741 self.iter.size_hint()
1742 }
1743}
1744
1745impl<'a, T> DoubleEndedIterator for OccurrencesRef<'a, T>
1746where
1747 Self: 'a,
1748{
1749 fn next_back(&mut self) -> Option<Self::Item> {
1750 self.iter.next_back()
1751 }
1752}
1753
1754impl<'a, T> ExactSizeIterator for OccurrencesRef<'a, T> where Self: 'a {}
1755impl<T> Default for OccurrencesRef<'_, T> {
1756 fn default() -> Self {
1757 static EMPTY: [Vec<AnyValue>; 0] = [];
1758 OccurrencesRef {
1759 iter: EMPTY[..].iter().map(|_| unreachable!()),
1760 }
1761 }
1762}
1763
1764#[derive(Clone, Debug)]
1765pub struct OccurrenceValuesRef<'a, T> {
1766 #[allow(clippy::type_complexity)]
1767 iter: Map<Iter<'a, AnyValue>, fn(&AnyValue) -> &T>,
1768}
1769
1770impl<'a, T> Iterator for OccurrenceValuesRef<'a, T>
1771where
1772 Self: 'a,
1773{
1774 type Item = &'a T;
1775
1776 fn next(&mut self) -> Option<Self::Item> {
1777 self.iter.next()
1778 }
1779
1780 fn size_hint(&self) -> (usize, Option<usize>) {
1781 self.iter.size_hint()
1782 }
1783}
1784
1785impl<'a, T> DoubleEndedIterator for OccurrenceValuesRef<'a, T>
1786where
1787 Self: 'a,
1788{
1789 fn next_back(&mut self) -> Option<Self::Item> {
1790 self.iter.next_back()
1791 }
1792}
1793
1794impl<'a, T> ExactSizeIterator for OccurrenceValuesRef<'a, T> where Self: 'a {}
1795
1796#[derive(Clone, Debug)]
1797pub struct RawOccurrences<'a> {
1798 #[allow(clippy::type_complexity)]
1799 iter: Map<Iter<'a, Vec<OsString>>, fn(&Vec<OsString>) -> RawOccurrenceValues<'_>>,
1800}
1801
1802impl<'a> Iterator for RawOccurrences<'a> {
1803 type Item = RawOccurrenceValues<'a>;
1804
1805 fn next(&mut self) -> Option<Self::Item> {
1806 self.iter.next()
1807 }
1808
1809 fn size_hint(&self) -> (usize, Option<usize>) {
1810 self.iter.size_hint()
1811 }
1812}
1813
1814impl DoubleEndedIterator for RawOccurrences<'_> {
1815 fn next_back(&mut self) -> Option<Self::Item> {
1816 self.iter.next_back()
1817 }
1818}
1819
1820impl ExactSizeIterator for RawOccurrences<'_> {}
1821
1822impl Default for RawOccurrences<'_> {
1823 fn default() -> Self {
1824 static EMPTY: [Vec<OsString>; 0] = [];
1825 RawOccurrences {
1826 iter: EMPTY[..].iter().map(|_| unreachable!()),
1827 }
1828 }
1829}
1830
1831#[derive(Clone, Debug)]
1832pub struct RawOccurrenceValues<'a> {
1833 #[allow(clippy::type_complexity)]
1834 iter: Map<Iter<'a, OsString>, fn(&OsString) -> &OsStr>,
1835}
1836
1837impl<'a> Iterator for RawOccurrenceValues<'a>
1838where
1839 Self: 'a,
1840{
1841 type Item = &'a OsStr;
1842
1843 fn next(&mut self) -> Option<Self::Item> {
1844 self.iter.next()
1845 }
1846
1847 fn size_hint(&self) -> (usize, Option<usize>) {
1848 self.iter.size_hint()
1849 }
1850}
1851
1852impl<'a> DoubleEndedIterator for RawOccurrenceValues<'a>
1853where
1854 Self: 'a,
1855{
1856 fn next_back(&mut self) -> Option<Self::Item> {
1857 self.iter.next_back()
1858 }
1859}
1860
1861impl ExactSizeIterator for RawOccurrenceValues<'_> {}
1862
1863/// Iterate over indices for where an argument appeared when parsing, via [`ArgMatches::indices_of`]
1864///
1865/// # Examples
1866///
1867/// ```rust
1868/// # use clap_builder as clap;
1869/// # use clap::{Command, Arg, ArgAction};
1870/// let m = Command::new("myapp")
1871/// .arg(Arg::new("output")
1872/// .short('o')
1873/// .num_args(1..)
1874/// .action(ArgAction::Set))
1875/// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]);
1876///
1877/// let mut indices = m.indices_of("output").unwrap();
1878///
1879/// assert_eq!(indices.next(), Some(2));
1880/// assert_eq!(indices.next(), Some(3));
1881/// assert_eq!(indices.next(), None);
1882/// ```
1883/// [`ArgMatches::indices_of`]: ArgMatches::indices_of()
1884#[derive(Clone, Debug)]
1885pub struct Indices<'a> {
1886 iter: Cloned<Iter<'a, usize>>,
1887 len: usize,
1888}
1889
1890impl Iterator for Indices<'_> {
1891 type Item = usize;
1892
1893 fn next(&mut self) -> Option<usize> {
1894 if let Some(next) = self.iter.next() {
1895 self.len -= 1;
1896 Some(next)
1897 } else {
1898 None
1899 }
1900 }
1901 fn size_hint(&self) -> (usize, Option<usize>) {
1902 (self.len, Some(self.len))
1903 }
1904}
1905
1906impl DoubleEndedIterator for Indices<'_> {
1907 fn next_back(&mut self) -> Option<usize> {
1908 if let Some(next) = self.iter.next_back() {
1909 self.len -= 1;
1910 Some(next)
1911 } else {
1912 None
1913 }
1914 }
1915}
1916
1917impl ExactSizeIterator for Indices<'_> {}
1918
1919/// Creates an empty iterator.
1920impl Default for Indices<'_> {
1921 fn default() -> Self {
1922 static EMPTY: [usize; 0] = [];
1923 // This is never called because the iterator is empty:
1924 Indices {
1925 iter: EMPTY[..].iter().cloned(),
1926 len: 0,
1927 }
1928 }
1929}
1930
1931#[track_caller]
1932fn unwrap_downcast_ref<T: Any + Clone + Send + Sync + 'static>(value: &AnyValue) -> &T {
1933 value.downcast_ref().expect(INTERNAL_ERROR_MSG)
1934}
1935
1936#[track_caller]
1937fn unwrap_downcast_into<T: Any + Clone + Send + Sync + 'static>(value: AnyValue) -> T {
1938 value.downcast_into().expect(INTERNAL_ERROR_MSG)
1939}
1940
1941#[cfg(test)]
1942mod tests {
1943 use super::*;
1944
1945 use crate::ArgAction;
1946
1947 #[test]
1948 fn check_auto_traits() {
1949 static_assertions::assert_impl_all!(ArgMatches: Send, Sync, Unpin);
1950 }
1951
1952 #[test]
1953 fn test_default_raw_values() {
1954 let mut values: RawValues<'_> = Default::default();
1955 assert_eq!(values.next(), None);
1956 }
1957
1958 #[test]
1959 fn test_default_indices() {
1960 let mut indices: Indices<'_> = Indices::default();
1961 assert_eq!(indices.next(), None);
1962 }
1963
1964 #[test]
1965 fn test_default_indices_with_shorter_lifetime() {
1966 let matches = ArgMatches::default();
1967 let mut indices = matches.indices_of("").unwrap_or_default();
1968 assert_eq!(indices.next(), None);
1969 }
1970
1971 #[test]
1972 fn values_exact_size() {
1973 let l = crate::Command::new("test")
1974 .arg(
1975 crate::Arg::new("POTATO")
1976 .action(ArgAction::Set)
1977 .num_args(1..)
1978 .required(true),
1979 )
1980 .try_get_matches_from(["test", "one"])
1981 .unwrap()
1982 .get_many::<String>("POTATO")
1983 .expect("present")
1984 .count();
1985 assert_eq!(l, 1);
1986 }
1987
1988 #[test]
1989 fn os_values_exact_size() {
1990 let l = crate::Command::new("test")
1991 .arg(
1992 crate::Arg::new("POTATO")
1993 .action(ArgAction::Set)
1994 .num_args(1..)
1995 .value_parser(crate::builder::ValueParser::os_string())
1996 .required(true),
1997 )
1998 .try_get_matches_from(["test", "one"])
1999 .unwrap()
2000 .get_many::<OsString>("POTATO")
2001 .expect("present")
2002 .count();
2003 assert_eq!(l, 1);
2004 }
2005
2006 #[test]
2007 fn indices_exact_size() {
2008 let l = crate::Command::new("test")
2009 .arg(
2010 crate::Arg::new("POTATO")
2011 .action(ArgAction::Set)
2012 .num_args(1..)
2013 .required(true),
2014 )
2015 .try_get_matches_from(["test", "one"])
2016 .unwrap()
2017 .indices_of("POTATO")
2018 .expect("present")
2019 .len();
2020 assert_eq!(l, 1);
2021 }
2022
2023 #[test]
2024 fn rev_iter() {
2025 let mut matches = crate::Command::new("myprog")
2026 .arg(crate::Arg::new("a").short('a').action(ArgAction::Append))
2027 .arg(crate::Arg::new("b").short('b').action(ArgAction::Append))
2028 .try_get_matches_from(vec!["myprog", "-a1", "-b1", "-b3"])
2029 .unwrap();
2030
2031 let a_index = matches
2032 .indices_of("a")
2033 .expect("missing aopt indices")
2034 .collect::<Vec<_>>();
2035 dbg!(&a_index);
2036 let a_value = matches
2037 .remove_many::<String>("a")
2038 .expect("missing aopt values");
2039 dbg!(&a_value);
2040 let a = a_index.into_iter().zip(a_value).rev().collect::<Vec<_>>();
2041 dbg!(a);
2042
2043 let b_index = matches
2044 .indices_of("b")
2045 .expect("missing aopt indices")
2046 .collect::<Vec<_>>();
2047 dbg!(&b_index);
2048 let b_value = matches
2049 .remove_many::<String>("b")
2050 .expect("missing aopt values");
2051 dbg!(&b_value);
2052 let b = b_index.into_iter().zip(b_value).rev().collect::<Vec<_>>();
2053 dbg!(b);
2054 }
2055}