From 5e20a29b4fdc8a2d442d1093681b396dcb4b816b Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 7 Jan 2020 11:18:04 +0000 Subject: Add structopt dependency in version 0.3.7 This patch series replaces argparse with structopt in the argument handling code. As a first step, we need structopt as a dependency. Import subrepo structopt/:structopt at efbdda4753592e27bc430fb01f7b9650b2f3174d Import subrepo bitflags/:bitflags at 30668016aca6bd3b02c766e8347e0b4080d4c296 Import subrepo clap/:clap at 784524f7eb193e35f81082cc69454c8c21b948f7 Import subrepo heck/:heck at 093d56fbf001e1506e56dbfa38631d99b1066df1 Import subrepo proc-macro-error/:proc-macro-error at 6c4cfe79a622c5de8ae68557993542be46eacae2 Import subrepo proc-macro2/:proc-macro2 at d5d48eddca4566e5438e8a2cbed4a74e049544de Import subrepo quote/:quote at 727436c6c137b20f0f34dde5d8fda2679b9747ad Import subrepo rustversion/:rustversion at 0c5663313516263059ce9059ef81fc7a1cf655ca Import subrepo syn-mid/:syn-mid at 5d3d85414a9e6674e1857ec22a87b96e04a6851a Import subrepo syn/:syn at e87c27e87f6f4ef8919d0372bdb056d53ef0d8f3 Import subrepo textwrap/:textwrap at abcd618beae3f74841032aa5b53c1086b0a57ca2 Import subrepo unicode-segmentation/:unicode-segmentation at 637c9874c4fe0c205ff27787faf150a40295c6c3 Import subrepo unicode-width/:unicode-width at 3033826f8bf05e82724140a981d5941e48fce393 Import subrepo unicode-xid/:unicode-xid at 4baae9fffb156ba229665b972a9cd5991787ceb7 --- clap/tests/app.yml | 121 ++++ clap/tests/app_settings.rs | 965 ++++++++++++++++++++++++++++ clap/tests/arg_aliases.rs | 200 ++++++ clap/tests/borrowed.rs | 19 + clap/tests/completions.rs | 883 +++++++++++++++++++++++++ clap/tests/conflicts.rs | 102 +++ clap/tests/default_vals.rs | 498 +++++++++++++++ clap/tests/delimiters.rs | 139 ++++ clap/tests/derive_order.rs | 245 +++++++ clap/tests/env.rs | 263 ++++++++ clap/tests/example1_tmpl_full.txt | 15 + clap/tests/example1_tmpl_simple.txt | 8 + clap/tests/flags.rs | 147 +++++ clap/tests/global_args.rs | 37 ++ clap/tests/groups.rs | 207 ++++++ clap/tests/help.rs | 1205 +++++++++++++++++++++++++++++++++++ clap/tests/hidden_args.rs | 178 ++++++ clap/tests/indices.rs | 175 +++++ clap/tests/macros.rs | 391 ++++++++++++ clap/tests/multiple_occurrences.rs | 75 +++ clap/tests/multiple_values.rs | 1122 ++++++++++++++++++++++++++++++++ clap/tests/opts.rs | 461 ++++++++++++++ clap/tests/positionals.rs | 274 ++++++++ clap/tests/posix_compatible.rs | 292 +++++++++ clap/tests/possible_values.rs | 266 ++++++++ clap/tests/propagate_globals.rs | 148 +++++ clap/tests/require.rs | 688 ++++++++++++++++++++ clap/tests/subcommands.rs | 216 +++++++ clap/tests/template_help.rs | 117 ++++ clap/tests/tests.rs | 435 +++++++++++++ clap/tests/unique_args.rs | 22 + clap/tests/utf8.rs | 223 +++++++ clap/tests/version-numbers.rs | 12 + clap/tests/version.rs | 58 ++ clap/tests/yaml.rs | 40 ++ 35 files changed, 10247 insertions(+) create mode 100644 clap/tests/app.yml create mode 100644 clap/tests/app_settings.rs create mode 100644 clap/tests/arg_aliases.rs create mode 100644 clap/tests/borrowed.rs create mode 100644 clap/tests/completions.rs create mode 100644 clap/tests/conflicts.rs create mode 100644 clap/tests/default_vals.rs create mode 100644 clap/tests/delimiters.rs create mode 100644 clap/tests/derive_order.rs create mode 100644 clap/tests/env.rs create mode 100644 clap/tests/example1_tmpl_full.txt create mode 100644 clap/tests/example1_tmpl_simple.txt create mode 100644 clap/tests/flags.rs create mode 100644 clap/tests/global_args.rs create mode 100644 clap/tests/groups.rs create mode 100644 clap/tests/help.rs create mode 100644 clap/tests/hidden_args.rs create mode 100644 clap/tests/indices.rs create mode 100755 clap/tests/macros.rs create mode 100644 clap/tests/multiple_occurrences.rs create mode 100644 clap/tests/multiple_values.rs create mode 100644 clap/tests/opts.rs create mode 100644 clap/tests/positionals.rs create mode 100644 clap/tests/posix_compatible.rs create mode 100644 clap/tests/possible_values.rs create mode 100644 clap/tests/propagate_globals.rs create mode 100644 clap/tests/require.rs create mode 100644 clap/tests/subcommands.rs create mode 100644 clap/tests/template_help.rs create mode 100644 clap/tests/tests.rs create mode 100644 clap/tests/unique_args.rs create mode 100644 clap/tests/utf8.rs create mode 100644 clap/tests/version-numbers.rs create mode 100644 clap/tests/version.rs create mode 100644 clap/tests/yaml.rs (limited to 'clap/tests') diff --git a/clap/tests/app.yml b/clap/tests/app.yml new file mode 100644 index 0000000..850bb82 --- /dev/null +++ b/clap/tests/app.yml @@ -0,0 +1,121 @@ +name: claptests +version: "1.0" +about: tests clap library +author: Kevin K. +settings: + - ArgRequiredElseHelp +help_message: prints help with a nonstandard description +args: + - opt: + short: o + long: option + multiple: true + help: tests options + - positional: + help: tests positionals + index: 1 + - positional2: + help: tests positionals with exclusions + index: 2 + default_value_if: + - [flag, Null, some] + - [postional, other, something] + - flag: + short: f + long: flag + multiple: true + help: tests flags + global: true + - flag2: + short: F + help: tests flags with exclusions + conflicts_with: + - flag + requires: + - option2 + - option2: + long: long-option-2 + help: tests long options with exclusions + conflicts_with: + - option + requires: + - positional2 + - option3: + short: O + long: Option + help: tests options with specific value sets + takes_value: true + possible_values: + - fast + - slow + requires_if: + - [fast, flag] + - positional3: + index: 3 + help: tests positionals with specific values + possible_values: [ vi, emacs ] + - multvals: + long: multvals + help: Tests multiple values, not mult occs + value_names: + - one + - two + - multvalsmo: + long: multvalsmo + multiple: true + help: Tests multiple values, not mult occs + value_names: [one, two] + - multvalsdelim: + long: multvalsdelim + help: Tests multiple values with required delimiter + multiple: true + require_delimiter: true + - singlealias: + long: singlealias + help: Tests single alias + aliases: [alias] + required_if: + - [multvalsmo, two] + - multaliases: + long: multaliases + help: Tests multiple aliases + aliases: [als1, als2, als3] + - minvals2: + long: minvals2 + multiple: true + help: Tests 2 min vals + min_values: 2 + - maxvals3: + long: maxvals3 + multiple: true + help: Tests 3 max vals + max_values: 3 + - case_insensitive: + help: Test case_insensitive + possible_values: [test123, test321] + case_insensitive: true + +arg_groups: + - test: + args: + - maxvals3 + - minmals2 + conflicts_with: + - option3 + requires: + - multvals +subcommands: + - subcmd: + about: tests subcommands + version: "0.1" + author: Kevin K. + args: + - scoption: + short: o + long: option + multiple: true + help: tests options + takes_value: true + - scpositional: + help: tests positionals + index: 1 diff --git a/clap/tests/app_settings.rs b/clap/tests/app_settings.rs new file mode 100644 index 0000000..3d72a3b --- /dev/null +++ b/clap/tests/app_settings.rs @@ -0,0 +1,965 @@ +extern crate clap; +extern crate regex; + +use clap::{App, Arg, SubCommand, AppSettings, ErrorKind}; + +include!("../clap-test.rs"); + +static ALLOW_EXT_SC: &'static str = "clap-test v1.4.8 + +USAGE: + clap-test [SUBCOMMAND] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information"; + +static DONT_COLLAPSE_ARGS: &'static str = "clap-test v1.4.8 + +USAGE: + clap-test [arg1] [arg2] [arg3] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +ARGS: + some + some + some"; + +static REQUIRE_EQUALS: &'static str = "clap-test v1.4.8 + +USAGE: + clap-test --opt= + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -o, --opt= some"; + +static UNIFIED_HELP: &'static str = "test 1.3 +Kevin K. +tests stuff + +USAGE: + test [OPTIONS] [arg1] + +OPTIONS: + -f, --flag some flag + -h, --help Prints help information + --option some option + -V, --version Prints version information + +ARGS: + some pos arg"; + +static SKIP_POS_VALS: &'static str = "test 1.3 +Kevin K. +tests stuff + +USAGE: + test [OPTIONS] [arg1] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -o, --opt some option + +ARGS: + some pos arg"; + +#[test] +fn sub_command_negate_required() { + App::new("sub_command_negate") + .setting(AppSettings::SubcommandsNegateReqs) + .arg(Arg::with_name("test") + .required(true) + .index(1)) + .subcommand(SubCommand::with_name("sub1")) + .get_matches_from(vec!["myprog", "sub1"]); +} + +#[test] +fn global_version() { + let mut app = App::new("global_version") + .setting(AppSettings::GlobalVersion) + .version("1.1") + .subcommand(SubCommand::with_name("sub1")); + app.p.propagate_settings(); + assert_eq!(app.p.subcommands[0].p.meta.version, Some("1.1")); +} + +#[test] +fn sub_command_negate_required_2() { + let result = App::new("sub_command_negate") + .setting(AppSettings::SubcommandsNegateReqs) + .arg(Arg::with_name("test") + .required(true) + .index(1)) + .subcommand(SubCommand::with_name("sub1")) + .get_matches_from_safe(vec![""]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::MissingRequiredArgument); +} + +#[test] +fn sub_command_required() { + let result = App::new("sc_required") + .setting(AppSettings::SubcommandRequired) + .subcommand(SubCommand::with_name("sub1")) + .get_matches_from_safe(vec![""]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::MissingSubcommand); +} + +#[test] +fn arg_required_else_help() { + let result = App::new("arg_required") + .setting(AppSettings::ArgRequiredElseHelp) + .arg(Arg::with_name("test") + .index(1)) + .get_matches_from_safe(vec![""]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::MissingArgumentOrSubcommand); +} + +#[test] +fn arg_required_else_help_over_reqs() { + let result = App::new("arg_required") + .setting(AppSettings::ArgRequiredElseHelp) + .arg(Arg::with_name("test") + .index(1).required(true)) + .get_matches_from_safe(vec![""]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::MissingArgumentOrSubcommand); +} + +#[cfg(not(feature = "suggestions"))] +#[test] +fn infer_subcommands_fail_no_args() { + let m = App::new("prog") + .setting(AppSettings::InferSubcommands) + .subcommand(SubCommand::with_name("test")) + .subcommand(SubCommand::with_name("temp")) + .get_matches_from_safe(vec![ + "prog", "te" + ]); + assert!(m.is_err(), "{:#?}", m.unwrap()); + assert_eq!(m.unwrap_err().kind, ErrorKind::UnrecognizedSubcommand); +} + +#[cfg(feature = "suggestions")] +#[test] +fn infer_subcommands_fail_no_args() { + let m = App::new("prog") + .setting(AppSettings::InferSubcommands) + .subcommand(SubCommand::with_name("test")) + .subcommand(SubCommand::with_name("temp")) + .get_matches_from_safe(vec![ + "prog", "te" + ]); + assert!(m.is_err(), "{:#?}", m.unwrap()); + assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidSubcommand); +} + +#[test] +fn infer_subcommands_fail_with_args() { + let m = App::new("prog") + .setting(AppSettings::InferSubcommands) + .arg(Arg::with_name("some")) + .subcommand(SubCommand::with_name("test")) + .subcommand(SubCommand::with_name("temp")) + .get_matches_from_safe(vec![ + "prog", "t" + ]); + assert!(m.is_ok(), "{:?}", m.unwrap_err().kind); + assert_eq!(m.unwrap().value_of("some"), Some("t")); +} + +#[test] +fn infer_subcommands_fail_with_args2() { + let m = App::new("prog") + .setting(AppSettings::InferSubcommands) + .arg(Arg::with_name("some")) + .subcommand(SubCommand::with_name("test")) + .subcommand(SubCommand::with_name("temp")) + .get_matches_from_safe(vec![ + "prog", "te" + ]); + assert!(m.is_ok(), "{:?}", m.unwrap_err().kind); + assert_eq!(m.unwrap().value_of("some"), Some("te")); +} + +#[test] +fn infer_subcommands_pass() { + let m = App::new("prog") + .setting(AppSettings::InferSubcommands) + .subcommand(SubCommand::with_name("test")) + .get_matches_from(vec![ + "prog", "te" + ]); + assert_eq!(m.subcommand_name(), Some("test")); +} + +#[test] +fn infer_subcommands_pass_close() { + let m = App::new("prog") + .setting(AppSettings::InferSubcommands) + .subcommand(SubCommand::with_name("test")) + .subcommand(SubCommand::with_name("temp")) + .get_matches_from(vec![ + "prog", "tes" + ]); + assert_eq!(m.subcommand_name(), Some("test")); +} + +#[test] +fn infer_subcommands_pass_exact_match() { + let m = App::new("prog") + .setting(AppSettings::InferSubcommands) + .subcommand(SubCommand::with_name("test")) + .subcommand(SubCommand::with_name("testa")) + .subcommand(SubCommand::with_name("testb")) + .get_matches_from(vec![ + "prog", "test" + ]); + assert_eq!(m.subcommand_name(), Some("test")); +} + +#[cfg(feature = "suggestions")] +#[test] +fn infer_subcommands_fail_suggestions() { + let m = App::new("prog") + .setting(AppSettings::InferSubcommands) + .subcommand(SubCommand::with_name("test")) + .subcommand(SubCommand::with_name("temp")) + .get_matches_from_safe(vec![ + "prog", "temps" + ]); + assert!(m.is_err(), "{:#?}", m.unwrap()); + assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidSubcommand); +} + +#[cfg(not(feature = "suggestions"))] +#[test] +fn infer_subcommands_fail_suggestions() { + let m = App::new("prog") + .setting(AppSettings::InferSubcommands) + .subcommand(SubCommand::with_name("test")) + .subcommand(SubCommand::with_name("temp")) + .get_matches_from_safe(vec![ + "prog", "temps" + ]); + assert!(m.is_err(), "{:#?}", m.unwrap()); + assert_eq!(m.unwrap_err().kind, ErrorKind::UnrecognizedSubcommand); +} + +#[test] +fn no_bin_name() { + let result = App::new("arg_required") + .setting(AppSettings::NoBinaryName) + .arg(Arg::with_name("test") + .required(true) + .index(1)) + .get_matches_from_safe(vec!["testing"]); + assert!(result.is_ok()); + let matches = result.unwrap(); + assert_eq!(matches.value_of("test").unwrap(), "testing"); +} + +#[test] +fn unified_help() { + let app = App::new("myTest") + .name("test") + .author("Kevin K.") + .about("tests stuff") + .version("1.3") + .setting(AppSettings::UnifiedHelpMessage) + .args_from_usage("-f, --flag 'some flag' + [arg1] 'some pos arg' + --option [opt] 'some option'"); + + assert!(test::compare_output(app, "test --help", UNIFIED_HELP, false)); +} + +#[test] +fn skip_possible_values() { + let app = App::new("test") + .author("Kevin K.") + .about("tests stuff") + .version("1.3") + .setting(AppSettings::HidePossibleValuesInHelp) + .args(&[Arg::from_usage("-o, --opt [opt] 'some option'").possible_values(&["one", "two"]), + Arg::from_usage("[arg1] 'some pos arg'").possible_values(&["three", "four"])]); + + assert!(test::compare_output(app, "test --help", SKIP_POS_VALS, false)); +} + +#[test] +fn global_setting() { + let mut app = App::new("test") + .global_setting(AppSettings::ColoredHelp) + .subcommand(SubCommand::with_name("subcmd")); + app.p.propagate_settings(); + assert!(app.p + .subcommands + .iter() + .filter(|s| s.p + .meta + .name == "subcmd") + .next() + .unwrap() + .p + .is_set(AppSettings::ColoredHelp)); +} + +#[test] +fn global_settings() { + let mut app = App::new("test") + .global_settings(&[AppSettings::ColoredHelp, AppSettings::TrailingVarArg]) + .subcommand(SubCommand::with_name("subcmd")); + app.p.propagate_settings(); + assert!(app.p + .subcommands + .iter() + .filter(|s| s.p + .meta + .name == "subcmd") + .next() + .unwrap() + .p + .is_set(AppSettings::ColoredHelp)); + assert!(app.p + .subcommands + .iter() + .filter(|s| s.p + .meta + .name == "subcmd") + .next() + .unwrap() + .p + .is_set(AppSettings::TrailingVarArg)); + +} + +#[test] +fn stop_delim_values_only_pos_follows() { + let r = App::new("onlypos") + .setting(AppSettings::DontDelimitTrailingValues) + .args(&[Arg::from_usage("-f [flag] 'some opt'"), + Arg::from_usage("[arg]... 'some arg'")]) + .get_matches_from_safe(vec!["", "--", "-f", "-g,x"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert!(!m.is_present("f")); + assert_eq!(m.values_of("arg").unwrap().collect::>(), &["-f", "-g,x"]); +} + +#[test] +fn dont_delim_values_trailingvararg() { + let m = App::new("positional") + .setting(AppSettings::TrailingVarArg) + .setting(AppSettings::DontDelimitTrailingValues) + .arg( + Arg::from_usage("[opt]... 'some pos'"), + ) + .get_matches_from(vec!["", "test", "--foo", "-Wl,-bar"]); + assert!(m.is_present("opt")); + assert_eq!(m.values_of("opt").unwrap().collect::>(), &["test", "--foo", "-Wl,-bar"]); +} + +#[test] +fn delim_values_only_pos_follows() { + let r = App::new("onlypos") + .args(&[Arg::from_usage("-f [flag] 'some opt'"), + Arg::from_usage("[arg]... 'some arg'")]) + .get_matches_from_safe(vec!["", "--", "-f", "-g,x"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert!(!m.is_present("f")); + assert_eq!(m.values_of("arg").unwrap().collect::>(), &["-f", "-g,x"]); +} + +#[test] +fn delim_values_trailingvararg() { + let m = App::new("positional") + .setting(AppSettings::TrailingVarArg) + .arg( + Arg::from_usage("[opt]... 'some pos'"), + ) + .get_matches_from(vec!["", "test", "--foo", "-Wl,-bar"]); + assert!(m.is_present("opt")); + assert_eq!(m.values_of("opt").unwrap().collect::>(), &["test", "--foo", "-Wl,-bar"]); +} + +#[test] +fn delim_values_only_pos_follows_with_delim() { + let r = App::new("onlypos") + .args(&[Arg::from_usage("-f [flag] 'some opt'"), + Arg::from_usage("[arg]... 'some arg'").use_delimiter(true)]) + .get_matches_from_safe(vec!["", "--", "-f", "-g,x"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert!(!m.is_present("f")); + assert_eq!(m.values_of("arg").unwrap().collect::>(), &["-f", "-g", "x"]); +} + +#[test] +fn delim_values_trailingvararg_with_delim() { + let m = App::new("positional") + .setting(AppSettings::TrailingVarArg) + .arg( + Arg::from_usage("[opt]... 'some pos'").use_delimiter(true), + ) + .get_matches_from(vec!["", "test", "--foo", "-Wl,-bar"]); + assert!(m.is_present("opt")); + assert_eq!(m.values_of("opt").unwrap().collect::>(), &["test", "--foo", "-Wl", "-bar"]); +} + +#[test] +fn leading_hyphen_short() { + let res = App::new("leadhy") + .setting(AppSettings::AllowLeadingHyphen) + .arg(Arg::with_name("some")) + .arg(Arg::with_name("other") + .short("o")) + .get_matches_from_safe(vec!["", "-bar", "-o"]); + assert!(res.is_ok(), "Error: {:?}", res.unwrap_err().kind); + let m = res.unwrap(); + assert!(m.is_present("some")); + assert!(m.is_present("other")); + assert_eq!(m.value_of("some").unwrap(), "-bar"); +} + +#[test] +fn leading_hyphen_long() { + let res = App::new("leadhy") + .setting(AppSettings::AllowLeadingHyphen) + .arg(Arg::with_name("some")) + .arg(Arg::with_name("other") + .short("o")) + .get_matches_from_safe(vec!["", "--bar", "-o"]); + assert!(res.is_ok(), "Error: {:?}", res.unwrap_err().kind); + let m = res.unwrap(); + assert!(m.is_present("some")); + assert!(m.is_present("other")); + assert_eq!(m.value_of("some").unwrap(), "--bar"); +} + +#[test] +fn leading_hyphen_opt() { + let res = App::new("leadhy") + .setting(AppSettings::AllowLeadingHyphen) + .arg(Arg::with_name("some") + .takes_value(true) + .long("opt")) + .arg(Arg::with_name("other") + .short("o")) + .get_matches_from_safe(vec!["", "--opt", "--bar", "-o"]); + assert!(res.is_ok(), "Error: {:?}", res.unwrap_err().kind); + let m = res.unwrap(); + assert!(m.is_present("some")); + assert!(m.is_present("other")); + assert_eq!(m.value_of("some").unwrap(), "--bar"); +} + +#[test] +fn allow_negative_numbers() { + let res = App::new("negnum") + .setting(AppSettings::AllowNegativeNumbers) + .arg(Arg::with_name("panum")) + .arg(Arg::with_name("onum") + .short("o") + .takes_value(true)) + .get_matches_from_safe(vec!["negnum", "-20", "-o", "-1.2"]); + assert!(res.is_ok(), "Error: {:?}", res.unwrap_err().kind); + let m = res.unwrap(); + assert_eq!(m.value_of("panum").unwrap(), "-20"); + assert_eq!(m.value_of("onum").unwrap(), "-1.2"); +} + +#[test] +fn allow_negative_numbers_fail() { + let res = App::new("negnum") + .setting(AppSettings::AllowNegativeNumbers) + .arg(Arg::with_name("panum")) + .arg(Arg::with_name("onum") + .short("o") + .takes_value(true)) + .get_matches_from_safe(vec!["negnum", "--foo", "-o", "-1.2"]); + assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument) +} + +#[test] +fn leading_double_hyphen_trailingvararg() { + let m = App::new("positional") + .setting(AppSettings::TrailingVarArg) + .setting(AppSettings::AllowLeadingHyphen) + .arg( + Arg::from_usage("[opt]... 'some pos'"), + ) + .get_matches_from(vec!["", "--foo", "-Wl", "bar"]); + assert!(m.is_present("opt")); + assert_eq!(m.values_of("opt").unwrap().collect::>(), &["--foo", "-Wl", "bar"]); +} + +#[test] +fn test_unset_setting() { + let m = App::new("unset_setting"); + assert!(m.p.is_set(AppSettings::AllowInvalidUtf8)); + + let m = m.unset_setting(AppSettings::AllowInvalidUtf8); + assert!(!m.p.is_set(AppSettings::AllowInvalidUtf8)); +} + +#[test] +fn test_unset_settings() { + let m = App::new("unset_settings"); + assert!(&m.p.is_set(AppSettings::AllowInvalidUtf8)); + assert!(&m.p.is_set(AppSettings::ColorAuto)); + + let m = m.unset_settings(&[AppSettings::AllowInvalidUtf8, + AppSettings::ColorAuto]); + assert!(!m.p.is_set(AppSettings::AllowInvalidUtf8)); + assert!(!m.p.is_set(AppSettings::ColorAuto)); +} + +#[test] +fn disable_help_subcommand() { + let result = App::new("disablehelp") + .setting(AppSettings::DisableHelpSubcommand) + .subcommand(SubCommand::with_name("sub1")) + .get_matches_from_safe(vec!["", "help"]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::UnknownArgument); +} + +#[test] +fn dont_collapse_args() { + let app = App::new("clap-test") + .version("v1.4.8") + .setting(AppSettings::DontCollapseArgsInUsage) + .args(&[ + Arg::with_name("arg1").help("some"), + Arg::with_name("arg2").help("some"), + Arg::with_name("arg3").help("some"), + ]); + assert!(test::compare_output(app, "clap-test --help", DONT_COLLAPSE_ARGS, false)); +} + +#[test] +fn require_eq() { + let app = App::new("clap-test") + .version("v1.4.8") + .arg( + Arg::with_name("opt") + .long("opt") + .short("o") + .required(true) + .require_equals(true) + .value_name("FILE") + .help("some"), + ); + assert!(test::compare_output(app, "clap-test --help", REQUIRE_EQUALS, false)); +} + +#[test] +fn args_negate_subcommands_one_level() { + let res = App::new("disablehelp") + .setting(AppSettings::ArgsNegateSubcommands) + .setting(AppSettings::SubcommandsNegateReqs) + .arg_from_usage(" 'some arg'") + .arg_from_usage(" 'some arg'") + .subcommand(SubCommand::with_name("sub1") + .subcommand(SubCommand::with_name("sub2") + .subcommand(SubCommand::with_name("sub3")) + ) + ) + .get_matches_from_safe(vec!["", "pickles", "sub1"]); + assert!(res.is_ok(), "error: {:?}", res.unwrap_err().kind); + let m = res.unwrap(); + assert_eq!(m.value_of("arg2"), Some("sub1")); +} + +#[test] +fn args_negate_subcommands_two_levels() { + let res = App::new("disablehelp") + .global_setting(AppSettings::ArgsNegateSubcommands) + .global_setting(AppSettings::SubcommandsNegateReqs) + .arg_from_usage(" 'some arg'") + .arg_from_usage(" 'some arg'") + .subcommand(SubCommand::with_name("sub1") + .arg_from_usage(" 'some'") + .arg_from_usage(" 'some'") + .subcommand(SubCommand::with_name("sub2") + .subcommand(SubCommand::with_name("sub3")) + ) + ) + .get_matches_from_safe(vec!["", "sub1", "arg", "sub2"]); + assert!(res.is_ok(), "error: {:?}", res.unwrap_err().kind); + let m = res.unwrap(); + assert_eq!(m.subcommand_matches("sub1").unwrap().value_of("arg2"), Some("sub2")); +} + + +#[test] +fn propagate_vals_down() { + let m = App::new("myprog") + .arg(Arg::from_usage("[cmd] 'command to run'").global(true)) + .subcommand(SubCommand::with_name("foo")) + .get_matches_from_safe(vec!["myprog", "set", "foo"]); + assert!(m.is_ok(), "{:?}", m.unwrap_err().kind); + let m = m.unwrap(); + assert_eq!(m.value_of("cmd"), Some("set")); + let sub_m = m.subcommand_matches("foo").unwrap(); + assert_eq!(sub_m.value_of("cmd"), Some("set")); +} + +#[test] +fn allow_missing_positional() { + let m = App::new("test") + .setting(AppSettings::AllowMissingPositional) + .arg(Arg::from_usage("[src] 'some file'").default_value("src")) + .arg_from_usage(" 'some file'") + .get_matches_from_safe(vec!["test", "file"]); + assert!(m.is_ok(), "{:?}", m.unwrap_err().kind); + let m = m.unwrap(); + assert_eq!(m.value_of("src"), Some("src")); + assert_eq!(m.value_of("dest"), Some("file")); +} + +#[test] +fn allow_missing_positional_no_default() { + let m = App::new("test") + .setting(AppSettings::AllowMissingPositional) + .arg(Arg::from_usage("[src] 'some file'")) + .arg_from_usage(" 'some file'") + .get_matches_from_safe(vec!["test", "file"]); + assert!(m.is_ok(), "{:?}", m.unwrap_err().kind); + let m = m.unwrap(); + assert_eq!(m.value_of("src"), None); + assert_eq!(m.value_of("dest"), Some("file")); +} + +#[test] +fn missing_positional_no_hyphen() { + let r = App::new("bench") + .setting(AppSettings::AllowMissingPositional) + .arg(Arg::from_usage("[BENCH] 'some bench'")) + .arg(Arg::from_usage("[ARGS]... 'some args'")) + .get_matches_from_safe(vec!["bench", "foo", "arg1", "arg2", "arg3"]); + assert!(r.is_ok(), "{:?}", r.unwrap_err().kind); + + let m = r.unwrap(); + + let expected_bench = Some("foo"); + let expected_args = vec!["arg1", "arg2", "arg3"]; + + assert_eq!(m.value_of("BENCH"), expected_bench); + assert_eq!(m.values_of("ARGS").unwrap().collect::>(), &*expected_args); +} + +#[test] +fn missing_positional_hyphen() { + let r = App::new("bench") + .setting(AppSettings::AllowMissingPositional) + .arg(Arg::from_usage("[BENCH] 'some bench'")) + .arg(Arg::from_usage("[ARGS]... 'some args'")) + .get_matches_from_safe(vec!["bench", "--", "arg1", "arg2", "arg3"]); + assert!(r.is_ok(), "{:?}", r.unwrap_err().kind); + + let m = r.unwrap(); + + let expected_bench = None; + let expected_args = vec!["arg1", "arg2", "arg3"]; + + assert_eq!(m.value_of("BENCH"), expected_bench); + assert_eq!(m.values_of("ARGS").unwrap().collect::>(), &*expected_args); +} + +#[test] +fn missing_positional_hyphen_far_back() { + let r = App::new("bench") + .setting(AppSettings::AllowMissingPositional) + .arg(Arg::from_usage("[BENCH1] 'some bench'")) + .arg(Arg::from_usage("[BENCH2] 'some bench'")) + .arg(Arg::from_usage("[BENCH3] 'some bench'")) + .arg(Arg::from_usage("[ARGS]... 'some args'")) + .get_matches_from_safe(vec!["bench", "foo", "--", "arg1", "arg2", "arg3"]); + assert!(r.is_ok(), "{:?}", r.unwrap_err().kind); + + let m = r.unwrap(); + + let expected_bench1 = Some("foo"); + let expected_bench2 = None; + let expected_bench3 = None; + let expected_args = vec!["arg1", "arg2", "arg3"]; + + assert_eq!(m.value_of("BENCH1"), expected_bench1); + assert_eq!(m.value_of("BENCH2"), expected_bench2); + assert_eq!(m.value_of("BENCH3"), expected_bench3); + assert_eq!(m.values_of("ARGS").unwrap().collect::>(), &*expected_args); +} + +#[test] +fn missing_positional_hyphen_req_error() { + let r = App::new("bench") + .setting(AppSettings::AllowMissingPositional) + .arg(Arg::from_usage("[BENCH1] 'some bench'")) + .arg(Arg::from_usage(" 'some bench'")) + .arg(Arg::from_usage("[ARGS]... 'some args'")) + .get_matches_from_safe(vec!["bench", "foo", "--", "arg1", "arg2", "arg3"]); + assert!(r.is_err()); + assert_eq!(r.unwrap_err().kind, ErrorKind::MissingRequiredArgument); +} + +#[test] +fn issue_1066_allow_leading_hyphen_and_unknown_args() { + let res = App::new("prog") + .global_setting(AppSettings::AllowLeadingHyphen) + .arg(Arg::from_usage("--some-argument")) + .get_matches_from_safe(vec!["prog", "hello"]); + + assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument); +} + +#[test] +fn issue_1066_allow_leading_hyphen_and_unknown_args_no_vals() { + let res = App::new("prog") + .global_setting(AppSettings::AllowLeadingHyphen) + .arg(Arg::from_usage("--some-argument")) + .get_matches_from_safe(vec!["prog", "--hello"]); + + assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument); +} + +#[test] +fn issue_1066_allow_leading_hyphen_and_unknown_args_option() { + let res = App::new("prog") + .global_setting(AppSettings::AllowLeadingHyphen) + .arg(Arg::from_usage("--some-argument=[val]")) + .get_matches_from_safe(vec!["prog", "-hello"]); + + assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument); +} + +#[test] +fn issue_1093_allow_ext_sc() { + let app = App::new("clap-test") + .version("v1.4.8") + .setting(AppSettings::AllowExternalSubcommands); + assert!(test::compare_output(app, "clap-test --help", ALLOW_EXT_SC, false)); +} + + +#[test] +fn allow_ext_sc_when_sc_required() { + let res = App::new("clap-test") + .version("v1.4.8") + .setting(AppSettings::AllowExternalSubcommands) + .setting(AppSettings::SubcommandRequiredElseHelp) + .get_matches_from_safe(vec!["clap-test", "external-cmd", "foo"]); + assert!(res.is_ok()); + let m = res.unwrap(); + match m.subcommand() { + (name, Some(args)) => { + assert_eq!(name, "external-cmd"); + assert_eq!(args.values_of_lossy(""), Some(vec!["foo".to_string()])); + } + _ => assert!(false), + } +} + +#[test] +fn external_subcommand_looks_like_built_in() { + let res = App::new("cargo") + .version("1.26.0") + .setting(AppSettings::AllowExternalSubcommands) + .subcommand(SubCommand::with_name("install")) + .get_matches_from_safe(vec!["cargo", "install-update", "foo"]); + assert!(res.is_ok()); + let m = res.unwrap(); + match m.subcommand() { + (name, Some(args)) => { + assert_eq!(name, "install-update"); + assert_eq!(args.values_of_lossy(""), Some(vec!["foo".to_string()])); + } + _ => assert!(false), + } +} + +#[test] +fn aaos_flags() { + // flags + let res = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("--flag 'some flag'")) + .get_matches_from_safe(vec!["", "--flag", "--flag"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert!(m.is_present("flag")); + assert_eq!(m.occurrences_of("flag"), 1); +} + +#[test] +fn aaos_flags_mult() { + // flags with multiple + let res = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("--flag... 'some flag'")) + .get_matches_from_safe(vec!["", "--flag", "--flag", "--flag", "--flag"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert!(m.is_present("flag")); + assert_eq!(m.occurrences_of("flag"), 4); +} + +#[test] +fn aaos_opts() { + // opts + let res = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("--opt [val] 'some option'")) + .get_matches_from_safe(vec!["", "--opt=some", "--opt=other"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert!(m.is_present("opt")); + assert_eq!(m.occurrences_of("opt"), 1); + assert_eq!(m.value_of("opt"), Some("other")); +} + +#[test] +fn aaos_opts_w_other_overrides() { + // opts with other overrides + let res = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("--opt [val] 'some option'")) + .arg(Arg::from_usage("--other [val] 'some other option'").overrides_with("opt")) + .get_matches_from_safe(vec!["", "--opt=some", "--other=test", "--opt=other"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert!(m.is_present("opt")); + assert!(!m.is_present("other")); + assert_eq!(m.occurrences_of("opt"), 1); + assert_eq!(m.value_of("opt"), Some("other")); +} + +#[test] +fn aaos_opts_w_other_overrides_rev() { + // opts with other overrides, rev + let res = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("--opt [val] 'some option'")) + .arg(Arg::from_usage("--other [val] 'some other option'").overrides_with("opt")) + .get_matches_from_safe(vec!["", "--opt=some", "--opt=other", "--other=val"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert!(!m.is_present("opt")); + assert!(m.is_present("other")); + assert_eq!(m.value_of("other"), Some("val")); +} + +#[test] +fn aaos_opts_w_other_overrides_2() { + // opts with other overrides + let res = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("--opt [val] 'some option'").overrides_with("other")) + .arg(Arg::from_usage("--other [val] 'some other option'")) + .get_matches_from_safe(vec!["", "--opt=some", "--other=test", "--opt=other"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert!(m.is_present("opt")); + assert!(!m.is_present("other")); + assert_eq!(m.occurrences_of("opt"), 1); + assert_eq!(m.value_of("opt"), Some("other")); +} + +#[test] +fn aaos_opts_w_other_overrides_rev_2() { + // opts with other overrides, rev + let res = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("--opt [val] 'some option'").overrides_with("other")) + .arg(Arg::from_usage("--other [val] 'some other option'")) + .get_matches_from_safe(vec!["", "--opt=some", "--opt=other", "--other=val"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert!(!m.is_present("opt")); + assert!(m.is_present("other")); + assert_eq!(m.value_of("other"), Some("val")); +} + +#[test] +fn aaos_opts_mult() { + // opts with multiple + let res = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("--opt [val]... 'some option'") + .number_of_values(1) + .require_delimiter(true)) + .get_matches_from_safe(vec!["", "--opt=some", "--opt=other", "--opt=one,two"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert!(m.is_present("opt")); + assert_eq!(m.occurrences_of("opt"), 3); + assert_eq!(m.values_of("opt").unwrap().collect::>(), &["some", "other", "one", "two"]); +} + +#[test] +fn aaos_opts_mult_req_delims() { + // opts with multiple and require delims + let res = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("--opt [val]... 'some option'")) + .get_matches_from_safe(vec!["", "--opt", "first", "overides", "--opt", "some", "other", "val"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert!(m.is_present("opt")); + assert_eq!(m.occurrences_of("opt"), 2); + assert_eq!(m.values_of("opt").unwrap().collect::>(), &["first", "overides", "some", "other", "val"]); +} + +#[test] +fn aaos_pos_mult() { + // opts with multiple + let res = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("[val]... 'some pos'")) + .get_matches_from_safe(vec!["", "some", "other", "value"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert!(m.is_present("val")); + assert_eq!(m.occurrences_of("val"), 3); + assert_eq!(m.values_of("val").unwrap().collect::>(), &["some", "other", "value"]); +} + +#[test] +fn aaos_option_use_delim_false() { + + let m = App::new("posix") + .setting(AppSettings::AllArgsOverrideSelf) + .arg(Arg::from_usage("--opt [val] 'some option'") + .use_delimiter(false)) + .get_matches_from(vec!["", "--opt=some,other", "--opt=one,two"]); + assert!(m.is_present("opt")); + assert_eq!(m.occurrences_of("opt"), 1); + assert_eq!(m.values_of("opt").unwrap().collect::>(), &["one,two"]); +} diff --git a/clap/tests/arg_aliases.rs b/clap/tests/arg_aliases.rs new file mode 100644 index 0000000..77bcd17 --- /dev/null +++ b/clap/tests/arg_aliases.rs @@ -0,0 +1,200 @@ +extern crate clap; +extern crate regex; + +include!("../clap-test.rs"); + +use clap::{App, Arg, SubCommand}; + +static SC_VISIBLE_ALIAS_HELP: &'static str = "ct-test 1.2 +Some help + +USAGE: + ct test [FLAGS] [OPTIONS] + +FLAGS: + -f, --flag [aliases: v_flg, flag2, flg3] + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -o, --opt [aliases: visible]"; + +static SC_INVISIBLE_ALIAS_HELP: &'static str = "ct-test 1.2 +Some help + +USAGE: + ct test [FLAGS] [OPTIONS] + +FLAGS: + -f, --flag + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -o, --opt "; + +#[test] +fn single_alias_of_option() { + let a = App::new("single_alias") + .arg(Arg::with_name("alias") + .long("alias") + .takes_value(true) + .help("single alias") + .alias("new-opt")) + .get_matches_from_safe(vec![ + "", "--new-opt", "cool" + ]); + assert!(a.is_ok()); + let a = a.unwrap(); + assert!(a.is_present("alias")); + assert_eq!(a.value_of("alias").unwrap(), "cool"); +} + +#[test] +fn multiple_aliases_of_option() { + let a = App::new("multiple_aliases") + .arg(Arg::with_name("aliases") + .long("aliases") + .takes_value(true) + .help("multiple aliases") + .aliases(&[ + "alias1", + "alias2", + "alias3" + ])); + let long = a.clone().get_matches_from_safe(vec![ + "", "--aliases", "value" + ]); + assert!(long.is_ok()); + let long = long.unwrap(); + + let als1 = a.clone().get_matches_from_safe(vec![ + "", "--alias1", "value" + ]); + assert!(als1.is_ok()); + let als1 = als1.unwrap(); + + let als2 = a.clone().get_matches_from_safe(vec![ + "", "--alias2", "value" + ]); + assert!(als2.is_ok()); + let als2 = als2.unwrap(); + + let als3 = a.clone().get_matches_from_safe(vec![ + "", "--alias3", "value" + ]); + assert!(als3.is_ok()); + let als3 = als3.unwrap(); + + assert!(long.is_present("aliases")); + assert!(als1.is_present("aliases")); + assert!(als2.is_present("aliases")); + assert!(als3.is_present("aliases")); + assert_eq!(long.value_of("aliases").unwrap(), "value"); + assert_eq!(als1.value_of("aliases").unwrap(), "value"); + assert_eq!(als2.value_of("aliases").unwrap(), "value"); + assert_eq!(als3.value_of("aliases").unwrap(), "value"); +} + +#[test] +fn single_alias_of_flag() { + let a = App::new("test") + .arg(Arg::with_name("flag") + .long("flag") + .alias("alias")) + .get_matches_from_safe(vec!["", "--alias"]); + assert!(a.is_ok()); + let a = a.unwrap(); + assert!(a.is_present("flag")); +} + +#[test] +fn multiple_aliases_of_flag() { + let a = App::new("test") + .arg(Arg::with_name("flag") + .long("flag") + .aliases(&["invisible", + "set", "of", + "cool", "aliases"])); + + let flag = a.clone().get_matches_from_safe(vec!["", "--flag"]); + assert!(flag.is_ok()); + let flag = flag.unwrap(); + + let inv = a.clone().get_matches_from_safe(vec!["", "--invisible"]); + assert!(inv.is_ok()); + let inv = inv.unwrap(); + + let cool = a.clone().get_matches_from_safe(vec!["", "--cool"]); + assert!(cool.is_ok()); + let cool = cool.unwrap(); + + let als = a.clone().get_matches_from_safe(vec!["", "--aliases"]); + assert!(als.is_ok()); + let als = als.unwrap(); + + assert!(flag.is_present("flag")); + assert!(inv.is_present("flag")); + assert!(cool.is_present("flag")); + assert!(als.is_present("flag")); +} + +#[test] +fn alias_on_a_subcommand_option() { + let m = App::new("test") + .subcommand(SubCommand::with_name("some") + .arg(Arg::with_name("test") + .short("t") + .long("test") + .takes_value(true) + .alias("opt") + .help("testing testing"))) + .arg(Arg::with_name("other") + .long("other") + .aliases(&["o1", "o2", "o3"])) + .get_matches_from(vec![ + "test", "some", "--opt", "awesome" + ]); + + assert!(m.subcommand_matches("some").is_some()); + let sub_m = m.subcommand_matches("some").unwrap(); + assert!(sub_m.is_present("test")); + assert_eq!(sub_m.value_of("test").unwrap(), "awesome"); +} + +#[test] +fn invisible_arg_aliases_help_output() { + let app = App::new("ct") + .author("Salim Afiune") + .subcommand(SubCommand::with_name("test") + .about("Some help") + .version("1.2") + .arg(Arg::with_name("opt") + .long("opt") + .short("o") + .takes_value(true) + .aliases(&["invisible", "als1", "more"])) + .arg(Arg::from_usage("-f, --flag") + .aliases(&["invisible", "flg1", "anyway"]))); + assert!(test::compare_output(app, "ct test --help", SC_INVISIBLE_ALIAS_HELP, false)); +} + +#[test] +fn visible_arg_aliases_help_output() { + let app = App::new("ct") + .author("Salim Afiune") + .subcommand(SubCommand::with_name("test") + .about("Some help") + .version("1.2") + .arg(Arg::with_name("opt") + .long("opt") + .short("o") + .takes_value(true) + .alias("invisible") + .visible_alias("visible")) + .arg(Arg::with_name("flg") + .long("flag") + .short("f") + .visible_aliases(&["v_flg", "flag2", "flg3"]))); + assert!(test::compare_output(app, "ct test --help", SC_VISIBLE_ALIAS_HELP, false)); +} diff --git a/clap/tests/borrowed.rs b/clap/tests/borrowed.rs new file mode 100644 index 0000000..e7a184b --- /dev/null +++ b/clap/tests/borrowed.rs @@ -0,0 +1,19 @@ +extern crate clap; +extern crate regex; + +use clap::{App, Arg, SubCommand}; + +include!("../clap-test.rs"); + +#[test] +fn borrowed_args() { + let arg = Arg::with_name("some").short("s").long("some").help("other help"); + let arg2 = Arg::with_name("some2").short("S").long("some-thing").help("other help"); + let result = App::new("sub_command_negate") + .arg(Arg::with_name("test").index(1)) + .arg(&arg) + .arg(&arg2) + .subcommand(SubCommand::with_name("sub1").arg(&arg)) + .get_matches_from_safe(vec!["prog"]); + assert!(result.is_ok()); +} diff --git a/clap/tests/completions.rs b/clap/tests/completions.rs new file mode 100644 index 0000000..24409ad --- /dev/null +++ b/clap/tests/completions.rs @@ -0,0 +1,883 @@ +extern crate regex; +extern crate clap; + +use clap::{App, Arg, SubCommand, Shell}; +use regex::Regex; + +static BASH: &'static str = r#"_myapp() { + local i cur prev opts cmds + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + cmd="" + opts="" + + for i in ${COMP_WORDS[@]} + do + case "${i}" in + myapp) + cmd="myapp" + ;; + + help) + cmd+="__help" + ;; + test) + cmd+="__test" + ;; + *) + ;; + esac + done + + case "${cmd}" in + myapp) + opts=" -h -V --help --version test help" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + + myapp__help) + opts=" -h -V --help --version " + if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + myapp__test) + opts=" -h -V --help --version --case " + if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + + --case) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + esac +} + +complete -F _myapp -o bashdefault -o default myapp +"#; + +static ZSH: &'static str = r#"#compdef myapp + +autoload -U is-at-least + +_myapp() { + typeset -A opt_args + typeset -a _arguments_options + local ret=1 + + if is-at-least 5.2; then + _arguments_options=(-s -S -C) + else + _arguments_options=(-s -C) + fi + + local context curcontext="$curcontext" state line + _arguments "${_arguments_options[@]}" \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +'::file -- some input file:_files' \ +":: :_myapp_commands" \ +"*::: :->myapp" \ +&& ret=0 + case $state in + (myapp) + words=($line[2] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:myapp-command-$line[2]:" + case $line[2] in + (test) +_arguments "${_arguments_options[@]}" \ +'--case=[the case to test]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; +(help) +_arguments "${_arguments_options[@]}" \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; + esac + ;; +esac +} + +(( $+functions[_myapp_commands] )) || +_myapp_commands() { + local commands; commands=( + "test:tests things" \ +"help:Prints this message or the help of the given subcommand(s)" \ + ) + _describe -t commands 'myapp commands' commands "$@" +} +(( $+functions[_myapp__help_commands] )) || +_myapp__help_commands() { + local commands; commands=( + + ) + _describe -t commands 'myapp help commands' commands "$@" +} +(( $+functions[_myapp__test_commands] )) || +_myapp__test_commands() { + local commands; commands=( + + ) + _describe -t commands 'myapp test commands' commands "$@" +} + +_myapp "$@""#; + +static FISH: &'static str = r#"complete -c myapp -n "__fish_use_subcommand" -s h -l help -d 'Prints help information' +complete -c myapp -n "__fish_use_subcommand" -s V -l version -d 'Prints version information' +complete -c myapp -n "__fish_use_subcommand" -f -a "test" -d 'tests things' +complete -c myapp -n "__fish_use_subcommand" -f -a "help" -d 'Prints this message or the help of the given subcommand(s)' +complete -c myapp -n "__fish_seen_subcommand_from test" -l case -d 'the case to test' +complete -c myapp -n "__fish_seen_subcommand_from test" -s h -l help -d 'Prints help information' +complete -c myapp -n "__fish_seen_subcommand_from test" -s V -l version -d 'Prints version information' +complete -c myapp -n "__fish_seen_subcommand_from help" -s h -l help -d 'Prints help information' +complete -c myapp -n "__fish_seen_subcommand_from help" -s V -l version -d 'Prints version information' +"#; + +static POWERSHELL: &'static str = r#" +using namespace System.Management.Automation +using namespace System.Management.Automation.Language + +Register-ArgumentCompleter -Native -CommandName 'my_app' -ScriptBlock { + param($wordToComplete, $commandAst, $cursorPosition) + + $commandElements = $commandAst.CommandElements + $command = @( + 'my_app' + for ($i = 1; $i -lt $commandElements.Count; $i++) { + $element = $commandElements[$i] + if ($element -isnot [StringConstantExpressionAst] -or + $element.StringConstantType -ne [StringConstantType]::BareWord -or + $element.Value.StartsWith('-')) { + break + } + $element.Value + }) -join ';' + + $completions = @(switch ($command) { + 'my_app' { + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information') + [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'tests things') + [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Prints this message or the help of the given subcommand(s)') + break + } + 'my_app;test' { + [CompletionResult]::new('--case', 'case', [CompletionResultType]::ParameterName, 'the case to test') + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information') + break + } + 'my_app;help' { + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information') + break + } + }) + + $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | + Sort-Object -Property ListItemText +} +"#; + +static ELVISH: &'static str = r#" +edit:completion:arg-completer[my_app] = [@words]{ + fn spaces [n]{ + repeat $n ' ' | joins '' + } + fn cand [text desc]{ + edit:complex-candidate $text &display-suffix=' '(spaces (- 14 (wcswidth $text)))$desc + } + command = 'my_app' + for word $words[1:-1] { + if (has-prefix $word '-') { + break + } + command = $command';'$word + } + completions = [ + &'my_app'= { + cand -h 'Prints help information' + cand --help 'Prints help information' + cand -V 'Prints version information' + cand --version 'Prints version information' + cand test 'tests things' + cand help 'Prints this message or the help of the given subcommand(s)' + } + &'my_app;test'= { + cand --case 'the case to test' + cand -h 'Prints help information' + cand --help 'Prints help information' + cand -V 'Prints version information' + cand --version 'Prints version information' + } + &'my_app;help'= { + cand -h 'Prints help information' + cand --help 'Prints help information' + cand -V 'Prints version information' + cand --version 'Prints version information' + } + ] + $completions[$command] +} +"#; + +static ELVISH_SPECIAL_CMDS: &'static str = r#" +edit:completion:arg-completer[my_app] = [@words]{ + fn spaces [n]{ + repeat $n ' ' | joins '' + } + fn cand [text desc]{ + edit:complex-candidate $text &display-suffix=' '(spaces (- 14 (wcswidth $text)))$desc + } + command = 'my_app' + for word $words[1:-1] { + if (has-prefix $word '-') { + break + } + command = $command';'$word + } + completions = [ + &'my_app'= { + cand -h 'Prints help information' + cand --help 'Prints help information' + cand -V 'Prints version information' + cand --version 'Prints version information' + cand test 'tests things' + cand some_cmd 'tests other things' + cand some-cmd-with-hypens 'some-cmd-with-hypens' + cand help 'Prints this message or the help of the given subcommand(s)' + } + &'my_app;test'= { + cand --case 'the case to test' + cand -h 'Prints help information' + cand --help 'Prints help information' + cand -V 'Prints version information' + cand --version 'Prints version information' + } + &'my_app;some_cmd'= { + cand --config 'the other case to test' + cand -h 'Prints help information' + cand --help 'Prints help information' + cand -V 'Prints version information' + cand --version 'Prints version information' + } + &'my_app;some-cmd-with-hypens'= { + cand -h 'Prints help information' + cand --help 'Prints help information' + cand -V 'Prints version information' + cand --version 'Prints version information' + } + &'my_app;help'= { + cand -h 'Prints help information' + cand --help 'Prints help information' + cand -V 'Prints version information' + cand --version 'Prints version information' + } + ] + $completions[$command] +} +"#; + +static POWERSHELL_SPECIAL_CMDS: &'static str = r#" +using namespace System.Management.Automation +using namespace System.Management.Automation.Language + +Register-ArgumentCompleter -Native -CommandName 'my_app' -ScriptBlock { + param($wordToComplete, $commandAst, $cursorPosition) + + $commandElements = $commandAst.CommandElements + $command = @( + 'my_app' + for ($i = 1; $i -lt $commandElements.Count; $i++) { + $element = $commandElements[$i] + if ($element -isnot [StringConstantExpressionAst] -or + $element.StringConstantType -ne [StringConstantType]::BareWord -or + $element.Value.StartsWith('-')) { + break + } + $element.Value + }) -join ';' + + $completions = @(switch ($command) { + 'my_app' { + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information') + [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'tests things') + [CompletionResult]::new('some_cmd', 'some_cmd', [CompletionResultType]::ParameterValue, 'tests other things') + [CompletionResult]::new('some-cmd-with-hypens', 'some-cmd-with-hypens', [CompletionResultType]::ParameterValue, 'some-cmd-with-hypens') + [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Prints this message or the help of the given subcommand(s)') + break + } + 'my_app;test' { + [CompletionResult]::new('--case', 'case', [CompletionResultType]::ParameterName, 'the case to test') + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information') + break + } + 'my_app;some_cmd' { + [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'the other case to test') + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information') + break + } + 'my_app;some-cmd-with-hypens' { + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information') + break + } + 'my_app;help' { + [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information') + [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information') + [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information') + break + } + }) + + $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | + Sort-Object -Property ListItemText +} +"#; + +static ZSH_SPECIAL_CMDS: &'static str = r#"#compdef my_app + +autoload -U is-at-least + +_my_app() { + typeset -A opt_args + typeset -a _arguments_options + local ret=1 + + if is-at-least 5.2; then + _arguments_options=(-s -S -C) + else + _arguments_options=(-s -C) + fi + + local context curcontext="$curcontext" state line + _arguments "${_arguments_options[@]}" \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +'::file -- some input file:_files' \ +":: :_my_app_commands" \ +"*::: :->my_app" \ +&& ret=0 + case $state in + (my_app) + words=($line[2] "${words[@]}") + (( CURRENT += 1 )) + curcontext="${curcontext%:*:*}:my_app-command-$line[2]:" + case $line[2] in + (test) +_arguments "${_arguments_options[@]}" \ +'--case=[the case to test]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; +(some_cmd) +_arguments "${_arguments_options[@]}" \ +'--config=[the other case to test]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; +(some-cmd-with-hypens) +_arguments "${_arguments_options[@]}" \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; +(help) +_arguments "${_arguments_options[@]}" \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 +;; + esac + ;; +esac +} + +(( $+functions[_my_app_commands] )) || +_my_app_commands() { + local commands; commands=( + "test:tests things" \ +"some_cmd:tests other things" \ +"some-cmd-with-hypens:" \ +"help:Prints this message or the help of the given subcommand(s)" \ + ) + _describe -t commands 'my_app commands' commands "$@" +} +(( $+functions[_my_app__help_commands] )) || +_my_app__help_commands() { + local commands; commands=( + + ) + _describe -t commands 'my_app help commands' commands "$@" +} +(( $+functions[_my_app__some-cmd-with-hypens_commands] )) || +_my_app__some-cmd-with-hypens_commands() { + local commands; commands=( + + ) + _describe -t commands 'my_app some-cmd-with-hypens commands' commands "$@" +} +(( $+functions[_my_app__some_cmd_commands] )) || +_my_app__some_cmd_commands() { + local commands; commands=( + + ) + _describe -t commands 'my_app some_cmd commands' commands "$@" +} +(( $+functions[_my_app__test_commands] )) || +_my_app__test_commands() { + local commands; commands=( + + ) + _describe -t commands 'my_app test commands' commands "$@" +} + +_my_app "$@""#; + +static FISH_SPECIAL_CMDS: &'static str = r#"complete -c my_app -n "__fish_use_subcommand" -s h -l help -d 'Prints help information' +complete -c my_app -n "__fish_use_subcommand" -s V -l version -d 'Prints version information' +complete -c my_app -n "__fish_use_subcommand" -f -a "test" -d 'tests things' +complete -c my_app -n "__fish_use_subcommand" -f -a "some_cmd" -d 'tests other things' +complete -c my_app -n "__fish_use_subcommand" -f -a "some-cmd-with-hypens" +complete -c my_app -n "__fish_use_subcommand" -f -a "help" -d 'Prints this message or the help of the given subcommand(s)' +complete -c my_app -n "__fish_seen_subcommand_from test" -l case -d 'the case to test' +complete -c my_app -n "__fish_seen_subcommand_from test" -s h -l help -d 'Prints help information' +complete -c my_app -n "__fish_seen_subcommand_from test" -s V -l version -d 'Prints version information' +complete -c my_app -n "__fish_seen_subcommand_from some_cmd" -l config -d 'the other case to test' +complete -c my_app -n "__fish_seen_subcommand_from some_cmd" -s h -l help -d 'Prints help information' +complete -c my_app -n "__fish_seen_subcommand_from some_cmd" -s V -l version -d 'Prints version information' +complete -c my_app -n "__fish_seen_subcommand_from some-cmd-with-hypens" -s h -l help -d 'Prints help information' +complete -c my_app -n "__fish_seen_subcommand_from some-cmd-with-hypens" -s V -l version -d 'Prints version information' +complete -c my_app -n "__fish_seen_subcommand_from help" -s h -l help -d 'Prints help information' +complete -c my_app -n "__fish_seen_subcommand_from help" -s V -l version -d 'Prints version information' +"#; + +static BASH_SPECIAL_CMDS: &'static str = r#"_my_app() { + local i cur prev opts cmds + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + cmd="" + opts="" + + for i in ${COMP_WORDS[@]} + do + case "${i}" in + my_app) + cmd="my_app" + ;; + + help) + cmd+="__help" + ;; + some-cmd-with-hypens) + cmd+="__some__cmd__with__hypens" + ;; + some_cmd) + cmd+="__some_cmd" + ;; + test) + cmd+="__test" + ;; + *) + ;; + esac + done + + case "${cmd}" in + my_app) + opts=" -h -V --help --version test some_cmd some-cmd-with-hypens help" + if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + + my_app__help) + opts=" -h -V --help --version " + if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my_app__some__cmd__with__hypens) + opts=" -h -V --help --version " + if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my_app__some_cmd) + opts=" -h -V --help --version --config " + if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + + --config) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + my_app__test) + opts=" -h -V --help --version --case " + if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + case "${prev}" in + + --case) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + *) + COMPREPLY=() + ;; + esac + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + ;; + esac +} + +complete -F _my_app -o bashdefault -o default my_app +"#; + +static FISH_SPECIAL_HELP: &'static str = r#"complete -c my_app -n "__fish_use_subcommand" -l single-quotes -d 'Can be \'always\', \'auto\', or \'never\'' +complete -c my_app -n "__fish_use_subcommand" -l double-quotes -d 'Can be "always", "auto", or "never"' +complete -c my_app -n "__fish_use_subcommand" -l backticks -d 'For more information see `echo test`' +complete -c my_app -n "__fish_use_subcommand" -l backslash -d 'Avoid \'\\n\'' +complete -c my_app -n "__fish_use_subcommand" -l brackets -d 'List packages [filter]' +complete -c my_app -n "__fish_use_subcommand" -l expansions -d 'Execute the shell command with $SHELL' +complete -c my_app -n "__fish_use_subcommand" -s h -l help -d 'Prints help information' +complete -c my_app -n "__fish_use_subcommand" -s V -l version -d 'Prints version information' +"#; + +static ZSH_SPECIAL_HELP: &'static str = r#"#compdef my_app + +autoload -U is-at-least + +_my_app() { + typeset -A opt_args + typeset -a _arguments_options + local ret=1 + + if is-at-least 5.2; then + _arguments_options=(-s -S -C) + else + _arguments_options=(-s -C) + fi + + local context curcontext="$curcontext" state line + _arguments "${_arguments_options[@]}" \ +'--single-quotes[Can be '\''always'\'', '\''auto'\'', or '\''never'\'']' \ +'--double-quotes[Can be "always", "auto", or "never"]' \ +'--backticks[For more information see `echo test`]' \ +'--backslash[Avoid '\''\\n'\'']' \ +'--brackets[List packages \[filter\]]' \ +'--expansions[Execute the shell command with $SHELL]' \ +'-h[Prints help information]' \ +'--help[Prints help information]' \ +'-V[Prints version information]' \ +'--version[Prints version information]' \ +&& ret=0 + +} + +(( $+functions[_my_app_commands] )) || +_my_app_commands() { + local commands; commands=( + + ) + _describe -t commands 'my_app commands' commands "$@" +} + +_my_app "$@""#; + +fn compare(left: &str, right: &str) -> bool { + let b = left == right; + if !b { + let re = Regex::new(" ").unwrap(); + println!(); + println!("--> left"); + // println!("{}", left); + println!("{}", re.replace_all(left, "\u{2022}")); + println!("--> right"); + println!("{}", re.replace_all(right, "\u{2022}")); + // println!("{}", right); + println!("--") + } + b +} + +fn build_app() -> App<'static, 'static> { build_app_with_name("myapp") } + +fn build_app_with_name(s: &'static str) -> App<'static, 'static> { + App::new(s) + .about("Tests completions") + .arg(Arg::with_name("file").help("some input file")) + .subcommand(SubCommand::with_name("test") + .about("tests things") + .arg(Arg::with_name("case") + .long("case") + .takes_value(true) + .help("the case to test"))) +} + +fn build_app_special_commands() -> App<'static, 'static> { + build_app_with_name("my_app") + .subcommand(SubCommand::with_name("some_cmd") + .about("tests other things") + .arg(Arg::with_name("config") + .long("--config") + .takes_value(true) + .help("the other case to test"))) + .subcommand(SubCommand::with_name("some-cmd-with-hypens")) +} + +fn build_app_special_help() -> App<'static, 'static> { + App::new("my_app") + .arg(Arg::with_name("single-quotes") + .long("single-quotes") + .help("Can be 'always', 'auto', or 'never'")) + .arg(Arg::with_name("double-quotes") + .long("double-quotes") + .help("Can be \"always\", \"auto\", or \"never\"")) + .arg(Arg::with_name("backticks") + .long("backticks") + .help("For more information see `echo test`")) + .arg(Arg::with_name("backslash") + .long("backslash") + .help("Avoid '\\n'")) + .arg(Arg::with_name("brackets") + .long("brackets") + .help("List packages [filter]")) + .arg(Arg::with_name("expansions") + .long("expansions") + .help("Execute the shell command with $SHELL")) +} + +#[test] +fn bash() { + let mut app = build_app(); + let mut buf = vec![]; + app.gen_completions_to("myapp", Shell::Bash, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, BASH)); +} + +#[test] +fn zsh() { + let mut app = build_app(); + let mut buf = vec![]; + app.gen_completions_to("myapp", Shell::Zsh, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, ZSH)); +} + +#[test] +fn fish() { + let mut app = build_app(); + let mut buf = vec![]; + app.gen_completions_to("myapp", Shell::Fish, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, FISH)); +} + +#[test] +fn powershell() { + let mut app = build_app(); + let mut buf = vec![]; + app.gen_completions_to("my_app", Shell::PowerShell, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, POWERSHELL)); +} + +#[test] +fn elvish() { + let mut app = build_app(); + let mut buf = vec![]; + app.gen_completions_to("my_app", Shell::Elvish, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, ELVISH)); +} + +#[test] +fn elvish_with_special_commands() { + let mut app = build_app_special_commands(); + let mut buf = vec![]; + app.gen_completions_to("my_app", Shell::Elvish, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, ELVISH_SPECIAL_CMDS)); +} + +#[test] +fn powershell_with_special_commands() { + let mut app = build_app_special_commands(); + let mut buf = vec![]; + app.gen_completions_to("my_app", Shell::PowerShell, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, POWERSHELL_SPECIAL_CMDS)); +} + +#[test] +fn bash_with_special_commands() { + let mut app = build_app_special_commands(); + let mut buf = vec![]; + app.gen_completions_to("my_app", Shell::Bash, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, BASH_SPECIAL_CMDS)); +} + +#[test] +fn fish_with_special_commands() { + let mut app = build_app_special_commands(); + let mut buf = vec![]; + app.gen_completions_to("my_app", Shell::Fish, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, FISH_SPECIAL_CMDS)); +} + +#[test] +fn zsh_with_special_commands() { + let mut app = build_app_special_commands(); + let mut buf = vec![]; + app.gen_completions_to("my_app", Shell::Zsh, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, ZSH_SPECIAL_CMDS)); +} + +#[test] +fn fish_with_special_help() { + let mut app = build_app_special_help(); + let mut buf = vec![]; + app.gen_completions_to("my_app", Shell::Fish, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, FISH_SPECIAL_HELP)); +} + +#[test] +fn zsh_with_special_help() { + let mut app = build_app_special_help(); + let mut buf = vec![]; + app.gen_completions_to("my_app", Shell::Zsh, &mut buf); + let string = String::from_utf8(buf).unwrap(); + + assert!(compare(&*string, ZSH_SPECIAL_HELP)); +} diff --git a/clap/tests/conflicts.rs b/clap/tests/conflicts.rs new file mode 100644 index 0000000..72a9e05 --- /dev/null +++ b/clap/tests/conflicts.rs @@ -0,0 +1,102 @@ +extern crate clap; +extern crate regex; + +include!("../clap-test.rs"); + +use clap::{App, Arg, ErrorKind, ArgGroup}; + +static CONFLICT_ERR: &'static str = "error: The argument '-F' cannot be used with '--flag' + +USAGE: + clap-test --flag --long-option-2 + +For more information try --help"; + +static CONFLICT_ERR_REV: &'static str = "error: The argument '--flag' cannot be used with '-F' + +USAGE: + clap-test -F --long-option-2 + +For more information try --help"; + +#[test] +fn flag_conflict() { + let result = App::new("flag_conflict") + .arg(Arg::from_usage("-f, --flag 'some flag'") + .conflicts_with("other")) + .arg(Arg::from_usage("-o, --other 'some flag'")) + .get_matches_from_safe(vec!["myprog", "-f", "-o"]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::ArgumentConflict); +} + +#[test] +fn flag_conflict_2() { + let result = App::new("flag_conflict") + .arg(Arg::from_usage("-f, --flag 'some flag'") + .conflicts_with("other")) + .arg(Arg::from_usage("-o, --other 'some flag'")) + .get_matches_from_safe(vec!["myprog", "-o", "-f"]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::ArgumentConflict); +} + +#[test] +fn group_conflict() { + let result = App::new("group_conflict") + .arg(Arg::from_usage("-f, --flag 'some flag'") + .conflicts_with("gr")) + .group(ArgGroup::with_name("gr") + .required(true) + .arg("some") + .arg("other")) + .arg(Arg::from_usage("--some 'some arg'")) + .arg(Arg::from_usage("--other 'other arg'")) + .get_matches_from_safe(vec!["myprog", "--other", "-f"]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::ArgumentConflict); +} + +#[test] +fn group_conflict_2() { + let result = App::new("group_conflict") + .arg(Arg::from_usage("-f, --flag 'some flag'") + .conflicts_with("gr")) + .group(ArgGroup::with_name("gr") + .required(true) + .arg("some") + .arg("other")) + .arg(Arg::from_usage("--some 'some arg'")) + .arg(Arg::from_usage("--other 'other arg'")) + .get_matches_from_safe(vec!["myprog", "-f", "--some"]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::ArgumentConflict); +} + +#[test] +fn conflict_output() { + test::compare_output(test::complex_app(), "clap-test val1 --flag --long-option-2 val2 -F", CONFLICT_ERR, true); +} + +#[test] +fn conflict_output_rev() { + test::compare_output(test::complex_app(), "clap-test val1 -F --long-option-2 val2 --flag", CONFLICT_ERR_REV, true); +} + +#[test] +fn conflict_with_unused_default_value() { + let result = App::new("conflict") + .arg(Arg::from_usage("-o, --opt=[opt] 'some opt'") + .default_value("default")) + .arg(Arg::from_usage("-f, --flag 'some flag'") + .conflicts_with("opt")) + .get_matches_from_safe(vec!["myprog", "-f"]); + assert!(result.is_ok()); + let m = result.unwrap(); + assert_eq!(m.value_of("opt"), Some("default")); + assert!(m.is_present("flag")); +} diff --git a/clap/tests/default_vals.rs b/clap/tests/default_vals.rs new file mode 100644 index 0000000..0dfd3c8 --- /dev/null +++ b/clap/tests/default_vals.rs @@ -0,0 +1,498 @@ +extern crate clap; +extern crate regex; + +include!("../clap-test.rs"); + +use clap::{App, Arg, ErrorKind}; + +#[test] +fn opts() { + let r = App::new("df") + .arg( + Arg::from_usage("-o [opt] 'some opt'").default_value("default"), + ) + .get_matches_from_safe(vec![""]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("o")); + assert_eq!(m.value_of("o").unwrap(), "default"); +} + +#[test] +fn opt_user_override() { + let r = App::new("df") + .arg( + Arg::from_usage("--opt [FILE] 'some arg'").default_value("default"), + ) + .get_matches_from_safe(vec!["", "--opt", "value"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("opt")); + assert_eq!(m.value_of("opt").unwrap(), "value"); +} + +#[test] +fn positionals() { + let r = App::new("df") + .arg(Arg::from_usage("[arg] 'some opt'").default_value("default")) + .get_matches_from_safe(vec![""]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "default"); +} + +#[test] +fn positional_user_override() { + let r = App::new("df") + .arg(Arg::from_usage("[arg] 'some arg'").default_value("default")) + .get_matches_from_safe(vec!["", "value"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "value"); +} + +// OsStr Default Values + +#[test] +fn osstr_opts() { + use std::ffi::OsStr; + let expected = OsStr::new("default"); + + let r = App::new("df") + .arg( + Arg::from_usage("-o [opt] 'some opt'").default_value_os(expected), + ) + .get_matches_from_safe(vec![""]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("o")); + assert_eq!(m.value_of("o").unwrap(), expected); +} + +#[test] +fn osstr_opt_user_override() { + use std::ffi::OsStr; + let default = OsStr::new("default"); + + let r = App::new("df") + .arg( + Arg::from_usage("--opt [FILE] 'some arg'").default_value_os(default), + ) + .get_matches_from_safe(vec!["", "--opt", "value"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("opt")); + assert_eq!(m.value_of("opt").unwrap(), "value"); +} + +#[test] +fn osstr_positionals() { + use std::ffi::OsStr; + let expected = OsStr::new("default"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some opt'").default_value_os(expected), + ) + .get_matches_from_safe(vec![""]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), expected); +} + +#[test] +fn osstr_positional_user_override() { + use std::ffi::OsStr; + let default = OsStr::new("default"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some arg'").default_value_os(default), + ) + .get_matches_from_safe(vec!["", "value"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "value"); +} + +// --- Default if arg is present + +#[test] +fn default_if_arg_present_no_default() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value_if( + "opt", + None, + "default", + )) + .get_matches_from_safe(vec!["", "--opt", "some"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "default"); +} + +#[test] +fn default_if_arg_present_no_default_user_override() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value_if( + "opt", + None, + "default", + )) + .get_matches_from_safe(vec!["", "--opt", "some", "other"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "other"); +} + +#[test] +fn default_if_arg_present_no_arg_with_default() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", None, "default"), + ) + .get_matches_from_safe(vec![""]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "first"); +} + +#[test] +fn default_if_arg_present_with_default() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", None, "default"), + ) + .get_matches_from_safe(vec!["", "--opt", "some"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "default"); +} + +#[test] +fn default_if_arg_present_with_default_user_override() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", None, "default"), + ) + .get_matches_from_safe(vec!["", "--opt", "some", "other"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "other"); +} + +#[test] +fn default_if_arg_present_no_arg_with_default_user_override() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", None, "default"), + ) + .get_matches_from_safe(vec!["", "other"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "other"); +} + +// Conditional Default Values + +#[test] +fn default_if_arg_present_with_value_no_default() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value_if( + "opt", + Some("value"), + "default", + )) + .get_matches_from_safe(vec!["", "--opt", "value"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "default"); +} + +#[test] +fn default_if_arg_present_with_value_no_default_fail() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value_if( + "opt", + Some("value"), + "default", + )) + .get_matches_from_safe(vec!["", "--opt", "other"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(!m.is_present("arg")); + //assert_eq!(m.value_of("arg").unwrap(), "default"); +} + +#[test] +fn default_if_arg_present_with_value_no_default_user_override() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value_if( + "opt", + Some("some"), + "default", + )) + .get_matches_from_safe(vec!["", "--opt", "some", "other"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "other"); +} + +#[test] +fn default_if_arg_present_with_value_no_arg_with_default() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) + .get_matches_from_safe(vec![""]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "first"); +} + +#[test] +fn default_if_arg_present_with_value_no_arg_with_default_fail() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) + .get_matches_from_safe(vec!["", "--opt", "other"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "first"); +} + +#[test] +fn default_if_arg_present_with_value_with_default() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) + .get_matches_from_safe(vec!["", "--opt", "some"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "default"); +} + +#[test] +fn default_if_arg_present_with_value_with_default_user_override() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) + .get_matches_from_safe(vec!["", "--opt", "some", "other"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "other"); +} + +#[test] +fn default_if_arg_present_no_arg_with_value_with_default_user_override() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) + .get_matches_from_safe(vec!["", "other"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "other"); +} + +#[test] +fn default_if_arg_present_no_arg_with_value_with_default_user_override_fail() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) + .get_matches_from_safe(vec!["", "--opt", "value", "other"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "other"); +} + +// Multiple conditions + +#[test] +fn default_ifs_arg_present() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("--flag 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_ifs(&[("opt", Some("some"), "default"), ("flag", None, "flg")]), + ) + .get_matches_from_safe(vec!["", "--flag"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "flg"); +} + +#[test] +fn default_ifs_arg_present_user_override() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("--flag 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_ifs(&[("opt", Some("some"), "default"), ("flag", None, "flg")]), + ) + .get_matches_from_safe(vec!["", "--flag", "value"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "value"); +} + +#[test] +fn default_ifs_arg_present_order() { + let r = App::new("df") + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("--flag 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_ifs(&[("opt", Some("some"), "default"), ("flag", None, "flg")]), + ) + .get_matches_from_safe(vec!["", "--opt=some", "--flag"]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "default"); +} + +#[test] +fn conditional_reqs_fail() { + let m = App::new("Test app") + .version("1.0") + .author("F0x06") + .about("Arg test") + .arg( + Arg::with_name("target") + .takes_value(true) + .default_value("file") + .possible_values(&["file", "stdout"]) + .long("target"), + ) + .arg( + Arg::with_name("input") + .takes_value(true) + .required(true) + .long("input"), + ) + .arg( + Arg::with_name("output") + .takes_value(true) + .required_if("target", "file") + .long("output"), + ) + .get_matches_from_safe(vec!["test", "--input", "some"]); + + assert!(m.is_err()); + assert_eq!(m.unwrap_err().kind, ErrorKind::MissingRequiredArgument); +} + +#[test] +fn conditional_reqs_pass() { + let m = App::new("Test app") + .version("1.0") + .author("F0x06") + .about("Arg test") + .arg( + Arg::with_name("target") + .takes_value(true) + .default_value("file") + .possible_values(&["file", "stdout"]) + .long("target"), + ) + .arg( + Arg::with_name("input") + .takes_value(true) + .required(true) + .long("input"), + ) + .arg( + Arg::with_name("output") + .takes_value(true) + .required_if("target", "file") + .long("output"), + ) + .get_matches_from_safe(vec!["test", "--input", "some", "--output", "other"]); + + assert!(m.is_ok()); + let m = m.unwrap(); + assert_eq!(m.value_of("output"), Some("other")); + assert_eq!(m.value_of("input"), Some("some")); +} + +#[test] +fn issue_1050_num_vals_and_defaults() { + let res = App::new("hello") + .arg( + Arg::with_name("exit-code") + .long("exit-code") + .required(true) + .takes_value(true) + .number_of_values(1) + .default_value("0"), + ) + .get_matches_from_safe(vec!["hello", "--exit-code=1"]); + assert!(res.is_ok()); + let m = res.unwrap(); + assert_eq!(m.value_of("exit-code"), Some("1")); +} diff --git a/clap/tests/delimiters.rs b/clap/tests/delimiters.rs new file mode 100644 index 0000000..d5b60b9 --- /dev/null +++ b/clap/tests/delimiters.rs @@ -0,0 +1,139 @@ +extern crate clap; + +use clap::{App, Arg}; + +#[test] +fn opt_default_no_delim() { + let m = App::new("no_delim") + .arg(Arg::with_name("option") + .long("option") + .takes_value(true)) + .get_matches_from_safe(vec![ + "", + "--option", "val1,val2,val3", + ]); + + assert!(m.is_ok()); + let m = m.unwrap(); + + assert!(m.is_present("option")); + assert_eq!(m.occurrences_of("option"), 1); + assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); +} + +#[test] +fn opt_eq_no_delim() { + let m = App::new("no_delim") + .arg(Arg::with_name("option") + .long("option") + .takes_value(true)) + .get_matches_from_safe(vec![ + "", + "--option=val1,val2,val3", + ]); + + assert!(m.is_ok()); + let m = m.unwrap(); + + assert!(m.is_present("option")); + assert_eq!(m.occurrences_of("option"), 1); + assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); +} + +#[test] +fn opt_s_eq_no_delim() { + let m = App::new("no_delim") + .arg(Arg::with_name("option") + .short("o") + .takes_value(true)) + .get_matches_from_safe(vec![ + "", + "-o=val1,val2,val3", + ]); + + assert!(m.is_ok(), "{:?}", m.unwrap_err()); + let m = m.unwrap(); + + assert!(m.is_present("option")); + assert_eq!(m.occurrences_of("option"), 1); + assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); +} + +#[test] +fn opt_s_default_no_delim() { + let m = App::new("no_delim") + .arg(Arg::with_name("option") + .short("o") + .takes_value(true)) + .get_matches_from_safe(vec![ + "", + "-o", "val1,val2,val3", + ]); + + assert!(m.is_ok(), "{:?}", m.unwrap_err()); + let m = m.unwrap(); + + assert!(m.is_present("option")); + assert_eq!(m.occurrences_of("option"), 1); + assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); +} + +#[test] +fn opt_s_no_space_no_delim() { + let m = App::new("no_delim") + .arg(Arg::with_name("option") + .short("o") + .takes_value(true)) + .get_matches_from_safe(vec![ + "", + "-o", "val1,val2,val3", + ]); + + assert!(m.is_ok()); + let m = m.unwrap(); + + assert!(m.is_present("option")); + assert_eq!(m.occurrences_of("option"), 1); + assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); +} + +#[test] +fn opt_s_no_space_mult_no_delim() { + let m = App::new("no_delim") + .arg(Arg::with_name("option") + .short("o") + .multiple(true) + .takes_value(true)) + .get_matches_from_safe(vec![ + "", + "-o", "val1,val2,val3", + ]); + + assert!(m.is_ok()); + let m = m.unwrap(); + + assert!(m.is_present("option")); + assert_eq!(m.occurrences_of("option"), 1); + assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); +} + +#[test] +fn opt_eq_mult_def_delim() { + let m = App::new("no_delim") + .arg(Arg::with_name("option") + .long("opt") + .multiple(true) + .use_delimiter(true) + .takes_value(true)) + .get_matches_from_safe(vec![ + "", + "--opt=val1,val2,val3", + ]); + + assert!(m.is_ok()); + let m = m.unwrap(); + + assert!(m.is_present("option")); + assert_eq!(m.occurrences_of("option"), 1); + assert_eq!(m.values_of("option").unwrap().collect::>(), &["val1", "val2", "val3"]); +} diff --git a/clap/tests/derive_order.rs b/clap/tests/derive_order.rs new file mode 100644 index 0000000..b30c8ad --- /dev/null +++ b/clap/tests/derive_order.rs @@ -0,0 +1,245 @@ +extern crate clap; +extern crate regex; + +use std::str; + +use clap::{App, Arg, SubCommand, AppSettings}; + +include!("../clap-test.rs"); + +static NO_DERIVE_ORDER: &'static str = "test 1.2 + +USAGE: + test [FLAGS] [OPTIONS] + +FLAGS: + --flag_a second flag + --flag_b first flag + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + --option_a second option + --option_b first option"; + +static DERIVE_ORDER: &'static str = "test 1.2 + +USAGE: + test [FLAGS] [OPTIONS] + +FLAGS: + --flag_b first flag + --flag_a second flag + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + --option_b first option + --option_a second option"; + +static UNIFIED_HELP: &'static str = "test 1.2 + +USAGE: + test [OPTIONS] + +OPTIONS: + --flag_a second flag + --flag_b first flag + -h, --help Prints help information + --option_a second option + --option_b first option + -V, --version Prints version information"; + +static UNIFIED_HELP_AND_DERIVE: &'static str = "test 1.2 + +USAGE: + test [OPTIONS] + +OPTIONS: + --flag_b first flag + --option_b first option + --flag_a second flag + --option_a second option + -h, --help Prints help information + -V, --version Prints version information"; + +static DERIVE_ORDER_SC_PROP: &'static str = "test-sub 1.2 + +USAGE: + test sub [FLAGS] [OPTIONS] + +FLAGS: + --flag_b first flag + --flag_a second flag + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + --option_b first option + --option_a second option"; + +static UNIFIED_SC_PROP: &'static str = "test-sub 1.2 + +USAGE: + test sub [OPTIONS] + +OPTIONS: + --flag_a second flag + --flag_b first flag + -h, --help Prints help information + --option_a second option + --option_b first option + -V, --version Prints version information"; + +static UNIFIED_DERIVE_SC_PROP: &'static str = "test-sub 1.2 + +USAGE: + test sub [OPTIONS] + +OPTIONS: + --flag_b first flag + --option_b first option + --flag_a second flag + --option_a second option + -h, --help Prints help information + -V, --version Prints version information"; + +static UNIFIED_DERIVE_SC_PROP_EXPLICIT_ORDER: &'static str = "test-sub 1.2 + +USAGE: + test sub [OPTIONS] + +OPTIONS: + --flag_a second flag + --flag_b first flag + --option_b first option + --option_a second option + -h, --help Prints help information + -V, --version Prints version information"; + +#[test] +fn no_derive_order() { + let app = App::new("test") + .version("1.2") + .args(&[ + Arg::with_name("flag_b").long("flag_b").help("first flag"), + Arg::with_name("option_b").long("option_b").takes_value(true).help("first option"), + Arg::with_name("flag_a").long("flag_a").help("second flag"), + Arg::with_name("option_a").long("option_a").takes_value(true).help("second option"), + ]); + + assert!(test::compare_output(app, "test --help", NO_DERIVE_ORDER, false)); +} + +#[test] +fn derive_order() { + let app = App::new("test") + .setting(AppSettings::DeriveDisplayOrder) + .version("1.2") + .args(&[ + Arg::with_name("flag_b").long("flag_b").help("first flag"), + Arg::with_name("option_b").long("option_b").takes_value(true).help("first option"), + Arg::with_name("flag_a").long("flag_a").help("second flag"), + Arg::with_name("option_a").long("option_a").takes_value(true).help("second option"), + ]); + + assert!(test::compare_output(app, "test --help", DERIVE_ORDER, false)); +} + +#[test] +fn unified_help() { + let app = App::new("test") + .setting(AppSettings::UnifiedHelpMessage) + .version("1.2") + .args(&[ + Arg::with_name("flag_b").long("flag_b").help("first flag"), + Arg::with_name("option_b").long("option_b").takes_value(true).help("first option"), + Arg::with_name("flag_a").long("flag_a").help("second flag"), + Arg::with_name("option_a").long("option_a").takes_value(true).help("second option"), + ]); + + assert!(test::compare_output(app, "test --help", UNIFIED_HELP, false)); +} + +#[test] +fn unified_help_and_derive_order() { + let app = App::new("test") + .setting(AppSettings::DeriveDisplayOrder) + .setting(AppSettings::UnifiedHelpMessage) + .version("1.2") + .args(&[ + Arg::with_name("flag_b").long("flag_b").help("first flag"), + Arg::with_name("option_b").long("option_b").takes_value(true).help("first option"), + Arg::with_name("flag_a").long("flag_a").help("second flag"), + Arg::with_name("option_a").long("option_a").takes_value(true).help("second option"), + ]); + + assert!(test::compare_output(app, "test --help", UNIFIED_HELP_AND_DERIVE, false)); +} + +#[test] +fn derive_order_subcommand_propagate() { + let app = App::new("test") + .global_setting(AppSettings::DeriveDisplayOrder) + .version("1.2") + .subcommand(SubCommand::with_name("sub") + .version("1.2") + .args(&[ + Arg::with_name("flag_b").long("flag_b").help("first flag"), + Arg::with_name("option_b").long("option_b").takes_value(true).help("first option"), + Arg::with_name("flag_a").long("flag_a").help("second flag"), + Arg::with_name("option_a").long("option_a").takes_value(true).help("second option"), + ])); + + assert!(test::compare_output(app, "test sub --help", DERIVE_ORDER_SC_PROP, false)); +} + +#[test] +fn unified_help_subcommand_propagate() { + let app = App::new("test") + .global_setting(AppSettings::UnifiedHelpMessage) + .subcommand(SubCommand::with_name("sub") + .version("1.2") + .args(&[ + Arg::with_name("flag_b").long("flag_b").help("first flag"), + Arg::with_name("option_b").long("option_b").takes_value(true).help("first option"), + Arg::with_name("flag_a").long("flag_a").help("second flag"), + Arg::with_name("option_a").long("option_a").takes_value(true).help("second option"), + ])); + + assert!(test::compare_output(app, "test sub --help", UNIFIED_SC_PROP, false)); +} + +#[test] +fn unified_help_and_derive_order_subcommand_propagate() { + let app = App::new("test") + .global_setting(AppSettings::DeriveDisplayOrder) + .global_setting(AppSettings::UnifiedHelpMessage) + .subcommand(SubCommand::with_name("sub") + .version("1.2") + .args(&[ + Arg::with_name("flag_b").long("flag_b").help("first flag"), + Arg::with_name("option_b").long("option_b").takes_value(true).help("first option"), + Arg::with_name("flag_a").long("flag_a").help("second flag"), + Arg::with_name("option_a").long("option_a").takes_value(true).help("second option"), + ])); + + assert!(test::compare_output(app, "test sub --help", UNIFIED_DERIVE_SC_PROP, false)); +} + +#[test] +fn unified_help_and_derive_order_subcommand_propagate_with_explicit_display_order() { + let app = App::new("test") + .global_setting(AppSettings::DeriveDisplayOrder) + .global_setting(AppSettings::UnifiedHelpMessage) + .subcommand(SubCommand::with_name("sub") + .version("1.2") + .args(&[ + Arg::with_name("flag_b").long("flag_b").help("first flag"), + Arg::with_name("option_b").long("option_b").takes_value(true).help("first option"), + Arg::with_name("flag_a").long("flag_a").help("second flag").display_order(0), + Arg::with_name("option_a").long("option_a").takes_value(true).help("second option"), + ])); + + assert!(test::compare_output(app, "test sub --help", UNIFIED_DERIVE_SC_PROP_EXPLICIT_ORDER, false)); +} diff --git a/clap/tests/env.rs b/clap/tests/env.rs new file mode 100644 index 0000000..62833ba --- /dev/null +++ b/clap/tests/env.rs @@ -0,0 +1,263 @@ +extern crate clap; + +use std::env; +use std::ffi::OsStr; + +use clap::{App, Arg}; + +#[test] +fn env() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg(Arg::from_usage("[arg] 'some opt'").env("CLP_TEST_ENV")) + .get_matches_from_safe(vec![""]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 0); + assert_eq!(m.value_of("arg").unwrap(), "env"); +} + +#[test] +fn env_os() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some opt'").env_os(OsStr::new("CLP_TEST_ENV")), + ) + .get_matches_from_safe(vec![""]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 0); + assert_eq!(m.value_of("arg").unwrap(), "env"); +} + +#[test] +fn no_env() { + // All the other tests use the presence of the Environment variable... + // we need another variable just in case one of the others is running at the same time... + env::remove_var("CLP_TEST_ENV_NONE"); + + let r = App::new("df") + .arg(Arg::from_usage("[arg] 'some opt'").env("CLP_TEST_ENV_NONE")) + .get_matches_from_safe(vec![""]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(!m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 0); + assert_eq!(m.value_of("arg"), None); +} + +#[test] +fn with_default() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some opt'") + .env("CLP_TEST_ENV") + .default_value("default"), + ) + .get_matches_from_safe(vec![""]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 0); + assert_eq!(m.value_of("arg").unwrap(), "env"); +} + +#[test] +fn opt_user_override() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg( + Arg::from_usage("--arg [FILE] 'some arg'").env("CLP_TEST_ENV"), + ) + .get_matches_from_safe(vec!["", "--arg", "opt"]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 1); + assert_eq!(m.value_of("arg").unwrap(), "opt"); +} + +#[test] +fn positionals() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg(Arg::from_usage("[arg] 'some opt'").env("CLP_TEST_ENV")) + .get_matches_from_safe(vec![""]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 0); + assert_eq!(m.value_of("arg").unwrap(), "env"); +} + +#[test] +fn positionals_user_override() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg(Arg::from_usage("[arg] 'some opt'").env("CLP_TEST_ENV")) + .get_matches_from_safe(vec!["", "opt"]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 1); + assert_eq!(m.value_of("arg").unwrap(), "opt"); +} + +#[test] +fn multiple_one() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some opt'") + .env("CLP_TEST_ENV") + .use_delimiter(true) + .multiple(true), + ) + .get_matches_from_safe(vec![""]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 0); + assert_eq!(m.values_of("arg").unwrap().collect::>(), vec!["env"]); +} + +#[test] +fn multiple_three() { + env::set_var("CLP_TEST_ENV_MULTI1", "env1,env2,env3"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some opt'") + .env("CLP_TEST_ENV_MULTI1") + .use_delimiter(true) + .multiple(true), + ) + .get_matches_from_safe(vec![""]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 0); + assert_eq!( + m.values_of("arg").unwrap().collect::>(), + vec!["env1", "env2", "env3"] + ); +} + +#[test] +fn multiple_no_delimiter() { + env::set_var("CLP_TEST_ENV_MULTI2", "env1 env2 env3"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some opt'") + .env("CLP_TEST_ENV_MULTI2") + .multiple(true), + ) + .get_matches_from_safe(vec![""]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 0); + assert_eq!( + m.values_of("arg").unwrap().collect::>(), + vec!["env1 env2 env3"] + ); +} + +#[test] +fn possible_value() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some opt'") + .env("CLP_TEST_ENV") + .possible_value("env"), + ) + .get_matches_from_safe(vec![""]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 0); + assert_eq!(m.value_of("arg").unwrap(), "env"); +} + + +#[test] +fn not_possible_value() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some opt'") + .env("CLP_TEST_ENV") + .possible_value("never"), + ) + .get_matches_from_safe(vec![""]); + + assert!(r.is_err()); +} + +#[test] +fn validator() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some opt'") + .env("CLP_TEST_ENV") + .validator(|s| if s == "env" { + Ok(()) + } else { + Err("not equal".to_string()) + }), + ) + .get_matches_from_safe(vec![""]); + + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.occurrences_of("arg"), 0); + assert_eq!(m.value_of("arg").unwrap(), "env"); +} + +#[test] +fn validator_invalid() { + env::set_var("CLP_TEST_ENV", "env"); + + let r = App::new("df") + .arg( + Arg::from_usage("[arg] 'some opt'") + .env("CLP_TEST_ENV") + .validator(|s| if s != "env" { + Ok(()) + } else { + Err("is equal".to_string()) + }), + ) + .get_matches_from_safe(vec![""]); + + assert!(r.is_err()); +} diff --git a/clap/tests/example1_tmpl_full.txt b/clap/tests/example1_tmpl_full.txt new file mode 100644 index 0000000..6ae57fa --- /dev/null +++ b/clap/tests/example1_tmpl_full.txt @@ -0,0 +1,15 @@ +{bin} {version} +{author} +{about} + +USAGE: + {usage} + +FLAGS: +{flags} +OPTIONS: +{options} +ARGS: +{positionals} +SUBCOMMANDS: +{subcommands} diff --git a/clap/tests/example1_tmpl_simple.txt b/clap/tests/example1_tmpl_simple.txt new file mode 100644 index 0000000..af6c4b0 --- /dev/null +++ b/clap/tests/example1_tmpl_simple.txt @@ -0,0 +1,8 @@ +{bin} {version} +{author} +{about} + +USAGE: + {usage} + +{all-args} diff --git a/clap/tests/flags.rs b/clap/tests/flags.rs new file mode 100644 index 0000000..143404e --- /dev/null +++ b/clap/tests/flags.rs @@ -0,0 +1,147 @@ +extern crate clap; + +use clap::{App, Arg, ArgSettings}; + +#[test] +fn flag_using_short() { + let m = App::new("flag") + .args(&[ + Arg::from_usage("-f, --flag 'some flag'"), + Arg::from_usage("-c, --color 'some other flag'") + ]) + .get_matches_from(vec!["", "-f", "-c"]); + assert!(m.is_present("flag")); + assert!(m.is_present("color")); +} + +#[test] +fn lots_o_flags_sep() { + let r = App::new("opts") + .arg( + Arg::from_usage("-o... 'some flag'"), + ) + .get_matches_from_safe(vec!["", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", + ]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("o")); + assert_eq!(m.occurrences_of("o"), 297); // i.e. more than u8 +} + +#[test] +fn lots_o_flags_combined() { + let r = App::new("opts") + .arg( + Arg::from_usage("-o... 'some flag'"), + ) + .get_matches_from_safe(vec!["", + "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", + "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", + "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", + "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", + "-ooooooooooooooooooooooooooooooooooooooooo", + ]); + assert!(r.is_ok()); + let m = r.unwrap(); + assert!(m.is_present("o")); + assert_eq!(m.occurrences_of("o"), 297); // i.e. more than u8 +} + +#[test] +fn flag_using_long() { + let m = App::new("flag") + .args(&[ + Arg::from_usage("--flag 'some flag'"), + Arg::from_usage("--color 'some other flag'") + ]) + .get_matches_from(vec!["", "--flag", "--color"]); + assert!(m.is_present("flag")); + assert!(m.is_present("color")); +} + +#[test] +fn flag_using_mixed() { + let m = App::new("flag") + .args(&[ + Arg::from_usage("-f, --flag 'some flag'"), + Arg::from_usage("-c, --color 'some other flag'") + ]) + .get_matches_from(vec!["", "-f", "--color"]); + assert!(m.is_present("flag")); + assert!(m.is_present("color")); + + let m = App::new("flag") + .args(&[ + Arg::from_usage("-f, --flag 'some flag'"), + Arg::from_usage("-c, --color 'some other flag'") + ]) + .get_matches_from(vec!["", "--flag", "-c"]); + assert!(m.is_present("flag")); + assert!(m.is_present("color")); +} + +#[test] +fn multiple_flags_in_single() { + let m = App::new("multe_flags") + .args(&[ + Arg::from_usage("-f, --flag 'some flag'"), + Arg::from_usage("-c, --color 'some other flag'"), + Arg::from_usage("-d, --debug 'another other flag'") + ]) + .get_matches_from(vec!["", "-fcd"]); + assert!(m.is_present("flag")); + assert!(m.is_present("color")); + assert!(m.is_present("debug")); +} + +#[test] +fn short_flag_misspel() { + let a = Arg::from_usage("-f1, --flag 'some flag'"); + assert_eq!(a.b.name, "flag"); + assert_eq!(a.s.short.unwrap(), 'f'); + assert_eq!(a.s.long.unwrap(), "flag"); + assert_eq!(a.b.help.unwrap(), "some flag"); + assert!(!a.is_set(ArgSettings::Multiple)); + assert!(a.v.val_names.is_none()); + assert!(a.v.num_vals.is_none()); +} + +#[test] +fn short_flag_name_missing() { + let a = Arg::from_usage("-f 'some flag'"); + assert_eq!(a.b.name, "f"); + assert_eq!(a.s.short.unwrap(), 'f'); + assert!(a.s.long.is_none()); + assert_eq!(a.b.help.unwrap(), "some flag"); + assert!(!a.is_set(ArgSettings::Multiple)); + assert!(a.v.val_names.is_none()); + assert!(a.v.num_vals.is_none()); + +} diff --git a/clap/tests/global_args.rs b/clap/tests/global_args.rs new file mode 100644 index 0000000..4adc685 --- /dev/null +++ b/clap/tests/global_args.rs @@ -0,0 +1,37 @@ +extern crate clap; +extern crate regex; + +#[cfg(test)] +mod tests { + include!("../clap-test.rs"); + use clap::{App, Arg, SubCommand}; + + fn get_app() -> App<'static, 'static> { + App::new("myprog") + .arg(Arg::with_name("GLOBAL_ARG") + .long("global-arg") + .help( + "Specifies something needed by the subcommands", + ) + .global(true) + .takes_value(true) + .default_value("default_value")) + .arg(Arg::with_name("GLOBAL_FLAG") + .long("global-flag") + .help( + "Specifies something needed by the subcommands", + ) + .multiple(true) + .global(true)) + .subcommand(SubCommand::with_name("outer") + .subcommand(SubCommand::with_name("inner"))) + } + + #[test] + fn issue_1076() { + let mut app = get_app(); + let _ = app.get_matches_from_safe_borrow(vec!["myprog"]); + let _ = app.get_matches_from_safe_borrow(vec!["myprog"]); + let _ = app.get_matches_from_safe_borrow(vec!["myprog"]); + } +} diff --git a/clap/tests/groups.rs b/clap/tests/groups.rs new file mode 100644 index 0000000..bb108ea --- /dev/null +++ b/clap/tests/groups.rs @@ -0,0 +1,207 @@ +extern crate clap; +extern crate regex; + +include!("../clap-test.rs"); + +use clap::{App, Arg, ArgGroup, ErrorKind, SubCommand}; + +static REQ_GROUP_USAGE: &'static str = "error: The following required arguments were not provided: + + +USAGE: + clap-test + +For more information try --help"; + +static REQ_GROUP_CONFLICT_USAGE: &'static str = "error: The argument '' cannot be used with '--delete' + +USAGE: + clap-test + +For more information try --help"; + +static REQ_GROUP_CONFLICT_REV: &'static str = "error: The argument '--delete' cannot be used with 'base' + +USAGE: + clap-test + +For more information try --help"; + +#[test] +fn required_group_missing_arg() { + let result = App::new("group") + .args_from_usage("-f, --flag 'some flag' + -c, --color 'some other flag'") + .group(ArgGroup::with_name("req") + .args(&["flag", "color"]) + .required(true)) + .get_matches_from_safe(vec![""]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::MissingRequiredArgument); +} + +#[test] +#[should_panic] +fn non_existing_arg() { + let _ = App::new("group") + .args_from_usage("-f, --flag 'some flag' + -c, --color 'some other flag'") + .group(ArgGroup::with_name("req") + .args(&["flg", "color"]) + .required(true)) + .get_matches_from_safe(vec![""]); +} + +#[test] +#[should_panic(expected = "The group 'c' contains the arg 'd' that doesn't actually exist.")] +fn non_existing_arg_in_subcommand_help() { + let _ = App::new("a") + .subcommand( + SubCommand::with_name("b") + .group( + ArgGroup::with_name("c") + .args(&["d"]) + .required(true), + ) + ).get_matches_from_safe(vec!["a", "help", "b"]); +} + +#[test] +fn group_single_value() { + let res = App::new("group") + .args_from_usage("-f, --flag 'some flag' + -c, --color [color] 'some option'") + .group(ArgGroup::with_name("grp") + .args(&["flag", "color"])) + .get_matches_from_safe(vec!["", "-c", "blue"]); + assert!(res.is_ok()); + + let m = res.unwrap(); + assert!(m.is_present("grp")); + assert_eq!(m.value_of("grp").unwrap(), "blue"); +} + +#[test] +fn group_single_flag() { + let res = App::new("group") + .args_from_usage("-f, --flag 'some flag' + -c, --color [color] 'some option'") + .group(ArgGroup::with_name("grp") + .args(&["flag", "color"])) + .get_matches_from_safe(vec!["", "-f"]); + assert!(res.is_ok()); + + let m = res.unwrap(); + assert!(m.is_present("grp")); + assert!(m.value_of("grp").is_none()); +} + +#[test] +fn group_empty() { + let res = App::new("group") + .args_from_usage("-f, --flag 'some flag' + -c, --color [color] 'some option'") + .group(ArgGroup::with_name("grp") + .args(&["flag", "color"])) + .get_matches_from_safe(vec![""]); + assert!(res.is_ok()); + + let m = res.unwrap(); + assert!(!m.is_present("grp")); + assert!(m.value_of("grp").is_none()); +} + +#[test] +fn group_reqired_flags_empty() { + let result = App::new("group") + .args_from_usage("-f, --flag 'some flag' + -c, --color 'some option'") + .group(ArgGroup::with_name("grp") + .required(true) + .args(&["flag", "color"])) + .get_matches_from_safe(vec![""]); + assert!(result.is_err()); + let err = result.err().unwrap(); + assert_eq!(err.kind, ErrorKind::MissingRequiredArgument); +} + +#[test] +fn group_multi_value_single_arg() { + let res = App::new("group") + .args_from_usage("-f, --flag 'some flag' + -c, --color [color]... 'some option'") + .group(ArgGroup::with_name("grp") + .args(&["flag", "color"])) + .get_matches_from_safe(vec!["", "-c", "blue", "red", "green"]); + assert!(res.is_ok(), "{:?}", res.unwrap_err().kind); + + let m = res.unwrap(); + assert!(m.is_present("grp")); + assert_eq!(&*m.values_of("grp").unwrap().collect::>(), &["blue", "red", "green"]); +} + +#[test] +fn empty_group() { + let r = App::new("empty_group") + .arg(Arg::from_usage("-f, --flag 'some flag'")) + .group(ArgGroup::with_name("vers") + .required(true)) + .get_matches_from_safe(vec!["empty_prog"]); + assert!(r.is_err()); + let err = r.err().unwrap(); + assert_eq!(err.kind, ErrorKind::MissingRequiredArgument); +} + +#[test] +fn req_group_usage_string() { + let app = App::new("req_group") + .args_from_usage("[base] 'Base commit' + -d, --delete 'Remove the base commit information'") + .group(ArgGroup::with_name("base_or_delete") + .args(&["base", "delete"]) + .required(true)); + + assert!(test::compare_output(app, "clap-test", REQ_GROUP_USAGE, true)); +} + +#[test] +fn req_group_with_conflict_usage_string() { + let app = App::new("req_group") + .arg(Arg::from_usage("[base] 'Base commit'").conflicts_with("delete")) + .arg(Arg::from_usage("-d, --delete 'Remove the base commit information'")) + .group(ArgGroup::with_name("base_or_delete") + .args(&["base", "delete"]) + .required(true)); + + assert!(test::compare_output2(app, "clap-test --delete base", REQ_GROUP_CONFLICT_REV, REQ_GROUP_CONFLICT_USAGE, true)); +} + +#[test] +fn required_group_multiple_args() { + let result = App::new("group") + .args_from_usage("-f, --flag 'some flag' + -c, --color 'some other flag'") + .group(ArgGroup::with_name("req") + .args(&["flag", "color"]) + .required(true) + .multiple(true)) + .get_matches_from_safe(vec!["group", "-f", "-c"]); + assert!(result.is_ok()); + let m = result.unwrap(); + assert!(m.is_present("flag")); + assert!(m.is_present("color")); +} + +#[test] +fn group_multiple_args_error() { + let result = App::new("group") + .args_from_usage("-f, --flag 'some flag' + -c, --color 'some other flag'") + .group(ArgGroup::with_name("req") + .args(&["flag", "color"])) + .get_matches_from_safe(vec!["group", "-f", "-c"]); + assert!(result.is_err()); + let err = result.unwrap_err(); + assert_eq!(err.kind, ErrorKind::ArgumentConflict); +} diff --git a/clap/tests/help.rs b/clap/tests/help.rs new file mode 100644 index 0000000..4b15281 --- /dev/null +++ b/clap/tests/help.rs @@ -0,0 +1,1205 @@ +#[macro_use] +extern crate clap; +extern crate regex; + +include!("../clap-test.rs"); + +use clap::{App, AppSettings, SubCommand, ErrorKind, Arg}; + +static REQUIRE_DELIM_HELP: &'static str = "test 1.3 +Kevin K. +tests stuff + +USAGE: + test --fake : + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -f, --fake : some help"; + +static HELP: &'static str = "clap-test v1.4.8 +Kevin K. +tests clap library + +USAGE: + clap-test [FLAGS] [OPTIONS] [ARGS] [SUBCOMMAND] + +FLAGS: + -f, --flag tests flags + -F tests flags with exclusions + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -O, --Option specific vals [possible values: fast, slow] + --long-option-2 tests long options with exclusions + --maxvals3 ... Tests 3 max vals + --minvals2 ... Tests 2 min vals + --multvals Tests multiple values, not mult occs + --multvalsmo Tests multiple values, and mult occs + -o, --option ... tests options + +ARGS: + tests positionals + tests positionals with exclusions + ... tests specific values [possible values: vi, emacs] + +SUBCOMMANDS: + help Prints this message or the help of the given subcommand(s) + subcmd tests subcommands"; + +static SC_NEGATES_REQS: &'static str = "prog 1.0 + +USAGE: + prog --opt [PATH] + prog [PATH] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -o, --opt tests options + +ARGS: + help + +SUBCOMMANDS: + help Prints this message or the help of the given subcommand(s) + test"; + +static ARGS_NEGATE_SC: &'static str = "prog 1.0 + +USAGE: + prog [FLAGS] [OPTIONS] [PATH] + prog + +FLAGS: + -f, --flag testing flags + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -o, --opt tests options + +ARGS: + help + +SUBCOMMANDS: + help Prints this message or the help of the given subcommand(s) + test"; + +static AFTER_HELP: &'static str = "some text that comes before the help + +clap-test v1.4.8 +tests clap library + +USAGE: + clap-test + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +some text that comes after the help"; + +static HIDDEN_ARGS: &'static str = "prog 1.0 + +USAGE: + prog [FLAGS] [OPTIONS] + +FLAGS: + -f, --flag testing flags + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -o, --opt tests options"; + +static SC_HELP: &'static str = "clap-test-subcmd 0.1 +Kevin K. +tests subcommands + +USAGE: + clap-test subcmd [FLAGS] [OPTIONS] [--] [scpositional] + +FLAGS: + -f, --flag tests flags + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -o, --option ... tests options + -s, --subcmdarg tests other args + +ARGS: + tests positionals"; + +static ISSUE_1046_HIDDEN_SCS: &'static str = "prog 1.0 + +USAGE: + prog [FLAGS] [OPTIONS] [PATH] + +FLAGS: + -f, --flag testing flags + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -o, --opt tests options + +ARGS: + some"; + +// Using number_of_values(1) with multiple(true) misaligns help message +static ISSUE_760: &'static str = "ctest 0.1 + +USAGE: + ctest [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -O, --opt tests options + -o, --option