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