diff --git a/src/builder/possible_value.rs b/src/builder/possible_value.rs
index 03964fe118b..7a313ad2585 100644
--- a/src/builder/possible_value.rs
+++ b/src/builder/possible_value.rs
@@ -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()
diff --git a/src/builder/value_parser.rs b/src/builder/value_parser.rs
index 1b2b51dba13..4681857acc1 100644
--- a/src/builder/value_parser.rs
+++ b/src/builder/value_parser.rs
@@ -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
From> for ValueParser
+where
+ P: Into,
+{
+ fn from(values: Vec) -> 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 {
-/// 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 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 {
-/// # 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)");
/// ```
diff --git a/src/lib.rs b/src/lib.rs
index 62b092929fd..393e1f0b9a7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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
diff --git a/src/util/color.rs b/src/util/color.rs
index c13d20d3ea8..7c7468eafd7 100644
--- a/src/util/color.rs
+++ b/src/util/color.rs
@@ -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 {
+ 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]