• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::utils;
2 
3 use std::io::Write;
4 use std::str;
5 
6 use clap::{Arg, Command};
7 
8 static SCF2OP: &str = "flag present 2 times
9 option NOT present
10 positional NOT present
11 flag2 NOT present
12 option2 maybe present with value of: Nothing
13 positional2 maybe present with value of: Nothing
14 option3 NOT present
15 positional3 NOT present
16 option NOT present
17 positional NOT present
18 subcmd present
19 flag present 2 times
20 scoption present with value: some
21 An scoption: some
22 scpositional present with value: value
23 ";
24 
25 static SCFOP: &str = "flag present 1 times
26 option NOT present
27 positional NOT present
28 flag2 NOT present
29 option2 maybe present with value of: Nothing
30 positional2 maybe present with value of: Nothing
31 option3 NOT present
32 positional3 NOT present
33 option NOT present
34 positional NOT present
35 subcmd present
36 flag present 1 times
37 scoption present with value: some
38 An scoption: some
39 scpositional present with value: value
40 ";
41 
42 static O2P: &str = "flag NOT present
43 option present with value: some
44 An option: some
45 An option: other
46 positional present with value: value
47 flag2 NOT present
48 option2 maybe present with value of: Nothing
49 positional2 maybe present with value of: Nothing
50 option3 NOT present
51 positional3 NOT present
52 option present with value: some
53 An option: some
54 An option: other
55 positional present with value: value
56 subcmd NOT present
57 ";
58 
59 static F2OP: &str = "flag present 2 times
60 option present with value: some
61 An option: some
62 positional present with value: value
63 flag2 NOT present
64 option2 maybe present with value of: Nothing
65 positional2 maybe present with value of: Nothing
66 option3 NOT present
67 positional3 NOT present
68 option present with value: some
69 An option: some
70 positional present with value: value
71 subcmd NOT present
72 ";
73 
74 static FOP: &str = "flag present 1 times
75 option present with value: some
76 An option: some
77 positional present with value: value
78 flag2 NOT present
79 option2 maybe present with value of: Nothing
80 positional2 maybe present with value of: Nothing
81 option3 NOT present
82 positional3 NOT present
83 option present with value: some
84 An option: some
85 positional present with value: value
86 subcmd NOT present
87 ";
88 
check_complex_output(args: &str, out: &str)89 pub fn check_complex_output(args: &str, out: &str) {
90     let mut w = vec![];
91     let matches = utils::complex_app()
92         .try_get_matches_from(args.split(' ').collect::<Vec<_>>())
93         .unwrap();
94     match matches.get_one::<u8>("flag").unwrap() {
95         0 => {
96             writeln!(w, "flag NOT present").unwrap();
97         }
98         n => {
99             writeln!(w, "flag present {} times", n).unwrap();
100         }
101     }
102 
103     if matches.contains_id("option") {
104         if let Some(v) = matches.get_one::<String>("option").map(|v| v.as_str()) {
105             writeln!(w, "option present with value: {}", v).unwrap();
106         }
107         if let Some(ov) = matches.get_many::<String>("option") {
108             for o in ov {
109                 writeln!(w, "An option: {}", o).unwrap();
110             }
111         }
112     } else {
113         writeln!(w, "option NOT present").unwrap();
114     }
115 
116     if let Some(p) = matches.get_one::<String>("positional").map(|v| v.as_str()) {
117         writeln!(w, "positional present with value: {}", p).unwrap();
118     } else {
119         writeln!(w, "positional NOT present").unwrap();
120     }
121 
122     if *matches.get_one::<bool>("flag2").expect("defaulted by clap") {
123         writeln!(w, "flag2 present").unwrap();
124         writeln!(
125             w,
126             "option2 present with value of: {}",
127             matches
128                 .get_one::<String>("long-option-2")
129                 .map(|v| v.as_str())
130                 .unwrap()
131         )
132         .unwrap();
133         writeln!(
134             w,
135             "positional2 present with value of: {}",
136             matches
137                 .get_one::<String>("positional2")
138                 .map(|v| v.as_str())
139                 .unwrap()
140         )
141         .unwrap();
142     } else {
143         writeln!(w, "flag2 NOT present").unwrap();
144         writeln!(
145             w,
146             "option2 maybe present with value of: {}",
147             matches
148                 .get_one::<String>("long-option-2")
149                 .map(|v| v.as_str())
150                 .unwrap_or("Nothing")
151         )
152         .unwrap();
153         writeln!(
154             w,
155             "positional2 maybe present with value of: {}",
156             matches
157                 .get_one::<String>("positional2")
158                 .map(|v| v.as_str())
159                 .unwrap_or("Nothing")
160         )
161         .unwrap();
162     }
163 
164     let _ = match matches
165         .get_one::<String>("option3")
166         .map(|v| v.as_str())
167         .unwrap_or("")
168     {
169         "fast" => writeln!(w, "option3 present quickly"),
170         "slow" => writeln!(w, "option3 present slowly"),
171         _ => writeln!(w, "option3 NOT present"),
172     };
173 
174     let _ = match matches
175         .get_one::<String>("positional3")
176         .map(|v| v.as_str())
177         .unwrap_or("")
178     {
179         "vi" => writeln!(w, "positional3 present in vi mode"),
180         "emacs" => writeln!(w, "positional3 present in emacs mode"),
181         _ => writeln!(w, "positional3 NOT present"),
182     };
183 
184     if matches.contains_id("option") {
185         if let Some(v) = matches.get_one::<String>("option").map(|v| v.as_str()) {
186             writeln!(w, "option present with value: {}", v).unwrap();
187         }
188         if let Some(ov) = matches.get_many::<String>("option") {
189             for o in ov {
190                 writeln!(w, "An option: {}", o).unwrap();
191             }
192         }
193     } else {
194         writeln!(w, "option NOT present").unwrap();
195     }
196 
197     if let Some(p) = matches.get_one::<String>("positional").map(|v| v.as_str()) {
198         writeln!(w, "positional present with value: {p}").unwrap();
199     } else {
200         writeln!(w, "positional NOT present").unwrap();
201     }
202     if let Some("subcmd") = matches.subcommand_name() {
203         writeln!(w, "subcmd present").unwrap();
204         if let Some(matches) = matches.subcommand_matches("subcmd") {
205             match matches.get_one::<u8>("flag").unwrap() {
206                 0 => {
207                     writeln!(w, "flag NOT present").unwrap();
208                 }
209                 n => {
210                     writeln!(w, "flag present {n} times").unwrap();
211                 }
212             }
213 
214             if matches.contains_id("option") {
215                 if let Some(v) = matches.get_one::<String>("option").map(|v| v.as_str()) {
216                     writeln!(w, "scoption present with value: {v}").unwrap();
217                 }
218                 if let Some(ov) = matches.get_many::<String>("option") {
219                     for o in ov {
220                         writeln!(w, "An scoption: {o}").unwrap();
221                     }
222                 }
223             } else {
224                 writeln!(w, "scoption NOT present").unwrap();
225             }
226 
227             if let Some(p) = matches
228                 .get_one::<String>("scpositional")
229                 .map(|v| v.as_str())
230             {
231                 writeln!(w, "scpositional present with value: {p}").unwrap();
232             }
233         }
234     } else {
235         writeln!(w, "subcmd NOT present").unwrap();
236     }
237 
238     let res = str::from_utf8(&w).unwrap();
239     snapbox::assert_eq(out, res);
240 }
241 
242 #[test]
create_app()243 fn create_app() {
244     let _ = Command::new("test")
245         .version("1.0")
246         .author("kevin")
247         .about("does awesome things")
248         .try_get_matches_from(vec![""])
249         .unwrap();
250 }
251 
252 #[test]
add_multiple_arg()253 fn add_multiple_arg() {
254     let _ = Command::new("test")
255         .args([Arg::new("test").short('s'), Arg::new("test2").short('l')])
256         .try_get_matches_from(vec![""])
257         .unwrap();
258 }
259 #[test]
flag_x2_opt()260 fn flag_x2_opt() {
261     check_complex_output(
262         "clap-test value -f -f -o some",
263         "flag present 2 times
264 option present with value: some
265 An option: some
266 positional present with value: value
267 flag2 NOT present
268 option2 maybe present with value of: Nothing
269 positional2 maybe present with value of: Nothing
270 option3 NOT present
271 positional3 NOT present
272 option present with value: some
273 An option: some
274 positional present with value: value
275 subcmd NOT present
276 ",
277     );
278 }
279 
280 #[test]
long_opt_x2_pos()281 fn long_opt_x2_pos() {
282     check_complex_output("clap-test value --option some --option other", O2P);
283 }
284 
285 #[test]
long_opt_eq_x2_pos()286 fn long_opt_eq_x2_pos() {
287     check_complex_output("clap-test value --option=some --option=other", O2P);
288 }
289 
290 #[test]
short_opt_x2_pos()291 fn short_opt_x2_pos() {
292     check_complex_output("clap-test value -o some -o other", O2P);
293 }
294 
295 #[test]
short_opt_eq_x2_pos()296 fn short_opt_eq_x2_pos() {
297     check_complex_output("clap-test value -o=some -o=other", O2P);
298 }
299 
300 #[test]
short_flag_x2_comb_short_opt_pos()301 fn short_flag_x2_comb_short_opt_pos() {
302     check_complex_output("clap-test value -ff -o some", F2OP);
303 }
304 
305 #[test]
short_flag_short_opt_pos()306 fn short_flag_short_opt_pos() {
307     check_complex_output("clap-test value -f -o some", FOP);
308 }
309 
310 #[test]
long_flag_long_opt_pos()311 fn long_flag_long_opt_pos() {
312     check_complex_output("clap-test value --flag --option some", FOP);
313 }
314 
315 #[test]
long_flag_long_opt_eq_pos()316 fn long_flag_long_opt_eq_pos() {
317     check_complex_output("clap-test value --flag --option=some", FOP);
318 }
319 
320 #[test]
sc_long_flag_long_opt()321 fn sc_long_flag_long_opt() {
322     check_complex_output("clap-test subcmd value --flag --option some", SCFOP);
323 }
324 
325 #[test]
sc_long_flag_short_opt_pos()326 fn sc_long_flag_short_opt_pos() {
327     check_complex_output("clap-test subcmd value --flag -o some", SCFOP);
328 }
329 
330 #[test]
sc_long_flag_long_opt_eq_pos()331 fn sc_long_flag_long_opt_eq_pos() {
332     check_complex_output("clap-test subcmd value --flag --option=some", SCFOP);
333 }
334 
335 #[test]
sc_short_flag_long_opt_pos()336 fn sc_short_flag_long_opt_pos() {
337     check_complex_output("clap-test subcmd value -f --option some", SCFOP);
338 }
339 
340 #[test]
sc_short_flag_short_opt_pos()341 fn sc_short_flag_short_opt_pos() {
342     check_complex_output("clap-test subcmd value -f -o some", SCFOP);
343 }
344 
345 #[test]
sc_short_flag_short_opt_eq_pos()346 fn sc_short_flag_short_opt_eq_pos() {
347     check_complex_output("clap-test subcmd value -f -o=some", SCFOP);
348 }
349 
350 #[test]
sc_short_flag_long_opt_eq_pos()351 fn sc_short_flag_long_opt_eq_pos() {
352     check_complex_output("clap-test subcmd value -f --option=some", SCFOP);
353 }
354 
355 #[test]
sc_short_flag_x2_comb_long_opt_pos()356 fn sc_short_flag_x2_comb_long_opt_pos() {
357     check_complex_output("clap-test subcmd value -ff --option some", SCF2OP);
358 }
359 
360 #[test]
sc_short_flag_x2_comb_short_opt_pos()361 fn sc_short_flag_x2_comb_short_opt_pos() {
362     check_complex_output("clap-test subcmd value -ff -o some", SCF2OP);
363 }
364 
365 #[test]
sc_short_flag_x2_comb_long_opt_eq_pos()366 fn sc_short_flag_x2_comb_long_opt_eq_pos() {
367     check_complex_output("clap-test subcmd value -ff --option=some", SCF2OP);
368 }
369 
370 #[test]
sc_short_flag_x2_comb_short_opt_eq_pos()371 fn sc_short_flag_x2_comb_short_opt_eq_pos() {
372     check_complex_output("clap-test subcmd value -ff -o=some", SCF2OP);
373 }
374 
375 #[test]
sc_long_flag_x2_long_opt_pos()376 fn sc_long_flag_x2_long_opt_pos() {
377     check_complex_output("clap-test subcmd value --flag --flag --option some", SCF2OP);
378 }
379 
380 #[test]
sc_long_flag_x2_short_opt_pos()381 fn sc_long_flag_x2_short_opt_pos() {
382     check_complex_output("clap-test subcmd value --flag --flag -o some", SCF2OP);
383 }
384 
385 #[test]
sc_long_flag_x2_short_opt_eq_pos()386 fn sc_long_flag_x2_short_opt_eq_pos() {
387     check_complex_output("clap-test subcmd value --flag --flag -o=some", SCF2OP);
388 }
389 
390 #[test]
sc_long_flag_x2_long_opt_eq_pos()391 fn sc_long_flag_x2_long_opt_eq_pos() {
392     check_complex_output("clap-test subcmd value --flag --flag --option=some", SCF2OP);
393 }
394 
395 #[test]
sc_short_flag_x2_long_opt_pos()396 fn sc_short_flag_x2_long_opt_pos() {
397     check_complex_output("clap-test subcmd value -f -f --option some", SCF2OP);
398 }
399 
400 #[test]
sc_short_flag_x2_short_opt_pos()401 fn sc_short_flag_x2_short_opt_pos() {
402     check_complex_output("clap-test subcmd value -f -f -o some", SCF2OP);
403 }
404 
405 #[test]
sc_short_flag_x2_short_opt_eq_pos()406 fn sc_short_flag_x2_short_opt_eq_pos() {
407     check_complex_output("clap-test subcmd value -f -f -o=some", SCF2OP);
408 }
409 
410 #[test]
sc_short_flag_x2_long_opt_eq_pos()411 fn sc_short_flag_x2_long_opt_eq_pos() {
412     check_complex_output("clap-test subcmd value -f -f --option=some", SCF2OP);
413 }
414 
415 #[test]
mut_arg_all()416 fn mut_arg_all() {
417     let mut cmd = utils::complex_app();
418     let arg_names = cmd
419         .get_arguments()
420         .map(|a| a.get_id().clone())
421         .filter(|a| a != "version" && a != "help")
422         .collect::<Vec<_>>();
423 
424     for arg_name in arg_names {
425         cmd = cmd.mut_arg(arg_name, |arg| arg.hide_possible_values(true));
426     }
427 }
428 
429 #[test]
mut_subcommand_all()430 fn mut_subcommand_all() {
431     let cmd = utils::complex_app();
432 
433     assert_eq!(
434         cmd.find_subcommand("subcmd")
435             .unwrap()
436             .is_disable_version_flag_set(),
437         false
438     );
439     let cmd = cmd.mut_subcommand("subcmd", |subcmd| subcmd.disable_version_flag(true));
440     assert_eq!(
441         cmd.find_subcommand("subcmd")
442             .unwrap()
443             .is_disable_version_flag_set(),
444         true
445     );
446 }
447 
448 #[test]
mut_subcommand_with_alias_resolve()449 fn mut_subcommand_with_alias_resolve() {
450     let mut cmd =
451         Command::new("foo").subcommand(Command::new("bar").alias("baz").about("test subcmd"));
452     assert_eq!(
453         cmd.find_subcommand("baz")
454             .unwrap()
455             .get_about()
456             .unwrap()
457             .to_string(),
458         "test subcmd"
459     );
460 
461     let true_name = cmd.find_subcommand("baz").unwrap().get_name().to_string();
462     assert_eq!(true_name, "bar");
463 
464     cmd = cmd.mut_subcommand(&*true_name, |subcmd| subcmd.about("modified about"));
465     assert_eq!(
466         cmd.find_subcommand("baz")
467             .unwrap()
468             .get_about()
469             .unwrap()
470             .to_string(),
471         "modified about"
472     );
473 }
474 
475 #[test]
issue_3669_command_build_recurses()476 fn issue_3669_command_build_recurses() {
477     let mut cmd = Command::new("ctest").subcommand(
478         Command::new("subcmd").subcommand(
479             Command::new("multi")
480                 .about("tests subcommands")
481                 .author("Kevin K. <kbknapp@gmail.com>")
482                 .version("0.1")
483                 .arg(clap::arg!(
484                     <FLAG>                    "tests flags"
485                 )),
486         ),
487     );
488     cmd.build();
489 }
490