mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 14:22:34 +00:00
Merge pull request #4509 from epage/possible
feat: Improve ValueParser experience
This commit is contained in:
commit
20e02eb34e
4 changed files with 68 additions and 48 deletions
|
@ -7,8 +7,11 @@ use crate::util::eq_ignore_case;
|
|||
///
|
||||
/// This is used for specifying [possible values] of [Args].
|
||||
///
|
||||
/// **NOTE:** This struct is likely not needed for most usecases as it is only required to
|
||||
/// [hide] single values from help messages and shell completions or to attach [help] to possible values.
|
||||
/// See also [`PossibleValuesParser`][crate::builder::PossibleValuesParser]
|
||||
///
|
||||
/// **NOTE:** Most likely you can use strings, rather than `PossibleValue` as it is only required
|
||||
/// to [hide] single values from help messages and shell completions or to attach [help] to
|
||||
/// possible values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -23,6 +26,7 @@ use crate::util::eq_ignore_case;
|
|||
/// PossibleValue::new("secret speed").hide(true)
|
||||
/// ]);
|
||||
/// ```
|
||||
///
|
||||
/// [Args]: crate::Arg
|
||||
/// [possible values]: crate::builder::ValueParser::possible_values
|
||||
/// [hide]: PossibleValue::hide()
|
||||
|
|
|
@ -508,6 +508,41 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a [`ValueParser`] with [`PossibleValuesParser`]
|
||||
///
|
||||
/// See [`PossibleValuesParser`] for more flexibility in creating the
|
||||
/// [`PossibleValue`][crate::builder::PossibleValue]s.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// let possible = vec!["always", "auto", "never"];
|
||||
/// let mut cmd = clap::Command::new("raw")
|
||||
/// .arg(
|
||||
/// clap::Arg::new("color")
|
||||
/// .long("color")
|
||||
/// .value_parser(possible)
|
||||
/// .default_value("auto")
|
||||
/// );
|
||||
///
|
||||
/// let m = cmd.try_get_matches_from_mut(
|
||||
/// ["cmd", "--color", "never"]
|
||||
/// ).unwrap();
|
||||
///
|
||||
/// let color: &String = m.get_one("color")
|
||||
/// .expect("default");
|
||||
/// assert_eq!(color, "never");
|
||||
/// ```
|
||||
impl<P> From<Vec<P>> for ValueParser
|
||||
where
|
||||
P: Into<super::PossibleValue>,
|
||||
{
|
||||
fn from(values: Vec<P>) -> Self {
|
||||
let inner = PossibleValuesParser::from(values);
|
||||
Self::from(inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ValueParser {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
match &self.0 {
|
||||
|
@ -957,31 +992,11 @@ impl Default for PathBufValueParser {
|
|||
///
|
||||
/// ```rust
|
||||
/// # use std::ffi::OsStr;
|
||||
/// # use clap::ColorChoice;
|
||||
/// # use clap::builder::TypedValueParser;
|
||||
/// # let cmd = clap::Command::new("test");
|
||||
/// # let arg = None;
|
||||
///
|
||||
/// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
/// enum ColorChoice {
|
||||
/// Always,
|
||||
/// Auto,
|
||||
/// Never,
|
||||
/// }
|
||||
///
|
||||
/// impl clap::ValueEnum for ColorChoice {
|
||||
/// fn value_variants<'a>() -> &'a [Self] {
|
||||
/// &[Self::Always, Self::Auto, Self::Never]
|
||||
/// }
|
||||
///
|
||||
/// fn to_possible_value<'a>(&self) -> Option<clap::builder::PossibleValue> {
|
||||
/// match self {
|
||||
/// Self::Always => Some(clap::builder::PossibleValue::new("always")),
|
||||
/// Self::Auto => Some(clap::builder::PossibleValue::new("auto")),
|
||||
/// Self::Never => Some(clap::builder::PossibleValue::new("never")),
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // Usage
|
||||
/// let mut cmd = clap::Command::new("raw")
|
||||
/// .arg(
|
||||
|
@ -1086,8 +1101,9 @@ impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> Default for EnumValueP
|
|||
/// Verify the value is from an enumerated set of [`PossibleValue`][crate::builder::PossibleValue].
|
||||
///
|
||||
/// See also:
|
||||
/// - [`EnumValueParser`] for directly supporting `enum`s
|
||||
/// - [`TypedValueParser::map`] for adapting values to a more specialized type
|
||||
/// - [`EnumValueParser`] for directly supporting [`ValueEnum`][crate::ValueEnum] types
|
||||
/// - [`TypedValueParser::map`] for adapting values to a more specialized type, like an external
|
||||
/// enums that can't implement [`ValueEnum`][crate::ValueEnum]
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -2327,6 +2343,7 @@ pub mod via_prelude {
|
|||
///
|
||||
/// Example mappings:
|
||||
/// ```rust
|
||||
/// # use clap::ColorChoice;
|
||||
/// // Built-in types
|
||||
/// let parser = clap::value_parser!(String);
|
||||
/// assert_eq!(format!("{:?}", parser), "ValueParser::string");
|
||||
|
@ -2344,25 +2361,6 @@ pub mod via_prelude {
|
|||
/// assert_eq!(format!("{:?}", parser), "_AnonymousValueParser(ValueParser::other(usize))");
|
||||
///
|
||||
/// // ValueEnum types
|
||||
/// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
/// enum ColorChoice {
|
||||
/// Always,
|
||||
/// Auto,
|
||||
/// Never,
|
||||
/// }
|
||||
/// impl clap::ValueEnum for ColorChoice {
|
||||
/// // ...
|
||||
/// # fn value_variants<'a>() -> &'a [Self] {
|
||||
/// # &[Self::Always, Self::Auto, Self::Never]
|
||||
/// # }
|
||||
/// # fn to_possible_value<'a>(&self) -> Option<clap::builder::PossibleValue> {
|
||||
/// # match self {
|
||||
/// # Self::Always => Some(clap::builder::PossibleValue::new("always")),
|
||||
/// # Self::Auto => Some(clap::builder::PossibleValue::new("auto")),
|
||||
/// # Self::Never => Some(clap::builder::PossibleValue::new("never")),
|
||||
/// # }
|
||||
/// # }
|
||||
/// }
|
||||
/// let parser = clap::value_parser!(ColorChoice);
|
||||
/// assert_eq!(format!("{:?}", parser), "EnumValueParser(PhantomData)");
|
||||
/// ```
|
||||
|
|
|
@ -102,11 +102,7 @@ pub use crate::builder::Command;
|
|||
pub use crate::builder::ValueHint;
|
||||
pub use crate::builder::{Arg, ArgGroup};
|
||||
pub use crate::parser::ArgMatches;
|
||||
#[cfg(feature = "color")]
|
||||
pub use crate::util::color::ColorChoice;
|
||||
#[cfg(not(feature = "color"))]
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use crate::util::color::ColorChoice;
|
||||
pub use crate::util::Id;
|
||||
|
||||
/// Command Line Argument Parser Error
|
||||
|
|
|
@ -64,6 +64,28 @@ impl Default for ColorChoice {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ColorChoice {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.to_possible_value()
|
||||
.expect("no values are skipped")
|
||||
.get_name()
|
||||
.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for ColorChoice {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
for variant in Self::value_variants() {
|
||||
if variant.to_possible_value().unwrap().matches(s, false) {
|
||||
return Ok(*variant);
|
||||
}
|
||||
}
|
||||
Err(format!("Invalid variant: {}", s))
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueEnum for ColorChoice {
|
||||
fn value_variants<'a>() -> &'a [Self] {
|
||||
&[Self::Auto, Self::Always, Self::Never]
|
||||
|
|
Loading…
Reference in a new issue