1use clap::{Parser, Subcommand, ValueEnum};
2
3#[derive(Parser)]
4#[command(
5 name = "winbrew",
6 version = concat!(env!("CARGO_PKG_VERSION"), " (", env!("WINBREW_GIT_HASH"), ")"),
7 about = "A modern package manager for Windows that tracks and cleanly removes software.",
8 arg_required_else_help = true
9)]
10pub struct Cli {
11 #[arg(short, long, global = true, action = clap::ArgAction::Count, help_heading = "Output")]
13 pub verbose: u8,
14
15 #[command(subcommand)]
16 pub command: Command,
17}
18
19#[derive(Debug, PartialEq, Eq, Subcommand)]
20pub enum Command {
21 List {
23 #[arg(value_name = "QUERY", num_args = 0..)]
24 query: Vec<String>,
25 },
26
27 Search {
29 #[arg(value_name = "QUERY", num_args = 1..)]
30 query: Vec<String>,
31 },
32
33 Install {
36 #[arg(value_name = "QUERY", num_args = 1..)]
37 query: Vec<String>,
38
39 #[arg(long, help_heading = "Safety")]
40 ignore_checksum_security: bool,
41
42 #[arg(long, help_heading = "Output")]
44 plan: bool,
45 },
46
47 Info,
49
50 Version,
52
53 Doctor {
55 #[arg(long, help_heading = "Output")]
57 json: bool,
58
59 #[arg(long, help_heading = "Output")]
61 warn_as_error: bool,
62 },
63
64 Update,
66
67 Remove {
69 #[arg(value_name = "PACKAGE", num_args = 1.., required = true)]
70 name: Vec<String>,
71
72 #[arg(long, short = 'y', help_heading = "Safety")]
73 yes: bool,
74
75 #[arg(long, help_heading = "Safety")]
76 force: bool,
77 },
78
79 Repair {
81 #[arg(long, short = 'y', help_heading = "Safety")]
83 yes: bool,
84 },
85
86 Config {
98 #[command(subcommand)]
99 command: ConfigCommand,
100 },
101
102 Completions {
104 #[arg(value_enum)]
105 shell: CompletionShell,
106 },
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
110pub enum CompletionShell {
111 Bash,
112 Fish,
113 Zsh,
114 #[value(name = "powershell")]
115 PowerShell,
116}
117
118#[derive(Debug, PartialEq, Eq, Subcommand)]
119pub enum ConfigCommand {
131 List,
133
134 Get {
136 #[arg(value_name = "KEY")]
137 key: String,
138 },
139
140 Set {
142 #[arg(value_name = "KEY")]
143 key: String,
144
145 #[arg(value_name = "VALUE")]
146 value: Option<String>,
147 },
148
149 Unset {
151 #[arg(value_name = "KEY")]
152 key: String,
153 },
154}
155
156#[cfg(test)]
157mod tests {
158 use super::{Cli, Command, ConfigCommand};
159 use clap::Parser;
160
161 #[test]
162 fn parse_verbose_doctor() {
163 let cli = Cli::parse_from(["brew", "doctor", "-vv"]);
164
165 assert_eq!(cli.verbose, 2);
166 assert_eq!(
167 cli.command,
168 Command::Doctor {
169 json: false,
170 warn_as_error: false,
171 }
172 );
173 }
174
175 #[test]
176 fn parse_config_unset_core_log_level() {
177 let cli = Cli::parse_from(["brew", "config", "unset", "core.log_level"]);
178
179 assert_eq!(
180 cli.command,
181 Command::Config {
182 command: ConfigCommand::Unset {
183 key: "core.log_level".to_string(),
184 },
185 }
186 );
187 }
188
189 #[test]
190 fn parse_doctor() {
191 let cli = Cli::parse_from(["brew", "doctor"]);
192
193 assert_eq!(
194 cli.command,
195 Command::Doctor {
196 json: false,
197 warn_as_error: false,
198 }
199 );
200 }
201
202 #[test]
203 fn parse_doctor_json() {
204 let cli = Cli::parse_from(["brew", "doctor", "--json"]);
205
206 assert_eq!(
207 cli.command,
208 Command::Doctor {
209 json: true,
210 warn_as_error: false,
211 }
212 );
213 }
214
215 #[test]
216 fn parse_doctor_warn_as_error() {
217 let cli = Cli::parse_from(["brew", "doctor", "--warn-as-error"]);
218
219 assert_eq!(
220 cli.command,
221 Command::Doctor {
222 json: false,
223 warn_as_error: true,
224 }
225 );
226 }
227}