aboutsummaryrefslogtreecommitdiff
path: root/vendor/clap_builder/src/parser
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
committerValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
commita990de90fe41456a23e58bd087d2f107d321f3a1 (patch)
tree15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/clap_builder/src/parser
parent3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff)
downloadfparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz
fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip
Deleted vendor folder
Diffstat (limited to 'vendor/clap_builder/src/parser')
-rw-r--r--vendor/clap_builder/src/parser/arg_matcher.rs238
-rw-r--r--vendor/clap_builder/src/parser/error.rs63
-rw-r--r--vendor/clap_builder/src/parser/features/mod.rs1
-rw-r--r--vendor/clap_builder/src/parser/features/suggestions.rs167
-rw-r--r--vendor/clap_builder/src/parser/matches/arg_matches.rs2030
-rw-r--r--vendor/clap_builder/src/parser/matches/matched_arg.rs225
-rw-r--r--vendor/clap_builder/src/parser/matches/mod.rs13
-rw-r--r--vendor/clap_builder/src/parser/matches/value_source.rs17
-rw-r--r--vendor/clap_builder/src/parser/mod.rs25
-rw-r--r--vendor/clap_builder/src/parser/parser.rs1622
-rw-r--r--vendor/clap_builder/src/parser/validator.rs561
11 files changed, 0 insertions, 4962 deletions
diff --git a/vendor/clap_builder/src/parser/arg_matcher.rs b/vendor/clap_builder/src/parser/arg_matcher.rs
deleted file mode 100644
index b8d827a..0000000
--- a/vendor/clap_builder/src/parser/arg_matcher.rs
+++ /dev/null
@@ -1,238 +0,0 @@
-// Std
-use std::ffi::OsString;
-use std::mem;
-use std::ops::Deref;
-
-// Internal
-use crate::builder::{Arg, ArgPredicate, Command};
-use crate::parser::Identifier;
-use crate::parser::PendingArg;
-use crate::parser::{ArgMatches, MatchedArg, SubCommand, ValueSource};
-use crate::util::AnyValue;
-use crate::util::FlatMap;
-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.get_id().clone());
- let groups = _cmd.get_groups().map(|g| g.get_id().clone());
- args.chain(groups).collect()
- },
- #[cfg(debug_assertions)]
- valid_subcommands: _cmd
- .get_subcommands()
- .map(|sc| sc.get_name_str().clone())
- .collect(),
- ..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 = FlatMap::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 FlatMap<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) -> bool {
- self.matches.args.remove(arg).is_some()
- }
-
- pub(crate) fn contains(&self, arg: &Id) -> bool {
- self.matches.args.contains_key(arg)
- }
-
- pub(crate) fn arg_ids(&self) -> std::slice::Iter<'_, Id> {
- self.matches.args.keys()
- }
-
- pub(crate) fn args(&self) -> crate::util::flat_map::Iter<'_, Id, MatchedArg> {
- self.matches.args.iter()
- }
-
- pub(crate) fn entry(&mut self, arg: Id) -> crate::util::Entry<Id, MatchedArg> {
- self.matches.args.entry(arg)
- }
-
- 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 check_explicit(&self, arg: &Id, predicate: &ArgPredicate) -> bool {
- self.get(arg)
- .map(|a| a.check_explicit(predicate))
- .unwrap_or_default()
- }
-
- pub(crate) fn start_custom_arg(&mut self, arg: &Arg, source: ValueSource) {
- let id = arg.get_id().clone();
- debug!("ArgMatcher::start_custom_arg: id={id:?}, source={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={id:?}, source={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_external(&mut self, cmd: &crate::Command) {
- let id = Id::from_static_ref(Id::EXTERNAL);
- 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);
- 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_pending = self
- .pending
- .as_ref()
- .and_then(|p| (p.id == *o.get_id()).then_some(p.raw_vals.len()))
- .unwrap_or(0);
- debug!(
- "ArgMatcher::needs_more_vals: o={}, pending={}",
- o.get_id(),
- num_pending
- );
- let expected = o.get_num_args().expect(INTERNAL_ERROR_MSG);
- debug!("ArgMatcher::needs_more_vals: expected={expected}, actual={num_pending}");
- expected.accepts_more(num_pending)
- }
-
- 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>,
- trailing_values: bool,
- ) -> &mut Vec<OsString> {
- let pending = self.pending.get_or_insert_with(|| PendingArg {
- id: id.clone(),
- ident,
- raw_vals: Default::default(),
- trailing_idx: None,
- });
- debug_assert_eq!(pending.id, *id, "{INTERNAL_ERROR_MSG}");
- if ident.is_some() {
- debug_assert_eq!(pending.ident, ident, "{INTERNAL_ERROR_MSG}");
- }
- if trailing_values {
- pending.trailing_idx.get_or_insert(pending.raw_vals.len());
- }
- &mut pending.raw_vals
- }
-
- pub(crate) fn start_trailing(&mut self) {
- if let Some(pending) = &mut self.pending {
- // Allow asserting its started on subsequent calls
- pending.trailing_idx.get_or_insert(pending.raw_vals.len());
- }
- }
-
- 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_builder/src/parser/error.rs b/vendor/clap_builder/src/parser/error.rs
deleted file mode 100644
index 77b0bb0..0000000
--- a/vendor/clap_builder/src/parser/error.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use crate::util::AnyValueId;
-
-/// 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: AnyValueId,
- /// The target type to downcast to
- expected: 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 {
- #[cfg_attr(debug_assertions, track_caller)]
- pub(crate) fn unwrap<T>(id: &str, 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 {expected:?}, need to downcast to {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_builder/src/parser/features/mod.rs b/vendor/clap_builder/src/parser/features/mod.rs
deleted file mode 100644
index bdeb766..0000000
--- a/vendor/clap_builder/src/parser/features/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub(crate) mod suggestions;
diff --git a/vendor/clap_builder/src/parser/features/suggestions.rs b/vendor/clap_builder/src/parser/features/suggestions.rs
deleted file mode 100644
index b8bb7ad..0000000
--- a/vendor/clap_builder/src/parser/features/suggestions.rs
+++ /dev/null
@@ -1,167 +0,0 @@
-#[cfg(feature = "suggestions")]
-use std::cmp::Ordering;
-
-// Internal
-use crate::builder::Command;
-
-/// Find strings from an iterable of `possible_values` similar to a given value `v`
-/// Returns a Vec of all possible values that exceed a similarity threshold
-/// sorted by ascending similarity, most similar comes last
-#[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()
- // GH #4660: using `jaro` because `jaro_winkler` implementation in `strsim-rs` is wrong
- // causing strings with common prefix >=10 to be considered perfectly similar
- .map(|pv| (strsim::jaro(v, pv.as_ref()), pv.as_ref().to_owned()))
- // Confidence of 0.7 so that bar -> baz is suggested
- .filter(|(confidence, _)| *confidence > 0.7)
- .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: &[&std::ffi::OsStr],
- longs: I,
- subcommands: impl IntoIterator<Item = &'a mut Command>,
-) -> 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(false);
-
- 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 = some!(did_you_mean(arg, longs).pop());
- let score = some!(remaining_args.iter().position(|x| subcommand_name == *x));
- Some((score, (candidate, Some(subcommand_name.to_string()))))
- })
- .min_by_key(|(x, _)| *x)
- .map(|(_, suggestion)| suggestion),
- }
-}
-
-#[cfg(all(test, feature = "suggestions"))]
-mod test {
- use super::*;
-
- #[test]
- fn missing_letter() {
- let p_vals = ["test", "possible", "values"];
- assert_eq!(did_you_mean("tst", p_vals.iter()), vec!["test"]);
- }
-
- #[test]
- fn ambiguous() {
- let p_vals = ["test", "temp", "possible", "values"];
- assert_eq!(did_you_mean("te", p_vals.iter()), vec!["test", "temp"]);
- }
-
- #[test]
- fn unrelated() {
- let p_vals = ["test", "possible", "values"];
- assert_eq!(
- did_you_mean("hahaahahah", p_vals.iter()),
- Vec::<String>::new()
- );
- }
-
- #[test]
- fn best_fit() {
- let p_vals = [
- "test",
- "possible",
- "values",
- "alignmentStart",
- "alignmentScore",
- ];
- assert_eq!(
- did_you_mean("alignmentScorr", p_vals.iter()),
- vec!["alignmentStart", "alignmentScore"]
- );
- }
-
- #[test]
- fn best_fit_long_common_prefix_issue_4660() {
- let p_vals = ["alignmentScore", "alignmentStart"];
- assert_eq!(
- did_you_mean("alignmentScorr", p_vals.iter()),
- vec!["alignmentStart", "alignmentScore"]
- );
- }
-
- #[test]
- fn flag_missing_letter() {
- let p_vals = ["test", "possible", "values"];
- assert_eq!(
- did_you_mean_flag("tst", &[], p_vals.iter(), []),
- Some(("test".to_owned(), None))
- );
- }
-
- #[test]
- fn flag_ambiguous() {
- let p_vals = ["test", "temp", "possible", "values"];
- assert_eq!(
- did_you_mean_flag("te", &[], p_vals.iter(), []),
- Some(("temp".to_owned(), None))
- );
- }
-
- #[test]
- fn flag_unrelated() {
- let p_vals = ["test", "possible", "values"];
- assert_eq!(
- did_you_mean_flag("hahaahahah", &[], p_vals.iter(), []),
- None
- );
- }
-
- #[test]
- fn flag_best_fit() {
- let p_vals = [
- "test",
- "possible",
- "values",
- "alignmentStart",
- "alignmentScore",
- ];
- assert_eq!(
- did_you_mean_flag("alignmentScorr", &[], p_vals.iter(), []),
- Some(("alignmentScore".to_owned(), None))
- );
- }
-}
diff --git a/vendor/clap_builder/src/parser/matches/arg_matches.rs b/vendor/clap_builder/src/parser/matches/arg_matches.rs
deleted file mode 100644
index e80c39b..0000000
--- a/vendor/clap_builder/src/parser/matches/arg_matches.rs
+++ /dev/null
@@ -1,2030 +0,0 @@
-// Std
-use std::any::Any;
-use std::ffi::{OsStr, OsString};
-use std::fmt::Debug;
-use std::iter::{Cloned, Flatten, Map};
-use std::slice::Iter;
-
-// Internal
-#[cfg(debug_assertions)]
-use crate::builder::Str;
-use crate::parser::MatchedArg;
-use crate::parser::MatchesError;
-use crate::parser::ValueSource;
-use crate::util::AnyValue;
-use crate::util::AnyValueId;
-use crate::util::FlatMap;
-use crate::util::Id;
-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_builder as clap;
-/// # use clap::{Command, Arg, ArgAction};
-/// # use clap::parser::ValueSource;
-/// let matches = Command::new("MyApp")
-/// .arg(Arg::new("out")
-/// .long("output")
-/// .required(true)
-/// .action(ArgAction::Set)
-/// .default_value("-"))
-/// .arg(Arg::new("cfg")
-/// .short('c')
-/// .action(ArgAction::Set))
-/// .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<Str>,
- pub(crate) args: FlatMap<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::num_args] 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_builder as clap;
- /// # use clap::{Command, Arg, value_parser, ArgAction};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("port")
- /// .value_parser(value_parser!(usize))
- /// .action(ArgAction::Set)
- /// .required(true))
- /// .get_matches_from(vec!["myapp", "2020"]);
- ///
- /// let port: usize = *m
- /// .get_one("port")
- /// .expect("`port`is required");
- /// assert_eq!(port, 2020);
- /// ```
- /// [positional]: crate::Arg::index()
- /// [`default_value`]: crate::Arg::default_value()
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn get_one<T: Any + Clone + Send + Sync + 'static>(&self, id: &str) -> Option<&T> {
- MatchesError::unwrap(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_builder as clap;
- /// # 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
- /// );
- /// ```
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn get_count(&self, id: &str) -> u8 {
- *self.get_one::<u8>(id).unwrap_or_else(|| {
- panic!("arg `{id}`'s `ArgAction` should be `Count` which should provide a default")
- })
- }
-
- /// 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_builder as clap;
- /// # 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"]).unwrap();
- /// assert!(matches.contains_id("flag"));
- /// assert_eq!(
- /// matches.get_flag("flag"),
- /// true
- /// );
- /// ```
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn get_flag(&self, id: &str) -> bool {
- *self
- .get_one::<bool>(id)
- .unwrap_or_else(|| {
- panic!(
- "arg `{id}`'s `ArgAction` should be one of `SetTrue`, `SetFalse` which should provide a default"
- )
- })
- }
-
- /// 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_builder as clap;
- /// # 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')
- /// .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]);
- /// ```
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn get_many<T: Any + Clone + Send + Sync + 'static>(
- &self,
- id: &str,
- ) -> Option<ValuesRef<T>> {
- MatchesError::unwrap(id, self.try_get_many(id))
- }
-
- /// Iterate over the values passed to each occurrence of an option.
- ///
- /// Each item is itself an iterator 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 argument definition and access mismatch (debug builds). To handle this case programmatically, see
- /// [`ArgMatches::try_get_occurrences`].
- ///
- /// # Examples
- /// ```rust
- /// # use clap_builder as clap;
- /// # use clap::{Command,Arg, ArgAction, value_parser};
- /// let m = Command::new("myprog")
- /// .arg(Arg::new("x")
- /// .short('x')
- /// .num_args(2)
- /// .action(ArgAction::Append)
- /// .value_parser(value_parser!(String)))
- /// .get_matches_from(vec![
- /// "myprog", "-x", "a", "b", "-x", "c", "d"]);
- /// let vals: Vec<Vec<&String>> = m.get_occurrences("x").unwrap().map(Iterator::collect).collect();
- /// assert_eq!(vals, [["a", "b"], ["c", "d"]]);
- /// ```
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn get_occurrences<T: Any + Clone + Send + Sync + 'static>(
- &self,
- id: &str,
- ) -> Option<OccurrencesRef<T>> {
- MatchesError::unwrap(id, self.try_get_occurrences(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
- ///
- /// ```rust
- /// # #[cfg(unix)] {
- /// # use clap_builder as clap;
- /// # 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
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn get_raw(&self, id: &str) -> Option<RawValues<'_>> {
- MatchesError::unwrap(id, self.try_get_raw(id))
- }
-
- /// Iterate over the original values for each occurrence of an option.
- ///
- /// Similar to [`ArgMatches::get_occurrences`] but returns raw 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_occurrences`].
- ///
- /// # Examples
- ///
- /// ```rust
- /// # #[cfg(unix)] {
- /// # use clap_builder as clap;
- /// # use clap::{Command, arg, value_parser, ArgAction, Arg};
- /// # use std::ffi::{OsStr,OsString};
- /// # use std::os::unix::ffi::{OsStrExt,OsStringExt};
- /// use std::path::PathBuf;
- ///
- /// let m = Command::new("myprog")
- /// .arg(Arg::new("x")
- /// .short('x')
- /// .num_args(2)
- /// .action(ArgAction::Append)
- /// .value_parser(value_parser!(PathBuf)))
- /// .get_matches_from(vec![OsString::from("myprog"),
- /// OsString::from("-x"),
- /// OsString::from("a"), OsString::from("b"),
- /// OsString::from("-x"),
- /// OsString::from("c"),
- /// // "{0xe9}!"
- /// OsString::from_vec(vec![0xe9, b'!'])]);
- /// let mut itr = m.get_raw_occurrences("x")
- /// .expect("`-x`is required")
- /// .map(Iterator::collect::<Vec<_>>);
- /// assert_eq!(itr.next(), Some(vec![OsStr::new("a"), OsStr::new("b")]));
- /// assert_eq!(itr.next(), Some(vec![OsStr::new("c"), OsStr::from_bytes(&[0xe9, b'!'])]));
- /// assert_eq!(itr.next(), None);
- /// # }
- /// ```
- /// [`Iterator`]: std::iter::Iterator
- /// [`OsStr`]: std::ffi::OsStr
- /// [values]: OsValues
- /// [`String`]: std::string::String
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn get_raw_occurrences(&self, id: &str) -> Option<RawOccurrences<'_>> {
- MatchesError::unwrap(id, self.try_get_raw_occurrences(id))
- }
-
- /// Returns the value of a specific option or positional argument.
- ///
- /// i.e. an argument that [takes an additional value][crate::Arg::num_args] 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_builder as clap;
- /// # use clap::{Command, Arg, value_parser, ArgAction};
- /// let mut m = Command::new("myprog")
- /// .arg(Arg::new("file")
- /// .required(true)
- /// .action(ArgAction::Set))
- /// .get_matches_from(vec![
- /// "myprog", "file.txt",
- /// ]);
- /// let vals: String = m.remove_one("file")
- /// .expect("`file`is required");
- /// assert_eq!(vals, "file.txt");
- /// ```
- /// [positional]: crate::Arg::index()
- /// [`default_value`]: crate::Arg::default_value()
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn remove_one<T: Any + Clone + Send + Sync + 'static>(&mut self, id: &str) -> Option<T> {
- MatchesError::unwrap(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_builder as clap;
- /// # use clap::{Command, Arg, value_parser, ArgAction};
- /// let mut m = Command::new("myprog")
- /// .arg(Arg::new("file")
- /// .action(ArgAction::Append)
- /// .num_args(1..)
- /// .required(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"]);
- /// ```
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn remove_many<T: Any + Clone + Send + Sync + 'static>(
- &mut self,
- id: &str,
- ) -> Option<Values<T>> {
- MatchesError::unwrap(id, self.try_remove_many(id))
- }
-
- /// Return values for each occurrence of an option.
- ///
- /// Each item is itself an iterator 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.
- ///
- /// # Panic
- ///
- /// If the argument definition and access mismatch. To handle this case programmatically, see
- /// [`ArgMatches::try_remove_occurrences`].
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap_builder as clap;
- /// # use clap::{Command, Arg, value_parser, ArgAction};
- /// let mut m = Command::new("myprog")
- /// .arg(Arg::new("x")
- /// .short('x')
- /// .num_args(2)
- /// .action(ArgAction::Append)
- /// .value_parser(value_parser!(String)))
- /// .get_matches_from(vec![
- /// "myprog", "-x", "a", "b", "-x", "c", "d"]);
- /// let vals: Vec<Vec<String>> = m.remove_occurrences("x").unwrap().map(Iterator::collect).collect();
- /// assert_eq!(vals, [["a", "b"], ["c", "d"]]);
- /// ```
- #[cfg_attr(debug_assertions, track_caller)]
- pub fn remove_occurrences<T: Any + Clone + Send + Sync + 'static>(
- &mut self,
- id: &str,
- ) -> Option<Occurrences<T>> {
- MatchesError::unwrap(id, self.try_remove_occurrences(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 not a valid argument or group name (debug builds). To handle this case programmatically, see
- /// [`ArgMatches::try_contains_id`].
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap_builder as clap;
- /// # use clap::{Command, Arg, ArgAction};
- /// let m = Command::new("myprog")
- /// .arg(Arg::new("debug")
- /// .short('d')
- /// .action(ArgAction::SetTrue))
- /// .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 {
- MatchesError::unwrap(id, self.try_contains_id(id))
- }
-
- /// Iterate over [`Arg`][crate::Arg] and [`ArgGroup`][crate::ArgGroup] [`Id`]s via [`ArgMatches::ids`].
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap_builder as clap;
- /// # use clap::{Command, arg, value_parser};
- ///
- /// let m = Command::new("myprog")
- /// .arg(arg!(--color <when>)
- /// .value_parser(["auto", "always", "never"]))
- /// .arg(arg!(--config <path>)
- /// .value_parser(value_parser!(std::path::PathBuf)))
- /// .get_matches_from(["myprog", "--config=config.toml", "--color=auto"]);
- /// assert_eq!(m.ids().len(), 2);
- /// assert_eq!(
- /// m.ids()
- /// .map(|id| id.as_str())
- /// .collect::<Vec<_>>(),
- /// ["config", "color"]
- /// );
- /// ```
- pub fn ids(&self) -> IdsRef<'_> {
- IdsRef {
- iter: self.args.keys(),
- }
- }
-
- /// Check if any args were present on the command line
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap_builder as clap;
- /// # use clap::{Command, Arg, ArgAction};
- /// let mut cmd = Command::new("myapp")
- /// .arg(Arg::new("output")
- /// .action(ArgAction::Set));
- ///
- /// 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()
- }
-
- /// Report where argument value came from
- ///
- /// # Panics
- ///
- /// If `id` is not a valid argument or group id (debug builds).
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap_builder as clap;
- /// # use clap::{Command, Arg, ArgAction};
- /// # use clap::parser::ValueSource;
- /// let m = Command::new("myprog")
- /// .arg(Arg::new("debug")
- /// .short('d')
- /// .action(ArgAction::SetTrue))
- /// .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(&self, id: &str) -> Option<ValueSource> {
- let value = self.get_arg(id);
-
- value.and_then(MatchedArg::source)
- }
-
- /// 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 not a valid argument or group id (debug builds).
- ///
- /// # 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_builder as clap;
- /// # use clap::{Command, Arg, ArgAction};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("flag")
- /// .short('f')
- /// .action(ArgAction::SetTrue))
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .action(ArgAction::Set))
- /// .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_builder as clap;
- /// # use clap::{Command, Arg, ArgAction};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("flag")
- /// .short('f')
- /// .action(ArgAction::SetTrue))
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .action(ArgAction::Set))
- /// .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_builder as clap;
- /// # use clap::{Command, Arg, ArgAction};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("flag")
- /// .short('f')
- /// .action(ArgAction::SetTrue))
- /// .arg(Arg::new("flag2")
- /// .short('F')
- /// .action(ArgAction::SetTrue))
- /// .arg(Arg::new("flag3")
- /// .short('z')
- /// .action(ArgAction::SetTrue))
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .action(ArgAction::Set))
- /// .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_builder as clap;
- /// # use clap::{Command, Arg, ArgAction};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("flag")
- /// .short('f')
- /// .action(ArgAction::SetTrue))
- /// .arg(Arg::new("flag2")
- /// .short('F')
- /// .action(ArgAction::SetTrue))
- /// .arg(Arg::new("flag3")
- /// .short('z')
- /// .action(ArgAction::SetTrue))
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .action(ArgAction::Set))
- /// .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_builder as clap;
- /// # use clap::{Command, Arg};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .value_delimiter(',')
- /// .num_args(1..))
- /// .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(&self, id: &str) -> Option<usize> {
- let arg = some!(self.get_arg(id));
- let i = some!(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 not a valid argument or group id (debug builds).
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap_builder as clap;
- /// # use clap::{Command, Arg};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .value_delimiter(','))
- /// .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_builder as clap;
- /// # use clap::{Command, Arg, ArgAction};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .action(ArgAction::Set)
- /// .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_builder as clap;
- /// # use clap::{Command, Arg, ArgAction};
- /// let m = Command::new("myapp")
- /// .arg(Arg::new("option")
- /// .short('o')
- /// .action(ArgAction::Set)
- /// .num_args(1..))
- /// .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(&self, id: &str) -> Option<Indices<'_>> {
- let arg = some!(self.get_arg(id));
- let i = Indices {
- iter: arg.indices(),
- len: arg.num_vals(),
- };
- Some(i)
- }
-}
-
-/// # 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_builder as clap;
- /// # 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_builder as clap;
- /// # use std::ffi::OsString;
- /// # use std::ffi::OsStr;
- /// # 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<&OsStr> = sub_m.get_many::<OsString>("")
- /// .unwrap().map(|s| s.as_os_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_builder as clap;
- /// # 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_builder as clap;
- /// # use std::ffi::OsString;
- /// # 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<OsString> = 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 not a valid subcommand (debug builds).
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use clap_builder as clap;
- /// # 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")
- /// .action(ArgAction::Set)))
- /// .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_flag("debug"));
- ///
- /// // 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(&self, name: &str) -> Option<&ArgMatches> {
- self.get_subcommand(name).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_builder as clap;
- /// # 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, _name: &str) -> bool {
- #[cfg(debug_assertions)]
- {
- _name.is_empty() || self.valid_subcommands.iter().any(|s| *s == _name)
- }
- #[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 arg = ok!(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 arg = match ok!(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(unwrap_downcast_ref),
- len,
- };
- Ok(Some(values))
- }
-
- /// Non-panicking version of [`ArgMatches::get_occurrences`]
- pub fn try_get_occurrences<T: Any + Clone + Send + Sync + 'static>(
- &self,
- id: &str,
- ) -> Result<Option<OccurrencesRef<T>>, MatchesError> {
- let arg = match ok!(self.try_get_arg_t::<T>(id)) {
- Some(arg) => arg,
- None => return Ok(None),
- };
- let values = arg.vals();
- Ok(Some(OccurrencesRef {
- iter: values.map(|g| OccurrenceValuesRef {
- iter: g.iter().map(unwrap_downcast_ref),
- }),
- }))
- }
-
- /// Non-panicking version of [`ArgMatches::get_raw`]
- pub fn try_get_raw(&self, id: &str) -> Result<Option<RawValues<'_>>, MatchesError> {
- let arg = match ok!(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::get_raw_occurrences`]
- pub fn try_get_raw_occurrences(
- &self,
- id: &str,
- ) -> Result<Option<RawOccurrences<'_>>, MatchesError> {
- let arg = match ok!(self.try_get_arg(id)) {
- Some(arg) => arg,
- None => return Ok(None),
- };
- let values = arg.raw_vals();
- let occurrences = RawOccurrences {
- iter: values.map(|g| RawOccurrenceValues {
- iter: g.iter().map(OsString::as_os_str),
- }),
- };
- Ok(Some(occurrences))
- }
-
- /// 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> {
- match ok!(self.try_remove_arg_t::<T>(id)) {
- Some(values) => Ok(values
- .into_vals_flatten()
- // enforced by `try_get_arg_t`
- .map(unwrap_downcast_into)
- .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<Values<T>>, MatchesError> {
- let arg = match ok!(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 = Values {
- // enforced by `try_get_arg_t`
- iter: values.map(unwrap_downcast_into),
- len,
- };
- Ok(Some(values))
- }
-
- /// Non-panicking version of [`ArgMatches::remove_occurrences`]
- pub fn try_remove_occurrences<T: Any + Clone + Send + Sync + 'static>(
- &mut self,
- id: &str,
- ) -> Result<Option<Occurrences<T>>, MatchesError> {
- let arg = match ok!(self.try_remove_arg_t::<T>(id)) {
- Some(arg) => arg,
- None => return Ok(None),
- };
- let values = arg.into_vals();
- let occurrences = Occurrences {
- iter: values.into_iter().map(|g| OccurrenceValues {
- iter: g.into_iter().map(unwrap_downcast_into),
- }),
- };
- Ok(Some(occurrences))
- }
-
- /// Non-panicking version of [`ArgMatches::contains_id`]
- pub fn try_contains_id(&self, id: &str) -> Result<bool, MatchesError> {
- ok!(self.verify_arg(id));
-
- let presence = self.args.contains_key(id);
- Ok(presence)
- }
-}
-
-// Private methods
-impl ArgMatches {
- #[inline]
- fn try_get_arg(&self, arg: &str) -> Result<Option<&MatchedArg>, MatchesError> {
- ok!(self.verify_arg(arg));
- Ok(self.args.get(arg))
- }
-
- #[inline]
- fn try_get_arg_t<T: Any + Send + Sync + 'static>(
- &self,
- arg: &str,
- ) -> Result<Option<&MatchedArg>, MatchesError> {
- let arg = match ok!(self.try_get_arg(arg)) {
- Some(arg) => arg,
- None => {
- return Ok(None);
- }
- };
- ok!(self.verify_arg_t::<T>(arg));
- Ok(Some(arg))
- }
-
- #[inline]
- fn try_remove_arg_t<T: Any + Send + Sync + 'static>(
- &mut self,
- arg: &str,
- ) -> Result<Option<MatchedArg>, MatchesError> {
- ok!(self.verify_arg(arg));
- let (id, matched) = match self.args.remove_entry(arg) {
- Some((id, matched)) => (id, 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(id, 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: &str) -> Result<(), MatchesError> {
- #[cfg(debug_assertions)]
- {
- if _arg == Id::EXTERNAL || self.valid_args.iter().any(|s| *s == _arg) {
- } 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<'s>(&'s self, arg: &str) -> Option<&'s MatchedArg> {
- #[cfg(debug_assertions)]
- {
- if arg == Id::EXTERNAL || self.valid_args.iter().any(|s| *s == arg) {
- } else {
- panic!(
- "`{arg:?}` 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."
- );
- }
- }
-
- self.args.get(arg)
- }
-
- #[inline]
- #[cfg_attr(debug_assertions, track_caller)]
- fn get_subcommand(&self, name: &str) -> Option<&SubCommand> {
- #[cfg(debug_assertions)]
- {
- if name.is_empty() || self.valid_subcommands.iter().any(|s| *s == name) {
- } else {
- panic!("`{name}` is not a name of a subcommand.");
- }
- }
-
- if let Some(ref sc) = self.subcommand {
- if sc.name == name {
- return Some(sc);
- }
- }
-
- None
- }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub(crate) struct SubCommand {
- pub(crate) name: String,
- pub(crate) matches: ArgMatches,
-}
-
-/// Iterate over [`Arg`][crate::Arg] and [`ArgGroup`][crate::ArgGroup] [`Id`]s via [`ArgMatches::ids`].
-///
-/// # Examples
-///
-/// ```rust
-/// # use clap_builder as clap;
-/// # use clap::{Command, arg, value_parser};
-///
-/// let m = Command::new("myprog")
-/// .arg(arg!(--color <when>)
-/// .value_parser(["auto", "always", "never"]))
-/// .arg(arg!(--config <path>)
-/// .value_parser(value_parser!(std::path::PathBuf)))
-/// .get_matches_from(["myprog", "--config=config.toml", "--color=auto"]);
-/// assert_eq!(
-/// m.ids()
-/// .map(|id| id.as_str())
-/// .collect::<Vec<_>>(),
-/// ["config", "color"]
-/// );
-/// ```
-#[derive(Clone, Debug)]
-pub struct IdsRef<'a> {
- iter: std::slice::Iter<'a, Id>,
-}
-
-impl<'a> Iterator for IdsRef<'a> {
- type Item = &'a Id;
-
- fn next(&mut self) -> Option<&'a Id> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl<'a> DoubleEndedIterator for IdsRef<'a> {
- fn next_back(&mut self) -> Option<&'a Id> {
- self.iter.next_back()
- }
-}
-
-impl<'a> ExactSizeIterator for IdsRef<'a> {}
-
-/// Iterate over multiple values for an argument via [`ArgMatches::remove_many`].
-///
-/// # Examples
-///
-/// ```rust
-/// # use clap_builder as clap;
-/// # use clap::{Command, Arg, ArgAction};
-/// let mut m = Command::new("myapp")
-/// .arg(Arg::new("output")
-/// .short('o')
-/// .action(ArgAction::Append))
-/// .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 Values<T> {
- #[allow(clippy::type_complexity)]
- iter: Map<Flatten<std::vec::IntoIter<Vec<AnyValue>>>, fn(AnyValue) -> T>,
- len: usize,
-}
-
-impl<T> Iterator for Values<T> {
- type Item = T;
-
- fn next(&mut self) -> Option<Self::Item> {
- if let Some(next) = self.iter.next() {
- self.len -= 1;
- Some(next)
- } else {
- None
- }
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.len, Some(self.len))
- }
-}
-
-impl<T> DoubleEndedIterator for Values<T> {
- fn next_back(&mut self) -> Option<Self::Item> {
- if let Some(next) = self.iter.next_back() {
- self.len -= 1;
- Some(next)
- } else {
- None
- }
- }
-}
-
-impl<T> ExactSizeIterator for Values<T> {}
-
-/// Creates an empty iterator.
-impl<T> Default for Values<T> {
- fn default() -> Self {
- let empty: Vec<Vec<AnyValue>> = Default::default();
- Values {
- iter: empty.into_iter().flatten().map(|_| unreachable!()),
- len: 0,
- }
- }
-}
-
-/// Iterate over multiple values for an argument via [`ArgMatches::get_many`].
-///
-/// # Examples
-///
-/// ```rust
-/// # use clap_builder as clap;
-/// # use clap::{Command, Arg, ArgAction};
-/// let m = Command::new("myapp")
-/// .arg(Arg::new("output")
-/// .short('o')
-/// .action(ArgAction::Append))
-/// .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> {
- if let Some(next) = self.iter.next() {
- self.len -= 1;
- Some(next)
- } else {
- None
- }
- }
- 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> {
- if let Some(next) = self.iter.next_back() {
- self.len -= 1;
- Some(next)
- } else {
- None
- }
- }
-}
-
-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
-///
-/// ```rust
-/// # #[cfg(unix)] {
-/// # use clap_builder as clap;
-/// # 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> {
- if let Some(next) = self.iter.next() {
- self.len -= 1;
- Some(next)
- } else {
- None
- }
- }
- 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> {
- if let Some(next) = self.iter.next_back() {
- self.len -= 1;
- Some(next)
- } else {
- None
- }
- }
-}
-
-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
-
-#[derive(Clone, Debug)]
-#[deprecated(since = "4.1.0", note = "Use Occurrences instead")]
-pub struct GroupedValues<'a> {
- #[allow(clippy::type_complexity)]
- iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> Vec<&str>>,
- len: usize,
-}
-
-#[allow(deprecated)]
-impl<'a> Iterator for GroupedValues<'a> {
- type Item = Vec<&'a str>;
-
- fn next(&mut self) -> Option<Self::Item> {
- if let Some(next) = self.iter.next() {
- self.len -= 1;
- Some(next)
- } else {
- None
- }
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.len, Some(self.len))
- }
-}
-
-#[allow(deprecated)]
-impl<'a> DoubleEndedIterator for GroupedValues<'a> {
- fn next_back(&mut self) -> Option<Self::Item> {
- if let Some(next) = self.iter.next_back() {
- self.len -= 1;
- Some(next)
- } else {
- None
- }
- }
-}
-
-#[allow(deprecated)]
-impl<'a> ExactSizeIterator for GroupedValues<'a> {}
-
-/// Creates an empty iterator. Used for `unwrap_or_default()`.
-#[allow(deprecated)]
-impl<'a> Default for GroupedValues<'a> {
- fn default() -> Self {
- static EMPTY: [Vec<AnyValue>; 0] = [];
- GroupedValues {
- iter: EMPTY[..].iter().map(|_| unreachable!()),
- len: 0,
- }
- }
-}
-
-#[derive(Clone, Debug)]
-pub struct Occurrences<T> {
- #[allow(clippy::type_complexity)]
- iter: Map<std::vec::IntoIter<Vec<AnyValue>>, fn(Vec<AnyValue>) -> OccurrenceValues<T>>,
-}
-
-impl<T> Iterator for Occurrences<T> {
- type Item = OccurrenceValues<T>;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl<T> DoubleEndedIterator for Occurrences<T> {
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-}
-
-impl<T> ExactSizeIterator for Occurrences<T> {}
-
-impl<T> Default for Occurrences<T> {
- fn default() -> Self {
- let empty: Vec<Vec<AnyValue>> = Default::default();
- Occurrences {
- iter: empty.into_iter().map(|_| unreachable!()),
- }
- }
-}
-
-#[derive(Clone, Debug)]
-pub struct OccurrenceValues<T> {
- #[allow(clippy::type_complexity)]
- iter: Map<std::vec::IntoIter<AnyValue>, fn(AnyValue) -> T>,
-}
-
-impl<T> Iterator for OccurrenceValues<T> {
- type Item = T;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl<T> DoubleEndedIterator for OccurrenceValues<T> {
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-}
-
-impl<T> ExactSizeIterator for OccurrenceValues<T> {}
-
-#[derive(Clone, Debug)]
-pub struct OccurrencesRef<'a, T> {
- #[allow(clippy::type_complexity)]
- iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> OccurrenceValuesRef<'_, T>>,
-}
-
-impl<'a, T> Iterator for OccurrencesRef<'a, T>
-where
- Self: 'a,
-{
- type Item = OccurrenceValuesRef<'a, T>;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl<'a, T> DoubleEndedIterator for OccurrencesRef<'a, T>
-where
- Self: 'a,
-{
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-}
-
-impl<'a, T> ExactSizeIterator for OccurrencesRef<'a, T> where Self: 'a {}
-impl<'a, T> Default for OccurrencesRef<'a, T> {
- fn default() -> Self {
- static EMPTY: [Vec<AnyValue>; 0] = [];
- OccurrencesRef {
- iter: EMPTY[..].iter().map(|_| unreachable!()),
- }
- }
-}
-
-#[derive(Clone, Debug)]
-pub struct OccurrenceValuesRef<'a, T> {
- #[allow(clippy::type_complexity)]
- iter: Map<Iter<'a, AnyValue>, fn(&AnyValue) -> &T>,
-}
-
-impl<'a, T> Iterator for OccurrenceValuesRef<'a, T>
-where
- Self: 'a,
-{
- type Item = &'a T;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl<'a, T> DoubleEndedIterator for OccurrenceValuesRef<'a, T>
-where
- Self: 'a,
-{
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-}
-
-impl<'a, T> ExactSizeIterator for OccurrenceValuesRef<'a, T> where Self: 'a {}
-
-#[derive(Clone, Debug)]
-pub struct RawOccurrences<'a> {
- #[allow(clippy::type_complexity)]
- iter: Map<Iter<'a, Vec<OsString>>, fn(&Vec<OsString>) -> RawOccurrenceValues<'_>>,
-}
-
-impl<'a> Iterator for RawOccurrences<'a> {
- type Item = RawOccurrenceValues<'a>;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl<'a> DoubleEndedIterator for RawOccurrences<'a> {
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-}
-
-impl<'a> ExactSizeIterator for RawOccurrences<'a> {}
-
-impl<'a> Default for RawOccurrences<'a> {
- fn default() -> Self {
- static EMPTY: [Vec<OsString>; 0] = [];
- RawOccurrences {
- iter: EMPTY[..].iter().map(|_| unreachable!()),
- }
- }
-}
-
-#[derive(Clone, Debug)]
-pub struct RawOccurrenceValues<'a> {
- #[allow(clippy::type_complexity)]
- iter: Map<Iter<'a, OsString>, fn(&OsString) -> &OsStr>,
-}
-
-impl<'a> Iterator for RawOccurrenceValues<'a>
-where
- Self: 'a,
-{
- type Item = &'a OsStr;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.iter.next()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl<'a> DoubleEndedIterator for RawOccurrenceValues<'a>
-where
- Self: 'a,
-{
- fn next_back(&mut self) -> Option<Self::Item> {
- self.iter.next_back()
- }
-}
-
-impl<'a> ExactSizeIterator for RawOccurrenceValues<'a> {}
-
-/// Iterate over indices for where an argument appeared when parsing, via [`ArgMatches::indices_of`]
-///
-/// # Examples
-///
-/// ```rust
-/// # use clap_builder as clap;
-/// # use clap::{Command, Arg, ArgAction};
-/// let m = Command::new("myapp")
-/// .arg(Arg::new("output")
-/// .short('o')
-/// .num_args(1..)
-/// .action(ArgAction::Set))
-/// .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> {
- if let Some(next) = self.iter.next() {
- self.len -= 1;
- Some(next)
- } else {
- None
- }
- }
- 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> {
- if let Some(next) = self.iter.next_back() {
- self.len -= 1;
- Some(next)
- } else {
- None
- }
- }
-}
-
-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,
- }
- }
-}
-
-#[track_caller]
-fn unwrap_downcast_ref<T: Any + Clone + Send + Sync + 'static>(value: &AnyValue) -> &T {
- value.downcast_ref().expect(INTERNAL_ERROR_MSG)
-}
-
-#[track_caller]
-fn unwrap_downcast_into<T: Any + Clone + Send + Sync + 'static>(value: AnyValue) -> T {
- value.downcast_into().expect(INTERNAL_ERROR_MSG)
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- use crate::ArgAction;
-
- #[test]
- fn check_auto_traits() {
- static_assertions::assert_impl_all!(ArgMatches: Send, Sync, Unpin);
- }
-
- #[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")
- .action(ArgAction::Set)
- .num_args(1..)
- .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")
- .action(ArgAction::Set)
- .num_args(1..)
- .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")
- .action(ArgAction::Set)
- .num_args(1..)
- .required(true),
- )
- .try_get_matches_from(["test", "one"])
- .unwrap()
- .indices_of("POTATO")
- .expect("present")
- .len();
- assert_eq!(l, 1);
- }
-
- #[test]
- fn rev_iter() {
- let mut matches = crate::Command::new("myprog")
- .arg(crate::Arg::new("a").short('a').action(ArgAction::Append))
- .arg(crate::Arg::new("b").short('b').action(ArgAction::Append))
- .try_get_matches_from(vec!["myprog", "-a1", "-b1", "-b3"])
- .unwrap();
-
- let a_index = matches
- .indices_of("a")
- .expect("missing aopt indices")
- .collect::<Vec<_>>();
- dbg!(&a_index);
- let a_value = matches
- .remove_many::<String>("a")
- .expect("missing aopt values");
- dbg!(&a_value);
- let a = a_index.into_iter().zip(a_value).rev().collect::<Vec<_>>();
- dbg!(a);
-
- let b_index = matches
- .indices_of("b")
- .expect("missing aopt indices")
- .collect::<Vec<_>>();
- dbg!(&b_index);
- let b_value = matches
- .remove_many::<String>("b")
- .expect("missing aopt values");
- dbg!(&b_value);
- let b = b_index.into_iter().zip(b_value).rev().collect::<Vec<_>>();
- dbg!(b);
- }
-}
diff --git a/vendor/clap_builder/src/parser/matches/matched_arg.rs b/vendor/clap_builder/src/parser/matches/matched_arg.rs
deleted file mode 100644
index 24df8b1..0000000
--- a/vendor/clap_builder/src/parser/matches/matched_arg.rs
+++ /dev/null
@@ -1,225 +0,0 @@
-// Std
-use std::{
- ffi::{OsStr, OsString},
- iter::{Cloned, Flatten},
- slice::Iter,
-};
-
-use crate::builder::ArgPredicate;
-use crate::parser::ValueSource;
-use crate::util::eq_ignore_case;
-use crate::util::AnyValue;
-use crate::util::AnyValueId;
-use crate::INTERNAL_ERROR_MSG;
-
-#[derive(Debug, Clone)]
-pub(crate) struct MatchedArg {
- 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 {
- 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 {
- 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 {
- 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,
- }
- }
-
- 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)
- }
-
- pub(crate) fn vals(&self) -> Iter<Vec<AnyValue>> {
- self.vals.iter()
- }
-
- pub(crate) fn into_vals(self) -> Vec<Vec<AnyValue>> {
- self.vals
- }
-
- 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(&self) -> Iter<Vec<OsString>> {
- self.raw_vals.iter()
- }
-
- 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.map(|s| !s.is_explicit()).unwrap_or(false) {
- 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 {
- 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 {
- source: other_source,
- indices: other_indices,
- type_id: other_type_id,
- vals: _,
- raw_vals: other_raw_vals,
- ignore_case: other_ignore_case,
- } = other;
- 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_builder/src/parser/matches/mod.rs b/vendor/clap_builder/src/parser/matches/mod.rs
deleted file mode 100644
index eb86585..0000000
--- a/vendor/clap_builder/src/parser/matches/mod.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-mod arg_matches;
-mod matched_arg;
-mod value_source;
-
-pub use arg_matches::IdsRef;
-pub use arg_matches::RawValues;
-pub use arg_matches::Values;
-pub use arg_matches::ValuesRef;
-pub use arg_matches::{ArgMatches, Indices};
-pub use value_source::ValueSource;
-
-pub(crate) use arg_matches::SubCommand;
-pub(crate) use matched_arg::MatchedArg;
diff --git a/vendor/clap_builder/src/parser/matches/value_source.rs b/vendor/clap_builder/src/parser/matches/value_source.rs
deleted file mode 100644
index db45d9c..0000000
--- a/vendor/clap_builder/src/parser/matches/value_source.rs
+++ /dev/null
@@ -1,17 +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,
-}
-
-impl ValueSource {
- pub(crate) fn is_explicit(self) -> bool {
- self != Self::DefaultValue
- }
-}
diff --git a/vendor/clap_builder/src/parser/mod.rs b/vendor/clap_builder/src/parser/mod.rs
deleted file mode 100644
index 3e73544..0000000
--- a/vendor/clap_builder/src/parser/mod.rs
+++ /dev/null
@@ -1,25 +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::{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::get_possible_values_cli;
-pub(crate) use self::validator::Validator;
-
-pub use self::matches::IdsRef;
-pub use self::matches::RawValues;
-pub use self::matches::Values;
-pub use self::matches::ValuesRef;
-pub use self::matches::{ArgMatches, Indices, ValueSource};
-pub use error::MatchesError;
diff --git a/vendor/clap_builder/src/parser/parser.rs b/vendor/clap_builder/src/parser/parser.rs
deleted file mode 100644
index 93616d6..0000000
--- a/vendor/clap_builder/src/parser/parser.rs
+++ /dev/null
@@ -1,1622 +0,0 @@
-// Std
-use std::{
- cell::Cell,
- ffi::{OsStr, OsString},
-};
-
-use clap_lex::OsStrExt as _;
-
-// Internal
-use crate::builder::{Arg, Command};
-use crate::error::Error as ClapError;
-use crate::error::Result as ClapResult;
-use crate::mkeymap::KeyType;
-use crate::output::Usage;
-use crate::parser::features::suggestions;
-use crate::parser::{ArgMatcher, SubCommand};
-use crate::parser::{Validator, ValueSource};
-use crate::util::AnyValue;
-use crate::util::Id;
-use crate::ArgAction;
-use crate::INTERNAL_ERROR_MSG;
-
-pub(crate) struct Parser<'cmd> {
- cmd: &'cmd mut Command,
- 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<'cmd> Parser<'cmd> {
- pub(crate) fn new(cmd: &'cmd mut Command) -> Self {
- Parser {
- cmd,
- cur_idx: Cell::new(0),
- flag_subcmd_at: None,
- flag_subcmd_skip: 0,
- }
- }
-}
-
-// Parsing Methods
-impl<'cmd> Parser<'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) {
- debug!(
- "Parser::get_matches_with: Begin parsing '{:?}'",
- arg_os.to_value_os(),
- );
-
- // 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 {
- if sc_name == "help" && !self.cmd.is_disable_help_subcommand_set() {
- ok!(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;
- matcher.start_trailing();
- continue;
- }
- } else if let Some((long_arg, long_value)) = arg_os.to_long() {
- let parse_result = ok!(self.parse_long_arg(
- matcher,
- long_arg,
- long_value,
- &parse_state,
- pos_counter,
- &mut valid_arg_found,
- ));
- 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).collect();
- return Err(self.did_you_mean_error(
- &arg,
- matcher,
- &remaining_args,
- trailing_values,
- ));
- }
- 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_with_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 = ok!(self.parse_short_arg(
- matcher,
- short_arg,
- &parse_state,
- pos_counter,
- &mut valid_arg_found,
- ));
- // 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);
- // We already know it looks like a flag
- let suggested_trailing_arg =
- !trailing_values && self.cmd.has_positionals();
- return Err(ClapError::unknown_argument(
- self.cmd,
- arg,
- None,
- suggested_trailing_arg,
- 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 = &self.cmd[id];
- let parse_result = if let Some(parse_result) =
- self.check_terminator(arg, arg_os.to_value_os())
- {
- parse_result
- } else {
- let trailing_values = false;
- let arg_values = matcher.pending_values_mut(id, None, trailing_values);
- arg_values.push(arg_os.to_value_os().to_owned());
- if matcher.needs_more_vals(arg) {
- ParseResult::Opt(arg.get_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.get_index().unwrap_or(0))
- })
- && self
- .cmd
- .get_positionals()
- .last()
- .map(|p_name| !p_name.is_last_set())
- .unwrap_or_default();
-
- let is_terminated = self
- .cmd
- .get_keymap()
- .get(&pos_counter)
- .map(|a| a.get_value_terminator().is_some())
- .unwrap_or_default();
-
- 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) && !is_terminated {
- let skip_current = if let Some(n) = raw_args.peek(&args_cursor) {
- if let Some(arg) = self
- .cmd
- .get_positionals()
- .find(|a| a.get_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);
- // Its already considered a positional, we don't need to suggest turning it
- // into one
- let suggested_trailing_arg = false;
- return Err(ClapError::unknown_argument(
- self.cmd,
- arg_os.display().to_string(),
- None,
- suggested_trailing_arg,
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
-
- if arg.is_trailing_var_arg_set() {
- trailing_values = true;
- }
-
- if matcher.pending_arg_id() != Some(arg.get_id()) || !arg.is_multiple_values_set() {
- ok!(self.resolve_pending(matcher));
- }
- parse_state =
- if let Some(parse_result) = self.check_terminator(arg, arg_os.to_value_os()) {
- debug_assert_eq!(parse_result, ParseResult::ValuesDone);
- pos_counter += 1;
- ParseState::ValuesDone
- } else {
- let arg_values = matcher.pending_values_mut(
- arg.get_id(),
- Some(Identifier::Index),
- trailing_values,
- );
- arg_values.push(arg_os.to_value_os().to_owned());
-
- // Only increment the positional counter if it doesn't allow multiples
- if !arg.is_multiple() {
- pos_counter += 1;
- ParseState::ValuesDone
- } else {
- ParseState::Pos(arg.get_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_owned(),
- 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);
- sc_m.start_occurrence_of_external(self.cmd);
-
- for raw_val in raw_args.remaining(&mut args_cursor) {
- let val = ok!(external_parser.parse_ref(
- self.cmd,
- None,
- raw_val,
- ValueSource::CommandLine
- ));
- let external_id = Id::from_static_ref(Id::EXTERNAL);
- sc_m.add_val_to(&external_id, val, raw_val.to_os_string());
- }
-
- matcher.subcommand(SubCommand {
- name: sc_name,
- matches: sc_m.into_inner(),
- });
-
- ok!(self.resolve_pending(matcher));
- #[cfg(feature = "env")]
- ok!(self.add_env(matcher));
- ok!(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();
- ok!(self.parse_subcommand(&sc_name, matcher, raw_args, args_cursor, keep_state));
- }
-
- ok!(self.resolve_pending(matcher));
- #[cfg(feature = "env")]
- ok!(self.add_env(matcher));
- ok!(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 suggested_trailing_arg = !trailing_values
- && self.cmd.has_positionals()
- && (arg_os.is_long() || arg_os.is_short());
-
- if !(self.cmd.is_args_conflicts_with_subcommands_set() && valid_arg_found) {
- 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() {
- return ClapError::invalid_subcommand(
- self.cmd,
- arg_os.display().to_string(),
- candidates,
- self.cmd.get_bin_name_fallback().to_owned(),
- suggested_trailing_arg,
- Usage::new(self.cmd).create_usage_with_title(&[]),
- );
- }
-
- // If the argument must be a subcommand.
- if self.cmd.has_subcommands()
- && (!self.cmd.has_positionals() || self.cmd.is_infer_subcommands_set())
- {
- 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,
- suggested_trailing_arg,
- 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, &OsStr>,
- valid_arg_found: bool,
- ) -> Option<&str> {
- debug!("Parser::possible_subcommand: arg={arg:?}");
- let arg = some!(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 mut iter = self.cmd.get_subcommands().filter_map(|s| {
- if s.get_name().starts_with(arg) {
- return Some(s.get_name());
- }
-
- // Use find here instead of chaining the iterator because we want to accept
- // conflicts in aliases.
- s.get_all_aliases().find(|s| s.starts_with(arg))
- });
-
- if let name @ Some(_) = iter.next() {
- if iter.next().is_none() {
- return name;
- }
- }
- }
- // Don't use an else here because we want inference to support exact matching even if
- // there are conflicts.
- 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 mut iter = self.cmd.get_subcommands().filter_map(|sc| {
- sc.get_long_flag().and_then(|long| {
- if long.starts_with(arg) {
- Some(sc.get_name())
- } else {
- sc.get_all_long_flag_aliases().find_map(|alias| {
- if alias.starts_with(arg) {
- Some(sc.get_name())
- } else {
- None
- }
- })
- }
- })
- });
-
- if let name @ Some(_) = iter.next() {
- if iter.next().is_none() {
- return name;
- }
- }
- }
- 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))
- }
-
- 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.get_id()
- );
-
- if self.cmd[current_positional.get_id()].is_allow_hyphen_values_set()
- || (self.cmd[current_positional.get_id()].is_allow_negative_numbers_set()
- && next.is_negative_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 {
- 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, &OsStr>,
- long_value: Option<&OsStr>,
- parse_state: &ParseState,
- pos_counter: usize,
- valid_arg_found: &mut bool,
- ) -> ClapResult<ParseResult> {
- // maybe here lifetime should be 'a
- debug!("Parser::parse_long_arg");
-
- #[allow(clippy::blocks_in_if_conditions)]
- if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if
- self.cmd[opt].is_allow_hyphen_values_set())
- {
- debug!("Parser::parse_long_arg: prior arg accepts hyphenated values",);
- 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_os) => {
- return Ok(ParseResult::NoMatchingArg {
- arg: long_arg_os.to_string_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}'");
- Some((long_arg, arg))
- } else if self.cmd.is_infer_long_args_set() {
- let mut iter = self.cmd.get_arguments().filter_map(|a| {
- if let Some(long) = a.get_long() {
- if long.starts_with(long_arg) {
- return Some((long, a));
- }
- }
- a.aliases
- .iter()
- .find_map(|(alias, _)| alias.starts_with(long_arg).then(|| (alias.as_str(), a)))
- });
-
- iter.next().filter(|_| iter.next().is_none())
- } 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, has_eq)
- } else if let Some(rest) = long_value {
- let required = self.cmd.required_graph();
- debug!("Parser::parse_long_arg({long_arg:?}): Got invalid literal `{rest:?}`");
- let mut 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(|a| !(a.is_hide_set() || required.contains(a.get_id())))
- .unwrap_or(true)
- })
- .cloned()
- .collect();
- used.push(arg.get_id().clone());
-
- Ok(ParseResult::UnneededAttachedValue {
- rest: rest.to_string_lossy().into_owned(),
- used,
- arg: arg.to_string(),
- })
- } else {
- debug!("Parser::parse_long_arg({long_arg:?}): Presence validated");
- let trailing_idx = None;
- self.react(
- Some(ident),
- ValueSource::CommandLine,
- arg,
- vec![],
- trailing_idx,
- 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
- .get_keymap()
- .get(&pos_counter)
- .map(|arg| arg.is_allow_hyphen_values_set() && !arg.is_last_set())
- .unwrap_or_default()
- {
- debug!("Parser::parse_long_args: positional at {pos_counter} allows hyphens");
- 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,
- ) -> ClapResult<ParseResult> {
- debug!("Parser::parse_short_arg: short_arg={short_arg:?}");
-
- #[allow(clippy::blocks_in_if_conditions)]
- if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt)
- if self.cmd[opt].is_allow_hyphen_values_set() || (self.cmd[opt].is_allow_negative_numbers_set() && short_arg.is_negative_number()))
- {
- debug!("Parser::parse_short_args: prior arg accepts hyphenated values",);
- return Ok(ParseResult::MaybeHyphenValue);
- } else if self
- .cmd
- .get_keymap()
- .get(&pos_counter)
- .map(|arg| arg.is_allow_negative_numbers_set())
- .unwrap_or_default()
- && short_arg.is_negative_number()
- {
- debug!("Parser::parse_short_arg: negative number");
- return Ok(ParseResult::MaybeHyphenValue);
- } else if self
- .cmd
- .get_keymap()
- .get(&pos_counter)
- .map(|arg| arg.is_allow_hyphen_values_set() && !arg.is_last_set())
- .unwrap_or_default()
- && short_arg
- .clone()
- .any(|c| !c.map(|c| self.cmd.contains_short(c)).unwrap_or_default())
- {
- debug!("Parser::parse_short_args: positional at {pos_counter} allows hyphens");
- 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_string_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:{c}: Found valid opt or flag");
- *valid_arg_found = true;
- if !arg.is_takes_value_set() {
- let arg_values = Vec::new();
- let trailing_idx = None;
- ret = ok!(self.react(
- Some(ident),
- ValueSource::CommandLine,
- arg,
- arg_values,
- trailing_idx,
- 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:{c}: val={val:?}, short_arg={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 ok!(self.parse_opt_value(ident, val, arg, matcher, 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:{c}: subcommand={sc_name}");
- // Make sure indices get updated before reading `self.cur_idx`
- ok!(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<&OsStr>,
- arg: &Arg,
- matcher: &mut ArgMatcher,
- has_eq: bool,
- ) -> ClapResult<ParseResult> {
- debug!(
- "Parser::parse_opt_value; arg={}, val={:?}, has_eq={:?}",
- arg.get_id(),
- 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.get_min_vals() == 0 {
- debug!("Requires equals, but min_vals == 0");
- let arg_values = Vec::new();
- let trailing_idx = None;
- let react_result = ok!(self.react(
- Some(ident),
- ValueSource::CommandLine,
- arg,
- arg_values,
- trailing_idx,
- 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 arg_values = vec![v.to_owned()];
- let trailing_idx = None;
- let react_result = ok!(self.react(
- Some(ident),
- ValueSource::CommandLine,
- arg,
- arg_values,
- trailing_idx,
- matcher,
- ));
- debug_assert_eq!(react_result, ParseResult::ValuesDone);
- // Attached are always done
- Ok(ParseResult::ValuesDone)
- } else {
- debug!("Parser::parse_opt_value: More arg vals required...");
- ok!(self.resolve_pending(matcher));
- let trailing_values = false;
- matcher.pending_values_mut(arg.get_id(), Some(ident), trailing_values);
- Ok(ParseResult::Opt(arg.get_id().clone()))
- }
- }
-
- fn check_terminator(&self, arg: &Arg, val: &OsStr) -> Option<ParseResult> {
- if Some(val) == arg.terminator.as_ref().map(|s| OsStr::new(s.as_str())) {
- debug!("Parser::check_terminator: terminator={:?}", arg.terminator);
- Some(ParseResult::ValuesDone)
- } else {
- None
- }
- }
-
- fn push_arg_values(
- &self,
- arg: &Arg,
- raw_vals: Vec<OsString>,
- source: ValueSource,
- 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 = ok!(value_parser.parse_ref(self.cmd, Some(arg), &raw_val, source));
-
- matcher.add_val_to(arg.get_id(), val, raw_val);
- matcher.add_index_to(arg.get_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 _ = ok!(self.react(
- pending.ident,
- ValueSource::CommandLine,
- arg,
- pending.raw_vals,
- pending.trailing_idx,
- matcher,
- ));
-
- Ok(())
- }
-
- fn react(
- &self,
- ident: Option<Identifier>,
- source: ValueSource,
- arg: &Arg,
- mut raw_vals: Vec<OsString>,
- mut trailing_idx: Option<usize>,
- matcher: &mut ArgMatcher,
- ) -> ClapResult<ParseResult> {
- ok!(self.resolve_pending(matcher));
-
- debug!(
- "Parser::react action={:?}, identifier={:?}, source={:?}",
- arg.get_action(),
- ident,
- source
- );
-
- // Process before `default_missing_values` to avoid it counting as values from the command
- // line
- if source == ValueSource::CommandLine {
- ok!(self.verify_num_args(arg, &raw_vals));
- }
-
- if raw_vals.is_empty() {
- // We assume this case is valid: require equals, but min_vals == 0.
- if !arg.default_missing_vals.is_empty() {
- debug!("Parser::react: has default_missing_vals");
- trailing_idx = None;
- raw_vals.extend(
- arg.default_missing_vals
- .iter()
- .map(|s| s.as_os_str().to_owned()),
- );
- }
- }
-
- if let Some(val_delim) = arg.get_value_delimiter() {
- if self.cmd.is_dont_delimit_trailing_values_set() && trailing_idx == Some(0) {
- // Nothing to do
- } else {
- let mut val_delim_buffer = [0; 4];
- let val_delim = val_delim.encode_utf8(&mut val_delim_buffer);
- let mut split_raw_vals = Vec::with_capacity(raw_vals.len());
- for (i, raw_val) in raw_vals.into_iter().enumerate() {
- if !raw_val.contains(val_delim)
- || (self.cmd.is_dont_delimit_trailing_values_set()
- && trailing_idx == Some(i))
- {
- split_raw_vals.push(raw_val);
- } else {
- split_raw_vals.extend(raw_val.split(val_delim).map(|x| x.to_owned()));
- }
- }
- raw_vals = split_raw_vals
- }
- }
-
- 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());
- }
- if matcher.remove(arg.get_id())
- && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
- {
- return Err(ClapError::argument_conflict(
- self.cmd,
- arg.to_string(),
- vec![arg.to_string()],
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
- self.start_custom_arg(matcher, arg, source);
- ok!(self.push_arg_values(arg, raw_vals, source, 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);
- ok!(self.push_arg_values(arg, raw_vals, source, 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::SetTrue => {
- let raw_vals = if raw_vals.is_empty() {
- vec![OsString::from("true")]
- } else {
- raw_vals
- };
-
- if matcher.remove(arg.get_id())
- && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
- {
- return Err(ClapError::argument_conflict(
- self.cmd,
- arg.to_string(),
- vec![arg.to_string()],
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
- self.start_custom_arg(matcher, arg, source);
- ok!(self.push_arg_values(arg, raw_vals, source, matcher));
- Ok(ParseResult::ValuesDone)
- }
- ArgAction::SetFalse => {
- let raw_vals = if raw_vals.is_empty() {
- vec![OsString::from("false")]
- } else {
- raw_vals
- };
-
- if matcher.remove(arg.get_id())
- && !(self.cmd.is_args_override_self() || arg.overrides.contains(arg.get_id()))
- {
- return Err(ClapError::argument_conflict(
- self.cmd,
- arg.to_string(),
- vec![arg.to_string()],
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
- self.start_custom_arg(matcher, arg, source);
- ok!(self.push_arg_values(arg, raw_vals, source, matcher));
- Ok(ParseResult::ValuesDone)
- }
- ArgAction::Count => {
- let raw_vals = if raw_vals.is_empty() {
- let existing_value = *matcher
- .get_one::<crate::builder::CountType>(arg.get_id().as_str())
- .unwrap_or(&0);
- let next_value = existing_value.saturating_add(1);
- vec![OsString::from(next_value.to_string())]
- } else {
- raw_vals
- };
-
- matcher.remove(arg.get_id());
- self.start_custom_arg(matcher, arg, source);
- ok!(self.push_arg_values(arg, raw_vals, source, matcher));
- Ok(ParseResult::ValuesDone)
- }
- ArgAction::Help => {
- 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))
- }
- ArgAction::HelpShort => {
- let use_long = false;
- debug!("Help: use_long={use_long}");
- Err(self.help_err(use_long))
- }
- ArgAction::HelpLong => {
- let use_long = true;
- debug!("Help: use_long={use_long}");
- Err(self.help_err(use_long))
- }
- ArgAction::Version => {
- 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 verify_num_args(&self, arg: &Arg, raw_vals: &[OsString]) -> ClapResult<()> {
- if self.cmd.is_ignore_errors_set() {
- return Ok(());
- }
-
- let actual = raw_vals.len();
- let expected = arg.get_num_args().expect(INTERNAL_ERROR_MSG);
-
- if 0 < expected.min_values() && actual == 0 {
- // Issue 665 (https://github.com/clap-rs/clap/issues/665)
- // Issue 1105 (https://github.com/clap-rs/clap/issues/1105)
- return Err(ClapError::empty_value(
- self.cmd,
- &super::get_possible_values_cli(arg)
- .iter()
- .filter(|pv| !pv.is_hide_set())
- .map(|n| n.get_name().to_owned())
- .collect::<Vec<_>>(),
- arg.to_string(),
- ));
- } else if let Some(expected) = expected.num_values() {
- if expected != actual {
- debug!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues");
- return Err(ClapError::wrong_number_of_values(
- self.cmd,
- arg.to_string(),
- expected,
- actual,
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
- } else if actual < expected.min_values() {
- return Err(ClapError::too_few_values(
- self.cmd,
- arg.to_string(),
- expected.min_values(),
- actual,
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- } else if expected.max_values() < actual {
- debug!("Validator::validate_arg_num_vals: Sending error TooManyValues");
- return Err(ClapError::too_many_values(
- self.cmd,
- raw_vals
- .last()
- .expect(INTERNAL_ERROR_MSG)
- .to_string_lossy()
- .into_owned(),
- arg.to_string(),
- Usage::new(self.cmd).create_usage_with_title(&[]),
- ));
- }
-
- Ok(())
- }
-
- fn remove_overrides(&self, arg: &Arg, matcher: &mut ArgMatcher) {
- debug!("Parser::remove_overrides: id={:?}", arg.id);
- for override_id in &arg.overrides {
- debug!("Parser::remove_overrides:iter:{override_id:?}: removing");
- 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.get_id()) {
- transitive.push(overrider.get_id());
- }
- }
- }
- for overrider_id in transitive {
- debug!("Parser::remove_overrides:iter:{overrider_id:?}: removing");
- matcher.remove(overrider_id);
- }
- }
-
- #[cfg(feature = "env")]
- fn add_env(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
- debug!("Parser::add_env");
-
- 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 {
- debug!("Parser::add_env: Found an opt with value={val:?}");
- let arg_values = vec![val.to_owned()];
- let trailing_idx = None;
- let _ = ok!(self.react(
- None,
- ValueSource::EnvVariable,
- arg,
- arg_values,
- trailing_idx,
- 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.get_id());
- ok!(self.add_default_value(arg, matcher));
- }
-
- Ok(())
- }
-
- fn add_default_value(&self, arg: &Arg, matcher: &mut ArgMatcher) -> ClapResult<()> {
- if !arg.default_vals_ifs.is_empty() {
- debug!("Parser::add_default_value: has conditional defaults");
- if !matcher.contains(arg.get_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 arg_values = vec![default.to_os_string()];
- let trailing_idx = None;
- let _ = ok!(self.react(
- None,
- ValueSource::DefaultValue,
- arg,
- arg_values,
- trailing_idx,
- matcher,
- ));
- }
- 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.get_id()
- );
- if matcher.contains(arg.get_id()) {
- debug!("Parser::add_default_value:iter:{}: was used", arg.get_id());
- // do nothing
- } else {
- debug!(
- "Parser::add_default_value:iter:{}: wasn't used",
- arg.get_id()
- );
- let arg_values: Vec<_> = arg
- .default_vals
- .iter()
- .map(crate::builder::OsStr::to_os_string)
- .collect();
- let trailing_idx = None;
- let _ = ok!(self.react(
- None,
- ValueSource::DefaultValue,
- arg,
- arg_values,
- trailing_idx,
- matcher,
- ));
- }
- } else {
- debug!(
- "Parser::add_default_value:iter:{}: doesn't have default vals",
- arg.get_id()
- );
-
- // do nothing
- }
-
- Ok(())
- }
-
- fn start_custom_arg(&self, matcher: &mut ArgMatcher, arg: &Arg, 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);
- if source.is_explicit() {
- for group in self.cmd.groups_for_arg(arg.get_id()) {
- matcher.start_custom_group(group.clone(), source);
- matcher.add_val_to(
- &group,
- AnyValue::new(arg.get_id().clone()),
- OsString::from(arg.get_id().as_str()),
- );
- }
- }
- }
-}
-
-// Error, Help, and Version Methods
-impl<'cmd> Parser<'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: &[&OsStr],
- trailing_values: bool,
- ) -> 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_custom_arg(matcher, arg, ValueSource::CommandLine);
- }
- }
- let did_you_mean = did_you_mean.map(|(arg, cmd)| (format!("--{arg}"), cmd));
-
- 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(|a| !a.is_hide_set()).unwrap_or(true))
- .cloned()
- .collect();
-
- // `did_you_mean` is a lot more likely and should cause us to skip the `--` suggestion
- //
- // In theory, this is only called for `--long`s, so we don't need to check
- let suggested_trailing_arg =
- did_you_mean.is_none() && !trailing_values && self.cmd.has_positionals();
- ClapError::unknown_argument(
- self.cmd,
- format!("--{arg}"),
- did_you_mean,
- suggested_trailing_arg,
- Usage::new(self.cmd)
- .required(&required)
- .create_usage_with_title(&used),
- )
- }
-
- fn help_err(&self, use_long: bool) -> ClapError {
- let styled = self.cmd.write_help_err(use_long);
- ClapError::display_help(self.cmd, styled)
- }
-
- fn version_err(&self, use_long: bool) -> ClapError {
- let styled = self.cmd.write_version_err(use_long);
- ClapError::display_version(self.cmd, styled)
- }
-}
-
-#[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>,
- pub(crate) trailing_idx: Option<usize>,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub(crate) enum Identifier {
- Short,
- Long,
- Index,
-}
diff --git a/vendor/clap_builder/src/parser/validator.rs b/vendor/clap_builder/src/parser/validator.rs
deleted file mode 100644
index 55f4633..0000000
--- a/vendor/clap_builder/src/parser/validator.rs
+++ /dev/null
@@ -1,561 +0,0 @@
-// Internal
-use crate::builder::StyledStr;
-use crate::builder::{Arg, ArgGroup, ArgPredicate, Command, PossibleValue};
-use crate::error::{Error, Result as ClapResult};
-use crate::output::Usage;
-use crate::parser::{ArgMatcher, ParseState};
-use crate::util::ChildGraph;
-use crate::util::FlatMap;
-use crate::util::FlatSet;
-use crate::util::Id;
-use crate::INTERNAL_ERROR_MSG;
-
-pub(crate) struct Validator<'cmd> {
- cmd: &'cmd Command,
- required: ChildGraph<Id>,
-}
-
-impl<'cmd> Validator<'cmd> {
- pub(crate) fn new(cmd: &'cmd Command) -> 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 conflicts = Conflicts::with_args(self.cmd, matcher);
- 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.get_id()) {
- v.all_val_groups_empty() && o.get_min_vals() != 0
- } else {
- true
- };
- if should_err {
- return Err(Error::empty_value(
- self.cmd,
- &get_possible_values_cli(o)
- .iter()
- .filter(|pv| !pv.is_hide_set())
- .map(|n| n.get_name().to_owned())
- .collect::<Vec<_>>(),
- o.to_string(),
- ));
- }
- }
-
- if !has_subcmd && self.cmd.is_arg_required_else_help_set() {
- let num_user_values = matcher
- .args()
- .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
- .count();
- if num_user_values == 0 {
- let message = self.cmd.write_help_err(false);
- return Err(Error::display_help_error(self.cmd, message));
- }
- }
- if !has_subcmd && self.cmd.is_subcommand_required_set() {
- let bn = self.cmd.get_bin_name_fallback();
- return Err(Error::missing_subcommand(
- self.cmd,
- bn.to_string(),
- self.cmd
- .all_subcommand_names()
- .map(|s| s.to_owned())
- .collect::<Vec<_>>(),
- Usage::new(self.cmd)
- .required(&self.required)
- .create_usage_with_title(&[]),
- ));
- }
-
- ok!(self.validate_conflicts(matcher, &conflicts));
- if !(self.cmd.is_subcommand_negates_reqs_set() && has_subcmd) {
- ok!(self.validate_required(matcher, &conflicts));
- }
-
- Ok(())
- }
-
- fn validate_conflicts(
- &mut self,
- matcher: &ArgMatcher,
- conflicts: &Conflicts,
- ) -> ClapResult<()> {
- debug!("Validator::validate_conflicts");
-
- ok!(self.validate_exclusive(matcher));
-
- for (arg_id, _) in matcher
- .args()
- .filter(|(_, matched)| matched.check_explicit(&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, arg_id);
- ok!(self.build_conflict_err(arg_id, &conflicts, matcher));
- }
-
- Ok(())
- }
-
- fn validate_exclusive(&self, matcher: &ArgMatcher) -> ClapResult<()> {
- debug!("Validator::validate_exclusive");
- let args_count = matcher
- .args()
- .filter(|(arg_id, matched)| {
- matched.check_explicit(&crate::builder::ArgPredicate::IsPresent)
- // Avoid including our own groups by checking none of them. If a group is present, the
- // args for the group will be.
- && self.cmd.find(arg_id).is_some()
- })
- .count();
- if args_count <= 1 {
- // Nothing present to conflict with
- return Ok(());
- }
-
- matcher
- .args()
- .filter(|(_, matched)| matched.check_explicit(&crate::builder::ArgPredicate::IsPresent))
- .filter_map(|(id, _)| {
- debug!("Validator::validate_exclusive:iter:{id:?}");
- self.cmd
- .find(id)
- // Find `arg`s which are exclusive but also appear with other args.
- .filter(|&arg| arg.is_exclusive_set() && args_count > 1)
- })
- .next()
- .map(|arg| {
- // Throw an error for the first conflict found.
- Err(Error::argument_conflict(
- self.cmd,
- arg.to_string(),
- Vec::new(),
- Usage::new(self.cmd)
- .required(&self.required)
- .create_usage_with_title(&[]),
- ))
- })
- .unwrap_or(Ok(()))
- }
-
- 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 = FlatSet::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],
- ) -> Option<StyledStr> {
- let used_filtered: Vec<Id> = matcher
- .args()
- .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
- .map(|(n, _)| n)
- .filter(|n| {
- // Filter out the args we don't want to specify.
- self.cmd
- .find(n)
- .map(|a| !a.is_hide_set())
- .unwrap_or_default()
- })
- .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, matched) in matcher
- .args()
- .filter(|(_, matched)| matched.check_explicit(&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 = matched.check_explicit(val);
- required.then(|| req_arg.clone())
- };
-
- for req in self.cmd.unroll_arg_requires(is_relevant, arg.get_id()) {
- self.required.insert(req);
- }
- } else if let Some(g) = self.cmd.find_group(name) {
- debug!("Validator::gather_requires:iter:{name:?}:group");
- for r in &g.requires {
- self.required.insert(r.clone());
- }
- }
- }
- }
-
- fn validate_required(&mut self, matcher: &ArgMatcher, conflicts: &Conflicts) -> ClapResult<()> {
- debug!("Validator::validate_required: required={:?}", self.required);
- self.gather_requires(matcher);
-
- let mut missing_required = Vec::new();
- let mut highest_index = 0;
-
- let is_exclusive_present = matcher
- .args()
- .filter(|(_, matched)| matched.check_explicit(&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, conflicts) {
- debug!(
- "Validator::validate_required:iter: Missing {:?}",
- arg.get_id()
- );
- missing_required.push(arg.get_id().clone());
- if !arg.is_last_set() {
- highest_index = highest_index.max(arg.get_index().unwrap_or(0));
- }
- }
- } 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))
- {
- debug!(
- "Validator::validate_required:iter: Missing {:?}",
- group.get_id()
- );
- missing_required.push(group.get_id().clone());
- }
- }
- }
-
- // Validate the conditionally required args
- for a in self
- .cmd
- .get_arguments()
- .filter(|a| !matcher.check_explicit(a.get_id(), &ArgPredicate::IsPresent))
- {
- let mut required = false;
-
- for (other, val) in &a.r_ifs {
- if matcher.check_explicit(other, &ArgPredicate::Equals(val.into())) {
- debug!(
- "Validator::validate_required:iter: Missing {:?}",
- a.get_id()
- );
- required = true;
- }
- }
-
- let match_all = a.r_ifs_all.iter().all(|(other, val)| {
- matcher.check_explicit(other, &ArgPredicate::Equals(val.into()))
- });
- if match_all && !a.r_ifs_all.is_empty() {
- debug!(
- "Validator::validate_required:iter: Missing {:?}",
- a.get_id()
- );
- required = true;
- }
-
- if (!a.r_unless.is_empty() || !a.r_unless_all.is_empty())
- && self.fails_arg_required_unless(a, matcher)
- {
- debug!(
- "Validator::validate_required:iter: Missing {:?}",
- a.get_id()
- );
- required = true;
- }
-
- if required {
- missing_required.push(a.get_id().clone());
- if !a.is_last_set() {
- highest_index = highest_index.max(a.get_index().unwrap_or(0));
- }
- }
- }
-
- // For display purposes, include all of the preceding positional arguments
- if !self.cmd.is_allow_missing_positional_set() {
- for pos in self
- .cmd
- .get_positionals()
- .filter(|a| !matcher.check_explicit(a.get_id(), &ArgPredicate::IsPresent))
- {
- if pos.get_index() < Some(highest_index) {
- debug!(
- "Validator::validate_required:iter: Missing {:?}",
- pos.get_id()
- );
- missing_required.push(pos.get_id().clone());
- }
- }
- }
-
- if !missing_required.is_empty() {
- ok!(self.missing_required_error(matcher, missing_required));
- }
-
- Ok(())
- }
-
- fn is_missing_required_ok(&self, a: &Arg, conflicts: &Conflicts) -> bool {
- debug!("Validator::is_missing_required_ok: {}", a.get_id());
- if !conflicts.gather_conflicts(self.cmd, a.get_id()).is_empty() {
- debug!("Validator::is_missing_required_ok: true (self)");
- return true;
- }
- for group_id in self.cmd.groups_for_arg(a.get_id()) {
- if !conflicts.gather_conflicts(self.cmd, &group_id).is_empty() {
- debug!("Validator::is_missing_required_ok: true ({group_id})");
- return true;
- }
- }
- false
- }
-
- // Failing a required unless means, the arg's "unless" wasn't present, and neither were they
- fn fails_arg_required_unless(&self, a: &Arg, matcher: &ArgMatcher) -> bool {
- debug!("Validator::fails_arg_required_unless: a={:?}", a.get_id());
- 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)
- }
-
- // `req_args`: an arg to include in the error even if not used
- fn missing_required_error(
- &self,
- matcher: &ArgMatcher,
- raw_req_args: Vec<Id>,
- ) -> ClapResult<()> {
- debug!("Validator::missing_required_error; incl={raw_req_args:?}");
- debug!(
- "Validator::missing_required_error: reqs={:?}",
- self.required
- );
-
- let usg = Usage::new(self.cmd).required(&self.required);
-
- let req_args = {
- #[cfg(feature = "usage")]
- {
- usg.get_required_usage_from(&raw_req_args, Some(matcher), true)
- .into_iter()
- .map(|s| s.to_string())
- .collect::<Vec<_>>()
- }
-
- #[cfg(not(feature = "usage"))]
- {
- raw_req_args
- .iter()
- .map(|id| {
- if let Some(arg) = self.cmd.find(id) {
- arg.to_string()
- } else if let Some(_group) = self.cmd.find_group(id) {
- self.cmd.format_group(id).to_string()
- } else {
- debug_assert!(false, "id={id:?} is unknown");
- "".to_owned()
- }
- })
- .collect::<Vec<_>>()
- }
- };
-
- debug!("Validator::missing_required_error: req_args={req_args:#?}");
-
- let used: Vec<Id> = matcher
- .args()
- .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
- .map(|(n, _)| n)
- .filter(|n| {
- // Filter out the args we don't want to specify.
- self.cmd
- .find(n)
- .map(|a| !a.is_hide_set())
- .unwrap_or_default()
- })
- .cloned()
- .chain(raw_req_args)
- .collect();
-
- Err(Error::missing_required_argument(
- self.cmd,
- req_args,
- usg.create_usage_with_title(&used),
- ))
- }
-}
-
-#[derive(Default, Clone, Debug)]
-struct Conflicts {
- potential: FlatMap<Id, Vec<Id>>,
-}
-
-impl Conflicts {
- fn with_args(cmd: &Command, matcher: &ArgMatcher) -> Self {
- let mut potential = FlatMap::new();
- potential.extend_unchecked(
- matcher
- .args()
- .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
- .map(|(id, _)| {
- let conf = gather_direct_conflicts(cmd, id);
- (id.clone(), conf)
- }),
- );
- Self { potential }
- }
-
- fn gather_conflicts(&self, cmd: &Command, arg_id: &Id) -> Vec<Id> {
- debug!("Conflicts::gather_conflicts: arg={arg_id:?}");
- let mut conflicts = Vec::new();
-
- let arg_id_conflicts_storage;
- let arg_id_conflicts = if let Some(arg_id_conflicts) = self.get_direct_conflicts(arg_id) {
- arg_id_conflicts
- } else {
- // `is_missing_required_ok` is a case where we check not-present args for conflicts
- arg_id_conflicts_storage = gather_direct_conflicts(cmd, arg_id);
- &arg_id_conflicts_storage
- };
- for (other_arg_id, other_arg_id_conflicts) in self.potential.iter() {
- if arg_id == other_arg_id {
- continue;
- }
-
- if arg_id_conflicts.contains(other_arg_id) {
- conflicts.push(other_arg_id.clone());
- }
- if other_arg_id_conflicts.contains(arg_id) {
- conflicts.push(other_arg_id.clone());
- }
- }
-
- debug!("Conflicts::gather_conflicts: conflicts={conflicts:?}");
- conflicts
- }
-
- fn get_direct_conflicts(&self, arg_id: &Id) -> Option<&[Id]> {
- self.potential.get(arg_id).map(Vec::as_slice)
- }
-}
-
-fn gather_direct_conflicts(cmd: &Command, id: &Id) -> Vec<Id> {
- let conf = if let Some(arg) = cmd.find(id) {
- gather_arg_direct_conflicts(cmd, arg)
- } else if let Some(group) = cmd.find_group(id) {
- gather_group_direct_conflicts(group)
- } else {
- debug_assert!(false, "id={id:?} is unknown");
- Vec::new()
- };
- debug!("Conflicts::gather_direct_conflicts id={id:?}, conflicts={conf:?}",);
- conf
-}
-
-fn gather_arg_direct_conflicts(cmd: &Command, arg: &Arg) -> Vec<Id> {
- let mut conf = arg.blacklist.clone();
- for group_id in cmd.groups_for_arg(arg.get_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.get_id() {
- conf.push(member_id.clone());
- }
- }
- }
- }
-
- // Overrides are implicitly conflicts
- conf.extend(arg.overrides.iter().cloned());
-
- conf
-}
-
-fn gather_group_direct_conflicts(group: &ArgGroup) -> Vec<Id> {
- group.conflicts.clone()
-}
-
-pub(crate) fn get_possible_values_cli(a: &Arg) -> Vec<PossibleValue> {
- if !a.is_takes_value_set() {
- vec![]
- } else {
- a.get_value_parser()
- .possible_values()
- .map(|pvs| pvs.collect())
- .unwrap_or_default()
- }
-}