04_04_custom_derive/
04_04_custom.rs1use clap::error::ErrorKind;
2use clap::{CommandFactory, Parser};
3
4#[derive(Parser)]
5#[command(version, about, long_about = None)]
6struct Cli {
7 #[arg(long, value_name = "VER")]
9 set_ver: Option<String>,
10
11 #[arg(long)]
13 major: bool,
14
15 #[arg(long)]
17 minor: bool,
18
19 #[arg(long)]
21 patch: bool,
22
23 input_file: Option<String>,
25
26 #[arg(long)]
28 spec_in: Option<String>,
29
30 #[arg(short)]
31 config: Option<String>,
32}
33
34fn main() {
35 let cli = Cli::parse();
36
37 let mut major = 1;
39 let mut minor = 2;
40 let mut patch = 3;
41
42 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 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 if let Some(config) = cli.config.as_deref() {
76 let input = cli
77 .input_file
78 .as_deref()
79 .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}