summaryrefslogtreecommitdiffstats
path: root/vendor/clap_builder/src/builder/value_parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/clap_builder/src/builder/value_parser.rs')
-rw-r--r--vendor/clap_builder/src/builder/value_parser.rs190
1 files changed, 189 insertions, 1 deletions
diff --git a/vendor/clap_builder/src/builder/value_parser.rs b/vendor/clap_builder/src/builder/value_parser.rs
index c7c7e61eb..1f0ef925f 100644
--- a/vendor/clap_builder/src/builder/value_parser.rs
+++ b/vendor/clap_builder/src/builder/value_parser.rs
@@ -1,6 +1,9 @@
use std::convert::TryInto;
use std::ops::RangeBounds;
+use crate::builder::Str;
+use crate::builder::StyledStr;
+use crate::parser::ValueSource;
use crate::util::AnyValue;
use crate::util::AnyValueId;
@@ -234,8 +237,9 @@ impl ValueParser {
cmd: &crate::Command,
arg: Option<&crate::Arg>,
value: &std::ffi::OsStr,
+ source: ValueSource,
) -> Result<AnyValue, crate::Error> {
- self.any_value_parser().parse_ref(cmd, arg, value)
+ self.any_value_parser().parse_ref_(cmd, arg, value, source)
}
/// Describes the content of `AnyValue`
@@ -592,6 +596,16 @@ trait AnyValueParser: Send + Sync + 'static {
value: &std::ffi::OsStr,
) -> Result<AnyValue, crate::Error>;
+ fn parse_ref_(
+ &self,
+ cmd: &crate::Command,
+ arg: Option<&crate::Arg>,
+ value: &std::ffi::OsStr,
+ _source: ValueSource,
+ ) -> Result<AnyValue, crate::Error> {
+ self.parse_ref(cmd, arg, value)
+ }
+
fn parse(
&self,
cmd: &crate::Command,
@@ -599,6 +613,16 @@ trait AnyValueParser: Send + Sync + 'static {
value: std::ffi::OsString,
) -> Result<AnyValue, crate::Error>;
+ fn parse_(
+ &self,
+ cmd: &crate::Command,
+ arg: Option<&crate::Arg>,
+ value: std::ffi::OsString,
+ _source: ValueSource,
+ ) -> Result<AnyValue, crate::Error> {
+ self.parse(cmd, arg, value)
+ }
+
/// Describes the content of `AnyValue`
fn type_id(&self) -> AnyValueId;
@@ -624,6 +648,17 @@ where
Ok(AnyValue::new(value))
}
+ fn parse_ref_(
+ &self,
+ cmd: &crate::Command,
+ arg: Option<&crate::Arg>,
+ value: &std::ffi::OsStr,
+ source: ValueSource,
+ ) -> Result<AnyValue, crate::Error> {
+ let value = ok!(TypedValueParser::parse_ref_(self, cmd, arg, value, source));
+ Ok(AnyValue::new(value))
+ }
+
fn parse(
&self,
cmd: &crate::Command,
@@ -634,6 +669,17 @@ where
Ok(AnyValue::new(value))
}
+ fn parse_(
+ &self,
+ cmd: &crate::Command,
+ arg: Option<&crate::Arg>,
+ value: std::ffi::OsString,
+ source: ValueSource,
+ ) -> Result<AnyValue, crate::Error> {
+ let value = ok!(TypedValueParser::parse_(self, cmd, arg, value, source));
+ Ok(AnyValue::new(value))
+ }
+
fn type_id(&self) -> AnyValueId {
AnyValueId::of::<T>()
}
@@ -717,6 +763,19 @@ pub trait TypedValueParser: Clone + Send + Sync + 'static {
/// Parse the argument value
///
/// When `arg` is `None`, an external subcommand value is being parsed.
+ fn parse_ref_(
+ &self,
+ cmd: &crate::Command,
+ arg: Option<&crate::Arg>,
+ value: &std::ffi::OsStr,
+ _source: ValueSource,
+ ) -> Result<Self::Value, crate::Error> {
+ self.parse_ref(cmd, arg, value)
+ }
+
+ /// Parse the argument value
+ ///
+ /// When `arg` is `None`, an external subcommand value is being parsed.
fn parse(
&self,
cmd: &crate::Command,
@@ -726,6 +785,19 @@ pub trait TypedValueParser: Clone + Send + Sync + 'static {
self.parse_ref(cmd, arg, &value)
}
+ /// Parse the argument value
+ ///
+ /// When `arg` is `None`, an external subcommand value is being parsed.
+ fn parse_(
+ &self,
+ cmd: &crate::Command,
+ arg: Option<&crate::Arg>,
+ value: std::ffi::OsString,
+ _source: ValueSource,
+ ) -> Result<Self::Value, crate::Error> {
+ self.parse(cmd, arg, value)
+ }
+
/// Reflect on enumerated value properties
///
/// Error checking should not be done with this; it is mostly targeted at user-facing
@@ -2086,6 +2158,122 @@ where
}
}
+/// When encountered, report [ErrorKind::UnknownArgument][crate::error::ErrorKind::UnknownArgument]
+///
+/// Useful to help users migrate, either from old versions or similar tools.
+///
+/// # Examples
+///
+/// ```rust
+/// # use clap_builder as clap;
+/// # use clap::Command;
+/// # use clap::Arg;
+/// let cmd = Command::new("mycmd")
+/// .args([
+/// Arg::new("current-dir")
+/// .short('C'),
+/// Arg::new("current-dir-unknown")
+/// .long("cwd")
+/// .aliases(["current-dir", "directory", "working-directory", "root"])
+/// .value_parser(clap::builder::UnknownArgumentValueParser::suggest_arg("-C"))
+/// .hide(true),
+/// ]);
+///
+/// // Use a supported version of the argument
+/// let matches = cmd.clone().try_get_matches_from(["mycmd", "-C", ".."]).unwrap();
+/// assert!(matches.contains_id("current-dir"));
+/// assert_eq!(
+/// matches.get_many::<String>("current-dir").unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(),
+/// vec![".."]
+/// );
+///
+/// // Use one of the invalid versions
+/// let err = cmd.try_get_matches_from(["mycmd", "--cwd", ".."]).unwrap_err();
+/// assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument);
+/// ```
+#[derive(Clone, Debug)]
+pub struct UnknownArgumentValueParser {
+ arg: Option<Str>,
+ suggestions: Vec<StyledStr>,
+}
+
+impl UnknownArgumentValueParser {
+ /// Suggest an alternative argument
+ pub fn suggest_arg(arg: impl Into<Str>) -> Self {
+ Self {
+ arg: Some(arg.into()),
+ suggestions: Default::default(),
+ }
+ }
+
+ /// Provide a general suggestion
+ pub fn suggest(text: impl Into<StyledStr>) -> Self {
+ Self {
+ arg: Default::default(),
+ suggestions: vec![text.into()],
+ }
+ }
+
+ /// Extend the suggestions
+ pub fn and_suggest(mut self, text: impl Into<StyledStr>) -> Self {
+ self.suggestions.push(text.into());
+ self
+ }
+}
+
+impl TypedValueParser for UnknownArgumentValueParser {
+ type Value = String;
+
+ fn parse_ref(
+ &self,
+ cmd: &crate::Command,
+ arg: Option<&crate::Arg>,
+ value: &std::ffi::OsStr,
+ ) -> Result<Self::Value, crate::Error> {
+ TypedValueParser::parse_ref_(self, cmd, arg, value, ValueSource::CommandLine)
+ }
+
+ fn parse_ref_(
+ &self,
+ cmd: &crate::Command,
+ arg: Option<&crate::Arg>,
+ _value: &std::ffi::OsStr,
+ source: ValueSource,
+ ) -> Result<Self::Value, crate::Error> {
+ match source {
+ ValueSource::DefaultValue => {
+ TypedValueParser::parse_ref_(&StringValueParser::new(), cmd, arg, _value, source)
+ }
+ ValueSource::EnvVariable | ValueSource::CommandLine => {
+ let arg = match arg {
+ Some(arg) => arg.to_string(),
+ None => "..".to_owned(),
+ };
+ let err = crate::Error::unknown_argument(
+ cmd,
+ arg,
+ self.arg.as_ref().map(|s| (s.as_str().to_owned(), None)),
+ false,
+ crate::output::Usage::new(cmd).create_usage_with_title(&[]),
+ );
+ #[cfg(feature = "error-context")]
+ let err = {
+ debug_assert_eq!(
+ err.get(crate::error::ContextKind::Suggested),
+ None,
+ "Assuming `Error::unknown_argument` doesn't apply any `Suggested` so we can without caution"
+ );
+ err.insert_context_unchecked(
+ crate::error::ContextKind::Suggested,
+ crate::error::ContextValue::StyledStrs(self.suggestions.clone()),
+ )
+ };
+ Err(err)
+ }
+ }
+ }
+}
+
/// Register a type with [value_parser!][crate::value_parser!]
///
/// # Example