1 #![cfg(feature = "help")]
2
3 use clap::{arg, builder::PossibleValue, error::ErrorKind, Arg, ArgAction, ArgGroup, Command};
4
5 use super::utils;
6
setup() -> Command7 fn setup() -> Command {
8 Command::new("test")
9 .author("Kevin K.")
10 .about("tests stuff")
11 .version("1.3")
12 }
13
empty_args() -> impl IntoIterator<Item = String>14 fn empty_args() -> impl IntoIterator<Item = String> {
15 std::iter::empty()
16 }
17
18 #[test]
help_short()19 fn help_short() {
20 let m = setup().try_get_matches_from(vec!["myprog", "-h"]);
21
22 assert!(m.is_err());
23 assert_eq!(m.unwrap_err().kind(), ErrorKind::DisplayHelp);
24 }
25
26 #[test]
help_long()27 fn help_long() {
28 let m = setup().try_get_matches_from(vec!["myprog", "--help"]);
29
30 assert!(m.is_err());
31 assert_eq!(m.unwrap_err().kind(), ErrorKind::DisplayHelp);
32 }
33
34 #[test]
help_no_subcommand()35 fn help_no_subcommand() {
36 let m = setup().try_get_matches_from(vec!["myprog", "help"]);
37
38 assert!(m.is_err());
39 assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
40 }
41
42 #[test]
help_subcommand()43 fn help_subcommand() {
44 let m = setup()
45 .subcommand(
46 Command::new("test")
47 .about("tests things")
48 .arg(arg!(-v --verbose "with verbosity")),
49 )
50 .try_get_matches_from(vec!["myprog", "help"]);
51
52 assert!(m.is_err());
53 assert_eq!(m.unwrap_err().kind(), ErrorKind::DisplayHelp);
54 }
55
56 #[test]
57 #[cfg(feature = "error-context")]
help_multi_subcommand_error()58 fn help_multi_subcommand_error() {
59 let cmd = Command::new("ctest").subcommand(
60 Command::new("subcmd").subcommand(
61 Command::new("multi")
62 .about("tests subcommands")
63 .author("Kevin K. <kbknapp@gmail.com>")
64 .version("0.1")
65 .arg(arg!(
66 -f --flag "tests flags"
67 ))
68 .arg(
69 arg!(
70 -o --option <scoption> "tests options"
71 )
72 .required(false)
73 .num_args(1..)
74 .action(ArgAction::Append),
75 ),
76 ),
77 );
78 let err = cmd
79 .try_get_matches_from(["ctest", "help", "subcmd", "multi", "foo"])
80 .unwrap_err();
81
82 static EXPECTED: &str = "error: unrecognized subcommand 'foo'
83
84 Usage: ctest subcmd multi [OPTIONS]
85
86 For more information, try '--help'.
87 ";
88 utils::assert_eq(EXPECTED, err.to_string());
89 }
90
91 #[test]
req_last_arg_usage()92 fn req_last_arg_usage() {
93 static LAST_ARG_REQ_MULT: &str = "\
94 Usage: example <FIRST>... -- <SECOND>...
95
96 Arguments:
97 <FIRST>... First
98 <SECOND>... Second
99
100 Options:
101 -h, --help Print help
102 -V, --version Print version
103 ";
104
105 let cmd = Command::new("example")
106 .version("1.0")
107 .arg(Arg::new("FIRST").help("First").num_args(1..).required(true))
108 .arg(
109 Arg::new("SECOND")
110 .help("Second")
111 .num_args(1..)
112 .required(true)
113 .last(true),
114 );
115 utils::assert_output(cmd, "example --help", LAST_ARG_REQ_MULT, false);
116 }
117
118 #[test]
args_with_last_usage()119 fn args_with_last_usage() {
120 static LAST_ARG_USAGE: &str = "\
121 Usage: flamegraph [OPTIONS] [BINFILE] [-- <ARGS>...]
122
123 Arguments:
124 [BINFILE] The path of the binary to be profiled. for a binary.
125 [ARGS]... Any arguments you wish to pass to the being profiled.
126
127 Options:
128 -v, --verbose Prints out more stuff.
129 -t, --timeout <SECONDS> Timeout in seconds.
130 -f, --frequency <HERTZ> The sampling frequency.
131 -h, --help Print help
132 -V, --version Print version
133 ";
134
135 let cmd = Command::new("flamegraph")
136 .version("0.1")
137 .arg(
138 Arg::new("verbose")
139 .help("Prints out more stuff.")
140 .short('v')
141 .long("verbose")
142 .action(ArgAction::SetTrue),
143 )
144 .arg(
145 Arg::new("timeout")
146 .help("Timeout in seconds.")
147 .short('t')
148 .long("timeout")
149 .value_name("SECONDS"),
150 )
151 .arg(
152 Arg::new("frequency")
153 .help("The sampling frequency.")
154 .short('f')
155 .long("frequency")
156 .value_name("HERTZ"),
157 )
158 .arg(
159 Arg::new("binary path")
160 .help("The path of the binary to be profiled. for a binary.")
161 .value_name("BINFILE"),
162 )
163 .arg(
164 Arg::new("pass through args")
165 .help("Any arguments you wish to pass to the being profiled.")
166 .action(ArgAction::Set)
167 .num_args(1..)
168 .last(true)
169 .value_name("ARGS"),
170 );
171 utils::assert_output(cmd, "flamegraph --help", LAST_ARG_USAGE, false);
172 }
173
174 #[test]
subcommand_short_help()175 fn subcommand_short_help() {
176 let m = utils::complex_app().try_get_matches_from(vec!["clap-test", "subcmd", "-h"]);
177
178 assert!(m.is_err());
179 assert_eq!(m.unwrap_err().kind(), ErrorKind::DisplayHelp);
180 }
181
182 #[test]
subcommand_long_help()183 fn subcommand_long_help() {
184 let m = utils::complex_app().try_get_matches_from(vec!["clap-test", "subcmd", "--help"]);
185
186 assert!(m.is_err());
187 assert_eq!(m.unwrap_err().kind(), ErrorKind::DisplayHelp);
188 }
189
190 #[test]
subcommand_help_rev()191 fn subcommand_help_rev() {
192 let m = utils::complex_app().try_get_matches_from(vec!["clap-test", "help", "subcmd"]);
193
194 assert!(m.is_err());
195 assert_eq!(m.unwrap_err().kind(), ErrorKind::DisplayHelp);
196 }
197
198 #[test]
complex_help_output()199 fn complex_help_output() {
200 static HELP: &str = "\
201 clap-test v1.4.8
202 Kevin K. <kbknapp@gmail.com>
203 tests clap library
204
205 Usage: clap-test [OPTIONS] [positional] [positional2] [positional3]... [COMMAND]
206
207 Commands:
208 subcmd tests subcommands
209 help Print this message or the help of the given subcommand(s)
210
211 Arguments:
212 [positional] tests positionals
213 [positional2] tests positionals with exclusions
214 [positional3]... tests specific values [possible values: vi, emacs]
215
216 Options:
217 -o, --option <opt>... tests options
218 -f, --flag... tests flags
219 -F tests flags with exclusions
220 --long-option-2 <option2> tests long options with exclusions
221 -O, --option3 <option3> specific vals [possible values: fast, slow]
222 --multvals <one> <two> Tests multiple values, not mult occs
223 --multvalsmo <one> <two> Tests multiple values, and mult occs
224 --minvals2 <minvals> <minvals>... Tests 2 min vals
225 --maxvals3 <maxvals>... Tests 3 max vals
226 --optvaleq[=<optval>] Tests optional value, require = sign
227 --optvalnoeq [<optval>] Tests optional value
228 -h, --help Print help
229 -V, --version Print version
230 ";
231
232 utils::assert_output(utils::complex_app(), "clap-test --help", HELP, false);
233 }
234
235 #[test]
after_and_before_help_output()236 fn after_and_before_help_output() {
237 static AFTER_HELP: &str = "some text that comes before the help
238
239 tests clap library
240
241 Usage: clap-test
242
243 Options:
244 -h, --help Print help
245 -V, --version Print version
246
247 some text that comes after the help
248 ";
249
250 let cmd = Command::new("clap-test")
251 .version("v1.4.8")
252 .about("tests clap library")
253 .before_help("some text that comes before the help")
254 .after_help("some text that comes after the help");
255 utils::assert_output(cmd.clone(), "clap-test -h", AFTER_HELP, false);
256 utils::assert_output(cmd, "clap-test --help", AFTER_HELP, false);
257 }
258
259 #[test]
after_and_before_long_help_output()260 fn after_and_before_long_help_output() {
261 static AFTER_HELP: &str = "some text that comes before the help
262
263 tests clap library
264
265 Usage: clap-test
266
267 Options:
268 -h, --help Print help (see more with '--help')
269 -V, --version Print version
270
271 some text that comes after the help
272 ";
273
274 static AFTER_LONG_HELP: &str = "some longer text that comes before the help
275
276 tests clap library
277
278 Usage: clap-test
279
280 Options:
281 -h, --help
282 Print help (see a summary with '-h')
283
284 -V, --version
285 Print version
286
287 some longer text that comes after the help
288 ";
289
290 let cmd = Command::new("clap-test")
291 .version("v1.4.8")
292 .about("tests clap library")
293 .before_help("some text that comes before the help")
294 .after_help("some text that comes after the help")
295 .before_long_help("some longer text that comes before the help")
296 .after_long_help("some longer text that comes after the help");
297 utils::assert_output(cmd.clone(), "clap-test --help", AFTER_LONG_HELP, false);
298 utils::assert_output(cmd, "clap-test -h", AFTER_HELP, false);
299 }
300
301 static MULTI_SC_HELP: &str = "\
302 tests subcommands
303
304 Usage: ctest subcmd multi [OPTIONS]
305
306 Options:
307 -f, --flag tests flags
308 -o, --option <scoption>... tests options
309 -h, --help Print help
310 -V, --version Print version
311 ";
312
313 #[test]
multi_level_sc_help()314 fn multi_level_sc_help() {
315 let cmd = Command::new("ctest").subcommand(
316 Command::new("subcmd").subcommand(
317 Command::new("multi")
318 .about("tests subcommands")
319 .author("Kevin K. <kbknapp@gmail.com>")
320 .version("0.1")
321 .arg(arg!(
322 -f --flag "tests flags"
323 ))
324 .arg(
325 arg!(
326 -o --option <scoption> "tests options"
327 )
328 .required(false)
329 .num_args(1..)
330 .action(ArgAction::Append),
331 ),
332 ),
333 );
334 utils::assert_output(cmd, "ctest help subcmd multi", MULTI_SC_HELP, false);
335 }
336
337 #[test]
no_wrap_default_help()338 fn no_wrap_default_help() {
339 static DEFAULT_HELP: &str = "\
340 Usage: ctest
341
342 Options:
343 -h, --help Print help
344 -V, --version Print version
345 ";
346
347 let cmd = Command::new("ctest").version("1.0").term_width(0);
348 utils::assert_output(cmd, "ctest --help", DEFAULT_HELP, false);
349 }
350
351 #[test]
352 #[cfg(feature = "wrap_help")]
wrapped_help()353 fn wrapped_help() {
354 static WRAPPED_HELP: &str = "\
355 Usage: test [OPTIONS]
356
357 Options:
358 -a, --all Also do versioning for private crates (will
359 not be published)
360 --exact Specify inter dependency version numbers
361 exactly with `=`
362 --no-git-commit Do not commit version changes
363 --no-git-push Do not push generated commit and tags to git
364 remote
365 -h, --help Print help
366 ";
367 let cmd = Command::new("test")
368 .term_width(67)
369 .arg(
370 Arg::new("all")
371 .short('a')
372 .long("all")
373 .action(ArgAction::SetTrue)
374 .help("Also do versioning for private crates (will not be published)"),
375 )
376 .arg(
377 Arg::new("exact")
378 .long("exact")
379 .action(ArgAction::SetTrue)
380 .help("Specify inter dependency version numbers exactly with `=`"),
381 )
382 .arg(
383 Arg::new("no_git_commit")
384 .long("no-git-commit")
385 .action(ArgAction::SetTrue)
386 .help("Do not commit version changes"),
387 )
388 .arg(
389 Arg::new("no_git_push")
390 .long("no-git-push")
391 .action(ArgAction::SetTrue)
392 .help("Do not push generated commit and tags to git remote"),
393 );
394 utils::assert_output(cmd, "test --help", WRAPPED_HELP, false);
395 }
396
397 #[test]
398 #[cfg(feature = "wrap_help")]
unwrapped_help()399 fn unwrapped_help() {
400 static UNWRAPPED_HELP: &str = "\
401 Usage: test [OPTIONS]
402
403 Options:
404 -a, --all Also do versioning for private crates (will
405 not be published)
406 --exact Specify inter dependency version numbers
407 exactly with `=`
408 --no-git-commit Do not commit version changes
409 --no-git-push Do not push generated commit and tags to git
410 remote
411 -h, --help Print help
412 ";
413 let cmd = Command::new("test")
414 .term_width(68)
415 .arg(
416 Arg::new("all")
417 .short('a')
418 .long("all")
419 .action(ArgAction::SetTrue)
420 .help("Also do versioning for private crates (will not be published)"),
421 )
422 .arg(
423 Arg::new("exact")
424 .long("exact")
425 .action(ArgAction::SetTrue)
426 .help("Specify inter dependency version numbers exactly with `=`"),
427 )
428 .arg(
429 Arg::new("no_git_commit")
430 .long("no-git-commit")
431 .action(ArgAction::SetTrue)
432 .help("Do not commit version changes"),
433 )
434 .arg(
435 Arg::new("no_git_push")
436 .long("no-git-push")
437 .action(ArgAction::SetTrue)
438 .help("Do not push generated commit and tags to git remote"),
439 );
440 utils::assert_output(cmd, "test --help", UNWRAPPED_HELP, false);
441 }
442
443 #[test]
444 #[cfg(all(feature = "wrap_help"))]
possible_value_wrapped_help()445 fn possible_value_wrapped_help() {
446 static WRAPPED_HELP: &str = "\
447 Usage: test [OPTIONS]
448
449 Options:
450 --possible-values <possible_values>
451 Possible values:
452 - short_name:
453 Long enough help message, barely warrant wrapping
454 - second:
455 Short help gets handled the same
456
457 --possible-values-with-new-line <possible_values_with_new_line>
458 Possible values:
459 - long enough name to trigger new line:
460 Really long enough help message to clearly warrant
461 wrapping believe me
462 - second
463
464 --possible-values-without-new-line <possible_values_without_new_line>
465 Possible values:
466 - name: Short enough help message with no wrapping
467 - second: short help
468
469 -h, --help
470 Print help (see a summary with '-h')
471 ";
472 let cmd = Command::new("test")
473 .term_width(67)
474 .arg(
475 Arg::new("possible_values")
476 .long("possible-values")
477 .action(ArgAction::Set)
478 .value_parser([
479 PossibleValue::new("short_name")
480 .help("Long enough help message, barely warrant wrapping"),
481 PossibleValue::new("second").help("Short help gets handled the same"),
482 ]),
483 )
484 .arg(
485 Arg::new("possible_values_with_new_line")
486 .long("possible-values-with-new-line")
487 .action(ArgAction::Set)
488 .value_parser([
489 PossibleValue::new("long enough name to trigger new line").help(
490 "Really long enough help message to clearly warrant wrapping believe me",
491 ),
492 PossibleValue::new("second"),
493 ]),
494 )
495 .arg(
496 Arg::new("possible_values_without_new_line")
497 .long("possible-values-without-new-line")
498 .action(ArgAction::Set)
499 .value_parser([
500 PossibleValue::new("name").help("Short enough help message with no wrapping"),
501 PossibleValue::new("second").help("short help"),
502 ]),
503 );
504 utils::assert_output(cmd, "test --help", WRAPPED_HELP, false);
505 }
506
507 #[test]
complex_subcommand_help_output()508 fn complex_subcommand_help_output() {
509 static SC_HELP: &str = "clap-test-subcmd 0.1
510 Kevin K. <kbknapp@gmail.com>
511 tests subcommands
512
513 Usage: clap-test subcmd [OPTIONS] [scpositional]
514
515 Arguments:
516 [scpositional] tests positionals
517
518 Options:
519 -o, --option <scoption>... tests options
520 -f, --flag... tests flags
521 -s, --subcmdarg <subcmdarg> tests other args
522 -h, --help Print help
523 -V, --version Print version
524 ";
525
526 let a = utils::complex_app();
527 utils::assert_output(a, "clap-test subcmd --help", SC_HELP, false);
528 }
529
530 #[test]
531 #[cfg(feature = "wrap_help")]
issue_626_unicode_cutoff()532 fn issue_626_unicode_cutoff() {
533 static ISSUE_626_CUTOFF: &str = "\
534 Usage: ctest [OPTIONS]
535
536 Options:
537 -c, --cafe <FILE> A coffeehouse, coffee shop, or café is an
538 establishment which primarily serves hot coffee,
539 related coffee beverages (e.g., café latte,
540 cappuccino, espresso), tea, and other hot
541 beverages. Some coffeehouses also serve cold
542 beverages such as iced coffee and iced tea. Many
543 cafés also serve some type of food, such as light
544 snacks, muffins, or pastries.
545 -h, --help Print help
546 -V, --version Print version
547 ";
548
549 let cmd = Command::new("ctest").version("0.1").term_width(70).arg(
550 Arg::new("cafe")
551 .short('c')
552 .long("cafe")
553 .value_name("FILE")
554 .help(
555 "A coffeehouse, coffee shop, or café is an establishment \
556 which primarily serves hot coffee, related coffee beverages \
557 (e.g., café latte, cappuccino, espresso), tea, and other hot \
558 beverages. Some coffeehouses also serve cold beverages such as \
559 iced coffee and iced tea. Many cafés also serve some type of \
560 food, such as light snacks, muffins, or pastries.",
561 )
562 .action(ArgAction::Set),
563 );
564 utils::assert_output(cmd, "ctest --help", ISSUE_626_CUTOFF, false);
565 }
566
567 static HIDE_POS_VALS: &str = "\
568 Usage: ctest [OPTIONS]
569
570 Options:
571 -p, --pos <VAL> Some vals [possible values: fast, slow]
572 -c, --cafe <FILE> A coffeehouse, coffee shop, or café.
573 -h, --help Print help
574 -V, --version Print version
575 ";
576
577 #[test]
hide_possible_vals()578 fn hide_possible_vals() {
579 let cmd = Command::new("ctest")
580 .version("0.1")
581 .arg(
582 Arg::new("pos")
583 .short('p')
584 .long("pos")
585 .value_name("VAL")
586 .value_parser(["fast", "slow"])
587 .help("Some vals")
588 .action(ArgAction::Set),
589 )
590 .arg(
591 Arg::new("cafe")
592 .short('c')
593 .long("cafe")
594 .value_name("FILE")
595 .hide_possible_values(true)
596 .value_parser(["fast", "slow"])
597 .help("A coffeehouse, coffee shop, or café.")
598 .action(ArgAction::Set),
599 );
600 utils::assert_output(cmd, "ctest --help", HIDE_POS_VALS, false);
601 }
602
603 #[test]
hide_single_possible_val()604 fn hide_single_possible_val() {
605 let cmd = Command::new("ctest")
606 .version("0.1")
607 .arg(
608 Arg::new("pos")
609 .short('p')
610 .long("pos")
611 .value_name("VAL")
612 .value_parser([
613 "fast".into(),
614 "slow".into(),
615 PossibleValue::new("secret speed").hide(true),
616 ])
617 .help("Some vals")
618 .action(ArgAction::Set),
619 )
620 .arg(
621 Arg::new("cafe")
622 .short('c')
623 .long("cafe")
624 .value_name("FILE")
625 .help("A coffeehouse, coffee shop, or café.")
626 .action(ArgAction::Set),
627 );
628 utils::assert_output(cmd, "ctest --help", HIDE_POS_VALS, false);
629 }
630
631 #[test]
possible_vals_with_help()632 fn possible_vals_with_help() {
633 static POS_VALS_HELP: &str = "\
634 Usage: ctest [OPTIONS]
635
636 Options:
637 -p, --pos <VAL>
638 Some vals
639
640 Possible values:
641 - fast
642 - slow: not as fast
643
644 -c, --cafe <FILE>
645 A coffeehouse, coffee shop, or café.
646
647 -h, --help
648 Print help (see a summary with '-h')
649
650 -V, --version
651 Print version
652 ";
653 let app = Command::new("ctest")
654 .version("0.1")
655 .arg(
656 Arg::new("pos")
657 .short('p')
658 .long("pos")
659 .value_name("VAL")
660 .value_parser([
661 PossibleValue::new("fast"),
662 PossibleValue::new("slow").help("not as fast"),
663 PossibleValue::new("secret speed").hide(true),
664 ])
665 .help("Some vals")
666 .action(ArgAction::Set),
667 )
668 .arg(
669 Arg::new("cafe")
670 .short('c')
671 .long("cafe")
672 .value_name("FILE")
673 .help("A coffeehouse, coffee shop, or café.")
674 .action(ArgAction::Set),
675 );
676 utils::assert_output(app, "ctest --help", POS_VALS_HELP, false);
677 }
678
679 #[test]
hidden_possible_vals()680 fn hidden_possible_vals() {
681 static POS_VALS_HELP: &str = "\
682 Usage: ctest [pos]
683
684 Arguments:
685 [pos]
686
687 Options:
688 -h, --help Print help
689 ";
690 let app = Command::new("ctest").arg(
691 Arg::new("pos")
692 .hide_possible_values(true)
693 .value_parser([
694 PossibleValue::new("fast"),
695 PossibleValue::new("slow").help("not as fast"),
696 ])
697 .action(ArgAction::Set),
698 );
699 utils::assert_output(app, "ctest --help", POS_VALS_HELP, false);
700 }
701
702 #[test]
703 #[cfg(feature = "wrap_help")]
issue_626_panic()704 fn issue_626_panic() {
705 static ISSUE_626_PANIC: &str = "\
706 Usage: ctest [OPTIONS]
707
708 Options:
709 -c, --cafe <FILE>
710 La culture du café est très développée
711 dans de nombreux pays à climat chaud
712 d\'Amérique, d\'Afrique et d\'Asie, dans des
713 plantations qui sont cultivées pour les
714 marchés d\'exportation. Le café est souvent
715 une contribution majeure aux exportations
716 des régions productrices.
717 -h, --help
718 Print help
719 -V, --version
720 Print version
721 ";
722
723 let cmd = Command::new("ctest")
724 .version("0.1")
725 .term_width(52)
726 .arg(Arg::new("cafe")
727 .short('c')
728 .long("cafe")
729 .value_name("FILE")
730 .help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
731 d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
732 Le café est souvent une contribution majeure aux exportations des régions productrices.")
733 .action(ArgAction::Set));
734 utils::assert_output(cmd, "ctest --help", ISSUE_626_PANIC, false);
735 }
736
737 #[test]
738 #[cfg(feature = "wrap_help")]
issue_626_variable_panic()739 fn issue_626_variable_panic() {
740 for i in 10..320 {
741 let _ = Command::new("ctest")
742 .version("0.1")
743 .term_width(i)
744 .arg(Arg::new("cafe")
745 .short('c')
746 .long("cafe")
747 .value_name("FILE")
748 .help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
749 d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
750 Le café est souvent une contribution majeure aux exportations des régions productrices.")
751 .action(ArgAction::Set))
752 .try_get_matches_from(vec!["ctest", "--help"]);
753 }
754 }
755
756 #[test]
757 #[cfg(feature = "wrap_help")]
final_word_wrapping()758 fn final_word_wrapping() {
759 static FINAL_WORD_WRAPPING: &str = "\
760 Usage: ctest
761
762 Options:
763 -h, --help
764 Print help
765 -V, --version
766 Print version
767 ";
768
769 let cmd = Command::new("ctest").version("0.1").term_width(24);
770 utils::assert_output(cmd, "ctest --help", FINAL_WORD_WRAPPING, false);
771 }
772
773 #[test]
774 #[cfg(feature = "wrap_help")]
wrapping_newline_chars()775 fn wrapping_newline_chars() {
776 static WRAPPING_NEWLINE_CHARS: &str = "\
777 Usage: ctest [mode]
778
779 Arguments:
780 [mode] x, max, maximum 20 characters, contains symbols.
781 l, long Copy-friendly, 14 characters,
782 contains symbols.
783 m, med, medium Copy-friendly, 8 characters,
784 contains symbols.
785
786 Options:
787 -h, --help Print help
788 -V, --version Print version
789 ";
790
791 let cmd = Command::new("ctest")
792 .version("0.1")
793 .term_width(60)
794 .arg(Arg::new("mode").help(
795 "x, max, maximum 20 characters, contains symbols.\n\
796 l, long Copy-friendly, 14 characters, contains symbols.\n\
797 m, med, medium Copy-friendly, 8 characters, contains symbols.\n",
798 ));
799 utils::assert_output(cmd, "ctest --help", WRAPPING_NEWLINE_CHARS, false);
800 }
801
802 #[test]
803 #[cfg(feature = "wrap_help")]
wrapping_newline_variables()804 fn wrapping_newline_variables() {
805 static WRAPPING_NEWLINE_CHARS: &str = "\
806 Usage: ctest [mode]
807
808 Arguments:
809 [mode] x, max, maximum 20 characters, contains symbols.
810 l, long Copy-friendly, 14 characters,
811 contains symbols.
812 m, med, medium Copy-friendly, 8 characters,
813 contains symbols.
814
815 Options:
816 -h, --help Print help
817 -V, --version Print version
818 ";
819
820 let cmd = Command::new("ctest")
821 .version("0.1")
822 .term_width(60)
823 .arg(Arg::new("mode").help(
824 "x, max, maximum 20 characters, contains symbols.{n}\
825 l, long Copy-friendly, 14 characters, contains symbols.{n}\
826 m, med, medium Copy-friendly, 8 characters, contains symbols.{n}",
827 ));
828 utils::assert_output(cmd, "ctest --help", WRAPPING_NEWLINE_CHARS, false);
829 }
830
831 #[test]
832 #[cfg(feature = "wrap_help")]
dont_wrap_urls()833 fn dont_wrap_urls() {
834 let cmd = Command::new("Example")
835 .term_width(30)
836 .subcommand(Command::new("update").arg(
837 Arg::new("force-non-host")
838 .help("Install toolchains that require an emulator. See https://github.com/rust-lang/rustup/wiki/Non-host-toolchains")
839 .long("force-non-host")
840 .action(ArgAction::SetTrue))
841 );
842
843 const EXPECTED: &str = "\
844 Usage: Example update [OPTIONS]
845
846 Options:
847 --force-non-host
848 Install toolchains
849 that require an
850 emulator. See
851 https://github.com/rust-lang/rustup/wiki/Non-host-toolchains
852 -h, --help
853 Print help
854 ";
855 utils::assert_output(cmd, "Example update --help", EXPECTED, false);
856 }
857
858 static OLD_NEWLINE_CHARS: &str = "\
859 Usage: ctest [OPTIONS]
860
861 Options:
862 -m Some help with some wrapping
863 (Defaults to something)
864 -h, --help Print help
865 -V, --version Print version
866 ";
867
868 #[test]
old_newline_chars()869 fn old_newline_chars() {
870 let cmd = Command::new("ctest").version("0.1").arg(
871 Arg::new("mode")
872 .short('m')
873 .action(ArgAction::SetTrue)
874 .help("Some help with some wrapping\n(Defaults to something)"),
875 );
876 utils::assert_output(cmd, "ctest --help", OLD_NEWLINE_CHARS, false);
877 }
878
879 #[test]
old_newline_variables()880 fn old_newline_variables() {
881 let cmd = Command::new("ctest").version("0.1").arg(
882 Arg::new("mode")
883 .short('m')
884 .action(ArgAction::SetTrue)
885 .help("Some help with some wrapping{n}(Defaults to something)"),
886 );
887 utils::assert_output(cmd, "ctest --help", OLD_NEWLINE_CHARS, false);
888 }
889
890 #[test]
891 #[cfg(feature = "wrap_help")]
issue_688_hide_pos_vals()892 fn issue_688_hide_pos_vals() {
893 static ISSUE_688: &str = "\
894 Usage: ctest [OPTIONS]
895
896 Options:
897 --filter <filter> Sets the filter, or sampling method, to use for interpolation when resizing the particle
898 images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic, Gaussian,
899 Lanczos3]
900 -h, --help Print help
901 -V, --version Print version
902 ";
903
904 let filter_values = ["Nearest", "Linear", "Cubic", "Gaussian", "Lanczos3"];
905
906 let app1 = Command::new("ctest")
907 .version("0.1")
908 .term_width(120)
909 .hide_possible_values(true)
910 .arg(Arg::new("filter")
911 .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \
912 images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic, Gaussian, Lanczos3]")
913 .long("filter")
914 .value_parser(filter_values)
915 .action(ArgAction::Set));
916 utils::assert_output(app1, "ctest --help", ISSUE_688, false);
917
918 let app2 = Command::new("ctest")
919 .version("0.1")
920 .term_width(120)
921 .arg(Arg::new("filter")
922 .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \
923 images. The default is Linear (Bilinear).")
924 .long("filter")
925 .value_parser(filter_values)
926 .action(ArgAction::Set));
927 utils::assert_output(app2, "ctest --help", ISSUE_688, false);
928
929 let app3 = Command::new("ctest")
930 .version("0.1")
931 .term_width(120)
932 .arg(Arg::new("filter")
933 .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \
934 images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic, Gaussian, Lanczos3]")
935 .long("filter")
936 .action(ArgAction::Set));
937 utils::assert_output(app3, "ctest --help", ISSUE_688, false);
938 }
939
940 #[test]
issue_702_multiple_values()941 fn issue_702_multiple_values() {
942 static ISSUE_702: &str = "\
943 bar
944
945 Usage: myapp [OPTIONS] [arg1] [arg2]...
946
947 Arguments:
948 [arg1] some option
949 [arg2]... some option
950
951 Options:
952 -s, --some <some> some option
953 -o, --other <other> some other option
954 -l, --label <label>... a label
955 -h, --help Print help
956 -V, --version Print version
957 ";
958
959 let cmd = Command::new("myapp")
960 .version("1.0")
961 .author("foo")
962 .about("bar")
963 .arg(Arg::new("arg1").help("some option"))
964 .arg(
965 Arg::new("arg2")
966 .action(ArgAction::Set)
967 .num_args(1..)
968 .help("some option"),
969 )
970 .arg(
971 Arg::new("some")
972 .help("some option")
973 .short('s')
974 .long("some")
975 .action(ArgAction::Set),
976 )
977 .arg(
978 Arg::new("other")
979 .help("some other option")
980 .short('o')
981 .long("other")
982 .action(ArgAction::Set),
983 )
984 .arg(
985 Arg::new("label")
986 .help("a label")
987 .short('l')
988 .long("label")
989 .num_args(1..)
990 .action(ArgAction::Set),
991 );
992 utils::assert_output(cmd, "myapp --help", ISSUE_702, false);
993 }
994
995 #[test]
long_about()996 fn long_about() {
997 static LONG_ABOUT: &str = "\
998 something really really long, with
999 multiple lines of text
1000 that should be displayed
1001
1002 Usage: myapp [arg1]
1003
1004 Arguments:
1005 [arg1]
1006 some option
1007
1008 Options:
1009 -h, --help
1010 Print help (see a summary with '-h')
1011
1012 -V, --version
1013 Print version
1014 ";
1015
1016 let cmd = Command::new("myapp")
1017 .version("1.0")
1018 .author("foo")
1019 .about("bar")
1020 .long_about(
1021 "something really really long, with\nmultiple lines of text\nthat should be displayed",
1022 )
1023 .arg(Arg::new("arg1").help("some option"));
1024 utils::assert_output(cmd, "myapp --help", LONG_ABOUT, false);
1025 }
1026
1027 #[test]
ripgrep_usage()1028 fn ripgrep_usage() {
1029 static RIPGREP_USAGE: &str = "\
1030 Usage: rg [OPTIONS] <pattern> [<path> ...]
1031 rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
1032 rg [OPTIONS] --files [<path> ...]
1033 rg [OPTIONS] --type-list
1034
1035 Options:
1036 -h, --help Print help
1037 -V, --version Print version
1038 ";
1039
1040 let cmd = Command::new("ripgrep").version("0.5").override_usage(
1041 "rg [OPTIONS] <pattern> [<path> ...]
1042 rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
1043 rg [OPTIONS] --files [<path> ...]
1044 rg [OPTIONS] --type-list",
1045 );
1046
1047 utils::assert_output(cmd, "rg --help", RIPGREP_USAGE, false);
1048 }
1049
1050 #[test]
ripgrep_usage_using_templates()1051 fn ripgrep_usage_using_templates() {
1052 static RIPGREP_USAGE: &str = "\
1053 ripgrep 0.5
1054
1055 Usage: rg [OPTIONS] <pattern> [<path> ...]
1056 rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
1057 rg [OPTIONS] --files [<path> ...]
1058 rg [OPTIONS] --type-list
1059
1060 Options:
1061 -h, --help Print help
1062 -V, --version Print version
1063 ";
1064
1065 #[cfg(not(feature = "unstable-v5"))]
1066 let cmd = Command::new("ripgrep")
1067 .version("0.5")
1068 .override_usage(
1069 "\
1070 rg [OPTIONS] <pattern> [<path> ...]
1071 rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
1072 rg [OPTIONS] --files [<path> ...]
1073 rg [OPTIONS] --type-list",
1074 )
1075 .help_template(
1076 "\
1077 {bin} {version}
1078
1079 Usage: {usage}
1080
1081 Options:
1082 {options}",
1083 );
1084
1085 #[cfg(feature = "unstable-v5")]
1086 let cmd = Command::new("ripgrep")
1087 .version("0.5")
1088 .override_usage(
1089 "\
1090 rg [OPTIONS] <pattern> [<path> ...]
1091 rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
1092 rg [OPTIONS] --files [<path> ...]
1093 rg [OPTIONS] --type-list",
1094 )
1095 .help_template(
1096 "\
1097 {name} {version}
1098
1099 Usage: {usage}
1100
1101 Options:
1102 {options}",
1103 );
1104
1105 utils::assert_output(cmd, "rg --help", RIPGREP_USAGE, false);
1106 }
1107
1108 #[test]
sc_negates_reqs()1109 fn sc_negates_reqs() {
1110 static SC_NEGATES_REQS: &str = "\
1111 Usage: prog --opt <FILE> [PATH]
1112 prog [PATH] <COMMAND>
1113
1114 Commands:
1115 test
1116 help Print this message or the help of the given subcommand(s)
1117
1118 Arguments:
1119 [PATH] help
1120
1121 Options:
1122 -o, --opt <FILE> tests options
1123 -h, --help Print help
1124 -V, --version Print version
1125 ";
1126
1127 let cmd = Command::new("prog")
1128 .version("1.0")
1129 .subcommand_negates_reqs(true)
1130 .arg(arg!(-o --opt <FILE> "tests options").required(true))
1131 .arg(Arg::new("PATH").help("help"))
1132 .subcommand(Command::new("test"));
1133 utils::assert_output(cmd, "prog --help", SC_NEGATES_REQS, false);
1134 }
1135
1136 #[test]
hide_args()1137 fn hide_args() {
1138 static HIDDEN_ARGS: &str = "\
1139 Usage: prog [OPTIONS]
1140
1141 Options:
1142 -f, --flag testing flags
1143 -o, --opt <FILE> tests options
1144 -h, --help Print help
1145 -V, --version Print version
1146 ";
1147
1148 let cmd = Command::new("prog")
1149 .version("1.0")
1150 .arg(arg!(-f --flag "testing flags"))
1151 .arg(arg!(-o --opt <FILE> "tests options"))
1152 .arg(Arg::new("pos").hide(true));
1153 utils::assert_output(cmd, "prog --help", HIDDEN_ARGS, false);
1154 }
1155
1156 #[test]
args_negate_sc()1157 fn args_negate_sc() {
1158 static ARGS_NEGATE_SC: &str = "\
1159 Usage: prog [OPTIONS] [PATH]
1160 prog <COMMAND>
1161
1162 Commands:
1163 test
1164 help Print this message or the help of the given subcommand(s)
1165
1166 Arguments:
1167 [PATH] help
1168
1169 Options:
1170 -f, --flag testing flags
1171 -o, --opt <FILE> tests options
1172 -h, --help Print help
1173 -V, --version Print version
1174 ";
1175
1176 let cmd = Command::new("prog")
1177 .version("1.0")
1178 .args_conflicts_with_subcommands(true)
1179 .arg(arg!(-f --flag "testing flags"))
1180 .arg(arg!(-o --opt <FILE> "tests options"))
1181 .arg(Arg::new("PATH").help("help"))
1182 .subcommand(Command::new("test"));
1183 utils::assert_output(cmd, "prog --help", ARGS_NEGATE_SC, false);
1184 }
1185
1186 #[test]
issue_1046_hide_scs()1187 fn issue_1046_hide_scs() {
1188 static ISSUE_1046_HIDDEN_SCS: &str = "\
1189 Usage: prog [OPTIONS] [PATH]
1190
1191 Arguments:
1192 [PATH] some
1193
1194 Options:
1195 -f, --flag testing flags
1196 -o, --opt <FILE> tests options
1197 -h, --help Print help
1198 -V, --version Print version
1199 ";
1200
1201 let cmd = Command::new("prog")
1202 .version("1.0")
1203 .arg(arg!(-f --flag "testing flags"))
1204 .arg(arg!(-o --opt <FILE> "tests options"))
1205 .arg(Arg::new("PATH").help("some"))
1206 .subcommand(Command::new("test").hide(true));
1207 utils::assert_output(cmd, "prog --help", ISSUE_1046_HIDDEN_SCS, false);
1208 }
1209
1210 #[test]
1211 #[cfg(feature = "wrap_help")]
issue_777_wrap_all_things()1212 fn issue_777_wrap_all_things() {
1213 static ISSUE_777: &str = "A cmd with a crazy very long long
1214 long name hahaha 1.0
1215 Some Very Long Name and crazy long
1216 email <email@server.com>
1217 Show how the about text is not
1218 wrapped
1219
1220 Usage: ctest
1221
1222 Options:
1223 -h, --help Print help
1224 -V, --version Print version
1225 ";
1226
1227 let cmd = Command::new("A cmd with a crazy very long long long name hahaha")
1228 .version("1.0")
1229 .author("Some Very Long Name and crazy long email <email@server.com>")
1230 .about("Show how the about text is not wrapped")
1231 .help_template(utils::FULL_TEMPLATE)
1232 .term_width(35);
1233 utils::assert_output(cmd, "ctest --help", ISSUE_777, false);
1234 }
1235
1236 static OVERRIDE_HELP_SHORT: &str = "\
1237 Usage: test
1238
1239 Options:
1240 -H, --help Print help
1241 -V, --version Print version
1242 ";
1243
1244 #[test]
override_help_short()1245 fn override_help_short() {
1246 let cmd = Command::new("test")
1247 .version("0.1")
1248 .arg(arg!(-H --help "Print help").action(ArgAction::Help))
1249 .disable_help_flag(true);
1250
1251 utils::assert_output(cmd.clone(), "test --help", OVERRIDE_HELP_SHORT, false);
1252 utils::assert_output(cmd, "test -H", OVERRIDE_HELP_SHORT, false);
1253 }
1254
1255 static OVERRIDE_HELP_LONG: &str = "\
1256 Usage: test [OPTIONS]
1257
1258 Options:
1259 -h, --hell Print help
1260 -V, --version Print version
1261 ";
1262
1263 #[test]
override_help_long()1264 fn override_help_long() {
1265 let cmd = Command::new("test")
1266 .version("0.1")
1267 .arg(arg!(-h --hell "Print help").action(ArgAction::Help))
1268 .disable_help_flag(true);
1269
1270 utils::assert_output(cmd.clone(), "test --hell", OVERRIDE_HELP_LONG, false);
1271 utils::assert_output(cmd, "test -h", OVERRIDE_HELP_LONG, false);
1272 }
1273
1274 static OVERRIDE_HELP_ABOUT: &str = "\
1275 Usage: test
1276
1277 Options:
1278 -h, --help Print custom help information
1279 -V, --version Print version
1280 ";
1281
1282 #[test]
override_help_about()1283 fn override_help_about() {
1284 let cmd = Command::new("test")
1285 .version("0.1")
1286 .arg(arg!(-h --help "Print custom help information").action(ArgAction::Help))
1287 .disable_help_flag(true);
1288
1289 utils::assert_output(cmd.clone(), "test --help", OVERRIDE_HELP_ABOUT, false);
1290 utils::assert_output(cmd, "test -h", OVERRIDE_HELP_ABOUT, false);
1291 }
1292
1293 #[test]
1294 #[cfg(debug_assertions)]
1295 #[should_panic = "Command conflict: Argument names must be unique, but 'help' is in use by more than one argument or group (call `cmd.disable_help_flag(true)` to remove the auto-generated `--help`)"]
arg_id_conflict_with_help()1296 fn arg_id_conflict_with_help() {
1297 Command::new("conflict")
1298 .arg(Arg::new("help").short('?').action(ArgAction::SetTrue))
1299 .build();
1300 }
1301
1302 #[test]
1303 #[cfg(debug_assertions)]
1304 #[should_panic = "Command conflict: Short option names must be unique for each argument, but '-h' is in use by both 'home' and 'help' (call `cmd.disable_help_flag(true)` to remove the auto-generated `--help`)"]
arg_short_conflict_with_help()1305 fn arg_short_conflict_with_help() {
1306 Command::new("conflict")
1307 .arg(Arg::new("home").short('h').action(ArgAction::SetTrue))
1308 .build();
1309 }
1310
1311 #[test]
1312 #[cfg(debug_assertions)]
1313 #[should_panic = "Command conflict: Long option names must be unique for each argument, but '--help' is in use by both 'custom-help' and 'help' (call `cmd.disable_help_flag(true)` to remove the auto-generated `--help`)"]
arg_long_conflict_with_help()1314 fn arg_long_conflict_with_help() {
1315 Command::new("conflict")
1316 .arg(
1317 Arg::new("custom-help")
1318 .long("help")
1319 .action(ArgAction::SetTrue),
1320 )
1321 .build();
1322 }
1323
1324 #[test]
last_arg_mult_usage()1325 fn last_arg_mult_usage() {
1326 static LAST_ARG: &str = "\
1327 Usage: last <TARGET> [CORPUS] [-- <ARGS>...]
1328
1329 Arguments:
1330 <TARGET> some
1331 [CORPUS] some
1332 [ARGS]... some
1333
1334 Options:
1335 -h, --help Print help
1336 -V, --version Print version
1337 ";
1338
1339 let cmd = Command::new("last")
1340 .version("0.1")
1341 .arg(Arg::new("TARGET").required(true).help("some"))
1342 .arg(Arg::new("CORPUS").help("some"))
1343 .arg(
1344 Arg::new("ARGS")
1345 .action(ArgAction::Set)
1346 .num_args(1..)
1347 .last(true)
1348 .help("some"),
1349 );
1350 utils::assert_output(cmd, "last --help", LAST_ARG, false);
1351 }
1352
1353 #[test]
last_arg_mult_usage_req()1354 fn last_arg_mult_usage_req() {
1355 static LAST_ARG_REQ: &str = "\
1356 Usage: last <TARGET> [CORPUS] -- <ARGS>...
1357
1358 Arguments:
1359 <TARGET> some
1360 [CORPUS] some
1361 <ARGS>... some
1362
1363 Options:
1364 -h, --help Print help
1365 -V, --version Print version
1366 ";
1367
1368 let cmd = Command::new("last")
1369 .version("0.1")
1370 .arg(Arg::new("TARGET").required(true).help("some"))
1371 .arg(Arg::new("CORPUS").help("some"))
1372 .arg(
1373 Arg::new("ARGS")
1374 .action(ArgAction::Set)
1375 .num_args(1..)
1376 .last(true)
1377 .required(true)
1378 .help("some"),
1379 );
1380 utils::assert_output(cmd, "last --help", LAST_ARG_REQ, false);
1381 }
1382
1383 #[test]
last_arg_mult_usage_req_with_sc()1384 fn last_arg_mult_usage_req_with_sc() {
1385 static LAST_ARG_REQ_SC: &str = "\
1386 Usage: last <TARGET> [CORPUS] -- <ARGS>...
1387 last [TARGET] [CORPUS] <COMMAND>
1388
1389 Commands:
1390 test some
1391 help Print this message or the help of the given subcommand(s)
1392
1393 Arguments:
1394 <TARGET> some
1395 [CORPUS] some
1396 <ARGS>... some
1397
1398 Options:
1399 -h, --help Print help
1400 -V, --version Print version
1401 ";
1402
1403 let cmd = Command::new("last")
1404 .version("0.1")
1405 .subcommand_negates_reqs(true)
1406 .arg(Arg::new("TARGET").required(true).help("some"))
1407 .arg(Arg::new("CORPUS").help("some"))
1408 .arg(
1409 Arg::new("ARGS")
1410 .action(ArgAction::Set)
1411 .num_args(1..)
1412 .last(true)
1413 .required(true)
1414 .help("some"),
1415 )
1416 .subcommand(Command::new("test").about("some"));
1417 utils::assert_output(cmd, "last --help", LAST_ARG_REQ_SC, false);
1418 }
1419
1420 #[test]
last_arg_mult_usage_with_sc()1421 fn last_arg_mult_usage_with_sc() {
1422 static LAST_ARG_SC: &str = "\
1423 Usage: last <TARGET> [CORPUS] [-- <ARGS>...]
1424 last <COMMAND>
1425
1426 Commands:
1427 test some
1428 help Print this message or the help of the given subcommand(s)
1429
1430 Arguments:
1431 <TARGET> some
1432 [CORPUS] some
1433 [ARGS]... some
1434
1435 Options:
1436 -h, --help Print help
1437 -V, --version Print version
1438 ";
1439
1440 let cmd = Command::new("last")
1441 .version("0.1")
1442 .args_conflicts_with_subcommands(true)
1443 .arg(Arg::new("TARGET").required(true).help("some"))
1444 .arg(Arg::new("CORPUS").help("some"))
1445 .arg(
1446 Arg::new("ARGS")
1447 .action(ArgAction::Set)
1448 .num_args(1..)
1449 .last(true)
1450 .help("some"),
1451 )
1452 .subcommand(Command::new("test").about("some"));
1453 utils::assert_output(cmd, "last --help", LAST_ARG_SC, false);
1454 }
1455
1456 static HIDE_DEFAULT_VAL: &str = "\
1457 Usage: default [OPTIONS]
1458
1459 Options:
1460 --arg <argument> Pass an argument to the program. [default: default-argument]
1461 -h, --help Print help
1462 -V, --version Print version
1463 ";
1464
1465 #[test]
hide_default_val()1466 fn hide_default_val() {
1467 let app1 = Command::new("default").version("0.1").term_width(120).arg(
1468 Arg::new("argument")
1469 .help("Pass an argument to the program. [default: default-argument]")
1470 .long("arg")
1471 .default_value("default-argument")
1472 .hide_default_value(true),
1473 );
1474 utils::assert_output(app1, "default --help", HIDE_DEFAULT_VAL, false);
1475
1476 let app2 = Command::new("default").version("0.1").term_width(120).arg(
1477 Arg::new("argument")
1478 .help("Pass an argument to the program.")
1479 .long("arg")
1480 .default_value("default-argument"),
1481 );
1482 utils::assert_output(app2, "default --help", HIDE_DEFAULT_VAL, false);
1483 }
1484
1485 #[test]
1486 #[cfg(feature = "wrap_help")]
escaped_whitespace_values()1487 fn escaped_whitespace_values() {
1488 static ESCAPED_DEFAULT_VAL: &str = "\
1489 Usage: default [OPTIONS]
1490
1491 Options:
1492 --arg <argument> Pass an argument to the program. [default: \"\\n\"] [possible values: normal, \" \", \"\\n\", \"\\t\",
1493 other]
1494 -h, --help Print help
1495 -V, --version Print version
1496 ";
1497
1498 let app1 = Command::new("default").version("0.1").term_width(120).arg(
1499 Arg::new("argument")
1500 .help("Pass an argument to the program.")
1501 .long("arg")
1502 .default_value("\n")
1503 .value_parser(["normal", " ", "\n", "\t", "other"]),
1504 );
1505 utils::assert_output(app1, "default --help", ESCAPED_DEFAULT_VAL, false);
1506 }
1507
issue_1112_setup() -> Command1508 fn issue_1112_setup() -> Command {
1509 Command::new("test")
1510 .version("1.3")
1511 .disable_help_flag(true)
1512 .arg(
1513 Arg::new("help1")
1514 .long("help")
1515 .short('h')
1516 .help("some help")
1517 .action(ArgAction::SetTrue),
1518 )
1519 .subcommand(
1520 Command::new("foo").arg(
1521 Arg::new("help1")
1522 .long("help")
1523 .short('h')
1524 .help("some help")
1525 .action(ArgAction::SetTrue),
1526 ),
1527 )
1528 }
1529
1530 #[test]
prefer_user_help_long_1112()1531 fn prefer_user_help_long_1112() {
1532 let m = issue_1112_setup().try_get_matches_from(vec!["test", "--help"]);
1533
1534 assert!(m.is_ok(), "{}", m.unwrap_err());
1535 let m = m.unwrap();
1536 assert!(*m.get_one::<bool>("help1").expect("defaulted by clap"));
1537 }
1538
1539 #[test]
prefer_user_help_short_1112()1540 fn prefer_user_help_short_1112() {
1541 let m = issue_1112_setup().try_get_matches_from(vec!["test", "-h"]);
1542
1543 assert!(m.is_ok(), "{}", m.unwrap_err());
1544 let m = m.unwrap();
1545 assert!(*m.get_one::<bool>("help1").expect("defaulted by clap"));
1546 }
1547
1548 #[test]
prefer_user_subcmd_help_long_1112()1549 fn prefer_user_subcmd_help_long_1112() {
1550 let m = issue_1112_setup().try_get_matches_from(vec!["test", "foo", "--help"]);
1551
1552 assert!(m.is_ok(), "{}", m.unwrap_err());
1553 let m = m.unwrap();
1554 assert!(*m
1555 .subcommand_matches("foo")
1556 .unwrap()
1557 .get_one::<bool>("help1")
1558 .expect("defaulted by clap"));
1559 }
1560
1561 #[test]
prefer_user_subcmd_help_short_1112()1562 fn prefer_user_subcmd_help_short_1112() {
1563 let m = issue_1112_setup().try_get_matches_from(vec!["test", "foo", "-h"]);
1564
1565 assert!(m.is_ok(), "{}", m.unwrap_err());
1566 let m = m.unwrap();
1567 assert!(m
1568 .subcommand_matches("foo")
1569 .unwrap()
1570 .get_one::<bool>("help1")
1571 .expect("defaulted by clap"));
1572 }
1573
1574 #[test]
issue_1052_require_delim_help()1575 fn issue_1052_require_delim_help() {
1576 static REQUIRE_DELIM_HELP: &str = "\
1577 tests stuff
1578
1579 Usage: test --fake <some> <val>
1580
1581 Options:
1582 -f, --fake <some> <val> some help
1583 -h, --help Print help
1584 -V, --version Print version
1585 ";
1586
1587 let cmd = Command::new("test")
1588 .author("Kevin K.")
1589 .about("tests stuff")
1590 .version("1.3")
1591 .arg(
1592 arg!(-f --fake <s> "some help")
1593 .required(true)
1594 .value_names(["some", "val"])
1595 .action(ArgAction::Set)
1596 .value_delimiter(':'),
1597 );
1598
1599 utils::assert_output(cmd, "test --help", REQUIRE_DELIM_HELP, false);
1600 }
1601
1602 #[test]
custom_headers_headers()1603 fn custom_headers_headers() {
1604 static CUSTOM_HELP_SECTION: &str = "\
1605 does stuff
1606
1607 Usage: test [OPTIONS] --fake <some> <val>
1608
1609 Options:
1610 -f, --fake <some> <val> some help
1611 -h, --help Print help
1612 -V, --version Print version
1613
1614 NETWORKING:
1615 -n, --no-proxy Do not use system proxy settings
1616 --port
1617 ";
1618
1619 let cmd = Command::new("blorp")
1620 .author("Will M.")
1621 .about("does stuff")
1622 .version("1.4")
1623 .arg(
1624 arg!(-f --fake <s> "some help")
1625 .required(true)
1626 .value_names(["some", "val"])
1627 .action(ArgAction::Set)
1628 .value_delimiter(':'),
1629 )
1630 .next_help_heading(Some("NETWORKING"))
1631 .arg(
1632 Arg::new("no-proxy")
1633 .short('n')
1634 .long("no-proxy")
1635 .action(ArgAction::SetTrue)
1636 .help("Do not use system proxy settings"),
1637 )
1638 .args([Arg::new("port").long("port").action(ArgAction::SetTrue)]);
1639
1640 utils::assert_output(cmd, "test --help", CUSTOM_HELP_SECTION, false);
1641 }
1642
1643 static MULTIPLE_CUSTOM_HELP_SECTIONS: &str = "\
1644 does stuff
1645
1646 Usage: test [OPTIONS] --fake <some> <val> --birthday-song <song> --birthday-song-volume <volume>
1647
1648 Options:
1649 -f, --fake <some> <val> some help
1650 --style <style> Choose musical style to play the song
1651 -s, --speed <SPEED> How fast? [possible values: fast, slow]
1652 -h, --help Print help
1653 -V, --version Print version
1654
1655 NETWORKING:
1656 -n, --no-proxy Do not use system proxy settings
1657 -a, --server-addr Set server address
1658
1659 OVERRIDE SPECIAL:
1660 -b, --birthday-song <song> Change which song is played for birthdays
1661
1662 SPECIAL:
1663 -v, --birthday-song-volume <volume> Change the volume of the birthday song
1664 ";
1665
1666 #[test]
multiple_custom_help_headers()1667 fn multiple_custom_help_headers() {
1668 let cmd = Command::new("blorp")
1669 .author("Will M.")
1670 .about("does stuff")
1671 .version("1.4")
1672 .arg(
1673 arg!(-f --fake <s> "some help")
1674 .required(true)
1675 .value_names(["some", "val"])
1676 .action(ArgAction::Set)
1677 .value_delimiter(':'),
1678 )
1679 .next_help_heading(Some("NETWORKING"))
1680 .arg(
1681 Arg::new("no-proxy")
1682 .short('n')
1683 .long("no-proxy")
1684 .action(ArgAction::SetTrue)
1685 .help("Do not use system proxy settings"),
1686 )
1687 .next_help_heading(Some("SPECIAL"))
1688 .arg(
1689 arg!(-b --"birthday-song" <song> "Change which song is played for birthdays")
1690 .required(true)
1691 .help_heading(Some("OVERRIDE SPECIAL")),
1692 )
1693 .arg(arg!(--style <style> "Choose musical style to play the song").help_heading(None))
1694 .arg(
1695 arg!(
1696 -v --"birthday-song-volume" <volume> "Change the volume of the birthday song"
1697 )
1698 .required(true),
1699 )
1700 .next_help_heading(None)
1701 .arg(
1702 Arg::new("server-addr")
1703 .short('a')
1704 .long("server-addr")
1705 .action(ArgAction::SetTrue)
1706 .help("Set server address")
1707 .help_heading(Some("NETWORKING")),
1708 )
1709 .arg(
1710 Arg::new("speed")
1711 .long("speed")
1712 .short('s')
1713 .value_name("SPEED")
1714 .value_parser(["fast", "slow"])
1715 .help("How fast?")
1716 .action(ArgAction::Set),
1717 );
1718
1719 utils::assert_output(cmd, "test --help", MULTIPLE_CUSTOM_HELP_SECTIONS, false);
1720 }
1721
1722 static CUSTOM_HELP_SECTION_HIDDEN_ARGS: &str = "\
1723 does stuff
1724
1725 Usage: test [OPTIONS] --song <song> --song-volume <volume>
1726
1727 Options:
1728 -h, --help Print help (see more with '--help')
1729 -V, --version Print version
1730
1731 OVERRIDE SPECIAL:
1732 -b, --song <song> Change which song is played for birthdays
1733
1734 SPECIAL:
1735 -v, --song-volume <volume> Change the volume of the birthday song
1736 ";
1737
1738 #[test]
custom_help_headers_hide_args()1739 fn custom_help_headers_hide_args() {
1740 let cmd = Command::new("blorp")
1741 .author("Will M.")
1742 .about("does stuff")
1743 .version("1.4")
1744 .next_help_heading(Some("NETWORKING"))
1745 .arg(
1746 Arg::new("no-proxy")
1747 .short('n')
1748 .long("no-proxy")
1749 .help("Do not use system proxy settings")
1750 .hide_short_help(true),
1751 )
1752 .next_help_heading(Some("SPECIAL"))
1753 .arg(
1754 arg!(-b --song <song> "Change which song is played for birthdays")
1755 .required(true)
1756 .help_heading(Some("OVERRIDE SPECIAL")),
1757 )
1758 .arg(
1759 arg!(
1760 -v --"song-volume" <volume> "Change the volume of the birthday song"
1761 )
1762 .required(true),
1763 )
1764 .next_help_heading(None)
1765 .arg(
1766 Arg::new("server-addr")
1767 .short('a')
1768 .long("server-addr")
1769 .help("Set server address")
1770 .help_heading(Some("NETWORKING"))
1771 .hide_short_help(true),
1772 );
1773
1774 utils::assert_output(cmd, "test -h", CUSTOM_HELP_SECTION_HIDDEN_ARGS, false);
1775 }
1776
1777 static ISSUE_897: &str = "\
1778 Long about foo
1779
1780 Usage: ctest foo
1781
1782 Options:
1783 -h, --help
1784 Print help (see a summary with '-h')
1785
1786 -V, --version
1787 Print version
1788 ";
1789
1790 #[test]
show_long_about_issue_897()1791 fn show_long_about_issue_897() {
1792 let cmd = Command::new("ctest").version("0.1").subcommand(
1793 Command::new("foo")
1794 .version("0.1")
1795 .about("About foo")
1796 .long_about("Long about foo"),
1797 );
1798 utils::assert_output(cmd, "ctest foo --help", ISSUE_897, false);
1799 }
1800
1801 static ISSUE_897_SHORT: &str = "\
1802 About foo
1803
1804 Usage: ctest foo
1805
1806 Options:
1807 -h, --help Print help (see more with '--help')
1808 -V, --version Print version
1809 ";
1810
1811 #[test]
show_short_about_issue_897()1812 fn show_short_about_issue_897() {
1813 let cmd = Command::new("ctest").version("0.1").subcommand(
1814 Command::new("foo")
1815 .version("0.1")
1816 .about("About foo")
1817 .long_about("Long about foo"),
1818 );
1819 utils::assert_output(cmd, "ctest foo -h", ISSUE_897_SHORT, false);
1820 }
1821
1822 #[test]
issue_1364_no_short_options()1823 fn issue_1364_no_short_options() {
1824 static ISSUE_1364: &str = "\
1825 Usage: demo [OPTIONS] [FILES]...
1826
1827 Arguments:
1828 [FILES]...
1829
1830 Options:
1831 -f
1832 -h, --help Print help (see more with '--help')
1833 ";
1834
1835 let cmd = Command::new("demo")
1836 .arg(Arg::new("foo").short('f').action(ArgAction::SetTrue))
1837 .arg(
1838 Arg::new("baz")
1839 .short('z')
1840 .value_name("BAZ")
1841 .hide_short_help(true),
1842 )
1843 .arg(
1844 Arg::new("files")
1845 .value_name("FILES")
1846 .action(ArgAction::Set)
1847 .num_args(1..),
1848 );
1849
1850 utils::assert_output(cmd, "demo -h", ISSUE_1364, false);
1851 }
1852
1853 #[rustfmt::skip]
1854 #[test]
issue_1487()1855 fn issue_1487() {
1856 static ISSUE_1487: &str = "\
1857 Usage: ctest <arg1|arg2>
1858
1859 Arguments:
1860 [arg1]
1861 [arg2]
1862
1863 Options:
1864 -h, --help Print help
1865 ";
1866
1867 let cmd = Command::new("test")
1868 .arg(Arg::new("arg1")
1869 .group("group1"))
1870 .arg(Arg::new("arg2")
1871 .group("group1"))
1872 .group(ArgGroup::new("group1")
1873 .args(["arg1", "arg2"])
1874 .required(true));
1875 utils::assert_output(cmd, "ctest -h", ISSUE_1487, false);
1876 }
1877
1878 #[cfg(debug_assertions)]
1879 #[test]
1880 #[should_panic = "Command::help_expected is enabled for the Command"]
help_required_but_not_given()1881 fn help_required_but_not_given() {
1882 Command::new("myapp")
1883 .help_expected(true)
1884 .arg(Arg::new("foo"))
1885 .try_get_matches_from(empty_args())
1886 .unwrap();
1887 }
1888
1889 #[cfg(debug_assertions)]
1890 #[test]
1891 #[should_panic = "Command::help_expected is enabled for the Command"]
help_required_but_not_given_settings_after_args()1892 fn help_required_but_not_given_settings_after_args() {
1893 Command::new("myapp")
1894 .arg(Arg::new("foo"))
1895 .help_expected(true)
1896 .try_get_matches_from(empty_args())
1897 .unwrap();
1898 }
1899
1900 #[cfg(debug_assertions)]
1901 #[test]
1902 #[should_panic = "Command::help_expected is enabled for the Command"]
help_required_but_not_given_for_one_of_two_arguments()1903 fn help_required_but_not_given_for_one_of_two_arguments() {
1904 Command::new("myapp")
1905 .help_expected(true)
1906 .arg(Arg::new("foo"))
1907 .arg(Arg::new("bar").help("It does bar stuff"))
1908 .try_get_matches_from(empty_args())
1909 .unwrap();
1910 }
1911
1912 #[test]
1913 #[should_panic = "List of such arguments: delete"]
help_required_globally()1914 fn help_required_globally() {
1915 Command::new("myapp")
1916 .help_expected(true)
1917 .arg(Arg::new("foo").help("It does foo stuff"))
1918 .subcommand(
1919 Command::new("bar")
1920 .arg(Arg::new("create").help("creates bar"))
1921 .arg(Arg::new("delete")),
1922 )
1923 .try_get_matches_from(empty_args())
1924 .unwrap();
1925 }
1926
1927 #[cfg(debug_assertions)]
1928 #[test]
1929 #[should_panic = "Command::help_expected is enabled for the Command"]
help_required_globally_but_not_given_for_subcommand()1930 fn help_required_globally_but_not_given_for_subcommand() {
1931 Command::new("myapp")
1932 .help_expected(true)
1933 .arg(Arg::new("foo").help("It does foo stuff"))
1934 .subcommand(
1935 Command::new("bar")
1936 .arg(Arg::new("create").help("creates bar"))
1937 .arg(Arg::new("delete")),
1938 )
1939 .try_get_matches_from(empty_args())
1940 .unwrap();
1941 }
1942
1943 #[test]
help_required_and_given_for_subcommand()1944 fn help_required_and_given_for_subcommand() {
1945 Command::new("myapp")
1946 .help_expected(true)
1947 .arg(Arg::new("foo").help("It does foo stuff"))
1948 .subcommand(
1949 Command::new("bar")
1950 .arg(Arg::new("create").help("creates bar"))
1951 .arg(Arg::new("delete").help("deletes bar")),
1952 )
1953 .try_get_matches_from(empty_args())
1954 .unwrap();
1955 }
1956
1957 #[test]
help_required_and_given()1958 fn help_required_and_given() {
1959 Command::new("myapp")
1960 .help_expected(true)
1961 .arg(Arg::new("foo").help("It does foo stuff"))
1962 .try_get_matches_from(empty_args())
1963 .unwrap();
1964 }
1965
1966 #[test]
help_required_and_no_args()1967 fn help_required_and_no_args() {
1968 Command::new("myapp")
1969 .help_expected(true)
1970 .try_get_matches_from(empty_args())
1971 .unwrap();
1972 }
1973
1974 #[test]
issue_1642_long_help_spacing()1975 fn issue_1642_long_help_spacing() {
1976 static ISSUE_1642: &str = "\
1977 Usage: prog [OPTIONS]
1978
1979 Options:
1980 --config
1981 The config file used by the myprog must be in JSON format
1982 with only valid keys and may not contain other nonsense
1983 that cannot be read by this program. Obviously I'm going on
1984 and on, so I'll stop now.
1985
1986 -h, --help
1987 Print help (see a summary with '-h')
1988 ";
1989
1990 let cmd = Command::new("prog").arg(
1991 Arg::new("cfg")
1992 .long("config")
1993 .action(ArgAction::SetTrue)
1994 .long_help(
1995 "The config file used by the myprog must be in JSON format
1996 with only valid keys and may not contain other nonsense
1997 that cannot be read by this program. Obviously I'm going on
1998 and on, so I'll stop now.",
1999 ),
2000 );
2001 utils::assert_output(cmd, "prog --help", ISSUE_1642, false);
2002 }
2003
2004 const AFTER_HELP_NO_ARGS: &str = "\
2005 Usage: myapp
2006
2007 This is after help.
2008 ";
2009
2010 #[test]
after_help_no_args()2011 fn after_help_no_args() {
2012 let mut cmd = Command::new("myapp")
2013 .version("1.0")
2014 .disable_help_flag(true)
2015 .disable_version_flag(true)
2016 .after_help("This is after help.");
2017
2018 let help = cmd.render_help().to_string();
2019
2020 assert_eq!(help, AFTER_HELP_NO_ARGS);
2021 }
2022
2023 #[test]
help_subcmd_help()2024 fn help_subcmd_help() {
2025 static HELP_SUBCMD_HELP: &str = "\
2026 Print this message or the help of the given subcommand(s)
2027
2028 Usage: myapp help [COMMAND]...
2029
2030 Arguments:
2031 [COMMAND]... Print help for the subcommand(s)
2032 ";
2033
2034 let cmd = Command::new("myapp")
2035 .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));
2036
2037 utils::assert_output(cmd.clone(), "myapp help help", HELP_SUBCMD_HELP, false);
2038 }
2039
2040 #[test]
subcmd_help_subcmd_help()2041 fn subcmd_help_subcmd_help() {
2042 static SUBCMD_HELP_SUBCMD_HELP: &str = "\
2043 Print this message or the help of the given subcommand(s)
2044
2045 Usage: myapp subcmd help [COMMAND]...
2046
2047 Arguments:
2048 [COMMAND]... Print help for the subcommand(s)
2049 ";
2050
2051 let cmd = Command::new("myapp")
2052 .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));
2053
2054 utils::assert_output(
2055 cmd.clone(),
2056 "myapp subcmd help help",
2057 SUBCMD_HELP_SUBCMD_HELP,
2058 false,
2059 );
2060 }
2061
2062 #[test]
global_args_should_show_on_toplevel_help_message()2063 fn global_args_should_show_on_toplevel_help_message() {
2064 static HELP: &str = "\
2065 Usage: myapp [OPTIONS] [COMMAND]
2066
2067 Commands:
2068 subcmd\x20\x20
2069 help Print this message or the help of the given subcommand(s)
2070
2071 Options:
2072 -g, --some-global <someglobal>\x20\x20
2073 -h, --help Print help
2074 ";
2075
2076 let cmd = Command::new("myapp")
2077 .arg(
2078 Arg::new("someglobal")
2079 .short('g')
2080 .long("some-global")
2081 .global(true),
2082 )
2083 .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));
2084
2085 utils::assert_output(cmd, "myapp help", HELP, false);
2086 }
2087
2088 #[test]
global_args_should_not_show_on_help_message_for_help_help()2089 fn global_args_should_not_show_on_help_message_for_help_help() {
2090 static HELP_HELP: &str = "\
2091 Print this message or the help of the given subcommand(s)
2092
2093 Usage: myapp help [COMMAND]...
2094
2095 Arguments:
2096 [COMMAND]... Print help for the subcommand(s)
2097 ";
2098
2099 let cmd = Command::new("myapp")
2100 .arg(
2101 Arg::new("someglobal")
2102 .short('g')
2103 .long("some-global")
2104 .global(true),
2105 )
2106 .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));
2107
2108 utils::assert_output(cmd, "myapp help help", HELP_HELP, false);
2109 }
2110
2111 #[test]
global_args_should_show_on_help_message_for_subcommand()2112 fn global_args_should_show_on_help_message_for_subcommand() {
2113 static HELP_SUBCMD: &str = "\
2114 Usage: myapp subcmd [OPTIONS] [COMMAND]
2115
2116 Commands:
2117 multi\x20\x20
2118 help Print this message or the help of the given subcommand(s)
2119
2120 Options:
2121 -g, --some-global <someglobal>\x20\x20
2122 -h, --help Print help
2123 ";
2124
2125 let cmd = Command::new("myapp")
2126 .arg(
2127 Arg::new("someglobal")
2128 .short('g')
2129 .long("some-global")
2130 .global(true),
2131 )
2132 .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));
2133
2134 utils::assert_output(cmd, "myapp help subcmd", HELP_SUBCMD, false);
2135 }
2136
2137 #[test]
global_args_should_show_on_help_message_for_nested_subcommand()2138 fn global_args_should_show_on_help_message_for_nested_subcommand() {
2139 static HELP_SUB_SUBCMD: &str = "\
2140 Usage: myapp subcmd multi [OPTIONS]
2141
2142 Options:
2143 -g, --some-global <someglobal>\x20\x20
2144 -h, --help Print help
2145 -V, --version Print version
2146 ";
2147
2148 let cmd = Command::new("myapp")
2149 .arg(
2150 Arg::new("someglobal")
2151 .short('g')
2152 .long("some-global")
2153 .global(true),
2154 )
2155 .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));
2156
2157 utils::assert_output(cmd, "myapp help subcmd multi", HELP_SUB_SUBCMD, false);
2158 }
2159
2160 #[test]
option_usage_order()2161 fn option_usage_order() {
2162 static OPTION_USAGE_ORDER: &str = "\
2163 Usage: order [OPTIONS]
2164
2165 Options:
2166 -a
2167 -B
2168 -b
2169 -s
2170 --select_file
2171 --select_folder
2172 -x
2173 -h, --help Print help
2174 ";
2175
2176 let cmd = Command::new("order").args([
2177 Arg::new("a").short('a').action(ArgAction::SetTrue),
2178 Arg::new("B").short('B').action(ArgAction::SetTrue),
2179 Arg::new("b").short('b').action(ArgAction::SetTrue),
2180 Arg::new("save").short('s').action(ArgAction::SetTrue),
2181 Arg::new("select_file")
2182 .long("select_file")
2183 .action(ArgAction::SetTrue),
2184 Arg::new("select_folder")
2185 .long("select_folder")
2186 .action(ArgAction::SetTrue),
2187 Arg::new("x").short('x').action(ArgAction::SetTrue),
2188 ]);
2189
2190 utils::assert_output(cmd, "order --help", OPTION_USAGE_ORDER, false);
2191 }
2192
2193 #[test]
prefer_about_over_long_about_in_subcommands_list()2194 fn prefer_about_over_long_about_in_subcommands_list() {
2195 static ABOUT_IN_COMMANDS_LIST: &str = "\
2196 Usage: about-in-subcommands-list [COMMAND]
2197
2198 Commands:
2199 sub short about sub
2200 help Print this message or the help of the given subcommand(s)
2201
2202 Options:
2203 -h, --help Print help
2204 ";
2205
2206 let cmd = Command::new("about-in-subcommands-list").subcommand(
2207 Command::new("sub")
2208 .long_about("long about sub")
2209 .about("short about sub"),
2210 );
2211
2212 utils::assert_output(
2213 cmd,
2214 "about-in-subcommands-list --help",
2215 ABOUT_IN_COMMANDS_LIST,
2216 false,
2217 );
2218 }
2219
2220 #[test]
issue_1794_usage()2221 fn issue_1794_usage() {
2222 static USAGE_WITH_GROUP: &str = "\
2223 Usage: deno <pos1|--option1> [pos2]
2224
2225 Arguments:
2226 [pos1]
2227 [pos2]
2228
2229 Options:
2230 --option1
2231 -h, --help Print help
2232 ";
2233
2234 let cmd = clap::Command::new("hello")
2235 .bin_name("deno")
2236 .arg(
2237 Arg::new("option1")
2238 .long("option1")
2239 .action(ArgAction::SetTrue),
2240 )
2241 .arg(Arg::new("pos1").action(ArgAction::Set))
2242 .group(
2243 ArgGroup::new("arg1")
2244 .args(["pos1", "option1"])
2245 .required(true),
2246 )
2247 .arg(Arg::new("pos2").action(ArgAction::Set));
2248
2249 utils::assert_output(cmd, "deno --help", USAGE_WITH_GROUP, false);
2250 }
2251
2252 static CUSTOM_HEADING_POS: &str = "\
2253 Usage: test [gear] [speed]
2254
2255 Arguments:
2256 [gear] Which gear
2257
2258 Options:
2259 -h, --help Print help
2260 -V, --version Print version
2261
2262 NETWORKING:
2263 [speed] How fast
2264 ";
2265
2266 #[test]
custom_heading_pos()2267 fn custom_heading_pos() {
2268 let cmd = Command::new("test")
2269 .version("1.4")
2270 .arg(Arg::new("gear").help("Which gear"))
2271 .next_help_heading(Some("NETWORKING"))
2272 .arg(Arg::new("speed").help("How fast"));
2273
2274 utils::assert_output(cmd, "test --help", CUSTOM_HEADING_POS, false);
2275 }
2276
2277 static ONLY_CUSTOM_HEADING_OPTS_NO_ARGS: &str = "\
2278 Usage: test [OPTIONS]
2279
2280 NETWORKING:
2281 -s, --speed <SPEED> How fast
2282 ";
2283
2284 #[test]
only_custom_heading_opts_no_args()2285 fn only_custom_heading_opts_no_args() {
2286 let cmd = Command::new("test")
2287 .version("1.4")
2288 .disable_version_flag(true)
2289 .disable_help_flag(true)
2290 .arg(arg!(--help).action(ArgAction::Help).hide(true))
2291 .next_help_heading(Some("NETWORKING"))
2292 .arg(arg!(-s --speed <SPEED> "How fast"));
2293
2294 utils::assert_output(cmd, "test --help", ONLY_CUSTOM_HEADING_OPTS_NO_ARGS, false);
2295 }
2296
2297 static ONLY_CUSTOM_HEADING_POS_NO_ARGS: &str = "\
2298 Usage: test [speed]
2299
2300 NETWORKING:
2301 [speed] How fast
2302 ";
2303
2304 #[test]
only_custom_heading_pos_no_args()2305 fn only_custom_heading_pos_no_args() {
2306 let cmd = Command::new("test")
2307 .version("1.4")
2308 .disable_version_flag(true)
2309 .disable_help_flag(true)
2310 .arg(arg!(--help).action(ArgAction::Help).hide(true))
2311 .next_help_heading(Some("NETWORKING"))
2312 .arg(Arg::new("speed").help("How fast"));
2313
2314 utils::assert_output(cmd, "test --help", ONLY_CUSTOM_HEADING_POS_NO_ARGS, false);
2315 }
2316
2317 #[test]
issue_2508_number_of_values_with_single_value_name()2318 fn issue_2508_number_of_values_with_single_value_name() {
2319 let cmd = Command::new("my_app")
2320 .arg(Arg::new("some_arg").long("some_arg").num_args(2))
2321 .arg(
2322 Arg::new("some_arg_issue")
2323 .long("some_arg_issue")
2324 .num_args(2)
2325 .value_name("ARG"),
2326 );
2327 utils::assert_output(
2328 cmd,
2329 "my_app --help",
2330 "\
2331 Usage: my_app [OPTIONS]
2332
2333 Options:
2334 --some_arg <some_arg> <some_arg>
2335 --some_arg_issue <ARG> <ARG>
2336 -h, --help Print help
2337 ",
2338 false,
2339 );
2340 }
2341
2342 #[test]
missing_positional_final_required()2343 fn missing_positional_final_required() {
2344 let cmd = Command::new("test")
2345 .allow_missing_positional(true)
2346 .arg(Arg::new("arg1"))
2347 .arg(Arg::new("arg2").required(true));
2348 utils::assert_output(
2349 cmd,
2350 "test --help",
2351 "\
2352 Usage: test [arg1] <arg2>
2353
2354 Arguments:
2355 [arg1]
2356 <arg2>
2357
2358 Options:
2359 -h, --help Print help
2360 ",
2361 false,
2362 );
2363 }
2364
2365 #[test]
missing_positional_final_multiple()2366 fn missing_positional_final_multiple() {
2367 let cmd = Command::new("test")
2368 .allow_missing_positional(true)
2369 .arg(Arg::new("foo"))
2370 .arg(Arg::new("bar"))
2371 .arg(Arg::new("baz").action(ArgAction::Set).num_args(1..));
2372 utils::assert_output(
2373 cmd,
2374 "test --help",
2375 "\
2376 Usage: test [foo] [bar] [baz]...
2377
2378 Arguments:
2379 [foo]
2380 [bar]
2381 [baz]...
2382
2383 Options:
2384 -h, --help Print help
2385 ",
2386 false,
2387 );
2388 }
2389
2390 #[test]
positional_multiple_values_is_dotted()2391 fn positional_multiple_values_is_dotted() {
2392 let cmd = Command::new("test").arg(
2393 Arg::new("foo")
2394 .required(true)
2395 .action(ArgAction::Set)
2396 .num_args(1..),
2397 );
2398 utils::assert_output(
2399 cmd,
2400 "test --help",
2401 "\
2402 Usage: test <foo>...
2403
2404 Arguments:
2405 <foo>...
2406
2407 Options:
2408 -h, --help Print help
2409 ",
2410 false,
2411 );
2412
2413 let cmd = Command::new("test").arg(
2414 Arg::new("foo")
2415 .required(true)
2416 .action(ArgAction::Set)
2417 .value_name("BAR")
2418 .num_args(1..),
2419 );
2420 utils::assert_output(
2421 cmd,
2422 "test --help",
2423 "\
2424 Usage: test <BAR>...
2425
2426 Arguments:
2427 <BAR>...
2428
2429 Options:
2430 -h, --help Print help
2431 ",
2432 false,
2433 );
2434 }
2435
2436 #[test]
positional_multiple_occurrences_is_dotted()2437 fn positional_multiple_occurrences_is_dotted() {
2438 let cmd = Command::new("test").arg(
2439 Arg::new("foo")
2440 .required(true)
2441 .action(ArgAction::Set)
2442 .num_args(1..)
2443 .action(ArgAction::Append),
2444 );
2445 utils::assert_output(
2446 cmd,
2447 "test --help",
2448 "\
2449 Usage: test <foo>...
2450
2451 Arguments:
2452 <foo>...
2453
2454 Options:
2455 -h, --help Print help
2456 ",
2457 false,
2458 );
2459
2460 let cmd = Command::new("test").arg(
2461 Arg::new("foo")
2462 .required(true)
2463 .action(ArgAction::Set)
2464 .value_name("BAR")
2465 .num_args(1..)
2466 .action(ArgAction::Append),
2467 );
2468 utils::assert_output(
2469 cmd,
2470 "test --help",
2471 "\
2472 Usage: test <BAR>...
2473
2474 Arguments:
2475 <BAR>...
2476
2477 Options:
2478 -h, --help Print help
2479 ",
2480 false,
2481 );
2482 }
2483
2484 #[test]
too_few_value_names_is_dotted()2485 fn too_few_value_names_is_dotted() {
2486 let cmd = Command::new("test").arg(
2487 Arg::new("foo")
2488 .long("foo")
2489 .required(true)
2490 .action(ArgAction::Set)
2491 .num_args(3)
2492 .value_names(["one", "two"]),
2493 );
2494 utils::assert_output(
2495 cmd,
2496 "test --help",
2497 "\
2498 Usage: test --foo <one> <two>...
2499
2500 Options:
2501 --foo <one> <two>...
2502 -h, --help Print help
2503 ",
2504 false,
2505 );
2506 }
2507
2508 #[test]
2509 #[should_panic = "Argument foo: Too many value names (2) compared to `num_args` (1)"]
too_many_value_names_panics()2510 fn too_many_value_names_panics() {
2511 Command::new("test")
2512 .arg(
2513 Arg::new("foo")
2514 .long("foo")
2515 .required(true)
2516 .action(ArgAction::Set)
2517 .num_args(1)
2518 .value_names(["one", "two"]),
2519 )
2520 .debug_assert()
2521 }
2522
2523 #[test]
disabled_help_flag()2524 fn disabled_help_flag() {
2525 let res = Command::new("foo")
2526 .subcommand(Command::new("sub"))
2527 .disable_help_flag(true)
2528 .try_get_matches_from("foo a".split(' '));
2529 assert!(res.is_err());
2530 let err = res.unwrap_err();
2531 assert_eq!(err.kind(), ErrorKind::InvalidSubcommand);
2532 }
2533
2534 #[test]
disabled_help_flag_and_subcommand()2535 fn disabled_help_flag_and_subcommand() {
2536 let res = Command::new("foo")
2537 .subcommand(Command::new("sub"))
2538 .disable_help_flag(true)
2539 .disable_help_subcommand(true)
2540 .try_get_matches_from("foo help".split(' '));
2541 assert!(res.is_err());
2542 let err = res.unwrap_err();
2543 assert_eq!(err.kind(), ErrorKind::InvalidSubcommand);
2544 assert!(
2545 err.to_string().ends_with('\n'),
2546 "Errors should have a trailing newline, got {:?}",
2547 err.to_string()
2548 );
2549 }
2550
2551 #[test]
override_help_subcommand()2552 fn override_help_subcommand() {
2553 let cmd = Command::new("bar")
2554 .subcommand(Command::new("help").arg(Arg::new("arg").action(ArgAction::Set)))
2555 .subcommand(Command::new("not_help").arg(Arg::new("arg").action(ArgAction::Set)))
2556 .disable_help_subcommand(true);
2557 let matches = cmd.try_get_matches_from(["bar", "help", "foo"]).unwrap();
2558 assert_eq!(
2559 matches
2560 .subcommand_matches("help")
2561 .unwrap()
2562 .get_one::<String>("arg")
2563 .map(|v| v.as_str()),
2564 Some("foo")
2565 );
2566 }
2567
2568 #[test]
override_help_flag_using_long()2569 fn override_help_flag_using_long() {
2570 let cmd = Command::new("foo")
2571 .subcommand(Command::new("help").long_flag("help"))
2572 .disable_help_flag(true)
2573 .disable_help_subcommand(true);
2574 let matches = cmd.try_get_matches_from(["foo", "--help"]).unwrap();
2575 assert!(matches.subcommand_matches("help").is_some());
2576 }
2577
2578 #[test]
override_help_flag_using_short()2579 fn override_help_flag_using_short() {
2580 let cmd = Command::new("foo")
2581 .disable_help_flag(true)
2582 .disable_help_subcommand(true)
2583 .subcommand(Command::new("help").short_flag('h'));
2584 let matches = cmd.try_get_matches_from(["foo", "-h"]).unwrap();
2585 assert!(matches.subcommand_matches("help").is_some());
2586 }
2587
2588 #[test]
subcommand_help_doesnt_have_useless_help_flag()2589 fn subcommand_help_doesnt_have_useless_help_flag() {
2590 // The main care-about is that the docs and behavior match. Since the `help` subcommand
2591 // currently ignores the `--help` flag, the output shouldn't have it.
2592 let cmd = Command::new("example").subcommand(Command::new("test").about("Subcommand"));
2593
2594 utils::assert_output(
2595 cmd,
2596 "example help help",
2597 "\
2598 Print this message or the help of the given subcommand(s)
2599
2600 Usage: example help [COMMAND]...
2601
2602 Arguments:
2603 [COMMAND]... Print help for the subcommand(s)
2604 ",
2605 false,
2606 );
2607 }
2608
2609 #[test]
disable_help_flag_affects_help_subcommand()2610 fn disable_help_flag_affects_help_subcommand() {
2611 let mut cmd = Command::new("test_app")
2612 .disable_help_flag(true)
2613 .subcommand(Command::new("test").about("Subcommand"));
2614 cmd.build();
2615
2616 let args = cmd
2617 .find_subcommand("help")
2618 .unwrap()
2619 .get_arguments()
2620 .map(|a| a.get_id().as_str())
2621 .collect::<Vec<_>>();
2622 assert!(
2623 !args.contains(&"help"),
2624 "`help` should not be present: {:?}",
2625 args
2626 );
2627 }
2628
2629 #[test]
dont_propagate_version_to_help_subcommand()2630 fn dont_propagate_version_to_help_subcommand() {
2631 let cmd = clap::Command::new("example")
2632 .version("1.0")
2633 .propagate_version(true)
2634 .subcommand(clap::Command::new("subcommand"));
2635
2636 utils::assert_output(
2637 cmd.clone(),
2638 "example help help",
2639 "\
2640 Print this message or the help of the given subcommand(s)
2641
2642 Usage: example help [COMMAND]...
2643
2644 Arguments:
2645 [COMMAND]... Print help for the subcommand(s)
2646 ",
2647 false,
2648 );
2649
2650 cmd.debug_assert();
2651 }
2652
2653 #[test]
help_without_short()2654 fn help_without_short() {
2655 let mut cmd = clap::Command::new("test")
2656 .arg(arg!(-h --hex <NUM>).required(true))
2657 .arg(arg!(--help).action(ArgAction::Help))
2658 .disable_help_flag(true);
2659
2660 cmd.build();
2661 let help = cmd.get_arguments().find(|a| a.get_id() == "help").unwrap();
2662 assert_eq!(help.get_short(), None);
2663
2664 let m = cmd.try_get_matches_from(["test", "-h", "0x100"]).unwrap();
2665 assert_eq!(
2666 m.get_one::<String>("hex").map(|v| v.as_str()),
2667 Some("0x100")
2668 );
2669 }
2670
2671 #[test]
parent_cmd_req_in_usage_with_help_flag()2672 fn parent_cmd_req_in_usage_with_help_flag() {
2673 static EXPECTED: &str = "\
2674 some
2675
2676 Usage: parent <TARGET> <ARGS> test
2677
2678 Options:
2679 -h, --help Print help
2680 ";
2681 let cmd = Command::new("parent")
2682 .version("0.1")
2683 .arg(Arg::new("TARGET").required(true).help("some"))
2684 .arg(
2685 Arg::new("ARGS")
2686 .action(ArgAction::Set)
2687 .required(true)
2688 .help("some"),
2689 )
2690 .subcommand(Command::new("test").about("some"));
2691 utils::assert_output(cmd, "parent test --help", EXPECTED, false);
2692 }
2693
2694 #[test]
parent_cmd_req_in_usage_with_help_subcommand()2695 fn parent_cmd_req_in_usage_with_help_subcommand() {
2696 static EXPECTED: &str = "\
2697 some
2698
2699 Usage: parent <TARGET> <ARGS> test
2700
2701 Options:
2702 -h, --help Print help
2703 ";
2704 let cmd = Command::new("parent")
2705 .version("0.1")
2706 .arg(Arg::new("TARGET").required(true).help("some"))
2707 .arg(
2708 Arg::new("ARGS")
2709 .action(ArgAction::Set)
2710 .required(true)
2711 .help("some"),
2712 )
2713 .subcommand(Command::new("test").about("some"));
2714 utils::assert_output(cmd, "parent help test", EXPECTED, false);
2715 }
2716
2717 #[test]
parent_cmd_req_in_usage_with_render_help()2718 fn parent_cmd_req_in_usage_with_render_help() {
2719 static EXPECTED: &str = "\
2720 some
2721
2722 Usage: parent <TARGET> <ARGS> test
2723
2724 Options:
2725 -h, --help Print help
2726 ";
2727 let mut cmd = Command::new("parent")
2728 .version("0.1")
2729 .arg(Arg::new("TARGET").required(true).help("some"))
2730 .arg(
2731 Arg::new("ARGS")
2732 .action(ArgAction::Set)
2733 .required(true)
2734 .help("some"),
2735 )
2736 .subcommand(Command::new("test").about("some"));
2737 cmd.build();
2738 let subcmd = cmd.find_subcommand_mut("test").unwrap();
2739
2740 let help = subcmd.render_help().to_string();
2741 utils::assert_eq(EXPECTED, help);
2742 }
2743
2744 #[test]
parent_cmd_req_ignored_when_negates_reqs()2745 fn parent_cmd_req_ignored_when_negates_reqs() {
2746 static MULTI_SC_HELP: &str = "\
2747 Usage: ctest subcmd
2748
2749 Options:
2750 -h, --help Print help
2751 ";
2752
2753 let cmd = Command::new("ctest")
2754 .arg(arg!(<input>))
2755 .subcommand_negates_reqs(true)
2756 .subcommand(Command::new("subcmd"));
2757 utils::assert_output(cmd, "ctest subcmd --help", MULTI_SC_HELP, false);
2758 }
2759
2760 #[test]
parent_cmd_req_ignored_when_conflicts()2761 fn parent_cmd_req_ignored_when_conflicts() {
2762 static MULTI_SC_HELP: &str = "\
2763 Usage: ctest subcmd
2764
2765 Options:
2766 -h, --help Print help
2767 ";
2768
2769 let cmd = Command::new("ctest")
2770 .arg(arg!(<input>))
2771 .args_conflicts_with_subcommands(true)
2772 .subcommand(Command::new("subcmd"));
2773 utils::assert_output(cmd, "ctest subcmd --help", MULTI_SC_HELP, false);
2774 }
2775
2776 #[test]
no_wrap_help()2777 fn no_wrap_help() {
2778 let cmd = Command::new("ctest")
2779 .term_width(0)
2780 .override_help(MULTI_SC_HELP);
2781 utils::assert_output(cmd, "ctest --help", MULTI_SC_HELP, false);
2782 }
2783
2784 #[test]
display_name_default()2785 fn display_name_default() {
2786 let mut cmd = Command::new("app").bin_name("app.exe");
2787 cmd.build();
2788 assert_eq!(cmd.get_display_name(), None);
2789 }
2790
2791 #[test]
display_name_explicit()2792 fn display_name_explicit() {
2793 let mut cmd = Command::new("app")
2794 .bin_name("app.exe")
2795 .display_name("app.display");
2796 cmd.build();
2797 assert_eq!(cmd.get_display_name(), Some("app.display"));
2798 }
2799
2800 #[test]
display_name_subcommand_default()2801 fn display_name_subcommand_default() {
2802 let mut cmd = Command::new("parent").subcommand(Command::new("child").bin_name("child.exe"));
2803 cmd.build();
2804 assert_eq!(
2805 cmd.find_subcommand("child").unwrap().get_display_name(),
2806 Some("parent-child")
2807 );
2808 }
2809
2810 #[test]
display_name_subcommand_explicit()2811 fn display_name_subcommand_explicit() {
2812 let mut cmd = Command::new("parent").subcommand(
2813 Command::new("child")
2814 .bin_name("child.exe")
2815 .display_name("child.display"),
2816 );
2817 cmd.build();
2818 assert_eq!(
2819 cmd.find_subcommand("child").unwrap().get_display_name(),
2820 Some("child.display")
2821 );
2822 }
2823