1use clap::{arg, builder::PossibleValue, command, value_parser, ValueEnum};
2
3#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
4enum Mode {
5 Fast,
6 Slow,
7}
8
9// Can also be derived with feature flag `derive`
10impl ValueEnum for Mode {
11 fn value_variants<'a>() -> &'a [Self] {
12 &[Mode::Fast, Mode::Slow]
13 }
14
15 fn to_possible_value<'a>(&self) -> Option<PossibleValue> {
16 Some(match self {
17 Mode::Fast => PossibleValue::new("fast").help("Run swiftly"),
18 Mode::Slow => PossibleValue::new("slow").help("Crawl slowly but steadily"),
19 })
20 }
21}
22
23impl std::fmt::Display for Mode {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 self.to_possible_value()
26 .expect("no values are skipped")
27 .get_name()
28 .fmt(f)
29 }
30}
31
32impl std::str::FromStr for Mode {
33 type Err = String;
34
35 fn from_str(s: &str) -> Result<Self, Self::Err> {
36 for variant in Self::value_variants() {
37 if variant.to_possible_value().unwrap().matches(s, false) {
38 return Ok(*variant);
39 }
40 }
41 Err(format!("invalid variant: {s}"))
42 }
43}
44
45fn main() {
46 let matches = command!() // requires `cargo` feature
47 .arg(
48 arg!(<MODE>)
49 .help("What mode to run the program in")
50 .value_parser(value_parser!(Mode)),
51 )
52 .get_matches();
53
54 // Note, it's safe to call unwrap() because the arg is required
55 match matches
56 .get_one::<Mode>("MODE")
57 .expect("'MODE' is required and parsing will fail if its missing")
58 {
59 Mode::Fast => {
60 println!("Hare");
61 }
62 Mode::Slow => {
63 println!("Tortoise");
64 }
65 }
66}
67