summaryrefslogtreecommitdiffstats
path: root/vendor/clap/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/clap/src/parser')
-rw-r--r--vendor/clap/src/parser/arg_matcher.rs280
-rw-r--r--vendor/clap/src/parser/error.rs67
-rw-r--r--vendor/clap/src/parser/features/mod.rs1
-rw-r--r--vendor/clap/src/parser/features/suggestions.rs105
-rw-r--r--vendor/clap/src/parser/matches/any_value.rs112
-rw-r--r--vendor/clap/src/parser/matches/arg_matches.rs1896
-rw-r--r--vendor/clap/src/parser/matches/matched_arg.rs240
-rw-r--r--vendor/clap/src/parser/matches/mod.rs17
-rw-r--r--vendor/clap/src/parser/matches/value_source.rs11
-rw-r--r--vendor/clap/src/parser/mod.rs27
-rw-r--r--vendor/clap/src/parser/parser.rs1729
-rw-r--r--vendor/clap/src/parser/validator.rs692
12 files changed, 0 insertions, 5177 deletions
diff --git a/vendor/clap/src/parser/arg_matcher.rs b/vendor/clap/src/parser/arg_matcher.rs
deleted file mode 100644
index 22087e722..000000000
--- a/vendor/clap/src/parser/arg_matcher.rs
+++ /dev/null
@@ -1,280 +0,0 @@
-// Std
-use std::collections::HashMap;
-use std::ffi::OsString;
-use std::mem;
-use std::ops::Deref;
-
-// Internal
-use crate::builder::{Arg, ArgPredicate, Command};
-use crate::parser::AnyValue;
-use crate::parser::Identifier;
-use crate::parser::PendingArg;
-use crate::parser::{ArgMatches, MatchedArg, SubCommand, ValueSource};
-use crate::util::Id;
-use crate::INTERNAL_ERROR_MSG;
-
-#[derive(Debug, Default)]
-pub(crate) struct ArgMatcher {
- matches: ArgMatches,
- pending: Option<PendingArg>,
-}
-
-impl ArgMatcher {
- pub(crate) fn new(_cmd: &Command) -> Self {
- ArgMatcher {
- matches: ArgMatches {
- #[cfg(debug_assertions)]
- valid_args: {
- let args = _cmd.get_arguments().map(|a| a.id.clone());
- let groups = _cmd.get_groups().map(|g| g.id.clone());
- args.chain(groups).collect()
- },
- #[cfg(debug_assertions)]
- valid_subcommands: _cmd.get_subcommands().map(|sc| sc.get_id()).collect(),
- // HACK: Allow an external subcommand's ArgMatches be a stand-in for any ArgMatches
- // since users can't detect it and avoid the asserts.
- //
- // See clap-rs/clap#3263
- #[cfg(debug_assertions)]
- #[cfg(not(feature = "unstable-v4"))]
- disable_asserts: _cmd.is_allow_external_subcommands_set(),
- #[cfg(debug_assertions)]
- #[cfg(feature = "unstable-v4")]
- disable_asserts: false,
- ..Default::default()
- },
- pending: None,
- }
- }
-
- pub(crate) fn into_inner(self) -> ArgMatches {
- self.matches
- }
-
- pub(crate) fn propagate_globals(&mut self, global_arg_vec: &[Id]) {
- debug!(
- "ArgMatcher::get_global_values: global_arg_vec={:?}",
- global_arg_vec
- );
- let mut vals_map = HashMap::new();
- self.fill_in_global_values(global_arg_vec, &mut vals_map);
- }
-
- fn fill_in_global_values(
- &mut self,
- global_arg_vec: &[Id],
- vals_map: &mut HashMap<Id, MatchedArg>,
- ) {
- for global_arg in global_arg_vec {
- if let Some(ma) = self.get(global_arg) {
- // We have to check if the parent's global arg wasn't used but still exists
- // such as from a default value.
- //
- // For example, `myprog subcommand --global-arg=value` where `--global-arg` defines
- // a default value of `other` myprog would have an existing MatchedArg for
- // `--global-arg` where the value is `other`
- let to_update = if let Some(parent_ma) = vals_map.get(global_arg) {
- if parent_ma.source() > ma.source() {
- parent_ma
- } else {
- ma
- }
- } else {
- ma
- }
- .clone();
- vals_map.insert(global_arg.clone(), to_update);
- }
- }
- if let Some(ref mut sc) = self.matches.subcommand {
- let mut am = ArgMatcher {
- matches: mem::take(&mut sc.matches),
- pending: None,
- };
- am.fill_in_global_values(global_arg_vec, vals_map);
- mem::swap(&mut am.matches, &mut sc.matches);
- }
-
- for (name, matched_arg) in vals_map.iter_mut() {
- self.matches.args.insert(name.clone(), matched_arg.clone());
- }
- }
-
- pub(crate) fn get(&self, arg: &Id) -> Option<&MatchedArg> {
- self.matches.args.get(arg)
- }
-
- pub(crate) fn get_mut(&mut self, arg: &Id) -> Option<&mut MatchedArg> {
- self.matches.args.get_mut(arg)
- }
-
- pub(crate) fn remove(&mut self, arg: &Id) {
- self.matches.args.swap_remove(arg);
- }
-
- pub(crate) fn contains(&self, arg: &Id) -> bool {
- self.matches.args.contains_key(arg)
- }
-
- pub(crate) fn arg_ids(&self) -> indexmap::map::Keys<Id, MatchedArg> {
- self.matches.args.keys()
- }
-
- pub(crate) fn entry(&mut self, arg: &Id) -> indexmap::map::Entry<Id, MatchedArg> {
- self.matches.args.entry(arg.clone())
- }
-
- pub(crate) fn subcommand(&mut self, sc: SubCommand) {
- self.matches.subcommand = Some(Box::new(sc));
- }
-
- pub(crate) fn subcommand_name(&self) -> Option<&str> {
- self.matches.subcommand_name()
- }
-
- pub(crate) fn iter(&self) -> indexmap::map::Iter<Id, MatchedArg> {
- self.matches.args.iter()
- }
-
- pub(crate) fn check_explicit<'a>(&self, arg: &Id, predicate: ArgPredicate<'a>) -> bool {
- self.get(arg).map_or(false, |a| a.check_explicit(predicate))
- }
-
- pub(crate) fn start_custom_arg(&mut self, arg: &Arg, source: ValueSource) {
- let id = &arg.id;
- debug!(
- "ArgMatcher::start_custom_arg: id={:?}, source={:?}",
- id, source
- );
- let ma = self.entry(id).or_insert(MatchedArg::new_arg(arg));
- debug_assert_eq!(ma.type_id(), Some(arg.get_value_parser().type_id()));
- ma.set_source(source);
- ma.new_val_group();
- }
-
- pub(crate) fn start_custom_group(&mut self, id: &Id, source: ValueSource) {
- debug!(
- "ArgMatcher::start_custom_arg: id={:?}, source={:?}",
- id, source
- );
- let ma = self.entry(id).or_insert(MatchedArg::new_group());
- debug_assert_eq!(ma.type_id(), None);
- ma.set_source(source);
- ma.new_val_group();
- }
-
- pub(crate) fn start_occurrence_of_arg(&mut self, arg: &Arg) {
- let id = &arg.id;
- debug!("ArgMatcher::start_occurrence_of_arg: id={:?}", id);
- let ma = self.entry(id).or_insert(MatchedArg::new_arg(arg));
- debug_assert_eq!(ma.type_id(), Some(arg.get_value_parser().type_id()));
- ma.set_source(ValueSource::CommandLine);
- #[allow(deprecated)]
- ma.inc_occurrences();
- ma.new_val_group();
- }
-
- pub(crate) fn start_occurrence_of_group(&mut self, id: &Id) {
- debug!("ArgMatcher::start_occurrence_of_group: id={:?}", id);
- let ma = self.entry(id).or_insert(MatchedArg::new_group());
- debug_assert_eq!(ma.type_id(), None);
- ma.set_source(ValueSource::CommandLine);
- #[allow(deprecated)]
- ma.inc_occurrences();
- ma.new_val_group();
- }
-
- pub(crate) fn start_occurrence_of_external(&mut self, cmd: &crate::Command) {
- let id = &Id::empty_hash();
- debug!("ArgMatcher::start_occurrence_of_external: id={:?}", id,);
- let ma = self.entry(id).or_insert(MatchedArg::new_external(cmd));
- debug_assert_eq!(
- ma.type_id(),
- Some(
- cmd.get_external_subcommand_value_parser()
- .expect(INTERNAL_ERROR_MSG)
- .type_id()
- )
- );
- ma.set_source(ValueSource::CommandLine);
- #[allow(deprecated)]
- ma.inc_occurrences();
- ma.new_val_group();
- }
-
- pub(crate) fn add_val_to(&mut self, arg: &Id, val: AnyValue, raw_val: OsString) {
- let ma = self.get_mut(arg).expect(INTERNAL_ERROR_MSG);
- ma.append_val(val, raw_val);
- }
-
- pub(crate) fn add_index_to(&mut self, arg: &Id, idx: usize) {
- let ma = self.get_mut(arg).expect(INTERNAL_ERROR_MSG);
- ma.push_index(idx);
- }
-
- pub(crate) fn needs_more_vals(&self, o: &Arg) -> bool {
- let num_resolved = self.get(&o.id).map(|ma| ma.num_vals()).unwrap_or(0);
- let num_pending = self
- .pending
- .as_ref()
- .and_then(|p| (p.id == o.id).then(|| p.raw_vals.len()))
- .unwrap_or(0);
- let current_num = num_resolved + num_pending;
- debug!(
- "ArgMatcher::needs_more_vals: o={}, resolved={}, pending={}",
- o.name, num_resolved, num_pending
- );
- if current_num == 0 {
- true
- } else if let Some(num) = o.num_vals {
- debug!("ArgMatcher::needs_more_vals: num_vals...{}", num);
- #[allow(deprecated)]
- if o.is_multiple_occurrences_set() {
- (current_num % num) != 0
- } else {
- num != current_num
- }
- } else if let Some(num) = o.max_vals {
- debug!("ArgMatcher::needs_more_vals: max_vals...{}", num);
- current_num < num
- } else if o.min_vals.is_some() {
- debug!("ArgMatcher::needs_more_vals: min_vals...true");
- true
- } else {
- o.is_multiple_values_set()
- }
- }
-
- pub(crate) fn pending_arg_id(&self) -> Option<&Id> {
- self.pending.as_ref().map(|p| &p.id)
- }
-
- pub(crate) fn pending_values_mut(
- &mut self,
- id: &Id,
- ident: Option<Identifier>,
- ) -> &mut Vec<OsString> {
- let pending = self.pending.get_or_insert_with(|| PendingArg {
- id: id.clone(),
- ident,
- raw_vals: Default::default(),
- });
- debug_assert_eq!(pending.id, *id, "{}", INTERNAL_ERROR_MSG);
- if ident.is_some() {
- debug_assert_eq!(pending.ident, ident, "{}", INTERNAL_ERROR_MSG);
- }
- &mut pending.raw_vals
- }
-
- pub(crate) fn take_pending(&mut self) -> Option<PendingArg> {
- self.pending.take()
- }
-}
-
-impl Deref for ArgMatcher {
- type Target = ArgMatches;
-
- fn deref(&self) -> &Self::Target {
- &self.matches
- }
-}
diff --git a/vendor/clap/src/parser/error.rs b/vendor/clap/src/parser/error.rs
deleted file mode 100644
index caeba4b8f..000000000
--- a/vendor/clap/src/parser/error.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-use crate::util::Id;
-
-/// Violation of [`ArgMatches`][crate::ArgMatches] assumptions
-#[derive(Clone, Debug)]
-#[allow(missing_copy_implementations)] // We might add non-Copy types in the future
-#[non_exhaustive]
-pub enum MatchesError {
- /// Failed to downcast `AnyValue` to the specified type
- #[non_exhaustive]
- Downcast {
- /// Type for value stored in [`ArgMatches`][crate::ArgMatches]
- actual: super::AnyValueId,
- /// The target type to downcast to
- expected: super::AnyValueId,
- },
- /// Argument not defined in [`Command`][crate::Command]
- #[non_exhaustive]
- UnknownArgument {
- // Missing `id` but blocked on a public id type which will hopefully come with `unstable-v4`
- },
-}
-
-impl MatchesError {
- #[track_caller]
- pub(crate) fn unwrap<T>(id: &Id, r: Result<T, MatchesError>) -> T {
- let err = match r {
- Ok(t) => {
- return t;
- }
- Err(err) => err,
- };
- panic!(
- "Mismatch between definition and access of `{:?}`. {}",
- id, err
- )
- }
-}
-
-impl std::error::Error for MatchesError {}
-
-impl std::fmt::Display for MatchesError {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- match self {
- Self::Downcast { actual, expected } => {
- writeln!(
- f,
- "Could not downcast to {:?}, need to downcast to {:?}",
- expected, actual
- )
- }
- Self::UnknownArgument {} => {
- writeln!(f, "Unknown argument or group id. Make sure you are using the argument id and not the short or long flags")
- }
- }
- }
-}
-
-#[test]
-fn check_auto_traits() {
- static_assertions::assert_impl_all!(
- MatchesError: Send,
- Sync,
- std::panic::RefUnwindSafe,
- std::panic::UnwindSafe,
- Unpin
- );
-}
diff --git a/vendor/clap/src/parser/features/mod.rs b/vendor/clap/src/parser/features/mod.rs
deleted file mode 100644
index bdeb766ec..000000000
--- a/vendor/clap/src/parser/features/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub(crate) mod suggestions;
diff --git a/vendor/clap/src/parser/features/suggestions.rs b/vendor/clap/src/parser/features/suggestions.rs
deleted file mode 100644
index 9e46f3c9e..000000000
--- a/vendor/clap/src/parser/features/suggestions.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-#[cfg(feature = "suggestions")]
-use std::cmp::Ordering;
-
-// Internal
-use crate::builder::Command;
-
-/// Produces multiple strings from a given list of possible values which are similar
-/// to the passed in value `v` within a certain confidence by least confidence.
-/// Thus in a list of possible values like ["foo", "bar"], the value "fop" will yield
-/// `Some("foo")`, whereas "blark" would yield `None`.
-#[cfg(feature = "suggestions")]
-pub(crate) fn did_you_mean<T, I>(v: &str, possible_values: I) -> Vec<String>
-where
- T: AsRef<str>,
- I: IntoIterator<Item = T>,
-{
- let mut candidates: Vec<(f64, String)> = possible_values
- .into_iter()
- .map(|pv| (strsim::jaro_winkler(v, pv.as_ref()), pv.as_ref().to_owned()))
- .filter(|(confidence, _)| *confidence > 0.8)
- .collect();
- candidates.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal));
- candidates.into_iter().map(|(_, pv)| pv).collect()
-}
-
-#[cfg(not(feature = "suggestions"))]
-pub(crate) fn did_you_mean<T, I>(_: &str, _: I) -> Vec<String>
-where
- T: AsRef<str>,
- I: IntoIterator<Item = T>,
-{
- Vec::new()
-}
-
-/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
-pub(crate) fn did_you_mean_flag<'a, 'help, I, T>(
- arg: &str,
- remaining_args: &[&str],
- longs: I,
- subcommands: impl IntoIterator<Item = &'a mut Command<'help>>,
-) -> Option<(String, Option<String>)>
-where
- 'help: 'a,
- T: AsRef<str>,
- I: IntoIterator<Item = T>,
-{
- use crate::mkeymap::KeyType;
-
- match did_you_mean(arg, longs).pop() {
- Some(candidate) => Some((candidate, None)),
- None => subcommands
- .into_iter()
- .filter_map(|subcommand| {
- subcommand._build_self();
-
- let longs = subcommand.get_keymap().keys().filter_map(|a| {
- if let KeyType::Long(v) = a {
- Some(v.to_string_lossy().into_owned())
- } else {
- None
- }
- });
-
- let subcommand_name = subcommand.get_name();
-
- let candidate = did_you_mean(arg, longs).pop()?;
- let score = remaining_args.iter().position(|x| *x == subcommand_name)?;
- Some((score, (candidate, Some(subcommand_name.to_string()))))
- })
- .min_by_key(|(x, _)| *x)
- .map(|(_, suggestion)| suggestion),
- }
-}
-
-#[cfg(all(test, features = "suggestions"))]
-mod test {
- use super::*;
-
- #[test]
- fn possible_values_match() {
- let p_vals = ["test", "possible", "values"];
- assert_eq!(did_you_mean("tst", p_vals.iter()), Some("test"));
- }
-
- #[test]
- fn possible_values_match() {
- let p_vals = ["test", "temp"];
- assert_eq!(did_you_mean("te", p_vals.iter()), Some("test"));
- }
-
- #[test]
- fn possible_values_nomatch() {
- let p_vals = ["test", "possible", "values"];
- assert!(did_you_mean("hahaahahah", p_vals.iter()).is_none());
- }
-
- #[test]
- fn flag() {
- let p_vals = ["test", "possible", "values"];
- assert_eq!(
- did_you_mean_flag("tst", p_vals.iter(), []),
- Some(("test", None))
- );
- }
-}
diff --git a/vendor/clap/src/parser/matches/any_value.rs b/vendor/clap/src/parser/matches/any_value.rs
deleted file mode 100644
index a9277e75f..000000000
--- a/vendor/clap/src/parser/matches/any_value.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-#[derive(Clone)]
-pub(crate) struct AnyValue {
- inner: std::sync::Arc<dyn std::any::Any + Send + Sync + 'static>,
- // While we can extract `TypeId` from `inner`, the debug repr is of a number, so let's track
- // the type_name in debug builds.
- id: AnyValueId,
-}
-
-impl AnyValue {
- pub(crate) fn new<V: std::any::Any + Clone + Send + Sync + 'static>(inner: V) -> Self {
- let id = AnyValueId::of::<V>();
- let inner = std::sync::Arc::new(inner);
- Self { inner, id }
- }
-
- pub(crate) fn downcast_ref<T: std::any::Any + Clone + Send + Sync + 'static>(
- &self,
- ) -> Option<&T> {
- self.inner.downcast_ref::<T>()
- }
-
- pub(crate) fn downcast_into<T: std::any::Any + Clone + Send + Sync>(self) -> Result<T, Self> {
- let id = self.id;
- let value =
- std::sync::Arc::downcast::<T>(self.inner).map_err(|inner| Self { inner, id })?;
- let value = std::sync::Arc::try_unwrap(value).unwrap_or_else(|arc| (*arc).clone());
- Ok(value)
- }
-
- pub(crate) fn type_id(&self) -> AnyValueId {
- self.id
- }
-}
-
-impl std::fmt::Debug for AnyValue {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
- f.debug_struct("AnyValue").field("inner", &self.id).finish()
- }
-}
-
-#[derive(Copy, Clone)]
-pub struct AnyValueId {
- type_id: std::any::TypeId,
- #[cfg(debug_assertions)]
- type_name: &'static str,
-}
-
-impl AnyValueId {
- pub(crate) fn of<A: ?Sized + 'static>() -> Self {
- Self {
- type_id: std::any::TypeId::of::<A>(),
- #[cfg(debug_assertions)]
- type_name: std::any::type_name::<A>(),
- }
- }
-}
-
-impl PartialEq for AnyValueId {
- fn eq(&self, other: &Self) -> bool {
- self.type_id == other.type_id
- }
-}
-
-impl Eq for AnyValueId {}
-
-impl PartialOrd for AnyValueId {
- fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
- self.type_id.partial_cmp(&other.type_id)
- }
-}
-
-impl Ord for AnyValueId {
- fn cmp(&self, other: &Self) -> std::cmp::Ordering {
- self.type_id.cmp(&other.type_id)
- }
-}
-
-impl std::hash::Hash for AnyValueId {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- self.type_id.hash(state);
- }
-}
-
-impl std::fmt::Debug for AnyValueId {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
- #[cfg(not(debug_assertions))]
- {
- self.type_id.fmt(f)
- }
- #[cfg(debug_assertions)]
- {
- f.debug_struct(self.type_name).finish()
- }
- }
-}
-
-impl<'a, A: ?Sized + 'static> From<&'a A> for AnyValueId {
- fn from(_: &'a A) -> Self {
- Self::of::<A>()
- }
-}
-
-#[cfg(test)]
-mod test {
- #[test]
- #[cfg(debug_assertions)]
- fn debug_impl() {
- use super::*;
-
- assert_eq!(format!("{:?}", AnyValue::new(5)), "AnyValue { inner: i32 }");
- }
-}
diff --git a/vendor/clap/src/parser/matches/arg_matches.rs b/vendor/clap/src/parser/matches/arg_matches.rs
deleted file mode 100644
index 2585c0219..000000000
--- a/vendor/clap/src/parser/matches/arg_matches.rs
+++ /dev/null
@@ -1,1896 +0,0 @@
-// Std
-use std::any::Any;
-use std::borrow::Cow;
-use std::ffi::{OsStr, OsString};
-use std::fmt::{Debug, Display};
-use std::iter::{Cloned, Flatten, Map};
-use std::slice::Iter;
-use std::str::FromStr;
-
-// Third Party
-use indexmap::IndexMap;
-
-// Internal
-use crate::parser::AnyValue;
-use crate::parser::AnyValueId;
-use crate::parser::MatchedArg;
-use crate::parser::MatchesError;
-use crate::parser::ValueSource;
-use crate::util::{Id, Key};
-use crate::Error;
-use crate::INTERNAL_ERROR_MSG;
-
-/// Container for parse results.
-///
-/// Used to get information about the arguments that were supplied to the program at runtime by
-/// the user. New instances of this struct are obtained by using the [`Command::get_matches`] family of
-/// methods.
-///
-/// # Examples
-///
-/// ```no_run
-/// # use clap::{Command, Arg, ValueSource};
-/// let matches = Command::new("MyApp")
-/// .arg(Arg::new("out")
-/// .long("output")
-/// .required(true)
-/// .takes_value(true)
-/// .default_value("-"))
-/// .arg(Arg::new("cfg")
-/// .short('c')
-/// .takes_value(true))
-/// .get_matches(); // builds the instance of ArgMatches
-///
-/// // to get information about the "cfg" argument we created, such as the value supplied we use
-/// // various ArgMatches methods, such as [ArgMatches::get_one]
-/// if let Some(c) = matches.get_one::<String>("cfg") {
-/// println!("Value for -c: {}", c);
-/// }
-///
-/// // The ArgMatches::get_one method returns an Option because the user may not have supplied
-/// // that argument at runtime. But if we specified that the argument was "required" as we did
-/// // with the "out" argument, we can safely unwrap because `clap` verifies that was actually
-/// // used at runtime.
-/// println!("Value for --output: {}", matches.get_one::<String>("out").unwrap());
-///
-/// // You can check the presence of an argument's values
-/// if matches.contains_id("out") {
-/// // However, if you want to know where the value came from
-/// if matches.value_source("out").expect("checked contains_id") == ValueSource::CommandLine {
-/// println!("`out` set by user");
-/// } else {
-/// println!("`out` is defaulted");
-/// }
-/// }
-/// ```
-/// [`Command::get_matches`]: crate::Command::get_matches()
-#[derive(Debug, Clone, Default, PartialEq, Eq)]
-pub struct ArgMatches {
- #[cfg(debug_assertions)]
- pub(crate) valid_args: Vec<Id>,
- #[cfg(debug_assertions)]
- pub(crate) valid_subcommands: Vec<Id>,
- #[cfg(debug_assertions)]
- pub(crate) disable_asserts: bool,
- pub(crate) args: IndexMap<Id, MatchedArg>,
- pub(crate) subcommand: Option<Box<SubCommand>>,
-}
-
-/// # Arguments
-impl ArgMatches {
- /// Gets the value of a specific option or positional argument.
- ///
- /// i.e. an argument that [takes an additional value][crate::Arg::takes_value] at runtime.
- ///
- /// Returns an error if the wrong type was used.
- ///
- /// Returns `None` if the option wasn't present.
- ///
- /// *NOTE:* This will always return `Some(value)` if [`default_value`] has been set.
- /// [`ArgMatches::value_source`] can be used to check if a value is present at runtime.
- ///
- /// # Panic
- ///
- /// If the argument definition and access mismatch. To handle this case programmatically, see
- /// [`ArgMatches::try_get_one`].
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::{Command, Arg, value_parser};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("port")
- /// .value_parser(value_parser!(usize))
- /// .takes_value(true)
- /// .required(true))
- /// .get_matches_from(vec!["myapp", "2020"]);
- ///
- /// let port: usize = *m
- /// .get_one("port")
- /// .expect("`port`is required");
- /// assert_eq!(port, 2020);
- /// ```
- /// [option]: crate::Arg::takes_value()
- /// [positional]: crate::Arg::index()
- /// [`default_value`]: crate::Arg::default_value()
- #[track_caller]
- pub fn get_one<T: Any + Clone + Send + Sync + 'static>(&self, id: &str) -> Option<&T> {
- let internal_id = Id::from(id);
- MatchesError::unwrap(&internal_id, self.try_get_one(id))
- }
-
- /// Gets the value of a specific [`ArgAction::Count`][crate::ArgAction::Count] flag
- ///
- /// # Panic
- ///
- /// If the argument's action is not [`ArgAction::Count`][crate::ArgAction::Count]
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::Command;
- /// # use clap::Arg;
- /// let cmd = Command::new("mycmd")
- /// .arg(
- /// Arg::new("flag")
- /// .long("flag")
- /// .action(clap::ArgAction::Count)
- /// );
- ///
- /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag", "--flag"]).unwrap();
- /// assert_eq!(
- /// matches.get_count("flag"),
- /// 2
- /// );
- /// ```
- #[track_caller]
- pub fn get_count(&self, id: &str) -> u8 {
- *self
- .get_one::<u8>(id)
- .expect("ArgAction::Count is defaulted")
- }
-
- /// Gets the value of a specific [`ArgAction::SetTrue`][crate::ArgAction::SetTrue] or [`ArgAction::SetFalse`][crate::ArgAction::SetFalse] flag
- ///
- /// # Panic
- ///
- /// If the argument's action is not [`ArgAction::SetTrue`][crate::ArgAction::SetTrue] or [`ArgAction::SetFalse`][crate::ArgAction::SetFalse]
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::Command;
- /// # use clap::Arg;
- /// let cmd = Command::new("mycmd")
- /// .arg(
- /// Arg::new("flag")
- /// .long("flag")
- /// .action(clap::ArgAction::SetTrue)
- /// );
- ///
- /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag", "--flag"]).unwrap();
- /// assert!(matches.contains_id("flag"));
- /// assert_eq!(
- /// matches.get_flag("flag"),
- /// true
- /// );
- /// ```
- #[track_caller]
- pub fn get_flag(&self, id: &str) -> bool {
- *self
- .get_one::<bool>(id)
- .expect("ArgAction::SetTrue / ArgAction::SetFalse is defaulted")
- }
-
- /// Iterate over values of a specific option or positional argument.
- ///
- /// i.e. an argument that takes multiple values at runtime.
- ///
- /// Returns an error if the wrong type was used.
- ///
- /// Returns `None` if the option wasn't present.
- ///
- /// # Panic
- ///
- /// If the argument definition and access mismatch. To handle this case programmatically, see
- /// [`ArgMatches::try_get_many`].
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::{Command, Arg, value_parser, ArgAction};
- /// let m = Command::new("myprog")
- /// .arg(Arg::new("ports")
- /// .action(ArgAction::Append)
- /// .value_parser(value_parser!(usize))
- /// .short('p')
- /// .takes_value(true)
- /// .required(true))
- /// .get_matches_from(vec![
- /// "myprog", "-p", "22", "-p", "80", "-p", "2020"
- /// ]);
- /// let vals: Vec<usize> = m.get_many("ports")
- /// .expect("`port`is required")
- /// .copied()
- /// .collect();
- /// assert_eq!(vals, [22, 80, 2020]);
- /// ```
- #[track_caller]
- pub fn get_many<T: Any + Clone + Send + Sync + 'static>(
- &self,
- id: &str,
- ) -> Option<ValuesRef<T>> {
- let internal_id = Id::from(id);
- MatchesError::unwrap(&internal_id, self.try_get_many(id))
- }
-
- /// Iterate over the original argument values.
- ///
- /// An `OsStr` on Unix-like systems is any series of bytes, regardless of whether or not they
- /// contain valid UTF-8. Since [`String`]s in Rust are guaranteed to be valid UTF-8, a valid
- /// filename on a Unix system as an argument value may contain invalid UTF-8.
- ///
- /// Returns `None` if the option wasn't present.
- ///
- /// # Panic
- ///
- /// If the argument definition and access mismatch. To handle this case programmatically, see
- /// [`ArgMatches::try_get_raw`].
- ///
- /// # Examples
- ///
- #[cfg_attr(not(unix), doc = " ```ignore")]
- #[cfg_attr(unix, doc = " ```")]
- /// # use clap::{Command, arg, value_parser};
- /// # use std::ffi::{OsStr,OsString};
- /// # use std::os::unix::ffi::{OsStrExt,OsStringExt};
- /// use std::path::PathBuf;
- ///
- /// let m = Command::new("utf8")
- /// .arg(arg!(<arg> ... "some arg").value_parser(value_parser!(PathBuf)))
- /// .get_matches_from(vec![OsString::from("myprog"),
- /// // "Hi"
- /// OsString::from_vec(vec![b'H', b'i']),
- /// // "{0xe9}!"
- /// OsString::from_vec(vec![0xe9, b'!'])]);
- ///
- /// let mut itr = m.get_raw("arg")
- /// .expect("`port`is required")
- /// .into_iter();
- /// assert_eq!(itr.next(), Some(OsStr::new("Hi")));
- /// assert_eq!(itr.next(), Some(OsStr::from_bytes(&[0xe9, b'!'])));
- /// assert_eq!(itr.next(), None);
- /// ```
- /// [`Iterator`]: std::iter::Iterator
- /// [`OsSt`]: std::ffi::OsStr
- /// [values]: OsValues
- /// [`String`]: std::string::String
- #[track_caller]
- pub fn get_raw(&self, id: &str) -> Option<RawValues<'_>> {
- let internal_id = Id::from(id);
- MatchesError::unwrap(&internal_id, self.try_get_raw(id))
- }
-
- /// Returns the value of a specific option or positional argument.
- ///
- /// i.e. an argument that [takes an additional value][crate::Arg::takes_value] at runtime.
- ///
- /// Returns an error if the wrong type was used. No item will have been removed.
- ///
- /// Returns `None` if the option wasn't present.
- ///
- /// *NOTE:* This will always return `Some(value)` if [`default_value`] has been set.
- /// [`ArgMatches::value_source`] can be used to check if a value is present at runtime.
- ///
- /// # Panic
- ///
- /// If the argument definition and access mismatch. To handle this case programmatically, see
- /// [`ArgMatches::try_remove_one`].
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::{Command, Arg, value_parser};
- /// let mut m = Command::new("myprog")
- /// .arg(Arg::new("file")
- /// .required(true)
- /// .takes_value(true))
- /// .get_matches_from(vec![
- /// "myprog", "file.txt",
- /// ]);
- /// let vals: String = m.remove_one("file")
- /// .expect("`file`is required");
- /// assert_eq!(vals, "file.txt");
- /// ```
- /// [option]: crate::Arg::takes_value()
- /// [positional]: crate::Arg::index()
- /// [`default_value`]: crate::Arg::default_value()
- #[track_caller]
- pub fn remove_one<T: Any + Clone + Send + Sync + 'static>(&mut self, id: &str) -> Option<T> {
- let internal_id = Id::from(id);
- MatchesError::unwrap(&internal_id, self.try_remove_one(id))
- }
-
- /// Return values of a specific option or positional argument.
- ///
- /// i.e. an argument that takes multiple values at runtime.
- ///
- /// Returns an error if the wrong type was used. No item will have been removed.
- ///
- /// Returns `None` if the option wasn't present.
- ///
- /// # Panic
- ///
- /// If the argument definition and access mismatch. To handle this case programmatically, see
- /// [`ArgMatches::try_remove_many`].
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::{Command, Arg, value_parser, ArgAction};
- /// let mut m = Command::new("myprog")
- /// .arg(Arg::new("file")
- /// .action(ArgAction::Append)
- /// .multiple_values(true)
- /// .required(true)
- /// .takes_value(true))
- /// .get_matches_from(vec![
- /// "myprog", "file1.txt", "file2.txt", "file3.txt", "file4.txt",
- /// ]);
- /// let vals: Vec<String> = m.remove_many("file")
- /// .expect("`file`is required")
- /// .collect();
- /// assert_eq!(vals, ["file1.txt", "file2.txt", "file3.txt", "file4.txt"]);
- /// ```
- #[track_caller]
- pub fn remove_many<T: Any + Clone + Send + Sync + 'static>(
- &mut self,
- id: &str,
- ) -> Option<Values2<T>> {
- let internal_id = Id::from(id);
- MatchesError::unwrap(&internal_id, self.try_remove_many(id))
- }
-
- /// Check if values are present for the argument or group id
- ///
- /// *NOTE:* This will always return `true` if [`default_value`] has been set.
- /// [`ArgMatches::value_source`] can be used to check if a value is present at runtime.
- ///
- /// # Panics
- ///
- /// If `id` is is not a valid argument or group name. To handle this case programmatically, see
- /// [`ArgMatches::try_contains_id`].
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::{Command, Arg};
- /// let m = Command::new("myprog")
- /// .arg(Arg::new("debug")
- /// .short('d'))
- /// .get_matches_from(vec![
- /// "myprog", "-d"
- /// ]);
- ///
- /// assert!(m.contains_id("debug"));
- /// ```
- ///
- /// [`default_value`]: crate::Arg::default_value()
- pub fn contains_id(&self, id: &str) -> bool {
- let internal_id = Id::from(id);
- MatchesError::unwrap(&internal_id, self.try_contains_id(id))
- }
-
- /// Check if any args were present on the command line
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::{Command, Arg};
- /// let mut cmd = Command::new("myapp")
- /// .arg(Arg::new("output")
- /// .takes_value(true));
- ///
- /// let m = cmd
- /// .try_get_matches_from_mut(vec!["myapp", "something"])
- /// .unwrap();
- /// assert!(m.args_present());
- ///
- /// let m = cmd
- /// .try_get_matches_from_mut(vec!["myapp"])
- /// .unwrap();
- /// assert!(! m.args_present());
- pub fn args_present(&self) -> bool {
- !self.args.is_empty()
- }
-
- /// Deprecated, replaced with [`ArgMatches::get_one()`]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn value_of<T: Key>(&self, id: T) -> Option<&str> {
- let id = Id::from(id);
- let arg = self.get_arg(&id)?;
- let v = unwrap_string_arg(&id, arg.first()?);
- Some(v)
- }
-
- /// Deprecated, replaced with [`ArgMatches::get_one()`]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn value_of_lossy<T: Key>(&self, id: T) -> Option<Cow<'_, str>> {
- let id = Id::from(id);
- let arg = self.get_arg(&id)?;
- let v = unwrap_os_string_arg(&id, arg.first()?);
- Some(v.to_string_lossy())
- }
-
- /// Deprecated, replaced with [`ArgMatches::get_one()`]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn value_of_os<T: Key>(&self, id: T) -> Option<&OsStr> {
- let id = Id::from(id);
- let arg = self.get_arg(&id)?;
- let v = unwrap_os_string_arg(&id, arg.first()?);
- Some(v)
- }
-
- /// Deprecated, replaced with [`ArgMatches::get_many()`]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn values_of<T: Key>(&self, id: T) -> Option<Values> {
- #![allow(deprecated)]
- let id = Id::from(id);
- let arg = self.get_arg(&id)?;
- let v = Values {
- iter: arg.vals_flatten().map(unwrap_string),
- len: arg.num_vals(),
- };
- Some(v)
- }
-
- /// Get an [`Iterator`] over groups of values of a specific option.
- ///
- /// specifically grouped by the occurrences of the options.
- ///
- /// Each group is a `Vec<&str>` containing the arguments passed to a single occurrence
- /// of the option.
- ///
- /// If the option doesn't support multiple occurrences, or there was only a single occurrence,
- /// the iterator will only contain a single item.
- ///
- /// Returns `None` if the option wasn't present.
- ///
- /// # Panics
- ///
- /// If the value is invalid UTF-8.
- ///
- /// If `id` is not a valid argument or group id.
- ///
- /// # Examples
- /// ```rust
- /// # use clap::{Command,Arg, ArgAction};
- /// let m = Command::new("myprog")
- /// .arg(Arg::new("exec")
- /// .short('x')
- /// .min_values(1)
- /// .action(ArgAction::Append)
- /// .value_terminator(";"))
- /// .get_matches_from(vec![
- /// "myprog", "-x", "echo", "hi", ";", "-x", "echo", "bye"]);
- /// let vals: Vec<Vec<&str>> = m.grouped_values_of("exec").unwrap().collect();
- /// assert_eq!(vals, [["echo", "hi"], ["echo", "bye"]]);
- /// ```
- /// [`Iterator`]: std::iter::Iterator
- #[cfg(feature = "unstable-grouped")]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn grouped_values_of<T: Key>(&self, id: T) -> Option<GroupedValues> {
- let id = Id::from(id);
- let arg = self.get_arg(&id)?;
- let v = GroupedValues {
- iter: arg.vals().map(|g| g.iter().map(unwrap_string).collect()),
- len: arg.vals().len(),
- };
- Some(v)
- }
-
- /// Deprecated, replaced with [`ArgMatches::get_many()`]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn values_of_lossy<T: Key>(&self, id: T) -> Option<Vec<String>> {
- let id = Id::from(id);
- let arg = self.get_arg(&id)?;
- let v = arg
- .vals_flatten()
- .map(|v| unwrap_os_string_arg(&id, v).to_string_lossy().into_owned())
- .collect();
- Some(v)
- }
-
- /// Deprecated, replaced with [`ArgMatches::get_many()`]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn values_of_os<T: Key>(&self, id: T) -> Option<OsValues> {
- #![allow(deprecated)]
- let id = Id::from(id);
- let arg = self.get_arg(&id)?;
- let v = OsValues {
- iter: arg.vals_flatten().map(unwrap_os_string),
- len: arg.num_vals(),
- };
- Some(v)
- }
-
- /// Deprecated, replaced with [`ArgMatches::get_one()`]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn value_of_t<R>(&self, name: &str) -> Result<R, Error>
- where
- R: FromStr,
- <R as FromStr>::Err: Display,
- {
- #![allow(deprecated)]
- let v = self
- .value_of(name)
- .ok_or_else(|| Error::argument_not_found_auto(name.to_string()))?;
- v.parse::<R>().map_err(|e| {
- let message = format!(
- "The argument '{}' isn't a valid value for '{}': {}",
- v, name, e
- );
-
- Error::value_validation(name.to_string(), v.to_string(), message.into())
- })
- }
-
- /// Deprecated, replaced with [`ArgMatches::get_one()`]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn value_of_t_or_exit<R>(&self, name: &str) -> R
- where
- R: FromStr,
- <R as FromStr>::Err: Display,
- {
- #![allow(deprecated)]
- self.value_of_t(name).unwrap_or_else(|e| e.exit())
- }
-
- /// Deprecated, replaced with [`ArgMatches::get_many()`]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn values_of_t<R>(&self, name: &str) -> Result<Vec<R>, Error>
- where
- R: FromStr,
- <R as FromStr>::Err: Display,
- {
- #![allow(deprecated)]
- let v = self
- .values_of(name)
- .ok_or_else(|| Error::argument_not_found_auto(name.to_string()))?;
- v.map(|v| {
- v.parse::<R>().map_err(|e| {
- let message = format!("The argument '{}' isn't a valid value: {}", v, e);
-
- Error::value_validation(name.to_string(), v.to_string(), message.into())
- })
- })
- .collect()
- }
-
- /// Deprecated, replaced with [`ArgMatches::get_many()`]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn values_of_t_or_exit<R>(&self, name: &str) -> Vec<R>
- where
- R: FromStr,
- <R as FromStr>::Err: Display,
- {
- #![allow(deprecated)]
- self.values_of_t(name).unwrap_or_else(|e| e.exit())
- }
-
- /// Deprecated, replaced with [`ArgAction::SetTrue`][crate::ArgAction] or
- /// [`ArgMatches::contains_id`].
- #[cfg_attr(
- feature = "deprecated",
- deprecated(
- since = "3.2.0",
- note = "Replaced with either `ArgAction::SetTrue` or `ArgMatches::contains_id(...)`"
- )
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn is_present<T: Key>(&self, id: T) -> bool {
- let id = Id::from(id);
-
- #[cfg(debug_assertions)]
- self.get_arg(&id);
-
- self.args.contains_key(&id)
- }
-
- /// Report where argument value came from
- ///
- /// # Panics
- ///
- /// If `id` is is not a valid argument or group id.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::{Command, Arg, ValueSource};
- /// let m = Command::new("myprog")
- /// .arg(Arg::new("debug")
- /// .short('d'))
- /// .get_matches_from(vec![
- /// "myprog", "-d"
- /// ]);
- ///
- /// assert_eq!(m.value_source("debug"), Some(ValueSource::CommandLine));
- /// ```
- ///
- /// [`default_value`]: crate::Arg::default_value()
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn value_source<T: Key>(&self, id: T) -> Option<ValueSource> {
- let id = Id::from(id);
-
- let value = self.get_arg(&id);
-
- value.and_then(MatchedArg::source)
- }
-
- /// Deprecated, replaced with [`ArgAction::Count`][crate::ArgAction],
- /// [`ArgMatches::get_many`]`.len()`, or [`ArgMatches::value_source`].
- #[cfg_attr(
- feature = "deprecated",
- deprecated(
- since = "3.2.0",
- note = "Replaced with either `ArgAction::Count`, `ArgMatches::get_many(...).len()`, or `ArgMatches::value_source`"
- )
- )]
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn occurrences_of<T: Key>(&self, id: T) -> u64 {
- #![allow(deprecated)]
- self.get_arg(&Id::from(id))
- .map_or(0, |a| a.get_occurrences())
- }
-
- /// The first index of that an argument showed up.
- ///
- /// Indices are similar to argv indices, but are not exactly 1:1.
- ///
- /// For flags (i.e. those arguments which don't have an associated value), indices refer
- /// to occurrence of the switch, such as `-f`, or `--flag`. However, for options the indices
- /// refer to the *values* `-o val` would therefore not represent two distinct indices, only the
- /// index for `val` would be recorded. This is by design.
- ///
- /// Besides the flag/option discrepancy, the primary difference between an argv index and clap
- /// index, is that clap continues counting once all arguments have properly separated, whereas
- /// an argv index does not.
- ///
- /// The examples should clear this up.
- ///
- /// *NOTE:* If an argument is allowed multiple times, this method will only give the *first*
- /// index. See [`ArgMatches::indices_of`].
- ///
- /// # Panics
- ///
- /// If `id` is is not a valid argument or group id.
- ///
- /// # Examples
- ///
- /// The argv indices are listed in the comments below. See how they correspond to the clap
- /// indices. Note that if it's not listed in a clap index, this is because it's not saved in
- /// in an `ArgMatches` struct for querying.
- ///
- /// ```rust
- /// # use clap::{Command, Arg};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("flag")
- /// .short('f'))
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .takes_value(true))
- /// .get_matches_from(vec!["myapp", "-f", "-o", "val"]);
- /// // ARGV indices: ^0 ^1 ^2 ^3
- /// // clap indices: ^1 ^3
- ///
- /// assert_eq!(m.index_of("flag"), Some(1));
- /// assert_eq!(m.index_of("option"), Some(3));
- /// ```
- ///
- /// Now notice, if we use one of the other styles of options:
- ///
- /// ```rust
- /// # use clap::{Command, Arg};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("flag")
- /// .short('f'))
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .takes_value(true))
- /// .get_matches_from(vec!["myapp", "-f", "-o=val"]);
- /// // ARGV indices: ^0 ^1 ^2
- /// // clap indices: ^1 ^3
- ///
- /// assert_eq!(m.index_of("flag"), Some(1));
- /// assert_eq!(m.index_of("option"), Some(3));
- /// ```
- ///
- /// Things become much more complicated, or clear if we look at a more complex combination of
- /// flags. Let's also throw in the final option style for good measure.
- ///
- /// ```rust
- /// # use clap::{Command, Arg};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("flag")
- /// .short('f'))
- /// .arg(Arg::new("flag2")
- /// .short('F'))
- /// .arg(Arg::new("flag3")
- /// .short('z'))
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .takes_value(true))
- /// .get_matches_from(vec!["myapp", "-fzF", "-oval"]);
- /// // ARGV indices: ^0 ^1 ^2
- /// // clap indices: ^1,2,3 ^5
- /// //
- /// // clap sees the above as 'myapp -f -z -F -o val'
- /// // ^0 ^1 ^2 ^3 ^4 ^5
- /// assert_eq!(m.index_of("flag"), Some(1));
- /// assert_eq!(m.index_of("flag2"), Some(3));
- /// assert_eq!(m.index_of("flag3"), Some(2));
- /// assert_eq!(m.index_of("option"), Some(5));
- /// ```
- ///
- /// One final combination of flags/options to see how they combine:
- ///
- /// ```rust
- /// # use clap::{Command, Arg};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("flag")
- /// .short('f'))
- /// .arg(Arg::new("flag2")
- /// .short('F'))
- /// .arg(Arg::new("flag3")
- /// .short('z'))
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .takes_value(true))
- /// .get_matches_from(vec!["myapp", "-fzFoval"]);
- /// // ARGV indices: ^0 ^1
- /// // clap indices: ^1,2,3^5
- /// //
- /// // clap sees the above as 'myapp -f -z -F -o val'
- /// // ^0 ^1 ^2 ^3 ^4 ^5
- /// assert_eq!(m.index_of("flag"), Some(1));
- /// assert_eq!(m.index_of("flag2"), Some(3));
- /// assert_eq!(m.index_of("flag3"), Some(2));
- /// assert_eq!(m.index_of("option"), Some(5));
- /// ```
- ///
- /// The last part to mention is when values are sent in multiple groups with a [delimiter].
- ///
- /// ```rust
- /// # use clap::{Command, Arg};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .use_value_delimiter(true)
- /// .multiple_values(true))
- /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
- /// // ARGV indices: ^0 ^1
- /// // clap indices: ^2 ^3 ^4
- /// //
- /// // clap sees the above as 'myapp -o val1 val2 val3'
- /// // ^0 ^1 ^2 ^3 ^4
- /// assert_eq!(m.index_of("option"), Some(2));
- /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 3, 4]);
- /// ```
- /// [delimiter]: crate::Arg::value_delimiter()
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn index_of<T: Key>(&self, id: T) -> Option<usize> {
- let arg = self.get_arg(&Id::from(id))?;
- let i = arg.get_index(0)?;
- Some(i)
- }
-
- /// All indices an argument appeared at when parsing.
- ///
- /// Indices are similar to argv indices, but are not exactly 1:1.
- ///
- /// For flags (i.e. those arguments which don't have an associated value), indices refer
- /// to occurrence of the switch, such as `-f`, or `--flag`. However, for options the indices
- /// refer to the *values* `-o val` would therefore not represent two distinct indices, only the
- /// index for `val` would be recorded. This is by design.
- ///
- /// *NOTE:* For more information about how clap indices compared to argv indices, see
- /// [`ArgMatches::index_of`]
- ///
- /// # Panics
- ///
- /// If `id` is is not a valid argument or group id.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::{Command, Arg};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .use_value_delimiter(true)
- /// .multiple_values(true))
- /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
- /// // ARGV indices: ^0 ^1
- /// // clap indices: ^2 ^3 ^4
- /// //
- /// // clap sees the above as 'myapp -o val1 val2 val3'
- /// // ^0 ^1 ^2 ^3 ^4
- /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 3, 4]);
- /// ```
- ///
- /// Another quick example is when flags and options are used together
- ///
- /// ```rust
- /// # use clap::{Command, Arg, ArgAction};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .takes_value(true)
- /// .action(ArgAction::Append))
- /// .arg(Arg::new("flag")
- /// .short('f')
- /// .action(ArgAction::Count))
- /// .get_matches_from(vec!["myapp", "-o", "val1", "-f", "-o", "val2", "-f"]);
- /// // ARGV indices: ^0 ^1 ^2 ^3 ^4 ^5 ^6
- /// // clap indices: ^2 ^3 ^5 ^6
- ///
- /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 5]);
- /// assert_eq!(m.indices_of("flag").unwrap().collect::<Vec<_>>(), &[6]);
- /// ```
- ///
- /// One final example, which is an odd case; if we *don't* use value delimiter as we did with
- /// the first example above instead of `val1`, `val2` and `val3` all being distinc values, they
- /// would all be a single value of `val1,val2,val3`, in which case they'd only receive a single
- /// index.
- ///
- /// ```rust
- /// # use clap::{Command, Arg};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .takes_value(true)
- /// .multiple_values(true))
- /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
- /// // ARGV indices: ^0 ^1
- /// // clap indices: ^2
- /// //
- /// // clap sees the above as 'myapp -o "val1,val2,val3"'
- /// // ^0 ^1 ^2
- /// assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2]);
- /// ```
- /// [`ArgMatches::index_of`]: ArgMatches::index_of()
- /// [delimiter]: Arg::value_delimiter()
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn indices_of<T: Key>(&self, id: T) -> Option<Indices<'_>> {
- let arg = self.get_arg(&Id::from(id))?;
- let i = Indices {
- iter: arg.indices(),
- len: arg.num_vals(),
- };
- Some(i)
- }
-
- #[inline]
- #[doc(hidden)]
- #[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::try_get_one()`")
- )]
- pub fn is_valid_arg(&self, _id: impl Key) -> bool {
- #[cfg(debug_assertions)]
- {
- let id = Id::from(_id);
- self.disable_asserts || id == Id::empty_hash() || self.valid_args.contains(&id)
- }
- #[cfg(not(debug_assertions))]
- {
- true
- }
- }
-}
-
-/// # Subcommands
-impl ArgMatches {
- /// The name and `ArgMatches` of the current [subcommand].
- ///
- /// Subcommand values are put in a child [`ArgMatches`]
- ///
- /// Returns `None` if the subcommand wasn't present at runtime,
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # use clap::{Command, Arg, };
- /// let app_m = Command::new("git")
- /// .subcommand(Command::new("clone"))
- /// .subcommand(Command::new("push"))
- /// .subcommand(Command::new("commit"))
- /// .get_matches();
- ///
- /// match app_m.subcommand() {
- /// Some(("clone", sub_m)) => {}, // clone was used
- /// Some(("push", sub_m)) => {}, // push was used
- /// Some(("commit", sub_m)) => {}, // commit was used
- /// _ => {}, // Either no subcommand or one not tested for...
- /// }
- /// ```
- ///
- /// Another useful scenario is when you want to support third party, or external, subcommands.
- /// In these cases you can't know the subcommand name ahead of time, so use a variable instead
- /// with pattern matching!
- ///
- /// ```rust
- /// # use clap::Command;
- /// // Assume there is an external subcommand named "subcmd"
- /// let app_m = Command::new("myprog")
- /// .allow_external_subcommands(true)
- /// .get_matches_from(vec![
- /// "myprog", "subcmd", "--option", "value", "-fff", "--flag"
- /// ]);
- ///
- /// // All trailing arguments will be stored under the subcommand's sub-matches using an empty
- /// // string argument name
- /// match app_m.subcommand() {
- /// Some((external, sub_m)) => {
- /// let ext_args: Vec<&str> = sub_m.get_many::<String>("")
- /// .unwrap().map(|s| s.as_str()).collect();
- /// assert_eq!(external, "subcmd");
- /// assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]);
- /// },
- /// _ => {},
- /// }
- /// ```
- /// [subcommand]: crate::Command::subcommand
- #[inline]
- pub fn subcommand(&self) -> Option<(&str, &ArgMatches)> {
- self.subcommand.as_ref().map(|sc| (&*sc.name, &sc.matches))
- }
-
- /// Return the name and `ArgMatches` of the current [subcommand].
- ///
- /// Subcommand values are put in a child [`ArgMatches`]
- ///
- /// Returns `None` if the subcommand wasn't present at runtime,
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # use clap::{Command, Arg, };
- /// let mut app_m = Command::new("git")
- /// .subcommand(Command::new("clone"))
- /// .subcommand(Command::new("push"))
- /// .subcommand(Command::new("commit"))
- /// .subcommand_required(true)
- /// .get_matches();
- ///
- /// let (name, sub_m) = app_m.remove_subcommand().expect("required");
- /// match (name.as_str(), sub_m) {
- /// ("clone", sub_m) => {}, // clone was used
- /// ("push", sub_m) => {}, // push was used
- /// ("commit", sub_m) => {}, // commit was used
- /// (name, _) => unimplemented!("{}", name),
- /// }
- /// ```
- ///
- /// Another useful scenario is when you want to support third party, or external, subcommands.
- /// In these cases you can't know the subcommand name ahead of time, so use a variable instead
- /// with pattern matching!
- ///
- /// ```rust
- /// # use clap::Command;
- /// // Assume there is an external subcommand named "subcmd"
- /// let mut app_m = Command::new("myprog")
- /// .allow_external_subcommands(true)
- /// .get_matches_from(vec![
- /// "myprog", "subcmd", "--option", "value", "-fff", "--flag"
- /// ]);
- ///
- /// // All trailing arguments will be stored under the subcommand's sub-matches using an empty
- /// // string argument name
- /// match app_m.remove_subcommand() {
- /// Some((external, mut sub_m)) => {
- /// let ext_args: Vec<String> = sub_m.remove_many("")
- /// .expect("`file`is required")
- /// .collect();
- /// assert_eq!(external, "subcmd");
- /// assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]);
- /// },
- /// _ => {},
- /// }
- /// ```
- /// [subcommand]: crate::Command::subcommand
- pub fn remove_subcommand(&mut self) -> Option<(String, ArgMatches)> {
- self.subcommand.take().map(|sc| (sc.name, sc.matches))
- }
-
- /// The `ArgMatches` for the current [subcommand].
- ///
- /// Subcommand values are put in a child [`ArgMatches`]
- ///
- /// Returns `None` if the subcommand wasn't present at runtime,
- ///
- /// # Panics
- ///
- /// If `id` is is not a valid subcommand.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap::{Command, Arg, ArgAction};
- /// let app_m = Command::new("myprog")
- /// .arg(Arg::new("debug")
- /// .short('d')
- /// .action(ArgAction::SetTrue)
- /// )
- /// .subcommand(Command::new("test")
- /// .arg(Arg::new("opt")
- /// .long("option")
- /// .takes_value(true)))
- /// .get_matches_from(vec![
- /// "myprog", "-d", "test", "--option", "val"
- /// ]);
- ///
- /// // Both parent commands, and child subcommands can have arguments present at the same times
- /// assert!(*app_m.get_one::<bool>("debug").expect("defaulted by clap"));
- ///
- /// // Get the subcommand's ArgMatches instance
- /// if let Some(sub_m) = app_m.subcommand_matches("test") {
- /// // Use the struct like normal
- /// assert_eq!(sub_m.get_one::<String>("opt").map(|s| s.as_str()), Some("val"));
- /// }
- /// ```
- ///
- /// [subcommand]: crate::Command::subcommand
- /// [`Command`]: crate::Command
- pub fn subcommand_matches<T: Key>(&self, id: T) -> Option<&ArgMatches> {
- self.get_subcommand(&id.into()).map(|sc| &sc.matches)
- }
-
- /// The name of the current [subcommand].
- ///
- /// Returns `None` if the subcommand wasn't present at runtime,
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # use clap::{Command, Arg, };
- /// let app_m = Command::new("git")
- /// .subcommand(Command::new("clone"))
- /// .subcommand(Command::new("push"))
- /// .subcommand(Command::new("commit"))
- /// .get_matches();
- ///
- /// match app_m.subcommand_name() {
- /// Some("clone") => {}, // clone was used
- /// Some("push") => {}, // push was used
- /// Some("commit") => {}, // commit was used
- /// _ => {}, // Either no subcommand or one not tested for...
- /// }
- /// ```
- /// [subcommand]: crate::Command::subcommand
- /// [`Command`]: crate::Command
- #[inline]
- pub fn subcommand_name(&self) -> Option<&str> {
- self.subcommand.as_ref().map(|sc| &*sc.name)
- }
-
- /// Check if a subcommand can be queried
- ///
- /// By default, `ArgMatches` functions assert on undefined `Id`s to help catch programmer
- /// mistakes. In some context, this doesn't work, so users can use this function to check
- /// before they do a query on `ArgMatches`.
- #[inline]
- #[doc(hidden)]
- pub fn is_valid_subcommand(&self, _id: impl Key) -> bool {
- #[cfg(debug_assertions)]
- {
- let id = Id::from(_id);
- self.disable_asserts || id == Id::empty_hash() || self.valid_subcommands.contains(&id)
- }
- #[cfg(not(debug_assertions))]
- {
- true
- }
- }
-}
-
-/// # Advanced
-impl ArgMatches {
- /// Non-panicking version of [`ArgMatches::get_one`]
- pub fn try_get_one<T: Any + Clone + Send + Sync + 'static>(
- &self,
- id: &str,
- ) -> Result<Option<&T>, MatchesError> {
- let id = Id::from(id);
- let arg = self.try_get_arg_t::<T>(&id)?;
- let value = match arg.and_then(|a| a.first()) {
- Some(value) => value,
- None => {
- return Ok(None);
- }
- };
- Ok(value
- .downcast_ref::<T>()
- .map(Some)
- .expect(INTERNAL_ERROR_MSG)) // enforced by `try_get_arg_t`
- }
-
- /// Non-panicking version of [`ArgMatches::get_many`]
- pub fn try_get_many<T: Any + Clone + Send + Sync + 'static>(
- &self,
- id: &str,
- ) -> Result<Option<ValuesRef<T>>, MatchesError> {
- let id = Id::from(id);
- let arg = match self.try_get_arg_t::<T>(&id)? {
- Some(arg) => arg,
- None => return Ok(None),
- };
- let len = arg.num_vals();
- let values = arg.vals_flatten();
- let values = ValuesRef {
- // enforced by `try_get_arg_t`
- iter: values.map(|v| v.downcast_ref::<T>().expect(INTERNAL_ERROR_MSG)),
- len,
- };
- Ok(Some(values))
- }
-
- /// Non-panicking version of [`ArgMatches::get_raw`]
- pub fn try_get_raw(&self, id: &str) -> Result<Option<RawValues<'_>>, MatchesError> {
- let id = Id::from(id);
- let arg = match self.try_get_arg(&id)? {
- Some(arg) => arg,
- None => return Ok(None),
- };
- let len = arg.num_vals();
- let values = arg.raw_vals_flatten();
- let values = RawValues {
- iter: values.map(OsString::as_os_str),
- len,
- };
- Ok(Some(values))
- }
-
- /// Non-panicking version of [`ArgMatches::remove_one`]
- pub fn try_remove_one<T: Any + Clone + Send + Sync + 'static>(
- &mut self,
- id: &str,
- ) -> Result<Option<T>, MatchesError> {
- let id = Id::from(id);
- match self.try_remove_arg_t::<T>(&id)? {
- Some(values) => Ok(values
- .into_vals_flatten()
- // enforced by `try_get_arg_t`
- .map(|v| v.downcast_into::<T>().expect(INTERNAL_ERROR_MSG))
- .next()),
- None => Ok(None),
- }
- }
-
- /// Non-panicking version of [`ArgMatches::remove_many`]
- pub fn try_remove_many<T: Any + Clone + Send + Sync + 'static>(
- &mut self,
- id: &str,
- ) -> Result<Option<Values2<T>>, MatchesError> {
- let id = Id::from(id);
- let arg = match self.try_remove_arg_t::<T>(&id)? {
- Some(arg) => arg,
- None => return Ok(None),
- };
- let len = arg.num_vals();
- let values = arg.into_vals_flatten();
- let values = Values2 {
- // enforced by `try_get_arg_t`
- iter: values.map(|v| v.downcast_into::<T>().expect(INTERNAL_ERROR_MSG)),
- len,
- };
- Ok(Some(values))
- }
-
- /// Non-panicking version of [`ArgMatches::contains_id`]
- pub fn try_contains_id(&self, id: &str) -> Result<bool, MatchesError> {
- let id = Id::from(id);
-
- self.verify_arg(&id)?;
-
- let presence = self.args.contains_key(&id);
- Ok(presence)
- }
-}
-
-// Private methods
-impl ArgMatches {
- #[inline]
- fn try_get_arg(&self, arg: &Id) -> Result<Option<&MatchedArg>, MatchesError> {
- self.verify_arg(arg)?;
- Ok(self.args.get(arg))
- }
-
- #[inline]
- fn try_get_arg_t<T: Any + Send + Sync + 'static>(
- &self,
- arg: &Id,
- ) -> Result<Option<&MatchedArg>, MatchesError> {
- let arg = match self.try_get_arg(arg)? {
- Some(arg) => arg,
- None => {
- return Ok(None);
- }
- };
- self.verify_arg_t::<T>(arg)?;
- Ok(Some(arg))
- }
-
- #[inline]
- fn try_remove_arg_t<T: Any + Send + Sync + 'static>(
- &mut self,
- arg: &Id,
- ) -> Result<Option<MatchedArg>, MatchesError> {
- self.verify_arg(arg)?;
- let matched = match self.args.remove(arg) {
- Some(matched) => matched,
- None => {
- return Ok(None);
- }
- };
-
- let expected = AnyValueId::of::<T>();
- let actual = matched.infer_type_id(expected);
- if actual == expected {
- Ok(Some(matched))
- } else {
- self.args.insert(arg.clone(), matched);
- Err(MatchesError::Downcast { actual, expected })
- }
- }
-
- fn verify_arg_t<T: Any + Send + Sync + 'static>(
- &self,
- arg: &MatchedArg,
- ) -> Result<(), MatchesError> {
- let expected = AnyValueId::of::<T>();
- let actual = arg.infer_type_id(expected);
- if expected == actual {
- Ok(())
- } else {
- Err(MatchesError::Downcast { actual, expected })
- }
- }
-
- #[inline]
- fn verify_arg(&self, _arg: &Id) -> Result<(), MatchesError> {
- #[cfg(debug_assertions)]
- {
- if self.disable_asserts || *_arg == Id::empty_hash() || self.valid_args.contains(_arg) {
- } else if self.valid_subcommands.contains(_arg) {
- debug!(
- "Subcommand `{:?}` used where an argument or group name was expected.",
- _arg
- );
- return Err(MatchesError::UnknownArgument {});
- } else {
- debug!(
- "`{:?}` is not an id of an argument or a group.\n\
- Make sure you're using the name of the argument itself \
- and not the name of short or long flags.",
- _arg
- );
- return Err(MatchesError::UnknownArgument {});
- }
- }
- Ok(())
- }
-
- #[inline]
- #[cfg_attr(debug_assertions, track_caller)]
- fn get_arg(&self, arg: &Id) -> Option<&MatchedArg> {
- #[cfg(debug_assertions)]
- {
- if self.disable_asserts || *arg == Id::empty_hash() || self.valid_args.contains(arg) {
- } else if self.valid_subcommands.contains(arg) {
- panic!(
- "Subcommand `{:?}` used where an argument or group name was expected.",
- arg
- );
- } else {
- panic!(
- "`{:?}` is not an id of an argument or a group.\n\
- Make sure you're using the name of the argument itself \
- and not the name of short or long flags.",
- arg
- );
- }
- }
-
- self.args.get(arg)
- }
-
- #[inline]
- #[cfg_attr(debug_assertions, track_caller)]
- fn get_subcommand(&self, id: &Id) -> Option<&SubCommand> {
- #[cfg(debug_assertions)]
- {
- if self.disable_asserts
- || *id == Id::empty_hash()
- || self.valid_subcommands.contains(id)
- {
- } else if self.valid_args.contains(id) {
- panic!(
- "Argument or group `{:?}` used where a subcommand name was expected.",
- id
- );
- } else {
- panic!("`{:?}` is not a name of a subcommand.", id);
- }
- }
-
- if let Some(ref sc) = self.subcommand {
- if sc.id == *id {
- return Some(sc);
- }
- }
-
- None
- }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub(crate) struct SubCommand {
- pub(crate) id: Id,
- pub(crate) name: String,
- pub(crate) matches: ArgMatches,
-}
-
-/// Iterate over multiple values for an argument via [`ArgMatches::remove_many`].
-///
-/// # Examples
-///
-/// ```rust
-/// # use clap::{Command, Arg, ArgAction};
-/// let mut m = Command::new("myapp")
-/// .arg(Arg::new("output")
-/// .short('o')
-/// .action(ArgAction::Append)
-/// .takes_value(true))
-/// .get_matches_from(vec!["myapp", "-o", "val1", "-o", "val2"]);
-///
-/// let mut values = m.remove_many::<String>("output")
-/// .unwrap();
-///
-/// assert_eq!(values.next(), Some(String::from("val1")));
-/// assert_eq!(values.next(), Some(String::from("val2")));
-/// assert_eq!(values.next(), None);
-/// ```
-#[derive(Clone, Debug)]
-pub struct Values2<T> {
- #[allow(clippy::type_complexity)]
- iter: Map<Flatten<std::vec::IntoIter<Vec<AnyValue>>>, fn(AnyValue) -> T>,
- len: usize,
-}
-
-impl<T> Iterator for Values2<T> {
- type Item = T;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.len, Some(self.len))
- }
-}
-
-impl<T> DoubleEndedIterator for Values2<T> {
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-}
-
-impl<T> ExactSizeIterator for Values2<T> {}
-
-/// Creates an empty iterator.
-impl<T> Default for Values2<T> {
- fn default() -> Self {
- let empty: Vec<Vec<AnyValue>> = Default::default();
- Values2 {
- iter: empty.into_iter().flatten().map(|_| unreachable!()),
- len: 0,
- }
- }
-}
-
-/// Iterate over multiple values for an argument via [`ArgMatches::get_many`].
-///
-/// # Examples
-///
-/// ```rust
-/// # use clap::{Command, Arg, ArgAction};
-/// let m = Command::new("myapp")
-/// .arg(Arg::new("output")
-/// .short('o')
-/// .action(ArgAction::Append)
-/// .takes_value(true))
-/// .get_matches_from(vec!["myapp", "-o", "val1", "-o", "val2"]);
-///
-/// let mut values = m.get_many::<String>("output")
-/// .unwrap()
-/// .map(|s| s.as_str());
-///
-/// assert_eq!(values.next(), Some("val1"));
-/// assert_eq!(values.next(), Some("val2"));
-/// assert_eq!(values.next(), None);
-/// ```
-#[derive(Clone, Debug)]
-pub struct ValuesRef<'a, T> {
- #[allow(clippy::type_complexity)]
- iter: Map<Flatten<Iter<'a, Vec<AnyValue>>>, fn(&AnyValue) -> &T>,
- len: usize,
-}
-
-impl<'a, T: 'a> Iterator for ValuesRef<'a, T> {
- type Item = &'a T;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.len, Some(self.len))
- }
-}
-
-impl<'a, T: 'a> DoubleEndedIterator for ValuesRef<'a, T> {
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-}
-
-impl<'a, T: 'a> ExactSizeIterator for ValuesRef<'a, T> {}
-
-/// Creates an empty iterator.
-impl<'a, T: 'a> Default for ValuesRef<'a, T> {
- fn default() -> Self {
- static EMPTY: [Vec<AnyValue>; 0] = [];
- ValuesRef {
- iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
- len: 0,
- }
- }
-}
-
-/// Iterate over raw argument values via [`ArgMatches::get_raw`].
-///
-/// # Examples
-///
-#[cfg_attr(not(unix), doc = " ```ignore")]
-#[cfg_attr(unix, doc = " ```")]
-/// # use clap::{Command, arg, value_parser};
-/// use std::ffi::OsString;
-/// use std::os::unix::ffi::{OsStrExt,OsStringExt};
-///
-/// let m = Command::new("utf8")
-/// .arg(arg!(<arg> "some arg")
-/// .value_parser(value_parser!(OsString)))
-/// .get_matches_from(vec![OsString::from("myprog"),
-/// // "Hi {0xe9}!"
-/// OsString::from_vec(vec![b'H', b'i', b' ', 0xe9, b'!'])]);
-/// assert_eq!(
-/// &*m.get_raw("arg")
-/// .unwrap()
-/// .next().unwrap()
-/// .as_bytes(),
-/// [b'H', b'i', b' ', 0xe9, b'!']
-/// );
-/// ```
-#[derive(Clone, Debug)]
-pub struct RawValues<'a> {
- #[allow(clippy::type_complexity)]
- iter: Map<Flatten<Iter<'a, Vec<OsString>>>, fn(&OsString) -> &OsStr>,
- len: usize,
-}
-
-impl<'a> Iterator for RawValues<'a> {
- type Item = &'a OsStr;
-
- fn next(&mut self) -> Option<&'a OsStr> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.len, Some(self.len))
- }
-}
-
-impl<'a> DoubleEndedIterator for RawValues<'a> {
- fn next_back(&mut self) -> Option<&'a OsStr> {
- self.iter.next_back()
- }
-}
-
-impl<'a> ExactSizeIterator for RawValues<'a> {}
-
-/// Creates an empty iterator.
-impl Default for RawValues<'_> {
- fn default() -> Self {
- static EMPTY: [Vec<OsString>; 0] = [];
- RawValues {
- iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
- len: 0,
- }
- }
-}
-
-// The following were taken and adapted from vec_map source
-// repo: https://github.com/contain-rs/vec-map
-// commit: be5e1fa3c26e351761b33010ddbdaf5f05dbcc33
-// license: MIT - Copyright (c) 2015 The Rust Project Developers
-
-/// Deprecated, replaced with [`ArgMatches::get_many()`]
-#[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
-)]
-#[derive(Clone, Debug)]
-pub struct Values<'a> {
- #[allow(clippy::type_complexity)]
- iter: Map<Flatten<Iter<'a, Vec<AnyValue>>>, for<'r> fn(&'r AnyValue) -> &'r str>,
- len: usize,
-}
-
-#[allow(deprecated)]
-impl<'a> Iterator for Values<'a> {
- type Item = &'a str;
-
- fn next(&mut self) -> Option<&'a str> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.len, Some(self.len))
- }
-}
-
-#[allow(deprecated)]
-impl<'a> DoubleEndedIterator for Values<'a> {
- fn next_back(&mut self) -> Option<&'a str> {
- self.iter.next_back()
- }
-}
-
-#[allow(deprecated)]
-impl<'a> ExactSizeIterator for Values<'a> {}
-
-/// Creates an empty iterator.
-#[allow(deprecated)]
-impl<'a> Default for Values<'a> {
- fn default() -> Self {
- static EMPTY: [Vec<AnyValue>; 0] = [];
- Values {
- iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
- len: 0,
- }
- }
-}
-
-#[derive(Clone)]
-#[allow(missing_debug_implementations)]
-pub struct GroupedValues<'a> {
- #[allow(clippy::type_complexity)]
- iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> Vec<&str>>,
- len: usize,
-}
-
-impl<'a> Iterator for GroupedValues<'a> {
- type Item = Vec<&'a str>;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.len, Some(self.len))
- }
-}
-
-impl<'a> DoubleEndedIterator for GroupedValues<'a> {
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-}
-
-impl<'a> ExactSizeIterator for GroupedValues<'a> {}
-
-/// Creates an empty iterator. Used for `unwrap_or_default()`.
-impl<'a> Default for GroupedValues<'a> {
- fn default() -> Self {
- #![allow(deprecated)]
- static EMPTY: [Vec<AnyValue>; 0] = [];
- GroupedValues {
- iter: EMPTY[..].iter().map(|_| unreachable!()),
- len: 0,
- }
- }
-}
-
-/// Deprecated, replaced with [`ArgMatches::get_many()`]
-#[cfg_attr(
- feature = "deprecated",
- deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")
-)]
-#[derive(Clone, Debug)]
-pub struct OsValues<'a> {
- #[allow(clippy::type_complexity)]
- iter: Map<Flatten<Iter<'a, Vec<AnyValue>>>, fn(&AnyValue) -> &OsStr>,
- len: usize,
-}
-
-#[allow(deprecated)]
-impl<'a> Iterator for OsValues<'a> {
- type Item = &'a OsStr;
-
- fn next(&mut self) -> Option<&'a OsStr> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.len, Some(self.len))
- }
-}
-
-#[allow(deprecated)]
-impl<'a> DoubleEndedIterator for OsValues<'a> {
- fn next_back(&mut self) -> Option<&'a OsStr> {
- self.iter.next_back()
- }
-}
-
-#[allow(deprecated)]
-impl<'a> ExactSizeIterator for OsValues<'a> {}
-
-/// Creates an empty iterator.
-#[allow(deprecated)]
-impl Default for OsValues<'_> {
- fn default() -> Self {
- static EMPTY: [Vec<AnyValue>; 0] = [];
- OsValues {
- iter: EMPTY[..].iter().flatten().map(|_| unreachable!()),
- len: 0,
- }
- }
-}
-
-/// Iterate over indices for where an argument appeared when parsing, via [`ArgMatches::indices_of`]
-///
-/// # Examples
-///
-/// ```rust
-/// # use clap::{Command, Arg};
-/// let m = Command::new("myapp")
-/// .arg(Arg::new("output")
-/// .short('o')
-/// .multiple_values(true)
-/// .takes_value(true))
-/// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]);
-///
-/// let mut indices = m.indices_of("output").unwrap();
-///
-/// assert_eq!(indices.next(), Some(2));
-/// assert_eq!(indices.next(), Some(3));
-/// assert_eq!(indices.next(), None);
-/// ```
-/// [`ArgMatches::indices_of`]: ArgMatches::indices_of()
-#[derive(Clone, Debug)]
-pub struct Indices<'a> {
- iter: Cloned<Iter<'a, usize>>,
- len: usize,
-}
-
-impl<'a> Iterator for Indices<'a> {
- type Item = usize;
-
- fn next(&mut self) -> Option<usize> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.len, Some(self.len))
- }
-}
-
-impl<'a> DoubleEndedIterator for Indices<'a> {
- fn next_back(&mut self) -> Option<usize> {
- self.iter.next_back()
- }
-}
-
-impl<'a> ExactSizeIterator for Indices<'a> {}
-
-/// Creates an empty iterator.
-impl<'a> Default for Indices<'a> {
- fn default() -> Self {
- static EMPTY: [usize; 0] = [];
- // This is never called because the iterator is empty:
- Indices {
- iter: EMPTY[..].iter().cloned(),
- len: 0,
- }
- }
-}
-
-#[cfg_attr(debug_assertions, track_caller)]
-#[inline]
-fn unwrap_string(value: &AnyValue) -> &str {
- match value.downcast_ref::<String>() {
- Some(value) => value,
- None => {
- panic!("Must use `_os` lookups with `Arg::allow_invalid_utf8`",)
- }
- }
-}
-
-#[cfg_attr(debug_assertions, track_caller)]
-#[inline]
-fn unwrap_string_arg<'v>(id: &Id, value: &'v AnyValue) -> &'v str {
- match value.downcast_ref::<String>() {
- Some(value) => value,
- None => {
- panic!(
- "Must use `_os` lookups with `Arg::allow_invalid_utf8` at `{:?}`",
- id
- )
- }
- }
-}
-
-#[cfg_attr(debug_assertions, track_caller)]
-#[inline]
-fn unwrap_os_string(value: &AnyValue) -> &OsStr {
- match value.downcast_ref::<OsString>() {
- Some(value) => value,
- None => {
- panic!("Must use `Arg::allow_invalid_utf8` with `_os` lookups",)
- }
- }
-}
-
-#[cfg_attr(debug_assertions, track_caller)]
-#[inline]
-fn unwrap_os_string_arg<'v>(id: &Id, value: &'v AnyValue) -> &'v OsStr {
- match value.downcast_ref::<OsString>() {
- Some(value) => value,
- None => {
- panic!(
- "Must use `Arg::allow_invalid_utf8` with `_os` lookups at `{:?}`",
- id
- )
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn check_auto_traits() {
- static_assertions::assert_impl_all!(ArgMatches: Send, Sync, Unpin);
- }
-
- #[test]
- fn test_default_values() {
- #![allow(deprecated)]
- let mut values: Values = Values::default();
- assert_eq!(values.next(), None);
- }
-
- #[test]
- fn test_default_osvalues() {
- #![allow(deprecated)]
- let mut values: OsValues = OsValues::default();
- assert_eq!(values.next(), None);
- }
-
- #[test]
- fn test_default_raw_values() {
- let mut values: RawValues = Default::default();
- assert_eq!(values.next(), None);
- }
-
- #[test]
- fn test_default_indices() {
- let mut indices: Indices = Indices::default();
- assert_eq!(indices.next(), None);
- }
-
- #[test]
- fn test_default_indices_with_shorter_lifetime() {
- let matches = ArgMatches::default();
- let mut indices = matches.indices_of("").unwrap_or_default();
- assert_eq!(indices.next(), None);
- }
-
- #[test]
- fn values_exact_size() {
- let l = crate::Command::new("test")
- .arg(
- crate::Arg::new("POTATO")
- .takes_value(true)
- .multiple_values(true)
- .required(true),
- )
- .try_get_matches_from(["test", "one"])
- .unwrap()
- .get_many::<String>("POTATO")
- .expect("present")
- .count();
- assert_eq!(l, 1);
- }
-
- #[test]
- fn os_values_exact_size() {
- let l = crate::Command::new("test")
- .arg(
- crate::Arg::new("POTATO")
- .takes_value(true)
- .multiple_values(true)
- .value_parser(crate::builder::ValueParser::os_string())
- .required(true),
- )
- .try_get_matches_from(["test", "one"])
- .unwrap()
- .get_many::<std::ffi::OsString>("POTATO")
- .expect("present")
- .count();
- assert_eq!(l, 1);
- }
-
- #[test]
- fn indices_exact_size() {
- let l = crate::Command::new("test")
- .arg(
- crate::Arg::new("POTATO")
- .takes_value(true)
- .multiple_values(true)
- .required(true),
- )
- .try_get_matches_from(["test", "one"])
- .unwrap()
- .indices_of("POTATO")
- .expect("present")
- .len();
- assert_eq!(l, 1);
- }
-}
diff --git a/vendor/clap/src/parser/matches/matched_arg.rs b/vendor/clap/src/parser/matches/matched_arg.rs
deleted file mode 100644
index fde6d37f3..000000000
--- a/vendor/clap/src/parser/matches/matched_arg.rs
+++ /dev/null
@@ -1,240 +0,0 @@
-// Std
-use std::{
- ffi::{OsStr, OsString},
- iter::{Cloned, Flatten},
- slice::Iter,
-};
-
-use crate::builder::ArgPredicate;
-use crate::parser::AnyValue;
-use crate::parser::AnyValueId;
-use crate::parser::ValueSource;
-use crate::util::eq_ignore_case;
-use crate::INTERNAL_ERROR_MSG;
-
-#[derive(Debug, Clone)]
-pub(crate) struct MatchedArg {
- occurs: u64,
- source: Option<ValueSource>,
- indices: Vec<usize>,
- type_id: Option<AnyValueId>,
- vals: Vec<Vec<AnyValue>>,
- raw_vals: Vec<Vec<OsString>>,
- ignore_case: bool,
-}
-
-impl MatchedArg {
- pub(crate) fn new_arg(arg: &crate::Arg) -> Self {
- let ignore_case = arg.is_ignore_case_set();
- Self {
- occurs: 0,
- source: None,
- indices: Vec::new(),
- type_id: Some(arg.get_value_parser().type_id()),
- vals: Vec::new(),
- raw_vals: Vec::new(),
- ignore_case,
- }
- }
-
- pub(crate) fn new_group() -> Self {
- let ignore_case = false;
- Self {
- occurs: 0,
- source: None,
- indices: Vec::new(),
- type_id: None,
- vals: Vec::new(),
- raw_vals: Vec::new(),
- ignore_case,
- }
- }
-
- pub(crate) fn new_external(cmd: &crate::Command) -> Self {
- let ignore_case = false;
- Self {
- occurs: 0,
- source: None,
- indices: Vec::new(),
- type_id: Some(
- cmd.get_external_subcommand_value_parser()
- .expect(INTERNAL_ERROR_MSG)
- .type_id(),
- ),
- vals: Vec::new(),
- raw_vals: Vec::new(),
- ignore_case,
- }
- }
-
- #[cfg_attr(feature = "deprecated", deprecated(since = "3.2.0"))]
- pub(crate) fn inc_occurrences(&mut self) {
- self.occurs += 1;
- }
-
- #[cfg_attr(feature = "deprecated", deprecated(since = "3.2.0"))]
- pub(crate) fn set_occurrences(&mut self, occurs: u64) {
- self.occurs = occurs
- }
-
- #[cfg_attr(feature = "deprecated", deprecated(since = "3.2.0"))]
- pub(crate) fn get_occurrences(&self) -> u64 {
- self.occurs
- }
-
- pub(crate) fn indices(&self) -> Cloned<Iter<'_, usize>> {
- self.indices.iter().cloned()
- }
-
- pub(crate) fn get_index(&self, index: usize) -> Option<usize> {
- self.indices.get(index).cloned()
- }
-
- pub(crate) fn push_index(&mut self, index: usize) {
- self.indices.push(index)
- }
-
- #[cfg(feature = "unstable-grouped")]
- pub(crate) fn vals(&self) -> Iter<Vec<AnyValue>> {
- self.vals.iter()
- }
-
- pub(crate) fn vals_flatten(&self) -> Flatten<Iter<Vec<AnyValue>>> {
- self.vals.iter().flatten()
- }
-
- pub(crate) fn into_vals_flatten(self) -> Flatten<std::vec::IntoIter<Vec<AnyValue>>> {
- self.vals.into_iter().flatten()
- }
-
- pub(crate) fn raw_vals_flatten(&self) -> Flatten<Iter<Vec<OsString>>> {
- self.raw_vals.iter().flatten()
- }
-
- pub(crate) fn first(&self) -> Option<&AnyValue> {
- self.vals_flatten().next()
- }
-
- #[cfg(test)]
- pub(crate) fn first_raw(&self) -> Option<&OsString> {
- self.raw_vals_flatten().next()
- }
-
- pub(crate) fn new_val_group(&mut self) {
- self.vals.push(vec![]);
- self.raw_vals.push(vec![]);
- }
-
- pub(crate) fn append_val(&mut self, val: AnyValue, raw_val: OsString) {
- // We assume there is always a group created before.
- self.vals.last_mut().expect(INTERNAL_ERROR_MSG).push(val);
- self.raw_vals
- .last_mut()
- .expect(INTERNAL_ERROR_MSG)
- .push(raw_val);
- }
-
- pub(crate) fn num_vals(&self) -> usize {
- self.vals.iter().map(|v| v.len()).sum()
- }
-
- // Will be used later
- #[allow(dead_code)]
- pub(crate) fn num_vals_last_group(&self) -> usize {
- self.vals.last().map(|x| x.len()).unwrap_or(0)
- }
-
- pub(crate) fn all_val_groups_empty(&self) -> bool {
- self.vals.iter().flatten().count() == 0
- }
-
- pub(crate) fn check_explicit(&self, predicate: ArgPredicate) -> bool {
- if self.source == Some(ValueSource::DefaultValue) {
- return false;
- }
-
- match predicate {
- ArgPredicate::Equals(val) => self.raw_vals_flatten().any(|v| {
- if self.ignore_case {
- // If `v` isn't utf8, it can't match `val`, so `OsStr::to_str` should be fine
- eq_ignore_case(&v.to_string_lossy(), &val.to_string_lossy())
- } else {
- OsString::as_os_str(v) == OsStr::new(val)
- }
- }),
- ArgPredicate::IsPresent => true,
- }
- }
-
- pub(crate) fn source(&self) -> Option<ValueSource> {
- self.source
- }
-
- pub(crate) fn set_source(&mut self, source: ValueSource) {
- if let Some(existing) = self.source {
- self.source = Some(existing.max(source));
- } else {
- self.source = Some(source)
- }
- }
-
- pub(crate) fn type_id(&self) -> Option<AnyValueId> {
- self.type_id
- }
-
- pub(crate) fn infer_type_id(&self, expected: AnyValueId) -> AnyValueId {
- self.type_id()
- .or_else(|| {
- self.vals_flatten()
- .map(|v| v.type_id())
- .find(|actual| *actual != expected)
- })
- .unwrap_or(expected)
- }
-}
-
-impl PartialEq for MatchedArg {
- fn eq(&self, other: &MatchedArg) -> bool {
- let MatchedArg {
- occurs: self_occurs,
- source: self_source,
- indices: self_indices,
- type_id: self_type_id,
- vals: _,
- raw_vals: self_raw_vals,
- ignore_case: self_ignore_case,
- } = self;
- let MatchedArg {
- occurs: other_occurs,
- source: other_source,
- indices: other_indices,
- type_id: other_type_id,
- vals: _,
- raw_vals: other_raw_vals,
- ignore_case: other_ignore_case,
- } = other;
- self_occurs == other_occurs
- && self_source == other_source
- && self_indices == other_indices
- && self_type_id == other_type_id
- && self_raw_vals == other_raw_vals
- && self_ignore_case == other_ignore_case
- }
-}
-
-impl Eq for MatchedArg {}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_grouped_vals_first() {
- let mut m = MatchedArg::new_group();
- m.new_val_group();
- m.new_val_group();
- m.append_val(AnyValue::new(String::from("bbb")), "bbb".into());
- m.append_val(AnyValue::new(String::from("ccc")), "ccc".into());
- assert_eq!(m.first_raw(), Some(&OsString::from("bbb")));
- }
-}
diff --git a/vendor/clap/src/parser/matches/mod.rs b/vendor/clap/src/parser/matches/mod.rs
deleted file mode 100644
index 7b88eeca7..000000000
--- a/vendor/clap/src/parser/matches/mod.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-mod any_value;
-mod arg_matches;
-mod matched_arg;
-mod value_source;
-
-pub use any_value::AnyValueId;
-pub use arg_matches::RawValues;
-pub use arg_matches::ValuesRef;
-pub use arg_matches::{ArgMatches, Indices};
-pub use value_source::ValueSource;
-
-pub(crate) use any_value::AnyValue;
-pub(crate) use arg_matches::SubCommand;
-pub(crate) use matched_arg::MatchedArg;
-
-#[allow(deprecated)]
-pub use arg_matches::{OsValues, Values};
diff --git a/vendor/clap/src/parser/matches/value_source.rs b/vendor/clap/src/parser/matches/value_source.rs
deleted file mode 100644
index fb762d2af..000000000
--- a/vendor/clap/src/parser/matches/value_source.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-/// Origin of the argument's value
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-#[non_exhaustive]
-pub enum ValueSource {
- /// Value came [`Arg::default_value`][crate::Arg::default_value]
- DefaultValue,
- /// Value came [`Arg::env`][crate::Arg::env]
- EnvVariable,
- /// Value was passed in on the command-line
- CommandLine,
-}
diff --git a/vendor/clap/src/parser/mod.rs b/vendor/clap/src/parser/mod.rs
deleted file mode 100644
index da81648e1..000000000
--- a/vendor/clap/src/parser/mod.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-//! [`Command`][crate::Command] line argument parser
-
-mod arg_matcher;
-mod error;
-mod matches;
-#[allow(clippy::module_inception)]
-mod parser;
-mod validator;
-
-pub(crate) mod features;
-
-pub(crate) use self::arg_matcher::ArgMatcher;
-pub(crate) use self::matches::AnyValue;
-pub(crate) use self::matches::AnyValueId;
-pub(crate) use self::matches::{MatchedArg, SubCommand};
-pub(crate) use self::parser::Identifier;
-pub(crate) use self::parser::PendingArg;
-pub(crate) use self::parser::{ParseState, Parser};
-pub(crate) use self::validator::Validator;
-
-pub use self::matches::RawValues;
-pub use self::matches::ValuesRef;
-pub use self::matches::{ArgMatches, Indices, ValueSource};
-pub use error::MatchesError;
-
-#[allow(deprecated)]
-pub use self::matches::{OsValues, Values};
diff --git a/vendor/clap/src/parser/parser.rs b/vendor/clap/src/parser/parser.rs
deleted file mode 100644
index ad2bc6e9c..000000000
--- a/vendor/clap/src/parser/parser.rs
+++ /dev/null
@@ -1,1729 +0,0 @@
-// Std
-use std::{
- cell::Cell,
- ffi::{OsStr, OsString},
-};
-
-// Third Party
-use clap_lex::RawOsStr;
-
-// Internal
-use crate::builder::AppSettings as AS;
-use crate::builder::{Arg, Command};
-use crate::error::Error as ClapError;
-use crate::error::Result as ClapResult;
-use crate::mkeymap::KeyType;
-use crate::output::fmt::Stream;
-use crate::output::{fmt::Colorizer, Usage};
-use crate::parser::features::suggestions;
-use crate::parser::{ArgMatcher, SubCommand};
-use crate::parser::{Validator, ValueSource};
-use crate::util::Id;
-use crate::ArgAction;
-use crate::{INTERNAL_ERROR_MSG, INVALID_UTF8};
-
-pub(crate) struct Parser<'help, 'cmd> {
- cmd: &'cmd mut Command<'help>,
- cur_idx: Cell<usize>,
- /// Index of the previous flag subcommand in a group of flags.
- flag_subcmd_at: Option<usize>,
- /// Counter indicating the number of items to skip
- /// when revisiting the group of flags which includes the flag subcommand.
- flag_subcmd_skip: usize,
-}
-
-// Initializing Methods
-impl<'help, 'cmd> Parser<'help, 'cmd> {
- pub(crate) fn new(cmd: &'cmd mut Command<'help>) -> Self {
- Parser {
- cmd,
- cur_idx: Cell::new(0),
- flag_subcmd_at: None,
- flag_subcmd_skip: 0,
- }
- }
-}
-
-// Parsing Methods
-impl<'help, 'cmd> Parser<'help, 'cmd> {
- // The actual parsing function
- #[allow(clippy::cognitive_complexity)]
- pub(crate) fn get_matches_with(
- &mut self,
- matcher: &mut ArgMatcher,
- raw_args: &mut clap_lex::RawArgs,
- mut args_cursor: clap_lex::ArgCursor,
- ) -> ClapResult<()> {
- debug!("Parser::get_matches_with");
- // Verify all positional assertions pass
-
- let mut subcmd_name: Option<String> = None;
- let mut keep_state = false;
- let mut parse_state = ParseState::ValuesDone;
- let mut pos_counter = 1;
-
- // Already met any valid arg(then we shouldn't expect subcommands after it).
- let mut valid_arg_found = false;
- // If the user already passed '--'. Meaning only positional args follow.
- let mut trailing_values = false;
-
- // Count of positional args
- let positional_count = self
- .cmd
- .get_keymap()
- .keys()
- .filter(|x| x.is_position())
- .count();
- // If any arg sets .last(true)
- let contains_last = self.cmd.get_arguments().any(|x| x.is_last_set());
-
- while let Some(arg_os) = raw_args.next(&mut args_cursor) {
- // Recover the replaced items if any.
- if let Some(replaced_items) = arg_os
- .to_value()
- .ok()
- .and_then(|a| self.cmd.get_replacement(a))
- {
- debug!(
- "Parser::get_matches_with: found replacer: {:?}, target: {:?}",
- arg_os, replaced_items
- );
- raw_args.insert(&args_cursor, replaced_items);
- continue;
- }
-
- debug!(
- "Parser::get_matches_with: Begin parsing '{:?}' ({:?})",
- arg_os.to_value_os(),
- arg_os.to_value_os().as_raw_bytes()
- );
-
- // Has the user already passed '--'? Meaning only positional args follow
- if !trailing_values {
- if self.cmd.is_subcommand_precedence_over_arg_set()
- || !matches!(parse_state, ParseState::Opt(_) | ParseState::Pos(_))
- {
- // Does the arg match a subcommand name, or any of its aliases (if defined)
- let sc_name = self.possible_subcommand(arg_os.to_value(), valid_arg_found);
- debug!("Parser::get_matches_with: sc={:?}", sc_name);
- if let Some(sc_name) = sc_name {
- #[allow(deprecated)]
- if sc_name == "help"
- && !self.is_set(AS::NoAutoHelp)
- && !self.cmd.is_disable_help_subcommand_set()
- {
- self.parse_help_subcommand(raw_args.remaining(&mut args_cursor))?;
- unreachable!("`parse_help_subcommand` always errors");
- } else {
- subcmd_name = Some(sc_name.to_owned());
- }
- break;
- }
- }
-
- if arg_os.is_escape() {
- if matches!(&parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if
- self.cmd[opt].is_allow_hyphen_values_set())
- {
- // ParseResult::MaybeHyphenValue, do nothing
- } else {
- debug!("Parser::get_matches_with: setting TrailingVals=true");
- trailing_values = true;
- continue;
- }
- } else if let Some((long_arg, long_value)) = arg_os.to_long() {
- let parse_result = self.parse_long_arg(
- matcher,
- long_arg,
- long_value,
- &parse_state,
- &mut valid_arg_found,
- trailing_values,
- )?;
- debug!(
- "Parser::get_matches_with: After parse_long_arg {:?}",
- parse_result
- );
- match parse_result {
- ParseResult::NoArg => {
- unreachable!("`to_long` always has the flag specified")
- }
- ParseResult::ValuesDone => {
- parse_state = ParseState::ValuesDone;
- continue;
- }
- ParseResult::Opt(id) => {
- parse_state = ParseState::Opt(id);
- continue;
- }
- ParseResult::FlagSubCommand(name) => {
- debug!(
- "Parser::get_matches_with: FlagSubCommand found in long arg {:?}",
- &name
- );
- subcmd_name = Some(name);
- break;
- }
- ParseResult::EqualsNotProvided { arg } => {
- let _ = self.resolve_pending(matcher);
- return Err(ClapError::no_equals(
- self.cmd,
- arg,
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
- ParseResult::NoMatchingArg { arg } => {
- let _ = self.resolve_pending(matcher);
- let remaining_args: Vec<_> = raw_args
- .remaining(&mut args_cursor)
- .map(|x| x.to_str().expect(INVALID_UTF8))
- .collect();
- return Err(self.did_you_mean_error(&arg, matcher, &remaining_args));
- }
- ParseResult::UnneededAttachedValue { rest, used, arg } => {
- let _ = self.resolve_pending(matcher);
- return Err(ClapError::too_many_values(
- self.cmd,
- rest,
- arg,
- Usage::new(self.cmd).create_usage_no_title(&used),
- ));
- }
- ParseResult::MaybeHyphenValue => {
- // Maybe a hyphen value, do nothing.
- }
- ParseResult::AttachedValueNotConsumed => {
- unreachable!()
- }
- }
- } else if let Some(short_arg) = arg_os.to_short() {
- // Arg looks like a short flag, and not a possible number
-
- // Try to parse short args like normal, if allow_hyphen_values or
- // AllowNegativeNumbers is set, parse_short_arg will *not* throw
- // an error, and instead return Ok(None)
- let parse_result = self.parse_short_arg(
- matcher,
- short_arg,
- &parse_state,
- pos_counter,
- &mut valid_arg_found,
- trailing_values,
- )?;
- // If it's None, we then check if one of those two AppSettings was set
- debug!(
- "Parser::get_matches_with: After parse_short_arg {:?}",
- parse_result
- );
- match parse_result {
- ParseResult::NoArg => {
- // Is a single dash `-`, try positional.
- }
- ParseResult::ValuesDone => {
- parse_state = ParseState::ValuesDone;
- continue;
- }
- ParseResult::Opt(id) => {
- parse_state = ParseState::Opt(id);
- continue;
- }
- ParseResult::FlagSubCommand(name) => {
- // If there are more short flags to be processed, we should keep the state, and later
- // revisit the current group of short flags skipping the subcommand.
- keep_state = self
- .flag_subcmd_at
- .map(|at| {
- raw_args
- .seek(&mut args_cursor, clap_lex::SeekFrom::Current(-1));
- // Since we are now saving the current state, the number of flags to skip during state recovery should
- // be the current index (`cur_idx`) minus ONE UNIT TO THE LEFT of the starting position.
- self.flag_subcmd_skip = self.cur_idx.get() - at + 1;
- })
- .is_some();
-
- debug!(
- "Parser::get_matches_with:FlagSubCommandShort: subcmd_name={}, keep_state={}, flag_subcmd_skip={}",
- name,
- keep_state,
- self.flag_subcmd_skip
- );
-
- subcmd_name = Some(name);
- break;
- }
- ParseResult::EqualsNotProvided { arg } => {
- let _ = self.resolve_pending(matcher);
- return Err(ClapError::no_equals(
- self.cmd,
- arg,
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
- ParseResult::NoMatchingArg { arg } => {
- let _ = self.resolve_pending(matcher);
- return Err(ClapError::unknown_argument(
- self.cmd,
- arg,
- None,
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
- ParseResult::MaybeHyphenValue => {
- // Maybe a hyphen value, do nothing.
- }
- ParseResult::UnneededAttachedValue { .. }
- | ParseResult::AttachedValueNotConsumed => unreachable!(),
- }
- }
-
- if let ParseState::Opt(id) = &parse_state {
- // Assume this is a value of a previous arg.
-
- // get the option so we can check the settings
- let arg_values = matcher.pending_values_mut(id, None);
- let arg = &self.cmd[id];
- let parse_result = self.split_arg_values(
- arg,
- arg_os.to_value_os(),
- trailing_values,
- arg_values,
- );
- let parse_result = parse_result.unwrap_or_else(|| {
- if matcher.needs_more_vals(arg) {
- ParseResult::Opt(arg.id.clone())
- } else {
- ParseResult::ValuesDone
- }
- });
- parse_state = match parse_result {
- ParseResult::Opt(id) => ParseState::Opt(id),
- ParseResult::ValuesDone => ParseState::ValuesDone,
- _ => unreachable!(),
- };
- // get the next value from the iterator
- continue;
- }
- }
-
- // Correct pos_counter.
- pos_counter = {
- let is_second_to_last = pos_counter + 1 == positional_count;
-
- // The last positional argument, or second to last positional
- // argument may be set to .multiple_values(true) or `.multiple_occurrences(true)`
- let low_index_mults = is_second_to_last
- && self
- .cmd
- .get_positionals()
- .any(|a| a.is_multiple() && (positional_count != a.index.unwrap_or(0)))
- && self
- .cmd
- .get_positionals()
- .last()
- .map_or(false, |p_name| !p_name.is_last_set());
-
- let missing_pos = self.cmd.is_allow_missing_positional_set()
- && is_second_to_last
- && !trailing_values;
-
- debug!(
- "Parser::get_matches_with: Positional counter...{}",
- pos_counter
- );
- debug!(
- "Parser::get_matches_with: Low index multiples...{:?}",
- low_index_mults
- );
-
- if low_index_mults || missing_pos {
- let skip_current = if let Some(n) = raw_args.peek(&args_cursor) {
- if let Some(arg) = self
- .cmd
- .get_positionals()
- .find(|a| a.index == Some(pos_counter))
- {
- // If next value looks like a new_arg or it's a
- // subcommand, skip positional argument under current
- // pos_counter(which means current value cannot be a
- // positional argument with a value next to it), assume
- // current value matches the next arg.
- self.is_new_arg(&n, arg)
- || self
- .possible_subcommand(n.to_value(), valid_arg_found)
- .is_some()
- } else {
- true
- }
- } else {
- true
- };
-
- if skip_current {
- debug!("Parser::get_matches_with: Bumping the positional counter...");
- pos_counter + 1
- } else {
- pos_counter
- }
- } else if trailing_values
- && (self.cmd.is_allow_missing_positional_set() || contains_last)
- {
- // Came to -- and one positional has .last(true) set, so we go immediately
- // to the last (highest index) positional
- debug!("Parser::get_matches_with: .last(true) and --, setting last pos");
- positional_count
- } else {
- pos_counter
- }
- };
-
- if let Some(arg) = self.cmd.get_keymap().get(&pos_counter) {
- if arg.is_last_set() && !trailing_values {
- let _ = self.resolve_pending(matcher);
- return Err(ClapError::unknown_argument(
- self.cmd,
- arg_os.display().to_string(),
- None,
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
-
- if self.cmd.is_trailing_var_arg_set() && pos_counter == positional_count {
- trailing_values = true;
- }
-
- if matcher.pending_arg_id() != Some(&arg.id) || !arg.is_multiple_values_set() {
- self.resolve_pending(matcher)?;
- }
- let arg_values = matcher.pending_values_mut(&arg.id, Some(Identifier::Index));
- let _parse_result =
- self.split_arg_values(arg, arg_os.to_value_os(), trailing_values, arg_values);
- if let Some(_parse_result) = _parse_result {
- if _parse_result != ParseResult::ValuesDone {
- debug!(
- "Parser::get_matches_with: Ignoring state {:?}; positionals do their own thing",
- _parse_result
- );
- }
- }
-
- // Only increment the positional counter if it doesn't allow multiples
- if !arg.is_multiple() {
- pos_counter += 1;
- parse_state = ParseState::ValuesDone;
- } else {
- parse_state = ParseState::Pos(arg.id.clone());
- }
- valid_arg_found = true;
- } else if let Some(external_parser) =
- self.cmd.get_external_subcommand_value_parser().cloned()
- {
- // Get external subcommand name
- let sc_name = match arg_os.to_value() {
- Ok(s) => s.to_string(),
- Err(_) => {
- let _ = self.resolve_pending(matcher);
- return Err(ClapError::invalid_utf8(
- self.cmd,
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
- };
-
- // Collect the external subcommand args
- let mut sc_m = ArgMatcher::new(self.cmd);
- if cfg!(feature = "unstable-v4") || !raw_args.is_end(&args_cursor) {
- sc_m.start_occurrence_of_external(self.cmd);
- }
-
- for raw_val in raw_args.remaining(&mut args_cursor) {
- let val = external_parser.parse_ref(self.cmd, None, raw_val)?;
- let external_id = &Id::empty_hash();
- sc_m.add_val_to(external_id, val, raw_val.to_os_string());
- }
-
- matcher.subcommand(SubCommand {
- id: Id::from(&*sc_name),
- name: sc_name,
- matches: sc_m.into_inner(),
- });
-
- self.resolve_pending(matcher)?;
- #[cfg(feature = "env")]
- self.add_env(matcher)?;
- self.add_defaults(matcher)?;
- return Validator::new(self.cmd).validate(parse_state, matcher);
- } else {
- // Start error processing
- let _ = self.resolve_pending(matcher);
- return Err(self.match_arg_error(&arg_os, valid_arg_found, trailing_values));
- }
- }
-
- if let Some(ref pos_sc_name) = subcmd_name {
- let sc_name = self
- .cmd
- .find_subcommand(pos_sc_name)
- .expect(INTERNAL_ERROR_MSG)
- .get_name()
- .to_owned();
- self.parse_subcommand(&sc_name, matcher, raw_args, args_cursor, keep_state)?;
- }
-
- self.resolve_pending(matcher)?;
- #[cfg(feature = "env")]
- self.add_env(matcher)?;
- self.add_defaults(matcher)?;
- Validator::new(self.cmd).validate(parse_state, matcher)
- }
-
- fn match_arg_error(
- &self,
- arg_os: &clap_lex::ParsedArg<'_>,
- valid_arg_found: bool,
- trailing_values: bool,
- ) -> ClapError {
- // If argument follows a `--`
- if trailing_values {
- // If the arg matches a subcommand name, or any of its aliases (if defined)
- if self
- .possible_subcommand(arg_os.to_value(), valid_arg_found)
- .is_some()
- {
- return ClapError::unnecessary_double_dash(
- self.cmd,
- arg_os.display().to_string(),
- Usage::new(self.cmd).create_usage_with_title(&[]),
- );
- }
- }
- let candidates = suggestions::did_you_mean(
- &arg_os.display().to_string(),
- self.cmd.all_subcommand_names(),
- );
- // If the argument looks like a subcommand.
- if !candidates.is_empty() {
- let candidates: Vec<_> = candidates
- .iter()
- .map(|candidate| format!("'{}'", candidate))
- .collect();
- return ClapError::invalid_subcommand(
- self.cmd,
- arg_os.display().to_string(),
- candidates.join(" or "),
- self.cmd
- .get_bin_name()
- .unwrap_or_else(|| self.cmd.get_name())
- .to_owned(),
- Usage::new(self.cmd).create_usage_with_title(&[]),
- );
- }
- // If the argument must be a subcommand.
- if !self.cmd.has_args() || self.cmd.is_infer_subcommands_set() && self.cmd.has_subcommands()
- {
- return ClapError::unrecognized_subcommand(
- self.cmd,
- arg_os.display().to_string(),
- Usage::new(self.cmd).create_usage_with_title(&[]),
- );
- }
- ClapError::unknown_argument(
- self.cmd,
- arg_os.display().to_string(),
- None,
- Usage::new(self.cmd).create_usage_with_title(&[]),
- )
- }
-
- // Checks if the arg matches a subcommand name, or any of its aliases (if defined)
- fn possible_subcommand(
- &self,
- arg: Result<&str, &RawOsStr>,
- valid_arg_found: bool,
- ) -> Option<&str> {
- debug!("Parser::possible_subcommand: arg={:?}", arg);
- let arg = arg.ok()?;
-
- if !(self.cmd.is_args_conflicts_with_subcommands_set() && valid_arg_found) {
- if self.cmd.is_infer_subcommands_set() {
- // For subcommand `test`, we accepts it's prefix: `t`, `te`,
- // `tes` and `test`.
- let v = self
- .cmd
- .all_subcommand_names()
- .filter(|s| s.starts_with(arg))
- .collect::<Vec<_>>();
-
- if v.len() == 1 {
- return Some(v[0]);
- }
-
- // If there is any ambiguity, fallback to non-infer subcommand
- // search.
- }
- if let Some(sc) = self.cmd.find_subcommand(arg) {
- return Some(sc.get_name());
- }
- }
- None
- }
-
- // Checks if the arg matches a long flag subcommand name, or any of its aliases (if defined)
- fn possible_long_flag_subcommand(&self, arg: &str) -> Option<&str> {
- debug!("Parser::possible_long_flag_subcommand: arg={:?}", arg);
- if self.cmd.is_infer_subcommands_set() {
- let options = self
- .cmd
- .get_subcommands()
- .fold(Vec::new(), |mut options, sc| {
- if let Some(long) = sc.get_long_flag() {
- if long.starts_with(arg) {
- options.push(long);
- }
- options.extend(sc.get_all_aliases().filter(|alias| alias.starts_with(arg)))
- }
- options
- });
- if options.len() == 1 {
- return Some(options[0]);
- }
-
- for sc in options {
- if sc == arg {
- return Some(sc);
- }
- }
- } else if let Some(sc_name) = self.cmd.find_long_subcmd(arg) {
- return Some(sc_name);
- }
- None
- }
-
- fn parse_help_subcommand(
- &self,
- cmds: impl Iterator<Item = &'cmd OsStr>,
- ) -> ClapResult<std::convert::Infallible> {
- debug!("Parser::parse_help_subcommand");
-
- let mut cmd = self.cmd.clone();
- let sc = {
- let mut sc = &mut cmd;
-
- for cmd in cmds {
- sc = if let Some(sc_name) =
- sc.find_subcommand(cmd).map(|sc| sc.get_name().to_owned())
- {
- sc._build_subcommand(&sc_name).unwrap()
- } else {
- return Err(ClapError::unrecognized_subcommand(
- sc,
- cmd.to_string_lossy().into_owned(),
- Usage::new(sc).create_usage_with_title(&[]),
- ));
- };
- }
-
- sc
- };
- let parser = Parser::new(sc);
-
- Err(parser.help_err(true, Stream::Stdout))
- }
-
- fn is_new_arg(&self, next: &clap_lex::ParsedArg<'_>, current_positional: &Arg) -> bool {
- #![allow(clippy::needless_bool)] // Prefer consistent if/else-if ladder
-
- debug!(
- "Parser::is_new_arg: {:?}:{:?}",
- next.to_value_os(),
- current_positional.name
- );
-
- if self.cmd.is_allow_hyphen_values_set()
- || self.cmd[&current_positional.id].is_allow_hyphen_values_set()
- || (self.cmd.is_allow_negative_numbers_set() && next.is_number())
- {
- // If allow hyphen, this isn't a new arg.
- debug!("Parser::is_new_arg: Allow hyphen");
- false
- } else if next.is_long() {
- // If this is a long flag, this is a new arg.
- debug!("Parser::is_new_arg: --<something> found");
- true
- } else if next.is_short() {
- // If this is a short flag, this is a new arg. But a singe '-' by
- // itself is a value and typically means "stdin" on unix systems.
- debug!("Parser::is_new_arg: -<something> found");
- true
- } else {
- // Nothing special, this is a value.
- debug!("Parser::is_new_arg: value");
- false
- }
- }
-
- fn parse_subcommand(
- &mut self,
- sc_name: &str,
- matcher: &mut ArgMatcher,
- raw_args: &mut clap_lex::RawArgs,
- args_cursor: clap_lex::ArgCursor,
- keep_state: bool,
- ) -> ClapResult<()> {
- debug!("Parser::parse_subcommand");
-
- let partial_parsing_enabled = self.cmd.is_ignore_errors_set();
-
- if let Some(sc) = self.cmd._build_subcommand(sc_name) {
- let mut sc_matcher = ArgMatcher::new(sc);
-
- debug!(
- "Parser::parse_subcommand: About to parse sc={}",
- sc.get_name()
- );
-
- {
- let mut p = Parser::new(sc);
- // HACK: maintain indexes between parsers
- // FlagSubCommand short arg needs to revisit the current short args, but skip the subcommand itself
- if keep_state {
- p.cur_idx.set(self.cur_idx.get());
- p.flag_subcmd_at = self.flag_subcmd_at;
- p.flag_subcmd_skip = self.flag_subcmd_skip;
- }
- if let Err(error) = p.get_matches_with(&mut sc_matcher, raw_args, args_cursor) {
- if partial_parsing_enabled {
- debug!(
- "Parser::parse_subcommand: ignored error in subcommand {}: {:?}",
- sc_name, error
- );
- } else {
- return Err(error);
- }
- }
- }
- matcher.subcommand(SubCommand {
- id: sc.get_id(),
- name: sc.get_name().to_owned(),
- matches: sc_matcher.into_inner(),
- });
- }
- Ok(())
- }
-
- fn parse_long_arg(
- &mut self,
- matcher: &mut ArgMatcher,
- long_arg: Result<&str, &RawOsStr>,
- long_value: Option<&RawOsStr>,
- parse_state: &ParseState,
- valid_arg_found: &mut bool,
- trailing_values: bool,
- ) -> ClapResult<ParseResult> {
- // maybe here lifetime should be 'a
- debug!("Parser::parse_long_arg");
-
- if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if
- self.cmd[opt].is_allow_hyphen_values_set())
- {
- return Ok(ParseResult::MaybeHyphenValue);
- }
-
- debug!("Parser::parse_long_arg: Does it contain '='...");
- let long_arg = match long_arg {
- Ok(long_arg) => long_arg,
- Err(long_arg) => {
- return Ok(ParseResult::NoMatchingArg {
- arg: long_arg.to_str_lossy().into_owned(),
- });
- }
- };
- if long_arg.is_empty() {
- debug_assert!(
- long_value.is_some(),
- "`--` should be filtered out before this point"
- );
- }
-
- let arg = if let Some(arg) = self.cmd.get_keymap().get(long_arg) {
- debug!(
- "Parser::parse_long_arg: Found valid arg or flag '{}'",
- arg.to_string()
- );
- Some((long_arg, arg))
- } else if self.cmd.is_infer_long_args_set() {
- self.cmd.get_arguments().find_map(|a| {
- if let Some(long) = a.long {
- if long.starts_with(long_arg) {
- return Some((long, a));
- }
- }
- a.aliases
- .iter()
- .find_map(|(alias, _)| alias.starts_with(long_arg).then(|| (*alias, a)))
- })
- } else {
- None
- };
-
- if let Some((_long_arg, arg)) = arg {
- let ident = Identifier::Long;
- *valid_arg_found = true;
- if arg.is_takes_value_set() {
- debug!(
- "Parser::parse_long_arg({:?}): Found an arg with value '{:?}'",
- long_arg, &long_value
- );
- let has_eq = long_value.is_some();
- self.parse_opt_value(ident, long_value, arg, matcher, trailing_values, has_eq)
- } else if let Some(rest) = long_value {
- let required = self.cmd.required_graph();
- debug!(
- "Parser::parse_long_arg({:?}): Got invalid literal `{:?}`",
- long_arg, rest
- );
- let used: Vec<Id> = matcher
- .arg_ids()
- .filter(|arg_id| {
- matcher.check_explicit(arg_id, crate::builder::ArgPredicate::IsPresent)
- })
- .filter(|&n| {
- self.cmd
- .find(n)
- .map_or(true, |a| !(a.is_hide_set() || required.contains(&a.id)))
- })
- .cloned()
- .collect();
-
- Ok(ParseResult::UnneededAttachedValue {
- rest: rest.to_str_lossy().into_owned(),
- used,
- arg: arg.to_string(),
- })
- } else {
- debug!("Parser::parse_long_arg({:?}): Presence validated", long_arg);
- self.react(Some(ident), ValueSource::CommandLine, arg, vec![], matcher)
- }
- } else if let Some(sc_name) = self.possible_long_flag_subcommand(long_arg) {
- Ok(ParseResult::FlagSubCommand(sc_name.to_string()))
- } else if self.cmd.is_allow_hyphen_values_set() {
- Ok(ParseResult::MaybeHyphenValue)
- } else {
- Ok(ParseResult::NoMatchingArg {
- arg: long_arg.to_owned(),
- })
- }
- }
-
- fn parse_short_arg(
- &mut self,
- matcher: &mut ArgMatcher,
- mut short_arg: clap_lex::ShortFlags<'_>,
- parse_state: &ParseState,
- // change this to possible pos_arg when removing the usage of &mut Parser.
- pos_counter: usize,
- valid_arg_found: &mut bool,
- trailing_values: bool,
- ) -> ClapResult<ParseResult> {
- debug!("Parser::parse_short_arg: short_arg={:?}", short_arg);
-
- #[allow(clippy::blocks_in_if_conditions)]
- if self.cmd.is_allow_negative_numbers_set() && short_arg.is_number() {
- debug!("Parser::parse_short_arg: negative number");
- return Ok(ParseResult::MaybeHyphenValue);
- } else if self.cmd.is_allow_hyphen_values_set()
- && short_arg
- .clone()
- .any(|c| !c.map(|c| self.cmd.contains_short(c)).unwrap_or_default())
- {
- debug!("Parser::parse_short_args: contains non-short flag");
- return Ok(ParseResult::MaybeHyphenValue);
- } else if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt)
- if self.cmd[opt].is_allow_hyphen_values_set())
- {
- debug!("Parser::parse_short_args: prior arg accepts hyphenated values",);
- return Ok(ParseResult::MaybeHyphenValue);
- } else if self
- .cmd
- .get_keymap()
- .get(&pos_counter)
- .map_or(false, |arg| {
- arg.is_allow_hyphen_values_set() && !arg.is_last_set()
- })
- {
- debug!(
- "Parser::parse_short_args: positional at {} allows hyphens",
- pos_counter
- );
- return Ok(ParseResult::MaybeHyphenValue);
- }
-
- let mut ret = ParseResult::NoArg;
-
- let skip = self.flag_subcmd_skip;
- self.flag_subcmd_skip = 0;
- let res = short_arg.advance_by(skip);
- debug_assert_eq!(
- res,
- Ok(()),
- "tracking of `flag_subcmd_skip` is off for `{:?}`",
- short_arg
- );
- while let Some(c) = short_arg.next_flag() {
- let c = match c {
- Ok(c) => c,
- Err(rest) => {
- return Ok(ParseResult::NoMatchingArg {
- arg: format!("-{}", rest.to_str_lossy()),
- });
- }
- };
- debug!("Parser::parse_short_arg:iter:{}", c);
-
- // Check for matching short options, and return the name if there is no trailing
- // concatenated value: -oval
- // Option: -o
- // Value: val
- if let Some(arg) = self.cmd.get_keymap().get(&c) {
- let ident = Identifier::Short;
- debug!(
- "Parser::parse_short_arg:iter:{}: Found valid opt or flag",
- c
- );
- *valid_arg_found = true;
- if !arg.is_takes_value_set() {
- ret =
- self.react(Some(ident), ValueSource::CommandLine, arg, vec![], matcher)?;
- continue;
- }
-
- // Check for trailing concatenated value
- //
- // Cloning the iterator, so we rollback if it isn't there.
- let val = short_arg.clone().next_value_os().unwrap_or_default();
- debug!(
- "Parser::parse_short_arg:iter:{}: val={:?} (bytes), val={:?} (ascii), short_arg={:?}",
- c, val, val.as_raw_bytes(), short_arg
- );
- let val = Some(val).filter(|v| !v.is_empty());
-
- // Default to "we're expecting a value later".
- //
- // If attached value is not consumed, we may have more short
- // flags to parse, continue.
- //
- // e.g. `-xvf`, when require_equals && x.min_vals == 0, we don't
- // consume the `vf`, even if it's provided as value.
- let (val, has_eq) = if let Some(val) = val.and_then(|v| v.strip_prefix('=')) {
- (Some(val), true)
- } else {
- (val, false)
- };
- match self.parse_opt_value(ident, val, arg, matcher, trailing_values, has_eq)? {
- ParseResult::AttachedValueNotConsumed => continue,
- x => return Ok(x),
- }
- }
-
- return if let Some(sc_name) = self.cmd.find_short_subcmd(c) {
- debug!("Parser::parse_short_arg:iter:{}: subcommand={}", c, sc_name);
- // Make sure indices get updated before reading `self.cur_idx`
- self.resolve_pending(matcher)?;
- self.cur_idx.set(self.cur_idx.get() + 1);
- debug!("Parser::parse_short_arg: cur_idx:={}", self.cur_idx.get());
-
- let name = sc_name.to_string();
- // Get the index of the previously saved flag subcommand in the group of flags (if exists).
- // If it is a new flag subcommand, then the formentioned index should be the current one
- // (ie. `cur_idx`), and should be registered.
- let cur_idx = self.cur_idx.get();
- self.flag_subcmd_at.get_or_insert(cur_idx);
- let done_short_args = short_arg.is_empty();
- if done_short_args {
- self.flag_subcmd_at = None;
- }
- Ok(ParseResult::FlagSubCommand(name))
- } else {
- Ok(ParseResult::NoMatchingArg {
- arg: format!("-{}", c),
- })
- };
- }
- Ok(ret)
- }
-
- fn parse_opt_value(
- &self,
- ident: Identifier,
- attached_value: Option<&RawOsStr>,
- arg: &Arg<'help>,
- matcher: &mut ArgMatcher,
- trailing_values: bool,
- has_eq: bool,
- ) -> ClapResult<ParseResult> {
- debug!(
- "Parser::parse_opt_value; arg={}, val={:?}, has_eq={:?}",
- arg.name, attached_value, has_eq
- );
- debug!("Parser::parse_opt_value; arg.settings={:?}", arg.settings);
-
- debug!("Parser::parse_opt_value; Checking for val...");
- // require_equals is set, but no '=' is provided, try throwing error.
- if arg.is_require_equals_set() && !has_eq {
- if arg.min_vals == Some(0) {
- debug!("Requires equals, but min_vals == 0");
- let mut arg_values = Vec::new();
- // We assume this case is valid: require equals, but min_vals == 0.
- if !arg.default_missing_vals.is_empty() {
- debug!("Parser::parse_opt_value: has default_missing_vals");
- for v in arg.default_missing_vals.iter() {
- let trailing_values = false; // CLI should not be affecting default_missing_values
- let _parse_result = self.split_arg_values(
- arg,
- &RawOsStr::new(v),
- trailing_values,
- &mut arg_values,
- );
- if let Some(_parse_result) = _parse_result {
- if _parse_result != ParseResult::ValuesDone {
- debug!("Parser::parse_opt_value: Ignoring state {:?}; no values accepted after default_missing_values", _parse_result);
- }
- }
- }
- };
- let react_result = self.react(
- Some(ident),
- ValueSource::CommandLine,
- arg,
- arg_values,
- matcher,
- )?;
- debug_assert_eq!(react_result, ParseResult::ValuesDone);
- if attached_value.is_some() {
- Ok(ParseResult::AttachedValueNotConsumed)
- } else {
- Ok(ParseResult::ValuesDone)
- }
- } else {
- debug!("Requires equals but not provided. Error.");
- Ok(ParseResult::EqualsNotProvided {
- arg: arg.to_string(),
- })
- }
- } else if let Some(v) = attached_value {
- let mut arg_values = Vec::new();
- let parse_result = self.split_arg_values(arg, v, trailing_values, &mut arg_values);
- let react_result = self.react(
- Some(ident),
- ValueSource::CommandLine,
- arg,
- arg_values,
- matcher,
- )?;
- debug_assert_eq!(react_result, ParseResult::ValuesDone);
- let mut parse_result = parse_result.unwrap_or_else(|| {
- if matcher.needs_more_vals(arg) {
- ParseResult::Opt(arg.id.clone())
- } else {
- ParseResult::ValuesDone
- }
- });
- if parse_result != ParseResult::ValuesDone {
- debug!("Parser::parse_opt_value: Overriding state {:?}; no values accepted after attached", parse_result);
- parse_result = ParseResult::ValuesDone;
- }
- Ok(parse_result)
- } else {
- debug!("Parser::parse_opt_value: More arg vals required...");
- self.resolve_pending(matcher)?;
- matcher.pending_values_mut(&arg.id, Some(ident));
- Ok(ParseResult::Opt(arg.id.clone()))
- }
- }
-
- fn split_arg_values(
- &self,
- arg: &Arg<'help>,
- val: &RawOsStr,
- trailing_values: bool,
- output: &mut Vec<OsString>,
- ) -> Option<ParseResult> {
- debug!("Parser::split_arg_values; arg={}, val={:?}", arg.name, val);
- debug!(
- "Parser::split_arg_values; trailing_values={:?}, DontDelimTrailingVals={:?}",
- trailing_values,
- self.cmd.is_dont_delimit_trailing_values_set()
- );
-
- let mut delim = arg.val_delim;
- if trailing_values && self.cmd.is_dont_delimit_trailing_values_set() {
- delim = None;
- }
- match delim {
- Some(delim) if val.contains(delim) => {
- let vals = val.split(delim).map(|x| x.to_os_str().into_owned());
- for raw_val in vals {
- if Some(raw_val.as_os_str()) == arg.terminator.map(OsStr::new) {
- return Some(ParseResult::ValuesDone);
- }
- output.push(raw_val);
- }
- // Delimited values are always considered the final value
- Some(ParseResult::ValuesDone)
- }
- _ if Some(val) == arg.terminator.map(RawOsStr::from_str) => {
- Some(ParseResult::ValuesDone)
- }
- _ => {
- output.push(val.to_os_str().into_owned());
- if arg.is_require_value_delimiter_set() {
- Some(ParseResult::ValuesDone)
- } else {
- None
- }
- }
- }
- }
-
- fn push_arg_values(
- &self,
- arg: &Arg<'help>,
- raw_vals: Vec<OsString>,
- matcher: &mut ArgMatcher,
- ) -> ClapResult<()> {
- debug!("Parser::push_arg_values: {:?}", raw_vals);
-
- for raw_val in raw_vals {
- // update the current index because each value is a distinct index to clap
- self.cur_idx.set(self.cur_idx.get() + 1);
- debug!(
- "Parser::add_single_val_to_arg: cur_idx:={}",
- self.cur_idx.get()
- );
- let value_parser = arg.get_value_parser();
- let val = value_parser.parse_ref(self.cmd, Some(arg), &raw_val)?;
-
- // Increment or create the group "args"
- for group in self.cmd.groups_for_arg(&arg.id) {
- matcher.add_val_to(&group, val.clone(), raw_val.clone());
- }
-
- matcher.add_val_to(&arg.id, val, raw_val);
- matcher.add_index_to(&arg.id, self.cur_idx.get());
- }
-
- Ok(())
- }
-
- fn resolve_pending(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
- let pending = match matcher.take_pending() {
- Some(pending) => pending,
- None => {
- return Ok(());
- }
- };
-
- debug!("Parser::resolve_pending: id={:?}", pending.id);
- let arg = self.cmd.find(&pending.id).expect(INTERNAL_ERROR_MSG);
- let _ = self.react(
- pending.ident,
- ValueSource::CommandLine,
- arg,
- pending.raw_vals,
- matcher,
- )?;
-
- Ok(())
- }
-
- fn react(
- &self,
- ident: Option<Identifier>,
- source: ValueSource,
- arg: &Arg<'help>,
- raw_vals: Vec<OsString>,
- matcher: &mut ArgMatcher,
- ) -> ClapResult<ParseResult> {
- self.resolve_pending(matcher)?;
-
- debug!(
- "Parser::react action={:?}, identifier={:?}, source={:?}",
- arg.get_action(),
- ident,
- source
- );
- match arg.get_action() {
- ArgAction::Set => {
- if source == ValueSource::CommandLine
- && matches!(ident, Some(Identifier::Short) | Some(Identifier::Long))
- {
- // Record flag's index
- self.cur_idx.set(self.cur_idx.get() + 1);
- debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
- }
- matcher.remove(&arg.id);
- self.start_custom_arg(matcher, arg, source);
- self.push_arg_values(arg, raw_vals, matcher)?;
- if cfg!(debug_assertions) && matcher.needs_more_vals(arg) {
- debug!(
- "Parser::react not enough values passed in, leaving it to the validator to complain",
- );
- }
- Ok(ParseResult::ValuesDone)
- }
- ArgAction::Append => {
- if source == ValueSource::CommandLine
- && matches!(ident, Some(Identifier::Short) | Some(Identifier::Long))
- {
- // Record flag's index
- self.cur_idx.set(self.cur_idx.get() + 1);
- debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
- }
- self.start_custom_arg(matcher, arg, source);
- self.push_arg_values(arg, raw_vals, matcher)?;
- if cfg!(debug_assertions) && matcher.needs_more_vals(arg) {
- debug!(
- "Parser::react not enough values passed in, leaving it to the validator to complain",
- );
- }
- Ok(ParseResult::ValuesDone)
- }
- #[allow(deprecated)]
- ArgAction::StoreValue => {
- if ident == Some(Identifier::Index)
- && arg.is_multiple_values_set()
- && matcher.contains(&arg.id)
- {
- // HACK: Reuse existing occurrence
- } else if source == ValueSource::CommandLine {
- if matches!(ident, Some(Identifier::Short) | Some(Identifier::Long)) {
- // Record flag's index
- self.cur_idx.set(self.cur_idx.get() + 1);
- debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
- }
- self.start_occurrence_of_arg(matcher, arg);
- } else {
- self.start_custom_arg(matcher, arg, source);
- }
- self.push_arg_values(arg, raw_vals, matcher)?;
- if ident == Some(Identifier::Index) && arg.is_multiple_values_set() {
- // HACK: Maintain existing occurrence behavior
- let matched = matcher.get_mut(&arg.id).unwrap();
- #[allow(deprecated)]
- matched.set_occurrences(matched.num_vals() as u64);
- }
- if cfg!(debug_assertions) && matcher.needs_more_vals(arg) {
- debug!(
- "Parser::react not enough values passed in, leaving it to the validator to complain",
- );
- }
- Ok(ParseResult::ValuesDone)
- }
- #[allow(deprecated)]
- ArgAction::IncOccurrence => {
- debug_assert_eq!(raw_vals, Vec::<OsString>::new());
- if source == ValueSource::CommandLine {
- if matches!(ident, Some(Identifier::Short) | Some(Identifier::Long)) {
- // Record flag's index
- self.cur_idx.set(self.cur_idx.get() + 1);
- debug!("Parser::react: cur_idx:={}", self.cur_idx.get());
- }
- self.start_occurrence_of_arg(matcher, arg);
- } else {
- self.start_custom_arg(matcher, arg, source);
- }
- matcher.add_index_to(&arg.id, self.cur_idx.get());
- Ok(ParseResult::ValuesDone)
- }
- ArgAction::SetTrue => {
- let raw_vals = match raw_vals.len() {
- 0 => {
- vec![OsString::from("true")]
- }
- 1 => raw_vals,
- _ => {
- debug!("Parser::react ignoring trailing values: {:?}", raw_vals);
- let mut raw_vals = raw_vals;
- raw_vals.resize(1, Default::default());
- raw_vals
- }
- };
-
- matcher.remove(&arg.id);
- self.start_custom_arg(matcher, arg, source);
- self.push_arg_values(arg, raw_vals, matcher)?;
- Ok(ParseResult::ValuesDone)
- }
- ArgAction::SetFalse => {
- let raw_vals = match raw_vals.len() {
- 0 => {
- vec![OsString::from("false")]
- }
- 1 => raw_vals,
- _ => {
- debug!("Parser::react ignoring trailing values: {:?}", raw_vals);
- let mut raw_vals = raw_vals;
- raw_vals.resize(1, Default::default());
- raw_vals
- }
- };
-
- matcher.remove(&arg.id);
- self.start_custom_arg(matcher, arg, source);
- self.push_arg_values(arg, raw_vals, matcher)?;
- Ok(ParseResult::ValuesDone)
- }
- ArgAction::Count => {
- let raw_vals = match raw_vals.len() {
- 0 => {
- let existing_value = *matcher
- .get_one::<crate::builder::CountType>(arg.get_id())
- .unwrap_or(&0);
- let next_value = existing_value.saturating_add(1);
- vec![OsString::from(next_value.to_string())]
- }
- 1 => raw_vals,
- _ => {
- debug!("Parser::react ignoring trailing values: {:?}", raw_vals);
- let mut raw_vals = raw_vals;
- raw_vals.resize(1, Default::default());
- raw_vals
- }
- };
-
- matcher.remove(&arg.id);
- self.start_custom_arg(matcher, arg, source);
- self.push_arg_values(arg, raw_vals, matcher)?;
- Ok(ParseResult::ValuesDone)
- }
- ArgAction::Help => {
- debug_assert_eq!(raw_vals, Vec::<OsString>::new());
- let use_long = match ident {
- Some(Identifier::Long) => true,
- Some(Identifier::Short) => false,
- Some(Identifier::Index) => true,
- None => true,
- };
- debug!("Help: use_long={}", use_long);
- Err(self.help_err(use_long, Stream::Stdout))
- }
- ArgAction::Version => {
- debug_assert_eq!(raw_vals, Vec::<OsString>::new());
- let use_long = match ident {
- Some(Identifier::Long) => true,
- Some(Identifier::Short) => false,
- Some(Identifier::Index) => true,
- None => true,
- };
- debug!("Version: use_long={}", use_long);
- Err(self.version_err(use_long))
- }
- }
- }
-
- fn remove_overrides(&self, arg: &Arg<'help>, matcher: &mut ArgMatcher) {
- debug!("Parser::remove_overrides: id={:?}", arg.id);
- for override_id in &arg.overrides {
- debug!("Parser::remove_overrides:iter:{:?}: removing", override_id);
- matcher.remove(override_id);
- }
-
- // Override anything that can override us
- let mut transitive = Vec::new();
- for arg_id in matcher.arg_ids() {
- if let Some(overrider) = self.cmd.find(arg_id) {
- if overrider.overrides.contains(&arg.id) {
- transitive.push(&overrider.id);
- }
- }
- }
- for overrider_id in transitive {
- debug!("Parser::remove_overrides:iter:{:?}: removing", overrider_id);
- matcher.remove(overrider_id);
- }
- }
-
- #[cfg(feature = "env")]
- fn add_env(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
- debug!("Parser::add_env");
- use crate::util::str_to_bool;
-
- let trailing_values = false; // defaults are independent of the commandline
- for arg in self.cmd.get_arguments() {
- // Use env only if the arg was absent among command line args,
- // early return if this is not the case.
- if matcher.contains(&arg.id) {
- debug!("Parser::add_env: Skipping existing arg `{}`", arg);
- continue;
- }
-
- debug!("Parser::add_env: Checking arg `{}`", arg);
- if let Some((_, Some(ref val))) = arg.env {
- let val = RawOsStr::new(val);
-
- if arg.is_takes_value_set() {
- debug!(
- "Parser::add_env: Found an opt with value={:?}, trailing={:?}",
- val, trailing_values
- );
- let mut arg_values = Vec::new();
- let _parse_result =
- self.split_arg_values(arg, &val, trailing_values, &mut arg_values);
- let _ = self.react(None, ValueSource::EnvVariable, arg, arg_values, matcher)?;
- if let Some(_parse_result) = _parse_result {
- if _parse_result != ParseResult::ValuesDone {
- debug!("Parser::add_env: Ignoring state {:?}; env variables are outside of the parse loop", _parse_result);
- }
- }
- } else {
- match arg.get_action() {
- #[allow(deprecated)]
- ArgAction::StoreValue => unreachable!("{:?} is not a flag", arg.get_id()),
- #[allow(deprecated)]
- ArgAction::IncOccurrence => {
- debug!("Parser::add_env: Found a flag with value `{:?}`", val);
- let predicate = str_to_bool(val.to_str_lossy());
- debug!("Parser::add_env: Found boolean literal `{:?}`", predicate);
- if predicate.unwrap_or(true) {
- let _ = self.react(
- None,
- ValueSource::EnvVariable,
- arg,
- vec![],
- matcher,
- )?;
- }
- }
- ArgAction::Set
- | ArgAction::Append
- | ArgAction::SetTrue
- | ArgAction::SetFalse
- | ArgAction::Count => {
- let mut arg_values = Vec::new();
- let _parse_result =
- self.split_arg_values(arg, &val, trailing_values, &mut arg_values);
- let _ = self.react(
- None,
- ValueSource::EnvVariable,
- arg,
- arg_values,
- matcher,
- )?;
- if let Some(_parse_result) = _parse_result {
- if _parse_result != ParseResult::ValuesDone {
- debug!("Parser::add_env: Ignoring state {:?}; env variables are outside of the parse loop", _parse_result);
- }
- }
- }
- // Early return on `Help` or `Version`.
- ArgAction::Help | ArgAction::Version => {
- let _ =
- self.react(None, ValueSource::EnvVariable, arg, vec![], matcher)?;
- }
- }
- }
- }
- }
-
- Ok(())
- }
-
- fn add_defaults(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
- debug!("Parser::add_defaults");
-
- for arg in self.cmd.get_arguments() {
- debug!("Parser::add_defaults:iter:{}:", arg.name);
- self.add_default_value(arg, matcher)?;
- }
-
- Ok(())
- }
-
- fn add_default_value(&self, arg: &Arg<'help>, matcher: &mut ArgMatcher) -> ClapResult<()> {
- let trailing_values = false; // defaults are independent of the commandline
-
- if !arg.default_missing_vals.is_empty() {
- debug!(
- "Parser::add_default_value:iter:{}: has default missing vals",
- arg.name
- );
- match matcher.get(&arg.id) {
- Some(ma) if ma.all_val_groups_empty() => {
- debug!(
- "Parser::add_default_value:iter:{}: has no user defined vals",
- arg.name
- );
- // The flag occurred, we just want to add the val groups
- let mut arg_values = Vec::new();
- for v in arg.default_missing_vals.iter() {
- let _parse_result = self.split_arg_values(
- arg,
- &RawOsStr::new(v),
- trailing_values,
- &mut arg_values,
- );
- if let Some(_parse_result) = _parse_result {
- if _parse_result != ParseResult::ValuesDone {
- debug!("Parser::add_default_value: Ignoring state {:?}; defaults are outside of the parse loop", _parse_result);
- }
- }
- }
- self.start_custom_arg(matcher, arg, ValueSource::CommandLine);
- self.push_arg_values(arg, arg_values, matcher)?;
- }
- None => {
- debug!("Parser::add_default_value:iter:{}: wasn't used", arg.name);
- // do nothing
- }
- _ => {
- debug!(
- "Parser::add_default_value:iter:{}: has user defined vals",
- arg.name
- );
- // do nothing
- }
- }
- } else {
- debug!(
- "Parser::add_default_value:iter:{}: doesn't have default missing vals",
- arg.name
- );
- // do nothing
- }
-
- if !arg.default_vals_ifs.is_empty() {
- debug!("Parser::add_default_value: has conditional defaults");
- if !matcher.contains(&arg.id) {
- for (id, val, default) in arg.default_vals_ifs.iter() {
- let add = if let Some(a) = matcher.get(id) {
- match val {
- crate::builder::ArgPredicate::Equals(v) => {
- a.raw_vals_flatten().any(|value| v == value)
- }
- crate::builder::ArgPredicate::IsPresent => true,
- }
- } else {
- false
- };
-
- if add {
- if let Some(default) = default {
- let mut arg_values = Vec::new();
- let _parse_result = self.split_arg_values(
- arg,
- &RawOsStr::new(default),
- trailing_values,
- &mut arg_values,
- );
- let _ = self.react(
- None,
- ValueSource::DefaultValue,
- arg,
- arg_values,
- matcher,
- )?;
- if let Some(_parse_result) = _parse_result {
- if _parse_result != ParseResult::ValuesDone {
- debug!("Parser::add_default_value: Ignoring state {:?}; defaults are outside of the parse loop", _parse_result);
- }
- }
- }
- return Ok(());
- }
- }
- }
- } else {
- debug!("Parser::add_default_value: doesn't have conditional defaults");
- }
-
- if !arg.default_vals.is_empty() {
- debug!(
- "Parser::add_default_value:iter:{}: has default vals",
- arg.name
- );
- if matcher.contains(&arg.id) {
- debug!("Parser::add_default_value:iter:{}: was used", arg.name);
- // do nothing
- } else {
- debug!("Parser::add_default_value:iter:{}: wasn't used", arg.name);
- let mut arg_values = Vec::new();
- for v in arg.default_vals.iter() {
- let _parse_result = self.split_arg_values(
- arg,
- &RawOsStr::new(v),
- trailing_values,
- &mut arg_values,
- );
- if let Some(_parse_result) = _parse_result {
- if _parse_result != ParseResult::ValuesDone {
- debug!("Parser::add_default_value: Ignoring state {:?}; defaults are outside of the parse loop", _parse_result);
- }
- }
- }
- let _ = self.react(None, ValueSource::DefaultValue, arg, arg_values, matcher)?;
- }
- } else {
- debug!(
- "Parser::add_default_value:iter:{}: doesn't have default vals",
- arg.name
- );
-
- // do nothing
- }
-
- Ok(())
- }
-
- fn start_custom_arg(&self, matcher: &mut ArgMatcher, arg: &Arg<'help>, source: ValueSource) {
- if source == ValueSource::CommandLine {
- // With each new occurrence, remove overrides from prior occurrences
- self.remove_overrides(arg, matcher);
- }
- matcher.start_custom_arg(arg, source);
- for group in self.cmd.groups_for_arg(&arg.id) {
- matcher.start_custom_group(&group, source);
- }
- }
-
- /// Increase occurrence of specific argument and the grouped arg it's in.
- fn start_occurrence_of_arg(&self, matcher: &mut ArgMatcher, arg: &Arg<'help>) {
- // With each new occurrence, remove overrides from prior occurrences
- self.remove_overrides(arg, matcher);
-
- matcher.start_occurrence_of_arg(arg);
- // Increment or create the group "args"
- for group in self.cmd.groups_for_arg(&arg.id) {
- matcher.start_occurrence_of_group(&group);
- }
- }
-}
-
-// Error, Help, and Version Methods
-impl<'help, 'cmd> Parser<'help, 'cmd> {
- /// Is only used for the long flag(which is the only one needs fuzzy searching)
- fn did_you_mean_error(
- &mut self,
- arg: &str,
- matcher: &mut ArgMatcher,
- remaining_args: &[&str],
- ) -> ClapError {
- debug!("Parser::did_you_mean_error: arg={}", arg);
- // Didn't match a flag or option
- let longs = self
- .cmd
- .get_keymap()
- .keys()
- .filter_map(|x| match x {
- KeyType::Long(l) => Some(l.to_string_lossy().into_owned()),
- _ => None,
- })
- .collect::<Vec<_>>();
- debug!("Parser::did_you_mean_error: longs={:?}", longs);
-
- let did_you_mean = suggestions::did_you_mean_flag(
- arg,
- remaining_args,
- longs.iter().map(|x| &x[..]),
- self.cmd.get_subcommands_mut(),
- );
-
- // Add the arg to the matches to build a proper usage string
- if let Some((name, _)) = did_you_mean.as_ref() {
- if let Some(arg) = self.cmd.get_keymap().get(&name.as_ref()) {
- self.start_occurrence_of_arg(matcher, arg);
- }
- }
-
- let required = self.cmd.required_graph();
- let used: Vec<Id> = matcher
- .arg_ids()
- .filter(|arg_id| {
- matcher.check_explicit(arg_id, crate::builder::ArgPredicate::IsPresent)
- })
- .filter(|n| self.cmd.find(n).map_or(true, |a| !a.is_hide_set()))
- .cloned()
- .collect();
-
- ClapError::unknown_argument(
- self.cmd,
- format!("--{}", arg),
- did_you_mean,
- Usage::new(self.cmd)
- .required(&required)
- .create_usage_with_title(&*used),
- )
- }
-
- fn help_err(&self, use_long: bool, stream: Stream) -> ClapError {
- match self.cmd.write_help_err(use_long, stream) {
- Ok(c) => ClapError::display_help(self.cmd, c),
- Err(e) => e,
- }
- }
-
- fn version_err(&self, use_long: bool) -> ClapError {
- debug!("Parser::version_err");
-
- let msg = self.cmd._render_version(use_long);
- let mut c = Colorizer::new(Stream::Stdout, self.cmd.color_help());
- c.none(msg);
- ClapError::display_version(self.cmd, c)
- }
-}
-
-// Query Methods
-impl<'help, 'cmd> Parser<'help, 'cmd> {
- pub(crate) fn is_set(&self, s: AS) -> bool {
- self.cmd.is_set(s)
- }
-}
-
-#[derive(Debug, PartialEq, Eq)]
-pub(crate) enum ParseState {
- ValuesDone,
- Opt(Id),
- Pos(Id),
-}
-
-/// Recoverable Parsing results.
-#[derive(Debug, PartialEq, Clone)]
-#[must_use]
-enum ParseResult {
- FlagSubCommand(String),
- Opt(Id),
- ValuesDone,
- /// Value attached to the short flag is not consumed(e.g. 'u' for `-cu` is
- /// not consumed).
- AttachedValueNotConsumed,
- /// This long flag doesn't need a value but is provided one.
- UnneededAttachedValue {
- rest: String,
- used: Vec<Id>,
- arg: String,
- },
- /// This flag might be an hyphen Value.
- MaybeHyphenValue,
- /// Equals required but not provided.
- EqualsNotProvided {
- arg: String,
- },
- /// Failed to match a Arg.
- NoMatchingArg {
- arg: String,
- },
- /// No argument found e.g. parser is given `-` when parsing a flag.
- NoArg,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub(crate) struct PendingArg {
- pub(crate) id: Id,
- pub(crate) ident: Option<Identifier>,
- pub(crate) raw_vals: Vec<OsString>,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub(crate) enum Identifier {
- Short,
- Long,
- Index,
-}
diff --git a/vendor/clap/src/parser/validator.rs b/vendor/clap/src/parser/validator.rs
deleted file mode 100644
index ebf2b234d..000000000
--- a/vendor/clap/src/parser/validator.rs
+++ /dev/null
@@ -1,692 +0,0 @@
-// Internal
-use crate::builder::{AppSettings, Arg, ArgPredicate, Command, PossibleValue};
-use crate::error::{Error, Result as ClapResult};
-use crate::output::fmt::Stream;
-use crate::output::Usage;
-use crate::parser::{ArgMatcher, MatchedArg, ParseState};
-use crate::util::ChildGraph;
-use crate::util::Id;
-use crate::{INTERNAL_ERROR_MSG, INVALID_UTF8};
-
-pub(crate) struct Validator<'help, 'cmd> {
- cmd: &'cmd Command<'help>,
- required: ChildGraph<Id>,
-}
-
-impl<'help, 'cmd> Validator<'help, 'cmd> {
- pub(crate) fn new(cmd: &'cmd Command<'help>) -> Self {
- let required = cmd.required_graph();
- Validator { cmd, required }
- }
-
- pub(crate) fn validate(
- &mut self,
- parse_state: ParseState,
- matcher: &mut ArgMatcher,
- ) -> ClapResult<()> {
- debug!("Validator::validate");
- let mut conflicts = Conflicts::new();
- let has_subcmd = matcher.subcommand_name().is_some();
-
- if let ParseState::Opt(a) = parse_state {
- debug!("Validator::validate: needs_val_of={:?}", a);
-
- let o = &self.cmd[&a];
- let should_err = if let Some(v) = matcher.args.get(&o.id) {
- v.all_val_groups_empty() && !(o.min_vals.is_some() && o.min_vals.unwrap() == 0)
- } else {
- true
- };
- if should_err {
- return Err(Error::empty_value(
- self.cmd,
- &get_possible_values(o)
- .iter()
- .filter(|pv| !pv.is_hide_set())
- .map(PossibleValue::get_name)
- .collect::<Vec<_>>(),
- o.to_string(),
- ));
- }
- }
-
- if !has_subcmd && self.cmd.is_arg_required_else_help_set() {
- let num_user_values = matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
- .count();
- if num_user_values == 0 {
- let message = self.cmd.write_help_err(false, Stream::Stderr)?;
- return Err(Error::display_help_error(self.cmd, message));
- }
- }
- #[allow(deprecated)]
- if !has_subcmd && self.cmd.is_subcommand_required_set() {
- let bn = self
- .cmd
- .get_bin_name()
- .unwrap_or_else(|| self.cmd.get_name());
- return Err(Error::missing_subcommand(
- self.cmd,
- bn.to_string(),
- Usage::new(self.cmd)
- .required(&self.required)
- .create_usage_with_title(&[]),
- ));
- } else if !has_subcmd && self.cmd.is_set(AppSettings::SubcommandRequiredElseHelp) {
- debug!("Validator::new::get_matches_with: SubcommandRequiredElseHelp=true");
- let message = self.cmd.write_help_err(false, Stream::Stderr)?;
- return Err(Error::display_help_error(self.cmd, message));
- }
-
- self.validate_conflicts(matcher, &mut conflicts)?;
- if !(self.cmd.is_subcommand_negates_reqs_set() && has_subcmd) {
- self.validate_required(matcher, &mut conflicts)?;
- }
- self.validate_matched_args(matcher)?;
-
- Ok(())
- }
-
- fn validate_arg_values(&self, arg: &Arg, ma: &MatchedArg) -> ClapResult<()> {
- debug!("Validator::validate_arg_values: arg={:?}", arg.name);
- for val in ma.raw_vals_flatten() {
- if !arg.possible_vals.is_empty() {
- debug!(
- "Validator::validate_arg_values: possible_vals={:?}",
- arg.possible_vals
- );
- let val_str = val.to_string_lossy();
- let ok = arg
- .possible_vals
- .iter()
- .any(|pv| pv.matches(&val_str, arg.is_ignore_case_set()));
- if !ok {
- return Err(Error::invalid_value(
- self.cmd,
- val_str.into_owned(),
- &arg.possible_vals
- .iter()
- .filter(|pv| !pv.is_hide_set())
- .map(PossibleValue::get_name)
- .collect::<Vec<_>>(),
- arg.to_string(),
- ));
- }
- }
- {
- #![allow(deprecated)]
- if arg.is_forbid_empty_values_set() && val.is_empty() {
- debug!("Validator::validate_arg_values: illegal empty val found");
- return Err(Error::empty_value(
- self.cmd,
- &get_possible_values(arg)
- .iter()
- .filter(|pv| !pv.is_hide_set())
- .map(PossibleValue::get_name)
- .collect::<Vec<_>>(),
- arg.to_string(),
- ));
- }
- }
-
- if let Some(ref vtor) = arg.validator {
- debug!("Validator::validate_arg_values: checking validator...");
- let mut vtor = vtor.lock().unwrap();
- if let Err(e) = vtor(&*val.to_string_lossy()) {
- debug!("error");
- return Err(Error::value_validation(
- arg.to_string(),
- val.to_string_lossy().into_owned(),
- e,
- )
- .with_cmd(self.cmd));
- } else {
- debug!("good");
- }
- }
- if let Some(ref vtor) = arg.validator_os {
- debug!("Validator::validate_arg_values: checking validator_os...");
- let mut vtor = vtor.lock().unwrap();
- if let Err(e) = vtor(val) {
- debug!("error");
- return Err(Error::value_validation(
- arg.to_string(),
- val.to_string_lossy().into(),
- e,
- )
- .with_cmd(self.cmd));
- } else {
- debug!("good");
- }
- }
- }
- Ok(())
- }
-
- fn validate_conflicts(
- &mut self,
- matcher: &ArgMatcher,
- conflicts: &mut Conflicts,
- ) -> ClapResult<()> {
- debug!("Validator::validate_conflicts");
-
- self.validate_exclusive(matcher)?;
-
- for arg_id in matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
- .filter(|arg_id| self.cmd.find(arg_id).is_some())
- {
- debug!("Validator::validate_conflicts::iter: id={:?}", arg_id);
- let conflicts = conflicts.gather_conflicts(self.cmd, matcher, arg_id);
- self.build_conflict_err(arg_id, &conflicts, matcher)?;
- }
-
- Ok(())
- }
-
- fn validate_exclusive(&self, matcher: &ArgMatcher) -> ClapResult<()> {
- debug!("Validator::validate_exclusive");
- let args_count = matcher
- .arg_ids()
- .filter(|arg_id| {
- matcher.check_explicit(arg_id, crate::builder::ArgPredicate::IsPresent)
- })
- .count();
- if args_count <= 1 {
- // Nothing present to conflict with
- return Ok(());
- }
-
- matcher
- .arg_ids()
- .filter(|arg_id| {
- matcher.check_explicit(arg_id, crate::builder::ArgPredicate::IsPresent)
- })
- .filter_map(|name| {
- debug!("Validator::validate_exclusive:iter:{:?}", name);
- self.cmd
- .find(name)
- // Find `arg`s which are exclusive but also appear with other args.
- .filter(|&arg| arg.is_exclusive_set() && args_count > 1)
- })
- // Throw an error for the first conflict found.
- .try_for_each(|arg| {
- Err(Error::argument_conflict(
- self.cmd,
- arg.to_string(),
- Vec::new(),
- Usage::new(self.cmd)
- .required(&self.required)
- .create_usage_with_title(&[]),
- ))
- })
- }
-
- fn build_conflict_err(
- &self,
- name: &Id,
- conflict_ids: &[Id],
- matcher: &ArgMatcher,
- ) -> ClapResult<()> {
- if conflict_ids.is_empty() {
- return Ok(());
- }
-
- debug!("Validator::build_conflict_err: name={:?}", name);
- let mut seen = std::collections::HashSet::new();
- let conflicts = conflict_ids
- .iter()
- .flat_map(|c_id| {
- if self.cmd.find_group(c_id).is_some() {
- self.cmd.unroll_args_in_group(c_id)
- } else {
- vec![c_id.clone()]
- }
- })
- .filter_map(|c_id| {
- seen.insert(c_id.clone()).then(|| {
- let c_arg = self.cmd.find(&c_id).expect(INTERNAL_ERROR_MSG);
- c_arg.to_string()
- })
- })
- .collect();
-
- let former_arg = self.cmd.find(name).expect(INTERNAL_ERROR_MSG);
- let usg = self.build_conflict_err_usage(matcher, conflict_ids);
- Err(Error::argument_conflict(
- self.cmd,
- former_arg.to_string(),
- conflicts,
- usg,
- ))
- }
-
- fn build_conflict_err_usage(&self, matcher: &ArgMatcher, conflicting_keys: &[Id]) -> String {
- let used_filtered: Vec<Id> = matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
- .filter(|n| {
- // Filter out the args we don't want to specify.
- self.cmd.find(n).map_or(true, |a| !a.is_hide_set())
- })
- .filter(|key| !conflicting_keys.contains(key))
- .cloned()
- .collect();
- let required: Vec<Id> = used_filtered
- .iter()
- .filter_map(|key| self.cmd.find(key))
- .flat_map(|arg| arg.requires.iter().map(|item| &item.1))
- .filter(|key| !used_filtered.contains(key) && !conflicting_keys.contains(key))
- .chain(used_filtered.iter())
- .cloned()
- .collect();
- Usage::new(self.cmd)
- .required(&self.required)
- .create_usage_with_title(&required)
- }
-
- fn gather_requires(&mut self, matcher: &ArgMatcher) {
- debug!("Validator::gather_requires");
- for name in matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
- {
- debug!("Validator::gather_requires:iter:{:?}", name);
- if let Some(arg) = self.cmd.find(name) {
- let is_relevant = |(val, req_arg): &(ArgPredicate<'_>, Id)| -> Option<Id> {
- let required = matcher.check_explicit(&arg.id, *val);
- required.then(|| req_arg.clone())
- };
-
- for req in self.cmd.unroll_arg_requires(is_relevant, &arg.id) {
- self.required.insert(req);
- }
- } else if let Some(g) = self.cmd.find_group(name) {
- debug!("Validator::gather_requires:iter:{:?}:group", name);
- for r in &g.requires {
- self.required.insert(r.clone());
- }
- }
- }
- }
-
- fn validate_matched_args(&self, matcher: &ArgMatcher) -> ClapResult<()> {
- debug!("Validator::validate_matched_args");
- matcher.iter().try_for_each(|(name, ma)| {
- debug!(
- "Validator::validate_matched_args:iter:{:?}: vals={:#?}",
- name,
- ma.vals_flatten()
- );
- if let Some(arg) = self.cmd.find(name) {
- self.validate_arg_num_vals(arg, ma)?;
- self.validate_arg_values(arg, ma)?;
- self.validate_arg_num_occurs(arg, ma)?;
- }
- Ok(())
- })
- }
-
- fn validate_arg_num_occurs(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> {
- #![allow(deprecated)]
- debug!(
- "Validator::validate_arg_num_occurs: {:?}={}",
- a.name,
- ma.get_occurrences()
- );
- // Occurrence of positional argument equals to number of values rather
- // than number of grouped values.
- if ma.get_occurrences() > 1 && !a.is_multiple_occurrences_set() && !a.is_positional() {
- // Not the first time, and we don't allow multiples
- return Err(Error::unexpected_multiple_usage(
- self.cmd,
- a.to_string(),
- Usage::new(self.cmd)
- .required(&self.required)
- .create_usage_with_title(&[]),
- ));
- }
- if let Some(max_occurs) = a.max_occurs {
- debug!(
- "Validator::validate_arg_num_occurs: max_occurs set...{}",
- max_occurs
- );
- let occurs = ma.get_occurrences() as usize;
- if occurs > max_occurs {
- return Err(Error::too_many_occurrences(
- self.cmd,
- a.to_string(),
- max_occurs,
- occurs,
- Usage::new(self.cmd)
- .required(&self.required)
- .create_usage_with_title(&[]),
- ));
- }
- }
-
- Ok(())
- }
-
- fn validate_arg_num_vals(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> {
- debug!("Validator::validate_arg_num_vals");
- if let Some(num) = a.num_vals {
- let total_num = ma.num_vals();
- debug!("Validator::validate_arg_num_vals: num_vals set...{}", num);
- #[allow(deprecated)]
- let should_err = if a.is_multiple_occurrences_set() {
- total_num % num != 0
- } else {
- num != total_num
- };
- if should_err {
- debug!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues");
- return Err(Error::wrong_number_of_values(
- self.cmd,
- a.to_string(),
- num,
- #[allow(deprecated)]
- if a.is_multiple_occurrences_set() {
- total_num % num
- } else {
- total_num
- },
- Usage::new(self.cmd)
- .required(&self.required)
- .create_usage_with_title(&[]),
- ));
- }
- }
- if let Some(num) = a.max_vals {
- debug!("Validator::validate_arg_num_vals: max_vals set...{}", num);
- if ma.num_vals() > num {
- debug!("Validator::validate_arg_num_vals: Sending error TooManyValues");
- return Err(Error::too_many_values(
- self.cmd,
- ma.raw_vals_flatten()
- .last()
- .expect(INTERNAL_ERROR_MSG)
- .to_str()
- .expect(INVALID_UTF8)
- .to_string(),
- a.to_string(),
- Usage::new(self.cmd)
- .required(&self.required)
- .create_usage_with_title(&[]),
- ));
- }
- }
- let min_vals_zero = if let Some(num) = a.min_vals {
- debug!("Validator::validate_arg_num_vals: min_vals set: {}", num);
- if ma.num_vals() < num && num != 0 {
- debug!("Validator::validate_arg_num_vals: Sending error TooFewValues");
- return Err(Error::too_few_values(
- self.cmd,
- a.to_string(),
- num,
- ma.num_vals(),
- Usage::new(self.cmd)
- .required(&self.required)
- .create_usage_with_title(&[]),
- ));
- }
- num == 0
- } else {
- false
- };
- // Issue 665 (https://github.com/clap-rs/clap/issues/665)
- // Issue 1105 (https://github.com/clap-rs/clap/issues/1105)
- if a.is_takes_value_set() && !min_vals_zero && ma.all_val_groups_empty() {
- return Err(Error::empty_value(
- self.cmd,
- &get_possible_values(a)
- .iter()
- .filter(|pv| !pv.is_hide_set())
- .map(PossibleValue::get_name)
- .collect::<Vec<_>>(),
- a.to_string(),
- ));
- }
- Ok(())
- }
-
- fn validate_required(
- &mut self,
- matcher: &ArgMatcher,
- conflicts: &mut Conflicts,
- ) -> ClapResult<()> {
- debug!("Validator::validate_required: required={:?}", self.required);
- self.gather_requires(matcher);
-
- let is_exclusive_present = matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
- .any(|id| {
- self.cmd
- .find(id)
- .map(|arg| arg.is_exclusive_set())
- .unwrap_or_default()
- });
- debug!(
- "Validator::validate_required: is_exclusive_present={}",
- is_exclusive_present
- );
-
- for arg_or_group in self
- .required
- .iter()
- .filter(|r| !matcher.check_explicit(r, ArgPredicate::IsPresent))
- {
- debug!("Validator::validate_required:iter:aog={:?}", arg_or_group);
- if let Some(arg) = self.cmd.find(arg_or_group) {
- debug!("Validator::validate_required:iter: This is an arg");
- if !is_exclusive_present && !self.is_missing_required_ok(arg, matcher, conflicts) {
- return self.missing_required_error(matcher, vec![]);
- }
- } else if let Some(group) = self.cmd.find_group(arg_or_group) {
- debug!("Validator::validate_required:iter: This is a group");
- if !self
- .cmd
- .unroll_args_in_group(&group.id)
- .iter()
- .any(|a| matcher.check_explicit(a, ArgPredicate::IsPresent))
- {
- return self.missing_required_error(matcher, vec![]);
- }
- }
- }
-
- // Validate the conditionally required args
- for a in self.cmd.get_arguments() {
- for (other, val) in &a.r_ifs {
- if matcher.check_explicit(other, ArgPredicate::Equals(std::ffi::OsStr::new(*val)))
- && !matcher.check_explicit(&a.id, ArgPredicate::IsPresent)
- {
- return self.missing_required_error(matcher, vec![a.id.clone()]);
- }
- }
-
- let match_all = a.r_ifs_all.iter().all(|(other, val)| {
- matcher.check_explicit(other, ArgPredicate::Equals(std::ffi::OsStr::new(*val)))
- });
- if match_all
- && !a.r_ifs_all.is_empty()
- && !matcher.check_explicit(&a.id, ArgPredicate::IsPresent)
- {
- return self.missing_required_error(matcher, vec![a.id.clone()]);
- }
- }
-
- self.validate_required_unless(matcher)?;
-
- Ok(())
- }
-
- fn is_missing_required_ok(
- &self,
- a: &Arg<'help>,
- matcher: &ArgMatcher,
- conflicts: &mut Conflicts,
- ) -> bool {
- debug!("Validator::is_missing_required_ok: {}", a.name);
- let conflicts = conflicts.gather_conflicts(self.cmd, matcher, &a.id);
- !conflicts.is_empty()
- }
-
- fn validate_required_unless(&self, matcher: &ArgMatcher) -> ClapResult<()> {
- debug!("Validator::validate_required_unless");
- let failed_args: Vec<_> = self
- .cmd
- .get_arguments()
- .filter(|&a| {
- (!a.r_unless.is_empty() || !a.r_unless_all.is_empty())
- && !matcher.check_explicit(&a.id, ArgPredicate::IsPresent)
- && self.fails_arg_required_unless(a, matcher)
- })
- .map(|a| a.id.clone())
- .collect();
- if failed_args.is_empty() {
- Ok(())
- } else {
- self.missing_required_error(matcher, failed_args)
- }
- }
-
- // Failing a required unless means, the arg's "unless" wasn't present, and neither were they
- fn fails_arg_required_unless(&self, a: &Arg<'help>, matcher: &ArgMatcher) -> bool {
- debug!("Validator::fails_arg_required_unless: a={:?}", a.name);
- let exists = |id| matcher.check_explicit(id, ArgPredicate::IsPresent);
-
- (a.r_unless_all.is_empty() || !a.r_unless_all.iter().all(exists))
- && !a.r_unless.iter().any(exists)
- }
-
- // `incl`: an arg to include in the error even if not used
- fn missing_required_error(&self, matcher: &ArgMatcher, incl: Vec<Id>) -> ClapResult<()> {
- debug!("Validator::missing_required_error; incl={:?}", incl);
- debug!(
- "Validator::missing_required_error: reqs={:?}",
- self.required
- );
-
- let usg = Usage::new(self.cmd).required(&self.required);
-
- let req_args = usg
- .get_required_usage_from(&incl, Some(matcher), true)
- .into_iter()
- .collect::<Vec<_>>();
-
- debug!(
- "Validator::missing_required_error: req_args={:#?}",
- req_args
- );
-
- let used: Vec<Id> = matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
- .filter(|n| {
- // Filter out the args we don't want to specify.
- self.cmd.find(n).map_or(true, |a| !a.is_hide_set())
- })
- .cloned()
- .chain(incl)
- .collect();
-
- Err(Error::missing_required_argument(
- self.cmd,
- req_args,
- usg.create_usage_with_title(&used),
- ))
- }
-}
-
-#[derive(Default, Clone, Debug)]
-struct Conflicts {
- potential: std::collections::HashMap<Id, Vec<Id>>,
-}
-
-impl Conflicts {
- fn new() -> Self {
- Self::default()
- }
-
- fn gather_conflicts(&mut self, cmd: &Command, matcher: &ArgMatcher, arg_id: &Id) -> Vec<Id> {
- debug!("Conflicts::gather_conflicts: arg={:?}", arg_id);
- let mut conflicts = Vec::new();
- for other_arg_id in matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
- {
- if arg_id == other_arg_id {
- continue;
- }
-
- if self
- .gather_direct_conflicts(cmd, arg_id)
- .contains(other_arg_id)
- {
- conflicts.push(other_arg_id.clone());
- }
- if self
- .gather_direct_conflicts(cmd, other_arg_id)
- .contains(arg_id)
- {
- conflicts.push(other_arg_id.clone());
- }
- }
- debug!("Conflicts::gather_conflicts: conflicts={:?}", conflicts);
- conflicts
- }
-
- fn gather_direct_conflicts(&mut self, cmd: &Command, arg_id: &Id) -> &[Id] {
- self.potential.entry(arg_id.clone()).or_insert_with(|| {
- let conf = if let Some(arg) = cmd.find(arg_id) {
- let mut conf = arg.blacklist.clone();
- for group_id in cmd.groups_for_arg(arg_id) {
- let group = cmd.find_group(&group_id).expect(INTERNAL_ERROR_MSG);
- conf.extend(group.conflicts.iter().cloned());
- if !group.multiple {
- for member_id in &group.args {
- if member_id != arg_id {
- conf.push(member_id.clone());
- }
- }
- }
- }
-
- // Overrides are implicitly conflicts
- conf.extend(arg.overrides.iter().cloned());
-
- conf
- } else if let Some(group) = cmd.find_group(arg_id) {
- group.conflicts.clone()
- } else {
- debug_assert!(false, "id={:?} is unknown", arg_id);
- Vec::new()
- };
- debug!(
- "Conflicts::gather_direct_conflicts id={:?}, conflicts={:?}",
- arg_id, conf
- );
- conf
- })
- }
-}
-
-fn get_possible_values<'help>(a: &Arg<'help>) -> Vec<PossibleValue<'help>> {
- #![allow(deprecated)]
- if !a.is_takes_value_set() {
- vec![]
- } else if let Some(pvs) = a.get_possible_values() {
- // Check old first in case the user explicitly set possible values and the derive inferred
- // a `ValueParser` with some.
- pvs.to_vec()
- } else {
- a.get_value_parser()
- .possible_values()
- .map(|pvs| pvs.collect())
- .unwrap_or_default()
- }
-}