mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 14:22:34 +00:00
feat(parser): Verify possible values
This commit is contained in:
parent
9d07b3c028
commit
a798858ced
2 changed files with 85 additions and 0 deletions
|
@ -35,6 +35,7 @@ pub use value_parser::AutoValueParser;
|
|||
pub use value_parser::BoolishValueParser;
|
||||
pub use value_parser::FalseyValueParser;
|
||||
pub use value_parser::NonEmptyStringValueParser;
|
||||
pub use value_parser::PossibleValuesParser;
|
||||
pub use value_parser::TypedValueParser;
|
||||
pub use value_parser::ValueParser;
|
||||
pub use value_parser::ValueParserViaArgEnum;
|
||||
|
|
|
@ -332,6 +332,90 @@ impl<E: crate::ArgEnum + Clone + Send + Sync + 'static> TypedValueParser for Arg
|
|||
}
|
||||
}
|
||||
|
||||
/// Verify the value is from an enumerated set pf [`PossibleValue`][crate::PossibleValue].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::ffi::OsStr;
|
||||
/// # use clap::builder::TypedValueParser;
|
||||
/// # let cmd = clap::Command::new("test");
|
||||
/// # let arg = None;
|
||||
/// let value_parser = clap::builder::PossibleValuesParser::new(["always", "auto", "never"]);
|
||||
/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err());
|
||||
/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
|
||||
/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("always")).unwrap(), "always");
|
||||
/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("auto")).unwrap(), "auto");
|
||||
/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("never")).unwrap(), "never");
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PossibleValuesParser(Vec<super::PossibleValue<'static>>);
|
||||
|
||||
impl PossibleValuesParser {
|
||||
/// Verify the value is from an enumerated set pf [`PossibleValue`][crate::PossibleValue].
|
||||
pub fn new(values: impl Into<PossibleValuesParser>) -> Self {
|
||||
values.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TypedValueParser for PossibleValuesParser {
|
||||
type Value = String;
|
||||
|
||||
fn parse_ref(
|
||||
&self,
|
||||
cmd: &crate::Command,
|
||||
arg: Option<&crate::Arg>,
|
||||
value: &std::ffi::OsStr,
|
||||
) -> Result<String, crate::Error> {
|
||||
TypedValueParser::parse(self, cmd, arg, value.to_owned())
|
||||
}
|
||||
|
||||
fn parse(
|
||||
&self,
|
||||
cmd: &crate::Command,
|
||||
arg: Option<&crate::Arg>,
|
||||
value: std::ffi::OsString,
|
||||
) -> Result<String, crate::Error> {
|
||||
let value = value.into_string().map_err(|_| {
|
||||
crate::Error::invalid_utf8(
|
||||
cmd,
|
||||
crate::output::Usage::new(cmd).create_usage_with_title(&[]),
|
||||
)
|
||||
})?;
|
||||
|
||||
let ignore_case = arg.map(|a| a.is_ignore_case_set()).unwrap_or(false);
|
||||
if self.0.iter().any(|v| v.matches(&value, ignore_case)) {
|
||||
Ok(value)
|
||||
} else {
|
||||
let possible_vals = self
|
||||
.0
|
||||
.iter()
|
||||
.filter(|v| !v.is_hide_set())
|
||||
.map(crate::builder::PossibleValue::get_name)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Err(crate::Error::invalid_value(
|
||||
cmd,
|
||||
value.to_owned(),
|
||||
&possible_vals,
|
||||
arg.map(ToString::to_string)
|
||||
.unwrap_or_else(|| "...".to_owned()),
|
||||
crate::output::Usage::new(cmd).create_usage_with_title(&[]),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T> From<I> for PossibleValuesParser
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<super::PossibleValue<'static>>,
|
||||
{
|
||||
fn from(values: I) -> Self {
|
||||
Self(values.into_iter().map(|t| t.into()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse false-like string values, everything else is `true`
|
||||
///
|
||||
/// # Example
|
||||
|
|
Loading…
Reference in a new issue