From ed683ef2485b08e320046570ae918b1ff51e8805 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 24 Nov 2022 09:47:24 -0600 Subject: [PATCH 1/5] fix: Always expose ColorChoice --- src/lib.rs | 4 ---- 1 file changed, 4 deletions(-) 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 From 8d92f3e7a8b3621b1a841e2375ce5c6748e764ba Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 24 Nov 2022 07:41:00 -0600 Subject: [PATCH 2/5] feat: Add Display/FromStr to ColorChoice This matches up with `clap_complete::Shell`. This makes it a bit more flexible. --- src/util/color.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) 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] From 19981a2455cdc2e5f0469cf6a02d32e08b99308c Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 24 Nov 2022 08:04:40 -0600 Subject: [PATCH 3/5] docs: Clarify ColorChoice impls ValueEnum --- src/builder/value_parser.rs | 42 ++----------------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/src/builder/value_parser.rs b/src/builder/value_parser.rs index 1b2b51dba13..8888bb21bcb 100644 --- a/src/builder/value_parser.rs +++ b/src/builder/value_parser.rs @@ -957,31 +957,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( @@ -2327,6 +2307,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 +2325,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)"); /// ``` From 3bccfced1af69aa6130688b9a29d3d2ca55429f4 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 24 Nov 2022 08:07:50 -0600 Subject: [PATCH 4/5] docs: Clarify PossibleValue is likely not needed Fixes #4504 --- src/builder/possible_value.rs | 8 ++++++-- src/builder/value_parser.rs | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) 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 8888bb21bcb..5fe6d2477d6 100644 --- a/src/builder/value_parser.rs +++ b/src/builder/value_parser.rs @@ -1066,8 +1066,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 /// From 94aca92e44a4a6974a087afdf3c3bfa19f631a05 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 24 Nov 2022 08:11:32 -0600 Subject: [PATCH 5/5] feat: Create ValueParser from Vec This dynamically generated list of possible values. Inspired by #4504 --- src/builder/value_parser.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/builder/value_parser.rs b/src/builder/value_parser.rs index 5fe6d2477d6..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 {