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