diff options
Diffstat (limited to 'vendor/clap/src/parser')
-rw-r--r-- | vendor/clap/src/parser/arg_matcher.rs | 280 | ||||
-rw-r--r-- | vendor/clap/src/parser/error.rs | 67 | ||||
-rw-r--r-- | vendor/clap/src/parser/features/mod.rs | 1 | ||||
-rw-r--r-- | vendor/clap/src/parser/features/suggestions.rs | 105 | ||||
-rw-r--r-- | vendor/clap/src/parser/matches/any_value.rs | 112 | ||||
-rw-r--r-- | vendor/clap/src/parser/matches/arg_matches.rs | 1896 | ||||
-rw-r--r-- | vendor/clap/src/parser/matches/matched_arg.rs | 240 | ||||
-rw-r--r-- | vendor/clap/src/parser/matches/mod.rs | 17 | ||||
-rw-r--r-- | vendor/clap/src/parser/matches/value_source.rs | 11 | ||||
-rw-r--r-- | vendor/clap/src/parser/mod.rs | 27 | ||||
-rw-r--r-- | vendor/clap/src/parser/parser.rs | 1729 | ||||
-rw-r--r-- | vendor/clap/src/parser/validator.rs | 692 |
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[¤t_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() - } -} |