diff --git a/Cargo.toml b/Cargo.toml index 42cb8da0..22123154 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -206,7 +206,7 @@ required-features = ["cargo"] [[example]] name = "04_01_enum" path = "examples/tutorial_builder/04_01_enum.rs" -required-features = ["cargo", "derive"] +required-features = ["cargo"] [[example]] name = "04_02_parse" diff --git a/examples/tutorial_builder/04_01_enum.rs b/examples/tutorial_builder/04_01_enum.rs index e76c9512..e8cf70f5 100644 --- a/examples/tutorial_builder/04_01_enum.rs +++ b/examples/tutorial_builder/04_01_enum.rs @@ -1,11 +1,47 @@ -use clap::{arg, command, value_parser, ValueEnum}; +use clap::{arg, builder::PossibleValue, command, value_parser, ValueEnum}; -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] // requires `derive` feature +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] enum Mode { Fast, Slow, } +// Can also be derived] with feature flag `derive` +impl ValueEnum for Mode { + fn value_variants<'a>() -> &'a [Self] { + &[Mode::Fast, Mode::Slow] + } + + fn to_possible_value<'a>(&self) -> Option> { + Some(match self { + Mode::Fast => PossibleValue::new("fast"), + Mode::Slow => PossibleValue::new("slow"), + }) + } +} + +impl std::fmt::Display for Mode { + 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 Mode { + 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)) + } +} + fn main() { let matches = command!() // requires `cargo` feature .arg(