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 /// Clears the values for the given `id`
1231 ///
1232 /// Alternative to [`try_remove_*`][ArgMatches::try_remove_one] when the type is not known.
1233 ///
1234 /// Returns `Err([``MatchesError``])` if the given `id` isn't valid for current `ArgMatches` instance.
1235 ///
1236 /// Returns `Ok(true)` if there were any matches with the given `id`, `Ok(false)` otherwise.
1237 pub fn try_clear_id(&mut self, id: &str) -> Result<bool, MatchesError> {
1238 ok!(self.verify_arg(id));
1239 Ok(self.args.remove_entry(id).is_some())
1240 }
1241}
1242
1243// Private methods
1244impl ArgMatches {
1245 #[inline]
1246 fn try_get_arg(&self, arg: &str) -> Result<Option<&MatchedArg>, MatchesError> {
1247 ok!(self.verify_arg(arg));
1248 Ok(self.args.get(arg))
1249 }
1250
1251 #[inline]
1252 fn try_get_arg_t<T: Any + Send + Sync + 'static>(
1253 &self,
1254 arg: &str,
1255 ) -> Result<Option<&MatchedArg>, MatchesError> {
1256 let arg = match ok!(self.try_get_arg(arg)) {
1257 Some(arg) => arg,
1258 None => {
1259 return Ok(None);
1260 }
1261 };
1262 ok!(self.verify_arg_t::<T>(arg));
1263 Ok(Some(arg))
1264 }
1265
1266 #[inline]
1267 fn try_remove_arg_t<T: Any + Send + Sync + 'static>(
1268 &mut self,
1269 arg: &str,
1270 ) -> Result<Option<MatchedArg>, MatchesError> {
1271 ok!(self.verify_arg(arg));
1272 let (id, matched) = match self.args.remove_entry(arg) {
1273 Some((id, matched)) => (id, matched),
1274 None => {
1275 return Ok(None);
1276 }
1277 };
1278
1279 let expected = AnyValueId::of::<T>();
1280 let actual = matched.infer_type_id(expected);
1281 if actual == expected {
1282 Ok(Some(matched))
1283 } else {
1284 self.args.insert(id, matched);
1285 Err(MatchesError::Downcast { actual, expected })
1286 }
1287 }
1288
1289 fn verify_arg_t<T: Any + Send + Sync + 'static>(
1290 &self,
1291 arg: &MatchedArg,
1292 ) -> Result<(), MatchesError> {
1293 let expected = AnyValueId::of::<T>();
1294 let actual = arg.infer_type_id(expected);
1295 if expected == actual {
1296 Ok(())
1297 } else {
1298 Err(MatchesError::Downcast { actual, expected })
1299 }
1300 }
1301
1302 #[inline]
1303 fn verify_arg(&self, _arg: &str) -> Result<(), MatchesError> {
1304 #[cfg(debug_assertions)]
1305 {
1306 if _arg == Id::EXTERNAL || self.valid_args.iter().any(|s| *s == _arg) {
1307 } else {
1308 debug!(
1309 "`{:?}` is not an id of an argument or a group.\n\
1310 Make sure you're using the name of the argument itself \
1311 and not the name of short or long flags.",
1312 _arg
1313 );
1314 return Err(MatchesError::UnknownArgument {});
1315 }
1316 }
1317 Ok(())
1318 }
1319
1320 #[inline]
1321 #[cfg_attr(debug_assertions, track_caller)]
1322 fn get_arg<'s>(&'s self, arg: &str) -> Option<&'s MatchedArg> {
1323 #[cfg(debug_assertions)]
1324 {
1325 if arg == Id::EXTERNAL || self.valid_args.iter().any(|s| *s == arg) {
1326 } else {
1327 panic!(
1328 "`{arg:?}` is not an id of an argument or a group.\n\
1329 Make sure you're using the name of the argument itself \
1330 and not the name of short or long flags."
1331 );
1332 }
1333 }
1334
1335 self.args.get(arg)
1336 }
1337
1338 #[inline]
1339 #[cfg_attr(debug_assertions, track_caller)]
1340 fn get_subcommand(&self, name: &str) -> Option<&SubCommand> {
1341 #[cfg(debug_assertions)]
1342 {
1343 if name.is_empty() || self.valid_subcommands.iter().any(|s| *s == name) {
1344 } else {
1345 panic!("`{name}` is not a name of a subcommand.");
1346 }
1347 }
1348
1349 if let Some(ref sc) = self.subcommand {
1350 if sc.name == name {
1351 return Some(sc);
1352 }
1353 }
1354
1355 None
1356 }
1357}
1358
1359#[derive(Debug, Clone, PartialEq, Eq)]
1360pub(crate) struct SubCommand {
1361 pub(crate) name: String,
1362 pub(crate) matches: ArgMatches,
1363}
1364
1365/// Iterate over [`Arg`][crate::Arg] and [`ArgGroup`][crate::ArgGroup] [`Id`]s via [`ArgMatches::ids`].
1366///
1367/// # Examples
1368///
1369/// ```rust
1370/// # use clap_builder as clap;
1371/// # use clap::{Command, arg, value_parser};
1372///
1373/// let m = Command::new("myprog")
1374/// .arg(arg!(--color <when>)
1375/// .value_parser(["auto", "always", "never"]))
1376/// .arg(arg!(--config <path>)
1377/// .value_parser(value_parser!(std::path::PathBuf)))
1378/// .get_matches_from(["myprog", "--config=config.toml", "--color=auto"]);
1379/// assert_eq!(
1380/// m.ids()
1381/// .map(|id| id.as_str())
1382/// .collect::<Vec<_>>(),
1383/// ["config", "color"]
1384/// );
1385/// ```
1386#[derive(Clone, Debug)]
1387pub struct IdsRef<'a> {
1388 iter: Iter<'a, Id>,
1389}
1390
1391impl<'a> Iterator for IdsRef<'a> {
1392 type Item = &'a Id;
1393
1394 fn next(&mut self) -> Option<&'a Id> {
1395 self.iter.next()
1396 }
1397 fn size_hint(&self) -> (usize, Option<usize>) {
1398 self.iter.size_hint()
1399 }
1400}
1401
1402impl<'a> DoubleEndedIterator for IdsRef<'a> {
1403 fn next_back(&mut self) -> Option<&'a Id> {
1404 self.iter.next_back()
1405 }
1406}
1407
1408impl ExactSizeIterator for IdsRef<'_> {}
1409
1410/// Iterate over multiple values for an argument via [`ArgMatches::remove_many`].
1411///
1412/// # Examples
1413///
1414/// ```rust
1415/// # use clap_builder as clap;
1416/// # use clap::{Command, Arg, ArgAction};
1417/// let mut m = Command::new("myapp")
1418/// .arg(Arg::new("output")
1419/// .short('o')
1420/// .action(ArgAction::Append))
1421/// .get_matches_from(vec!["myapp", "-o", "val1", "-o", "val2"]);
1422///
1423/// let mut values = m.remove_many::<String>("output")
1424/// .unwrap();
1425///
1426/// assert_eq!(values.next(), Some(String::from("val1")));
1427/// assert_eq!(values.next(), Some(String::from("val2")));
1428/// assert_eq!(values.next(), None);
1429/// ```
1430#[derive(Clone, Debug)]
1431pub struct Values<T> {
1432 #[allow(clippy::type_complexity)]
1433 iter: Map<Flatten<std::vec::IntoIter<Vec<AnyValue>>>, fn(AnyValue) -> T>,
1434 len: usize,
1435}
1436
1437impl<T> Iterator for Values<T> {
1438 type Item = T;
1439
1440 fn next(&mut self) -> Option<Self::Item> {
1441 if let Some(next) = self.iter.next() {
1442 self.len -= 1;
1443 Some(next)
1444 } else {
1445 None
1446 }
1447 }
1448 fn size_hint(&self) -> (usize, Option<usize>) {
1449 (self.len, Some(self.len))
1450 }
1451}
1452
1453impl<T> DoubleEndedIterator for Values<T> {
1454 fn next_back(&mut self) -> Option<Self::Item> {
1455 if let Some(next) = self.iter.next_back() {
1456 self.len -= 1;
1457 Some(next)
1458 } else {
1459 None
1460 }
1461 }
1462}
1463
1464impl<T> ExactSizeIterator for Values<T> {}
1465
1466/// Creates an empty iterator.
1467impl<T> Default for Values<T> {
1468 fn default() -> Self {
1469 let empty: Vec<Vec<AnyValue>> = Default::default();
1470 Values {
1471 iter: empty.into_iter().flatten().map(|_| unreachable!()),
1472 len: 0,
1473 }
1474 }
1475}
1476
1477/// Iterate over multiple values for an argument via [`ArgMatches::get_many`].
1478///
1479/// # Examples
1480///
1481/// ```rust
1482/// # use clap_builder as clap;
1483/// # use clap::{Command, Arg, ArgAction};
1484/// let m = Command::new("myapp")
1485/// .arg(Arg::new("output")
1486/// .short('o')
1487/// .action(ArgAction::Append))
1488/// .get_matches_from(vec!["myapp", "-o", "val1", "-o", "val2"]);
1489///
1490/// let mut values = m.get_many::<String>("output")
1491/// .unwrap()
1492/// .map(|s| s.as_str());
1493///
1494/// assert_eq!(values.next(), Some("val1"));
1495/// assert_eq!(values.next(), Some("val2"));
1496/// assert_eq!(values.next(), None);
1497/// ```
1498#[derive(Clone, Debug)]
1499pub struct ValuesRef<'a, T> {
1500 #[allow(clippy::type_complexity)]
1501 iter: Map<Flatten<Iter<'a, Vec<AnyValue>>>, fn(&AnyValue) -> &T>,
1502 len: usize,
1503}
1504
1505impl<'a, T: 'a> Iterator for ValuesRef<'a, T> {
1506 type Item = &'a T;
1507
1508 fn next(&mut self) -> Option<Self::Item> {
1509 if let Some(next) = self.iter.next() {
1510 self.len -= 1;
1511 Some(next)
1512 } else {
1513 None
1514 }
1515 }
1516 fn size_hint(&self) -> (usize, Option<usize>) {
1517 (self.len, Some(self.len))
1518 }
1519}
1520
1521impl<'a, T: 'a> DoubleEndedIterator for ValuesRef<'a, T> {
1522 fn next_back(&mut self) -> Option<Self::Item> {
1523 if let Some(next) = self.iter.next_back() {
1524 self.len -= 1;
1525 Some(next)
1526 } else {
1527 None
1528 }
1529 }
1530}
1531
1532impl<'a, T: 'a> ExactSizeIterator for ValuesRef<'a, T> {}
1533
1534/// Creates an empty iterator.
1535impl<'a, T: 'a> Default for ValuesRef<'a, T> {
1536 fn default() -> Self {
1537 static EMPTY: [Vec<AnyValue>; 0] = [];
1538 ValuesRef {
1539 iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
1540 len: 0,
1541 }
1542 }
1543}
1544
1545/// Iterate over raw argument values via [`ArgMatches::get_raw`].
1546///
1547/// # Examples
1548///
1549/// ```rust
1550/// # #[cfg(unix)] {
1551/// # use clap_builder as clap;
1552/// # use clap::{Command, arg, value_parser};
1553/// use std::ffi::OsString;
1554/// use std::os::unix::ffi::{OsStrExt,OsStringExt};
1555///
1556/// let m = Command::new("utf8")
1557/// .arg(arg!(<arg> "some arg")
1558/// .value_parser(value_parser!(OsString)))
1559/// .get_matches_from(vec![OsString::from("myprog"),
1560/// // "Hi {0xe9}!"
1561/// OsString::from_vec(vec![b'H', b'i', b' ', 0xe9, b'!'])]);
1562/// assert_eq!(
1563/// &*m.get_raw("arg")
1564/// .unwrap()
1565/// .next().unwrap()
1566/// .as_bytes(),
1567/// [b'H', b'i', b' ', 0xe9, b'!']
1568/// );
1569/// # }
1570/// ```
1571#[derive(Clone, Debug)]
1572pub struct RawValues<'a> {
1573 #[allow(clippy::type_complexity)]
1574 iter: Map<Flatten<Iter<'a, Vec<OsString>>>, fn(&OsString) -> &OsStr>,
1575 len: usize,
1576}
1577
1578impl<'a> Iterator for RawValues<'a> {
1579 type Item = &'a OsStr;
1580
1581 fn next(&mut self) -> Option<&'a OsStr> {
1582 if let Some(next) = self.iter.next() {
1583 self.len -= 1;
1584 Some(next)
1585 } else {
1586 None
1587 }
1588 }
1589 fn size_hint(&self) -> (usize, Option<usize>) {
1590 (self.len, Some(self.len))
1591 }
1592}
1593
1594impl<'a> DoubleEndedIterator for RawValues<'a> {
1595 fn next_back(&mut self) -> Option<&'a OsStr> {
1596 if let Some(next) = self.iter.next_back() {
1597 self.len -= 1;
1598 Some(next)
1599 } else {
1600 None
1601 }
1602 }
1603}
1604
1605impl ExactSizeIterator for RawValues<'_> {}
1606
1607/// Creates an empty iterator.
1608impl Default for RawValues<'_> {
1609 fn default() -> Self {
1610 static EMPTY: [Vec<OsString>; 0] = [];
1611 RawValues {
1612 iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
1613 len: 0,
1614 }
1615 }
1616}
1617
1618// The following were taken and adapted from vec_map source
1619// repo: https://github.com/contain-rs/vec-map
1620// commit: be5e1fa3c26e351761b33010ddbdaf5f05dbcc33
1621// license: MIT - Copyright (c) 2015 The Rust Project Developers
1622
1623#[derive(Clone, Debug)]
1624#[deprecated(since = "4.1.0", note = "Use Occurrences instead")]
1625pub(crate) struct GroupedValues<'a> {
1626 #[allow(clippy::type_complexity)]
1627 iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> Vec<&str>>,
1628 len: usize,
1629}
1630
1631#[allow(deprecated)]
1632impl<'a> Iterator for GroupedValues<'a> {
1633 type Item = Vec<&'a str>;
1634
1635 fn next(&mut self) -> Option<Self::Item> {
1636 if let Some(next) = self.iter.next() {
1637 self.len -= 1;
1638 Some(next)
1639 } else {
1640 None
1641 }
1642 }
1643 fn size_hint(&self) -> (usize, Option<usize>) {
1644 (self.len, Some(self.len))
1645 }
1646}
1647
1648#[allow(deprecated)]
1649impl DoubleEndedIterator for GroupedValues<'_> {
1650 fn next_back(&mut self) -> Option<Self::Item> {
1651 if let Some(next) = self.iter.next_back() {
1652 self.len -= 1;
1653 Some(next)
1654 } else {
1655 None
1656 }
1657 }
1658}
1659
1660#[allow(deprecated)]
1661impl ExactSizeIterator for GroupedValues<'_> {}
1662
1663/// Creates an empty iterator. Used for `unwrap_or_default()`.
1664#[allow(deprecated)]
1665impl Default for GroupedValues<'_> {
1666 fn default() -> Self {
1667 static EMPTY: [Vec<AnyValue>; 0] = [];
1668 GroupedValues {
1669 iter: EMPTY[..].iter().map(|_| unreachable!()),
1670 len: 0,
1671 }
1672 }
1673}
1674
1675#[derive(Clone, Debug)]
1676pub struct Occurrences<T> {
1677 #[allow(clippy::type_complexity)]
1678 iter: Map<std::vec::IntoIter<Vec<AnyValue>>, fn(Vec<AnyValue>) -> OccurrenceValues<T>>,
1679}
1680
1681impl<T> Iterator for Occurrences<T> {
1682 type Item = OccurrenceValues<T>;
1683
1684 fn next(&mut self) -> Option<Self::Item> {
1685 self.iter.next()
1686 }
1687
1688 fn size_hint(&self) -> (usize, Option<usize>) {
1689 self.iter.size_hint()
1690 }
1691}
1692
1693impl<T> DoubleEndedIterator for Occurrences<T> {
1694 fn next_back(&mut self) -> Option<Self::Item> {
1695 self.iter.next_back()
1696 }
1697}
1698
1699impl<T> ExactSizeIterator for Occurrences<T> {}
1700
1701impl<T> Default for Occurrences<T> {
1702 fn default() -> Self {
1703 let empty: Vec<Vec<AnyValue>> = Default::default();
1704 Occurrences {
1705 iter: empty.into_iter().map(|_| unreachable!()),
1706 }
1707 }
1708}
1709
1710#[derive(Clone, Debug)]
1711pub struct OccurrenceValues<T> {
1712 #[allow(clippy::type_complexity)]
1713 iter: Map<std::vec::IntoIter<AnyValue>, fn(AnyValue) -> T>,
1714}
1715
1716impl<T> Iterator for OccurrenceValues<T> {
1717 type Item = T;
1718
1719 fn next(&mut self) -> Option<Self::Item> {
1720 self.iter.next()
1721 }
1722
1723 fn size_hint(&self) -> (usize, Option<usize>) {
1724 self.iter.size_hint()
1725 }
1726}
1727
1728impl<T> DoubleEndedIterator for OccurrenceValues<T> {
1729 fn next_back(&mut self) -> Option<Self::Item> {
1730 self.iter.next_back()
1731 }
1732}
1733
1734impl<T> ExactSizeIterator for OccurrenceValues<T> {}
1735
1736#[derive(Clone, Debug)]
1737pub struct OccurrencesRef<'a, T> {
1738 #[allow(clippy::type_complexity)]
1739 iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> OccurrenceValuesRef<'_, T>>,
1740}
1741
1742impl<'a, T> Iterator for OccurrencesRef<'a, T>
1743where
1744 Self: 'a,
1745{
1746 type Item = OccurrenceValuesRef<'a, T>;
1747
1748 fn next(&mut self) -> Option<Self::Item> {
1749 self.iter.next()
1750 }
1751
1752 fn size_hint(&self) -> (usize, Option<usize>) {
1753 self.iter.size_hint()
1754 }
1755}
1756
1757impl<'a, T> DoubleEndedIterator for OccurrencesRef<'a, T>
1758where
1759 Self: 'a,
1760{
1761 fn next_back(&mut self) -> Option<Self::Item> {
1762 self.iter.next_back()
1763 }
1764}
1765
1766impl<'a, T> ExactSizeIterator for OccurrencesRef<'a, T> where Self: 'a {}
1767impl<T> Default for OccurrencesRef<'_, T> {
1768 fn default() -> Self {
1769 static EMPTY: [Vec<AnyValue>; 0] = [];
1770 OccurrencesRef {
1771 iter: EMPTY[..].iter().map(|_| unreachable!()),
1772 }
1773 }
1774}
1775
1776#[derive(Clone, Debug)]
1777pub struct OccurrenceValuesRef<'a, T> {
1778 #[allow(clippy::type_complexity)]
1779 iter: Map<Iter<'a, AnyValue>, fn(&AnyValue) -> &T>,
1780}
1781
1782impl<'a, T> Iterator for OccurrenceValuesRef<'a, T>
1783where
1784 Self: 'a,
1785{
1786 type Item = &'a T;
1787
1788 fn next(&mut self) -> Option<Self::Item> {
1789 self.iter.next()
1790 }
1791
1792 fn size_hint(&self) -> (usize, Option<usize>) {
1793 self.iter.size_hint()
1794 }
1795}
1796
1797impl<'a, T> DoubleEndedIterator for OccurrenceValuesRef<'a, T>
1798where
1799 Self: 'a,
1800{
1801 fn next_back(&mut self) -> Option<Self::Item> {
1802 self.iter.next_back()
1803 }
1804}
1805
1806impl<'a, T> ExactSizeIterator for OccurrenceValuesRef<'a, T> where Self: 'a {}
1807
1808#[derive(Clone, Debug)]
1809pub struct RawOccurrences<'a> {
1810 #[allow(clippy::type_complexity)]
1811 iter: Map<Iter<'a, Vec<OsString>>, fn(&Vec<OsString>) -> RawOccurrenceValues<'_>>,
1812}
1813
1814impl<'a> Iterator for RawOccurrences<'a> {
1815 type Item = RawOccurrenceValues<'a>;
1816
1817 fn next(&mut self) -> Option<Self::Item> {
1818 self.iter.next()
1819 }
1820
1821 fn size_hint(&self) -> (usize, Option<usize>) {
1822 self.iter.size_hint()
1823 }
1824}
1825
1826impl DoubleEndedIterator for RawOccurrences<'_> {
1827 fn next_back(&mut self) -> Option<Self::Item> {
1828 self.iter.next_back()
1829 }
1830}
1831
1832impl ExactSizeIterator for RawOccurrences<'_> {}
1833
1834impl Default for RawOccurrences<'_> {
1835 fn default() -> Self {
1836 static EMPTY: [Vec<OsString>; 0] = [];
1837 RawOccurrences {
1838 iter: EMPTY[..].iter().map(|_| unreachable!()),
1839 }
1840 }
1841}
1842
1843#[derive(Clone, Debug)]
1844pub struct RawOccurrenceValues<'a> {
1845 #[allow(clippy::type_complexity)]
1846 iter: Map<Iter<'a, OsString>, fn(&OsString) -> &OsStr>,
1847}
1848
1849impl<'a> Iterator for RawOccurrenceValues<'a>
1850where
1851 Self: 'a,
1852{
1853 type Item = &'a OsStr;
1854
1855 fn next(&mut self) -> Option<Self::Item> {
1856 self.iter.next()
1857 }
1858
1859 fn size_hint(&self) -> (usize, Option<usize>) {
1860 self.iter.size_hint()
1861 }
1862}
1863
1864impl<'a> DoubleEndedIterator for RawOccurrenceValues<'a>
1865where
1866 Self: 'a,
1867{
1868 fn next_back(&mut self) -> Option<Self::Item> {
1869 self.iter.next_back()
1870 }
1871}
1872
1873impl ExactSizeIterator for RawOccurrenceValues<'_> {}
1874
1875/// Iterate over indices for where an argument appeared when parsing, via [`ArgMatches::indices_of`]
1876///
1877/// # Examples
1878///
1879/// ```rust
1880/// # use clap_builder as clap;
1881/// # use clap::{Command, Arg, ArgAction};
1882/// let m = Command::new("myapp")
1883/// .arg(Arg::new("output")
1884/// .short('o')
1885/// .num_args(1..)
1886/// .action(ArgAction::Set))
1887/// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]);
1888///
1889/// let mut indices = m.indices_of("output").unwrap();
1890///
1891/// assert_eq!(indices.next(), Some(2));
1892/// assert_eq!(indices.next(), Some(3));
1893/// assert_eq!(indices.next(), None);
1894/// ```
1895/// [`ArgMatches::indices_of`]: ArgMatches::indices_of()
1896#[derive(Clone, Debug)]
1897pub struct Indices<'a> {
1898 iter: Cloned<Iter<'a, usize>>,
1899 len: usize,
1900}
1901
1902impl Iterator for Indices<'_> {
1903 type Item = usize;
1904
1905 fn next(&mut self) -> Option<usize> {
1906 if let Some(next) = self.iter.next() {
1907 self.len -= 1;
1908 Some(next)
1909 } else {
1910 None
1911 }
1912 }
1913 fn size_hint(&self) -> (usize, Option<usize>) {
1914 (self.len, Some(self.len))
1915 }
1916}
1917
1918impl DoubleEndedIterator for Indices<'_> {
1919 fn next_back(&mut self) -> Option<usize> {
1920 if let Some(next) = self.iter.next_back() {
1921 self.len -= 1;
1922 Some(next)
1923 } else {
1924 None
1925 }
1926 }
1927}
1928
1929impl ExactSizeIterator for Indices<'_> {}
1930
1931/// Creates an empty iterator.
1932impl Default for Indices<'_> {
1933 fn default() -> Self {
1934 static EMPTY: [usize; 0] = [];
1935 // This is never called because the iterator is empty:
1936 Indices {
1937 iter: EMPTY[..].iter().cloned(),
1938 len: 0,
1939 }
1940 }
1941}
1942
1943#[track_caller]
1944fn unwrap_downcast_ref<T: Any + Clone + Send + Sync + 'static>(value: &AnyValue) -> &T {
1945 value.downcast_ref().expect(INTERNAL_ERROR_MSG)
1946}
1947
1948#[track_caller]
1949fn unwrap_downcast_into<T: Any + Clone + Send + Sync + 'static>(value: AnyValue) -> T {
1950 value.downcast_into().expect(INTERNAL_ERROR_MSG)
1951}
1952
1953#[cfg(test)]
1954mod tests {
1955 use super::*;
1956
1957 use crate::ArgAction;
1958
1959 #[test]
1960 fn check_auto_traits() {
1961 static_assertions::assert_impl_all!(ArgMatches: Send, Sync, Unpin);
1962 }
1963
1964 #[test]
1965 fn test_default_raw_values() {
1966 let mut values: RawValues<'_> = Default::default();
1967 assert_eq!(values.next(), None);
1968 }
1969
1970 #[test]
1971 fn test_default_indices() {
1972 let mut indices: Indices<'_> = Indices::default();
1973 assert_eq!(indices.next(), None);
1974 }
1975
1976 #[test]
1977 fn test_default_indices_with_shorter_lifetime() {
1978 let matches = ArgMatches::default();
1979 let mut indices = matches.indices_of("").unwrap_or_default();
1980 assert_eq!(indices.next(), None);
1981 }
1982
1983 #[test]
1984 fn 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 .required(true),
1991 )
1992 .try_get_matches_from(["test", "one"])
1993 .unwrap()
1994 .get_many::<String>("POTATO")
1995 .expect("present")
1996 .count();
1997 assert_eq!(l, 1);
1998 }
1999
2000 #[test]
2001 fn os_values_exact_size() {
2002 let l = crate::Command::new("test")
2003 .arg(
2004 crate::Arg::new("POTATO")
2005 .action(ArgAction::Set)
2006 .num_args(1..)
2007 .value_parser(crate::builder::ValueParser::os_string())
2008 .required(true),
2009 )
2010 .try_get_matches_from(["test", "one"])
2011 .unwrap()
2012 .get_many::<OsString>("POTATO")
2013 .expect("present")
2014 .count();
2015 assert_eq!(l, 1);
2016 }
2017
2018 #[test]
2019 fn indices_exact_size() {
2020 let l = crate::Command::new("test")
2021 .arg(
2022 crate::Arg::new("POTATO")
2023 .action(ArgAction::Set)
2024 .num_args(1..)
2025 .required(true),
2026 )
2027 .try_get_matches_from(["test", "one"])
2028 .unwrap()
2029 .indices_of("POTATO")
2030 .expect("present")
2031 .len();
2032 assert_eq!(l, 1);
2033 }
2034
2035 #[test]
2036 fn rev_iter() {
2037 let mut matches = crate::Command::new("myprog")
2038 .arg(crate::Arg::new("a").short('a').action(ArgAction::Append))
2039 .arg(crate::Arg::new("b").short('b').action(ArgAction::Append))
2040 .try_get_matches_from(vec!["myprog", "-a1", "-b1", "-b3"])
2041 .unwrap();
2042
2043 let a_index = matches
2044 .indices_of("a")
2045 .expect("missing aopt indices")
2046 .collect::<Vec<_>>();
2047 dbg!(&a_index);
2048 let a_value = matches
2049 .remove_many::<String>("a")
2050 .expect("missing aopt values");
2051 dbg!(&a_value);
2052 let a = a_index.into_iter().zip(a_value).rev().collect::<Vec<_>>();
2053 dbg!(a);
2054
2055 let b_index = matches
2056 .indices_of("b")
2057 .expect("missing aopt indices")
2058 .collect::<Vec<_>>();
2059 dbg!(&b_index);
2060 let b_value = matches
2061 .remove_many::<String>("b")
2062 .expect("missing aopt values");
2063 dbg!(&b_value);
2064 let b = b_index.into_iter().zip(b_value).rev().collect::<Vec<_>>();
2065 dbg!(b);
2066 }
2067
2068 #[test]
2069 fn delete_id_without_returning() {
2070 let mut matches = crate::Command::new("myprog")
2071 .arg(crate::Arg::new("a").short('a').action(ArgAction::Append))
2072 .arg(crate::Arg::new("b").short('b').action(ArgAction::Append))
2073 .arg(crate::Arg::new("c").short('c').action(ArgAction::Append))
2074 .try_get_matches_from(vec!["myprog", "-b1", "-a1", "-b2"])
2075 .unwrap();
2076 let matches_ids_count = matches.ids().count();
2077 assert_eq!(matches_ids_count, 2);
2078
2079 let _ = matches
2080 .try_clear_id("d")
2081 .expect_err("should fail due to there is no arg 'd'");
2082
2083 let c_was_presented = matches
2084 .try_clear_id("c")
2085 .expect("doesn't fail because there is no matches for 'c' argument");
2086 assert!(!c_was_presented);
2087 let matches_ids_count = matches.ids().count();
2088 assert_eq!(matches_ids_count, 2);
2089
2090 let b_was_presented = matches.try_clear_id("b").unwrap();
2091 assert!(b_was_presented);
2092 let matches_ids_count = matches.ids().count();
2093 assert_eq!(matches_ids_count, 1);
2094
2095 let a_was_presented = matches.try_clear_id("a").unwrap();
2096 assert!(a_was_presented);
2097 let matches_ids_count = matches.ids().count();
2098 assert_eq!(matches_ids_count, 0);
2099 }
2100}