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]
680 #[cfg(feature = "wrap_help")]
issue_626_panic()681 fn issue_626_panic() {
682 static ISSUE_626_PANIC: &str = "\
683 Usage: ctest [OPTIONS]
684
685 Options:
686 -c, --cafe <FILE>
687 La culture du café est très développée
688 dans de nombreux pays à climat chaud
689 d\'Amérique, d\'Afrique et d\'Asie, dans des
690 plantations qui sont cultivées pour les
691 marchés d\'exportation. Le café est souvent
692 une contribution majeure aux exportations
693 des régions productrices.
694 -h, --help
695 Print help
696 -V, --version
697 Print version
698 ";
699
700 let cmd = Command::new("ctest")
701 .version("0.1")
702 .term_width(52)
703 .arg(Arg::new("cafe")
704 .short('c')
705 .long("cafe")
706 .value_name("FILE")
707 .help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
708 d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
709 Le café est souvent une contribution majeure aux exportations des régions productrices.")
710 .action(ArgAction::Set));
711 utils::assert_output(cmd, "ctest --help", ISSUE_626_PANIC, false);
712 }
713
714 #[test]
715 #[cfg(feature = "wrap_help")]
issue_626_variable_panic()716 fn issue_626_variable_panic() {
717 for i in 10..320 {
718 let _ = Command::new("ctest")
719 .version("0.1")
720 .term_width(i)
721 .arg(Arg::new("cafe")
722 .short('c')
723 .long("cafe")
724 .value_name("FILE")
725 .help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
726 d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
727 Le café est souvent une contribution majeure aux exportations des régions productrices.")
728 .action(ArgAction::Set))
729 .try_get_matches_from(vec!["ctest", "--help"]);
730 }
731 }
732
733 #[test]
734 #[cfg(feature = "wrap_help")]
final_word_wrapping()735 fn final_word_wrapping() {
736 static FINAL_WORD_WRAPPING: &str = "\
737 Usage: ctest
738
739 Options:
740 -h, --help
741 Print help
742 -V, --version
743 Print version
744 ";
745
746 let cmd = Command::new("ctest").version("0.1").term_width(24);
747 utils::assert_output(cmd, "ctest --help", FINAL_WORD_WRAPPING, false);
748 }
749
750 #[test]
751 #[cfg(feature = "wrap_help")]
wrapping_newline_chars()752 fn wrapping_newline_chars() {
753 static WRAPPING_NEWLINE_CHARS: &str = "\
754 Usage: ctest [mode]
755
756 Arguments:
757 [mode] x, max, maximum 20 characters, contains symbols.
758 l, long Copy-friendly, 14 characters,
759 contains symbols.
760 m, med, medium Copy-friendly, 8 characters,
761 contains symbols.
762
763 Options:
764 -h, --help Print help
765 -V, --version Print version
766 ";
767
768 let cmd = Command::new("ctest")
769 .version("0.1")
770 .term_width(60)
771 .arg(Arg::new("mode").help(
772 "x, max, maximum 20 characters, contains symbols.\n\
773 l, long Copy-friendly, 14 characters, contains symbols.\n\
774 m, med, medium Copy-friendly, 8 characters, contains symbols.\n",
775 ));
776 utils::assert_output(cmd, "ctest --help", WRAPPING_NEWLINE_CHARS, false);
777 }
778
779 #[test]
780 #[cfg(feature = "wrap_help")]
wrapping_newline_variables()781 fn wrapping_newline_variables() {
782 static WRAPPING_NEWLINE_CHARS: &str = "\
783 Usage: ctest [mode]
784
785 Arguments:
786 [mode] x, max, maximum 20 characters, contains symbols.
787 l, long Copy-friendly, 14 characters,
788 contains symbols.
789 m, med, medium Copy-friendly, 8 characters,
790 contains symbols.
791
792 Options:
793 -h, --help Print help
794 -V, --version Print version
795 ";
796
797 let cmd = Command::new("ctest")
798 .version("0.1")
799 .term_width(60)
800 .arg(Arg::new("mode").help(
801 "x, max, maximum 20 characters, contains symbols.{n}\
802 l, long Copy-friendly, 14 characters, contains symbols.{n}\
803 m, med, medium Copy-friendly, 8 characters, contains symbols.{n}",
804 ));
805 utils::assert_output(cmd, "ctest --help", WRAPPING_NEWLINE_CHARS, false);
806 }
807
808 #[test]
809 #[cfg(feature = "wrap_help")]
dont_wrap_urls()810 fn dont_wrap_urls() {
811 let cmd = Command::new("Example")
812 .term_width(30)
813 .subcommand(Command::new("update").arg(
814 Arg::new("force-non-host")
815 .help("Install toolchains that require an emulator. See https://github.com/rust-lang/rustup/wiki/Non-host-toolchains")
816 .long("force-non-host")
817 .action(ArgAction::SetTrue))
818 );
819
820 const EXPECTED: &str = "\
821 Usage: Example update [OPTIONS]
822
823 Options:
824 --force-non-host
825 Install toolchains
826 that require an
827 emulator. See
828 https://github.com/rust-lang/rustup/wiki/Non-host-toolchains
829 -h, --help
830 Print help
831 ";
832 utils::assert_output(cmd, "Example update --help", EXPECTED, false);
833 }
834
835 static OLD_NEWLINE_CHARS: &str = "\
836 Usage: ctest [OPTIONS]
837
838 Options:
839 -m Some help with some wrapping
840 (Defaults to something)
841 -h, --help Print help
842 -V, --version Print version
843 ";
844
845 #[test]
old_newline_chars()846 fn old_newline_chars() {
847 let cmd = Command::new("ctest").version("0.1").arg(
848 Arg::new("mode")
849 .short('m')
850 .action(ArgAction::SetTrue)
851 .help("Some help with some wrapping\n(Defaults to something)"),
852 );
853 utils::assert_output(cmd, "ctest --help", OLD_NEWLINE_CHARS, false);
854 }
855
856 #[test]
old_newline_variables()857 fn old_newline_variables() {
858 let cmd = Command::new("ctest").version("0.1").arg(
859 Arg::new("mode")
860 .short('m')
861 .action(ArgAction::SetTrue)
862 .help("Some help with some wrapping{n}(Defaults to something)"),
863 );
864 utils::assert_output(cmd, "ctest --help", OLD_NEWLINE_CHARS, false);
865 }
866
867 #[test]
868 #[cfg(feature = "wrap_help")]
issue_688_hide_pos_vals()869 fn issue_688_hide_pos_vals() {
870 static ISSUE_688: &str = "\
871 Usage: ctest [OPTIONS]
872
873 Options:
874 --filter <filter> Sets the filter, or sampling method, to use for interpolation when resizing the particle
875 images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic, Gaussian,
876 Lanczos3]
877 -h, --help Print help
878 -V, --version Print version
879 ";
880
881 let filter_values = ["Nearest", "Linear", "Cubic", "Gaussian", "Lanczos3"];
882
883 let app1 = Command::new("ctest")
884 .version("0.1")
885 .term_width(120)
886 .hide_possible_values(true)
887 .arg(Arg::new("filter")
888 .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \
889 images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic, Gaussian, Lanczos3]")
890 .long("filter")
891 .value_parser(filter_values)
892 .action(ArgAction::Set));
893 utils::assert_output(app1, "ctest --help", ISSUE_688, false);
894
895 let app2 = Command::new("ctest")
896 .version("0.1")
897 .term_width(120)
898 .arg(Arg::new("filter")
899 .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \
900 images. The default is Linear (Bilinear).")
901 .long("filter")
902 .value_parser(filter_values)
903 .action(ArgAction::Set));
904 utils::assert_output(app2, "ctest --help", ISSUE_688, false);
905
906 let app3 = Command::new("ctest")
907 .version("0.1")
908 .term_width(120)
909 .arg(Arg::new("filter")
910 .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \
911 images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic, Gaussian, Lanczos3]")
912 .long("filter")
913 .action(ArgAction::Set));
914 utils::assert_output(app3, "ctest --help", ISSUE_688, false);
915 }
916
917 #[test]
issue_702_multiple_values()918 fn issue_702_multiple_values() {
919 static ISSUE_702: &str = "\
920 bar
921
922 Usage: myapp [OPTIONS] [arg1] [arg2]...
923
924 Arguments:
925 [arg1] some option
926 [arg2]... some option
927
928 Options:
929 -s, --some <some> some option
930 -o, --other <other> some other option
931 -l, --label <label>... a label
932 -h, --help Print help
933 -V, --version Print version
934 ";
935
936 let cmd = Command::new("myapp")
937 .version("1.0")
938 .author("foo")
939 .about("bar")
940 .arg(Arg::new("arg1").help("some option"))
941 .arg(
942 Arg::new("arg2")
943 .action(ArgAction::Set)
944 .num_args(1..)
945 .help("some option"),
946 )
947 .arg(
948 Arg::new("some")
949 .help("some option")
950 .short('s')
951 .long("some")
952 .action(ArgAction::Set),
953 )
954 .arg(
955 Arg::new("other")
956 .help("some other option")
957 .short('o')
958 .long("other")
959 .action(ArgAction::Set),
960 )
961 .arg(
962 Arg::new("label")
963 .help("a label")
964 .short('l')
965 .long("label")
966 .num_args(1..)
967 .action(ArgAction::Set),
968 );
969 utils::assert_output(cmd, "myapp --help", ISSUE_702, false);
970 }
971
972 #[test]
long_about()973 fn long_about() {
974 static LONG_ABOUT: &str = "\
975 something really really long, with
976 multiple lines of text
977 that should be displayed
978
979 Usage: myapp [arg1]
980
981 Arguments:
982 [arg1]
983 some option
984
985 Options:
986 -h, --help
987 Print help (see a summary with '-h')
988
989 -V, --version
990 Print version
991 ";
992
993 let cmd = Command::new("myapp")
994 .version("1.0")
995 .author("foo")
996 .about("bar")
997 .long_about(
998 "something really really long, with\nmultiple lines of text\nthat should be displayed",
999 )
1000 .arg(Arg::new("arg1").help("some option"));
1001 utils::assert_output(cmd, "myapp --help", LONG_ABOUT, false);
1002 }
1003
1004 #[test]
ripgrep_usage()1005 fn ripgrep_usage() {
1006 static RIPGREP_USAGE: &str = "\
1007 Usage: rg [OPTIONS] <pattern> [<path> ...]
1008 rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
1009 rg [OPTIONS] --files [<path> ...]
1010 rg [OPTIONS] --type-list
1011
1012 Options:
1013 -h, --help Print help
1014 -V, --version Print version
1015 ";
1016
1017 let cmd = Command::new("ripgrep").version("0.5").override_usage(
1018 "rg [OPTIONS] <pattern> [<path> ...]
1019 rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
1020 rg [OPTIONS] --files [<path> ...]
1021 rg [OPTIONS] --type-list",
1022 );
1023
1024 utils::assert_output(cmd, "rg --help", RIPGREP_USAGE, false);
1025 }
1026
1027 #[test]
ripgrep_usage_using_templates()1028 fn ripgrep_usage_using_templates() {
1029 static RIPGREP_USAGE: &str = "\
1030 ripgrep 0.5
1031
1032 Usage: rg [OPTIONS] <pattern> [<path> ...]
1033 rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
1034 rg [OPTIONS] --files [<path> ...]
1035 rg [OPTIONS] --type-list
1036
1037 Options:
1038 -h, --help Print help
1039 -V, --version Print version
1040 ";
1041
1042 #[cfg(not(feature = "unstable-v5"))]
1043 let cmd = Command::new("ripgrep")
1044 .version("0.5")
1045 .override_usage(
1046 "\
1047 rg [OPTIONS] <pattern> [<path> ...]
1048 rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
1049 rg [OPTIONS] --files [<path> ...]
1050 rg [OPTIONS] --type-list",
1051 )
1052 .help_template(
1053 "\
1054 {bin} {version}
1055
1056 Usage: {usage}
1057
1058 Options:
1059 {options}",
1060 );
1061
1062 #[cfg(feature = "unstable-v5")]
1063 let cmd = Command::new("ripgrep")
1064 .version("0.5")
1065 .override_usage(
1066 "\
1067 rg [OPTIONS] <pattern> [<path> ...]
1068 rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
1069 rg [OPTIONS] --files [<path> ...]
1070 rg [OPTIONS] --type-list",
1071 )
1072 .help_template(
1073 "\
1074 {name} {version}
1075
1076 Usage: {usage}
1077
1078 Options:
1079 {options}",
1080 );
1081
1082 utils::assert_output(cmd, "rg --help", RIPGREP_USAGE, false);
1083 }
1084
1085 #[test]
sc_negates_reqs()1086 fn sc_negates_reqs() {
1087 static SC_NEGATES_REQS: &str = "\
1088 Usage: prog --opt <FILE> [PATH]
1089 prog [PATH] <COMMAND>
1090
1091 Commands:
1092 test
1093 help Print this message or the help of the given subcommand(s)
1094
1095 Arguments:
1096 [PATH] help
1097
1098 Options:
1099 -o, --opt <FILE> tests options
1100 -h, --help Print help
1101 -V, --version Print version
1102 ";
1103
1104 let cmd = Command::new("prog")
1105 .version("1.0")
1106 .subcommand_negates_reqs(true)
1107 .arg(arg!(-o --opt <FILE> "tests options").required(true))
1108 .arg(Arg::new("PATH").help("help"))
1109 .subcommand(Command::new("test"));
1110 utils::assert_output(cmd, "prog --help", SC_NEGATES_REQS, false);
1111 }
1112
1113 #[test]
hide_args()1114 fn hide_args() {
1115 static HIDDEN_ARGS: &str = "\
1116 Usage: prog [OPTIONS]
1117
1118 Options:
1119 -f, --flag testing flags
1120 -o, --opt <FILE> tests options
1121 -h, --help Print help
1122 -V, --version Print version
1123 ";
1124
1125 let cmd = Command::new("prog")
1126 .version("1.0")
1127 .arg(arg!(-f --flag "testing flags"))
1128 .arg(arg!(-o --opt <FILE> "tests options"))
1129 .arg(Arg::new("pos").hide(true));
1130 utils::assert_output(cmd, "prog --help", HIDDEN_ARGS, false);
1131 }
1132
1133 #[test]
args_negate_sc()1134 fn args_negate_sc() {
1135 static ARGS_NEGATE_SC: &str = "\
1136 Usage: prog [OPTIONS] [PATH]
1137 prog <COMMAND>
1138
1139 Commands:
1140 test
1141 help Print this message or the help of the given subcommand(s)
1142
1143 Arguments:
1144 [PATH] help
1145
1146 Options:
1147 -f, --flag testing flags
1148 -o, --opt <FILE> tests options
1149 -h, --help Print help
1150 -V, --version Print version
1151 ";
1152
1153 let cmd = Command::new("prog")
1154 .version("1.0")
1155 .args_conflicts_with_subcommands(true)
1156 .arg(arg!(-f --flag "testing flags"))
1157 .arg(arg!(-o --opt <FILE> "tests options"))
1158 .arg(Arg::new("PATH").help("help"))
1159 .subcommand(Command::new("test"));
1160 utils::assert_output(cmd, "prog --help", ARGS_NEGATE_SC, false);
1161 }
1162
1163 #[test]
issue_1046_hide_scs()1164 fn issue_1046_hide_scs() {
1165 static ISSUE_1046_HIDDEN_SCS: &str = "\
1166 Usage: prog [OPTIONS] [PATH]
1167
1168 Arguments:
1169 [PATH] some
1170
1171 Options:
1172 -f, --flag testing flags
1173 -o, --opt <FILE> tests options
1174 -h, --help Print help
1175 -V, --version Print version
1176 ";
1177
1178 let cmd = Command::new("prog")
1179 .version("1.0")
1180 .arg(arg!(-f --flag "testing flags"))
1181 .arg(arg!(-o --opt <FILE> "tests options"))
1182 .arg(Arg::new("PATH").help("some"))
1183 .subcommand(Command::new("test").hide(true));
1184 utils::assert_output(cmd, "prog --help", ISSUE_1046_HIDDEN_SCS, false);
1185 }
1186
1187 #[test]
1188 #[cfg(feature = "wrap_help")]
issue_777_wrap_all_things()1189 fn issue_777_wrap_all_things() {
1190 static ISSUE_777: &str = "A cmd with a crazy very long long
1191 long name hahaha 1.0
1192 Some Very Long Name and crazy long
1193 email <email@server.com>
1194 Show how the about text is not
1195 wrapped
1196
1197 Usage: ctest
1198
1199 Options:
1200 -h, --help Print help
1201 -V, --version Print version
1202 ";
1203
1204 let cmd = Command::new("A cmd with a crazy very long long long name hahaha")
1205 .version("1.0")
1206 .author("Some Very Long Name and crazy long email <email@server.com>")
1207 .about("Show how the about text is not wrapped")
1208 .help_template(utils::FULL_TEMPLATE)
1209 .term_width(35);
1210 utils::assert_output(cmd, "ctest --help", ISSUE_777, false);
1211 }
1212
1213 static OVERRIDE_HELP_SHORT: &str = "\
1214 Usage: test
1215
1216 Options:
1217 -H, --help Print help
1218 -V, --version Print version
1219 ";
1220
1221 #[test]
override_help_short()1222 fn override_help_short() {
1223 let cmd = Command::new("test")
1224 .version("0.1")
1225 .arg(arg!(-H --help "Print help").action(ArgAction::Help))
1226 .disable_help_flag(true);
1227
1228 utils::assert_output(cmd.clone(), "test --help", OVERRIDE_HELP_SHORT, false);
1229 utils::assert_output(cmd, "test -H", OVERRIDE_HELP_SHORT, false);
1230 }
1231
1232 static OVERRIDE_HELP_LONG: &str = "\
1233 Usage: test [OPTIONS]
1234
1235 Options:
1236 -h, --hell Print help
1237 -V, --version Print version
1238 ";
1239
1240 #[test]
override_help_long()1241 fn override_help_long() {
1242 let cmd = Command::new("test")
1243 .version("0.1")
1244 .arg(arg!(-h --hell "Print help").action(ArgAction::Help))
1245 .disable_help_flag(true);
1246
1247 utils::assert_output(cmd.clone(), "test --hell", OVERRIDE_HELP_LONG, false);
1248 utils::assert_output(cmd, "test -h", OVERRIDE_HELP_LONG, false);
1249 }
1250
1251 static OVERRIDE_HELP_ABOUT: &str = "\
1252 Usage: test
1253
1254 Options:
1255 -h, --help Print custom help information
1256 -V, --version Print version
1257 ";
1258
1259 #[test]
override_help_about()1260 fn override_help_about() {
1261 let cmd = Command::new("test")
1262 .version("0.1")
1263 .arg(arg!(-h --help "Print custom help information").action(ArgAction::Help))
1264 .disable_help_flag(true);
1265
1266 utils::assert_output(cmd.clone(), "test --help", OVERRIDE_HELP_ABOUT, false);
1267 utils::assert_output(cmd, "test -h", OVERRIDE_HELP_ABOUT, false);
1268 }
1269
1270 #[test]
1271 #[cfg(debug_assertions)]
1272 #[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()1273 fn arg_id_conflict_with_help() {
1274 Command::new("conflict")
1275 .arg(Arg::new("help").short('?').action(ArgAction::SetTrue))
1276 .build();
1277 }
1278
1279 #[test]
1280 #[cfg(debug_assertions)]
1281 #[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()1282 fn arg_short_conflict_with_help() {
1283 Command::new("conflict")
1284 .arg(Arg::new("home").short('h').action(ArgAction::SetTrue))
1285 .build();
1286 }
1287
1288 #[test]
1289 #[cfg(debug_assertions)]
1290 #[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()1291 fn arg_long_conflict_with_help() {
1292 Command::new("conflict")
1293 .arg(
1294 Arg::new("custom-help")
1295 .long("help")
1296 .action(ArgAction::SetTrue),
1297 )
1298 .build();
1299 }
1300
1301 #[test]
last_arg_mult_usage()1302 fn last_arg_mult_usage() {
1303 static LAST_ARG: &str = "\
1304 Usage: last <TARGET> [CORPUS] [-- <ARGS>...]
1305
1306 Arguments:
1307 <TARGET> some
1308 [CORPUS] some
1309 [ARGS]... some
1310
1311 Options:
1312 -h, --help Print help
1313 -V, --version Print version
1314 ";
1315
1316 let cmd = Command::new("last")
1317 .version("0.1")
1318 .arg(Arg::new("TARGET").required(true).help("some"))
1319 .arg(Arg::new("CORPUS").help("some"))
1320 .arg(
1321 Arg::new("ARGS")
1322 .action(ArgAction::Set)
1323 .num_args(1..)
1324 .last(true)
1325 .help("some"),
1326 );
1327 utils::assert_output(cmd, "last --help", LAST_ARG, false);
1328 }
1329
1330 #[test]
last_arg_mult_usage_req()1331 fn last_arg_mult_usage_req() {
1332 static LAST_ARG_REQ: &str = "\
1333 Usage: last <TARGET> [CORPUS] -- <ARGS>...
1334
1335 Arguments:
1336 <TARGET> some
1337 [CORPUS] some
1338 <ARGS>... some
1339
1340 Options:
1341 -h, --help Print help
1342 -V, --version Print version
1343 ";
1344
1345 let cmd = Command::new("last")
1346 .version("0.1")
1347 .arg(Arg::new("TARGET").required(true).help("some"))
1348 .arg(Arg::new("CORPUS").help("some"))
1349 .arg(
1350 Arg::new("ARGS")
1351 .action(ArgAction::Set)
1352 .num_args(1..)
1353 .last(true)
1354 .required(true)
1355 .help("some"),
1356 );
1357 utils::assert_output(cmd, "last --help", LAST_ARG_REQ, false);
1358 }
1359
1360 #[test]
last_arg_mult_usage_req_with_sc()1361 fn last_arg_mult_usage_req_with_sc() {
1362 static LAST_ARG_REQ_SC: &str = "\
1363 Usage: last <TARGET> [CORPUS] -- <ARGS>...
1364 last [TARGET] [CORPUS] <COMMAND>
1365
1366 Commands:
1367 test some
1368 help Print this message or the help of the given subcommand(s)
1369
1370 Arguments:
1371 <TARGET> some
1372 [CORPUS] some
1373 <ARGS>... some
1374
1375 Options:
1376 -h, --help Print help
1377 -V, --version Print version
1378 ";
1379
1380 let cmd = Command::new("last")
1381 .version("0.1")
1382 .subcommand_negates_reqs(true)
1383 .arg(Arg::new("TARGET").required(true).help("some"))
1384 .arg(Arg::new("CORPUS").help("some"))
1385 .arg(
1386 Arg::new("ARGS")
1387 .action(ArgAction::Set)
1388 .num_args(1..)
1389 .last(true)
1390 .required(true)
1391 .help("some"),
1392 )
1393 .subcommand(Command::new("test").about("some"));
1394 utils::assert_output(cmd, "last --help", LAST_ARG_REQ_SC, false);
1395 }
1396
1397 #[test]
last_arg_mult_usage_with_sc()1398 fn last_arg_mult_usage_with_sc() {
1399 static LAST_ARG_SC: &str = "\
1400 Usage: last <TARGET> [CORPUS] [-- <ARGS>...]
1401 last <COMMAND>
1402
1403 Commands:
1404 test some
1405 help Print this message or the help of the given subcommand(s)
1406
1407 Arguments:
1408 <TARGET> some
1409 [CORPUS] some
1410 [ARGS]... some
1411
1412 Options:
1413 -h, --help Print help
1414 -V, --version Print version
1415 ";
1416
1417 let cmd = Command::new("last")
1418 .version("0.1")
1419 .args_conflicts_with_subcommands(true)
1420 .arg(Arg::new("TARGET").required(true).help("some"))
1421 .arg(Arg::new("CORPUS").help("some"))
1422 .arg(
1423 Arg::new("ARGS")
1424 .action(ArgAction::Set)
1425 .num_args(1..)
1426 .last(true)
1427 .help("some"),
1428 )
1429 .subcommand(Command::new("test").about("some"));
1430 utils::assert_output(cmd, "last --help", LAST_ARG_SC, false);
1431 }
1432
1433 static HIDE_DEFAULT_VAL: &str = "\
1434 Usage: default [OPTIONS]
1435
1436 Options:
1437 --arg <argument> Pass an argument to the program. [default: default-argument]
1438 -h, --help Print help
1439 -V, --version Print version
1440 ";
1441
1442 #[test]
hide_default_val()1443 fn hide_default_val() {
1444 let app1 = Command::new("default").version("0.1").term_width(120).arg(
1445 Arg::new("argument")
1446 .help("Pass an argument to the program. [default: default-argument]")
1447 .long("arg")
1448 .default_value("default-argument")
1449 .hide_default_value(true),
1450 );
1451 utils::assert_output(app1, "default --help", HIDE_DEFAULT_VAL, false);
1452
1453 let app2 = Command::new("default").version("0.1").term_width(120).arg(
1454 Arg::new("argument")
1455 .help("Pass an argument to the program.")
1456 .long("arg")
1457 .default_value("default-argument"),
1458 );
1459 utils::assert_output(app2, "default --help", HIDE_DEFAULT_VAL, false);
1460 }
1461
1462 #[test]
1463 #[cfg(feature = "wrap_help")]
escaped_whitespace_values()1464 fn escaped_whitespace_values() {
1465 static ESCAPED_DEFAULT_VAL: &str = "\
1466 Usage: default [OPTIONS]
1467
1468 Options:
1469 --arg <argument> Pass an argument to the program. [default: \"\\n\"] [possible values: normal, \" \", \"\\n\", \"\\t\",
1470 other]
1471 -h, --help Print help
1472 -V, --version Print version
1473 ";
1474
1475 let app1 = Command::new("default").version("0.1").term_width(120).arg(
1476 Arg::new("argument")
1477 .help("Pass an argument to the program.")
1478 .long("arg")
1479 .default_value("\n")
1480 .value_parser(["normal", " ", "\n", "\t", "other"]),
1481 );
1482 utils::assert_output(app1, "default --help", ESCAPED_DEFAULT_VAL, false);
1483 }
1484
issue_1112_setup() -> Command1485 fn issue_1112_setup() -> Command {
1486 Command::new("test")
1487 .version("1.3")
1488 .disable_help_flag(true)
1489 .arg(
1490 Arg::new("help1")
1491 .long("help")
1492 .short('h')
1493 .help("some help")
1494 .action(ArgAction::SetTrue),
1495 )
1496 .subcommand(
1497 Command::new("foo").arg(
1498 Arg::new("help1")
1499 .long("help")
1500 .short('h')
1501 .help("some help")
1502 .action(ArgAction::SetTrue),
1503 ),
1504 )
1505 }
1506
1507 #[test]
prefer_user_help_long_1112()1508 fn prefer_user_help_long_1112() {
1509 let m = issue_1112_setup().try_get_matches_from(vec!["test", "--help"]);
1510
1511 assert!(m.is_ok(), "{}", m.unwrap_err());
1512 let m = m.unwrap();
1513 assert!(*m.get_one::<bool>("help1").expect("defaulted by clap"));
1514 }
1515
1516 #[test]
prefer_user_help_short_1112()1517 fn prefer_user_help_short_1112() {
1518 let m = issue_1112_setup().try_get_matches_from(vec!["test", "-h"]);
1519
1520 assert!(m.is_ok(), "{}", m.unwrap_err());
1521 let m = m.unwrap();
1522 assert!(*m.get_one::<bool>("help1").expect("defaulted by clap"));
1523 }
1524
1525 #[test]
prefer_user_subcmd_help_long_1112()1526 fn prefer_user_subcmd_help_long_1112() {
1527 let m = issue_1112_setup().try_get_matches_from(vec!["test", "foo", "--help"]);
1528
1529 assert!(m.is_ok(), "{}", m.unwrap_err());
1530 let m = m.unwrap();
1531 assert!(*m
1532 .subcommand_matches("foo")
1533 .unwrap()
1534 .get_one::<bool>("help1")
1535 .expect("defaulted by clap"));
1536 }
1537
1538 #[test]
prefer_user_subcmd_help_short_1112()1539 fn prefer_user_subcmd_help_short_1112() {
1540 let m = issue_1112_setup().try_get_matches_from(vec!["test", "foo", "-h"]);
1541
1542 assert!(m.is_ok(), "{}", m.unwrap_err());
1543 let m = m.unwrap();
1544 assert!(m
1545 .subcommand_matches("foo")
1546 .unwrap()
1547 .get_one::<bool>("help1")
1548 .expect("defaulted by clap"));
1549 }
1550
1551 #[test]
issue_1052_require_delim_help()1552 fn issue_1052_require_delim_help() {
1553 static REQUIRE_DELIM_HELP: &str = "\
1554 tests stuff
1555
1556 Usage: test --fake <some> <val>
1557
1558 Options:
1559 -f, --fake <some> <val> some help
1560 -h, --help Print help
1561 -V, --version Print version
1562 ";
1563
1564 let cmd = Command::new("test")
1565 .author("Kevin K.")
1566 .about("tests stuff")
1567 .version("1.3")
1568 .arg(
1569 arg!(-f --fake <s> "some help")
1570 .required(true)
1571 .value_names(["some", "val"])
1572 .action(ArgAction::Set)
1573 .value_delimiter(':'),
1574 );
1575
1576 utils::assert_output(cmd, "test --help", REQUIRE_DELIM_HELP, false);
1577 }
1578
1579 #[test]
custom_headers_headers()1580 fn custom_headers_headers() {
1581 static CUSTOM_HELP_SECTION: &str = "\
1582 does stuff
1583
1584 Usage: test [OPTIONS] --fake <some> <val>
1585
1586 Options:
1587 -f, --fake <some> <val> some help
1588 -h, --help Print help
1589 -V, --version Print version
1590
1591 NETWORKING:
1592 -n, --no-proxy Do not use system proxy settings
1593 --port
1594 ";
1595
1596 let cmd = Command::new("blorp")
1597 .author("Will M.")
1598 .about("does stuff")
1599 .version("1.4")
1600 .arg(
1601 arg!(-f --fake <s> "some help")
1602 .required(true)
1603 .value_names(["some", "val"])
1604 .action(ArgAction::Set)
1605 .value_delimiter(':'),
1606 )
1607 .next_help_heading(Some("NETWORKING"))
1608 .arg(
1609 Arg::new("no-proxy")
1610 .short('n')
1611 .long("no-proxy")
1612 .action(ArgAction::SetTrue)
1613 .help("Do not use system proxy settings"),
1614 )
1615 .args([Arg::new("port").long("port").action(ArgAction::SetTrue)]);
1616
1617 utils::assert_output(cmd, "test --help", CUSTOM_HELP_SECTION, false);
1618 }
1619
1620 static MULTIPLE_CUSTOM_HELP_SECTIONS: &str = "\
1621 does stuff
1622
1623 Usage: test [OPTIONS] --fake <some> <val> --birthday-song <song> --birthday-song-volume <volume>
1624
1625 Options:
1626 -f, --fake <some> <val> some help
1627 --style <style> Choose musical style to play the song
1628 -s, --speed <SPEED> How fast? [possible values: fast, slow]
1629 -h, --help Print help
1630 -V, --version Print version
1631
1632 NETWORKING:
1633 -n, --no-proxy Do not use system proxy settings
1634 -a, --server-addr Set server address
1635
1636 OVERRIDE SPECIAL:
1637 -b, --birthday-song <song> Change which song is played for birthdays
1638
1639 SPECIAL:
1640 -v, --birthday-song-volume <volume> Change the volume of the birthday song
1641 ";
1642
1643 #[test]
multiple_custom_help_headers()1644 fn multiple_custom_help_headers() {
1645 let cmd = Command::new("blorp")
1646 .author("Will M.")
1647 .about("does stuff")
1648 .version("1.4")
1649 .arg(
1650 arg!(-f --fake <s> "some help")
1651 .required(true)
1652 .value_names(["some", "val"])
1653 .action(ArgAction::Set)
1654 .value_delimiter(':'),
1655 )
1656 .next_help_heading(Some("NETWORKING"))
1657 .arg(
1658 Arg::new("no-proxy")
1659 .short('n')
1660 .long("no-proxy")
1661 .action(ArgAction::SetTrue)
1662 .help("Do not use system proxy settings"),
1663 )
1664 .next_help_heading(Some("SPECIAL"))
1665 .arg(
1666 arg!(-b --"birthday-song" <song> "Change which song is played for birthdays")
1667 .required(true)
1668 .help_heading(Some("OVERRIDE SPECIAL")),
1669 )
1670 .arg(arg!(--style <style> "Choose musical style to play the song").help_heading(None))
1671 .arg(
1672 arg!(
1673 -v --"birthday-song-volume" <volume> "Change the volume of the birthday song"
1674 )
1675 .required(true),
1676 )
1677 .next_help_heading(None)
1678 .arg(
1679 Arg::new("server-addr")
1680 .short('a')
1681 .long("server-addr")
1682 .action(ArgAction::SetTrue)
1683 .help("Set server address")
1684 .help_heading(Some("NETWORKING")),
1685 )
1686 .arg(
1687 Arg::new("speed")
1688 .long("speed")
1689 .short('s')
1690 .value_name("SPEED")
1691 .value_parser(["fast", "slow"])
1692 .help("How fast?")
1693 .action(ArgAction::Set),
1694 );
1695
1696 utils::assert_output(cmd, "test --help", MULTIPLE_CUSTOM_HELP_SECTIONS, false);
1697 }
1698
1699 static CUSTOM_HELP_SECTION_HIDDEN_ARGS: &str = "\
1700 does stuff
1701
1702 Usage: test [OPTIONS] --song <song> --song-volume <volume>
1703
1704 Options:
1705 -h, --help Print help (see more with '--help')
1706 -V, --version Print version
1707
1708 OVERRIDE SPECIAL:
1709 -b, --song <song> Change which song is played for birthdays
1710
1711 SPECIAL:
1712 -v, --song-volume <volume> Change the volume of the birthday song
1713 ";
1714
1715 #[test]
custom_help_headers_hide_args()1716 fn custom_help_headers_hide_args() {
1717 let cmd = Command::new("blorp")
1718 .author("Will M.")
1719 .about("does stuff")
1720 .version("1.4")
1721 .next_help_heading(Some("NETWORKING"))
1722 .arg(
1723 Arg::new("no-proxy")
1724 .short('n')
1725 .long("no-proxy")
1726 .help("Do not use system proxy settings")
1727 .hide_short_help(true),
1728 )
1729 .next_help_heading(Some("SPECIAL"))
1730 .arg(
1731 arg!(-b --song <song> "Change which song is played for birthdays")
1732 .required(true)
1733 .help_heading(Some("OVERRIDE SPECIAL")),
1734 )
1735 .arg(
1736 arg!(
1737 -v --"song-volume" <volume> "Change the volume of the birthday song"
1738 )
1739 .required(true),
1740 )
1741 .next_help_heading(None)
1742 .arg(
1743 Arg::new("server-addr")
1744 .short('a')
1745 .long("server-addr")
1746 .help("Set server address")
1747 .help_heading(Some("NETWORKING"))
1748 .hide_short_help(true),
1749 );
1750
1751 utils::assert_output(cmd, "test -h", CUSTOM_HELP_SECTION_HIDDEN_ARGS, false);
1752 }
1753
1754 static ISSUE_897: &str = "\
1755 Long about foo
1756
1757 Usage: ctest foo
1758
1759 Options:
1760 -h, --help
1761 Print help (see a summary with '-h')
1762
1763 -V, --version
1764 Print version
1765 ";
1766
1767 #[test]
show_long_about_issue_897()1768 fn show_long_about_issue_897() {
1769 let cmd = Command::new("ctest").version("0.1").subcommand(
1770 Command::new("foo")
1771 .version("0.1")
1772 .about("About foo")
1773 .long_about("Long about foo"),
1774 );
1775 utils::assert_output(cmd, "ctest foo --help", ISSUE_897, false);
1776 }
1777
1778 static ISSUE_897_SHORT: &str = "\
1779 About foo
1780
1781 Usage: ctest foo
1782
1783 Options:
1784 -h, --help Print help (see more with '--help')
1785 -V, --version Print version
1786 ";
1787
1788 #[test]
show_short_about_issue_897()1789 fn show_short_about_issue_897() {
1790 let cmd = Command::new("ctest").version("0.1").subcommand(
1791 Command::new("foo")
1792 .version("0.1")
1793 .about("About foo")
1794 .long_about("Long about foo"),
1795 );
1796 utils::assert_output(cmd, "ctest foo -h", ISSUE_897_SHORT, false);
1797 }
1798
1799 #[test]
issue_1364_no_short_options()1800 fn issue_1364_no_short_options() {
1801 static ISSUE_1364: &str = "\
1802 Usage: demo [OPTIONS] [FILES]...
1803
1804 Arguments:
1805 [FILES]...
1806
1807 Options:
1808 -f
1809 -h, --help Print help (see more with '--help')
1810 ";
1811
1812 let cmd = Command::new("demo")
1813 .arg(Arg::new("foo").short('f').action(ArgAction::SetTrue))
1814 .arg(
1815 Arg::new("baz")
1816 .short('z')
1817 .value_name("BAZ")
1818 .hide_short_help(true),
1819 )
1820 .arg(
1821 Arg::new("files")
1822 .value_name("FILES")
1823 .action(ArgAction::Set)
1824 .num_args(1..),
1825 );
1826
1827 utils::assert_output(cmd, "demo -h", ISSUE_1364, false);
1828 }
1829
1830 #[rustfmt::skip]
1831 #[test]
issue_1487()1832 fn issue_1487() {
1833 static ISSUE_1487: &str = "\
1834 Usage: ctest <arg1|arg2>
1835
1836 Arguments:
1837 [arg1]
1838 [arg2]
1839
1840 Options:
1841 -h, --help Print help
1842 ";
1843
1844 let cmd = Command::new("test")
1845 .arg(Arg::new("arg1")
1846 .group("group1"))
1847 .arg(Arg::new("arg2")
1848 .group("group1"))
1849 .group(ArgGroup::new("group1")
1850 .args(["arg1", "arg2"])
1851 .required(true));
1852 utils::assert_output(cmd, "ctest -h", ISSUE_1487, false);
1853 }
1854
1855 #[cfg(debug_assertions)]
1856 #[test]
1857 #[should_panic = "Command::help_expected is enabled for the Command"]
help_required_but_not_given()1858 fn help_required_but_not_given() {
1859 Command::new("myapp")
1860 .help_expected(true)
1861 .arg(Arg::new("foo"))
1862 .try_get_matches_from(empty_args())
1863 .unwrap();
1864 }
1865
1866 #[cfg(debug_assertions)]
1867 #[test]
1868 #[should_panic = "Command::help_expected is enabled for the Command"]
help_required_but_not_given_settings_after_args()1869 fn help_required_but_not_given_settings_after_args() {
1870 Command::new("myapp")
1871 .arg(Arg::new("foo"))
1872 .help_expected(true)
1873 .try_get_matches_from(empty_args())
1874 .unwrap();
1875 }
1876
1877 #[cfg(debug_assertions)]
1878 #[test]
1879 #[should_panic = "Command::help_expected is enabled for the Command"]
help_required_but_not_given_for_one_of_two_arguments()1880 fn help_required_but_not_given_for_one_of_two_arguments() {
1881 Command::new("myapp")
1882 .help_expected(true)
1883 .arg(Arg::new("foo"))
1884 .arg(Arg::new("bar").help("It does bar stuff"))
1885 .try_get_matches_from(empty_args())
1886 .unwrap();
1887 }
1888
1889 #[test]
1890 #[should_panic = "List of such arguments: delete"]
help_required_globally()1891 fn help_required_globally() {
1892 Command::new("myapp")
1893 .help_expected(true)
1894 .arg(Arg::new("foo").help("It does foo stuff"))
1895 .subcommand(
1896 Command::new("bar")
1897 .arg(Arg::new("create").help("creates bar"))
1898 .arg(Arg::new("delete")),
1899 )
1900 .try_get_matches_from(empty_args())
1901 .unwrap();
1902 }
1903
1904 #[cfg(debug_assertions)]
1905 #[test]
1906 #[should_panic = "Command::help_expected is enabled for the Command"]
help_required_globally_but_not_given_for_subcommand()1907 fn help_required_globally_but_not_given_for_subcommand() {
1908 Command::new("myapp")
1909 .help_expected(true)
1910 .arg(Arg::new("foo").help("It does foo stuff"))
1911 .subcommand(
1912 Command::new("bar")
1913 .arg(Arg::new("create").help("creates bar"))
1914 .arg(Arg::new("delete")),
1915 )
1916 .try_get_matches_from(empty_args())
1917 .unwrap();
1918 }
1919
1920 #[test]
help_required_and_given_for_subcommand()1921 fn help_required_and_given_for_subcommand() {
1922 Command::new("myapp")
1923 .help_expected(true)
1924 .arg(Arg::new("foo").help("It does foo stuff"))
1925 .subcommand(
1926 Command::new("bar")
1927 .arg(Arg::new("create").help("creates bar"))
1928 .arg(Arg::new("delete").help("deletes bar")),
1929 )
1930 .try_get_matches_from(empty_args())
1931 .unwrap();
1932 }
1933
1934 #[test]
help_required_and_given()1935 fn help_required_and_given() {
1936 Command::new("myapp")
1937 .help_expected(true)
1938 .arg(Arg::new("foo").help("It does foo stuff"))
1939 .try_get_matches_from(empty_args())
1940 .unwrap();
1941 }
1942
1943 #[test]
help_required_and_no_args()1944 fn help_required_and_no_args() {
1945 Command::new("myapp")
1946 .help_expected(true)
1947 .try_get_matches_from(empty_args())
1948 .unwrap();
1949 }
1950
1951 #[test]
issue_1642_long_help_spacing()1952 fn issue_1642_long_help_spacing() {
1953 static ISSUE_1642: &str = "\
1954 Usage: prog [OPTIONS]
1955
1956 Options:
1957 --config
1958 The config file used by the myprog must be in JSON format
1959 with only valid keys and may not contain other nonsense
1960 that cannot be read by this program. Obviously I'm going on
1961 and on, so I'll stop now.
1962
1963 -h, --help
1964 Print help (see a summary with '-h')
1965 ";
1966
1967 let cmd = Command::new("prog").arg(
1968 Arg::new("cfg")
1969 .long("config")
1970 .action(ArgAction::SetTrue)
1971 .long_help(
1972 "The config file used by the myprog must be in JSON format
1973 with only valid keys and may not contain other nonsense
1974 that cannot be read by this program. Obviously I'm going on
1975 and on, so I'll stop now.",
1976 ),
1977 );
1978 utils::assert_output(cmd, "prog --help", ISSUE_1642, false);
1979 }
1980
1981 const AFTER_HELP_NO_ARGS: &str = "\
1982 Usage: myapp
1983
1984 This is after help.
1985 ";
1986
1987 #[test]
after_help_no_args()1988 fn after_help_no_args() {
1989 let mut cmd = Command::new("myapp")
1990 .version("1.0")
1991 .disable_help_flag(true)
1992 .disable_version_flag(true)
1993 .after_help("This is after help.");
1994
1995 let help = cmd.render_help().to_string();
1996
1997 assert_eq!(help, AFTER_HELP_NO_ARGS);
1998 }
1999
2000 #[test]
help_subcmd_help()2001 fn help_subcmd_help() {
2002 static HELP_SUBCMD_HELP: &str = "\
2003 Print this message or the help of the given subcommand(s)
2004
2005 Usage: myapp help [COMMAND]...
2006
2007 Arguments:
2008 [COMMAND]... Print help for the subcommand(s)
2009 ";
2010
2011 let cmd = Command::new("myapp")
2012 .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));
2013
2014 utils::assert_output(cmd.clone(), "myapp help help", HELP_SUBCMD_HELP, false);
2015 }
2016
2017 #[test]
subcmd_help_subcmd_help()2018 fn subcmd_help_subcmd_help() {
2019 static SUBCMD_HELP_SUBCMD_HELP: &str = "\
2020 Print this message or the help of the given subcommand(s)
2021
2022 Usage: myapp subcmd help [COMMAND]...
2023
2024 Arguments:
2025 [COMMAND]... Print help for the subcommand(s)
2026 ";
2027
2028 let cmd = Command::new("myapp")
2029 .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));
2030
2031 utils::assert_output(
2032 cmd.clone(),
2033 "myapp subcmd help help",
2034 SUBCMD_HELP_SUBCMD_HELP,
2035 false,
2036 );
2037 }
2038
2039 #[test]
global_args_should_show_on_toplevel_help_message()2040 fn global_args_should_show_on_toplevel_help_message() {
2041 static HELP: &str = "\
2042 Usage: myapp [OPTIONS] [COMMAND]
2043
2044 Commands:
2045 subcmd\x20\x20
2046 help Print this message or the help of the given subcommand(s)
2047
2048 Options:
2049 -g, --some-global <someglobal>\x20\x20
2050 -h, --help Print help
2051 ";
2052
2053 let cmd = Command::new("myapp")
2054 .arg(
2055 Arg::new("someglobal")
2056 .short('g')
2057 .long("some-global")
2058 .global(true),
2059 )
2060 .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));
2061
2062 utils::assert_output(cmd, "myapp help", HELP, false);
2063 }
2064
2065 #[test]
global_args_should_not_show_on_help_message_for_help_help()2066 fn global_args_should_not_show_on_help_message_for_help_help() {
2067 static HELP_HELP: &str = "\
2068 Print this message or the help of the given subcommand(s)
2069
2070 Usage: myapp help [COMMAND]...
2071
2072 Arguments:
2073 [COMMAND]... Print help for the subcommand(s)
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", HELP_HELP, false);
2086 }
2087
2088 #[test]
global_args_should_show_on_help_message_for_subcommand()2089 fn global_args_should_show_on_help_message_for_subcommand() {
2090 static HELP_SUBCMD: &str = "\
2091 Usage: myapp subcmd [OPTIONS] [COMMAND]
2092
2093 Commands:
2094 multi\x20\x20
2095 help Print this message or the help of the given subcommand(s)
2096
2097 Options:
2098 -g, --some-global <someglobal>\x20\x20
2099 -h, --help Print help
2100 ";
2101
2102 let cmd = Command::new("myapp")
2103 .arg(
2104 Arg::new("someglobal")
2105 .short('g')
2106 .long("some-global")
2107 .global(true),
2108 )
2109 .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0")));
2110
2111 utils::assert_output(cmd, "myapp help subcmd", HELP_SUBCMD, false);
2112 }
2113
2114 #[test]
global_args_should_show_on_help_message_for_nested_subcommand()2115 fn global_args_should_show_on_help_message_for_nested_subcommand() {
2116 static HELP_SUB_SUBCMD: &str = "\
2117 Usage: myapp subcmd multi [OPTIONS]
2118
2119 Options:
2120 -g, --some-global <someglobal>\x20\x20
2121 -h, --help Print help
2122 -V, --version Print version
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 multi", HELP_SUB_SUBCMD, false);
2135 }
2136
2137 #[test]
option_usage_order()2138 fn option_usage_order() {
2139 static OPTION_USAGE_ORDER: &str = "\
2140 Usage: order [OPTIONS]
2141
2142 Options:
2143 -a
2144 -B
2145 -b
2146 -s
2147 --select_file
2148 --select_folder
2149 -x
2150 -h, --help Print help
2151 ";
2152
2153 let cmd = Command::new("order").args([
2154 Arg::new("a").short('a').action(ArgAction::SetTrue),
2155 Arg::new("B").short('B').action(ArgAction::SetTrue),
2156 Arg::new("b").short('b').action(ArgAction::SetTrue),
2157 Arg::new("save").short('s').action(ArgAction::SetTrue),
2158 Arg::new("select_file")
2159 .long("select_file")
2160 .action(ArgAction::SetTrue),
2161 Arg::new("select_folder")
2162 .long("select_folder")
2163 .action(ArgAction::SetTrue),
2164 Arg::new("x").short('x').action(ArgAction::SetTrue),
2165 ]);
2166
2167 utils::assert_output(cmd, "order --help", OPTION_USAGE_ORDER, false);
2168 }
2169
2170 #[test]
prefer_about_over_long_about_in_subcommands_list()2171 fn prefer_about_over_long_about_in_subcommands_list() {
2172 static ABOUT_IN_COMMANDS_LIST: &str = "\
2173 Usage: about-in-subcommands-list [COMMAND]
2174
2175 Commands:
2176 sub short about sub
2177 help Print this message or the help of the given subcommand(s)
2178
2179 Options:
2180 -h, --help Print help
2181 ";
2182
2183 let cmd = Command::new("about-in-subcommands-list").subcommand(
2184 Command::new("sub")
2185 .long_about("long about sub")
2186 .about("short about sub"),
2187 );
2188
2189 utils::assert_output(
2190 cmd,
2191 "about-in-subcommands-list --help",
2192 ABOUT_IN_COMMANDS_LIST,
2193 false,
2194 );
2195 }
2196
2197 #[test]
issue_1794_usage()2198 fn issue_1794_usage() {
2199 static USAGE_WITH_GROUP: &str = "\
2200 Usage: deno <pos1|--option1> [pos2]
2201
2202 Arguments:
2203 [pos1]
2204 [pos2]
2205
2206 Options:
2207 --option1
2208 -h, --help Print help
2209 ";
2210
2211 let cmd = clap::Command::new("hello")
2212 .bin_name("deno")
2213 .arg(
2214 Arg::new("option1")
2215 .long("option1")
2216 .action(ArgAction::SetTrue),
2217 )
2218 .arg(Arg::new("pos1").action(ArgAction::Set))
2219 .group(
2220 ArgGroup::new("arg1")
2221 .args(["pos1", "option1"])
2222 .required(true),
2223 )
2224 .arg(Arg::new("pos2").action(ArgAction::Set));
2225
2226 utils::assert_output(cmd, "deno --help", USAGE_WITH_GROUP, false);
2227 }
2228
2229 static CUSTOM_HEADING_POS: &str = "\
2230 Usage: test [gear] [speed]
2231
2232 Arguments:
2233 [gear] Which gear
2234
2235 Options:
2236 -h, --help Print help
2237 -V, --version Print version
2238
2239 NETWORKING:
2240 [speed] How fast
2241 ";
2242
2243 #[test]
custom_heading_pos()2244 fn custom_heading_pos() {
2245 let cmd = Command::new("test")
2246 .version("1.4")
2247 .arg(Arg::new("gear").help("Which gear"))
2248 .next_help_heading(Some("NETWORKING"))
2249 .arg(Arg::new("speed").help("How fast"));
2250
2251 utils::assert_output(cmd, "test --help", CUSTOM_HEADING_POS, false);
2252 }
2253
2254 static ONLY_CUSTOM_HEADING_OPTS_NO_ARGS: &str = "\
2255 Usage: test [OPTIONS]
2256
2257 NETWORKING:
2258 -s, --speed <SPEED> How fast
2259 ";
2260
2261 #[test]
only_custom_heading_opts_no_args()2262 fn only_custom_heading_opts_no_args() {
2263 let cmd = Command::new("test")
2264 .version("1.4")
2265 .disable_version_flag(true)
2266 .disable_help_flag(true)
2267 .arg(arg!(--help).action(ArgAction::Help).hide(true))
2268 .next_help_heading(Some("NETWORKING"))
2269 .arg(arg!(-s --speed <SPEED> "How fast"));
2270
2271 utils::assert_output(cmd, "test --help", ONLY_CUSTOM_HEADING_OPTS_NO_ARGS, false);
2272 }
2273
2274 static ONLY_CUSTOM_HEADING_POS_NO_ARGS: &str = "\
2275 Usage: test [speed]
2276
2277 NETWORKING:
2278 [speed] How fast
2279 ";
2280
2281 #[test]
only_custom_heading_pos_no_args()2282 fn only_custom_heading_pos_no_args() {
2283 let cmd = Command::new("test")
2284 .version("1.4")
2285 .disable_version_flag(true)
2286 .disable_help_flag(true)
2287 .arg(arg!(--help).action(ArgAction::Help).hide(true))
2288 .next_help_heading(Some("NETWORKING"))
2289 .arg(Arg::new("speed").help("How fast"));
2290
2291 utils::assert_output(cmd, "test --help", ONLY_CUSTOM_HEADING_POS_NO_ARGS, false);
2292 }
2293
2294 #[test]
issue_2508_number_of_values_with_single_value_name()2295 fn issue_2508_number_of_values_with_single_value_name() {
2296 let cmd = Command::new("my_app")
2297 .arg(Arg::new("some_arg").long("some_arg").num_args(2))
2298 .arg(
2299 Arg::new("some_arg_issue")
2300 .long("some_arg_issue")
2301 .num_args(2)
2302 .value_name("ARG"),
2303 );
2304 utils::assert_output(
2305 cmd,
2306 "my_app --help",
2307 "\
2308 Usage: my_app [OPTIONS]
2309
2310 Options:
2311 --some_arg <some_arg> <some_arg>
2312 --some_arg_issue <ARG> <ARG>
2313 -h, --help Print help
2314 ",
2315 false,
2316 );
2317 }
2318
2319 #[test]
missing_positional_final_required()2320 fn missing_positional_final_required() {
2321 let cmd = Command::new("test")
2322 .allow_missing_positional(true)
2323 .arg(Arg::new("arg1"))
2324 .arg(Arg::new("arg2").required(true));
2325 utils::assert_output(
2326 cmd,
2327 "test --help",
2328 "\
2329 Usage: test [arg1] <arg2>
2330
2331 Arguments:
2332 [arg1]
2333 <arg2>
2334
2335 Options:
2336 -h, --help Print help
2337 ",
2338 false,
2339 );
2340 }
2341
2342 #[test]
missing_positional_final_multiple()2343 fn missing_positional_final_multiple() {
2344 let cmd = Command::new("test")
2345 .allow_missing_positional(true)
2346 .arg(Arg::new("foo"))
2347 .arg(Arg::new("bar"))
2348 .arg(Arg::new("baz").action(ArgAction::Set).num_args(1..));
2349 utils::assert_output(
2350 cmd,
2351 "test --help",
2352 "\
2353 Usage: test [foo] [bar] [baz]...
2354
2355 Arguments:
2356 [foo]
2357 [bar]
2358 [baz]...
2359
2360 Options:
2361 -h, --help Print help
2362 ",
2363 false,
2364 );
2365 }
2366
2367 #[test]
positional_multiple_values_is_dotted()2368 fn positional_multiple_values_is_dotted() {
2369 let cmd = Command::new("test").arg(
2370 Arg::new("foo")
2371 .required(true)
2372 .action(ArgAction::Set)
2373 .num_args(1..),
2374 );
2375 utils::assert_output(
2376 cmd,
2377 "test --help",
2378 "\
2379 Usage: test <foo>...
2380
2381 Arguments:
2382 <foo>...
2383
2384 Options:
2385 -h, --help Print help
2386 ",
2387 false,
2388 );
2389
2390 let cmd = Command::new("test").arg(
2391 Arg::new("foo")
2392 .required(true)
2393 .action(ArgAction::Set)
2394 .value_name("BAR")
2395 .num_args(1..),
2396 );
2397 utils::assert_output(
2398 cmd,
2399 "test --help",
2400 "\
2401 Usage: test <BAR>...
2402
2403 Arguments:
2404 <BAR>...
2405
2406 Options:
2407 -h, --help Print help
2408 ",
2409 false,
2410 );
2411 }
2412
2413 #[test]
positional_multiple_occurrences_is_dotted()2414 fn positional_multiple_occurrences_is_dotted() {
2415 let cmd = Command::new("test").arg(
2416 Arg::new("foo")
2417 .required(true)
2418 .action(ArgAction::Set)
2419 .num_args(1..)
2420 .action(ArgAction::Append),
2421 );
2422 utils::assert_output(
2423 cmd,
2424 "test --help",
2425 "\
2426 Usage: test <foo>...
2427
2428 Arguments:
2429 <foo>...
2430
2431 Options:
2432 -h, --help Print help
2433 ",
2434 false,
2435 );
2436
2437 let cmd = Command::new("test").arg(
2438 Arg::new("foo")
2439 .required(true)
2440 .action(ArgAction::Set)
2441 .value_name("BAR")
2442 .num_args(1..)
2443 .action(ArgAction::Append),
2444 );
2445 utils::assert_output(
2446 cmd,
2447 "test --help",
2448 "\
2449 Usage: test <BAR>...
2450
2451 Arguments:
2452 <BAR>...
2453
2454 Options:
2455 -h, --help Print help
2456 ",
2457 false,
2458 );
2459 }
2460
2461 #[test]
too_few_value_names_is_dotted()2462 fn too_few_value_names_is_dotted() {
2463 let cmd = Command::new("test").arg(
2464 Arg::new("foo")
2465 .long("foo")
2466 .required(true)
2467 .action(ArgAction::Set)
2468 .num_args(3)
2469 .value_names(["one", "two"]),
2470 );
2471 utils::assert_output(
2472 cmd,
2473 "test --help",
2474 "\
2475 Usage: test --foo <one> <two>...
2476
2477 Options:
2478 --foo <one> <two>...
2479 -h, --help Print help
2480 ",
2481 false,
2482 );
2483 }
2484
2485 #[test]
2486 #[should_panic = "Argument foo: Too many value names (2) compared to `num_args` (1)"]
too_many_value_names_panics()2487 fn too_many_value_names_panics() {
2488 Command::new("test")
2489 .arg(
2490 Arg::new("foo")
2491 .long("foo")
2492 .required(true)
2493 .action(ArgAction::Set)
2494 .num_args(1)
2495 .value_names(["one", "two"]),
2496 )
2497 .debug_assert()
2498 }
2499
2500 #[test]
disabled_help_flag()2501 fn disabled_help_flag() {
2502 let res = Command::new("foo")
2503 .subcommand(Command::new("sub"))
2504 .disable_help_flag(true)
2505 .try_get_matches_from("foo a".split(' '));
2506 assert!(res.is_err());
2507 let err = res.unwrap_err();
2508 assert_eq!(err.kind(), ErrorKind::InvalidSubcommand);
2509 }
2510
2511 #[test]
disabled_help_flag_and_subcommand()2512 fn disabled_help_flag_and_subcommand() {
2513 let res = Command::new("foo")
2514 .subcommand(Command::new("sub"))
2515 .disable_help_flag(true)
2516 .disable_help_subcommand(true)
2517 .try_get_matches_from("foo help".split(' '));
2518 assert!(res.is_err());
2519 let err = res.unwrap_err();
2520 assert_eq!(err.kind(), ErrorKind::InvalidSubcommand);
2521 assert!(
2522 err.to_string().ends_with('\n'),
2523 "Errors should have a trailing newline, got {:?}",
2524 err.to_string()
2525 );
2526 }
2527
2528 #[test]
override_help_subcommand()2529 fn override_help_subcommand() {
2530 let cmd = Command::new("bar")
2531 .subcommand(Command::new("help").arg(Arg::new("arg").action(ArgAction::Set)))
2532 .subcommand(Command::new("not_help").arg(Arg::new("arg").action(ArgAction::Set)))
2533 .disable_help_subcommand(true);
2534 let matches = cmd.try_get_matches_from(["bar", "help", "foo"]).unwrap();
2535 assert_eq!(
2536 matches
2537 .subcommand_matches("help")
2538 .unwrap()
2539 .get_one::<String>("arg")
2540 .map(|v| v.as_str()),
2541 Some("foo")
2542 );
2543 }
2544
2545 #[test]
override_help_flag_using_long()2546 fn override_help_flag_using_long() {
2547 let cmd = Command::new("foo")
2548 .subcommand(Command::new("help").long_flag("help"))
2549 .disable_help_flag(true)
2550 .disable_help_subcommand(true);
2551 let matches = cmd.try_get_matches_from(["foo", "--help"]).unwrap();
2552 assert!(matches.subcommand_matches("help").is_some());
2553 }
2554
2555 #[test]
override_help_flag_using_short()2556 fn override_help_flag_using_short() {
2557 let cmd = Command::new("foo")
2558 .disable_help_flag(true)
2559 .disable_help_subcommand(true)
2560 .subcommand(Command::new("help").short_flag('h'));
2561 let matches = cmd.try_get_matches_from(["foo", "-h"]).unwrap();
2562 assert!(matches.subcommand_matches("help").is_some());
2563 }
2564
2565 #[test]
subcommand_help_doesnt_have_useless_help_flag()2566 fn subcommand_help_doesnt_have_useless_help_flag() {
2567 // The main care-about is that the docs and behavior match. Since the `help` subcommand
2568 // currently ignores the `--help` flag, the output shouldn't have it.
2569 let cmd = Command::new("example").subcommand(Command::new("test").about("Subcommand"));
2570
2571 utils::assert_output(
2572 cmd,
2573 "example help help",
2574 "\
2575 Print this message or the help of the given subcommand(s)
2576
2577 Usage: example help [COMMAND]...
2578
2579 Arguments:
2580 [COMMAND]... Print help for the subcommand(s)
2581 ",
2582 false,
2583 );
2584 }
2585
2586 #[test]
disable_help_flag_affects_help_subcommand()2587 fn disable_help_flag_affects_help_subcommand() {
2588 let mut cmd = Command::new("test_app")
2589 .disable_help_flag(true)
2590 .subcommand(Command::new("test").about("Subcommand"));
2591 cmd.build();
2592
2593 let args = cmd
2594 .find_subcommand("help")
2595 .unwrap()
2596 .get_arguments()
2597 .map(|a| a.get_id().as_str())
2598 .collect::<Vec<_>>();
2599 assert!(
2600 !args.contains(&"help"),
2601 "`help` should not be present: {:?}",
2602 args
2603 );
2604 }
2605
2606 #[test]
dont_propagate_version_to_help_subcommand()2607 fn dont_propagate_version_to_help_subcommand() {
2608 let cmd = clap::Command::new("example")
2609 .version("1.0")
2610 .propagate_version(true)
2611 .subcommand(clap::Command::new("subcommand"));
2612
2613 utils::assert_output(
2614 cmd.clone(),
2615 "example help help",
2616 "\
2617 Print this message or the help of the given subcommand(s)
2618
2619 Usage: example help [COMMAND]...
2620
2621 Arguments:
2622 [COMMAND]... Print help for the subcommand(s)
2623 ",
2624 false,
2625 );
2626
2627 cmd.debug_assert();
2628 }
2629
2630 #[test]
help_without_short()2631 fn help_without_short() {
2632 let mut cmd = clap::Command::new("test")
2633 .arg(arg!(-h --hex <NUM>).required(true))
2634 .arg(arg!(--help).action(ArgAction::Help))
2635 .disable_help_flag(true);
2636
2637 cmd.build();
2638 let help = cmd.get_arguments().find(|a| a.get_id() == "help").unwrap();
2639 assert_eq!(help.get_short(), None);
2640
2641 let m = cmd.try_get_matches_from(["test", "-h", "0x100"]).unwrap();
2642 assert_eq!(
2643 m.get_one::<String>("hex").map(|v| v.as_str()),
2644 Some("0x100")
2645 );
2646 }
2647
2648 #[test]
parent_cmd_req_in_usage_with_help_flag()2649 fn parent_cmd_req_in_usage_with_help_flag() {
2650 static EXPECTED: &str = "\
2651 some
2652
2653 Usage: parent <TARGET> <ARGS> test
2654
2655 Options:
2656 -h, --help Print help
2657 ";
2658 let cmd = Command::new("parent")
2659 .version("0.1")
2660 .arg(Arg::new("TARGET").required(true).help("some"))
2661 .arg(
2662 Arg::new("ARGS")
2663 .action(ArgAction::Set)
2664 .required(true)
2665 .help("some"),
2666 )
2667 .subcommand(Command::new("test").about("some"));
2668 utils::assert_output(cmd, "parent test --help", EXPECTED, false);
2669 }
2670
2671 #[test]
parent_cmd_req_in_usage_with_help_subcommand()2672 fn parent_cmd_req_in_usage_with_help_subcommand() {
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 help test", EXPECTED, false);
2692 }
2693
2694 #[test]
parent_cmd_req_in_usage_with_render_help()2695 fn parent_cmd_req_in_usage_with_render_help() {
2696 static EXPECTED: &str = "\
2697 some
2698
2699 Usage: parent <TARGET> <ARGS> test
2700
2701 Options:
2702 -h, --help Print help
2703 ";
2704 let mut 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 cmd.build();
2715 let subcmd = cmd.find_subcommand_mut("test").unwrap();
2716
2717 let help = subcmd.render_help().to_string();
2718 utils::assert_eq(EXPECTED, help);
2719 }
2720
2721 #[test]
parent_cmd_req_ignored_when_negates_reqs()2722 fn parent_cmd_req_ignored_when_negates_reqs() {
2723 static MULTI_SC_HELP: &str = "\
2724 Usage: ctest subcmd
2725
2726 Options:
2727 -h, --help Print help
2728 ";
2729
2730 let cmd = Command::new("ctest")
2731 .arg(arg!(<input>))
2732 .subcommand_negates_reqs(true)
2733 .subcommand(Command::new("subcmd"));
2734 utils::assert_output(cmd, "ctest subcmd --help", MULTI_SC_HELP, false);
2735 }
2736
2737 #[test]
parent_cmd_req_ignored_when_conflicts()2738 fn parent_cmd_req_ignored_when_conflicts() {
2739 static MULTI_SC_HELP: &str = "\
2740 Usage: ctest subcmd
2741
2742 Options:
2743 -h, --help Print help
2744 ";
2745
2746 let cmd = Command::new("ctest")
2747 .arg(arg!(<input>))
2748 .args_conflicts_with_subcommands(true)
2749 .subcommand(Command::new("subcmd"));
2750 utils::assert_output(cmd, "ctest subcmd --help", MULTI_SC_HELP, false);
2751 }
2752
2753 #[test]
no_wrap_help()2754 fn no_wrap_help() {
2755 let cmd = Command::new("ctest")
2756 .term_width(0)
2757 .override_help(MULTI_SC_HELP);
2758 utils::assert_output(cmd, "ctest --help", MULTI_SC_HELP, false);
2759 }
2760
2761 #[test]
display_name_default()2762 fn display_name_default() {
2763 let mut cmd = Command::new("app").bin_name("app.exe");
2764 cmd.build();
2765 assert_eq!(cmd.get_display_name(), None);
2766 }
2767
2768 #[test]
display_name_explicit()2769 fn display_name_explicit() {
2770 let mut cmd = Command::new("app")
2771 .bin_name("app.exe")
2772 .display_name("app.display");
2773 cmd.build();
2774 assert_eq!(cmd.get_display_name(), Some("app.display"));
2775 }
2776
2777 #[test]
display_name_subcommand_default()2778 fn display_name_subcommand_default() {
2779 let mut cmd = Command::new("parent").subcommand(Command::new("child").bin_name("child.exe"));
2780 cmd.build();
2781 assert_eq!(
2782 cmd.find_subcommand("child").unwrap().get_display_name(),
2783 Some("parent-child")
2784 );
2785 }
2786
2787 #[test]
display_name_subcommand_explicit()2788 fn display_name_subcommand_explicit() {
2789 let mut cmd = Command::new("parent").subcommand(
2790 Command::new("child")
2791 .bin_name("child.exe")
2792 .display_name("child.display"),
2793 );
2794 cmd.build();
2795 assert_eq!(
2796 cmd.find_subcommand("child").unwrap().get_display_name(),
2797 Some("child.display")
2798 );
2799 }
2800