use clap::error::{Error, ErrorKind}; use clap::{ArgMatches, Args as _, Command, FromArgMatches, Parser, Subcommand}; #[derive(Parser, Debug)] struct AddArgs { name: Vec, } #[derive(Parser, Debug)] struct RemoveArgs { #[clap(short, long)] force: bool, name: Vec, } #[derive(Debug)] enum CliSub { Add(AddArgs), Remove(RemoveArgs), } impl FromArgMatches for CliSub { fn from_arg_matches(matches: &ArgMatches) -> Result { match matches.subcommand() { Some(("add", args)) => Ok(Self::Add(AddArgs::from_arg_matches(args)?)), Some(("remove", args)) => Ok(Self::Remove(RemoveArgs::from_arg_matches(args)?)), Some((_, _)) => Err(Error::raw( ErrorKind::UnrecognizedSubcommand, "Valid subcommands are `add` and `remove`", )), None => Err(Error::raw( ErrorKind::MissingSubcommand, "Valid subcommands are `add` and `remove`", )), } } fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> { match matches.subcommand() { Some(("add", args)) => *self = Self::Add(AddArgs::from_arg_matches(args)?), Some(("remove", args)) => *self = Self::Remove(RemoveArgs::from_arg_matches(args)?), Some((_, _)) => { return Err(Error::raw( ErrorKind::UnrecognizedSubcommand, "Valid subcommands are `add` and `remove`", )) } None => (), }; Ok(()) } } impl Subcommand for CliSub { fn augment_subcommands(cmd: Command<'_>) -> Command<'_> { cmd.subcommand(AddArgs::augment_args(Command::new("add"))) .subcommand(RemoveArgs::augment_args(Command::new("remove"))) .subcommand_required(true) } fn augment_subcommands_for_update(cmd: Command<'_>) -> Command<'_> { cmd.subcommand(AddArgs::augment_args(Command::new("add"))) .subcommand(RemoveArgs::augment_args(Command::new("remove"))) .subcommand_required(true) } fn has_subcommand(name: &str) -> bool { matches!(name, "add" | "remove") } } #[derive(Parser, Debug)] struct Cli { #[clap(short, long)] top_level: bool, #[clap(subcommand)] subcommand: CliSub, } fn main() { let args = Cli::parse(); println!("{:#?}", args); }