1 use std::ffi::OsString;
2 use std::path::PathBuf;
3 
4 use clap::{Args, Parser, Subcommand};
5 
6 /// A fictional versioning CLI
7 #[derive(Debug, Parser)] // requires `derive` feature
8 #[clap(name = "git")]
9 #[clap(about = "A fictional versioning CLI", long_about = None)]
10 struct Cli {
11     #[clap(subcommand)]
12     command: Commands,
13 }
14 
15 #[derive(Debug, Subcommand)]
16 enum Commands {
17     /// Clones repos
18     #[clap(arg_required_else_help = true)]
19     Clone {
20         /// The remote to clone
21         #[clap(value_parser)]
22         remote: String,
23     },
24     /// pushes things
25     #[clap(arg_required_else_help = true)]
26     Push {
27         /// The remote to target
28         #[clap(value_parser)]
29         remote: String,
30     },
31     /// adds things
32     #[clap(arg_required_else_help = true)]
33     Add {
34         /// Stuff to add
35         #[clap(required = true, value_parser)]
36         path: Vec<PathBuf>,
37     },
38     Stash(Stash),
39     #[clap(external_subcommand)]
40     External(Vec<OsString>),
41 }
42 
43 #[derive(Debug, Args)]
44 #[clap(args_conflicts_with_subcommands = true)]
45 struct Stash {
46     #[clap(subcommand)]
47     command: Option<StashCommands>,
48 
49     #[clap(flatten)]
50     push: StashPush,
51 }
52 
53 #[derive(Debug, Subcommand)]
54 enum StashCommands {
55     Push(StashPush),
56     Pop {
57         #[clap(value_parser)]
58         stash: Option<String>,
59     },
60     Apply {
61         #[clap(value_parser)]
62         stash: Option<String>,
63     },
64 }
65 
66 #[derive(Debug, Args)]
67 struct StashPush {
68     #[clap(short, long, value_parser)]
69     message: Option<String>,
70 }
71 
main()72 fn main() {
73     let args = Cli::parse();
74 
75     match args.command {
76         Commands::Clone { remote } => {
77             println!("Cloning {}", remote);
78         }
79         Commands::Push { remote } => {
80             println!("Pushing to {}", remote);
81         }
82         Commands::Add { path } => {
83             println!("Adding {:?}", path);
84         }
85         Commands::Stash(stash) => {
86             let stash_cmd = stash.command.unwrap_or(StashCommands::Push(stash.push));
87             match stash_cmd {
88                 StashCommands::Push(push) => {
89                     println!("Pushing {:?}", push);
90                 }
91                 StashCommands::Pop { stash } => {
92                     println!("Popping {:?}", stash);
93                 }
94                 StashCommands::Apply { stash } => {
95                     println!("Applying {:?}", stash);
96                 }
97             }
98         }
99         Commands::External(args) => {
100             println!("Calling out to {:?} with {:?}", &args[0], &args[1..]);
101         }
102     }
103 
104     // Continued program logic goes here...
105 }
106