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