• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use clap::error::ErrorKind;
2 use clap::{CommandFactory, Parser};
3 
4 #[derive(Parser)]
5 #[command(author, version, about, long_about = None)]
6 struct Cli {
7     /// set version manually
8     #[arg(long, value_name = "VER")]
9     set_ver: Option<String>,
10 
11     /// auto inc major
12     #[arg(long)]
13     major: bool,
14 
15     /// auto inc minor
16     #[arg(long)]
17     minor: bool,
18 
19     /// auto inc patch
20     #[arg(long)]
21     patch: bool,
22 
23     /// some regular input
24     input_file: Option<String>,
25 
26     /// some special input argument
27     #[arg(long)]
28     spec_in: Option<String>,
29 
30     #[arg(short)]
31     config: Option<String>,
32 }
33 
main()34 fn main() {
35     let cli = Cli::parse();
36 
37     // Let's assume the old version 1.2.3
38     let mut major = 1;
39     let mut minor = 2;
40     let mut patch = 3;
41 
42     // See if --set-ver was used to set the version manually
43     let version = if let Some(ver) = cli.set_ver.as_deref() {
44         if cli.major || cli.minor || cli.patch {
45             let mut cmd = Cli::command();
46             cmd.error(
47                 ErrorKind::ArgumentConflict,
48                 "Can't do relative and absolute version change",
49             )
50             .exit();
51         }
52         ver.to_string()
53     } else {
54         // Increment the one requested (in a real program, we'd reset the lower numbers)
55         let (maj, min, pat) = (cli.major, cli.minor, cli.patch);
56         match (maj, min, pat) {
57             (true, false, false) => major += 1,
58             (false, true, false) => minor += 1,
59             (false, false, true) => patch += 1,
60             _ => {
61                 let mut cmd = Cli::command();
62                 cmd.error(
63                     ErrorKind::ArgumentConflict,
64                     "Can only modify one version field",
65                 )
66                 .exit();
67             }
68         };
69         format!("{major}.{minor}.{patch}")
70     };
71 
72     println!("Version: {version}");
73 
74     // Check for usage of -c
75     if let Some(config) = cli.config.as_deref() {
76         let input = cli
77             .input_file
78             .as_deref()
79             // 'or' is preferred to 'or_else' here since `Option::as_deref` is 'const'
80             .or(cli.spec_in.as_deref())
81             .unwrap_or_else(|| {
82                 let mut cmd = Cli::command();
83                 cmd.error(
84                     ErrorKind::MissingRequiredArgument,
85                     "INPUT_FILE or --spec-in is required when using --config",
86                 )
87                 .exit()
88             });
89         println!("Doing work using input {input} and config {config}");
90     }
91 }
92