1use clap::error::{Error, ErrorKind};
2use clap::{ArgMatches, Args as _, Command, FromArgMatches, Parser, Subcommand};
3
4#[derive(Parser, Debug)]
5struct AddArgs {
6 name: Vec<String>,
7}
8#[derive(Parser, Debug)]
9struct RemoveArgs {
10 #[arg(short, long)]
11 force: bool,
12 name: Vec<String>,
13}
14
15#[derive(Debug)]
16enum CliSub {
17 Add(AddArgs),
18 Remove(RemoveArgs),
19}
20
21impl FromArgMatches for CliSub {
22 fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error> {
23 match matches.subcommand() {
24 Some(("add", args)) => Ok(Self::Add(AddArgs::from_arg_matches(args)?)),
25 Some(("remove", args)) => Ok(Self::Remove(RemoveArgs::from_arg_matches(args)?)),
26 Some((_, _)) => Err(Error::raw(
27 ErrorKind::InvalidSubcommand,
28 "Valid subcommands are `add` and `remove`",
29 )),
30 None => Err(Error::raw(
31 ErrorKind::MissingSubcommand,
32 "Valid subcommands are `add` and `remove`",
33 )),
34 }
35 }
36 fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> {
37 match matches.subcommand() {
38 Some(("add", args)) => *self = Self::Add(AddArgs::from_arg_matches(args)?),
39 Some(("remove", args)) => *self = Self::Remove(RemoveArgs::from_arg_matches(args)?),
40 Some((_, _)) => {
41 return Err(Error::raw(
42 ErrorKind::InvalidSubcommand,
43 "Valid subcommands are `add` and `remove`",
44 ))
45 }
46 None => (),
47 };
48 Ok(())
49 }
50}
51
52impl Subcommand for CliSub {
53 fn augment_subcommands(cmd: Command) -> Command {
54 cmd.subcommand(AddArgs::augment_args(Command::new("add")))
55 .subcommand(RemoveArgs::augment_args(Command::new("remove")))
56 .subcommand_required(true)
57 }
58 fn augment_subcommands_for_update(cmd: Command) -> Command {
59 cmd.subcommand(AddArgs::augment_args(Command::new("add")))
60 .subcommand(RemoveArgs::augment_args(Command::new("remove")))
61 .subcommand_required(true)
62 }
63 fn has_subcommand(name: &str) -> bool {
64 matches!(name, "add" | "remove")
65 }
66}
67
68#[derive(Parser, Debug)]
69struct Cli {
70 #[arg(short, long)]
71 top_level: bool,
72 #[command(subcommand)]
73 subcommand: CliSub,
74}
75
76fn main() {
77 let args = Cli::parse();
78 println!("{args:#?}");
79}
80