aboutsummaryrefslogtreecommitdiff
path: root/clap/tests
diff options
context:
space:
mode:
Diffstat (limited to 'clap/tests')
-rw-r--r--clap/tests/app.yml121
-rw-r--r--clap/tests/app_settings.rs965
-rw-r--r--clap/tests/arg_aliases.rs200
-rw-r--r--clap/tests/borrowed.rs19
-rw-r--r--clap/tests/completions.rs883
-rw-r--r--clap/tests/conflicts.rs102
-rw-r--r--clap/tests/default_vals.rs498
-rw-r--r--clap/tests/delimiters.rs139
-rw-r--r--clap/tests/derive_order.rs245
-rw-r--r--clap/tests/env.rs263
-rw-r--r--clap/tests/example1_tmpl_full.txt15
-rw-r--r--clap/tests/example1_tmpl_simple.txt8
-rw-r--r--clap/tests/flags.rs147
-rw-r--r--clap/tests/global_args.rs37
-rw-r--r--clap/tests/groups.rs207
-rw-r--r--clap/tests/help.rs1205
-rw-r--r--clap/tests/hidden_args.rs178
-rw-r--r--clap/tests/indices.rs175
-rwxr-xr-xclap/tests/macros.rs391
-rw-r--r--clap/tests/multiple_occurrences.rs75
-rw-r--r--clap/tests/multiple_values.rs1122
-rw-r--r--clap/tests/opts.rs461
-rw-r--r--clap/tests/positionals.rs274
-rw-r--r--clap/tests/posix_compatible.rs292
-rw-r--r--clap/tests/possible_values.rs266
-rw-r--r--clap/tests/propagate_globals.rs148
-rw-r--r--clap/tests/require.rs688
-rw-r--r--clap/tests/subcommands.rs216
-rw-r--r--clap/tests/template_help.rs117
-rw-r--r--clap/tests/tests.rs435
-rw-r--r--clap/tests/unique_args.rs22
-rw-r--r--clap/tests/utf8.rs223
-rw-r--r--clap/tests/version-numbers.rs12
-rw-r--r--clap/tests/version.rs58
-rw-r--r--clap/tests/yaml.rs40
35 files changed, 10247 insertions, 0 deletions
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. <kbknapp@gmail.com>
+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. <kbknapp@gmail.com>
+ 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:
+ <arg1> some
+ <arg2> some
+ <arg3> some";
+
+static REQUIRE_EQUALS: &'static str = "clap-test v1.4.8
+
+USAGE:
+ clap-test --opt=<FILE>
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -o, --opt=<FILE> 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 <opt> some option
+ -V, --version Prints version information
+
+ARGS:
+ <arg1> 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 <opt> some option
+
+ARGS:
+ <arg1> 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::<Vec<_>>(), &["-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::<Vec<_>>(), &["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::<Vec<_>>(), &["-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::<Vec<_>>(), &["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::<Vec<_>>(), &["-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::<Vec<_>>(), &["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::<Vec<_>>(), &["--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("<arg1> 'some arg'")
+ .arg_from_usage("<arg2> '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("<arg1> 'some arg'")
+ .arg_from_usage("<arg2> 'some arg'")
+ .subcommand(SubCommand::with_name("sub1")
+ .arg_from_usage("<arg> 'some'")
+ .arg_from_usage("<arg2> '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("<dest> '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("<dest> '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::<Vec<_>>(), &*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::<Vec<_>>(), &*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::<Vec<_>>(), &*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("<BENCH2> '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::<Vec<_>>(), &["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::<Vec<_>>(), &["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::<Vec<_>>(), &["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::<Vec<_>>(), &["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 <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 <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 <file> 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 <file> 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 <positional> <positional2> --flag --long-option-2 <option2>
+
+For more information try --help";
+
+static CONFLICT_ERR_REV: &'static str = "error: The argument '--flag' cannot be used with '-F'
+
+USAGE:
+ clap-test <positional> <positional2> -F --long-option-2 <option2>
+
+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::<Vec<_>>(), &["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 <option_a> second option
+ --option_b <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 <option_b> first option
+ --option_a <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 <option_a> second option
+ --option_b <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 <option_b> first option
+ --flag_a second flag
+ --option_a <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 <option_b> first option
+ --option_a <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 <option_a> second option
+ --option_b <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 <option_b> first option
+ --flag_a second flag
+ --option_a <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 <option_b> first option
+ --option_a <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<_>>(), 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<_>>(),
+ 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<_>>(),
+ 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:
+ <base|--delete>
+
+USAGE:
+ clap-test <base|--delete>
+
+For more information try --help";
+
+static REQ_GROUP_CONFLICT_USAGE: &'static str = "error: The argument '<base>' cannot be used with '--delete'
+
+USAGE:
+ clap-test <base|--delete>
+
+For more information try --help";
+
+static REQ_GROUP_CONFLICT_REV: &'static str = "error: The argument '--delete' cannot be used with 'base'
+
+USAGE:
+ clap-test <base|--delete>
+
+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::<Vec<_>>(), &["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 <some>:<val>
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -f, --fake <some>:<val> some help";
+
+static HELP: &'static str = "clap-test v1.4.8
+Kevin K. <kbknapp@gmail.com>
+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 <option3> specific vals [possible values: fast, slow]
+ --long-option-2 <option2> tests long options with exclusions
+ --maxvals3 <maxvals>... Tests 3 max vals
+ --minvals2 <minvals>... Tests 2 min vals
+ --multvals <one> <two> Tests multiple values, not mult occs
+ --multvalsmo <one> <two> Tests multiple values, and mult occs
+ -o, --option <opt>... tests options
+
+ARGS:
+ <positional> tests positionals
+ <positional2> tests positionals with exclusions
+ <positional3>... 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 <FILE> [PATH]
+ prog [PATH] <SUBCOMMAND>
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -o, --opt <FILE> tests options
+
+ARGS:
+ <PATH> 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 <SUBCOMMAND>
+
+FLAGS:
+ -f, --flag testing flags
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -o, --opt <FILE> tests options
+
+ARGS:
+ <PATH> 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 <FILE> tests options";
+
+static SC_HELP: &'static str = "clap-test-subcmd 0.1
+Kevin K. <kbknapp@gmail.com>
+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 <scoption>... tests options
+ -s, --subcmdarg <subcmdarg> tests other args
+
+ARGS:
+ <scpositional> 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 <FILE> tests options
+
+ARGS:
+ <PATH> 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 <opt> tests options
+ -o, --option <option>... tests options";
+
+static RIPGREP_USAGE: &'static str = "ripgrep 0.5
+
+USAGE:
+ rg [OPTIONS] <pattern> [<path> ...]
+ rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
+ rg [OPTIONS] --files [<path> ...]
+ rg [OPTIONS] --type-list
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information";
+
+
+static MULTI_SC_HELP: &'static str = "ctest-subcmd-multi 0.1
+Kevin K. <kbknapp@gmail.com>
+tests subcommands
+
+USAGE:
+ ctest subcmd multi [FLAGS] [OPTIONS]
+
+FLAGS:
+ -f, --flag tests flags
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -o, --option <scoption>... tests options";
+
+static ISSUE_626_CUTOFF: &'static str = "ctest 0.1
+
+USAGE:
+ ctest [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -c, --cafe <FILE> A coffeehouse, coffee shop, or café is an
+ establishment which primarily serves hot
+ coffee, related coffee beverages (e.g., café
+ latte, cappuccino, espresso), tea, and other
+ hot beverages. Some coffeehouses also serve
+ cold beverages such as iced coffee and iced
+ tea. Many cafés also serve some type of food,
+ such as light snacks, muffins, or pastries.";
+
+static ISSUE_626_PANIC: &'static str = "ctest 0.1
+
+USAGE:
+ ctest [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -c, --cafe <FILE>
+ La culture du café est très développée
+ dans de nombreux pays à climat chaud
+ d\'Amérique, d\'Afrique et d\'Asie, dans
+ des plantations qui sont cultivées pour
+ les marchés d\'exportation. Le café est
+ souvent une contribution majeure aux
+ exportations des régions productrices.";
+
+static HIDE_POS_VALS: &'static str = "ctest 0.1
+
+USAGE:
+ ctest [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -c, --cafe <FILE> A coffeehouse, coffee shop, or café.
+ -p, --pos <VAL> Some vals [possible values: fast, slow]";
+
+static FINAL_WORD_WRAPPING: &'static str = "ctest 0.1
+
+USAGE:
+ ctest
+
+FLAGS:
+ -h, --help
+ Prints help
+ information
+ -V, --version
+ Prints
+ version
+ information";
+
+static OLD_NEWLINE_CHARS: &'static str = "ctest 0.1
+
+USAGE:
+ ctest [FLAGS]
+
+FLAGS:
+ -h, --help Prints help information
+ -m Some help with some wrapping
+ (Defaults to something)
+ -V, --version Prints version information";
+
+static WRAPPING_NEWLINE_CHARS: &'static str = "ctest 0.1
+
+USAGE:
+ ctest [mode]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+ARGS:
+ <mode> x, max, maximum 20 characters, contains
+ symbols.
+ l, long Copy-friendly, 14
+ characters, contains symbols.
+ m, med, medium Copy-friendly, 8
+ characters, contains symbols.";
+
+static ISSUE_688: &'static str = "ctest 0.1
+
+USAGE:
+ ctest [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ --filter <filter> Sets the filter, or sampling method, to use for interpolation when resizing the particle
+ images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic,
+ Gaussian, Lanczos3]";
+
+static ISSUE_702: &'static str = "myapp 1.0
+foo
+bar
+
+USAGE:
+ myapp [OPTIONS] [--] [ARGS]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -l, --label <label>... a label
+ -o, --other <other> some other option
+ -s, --some <some> some option
+
+ARGS:
+ <arg1> some option
+ <arg2>... some option";
+
+static ISSUE_777: &'static str = "A app with a crazy very long long
+long name hahaha 1.0
+Some Very Long Name and crazy long
+email <email@server.com>
+Show how the about text is not
+wrapped
+
+USAGE:
+ ctest
+
+FLAGS:
+ -h, --help
+ Prints help information
+
+ -V, --version
+ Prints version
+ information";
+
+static CUSTOM_VERSION_AND_HELP: &'static str = "customize 0.1
+Nobody <odysseus@example.com>
+You can customize the version and help text
+
+USAGE:
+ customize
+
+FLAGS:
+ -H, --help Print help information
+ -v, --version Print version information";
+
+static LAST_ARG: &'static str = "last 0.1
+
+USAGE:
+ last <TARGET> [CORPUS] [-- <ARGS>...]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+ARGS:
+ <TARGET> some
+ <CORPUS> some
+ <ARGS>... some";
+
+static LAST_ARG_SC: &'static str = "last 0.1
+
+USAGE:
+ last <TARGET> [CORPUS] [-- <ARGS>...]
+ last <SUBCOMMAND>
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+ARGS:
+ <TARGET> some
+ <CORPUS> some
+ <ARGS>... some
+
+SUBCOMMANDS:
+ help Prints this message or the help of the given subcommand(s)
+ test some";
+
+static LAST_ARG_REQ: &'static str = "last 0.1
+
+USAGE:
+ last <TARGET> [CORPUS] -- <ARGS>...
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+ARGS:
+ <TARGET> some
+ <CORPUS> some
+ <ARGS>... some";
+
+static LAST_ARG_REQ_SC: &'static str = "last 0.1
+
+USAGE:
+ last <TARGET> [CORPUS] -- <ARGS>...
+ last <SUBCOMMAND>
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+ARGS:
+ <TARGET> some
+ <CORPUS> some
+ <ARGS>... some
+
+SUBCOMMANDS:
+ help Prints this message or the help of the given subcommand(s)
+ test some";
+
+static HIDE_DEFAULT_VAL: &'static str = "default 0.1
+
+USAGE:
+ default [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ --arg <argument> Pass an argument to the program. [default: default-argument]";
+
+static LAST_ARG_USAGE: &'static str = "flamegraph 0.1
+
+USAGE:
+ flamegraph [FLAGS] [OPTIONS] [BINFILE] [-- <ARGS>...]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+ -v, --verbose Prints out more stuff.
+
+OPTIONS:
+ -f, --frequency <HERTZ> The sampling frequency.
+ -t, --timeout <SECONDS> Timeout in seconds.
+
+ARGS:
+ <BINFILE> The path of the binary to be profiled. for a binary.
+ <ARGS>... Any arguments you wish to pass to the being profiled.";
+
+static LAST_ARG_REQ_MULT: &'static str = "example 1.0
+
+USAGE:
+ example <FIRST>... [--] <SECOND>...
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+ARGS:
+ <FIRST>... First
+ <SECOND>... Second";
+
+static DEFAULT_HELP: &'static str = "ctest 1.0
+
+USAGE:
+ ctest
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information";
+
+static LONG_ABOUT: &'static str = "myapp 1.0
+foo
+something really really long, with
+multiple lines of text
+that should be displayed
+
+USAGE:
+ myapp [arg1]
+
+FLAGS:
+ -h, --help
+ Prints help information
+
+ -V, --version
+ Prints version information
+
+
+ARGS:
+ <arg1>
+ some option";
+
+static HIDE_ENV_VALS: &'static str = "ctest 0.1
+
+USAGE:
+ ctest [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -c, --cafe <FILE> A coffeehouse, coffee shop, or café. [env: ENVVAR]
+ -p, --pos <VAL> Some vals [possible values: fast, slow]";
+
+static SHOW_ENV_VALS: &'static str = "ctest 0.1
+
+USAGE:
+ ctest [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -c, --cafe <FILE> A coffeehouse, coffee shop, or café. [env: ENVVAR=MYVAL]
+ -p, --pos <VAL> Some vals [possible values: fast, slow]";
+
+fn setup() -> App<'static, 'static> {
+ App::new("test")
+ .author("Kevin K.")
+ .about("tests stuff")
+ .version("1.3")
+}
+
+#[test]
+fn help_short() {
+ let m = setup()
+ .get_matches_from_safe(vec!["myprog", "-h"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
+}
+
+#[test]
+fn help_long() {
+ let m = setup()
+ .get_matches_from_safe(vec!["myprog", "--help"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
+}
+
+#[test]
+fn help_no_subcommand() {
+ let m = setup()
+ .get_matches_from_safe(vec!["myprog", "help"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::UnknownArgument);
+}
+
+#[test]
+fn help_subcommand() {
+ let m = setup()
+ .subcommand(SubCommand::with_name("test")
+ .about("tests things")
+ .arg_from_usage("-v --verbose 'with verbosity'"))
+ .get_matches_from_safe(vec!["myprog", "help"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
+}
+
+#[test]
+fn req_last_arg_usage() {
+ let app = clap_app!(example =>
+ (version: "1.0")
+ (@arg FIRST: ... * "First")
+ (@arg SECOND: ... * +last "Second")
+ );
+ assert!(test::compare_output(app, "example --help", LAST_ARG_REQ_MULT, false));
+}
+
+#[test]
+fn args_with_last_usage() {
+ let app = App::new("flamegraph")
+ .version("0.1")
+ .setting(AppSettings::TrailingVarArg)
+ .arg(Arg::with_name("verbose")
+ .help("Prints out more stuff.")
+ .short("v")
+ .long("verbose")
+ .multiple(true)
+ )
+ .arg(Arg::with_name("timeout")
+ .help("Timeout in seconds.")
+ .short("t")
+ .long("timeout")
+ .value_name("SECONDS")
+ .takes_value(true)
+ )
+ .arg(Arg::with_name("frequency")
+ .help("The sampling frequency.")
+ .short("f")
+ .long("frequency")
+ .value_name("HERTZ")
+ .takes_value(true)
+ )
+ .arg(Arg::with_name("binary path")
+ .help("The path of the binary to be profiled. for a binary.")
+ .takes_value(true)
+ .value_name("BINFILE")
+ )
+ .arg(Arg::with_name("pass through args")
+ .help("Any arguments you wish to pass to the being profiled.")
+ .value_name("ARGS")
+ .last(true)
+ .multiple(true)
+ );
+ assert!(test::compare_output(app, "flamegraph --help", LAST_ARG_USAGE, false));
+}
+
+#[test]
+fn subcommand_short_help() {
+ let m = test::complex_app().get_matches_from_safe(vec!["clap-test", "subcmd", "-h"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
+}
+
+#[test]
+fn subcommand_long_help() {
+ let m = test::complex_app().get_matches_from_safe(vec!["clap-test", "subcmd", "--help"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
+}
+
+#[test]
+fn subcommand_help_rev() {
+ let m = test::complex_app().get_matches_from_safe(vec!["clap-test", "help", "subcmd"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
+}
+
+#[test]
+fn complex_help_output() {
+ assert!(test::compare_output(test::complex_app(), "clap-test --help", HELP, false));
+}
+
+#[test]
+fn after_and_before_help_output() {
+ let app = App::new("clap-test")
+ .version("v1.4.8")
+ .about("tests clap library")
+ .before_help("some text that comes before the help")
+ .after_help("some text that comes after the help");
+ assert!(test::compare_output(app, "clap-test --help", AFTER_HELP, false));
+}
+
+#[test]
+fn multi_level_sc_help() {
+ let app = App::new("ctest")
+ .subcommand(SubCommand::with_name("subcmd").subcommand(SubCommand::with_name("multi")
+ .about("tests subcommands")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .version("0.1")
+ .args_from_usage("
+ -f, --flag 'tests flags'
+ -o, --option [scoption]... 'tests options'
+ ")));
+ assert!(test::compare_output(app, "ctest help subcmd multi", MULTI_SC_HELP, false));
+}
+
+#[test]
+fn no_wrap_help() {
+ let app = App::new("ctest")
+ .set_term_width(0)
+ .help(MULTI_SC_HELP);
+ assert!(test::compare_output(app, "ctest --help", MULTI_SC_HELP, false));
+}
+
+#[test]
+fn no_wrap_default_help() {
+ let app = App::new("ctest").version("1.0").set_term_width(0);
+ assert!(test::compare_output(app, "ctest --help", DEFAULT_HELP, false));
+}
+
+#[test]
+fn complex_subcommand_help_output() {
+ let a = test::complex_app();
+ assert!(test::compare_output(a, "clap-test subcmd --help", SC_HELP, false));
+}
+
+
+#[test]
+fn issue_626_unicode_cutoff() {
+ let app = App::new("ctest")
+ .version("0.1")
+ .set_term_width(70)
+ .arg(Arg::with_name("cafe")
+ .short("c")
+ .long("cafe")
+ .value_name("FILE")
+ .help("A coffeehouse, coffee shop, or café is an establishment \
+ which primarily serves hot coffee, related coffee beverages \
+ (e.g., café latte, cappuccino, espresso), tea, and other hot \
+ beverages. Some coffeehouses also serve cold beverages such as \
+ iced coffee and iced tea. Many cafés also serve some type of \
+ food, such as light snacks, muffins, or pastries.")
+ .takes_value(true));
+ assert!(test::compare_output(app, "ctest --help", ISSUE_626_CUTOFF, false));
+}
+
+#[test]
+fn hide_possible_vals() {
+ let app = App::new("ctest")
+ .version("0.1")
+ .arg(Arg::with_name("pos")
+ .short("p")
+ .long("pos")
+ .value_name("VAL")
+ .possible_values(&["fast", "slow"])
+ .help("Some vals")
+ .takes_value(true))
+ .arg(Arg::with_name("cafe")
+ .short("c")
+ .long("cafe")
+ .value_name("FILE")
+ .hide_possible_values(true)
+ .possible_values(&["fast", "slow"])
+ .help("A coffeehouse, coffee shop, or café.")
+ .takes_value(true));
+ assert!(test::compare_output(app, "ctest --help", HIDE_POS_VALS, false));
+}
+
+#[test]
+fn issue_626_panic() {
+ let app = App::new("ctest")
+ .version("0.1")
+ .set_term_width(52)
+ .arg(Arg::with_name("cafe")
+ .short("c")
+ .long("cafe")
+ .value_name("FILE")
+ .help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
+ d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
+ Le café est souvent une contribution majeure aux exportations des régions productrices.")
+ .takes_value(true));
+ assert!(test::compare_output(app, "ctest --help", ISSUE_626_PANIC, false));
+}
+
+#[test]
+fn issue_626_variable_panic() {
+ for i in 10..320 {
+ let _ = App::new("ctest")
+ .version("0.1")
+ .set_term_width(i)
+ .arg(Arg::with_name("cafe")
+ .short("c")
+ .long("cafe")
+ .value_name("FILE")
+ .help("La culture du café est très développée dans de nombreux pays à climat chaud d'Amérique, \
+ d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \
+ Le café est souvent une contribution majeure aux exportations des régions productrices.")
+ .takes_value(true))
+ .get_matches_from_safe(vec!["ctest", "--help"]);
+ }
+}
+
+#[test]
+fn final_word_wrapping() {
+ let app = App::new("ctest").version("0.1").set_term_width(24);
+ assert!(test::compare_output(app, "ctest --help", FINAL_WORD_WRAPPING, false));
+}
+
+#[test]
+fn wrapping_newline_chars() {
+ let app = App::new("ctest")
+ .version("0.1")
+ .set_term_width(60)
+ .arg(Arg::with_name("mode")
+ .help("x, max, maximum 20 characters, contains symbols.{n}\
+ l, long Copy-friendly, 14 characters, contains symbols.{n}\
+ m, med, medium Copy-friendly, 8 characters, contains symbols.{n}"));
+ assert!(test::compare_output(app, "ctest --help", WRAPPING_NEWLINE_CHARS, false));
+}
+
+#[test]
+fn old_newline_chars() {
+ let app = App::new("ctest")
+ .version("0.1")
+ .arg(Arg::with_name("mode")
+ .short("m")
+ .help("Some help with some wrapping{n}(Defaults to something)"));
+ assert!(test::compare_output(app, "ctest --help", OLD_NEWLINE_CHARS, false));
+}
+
+#[test]
+fn issue_688_hidden_pos_vals() {
+ let filter_values = ["Nearest", "Linear", "Cubic", "Gaussian", "Lanczos3"];
+
+ let app1 = App::new("ctest")
+ .version("0.1")
+ .set_term_width(120)
+ .setting(AppSettings::HidePossibleValuesInHelp)
+ .arg(Arg::with_name("filter")
+ .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \
+ images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic, Gaussian, Lanczos3]")
+ .long("filter")
+ .possible_values(&filter_values)
+ .takes_value(true));
+ assert!(test::compare_output(app1, "ctest --help", ISSUE_688, false));
+
+ let app2 = App::new("ctest")
+ .version("0.1")
+ .set_term_width(120)
+ .arg(Arg::with_name("filter")
+ .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \
+ images. The default is Linear (Bilinear).")
+ .long("filter")
+ .possible_values(&filter_values)
+ .takes_value(true));
+ assert!(test::compare_output(app2, "ctest --help", ISSUE_688, false));
+
+ let app3 = App::new("ctest")
+ .version("0.1")
+ .set_term_width(120)
+ .arg(Arg::with_name("filter")
+ .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \
+ images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic, Gaussian, Lanczos3]")
+ .long("filter")
+ .takes_value(true));
+ assert!(test::compare_output(app3, "ctest --help", ISSUE_688, false));
+}
+
+#[test]
+fn issue_702_multiple_values() {
+ let app = App::new("myapp")
+ .version("1.0")
+ .author("foo")
+ .about("bar")
+ .arg(Arg::with_name("arg1").help("some option"))
+ .arg(Arg::with_name("arg2")
+ .multiple(true)
+ .help("some option"))
+ .arg(Arg::with_name("some")
+ .help("some option")
+ .short("s")
+ .long("some")
+ .takes_value(true))
+ .arg(Arg::with_name("other")
+ .help("some other option")
+ .short("o")
+ .long("other")
+ .takes_value(true))
+ .arg(Arg::with_name("label")
+ .help("a label")
+ .short("l")
+ .long("label")
+ .multiple(true)
+ .takes_value(true));
+ assert!(test::compare_output(app, "myapp --help", ISSUE_702, false));
+}
+
+#[test]
+fn long_about() {
+ let app = App::new("myapp")
+ .version("1.0")
+ .author("foo")
+ .about("bar")
+ .long_about("something really really long, with\nmultiple lines of text\nthat should be displayed")
+ .arg(Arg::with_name("arg1").help("some option"));
+ assert!(test::compare_output(app, "myapp --help", LONG_ABOUT, false));
+}
+
+#[test]
+fn issue_760() {
+ let app = App::new("ctest")
+ .version("0.1")
+ .arg(Arg::with_name("option")
+ .help("tests options")
+ .short("o")
+ .long("option")
+ .takes_value(true)
+ .multiple(true)
+ .number_of_values(1))
+ .arg(Arg::with_name("opt")
+ .help("tests options")
+ .short("O")
+ .long("opt")
+ .takes_value(true));
+ assert!(test::compare_output(app, "ctest --help", ISSUE_760, false));
+}
+
+#[test]
+fn ripgrep_usage() {
+ let app = App::new("ripgrep")
+ .version("0.5")
+ .usage("rg [OPTIONS] <pattern> [<path> ...]
+ rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
+ rg [OPTIONS] --files [<path> ...]
+ rg [OPTIONS] --type-list");
+
+ assert!(test::compare_output(app, "rg --help", RIPGREP_USAGE, false));
+}
+
+#[test]
+fn ripgrep_usage_using_templates() {
+ let app = App::new("ripgrep")
+ .version("0.5")
+ .usage("
+ rg [OPTIONS] <pattern> [<path> ...]
+ rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
+ rg [OPTIONS] --files [<path> ...]
+ rg [OPTIONS] --type-list")
+ .template("\
+{bin} {version}
+
+USAGE:{usage}
+
+FLAGS:
+{flags}");
+
+ assert!(test::compare_output(app, "rg --help", RIPGREP_USAGE, false));
+}
+
+#[test]
+fn sc_negates_reqs() {
+ let app = App::new("prog")
+ .version("1.0")
+ .setting(AppSettings::SubcommandsNegateReqs)
+ .arg_from_usage("-o, --opt <FILE> 'tests options'")
+ .arg(Arg::with_name("PATH").help("help"))
+ .subcommand(SubCommand::with_name("test"));
+ assert!(test::compare_output(app, "prog --help", SC_NEGATES_REQS, false));
+}
+
+#[test]
+fn hidden_args() {
+ let app = App::new("prog")
+ .version("1.0")
+ .args_from_usage("-f, --flag 'testing flags'
+ -o, --opt [FILE] 'tests options'")
+ .arg(Arg::with_name("pos").hidden(true));
+ assert!(test::compare_output(app, "prog --help", HIDDEN_ARGS, false));
+}
+
+#[test]
+fn args_negate_sc() {
+ let app = App::new("prog")
+ .version("1.0")
+ .setting(AppSettings::ArgsNegateSubcommands)
+ .args_from_usage("-f, --flag 'testing flags'
+ -o, --opt [FILE] 'tests options'")
+ .arg(Arg::with_name("PATH").help("help"))
+ .subcommand(SubCommand::with_name("test"));
+ assert!(test::compare_output(app, "prog --help", ARGS_NEGATE_SC, false));
+}
+
+#[test]
+fn issue_1046_hidden_scs() {
+ let app = App::new("prog")
+ .version("1.0")
+ .args_from_usage("-f, --flag 'testing flags'
+ -o, --opt [FILE] 'tests options'")
+ .arg(Arg::with_name("PATH").help("some"))
+ .subcommand(SubCommand::with_name("test").setting(AppSettings::Hidden));
+ assert!(test::compare_output(app, "prog --help", ISSUE_1046_HIDDEN_SCS, false));
+}
+
+#[test]
+fn issue_777_wrap_all_things() {
+ let app = App::new("A app with a crazy very long long long name hahaha")
+ .version("1.0")
+ .author("Some Very Long Name and crazy long email <email@server.com>")
+ .about("Show how the about text is not wrapped")
+ .set_term_width(35);
+ assert!(test::compare_output(app, "ctest --help", ISSUE_777, false));
+}
+
+#[test]
+fn customize_version_and_help() {
+ let app = App::new("customize")
+ .version("0.1")
+ .author("Nobody <odysseus@example.com>")
+ .about("You can customize the version and help text")
+ .help_short("H")
+ .help_message("Print help information")
+ .version_short("v")
+ .version_message("Print version information");
+ assert!(test::compare_output(app, "customize --help", CUSTOM_VERSION_AND_HELP, false));
+}
+
+#[test]
+fn last_arg_mult_usage() {
+ let app = App::new("last")
+ .version("0.1")
+ .arg(Arg::with_name("TARGET").required(true).help("some"))
+ .arg(Arg::with_name("CORPUS").help("some"))
+ .arg(Arg::with_name("ARGS").multiple(true).last(true).help("some"));
+ assert!(test::compare_output(app, "last --help", LAST_ARG, false));
+}
+
+#[test]
+fn last_arg_mult_usage_req() {
+ let app = App::new("last")
+ .version("0.1")
+ .arg(Arg::with_name("TARGET").required(true).help("some"))
+ .arg(Arg::with_name("CORPUS").help("some"))
+ .arg(Arg::with_name("ARGS").multiple(true).last(true).required(true).help("some"));
+ assert!(test::compare_output(app, "last --help", LAST_ARG_REQ, false));
+}
+
+#[test]
+fn last_arg_mult_usage_req_with_sc() {
+ let app = App::new("last")
+ .version("0.1")
+ .setting(AppSettings::SubcommandsNegateReqs)
+ .arg(Arg::with_name("TARGET").required(true).help("some"))
+ .arg(Arg::with_name("CORPUS").help("some"))
+ .arg(Arg::with_name("ARGS").multiple(true).last(true).required(true).help("some"))
+ .subcommand(SubCommand::with_name("test").about("some"));
+ assert!(test::compare_output(app, "last --help", LAST_ARG_REQ_SC, false));
+}
+
+#[test]
+fn last_arg_mult_usage_with_sc() {
+ let app = App::new("last")
+ .version("0.1")
+ .setting(AppSettings::ArgsNegateSubcommands)
+ .arg(Arg::with_name("TARGET").required(true).help("some"))
+ .arg(Arg::with_name("CORPUS").help("some"))
+ .arg(Arg::with_name("ARGS").multiple(true).last(true).help("some"))
+ .subcommand(SubCommand::with_name("test").about("some"));
+ assert!(test::compare_output(app, "last --help", LAST_ARG_SC, false));
+}
+
+
+#[test]
+fn hidden_default_val() {
+ let app1 = App::new("default")
+ .version("0.1")
+ .set_term_width(120)
+ .arg(Arg::with_name("argument")
+ .help("Pass an argument to the program. [default: default-argument]")
+ .long("arg")
+ .default_value("default-argument")
+ .hide_default_value(true));
+ assert!(test::compare_output(app1, "default --help", HIDE_DEFAULT_VAL, false));
+
+ let app2 = App::new("default")
+ .version("0.1")
+ .set_term_width(120)
+ .arg(Arg::with_name("argument")
+ .help("Pass an argument to the program.")
+ .long("arg")
+ .default_value("default-argument"));
+ assert!(test::compare_output(app2, "default --help", HIDE_DEFAULT_VAL, false));
+}
+
+fn issue_1112_setup() -> App<'static, 'static> {
+ App::new("test")
+ .author("Kevin K.")
+ .about("tests stuff")
+ .version("1.3")
+ .arg(Arg::from_usage("-h, --help 'some help'"))
+ .subcommand(SubCommand::with_name("foo")
+ .arg(Arg::from_usage("-h, --help 'some help'")))
+}
+
+#[test]
+fn issue_1112_override_help_long() {
+ let m = issue_1112_setup()
+ .get_matches_from_safe(vec!["test", "--help"]);
+
+ assert!(m.is_ok());
+ assert!(m.unwrap().is_present("help"));
+}
+
+#[test]
+fn issue_1112_override_help_short() {
+ let m = issue_1112_setup()
+ .get_matches_from_safe(vec!["test", "-h"]);
+
+ assert!(m.is_ok());
+ assert!(m.unwrap().is_present("help"));
+}
+
+#[test]
+fn issue_1112_override_help_subcmd_long() {
+ let m = issue_1112_setup()
+ .get_matches_from_safe(vec!["test", "foo", "--help"]);
+
+ assert!(m.is_ok());
+ assert!(m.unwrap().subcommand_matches("foo").unwrap().is_present("help"));
+}
+
+#[test]
+fn issue_1112_override_help_subcmd_short() {
+ let m = issue_1112_setup()
+ .get_matches_from_safe(vec!["test", "foo", "-h"]);
+
+ assert!(m.is_ok());
+ assert!(m.unwrap().subcommand_matches("foo").unwrap().is_present("help"));
+}
+
+#[test]
+fn issue_1052_require_delim_help() {
+ let app = App::new("test")
+ .author("Kevin K.")
+ .about("tests stuff")
+ .version("1.3")
+ .arg(Arg::from_usage("-f, --fake <some> <val> 'some help'").require_delimiter(true).value_delimiter(":"));
+
+ assert!(test::compare_output(app, "test --help", REQUIRE_DELIM_HELP, false));
+}
+
+#[test]
+fn hide_env_vals() {
+ use std::env;
+
+ env::set_var("ENVVAR", "MYVAL");
+ let app = App::new("ctest")
+ .version("0.1")
+ .arg(Arg::with_name("pos")
+ .short("p")
+ .long("pos")
+ .value_name("VAL")
+ .possible_values(&["fast", "slow"])
+ .help("Some vals")
+ .takes_value(true))
+ .arg(Arg::with_name("cafe")
+ .short("c")
+ .long("cafe")
+ .value_name("FILE")
+ .hide_env_values(true)
+ .env("ENVVAR")
+ .help("A coffeehouse, coffee shop, or café.")
+ .takes_value(true));
+ assert!(test::compare_output(app, "ctest --help", HIDE_ENV_VALS, false));
+}
+
+#[test]
+fn show_env_vals() {
+ use std::env;
+
+ env::set_var("ENVVAR", "MYVAL");
+ let app = App::new("ctest")
+ .version("0.1")
+ .arg(Arg::with_name("pos")
+ .short("p")
+ .long("pos")
+ .value_name("VAL")
+ .possible_values(&["fast", "slow"])
+ .help("Some vals")
+ .takes_value(true))
+ .arg(Arg::with_name("cafe")
+ .short("c")
+ .long("cafe")
+ .value_name("FILE")
+ .hide_possible_values(true)
+ .env("ENVVAR")
+ .help("A coffeehouse, coffee shop, or café.")
+ .takes_value(true));
+ assert!(test::compare_output(app, "ctest --help", SHOW_ENV_VALS, false));
+}
+
+static ISSUE_897: &'static str = "ctest-foo 0.1
+Long about foo
+
+USAGE:
+ ctest foo
+
+FLAGS:
+ -h, --help
+ Prints help information
+
+ -V, --version
+ Prints version information";
+
+#[test]
+fn show_long_about_issue_897() {
+ let app = App::new("ctest")
+ .version("0.1")
+ .subcommand(SubCommand::with_name("foo")
+ .version("0.1")
+ .about("About foo")
+ .long_about("Long about foo"));
+ assert!(test::compare_output(app, "ctest foo --help", ISSUE_897, false));
+}
+
+static ISSUE_897_SHORT: &'static str = "ctest-foo 0.1
+Long about foo
+
+USAGE:
+ ctest foo
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information";
+
+#[test]
+fn show_short_about_issue_897() {
+ let app = App::new("ctest")
+ .version("0.1")
+ .subcommand(SubCommand::with_name("foo")
+ .version("0.1")
+ .about("About foo")
+ .long_about("Long about foo"));
+ assert!(test::compare_output(app, "ctest foo -h", ISSUE_897_SHORT, false));
+}
diff --git a/clap/tests/hidden_args.rs b/clap/tests/hidden_args.rs
new file mode 100644
index 0000000..635e25e
--- /dev/null
+++ b/clap/tests/hidden_args.rs
@@ -0,0 +1,178 @@
+extern crate clap;
+extern crate regex;
+
+use clap::{App, Arg};
+
+include!("../clap-test.rs");
+
+static HIDDEN_ARGS: &'static str = "test 1.4
+Kevin K.
+tests stuff
+
+USAGE:
+ test [FLAGS] [OPTIONS]
+
+FLAGS:
+ -F, --flag2 some other flag
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ --option <opt> some option";
+
+#[test]
+fn hidden_args() {
+ let app = App::new("test")
+ .author("Kevin K.")
+ .about("tests stuff")
+ .version("1.4")
+ .args(&[Arg::from_usage("-f, --flag 'some flag'").hidden(true),
+ Arg::from_usage("-F, --flag2 'some other flag'"),
+ Arg::from_usage("--option [opt] 'some option'"),
+ Arg::with_name("DUMMY").required(false).hidden(true)]);
+ assert!(test::compare_output(app, "test --help", HIDDEN_ARGS, false));
+}
+
+static HIDDEN_SHORT_ARGS: &'static str = "test 2.31.2
+Steve P.
+hides short args
+
+USAGE:
+ test [FLAGS]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+ -v, --visible This text should be visible";
+
+static HIDDEN_SHORT_ARGS_LONG_HELP: &'static str = "test 2.31.2
+Steve P.
+hides short args
+
+USAGE:
+ test [FLAGS]
+
+FLAGS:
+ -c, --config
+ Some help text describing the --config arg
+
+ -h, --help
+ Prints help information
+
+ -V, --version
+ Prints version information
+
+ -v, --visible
+ This text should be visible";
+
+/// Ensure hidden with short option
+#[test]
+fn hidden_short_args() {
+ let app = App::new("test")
+ .about("hides short args")
+ .author("Steve P.")
+ .version("2.31.2")
+ .args(&[
+ Arg::with_name("cfg")
+ .short("c")
+ .long("config")
+ .hidden_short_help(true)
+ .help("Some help text describing the --config arg"),
+ Arg::with_name("visible")
+ .short("v")
+ .long("visible")
+ .help("This text should be visible")]);
+
+ assert!(test::compare_output(app, "test -h", HIDDEN_SHORT_ARGS, false));
+}
+
+/// Ensure visible with opposite option
+#[test]
+fn hidden_short_args_long_help() {
+ let app = App::new("test")
+ .about("hides short args")
+ .author("Steve P.")
+ .version("2.31.2")
+ .args(&[
+ Arg::with_name("cfg")
+ .short("c")
+ .long("config")
+ .hidden_short_help(true)
+ .help("Some help text describing the --config arg"),
+ Arg::with_name("visible")
+ .short("v")
+ .long("visible")
+ .help("This text should be visible")]);
+
+ assert!(test::compare_output(app, "test --help", HIDDEN_SHORT_ARGS_LONG_HELP, false));
+}
+
+static HIDDEN_LONG_ARGS: &'static str = "test 2.31.2
+Steve P.
+hides long args
+
+USAGE:
+ test [FLAGS]
+
+FLAGS:
+ -h, --help
+ Prints help information
+
+ -V, --version
+ Prints version information
+
+ -v, --visible
+ This text should be visible";
+
+#[test]
+fn hidden_long_args() {
+ let app = App::new("test")
+ .about("hides long args")
+ .author("Steve P.")
+ .version("2.31.2")
+ .args(&[
+ Arg::with_name("cfg")
+ .short("c")
+ .long("config")
+ .hidden_long_help(true)
+ .help("Some help text describing the --config arg"),
+ Arg::with_name("visible")
+ .short("v")
+ .long("visible")
+ .help("This text should be visible")]);
+
+ assert!(test::compare_output(app, "test --help", HIDDEN_LONG_ARGS, false));
+}
+
+static HIDDEN_LONG_ARGS_SHORT_HELP: &'static str = "test 2.31.2
+Steve P.
+hides long args
+
+USAGE:
+ test [FLAGS]
+
+FLAGS:
+ -c, --config Some help text describing the --config arg
+ -h, --help Prints help information
+ -V, --version Prints version information
+ -v, --visible This text should be visible";
+
+#[test]
+fn hidden_long_args_short_help() {
+ let app = App::new("test")
+ .about("hides long args")
+ .author("Steve P.")
+ .version("2.31.2")
+ .args(&[
+ Arg::with_name("cfg")
+ .short("c")
+ .long("config")
+ .hidden_long_help(true)
+ .help("Some help text describing the --config arg"),
+ Arg::with_name("visible")
+ .short("v")
+ .long("visible")
+ .help("This text should be visible")]);
+
+ assert!(test::compare_output(app, "test -h", HIDDEN_LONG_ARGS_SHORT_HELP, false));
+}
diff --git a/clap/tests/indices.rs b/clap/tests/indices.rs
new file mode 100644
index 0000000..910529e
--- /dev/null
+++ b/clap/tests/indices.rs
@@ -0,0 +1,175 @@
+extern crate clap;
+extern crate regex;
+
+include!("../clap-test.rs");
+
+use clap::{App, Arg};
+
+#[test]
+fn indices_mult_opts() {
+ let m = App::new("ind")
+ .arg(Arg::with_name("exclude")
+ .short("e")
+ .takes_value(true)
+ .multiple(true))
+ .arg(Arg::with_name("include")
+ .short("i")
+ .takes_value(true)
+ .multiple(true))
+ .get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]);
+
+ assert_eq!(m.indices_of("exclude").unwrap().collect::<Vec<_>>(), &[2, 3, 8]);
+ assert_eq!(m.indices_of("include").unwrap().collect::<Vec<_>>(), &[5, 6]);
+}
+
+#[test]
+fn index_mult_opts() {
+ let m = App::new("ind")
+ .arg(Arg::with_name("exclude")
+ .short("e")
+ .takes_value(true)
+ .multiple(true))
+ .arg(Arg::with_name("include")
+ .short("i")
+ .takes_value(true)
+ .multiple(true))
+ .get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]);
+
+ assert_eq!(m.index_of("exclude"), Some(2));
+ assert_eq!(m.index_of("include"), Some(5));
+}
+
+#[test]
+fn index_flag() {
+ let m = App::new("ind")
+ .arg(Arg::with_name("exclude")
+ .short("e"))
+ .arg(Arg::with_name("include")
+ .short("i"))
+ .get_matches_from(vec!["ind", "-e", "-i"]);
+
+ assert_eq!(m.index_of("exclude"), Some(1));
+ assert_eq!(m.index_of("include"), Some(2));
+}
+
+#[test]
+fn index_flags() {
+ let m = App::new("ind")
+ .arg(Arg::with_name("exclude")
+ .short("e")
+ .multiple(true))
+ .arg(Arg::with_name("include")
+ .short("i")
+ .multiple(true))
+ .get_matches_from(vec!["ind", "-e", "-i", "-e", "-e", "-i"]);
+
+ assert_eq!(m.index_of("exclude"), Some(1));
+ assert_eq!(m.index_of("include"), Some(2));
+}
+
+#[test]
+fn indices_mult_flags() {
+ let m = App::new("ind")
+ .arg(Arg::with_name("exclude")
+ .short("e")
+ .multiple(true))
+ .arg(Arg::with_name("include")
+ .short("i")
+ .multiple(true))
+ .get_matches_from(vec!["ind", "-e", "-i", "-e", "-e", "-i"]);
+
+ assert_eq!(m.indices_of("exclude").unwrap().collect::<Vec<_>>(), &[1, 3, 4]);
+ assert_eq!(m.indices_of("include").unwrap().collect::<Vec<_>>(), &[2, 5]);
+}
+
+#[test]
+fn indices_mult_flags_combined() {
+ let m = App::new("ind")
+ .arg(Arg::with_name("exclude")
+ .short("e")
+ .multiple(true))
+ .arg(Arg::with_name("include")
+ .short("i")
+ .multiple(true))
+ .get_matches_from(vec!["ind", "-eieei"]);
+
+ assert_eq!(m.indices_of("exclude").unwrap().collect::<Vec<_>>(), &[1, 3, 4]);
+ assert_eq!(m.indices_of("include").unwrap().collect::<Vec<_>>(), &[2, 5]);
+}
+
+#[test]
+fn indices_mult_flags_opt_combined() {
+ let m = App::new("ind")
+ .arg(Arg::with_name("exclude")
+ .short("e")
+ .multiple(true))
+ .arg(Arg::with_name("include")
+ .short("i")
+ .multiple(true))
+ .arg(Arg::with_name("option")
+ .short("o")
+ .takes_value(true))
+ .get_matches_from(vec!["ind", "-eieeio", "val"]);
+
+ assert_eq!(m.indices_of("exclude").unwrap().collect::<Vec<_>>(), &[1, 3, 4]);
+ assert_eq!(m.indices_of("include").unwrap().collect::<Vec<_>>(), &[2, 5]);
+ assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[7]);
+}
+
+#[test]
+fn indices_mult_flags_opt_combined_eq() {
+ let m = App::new("ind")
+ .arg(Arg::with_name("exclude")
+ .short("e")
+ .multiple(true))
+ .arg(Arg::with_name("include")
+ .short("i")
+ .multiple(true))
+ .arg(Arg::with_name("option")
+ .short("o")
+ .takes_value(true))
+ .get_matches_from(vec!["ind", "-eieeio=val"]);
+
+ assert_eq!(m.indices_of("exclude").unwrap().collect::<Vec<_>>(), &[1, 3, 4]);
+ assert_eq!(m.indices_of("include").unwrap().collect::<Vec<_>>(), &[2, 5]);
+ assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[7]);
+}
+
+#[test]
+fn indices_mult_opt_value_delim_eq() {
+ let m = App::new("myapp")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .takes_value(true)
+ .use_delimiter(true)
+ .multiple(true))
+ .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
+ assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 3, 4]);
+}
+
+#[test]
+fn indices_mult_opt_value_no_delim_eq() {
+ let m = App::new("myapp")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .takes_value(true)
+ .multiple(true))
+ .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
+ assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2]);
+}
+
+#[test]
+fn indices_mult_opt_mult_flag() {
+ let m = App::new("myapp")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .takes_value(true)
+ .multiple(true))
+ .arg(Arg::with_name("flag")
+ .short("f")
+ .multiple(true))
+ .get_matches_from(vec!["myapp", "-o", "val1", "-f", "-o", "val2", "-f"]);
+
+ assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 5]);
+ assert_eq!(m.indices_of("flag").unwrap().collect::<Vec<_>>(), &[3, 6]);
+}
diff --git a/clap/tests/macros.rs b/clap/tests/macros.rs
new file mode 100755
index 0000000..0cdcb52
--- /dev/null
+++ b/clap/tests/macros.rs
@@ -0,0 +1,391 @@
+#[macro_use]
+extern crate clap;
+
+use clap::ErrorKind;
+
+#[test]
+fn basic() {
+ clap_app!(claptests =>
+ (version: "0.1")
+ (about: "tests clap library")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@arg opt: -o --option +takes_value ... "tests options")
+ (@arg positional: index(1) "tests positionals")
+ (@arg flag: -f --flag ... +global "tests flags")
+ (@arg flag2: -F conflicts_with[flag] requires[option2]
+ "tests flags with exclusions")
+ (@arg option2: --long_option_2 conflicts_with[option] requires[positional2]
+ "tests long options with exclusions")
+ (@arg positional2: index(2) "tests positionals with exclusions")
+ (@arg option3: -O --Option +takes_value possible_value[fast slow]
+ "tests options with specific value sets")
+ (@arg positional3: index(3) ... possible_value[vi emacs]
+ "tests positionals with specific values")
+ (@arg multvals: --multvals +takes_value value_name[one two]
+ "Tests multiple values, not mult occs")
+ (@arg multvalsmo: --multvalsmo ... +takes_value value_name[one two]
+ "Tests multiple values, not mult occs")
+ (@arg minvals: --minvals2 min_values(1) ... +takes_value "Tests 2 min vals")
+ (@arg maxvals: --maxvals3 ... +takes_value max_values(3) "Tests 3 max vals")
+ (@subcommand subcmd =>
+ (about: "tests subcommands")
+ (version: "0.1")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@arg scoption: -o --option ... +takes_value "tests options")
+ (@arg scpositional: index(1) "tests positionals"))
+ );
+}
+
+#[test]
+fn quoted_app_name() {
+ let app = clap_app!(("app name with spaces-and-hyphens") =>
+ (version: "0.1")
+ (about: "tests clap library")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@arg opt: -o --option +takes_value ... "tests options")
+ (@arg positional: index(1) "tests positionals")
+ (@arg flag: -f --flag ... +global "tests flags")
+ (@arg flag2: -F conflicts_with[flag] requires[option2]
+ "tests flags with exclusions")
+ (@arg option2: --long_option_2 conflicts_with[option] requires[positional2]
+ "tests long options with exclusions")
+ (@arg positional2: index(2) "tests positionals with exclusions")
+ (@arg option3: -O --Option +takes_value possible_value[fast slow]
+ "tests options with specific value sets")
+ (@arg positional3: index(3) ... possible_value[vi emacs]
+ "tests positionals with specific values")
+ (@arg multvals: --multvals +takes_value value_name[one two]
+ "Tests multiple values, not mult occs")
+ (@arg multvalsmo: --multvalsmo ... +takes_value value_name[one two]
+ "Tests multiple values, not mult occs")
+ (@arg minvals: --minvals2 min_values(1) ... +takes_value "Tests 2 min vals")
+ (@arg maxvals: --maxvals3 ... +takes_value max_values(3) "Tests 3 max vals")
+ (@subcommand subcmd =>
+ (about: "tests subcommands")
+ (version: "0.1")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@arg scoption: -o --option ... +takes_value "tests options")
+ (@arg scpositional: index(1) "tests positionals"))
+ );
+
+ assert_eq!(app.p.meta.name, "app name with spaces-and-hyphens");
+
+ let mut help_text = vec![];
+ app.write_help(&mut help_text).expect("Could not write help text.");
+ let help_text = String::from_utf8(help_text).expect("Help text is not valid utf-8");
+ assert!(help_text.starts_with("app name with spaces-and-hyphens 0.1\n"));
+}
+
+#[test]
+fn quoted_arg_long_name() {
+ let app = clap_app!(claptests =>
+ (version: "0.1")
+ (about: "tests clap library")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@arg opt: -o --option +takes_value ... "tests options")
+ (@arg positional: index(1) "tests positionals")
+ (@arg flag: -f --flag ... +global "tests flags")
+ (@arg flag2: -F conflicts_with[flag] requires[option2]
+ "tests flags with exclusions")
+ (@arg option2: --("long-option-2") conflicts_with[option] requires[positional2]
+ "tests long options with exclusions")
+ (@arg positional2: index(2) "tests positionals with exclusions")
+ (@arg option3: -O --Option +takes_value possible_value[fast slow]
+ "tests options with specific value sets")
+ (@arg positional3: index(3) ... possible_value[vi emacs]
+ "tests positionals with specific values")
+ (@arg multvals: --multvals +takes_value value_name[one two]
+ "Tests multiple values, not mult occs")
+ (@arg multvalsmo: --multvalsmo ... +takes_value value_name[one two]
+ "Tests multiple values, not mult occs")
+ (@arg minvals: --minvals2 min_values(1) ... +takes_value "Tests 2 min vals")
+ (@arg maxvals: --maxvals3 ... +takes_value max_values(3) "Tests 3 max vals")
+ (@subcommand subcmd =>
+ (about: "tests subcommands")
+ (version: "0.1")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@arg scoption: -o --option ... +takes_value "tests options")
+ (@arg scpositional: index(1) "tests positionals"))
+ );
+
+ let matches = app.get_matches_from_safe(vec!["bin_name", "value1", "value2", "--long-option-2"])
+ .expect("Expected to successfully match the given args.");
+ assert!(matches.is_present("option2"));
+}
+
+#[test]
+fn quoted_arg_name() {
+ let app = clap_app!(claptests =>
+ (version: "0.1")
+ (about: "tests clap library")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@arg opt: -o --option +takes_value ... "tests options")
+ (@arg ("positional-arg"): index(1) "tests positionals")
+ (@arg flag: -f --flag ... +global "tests flags")
+ (@arg flag2: -F conflicts_with[flag] requires[option2]
+ "tests flags with exclusions")
+ (@arg option2: --("long-option-2") conflicts_with[option] requires[positional2]
+ "tests long options with exclusions")
+ (@arg positional2: index(2) "tests positionals with exclusions")
+ (@arg option3: -O --Option +takes_value possible_value[fast slow]
+ "tests options with specific value sets")
+ (@arg ("positional-3"): index(3) ... possible_value[vi emacs]
+ "tests positionals with specific values")
+ (@arg multvals: --multvals +takes_value value_name[one two]
+ "Tests multiple values, not mult occs")
+ (@arg multvalsmo: --multvalsmo ... +takes_value value_name[one two]
+ "Tests multiple values, not mult occs")
+ (@arg minvals: --minvals2 min_values(1) ... +takes_value "Tests 2 min vals")
+ (@arg maxvals: --maxvals3 ... +takes_value max_values(3) "Tests 3 max vals")
+ (@subcommand subcmd =>
+ (about: "tests subcommands")
+ (version: "0.1")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@arg scoption: -o --option ... +takes_value "tests options")
+ (@arg scpositional: index(1) "tests positionals"))
+ );
+
+ let matches = app.get_matches_from_safe(vec!["bin_name", "value1", "value2", "--long-option-2"])
+ .expect("Expected to successfully match the given args.");
+ assert!(matches.is_present("option2"));
+}
+
+#[test]
+fn group_macro() {
+ let app = clap_app!(claptests =>
+ (version: "0.1")
+ (about: "tests clap library")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@group difficulty =>
+ (@arg hard: -h --hard "Sets hard mode")
+ (@arg normal: -n --normal "Sets normal mode")
+ (@arg easy: -e --easy "Sets easy mode")
+ )
+ );
+
+ let result = app.get_matches_from_safe(vec!["bin_name", "--hard"]);
+ assert!(result.is_ok());
+ let matches = result.expect("Expected to successfully match the given args.");
+ assert!(matches.is_present("difficulty"));
+ assert!(matches.is_present("hard"));
+}
+
+#[test]
+fn group_macro_set_multiple() {
+ let app = clap_app!(claptests =>
+ (version: "0.1")
+ (about: "tests clap library")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@group difficulty +multiple =>
+ (@arg hard: -h --hard "Sets hard mode")
+ (@arg normal: -n --normal "Sets normal mode")
+ (@arg easy: -e --easy "Sets easy mode")
+ )
+ );
+
+ let result = app.get_matches_from_safe(vec!["bin_name", "--hard", "--easy"]);
+ assert!(result.is_ok());
+ let matches = result.expect("Expected to successfully match the given args.");
+ assert!(matches.is_present("difficulty"));
+ assert!(matches.is_present("hard"));
+ assert!(matches.is_present("easy"));
+ assert!(!matches.is_present("normal"));
+}
+
+#[test]
+fn group_macro_set_not_multiple() {
+ let app = clap_app!(claptests =>
+ (version: "0.1")
+ (about: "tests clap library")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@group difficulty !multiple =>
+ (@arg hard: -h --hard "Sets hard mode")
+ (@arg normal: -n --normal "Sets normal mode")
+ (@arg easy: -e --easy "Sets easy mode")
+ )
+ );
+
+ let result = app.get_matches_from_safe(vec!["bin_name", "--hard", "--easy"]);
+ assert!(result.is_err());
+ let err = result.unwrap_err();
+ assert_eq!(err.kind, ErrorKind::ArgumentConflict);
+}
+
+#[test]
+fn group_macro_set_required() {
+ let app = clap_app!(claptests =>
+ (version: "0.1")
+ (about: "tests clap library")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@group difficulty +required =>
+ (@arg hard: -h --hard "Sets hard mode")
+ (@arg normal: -n --normal "Sets normal mode")
+ (@arg easy: -e --easy "Sets easy mode")
+ )
+ );
+
+ let result = app.get_matches_from_safe(vec!["bin_name"]);
+ assert!(result.is_err());
+ let err = result.unwrap_err();
+ assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn group_macro_set_not_required() {
+ let app = clap_app!(claptests =>
+ (version: "0.1")
+ (about: "tests clap library")
+ (author: "Kevin K. <kbknapp@gmail.com>")
+ (@group difficulty !required =>
+ (@arg hard: -h --hard "Sets hard mode")
+ (@arg normal: -n --normal "Sets normal mode")
+ (@arg easy: -e --easy "Sets easy mode")
+ )
+ );
+
+ let result = app.get_matches_from_safe(vec!["bin_name"]);
+ assert!(result.is_ok());
+ let matches = result.expect("Expected to successfully match the given args.");
+ assert!(!matches.is_present("difficulty"));
+}
+
+#[test]
+fn multiarg() {
+ let app = || clap_app!(
+ claptests =>
+ (@arg flag: --flag "value")
+ (@arg multiarg: --multiarg
+ default_value("flag-unset") default_value_if("flag", None, "flag-set")
+ "multiarg")
+ (@arg multiarg2: --multiarg2
+ default_value("flag-unset") default_value_if("flag", None, "flag-set",)
+ "multiarg2")
+ );
+
+ let matches = app()
+ .get_matches_from_safe(vec!["bin_name"])
+ .expect("match failed");
+ assert_eq!(matches.value_of("multiarg"), Some("flag-unset"));
+ assert_eq!(matches.value_of("multiarg2"), Some("flag-unset"));
+
+ let matches = app()
+ .get_matches_from_safe(vec!["bin_name", "--flag"])
+ .expect("match failed");
+ assert_eq!(matches.value_of("multiarg"), Some("flag-set"));
+ assert_eq!(matches.value_of("multiarg2"), Some("flag-set"));
+}
+
+#[test]
+fn arg_enum() {
+ // Helper macros to avoid repetition
+ macro_rules! test_greek {
+ ($arg_enum:item, $tests:block) => {{
+ $arg_enum
+ // FromStr implementation
+ assert!("Charlie".parse::<Greek>().is_err());
+ // Display implementation
+ assert_eq!(format!("{}", Greek::Alpha), "Alpha");
+ assert_eq!(format!("{}", Greek::Bravo), "Bravo");
+ // fn variants()
+ assert_eq!(Greek::variants(), ["Alpha", "Bravo"]);
+ // rest of tests
+ $tests
+ }};
+ }
+ macro_rules! test_greek_no_meta {
+ {$arg_enum:item} => {
+ test_greek!($arg_enum, {
+ // FromStr implementation
+ assert!("Alpha".parse::<Greek>().is_ok());
+ assert!("Bravo".parse::<Greek>().is_ok());
+ })
+ };
+ }
+ macro_rules! test_greek_meta {
+ {$arg_enum:item} => {
+ test_greek!($arg_enum, {
+ // FromStr implementation
+ assert_eq!("Alpha".parse::<Greek>(), Ok(Greek::Alpha));
+ assert_eq!("Bravo".parse::<Greek>(), Ok(Greek::Bravo));
+ })
+ };
+ }
+
+ // Tests for each pattern
+ // meta NO, pub NO, trailing comma NO
+ test_greek_no_meta!{
+ arg_enum!{
+ enum Greek {
+ Alpha,
+ Bravo
+ }
+ }
+ };
+ // meta NO, pub NO, trailing comma YES
+ test_greek_no_meta!{
+ arg_enum!{
+ enum Greek {
+ Alpha,
+ Bravo,
+ }
+ }
+ };
+ // meta NO, pub YES, trailing comma NO
+ test_greek_no_meta!{
+ arg_enum!{
+ pub enum Greek {
+ Alpha,
+ Bravo
+ }
+ }
+ };
+ // meta NO, pub YES, trailing comma YES
+ test_greek_no_meta!{
+ arg_enum!{
+ pub enum Greek {
+ Alpha,
+ Bravo,
+ }
+ }
+ };
+ // meta YES, pub NO, trailing comma NO
+ test_greek_meta!{
+ arg_enum!{
+ #[derive(Debug, PartialEq, Copy, Clone)]
+ enum Greek {
+ Alpha,
+ Bravo
+ }
+ }
+ };
+ // meta YES, pub NO, trailing comma YES
+ test_greek_meta!{
+ arg_enum!{
+ #[derive(Debug, PartialEq, Copy, Clone)]
+ enum Greek {
+ Alpha,
+ Bravo,
+ }
+ }
+ };
+ // meta YES, pub YES, trailing comma NO
+ test_greek_meta!{
+ arg_enum!{
+ #[derive(Debug, PartialEq, Copy, Clone)]
+ pub enum Greek {
+ Alpha,
+ Bravo
+ }
+ }
+ };
+ // meta YES, pub YES, trailing comma YES
+ test_greek_meta!{
+ arg_enum!{
+ #[derive(Debug, PartialEq, Copy, Clone)]
+ pub enum Greek {
+ Alpha,
+ Bravo,
+ }
+ }
+ };
+}
diff --git a/clap/tests/multiple_occurrences.rs b/clap/tests/multiple_occurrences.rs
new file mode 100644
index 0000000..2f92fb1
--- /dev/null
+++ b/clap/tests/multiple_occurrences.rs
@@ -0,0 +1,75 @@
+extern crate clap;
+
+use clap::{App, Arg};
+
+#[test]
+fn multiple_occurrences_of_flags_long() {
+ let m = App::new("mo_flags_long")
+ .arg(Arg::from_usage("--multflag 'allowed multiple flag'")
+ .multiple(true))
+ .arg(Arg::from_usage("--flag 'disallowed multiple flag'"))
+ .get_matches_from(vec![
+ "",
+ "--multflag",
+ "--flag",
+ "--multflag"
+ ]);
+ assert!(m.is_present("multflag"));
+ assert_eq!(m.occurrences_of("multflag"), 2);
+ assert!(m.is_present("flag"));
+ assert_eq!(m.occurrences_of("flag"), 1)
+}
+
+#[test]
+fn multiple_occurrences_of_flags_short() {
+ let m = App::new("mo_flags_short")
+ .arg(Arg::from_usage("-m --multflag 'allowed multiple flag'")
+ .multiple(true))
+ .arg(Arg::from_usage("-f --flag 'disallowed multiple flag'"))
+ .get_matches_from(vec![
+ "",
+ "-m",
+ "-f",
+ "-m"
+ ]);
+ assert!(m.is_present("multflag"));
+ assert_eq!(m.occurrences_of("multflag"), 2);
+ assert!(m.is_present("flag"));
+ assert_eq!(m.occurrences_of("flag"), 1);
+}
+
+#[test]
+fn multiple_occurrences_of_flags_mixed() {
+ let m = App::new("mo_flags_mixed")
+ .arg(Arg::from_usage("-m, --multflag1 'allowed multiple flag'")
+ .multiple(true))
+ .arg(Arg::from_usage("-n, --multflag2 'another allowed multiple flag'")
+ .multiple(true))
+ .arg(Arg::from_usage("-f, --flag 'disallowed multiple flag'"))
+ .get_matches_from(vec![
+ "",
+ "-m",
+ "-f",
+ "-n",
+ "--multflag1",
+ "-m",
+ "--multflag2"
+ ]);
+ assert!(m.is_present("multflag1"));
+ assert_eq!(m.occurrences_of("multflag1"), 3);
+ assert!(m.is_present("multflag2"));
+ assert_eq!(m.occurrences_of("multflag2"), 2);
+ assert!(m.is_present("flag"));
+ assert_eq!(m.occurrences_of("flag"), 1);
+}
+
+#[test]
+fn multiple_occurrences_of_flags_large_quantity() {
+ let args : Vec<&str> = vec![""].into_iter().chain(vec!["-m"; 1024].into_iter()).collect();
+ let m = App::new("mo_flags_larg_qty")
+ .arg(Arg::from_usage("-m --multflag 'allowed multiple flag'")
+ .multiple(true))
+ .get_matches_from(args);
+ assert!(m.is_present("multflag"));
+ assert_eq!(m.occurrences_of("multflag"), 1024);
+}
diff --git a/clap/tests/multiple_values.rs b/clap/tests/multiple_values.rs
new file mode 100644
index 0000000..551aff1
--- /dev/null
+++ b/clap/tests/multiple_values.rs
@@ -0,0 +1,1122 @@
+extern crate clap;
+
+use clap::{App, Arg, ErrorKind, SubCommand};
+
+#[test]
+fn option_long() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .long("option")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true))
+ .get_matches_from_safe(vec![
+ "",
+ "--option", "val1",
+ "--option", "val2",
+ "--option", "val3",
+ ]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(m.occurrences_of("option"), 3);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn option_short() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1",
+ "-o", "val2",
+ "-o", "val3",
+ ]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(m.occurrences_of("option"), 3);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn option_mixed() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .long("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1",
+ "--option", "val2",
+ "--option", "val3",
+ "-o", "val4",
+ ]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(m.occurrences_of("option"), 4);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3", "val4"]);
+}
+
+#[test]
+fn option_exact_exact() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .number_of_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1",
+ "-o", "val2",
+ "-o", "val3",
+ ]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(m.occurrences_of("option"), 3);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn option_exact_exact_not_mult() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .number_of_values(3))
+ .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.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn option_exact_exact_mult() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .number_of_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1", "val2", "val3",
+ "-o", "val4", "val5", "val6",
+ ]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(m.occurrences_of("option"), 2);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3", "val4", "val5", "val6"]);
+}
+
+#[test]
+fn option_exact_less() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .number_of_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1",
+ "-o", "val2",
+ ]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
+}
+
+#[test]
+fn option_exact_more() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .number_of_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1",
+ "-o", "val2",
+ "-o", "val3",
+ "-o", "val4",
+ ]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
+}
+
+#[test]
+fn option_min_exact() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .min_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1",
+ "-o", "val2",
+ "-o", "val3",
+ ]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(m.occurrences_of("option"), 3);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn option_min_less() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .min_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1",
+ "-o", "val2",
+ ]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::TooFewValues);
+}
+
+#[test]
+fn option_short_min_more_mult_occurs() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("arg")
+ .required(true))
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .min_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "pos",
+ "-o", "val1",
+ "-o", "val2",
+ "-o", "val3",
+ "-o", "val4",
+ ]);
+
+ let m = m.map_err(|e| println!("failed to unwrap err with error kind {:?}", e.kind)).unwrap();
+
+ assert!(m.is_present("option"));
+ assert!(m.is_present("arg"));
+ assert_eq!(m.occurrences_of("option"), 4);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3", "val4"]);
+ assert_eq!(m.value_of("arg"), Some("pos"));
+}
+
+#[test]
+fn option_short_min_more_single_occur() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("arg")
+ .required(true))
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .min_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "pos",
+ "-o", "val1",
+ "val2",
+ "val3",
+ "val4",
+ ]);
+
+ let m = m.map_err(|e| println!("failed to unwrap err with error kind {:#?}", e)).unwrap();
+
+ assert!(m.is_present("option"));
+ assert!(m.is_present("arg"));
+ assert_eq!(m.occurrences_of("option"), 1);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3", "val4"]);
+ assert_eq!(m.value_of("arg"), Some("pos"));
+}
+
+#[test]
+fn option_max_exact() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .max_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1",
+ "-o", "val2",
+ "-o", "val3",
+ ]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(m.occurrences_of("option"), 3);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn option_max_less() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .max_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1",
+ "-o", "val2",
+ ]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(m.occurrences_of("option"), 2);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2"]);
+}
+
+#[test]
+fn option_max_more() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(true)
+ .max_values(3))
+ .get_matches_from_safe(vec![
+ "",
+ "-o", "val1",
+ "-o", "val2",
+ "-o", "val3",
+ "-o", "val4",
+ ]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::TooManyValues);
+}
+
+#[test]
+fn positional() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("pos")
+ .help("multiple positionals")
+ .multiple(true))
+ .get_matches_from_safe(vec!["myprog", "val1", "val2", "val3"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("pos"));
+ assert_eq!(m.occurrences_of("pos"), 3);
+ assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn positional_exact_exact() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("pos")
+ .help("multiple positionals")
+ .number_of_values(3))
+ .get_matches_from_safe(vec!["myprog", "val1", "val2", "val3"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("pos"));
+ assert_eq!(m.occurrences_of("pos"), 3);
+ assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn positional_exact_less() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("pos")
+ .help("multiple positionals")
+ .number_of_values(3))
+ .get_matches_from_safe(vec!["myprog", "val1", "val2"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
+}
+
+#[test]
+fn positional_exact_more() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("pos")
+ .help("multiple positionals")
+ .number_of_values(3))
+ .get_matches_from_safe(vec!["myprog", "val1", "val2", "val3", "val4"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
+}
+
+#[test]
+fn positional_min_exact() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("pos")
+ .help("multiple positionals")
+ .min_values(3))
+ .get_matches_from_safe(vec!["myprog", "val1", "val2", "val3"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("pos"));
+ assert_eq!(m.occurrences_of("pos"), 3);
+ assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn positional_min_less() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("pos")
+ .help("multiple positionals")
+ .min_values(3))
+ .get_matches_from_safe(vec!["myprog", "val1", "val2"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::TooFewValues);
+}
+
+#[test]
+fn positional_min_more() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("pos")
+ .help("multiple positionals")
+ .min_values(3))
+ .get_matches_from_safe(vec!["myprog", "val1", "val2", "val3", "val4"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("pos"));
+ assert_eq!(m.occurrences_of("pos"), 4);
+ assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3", "val4"]);
+}
+
+#[test]
+fn positional_max_exact() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("pos")
+ .help("multiple positionals")
+ .max_values(3))
+ .get_matches_from_safe(vec!["myprog", "val1", "val2", "val3"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("pos"));
+ assert_eq!(m.occurrences_of("pos"), 3);
+ assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn positional_max_less() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("pos")
+ .help("multiple positionals")
+ .max_values(3))
+ .get_matches_from_safe(vec!["myprog", "val1", "val2"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("pos"));
+ assert_eq!(m.occurrences_of("pos"), 2);
+ assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), ["val1", "val2"]);
+}
+
+#[test]
+fn positional_max_more() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("pos")
+ .help("multiple positionals")
+ .max_values(3))
+ .get_matches_from_safe(vec!["myprog", "val1", "val2", "val3", "val4"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::TooManyValues);
+}
+
+#[test]
+fn sep_long_equals() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .long("option")
+ .use_delimiter(true)
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(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.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn sep_long_space() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .long("option")
+ .use_delimiter(true)
+ .help("multiple options")
+ .takes_value(true)
+ .multiple(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.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn sep_short_equals() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .use_delimiter(true)
+ .takes_value(true)
+ .multiple(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.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn sep_short_space() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .use_delimiter(true)
+ .takes_value(true)
+ .multiple(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.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn sep_short_no_space() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .help("multiple options")
+ .use_delimiter(true)
+ .takes_value(true)
+ .multiple(true))
+ .get_matches_from_safe(vec![
+ "",
+ "-oval1,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::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn sep_positional() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .help("multiple options")
+ .use_delimiter(true)
+ .multiple(true))
+ .get_matches_from_safe(vec![
+ "",
+ "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::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn different_sep() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .long("option")
+ .help("multiple options")
+ .takes_value(true)
+ .value_delimiter(";"))
+ .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.values_of("option").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn different_sep_positional() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .help("multiple options")
+ .value_delimiter(";"))
+ .get_matches_from_safe(vec![
+ "",
+ "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::<Vec<_>>(), ["val1", "val2", "val3"]);
+}
+
+#[test]
+fn no_sep() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .long("option")
+ .help("multiple options")
+ .takes_value(true)
+ .use_delimiter(false))
+ .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 no_sep_positional() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .help("multiple options")
+ .use_delimiter(false))
+ .get_matches_from_safe(vec![
+ "",
+ "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 req_delimiter_long() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .long("option")
+ .multiple(true)
+ .use_delimiter(true)
+ .require_delimiter(true)
+ .takes_value(true))
+ .arg(Arg::with_name("args")
+ .multiple(true)
+ .index(1))
+ .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.values_of("option").unwrap().collect::<Vec<_>>(), &["val1"]);
+ assert_eq!(m.values_of("args").unwrap().collect::<Vec<_>>(), &["val2", "val3"]);
+}
+
+#[test]
+fn req_delimiter_long_with_equal() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .long("option")
+ .multiple(true)
+ .use_delimiter(true)
+ .require_delimiter(true)
+ .takes_value(true))
+ .arg(Arg::with_name("args")
+ .multiple(true)
+ .index(1))
+ .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.values_of("option").unwrap().collect::<Vec<_>>(), &["val1"]);
+ assert_eq!(m.values_of("args").unwrap().collect::<Vec<_>>(), &["val2", "val3"]);
+}
+
+#[test]
+fn req_delimiter_short_with_space() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .multiple(true)
+ .use_delimiter(true)
+ .require_delimiter(true)
+ .takes_value(true))
+ .arg(Arg::with_name("args")
+ .multiple(true)
+ .index(1))
+ .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.values_of("option").unwrap().collect::<Vec<_>>(), &["val1"]);
+ assert_eq!(m.values_of("args").unwrap().collect::<Vec<_>>(), &["val2", "val3"]);
+}
+
+#[test]
+fn req_delimiter_short_with_no_space() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("o")
+ .multiple(true)
+ .use_delimiter(true)
+ .require_delimiter(true)
+ .takes_value(true))
+ .arg(Arg::with_name("args")
+ .multiple(true)
+ .index(1))
+ .get_matches_from_safe(vec![
+ "",
+ "-oval1", "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::<Vec<_>>(), &["val1"]);
+ assert_eq!(m.values_of("args").unwrap().collect::<Vec<_>>(), &["val2", "val3"]);
+}
+
+#[test]
+fn req_delimiter_short_with_equal() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .short("option")
+ .multiple(true)
+ .use_delimiter(true)
+ .require_delimiter(true)
+ .takes_value(true))
+ .arg(Arg::with_name("args")
+ .multiple(true)
+ .index(1))
+ .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.values_of("option").unwrap().collect::<Vec<_>>(), &["val1"]);
+ assert_eq!(m.values_of("args").unwrap().collect::<Vec<_>>(), &["val2", "val3"]);
+}
+
+#[test]
+fn req_delimiter_complex() {
+ let m = App::new("multiple_values")
+ .arg(Arg::with_name("option")
+ .long("option")
+ .short("o")
+ .multiple(true)
+ .use_delimiter(true)
+ .require_delimiter(true)
+ .takes_value(true))
+ .arg(Arg::with_name("args")
+ .multiple(true)
+ .index(1))
+ .get_matches_from_safe(vec![
+ "",
+ "val1",
+ "-oval2", "val3",
+ "-o", "val4", "val5",
+ "-o=val6", "val7",
+ "--option=val8", "val9",
+ "--option", "val10", "val11",
+ "-oval12,val13", "val14",
+ "-o", "val15,val16", "val17",
+ "-o=val18,val19", "val20",
+ "--option=val21,val22", "val23",
+ "--option", "val24,val25", "val26"
+ ]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(m.occurrences_of("option"), 10);
+ assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(),
+ &["val2", "val4", "val6", "val8", "val10", "val12", "val13", "val15",
+ "val16", "val18", "val19", "val21", "val22", "val24", "val25"]);
+ assert_eq!(m.values_of("args").unwrap().collect::<Vec<_>>(),
+ &["val1", "val3", "val5", "val7", "val9", "val11", "val14", "val17",
+ "val20", "val23", "val26"]);
+}
+
+#[test]
+#[should_panic]
+fn low_index_positional_not_required() {
+ let _ = App::new("lip")
+ .arg(Arg::with_name("files")
+ .index(1)
+ .required(true)
+ .multiple(true))
+ .arg(Arg::with_name("target")
+ .index(2))
+ .get_matches_from_safe(vec![
+ "lip",
+ "file1", "file2",
+ "file3", "target",
+ ]);
+}
+
+#[test]
+#[should_panic]
+fn low_index_positional_last_multiple_too() {
+ let _ = App::new("lip")
+ .arg(Arg::with_name("files")
+ .index(1)
+ .required(true)
+ .multiple(true))
+ .arg(Arg::with_name("target")
+ .index(2)
+ .required(true)
+ .multiple(true))
+ .get_matches_from_safe(vec![
+ "lip",
+ "file1", "file2",
+ "file3", "target",
+ ]);
+}
+
+#[test]
+#[should_panic]
+fn low_index_positional_too_far_back() {
+ let _ = App::new("lip")
+ .arg(Arg::with_name("files")
+ .index(1)
+ .required(true)
+ .multiple(true))
+ .arg(Arg::with_name("target")
+ .required(true)
+ .index(2))
+ .arg(Arg::with_name("target2")
+ .required(true)
+ .index(3))
+ .get_matches_from_safe(vec![
+ "lip",
+ "file1", "file2",
+ "file3", "target",
+ ]);
+}
+
+#[test]
+fn low_index_positional() {
+ let m = App::new("lip")
+ .arg(Arg::with_name("files")
+ .index(1)
+ .required(true)
+ .multiple(true))
+ .arg(Arg::with_name("target")
+ .index(2)
+ .required(true))
+ .get_matches_from_safe(vec![
+ "lip",
+ "file1", "file2",
+ "file3", "target",
+ ]);
+
+ assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
+ let m = m.unwrap();
+
+ assert!(m.is_present("files"));
+ assert_eq!(m.occurrences_of("files"), 3);
+ assert!(m.is_present("target"));
+ assert_eq!(m.occurrences_of("target"), 1);
+ assert_eq!(m.values_of("files").unwrap().collect::<Vec<_>>(), ["file1", "file2", "file3"]);
+ assert_eq!(m.value_of("target").unwrap(), "target");
+}
+
+#[test]
+fn low_index_positional_in_subcmd() {
+ let m = App::new("lip")
+ .subcommand(SubCommand::with_name("test")
+ .arg(Arg::with_name("files")
+ .index(1)
+ .required(true)
+ .multiple(true))
+ .arg(Arg::with_name("target")
+ .index(2)
+ .required(true)))
+ .get_matches_from_safe(vec![
+ "lip", "test",
+ "file1", "file2",
+ "file3", "target"
+ ]);
+
+ assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
+ let m = m.unwrap();
+ let sm = m.subcommand_matches("test").unwrap();
+
+ assert!(sm.is_present("files"));
+ assert_eq!(sm.occurrences_of("files"), 3);
+ assert!(sm.is_present("target"));
+ assert_eq!(sm.occurrences_of("target"), 1);
+ assert_eq!(sm.values_of("files").unwrap().collect::<Vec<_>>(), ["file1", "file2", "file3"]);
+ assert_eq!(sm.value_of("target").unwrap(), "target");
+}
+
+#[test]
+fn low_index_positional_with_option() {
+ let m = App::new("lip")
+ .arg(Arg::with_name("files")
+ .required(true)
+ .index(1)
+ .multiple(true))
+ .arg(Arg::with_name("target")
+ .index(2)
+ .required(true))
+ .arg(Arg::with_name("opt")
+ .long("option")
+ .takes_value(true))
+ .get_matches_from_safe(vec![
+ "lip",
+ "file1", "file2",
+ "file3", "target",
+ "--option", "test"
+ ]);
+
+ assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
+ let m = m.unwrap();
+
+ assert!(m.is_present("files"));
+ assert_eq!(m.occurrences_of("files"), 3);
+ assert!(m.is_present("target"));
+ assert_eq!(m.occurrences_of("target"), 1);
+ assert_eq!(m.values_of("files").unwrap().collect::<Vec<_>>(), ["file1", "file2", "file3"]);
+ assert_eq!(m.value_of("target").unwrap(), "target");
+ assert_eq!(m.value_of("opt").unwrap(), "test");
+}
+
+#[test]
+fn low_index_positional_with_flag() {
+ let m = App::new("lip")
+ .arg(Arg::with_name("files")
+ .index(1)
+ .required(true)
+ .multiple(true))
+ .arg(Arg::with_name("target")
+ .index(2)
+ .required(true))
+ .arg(Arg::with_name("flg")
+ .long("flag"))
+ .get_matches_from_safe(vec![
+ "lip",
+ "file1", "file2",
+ "file3", "target",
+ "--flag"
+ ]);
+
+ assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
+ let m = m.unwrap();
+
+ assert!(m.is_present("files"));
+ assert_eq!(m.occurrences_of("files"), 3);
+ assert!(m.is_present("target"));
+ assert_eq!(m.occurrences_of("target"), 1);
+ assert_eq!(m.values_of("files").unwrap().collect::<Vec<_>>(), ["file1", "file2", "file3"]);
+ assert_eq!(m.value_of("target").unwrap(), "target");
+ assert!(m.is_present("flg"));
+}
+
+#[test]
+fn multiple_value_terminator_option() {
+ let m = App::new("lip")
+ .arg(Arg::with_name("files")
+ .short("f")
+ .value_terminator(";")
+ .multiple(true))
+ .arg(Arg::with_name("other"))
+ .get_matches_from_safe(vec![
+ "lip",
+ "-f", "val1", "val2", ";",
+ "otherval"
+ ]);
+
+ assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
+ let m = m.unwrap();
+
+ assert!(m.is_present("other"));
+ assert_eq!(m.occurrences_of("other"), 1);
+ assert!(m.is_present("files"));
+ assert_eq!(m.values_of("files").unwrap().collect::<Vec<_>>(), ["val1", "val2"]);
+ assert_eq!(m.value_of("other"), Some("otherval"));
+}
+
+#[test]
+fn multiple_value_terminator_option_other_arg() {
+ let m = App::new("lip")
+ .arg(Arg::with_name("files")
+ .short("f")
+ .value_terminator(";")
+ .multiple(true))
+ .arg(Arg::with_name("other"))
+ .arg(Arg::with_name("flag")
+ .short("-F"))
+ .get_matches_from_safe(vec![
+ "lip",
+ "-f", "val1", "val2",
+ "-F",
+ "otherval"
+ ]);
+
+ assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
+ let m = m.unwrap();
+
+ assert!(m.is_present("other"));
+ assert!(m.is_present("files"));
+ assert_eq!(m.values_of("files").unwrap().collect::<Vec<_>>(), ["val1", "val2"]);
+ assert_eq!(m.value_of("other"), Some("otherval"));
+ assert!(m.is_present("flag"));
+}
+
+#[test]
+fn multiple_vals_with_hyphen() {
+ let res = App::new("do")
+ .arg(Arg::with_name("cmds")
+ .multiple(true)
+ .allow_hyphen_values(true)
+ .value_terminator(";"))
+ .arg(Arg::with_name("location"))
+ .get_matches_from_safe(vec!["do", "find", "-type", "f", "-name", "special", ";", "/home/clap"]);
+ assert!(res.is_ok(), "{:?}", res.unwrap_err().kind);
+
+ let m = res.unwrap();
+ let cmds: Vec<_> = m.values_of("cmds").unwrap().collect();
+ assert_eq!(&cmds, &["find", "-type", "f", "-name", "special"]);
+ assert_eq!(m.value_of("location"), Some("/home/clap"));
+}
diff --git a/clap/tests/opts.rs b/clap/tests/opts.rs
new file mode 100644
index 0000000..a9029ac
--- /dev/null
+++ b/clap/tests/opts.rs
@@ -0,0 +1,461 @@
+extern crate clap;
+extern crate regex;
+
+include!("../clap-test.rs");
+
+use clap::{App, ArgMatches, Arg, ErrorKind};
+
+#[cfg(feature = "suggestions")]
+static DYM: &'static str = "error: Found argument '--optio' which wasn't expected, or isn't valid in this context
+\tDid you mean --option?
+
+USAGE:
+ clap-test --option <opt>...
+
+For more information try --help";
+
+#[test]
+fn require_equals_fail() {
+ let res = App::new("prog")
+ .arg(Arg::with_name("cfg")
+ .require_equals(true)
+ .takes_value(true)
+ .long("config"))
+ .get_matches_from_safe(vec![
+ "prog", "--config", "file.conf"
+ ]);
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
+}
+
+#[test]
+fn require_equals_min_values_zero() {
+ let res = App::new("prog")
+ .arg(Arg::with_name("cfg")
+ .require_equals(true)
+ .takes_value(true)
+ .min_values(0)
+ .long("config"))
+ .arg(Arg::with_name("cmd"))
+ .get_matches_from_safe(vec![
+ "prog", "--config", "cmd"
+ ]);
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("cfg"));
+ assert_eq!(m.value_of("cmd"), Some("cmd"));
+}
+
+#[test]
+fn double_hyphen_as_value() {
+ let res = App::new("prog")
+ .arg(Arg::with_name("cfg")
+ .takes_value(true)
+ .allow_hyphen_values(true)
+ .long("config"))
+ .get_matches_from_safe(vec![
+ "prog", "--config", "--"
+ ]);
+ assert!(res.is_ok(), "{:?}", res);
+ assert_eq!(res.unwrap().value_of("cfg"), Some("--"));
+}
+
+#[test]
+fn require_equals_no_empty_values_fail() {
+ let res = App::new("prog")
+ .arg(Arg::with_name("cfg")
+ .require_equals(true)
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("some"))
+ .get_matches_from_safe(vec![
+ "prog", "--config=", "file.conf"
+ ]);
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
+}
+
+#[test]
+fn require_equals_empty_vals_pass() {
+ let res = App::new("prog")
+ .arg(Arg::with_name("cfg")
+ .require_equals(true)
+ .takes_value(true)
+ .empty_values(true)
+ .long("config"))
+ .get_matches_from_safe(vec![
+ "prog", "--config="
+ ]);
+ assert!(res.is_ok());
+}
+
+#[test]
+fn require_equals_pass() {
+ let res = App::new("prog")
+ .arg(Arg::with_name("cfg")
+ .require_equals(true)
+ .takes_value(true)
+ .long("config"))
+ .get_matches_from_safe(vec![
+ "prog", "--config=file.conf"
+ ]);
+ assert!(res.is_ok());
+}
+
+#[test]
+fn stdin_char() {
+ let r = App::new("opts")
+ .arg(Arg::from_usage("-f [flag] 'some flag'"))
+ .get_matches_from_safe(vec!["", "-f", "-"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("f"));
+ assert_eq!(m.value_of("f").unwrap(), "-");
+}
+
+#[test]
+fn opts_using_short() {
+ let r = App::new("opts")
+ .args(&[Arg::from_usage("-f [flag] 'some flag'"),
+ Arg::from_usage("-c [color] 'some other flag'")])
+ .get_matches_from_safe(vec!["", "-f", "some", "-c", "other"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("f"));
+ assert_eq!(m.value_of("f").unwrap(), "some");
+ assert!(m.is_present("c"));
+ assert_eq!(m.value_of("c").unwrap(), "other");
+}
+
+#[test]
+fn lots_o_vals() {
+ let r = App::new("opts")
+ .arg(Arg::from_usage("-o [opt]... 'some opt'"))
+ .get_matches_from_safe(vec!["", "-o", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("o"));
+ assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>().len(), 297); // i.e. more than u8
+}
+
+#[test]
+fn opts_using_long_space() {
+ let r = App::new("opts")
+ .args(&[Arg::from_usage("--flag [flag] 'some flag'"),
+ Arg::from_usage("--color [color] 'some other flag'")])
+ .get_matches_from_safe(vec!["", "--flag", "some", "--color", "other"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("flag"));
+ assert_eq!(m.value_of("flag").unwrap(), "some");
+ assert!(m.is_present("color"));
+ assert_eq!(m.value_of("color").unwrap(), "other");
+}
+
+#[test]
+fn opts_using_long_equals() {
+ let r = App::new("opts")
+ .args(&[Arg::from_usage("--flag [flag] 'some flag'"),
+ Arg::from_usage("--color [color] 'some other flag'")])
+ .get_matches_from_safe(vec!["", "--flag=some", "--color=other"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("flag"));
+ assert_eq!(m.value_of("flag").unwrap(), "some");
+ assert!(m.is_present("color"));
+ assert_eq!(m.value_of("color").unwrap(), "other");
+}
+
+#[test]
+fn opts_using_mixed() {
+ let r = App::new("opts")
+ .args(&[Arg::from_usage("-f, --flag [flag] 'some flag'"),
+ Arg::from_usage("-c, --color [color] 'some other flag'")])
+ .get_matches_from_safe(vec!["", "-f", "some", "--color", "other"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("flag"));
+ assert_eq!(m.value_of("flag").unwrap(), "some");
+ assert!(m.is_present("color"));
+ assert_eq!(m.value_of("color").unwrap(), "other");
+}
+
+#[test]
+fn opts_using_mixed2() {
+ let r = App::new("opts")
+ .args(&[Arg::from_usage("-f, --flag [flag] 'some flag'"),
+ Arg::from_usage("-c, --color [color] 'some other flag'")])
+ .get_matches_from_safe(vec!["", "--flag=some", "-c", "other"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("flag"));
+ assert_eq!(m.value_of("flag").unwrap(), "some");
+ assert!(m.is_present("color"));
+ assert_eq!(m.value_of("color").unwrap(), "other");
+}
+
+#[test]
+fn default_values_user_value() {
+ let r = App::new("df")
+ .arg(Arg::from_usage("-o [opt] 'some opt'").default_value("default"))
+ .get_matches_from_safe(vec!["", "-o", "value"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("o"));
+ assert_eq!(m.value_of("o").unwrap(), "value");
+}
+
+#[test]
+fn multiple_vals_pos_arg_equals() {
+ let r = App::new("mvae")
+ .arg(Arg::from_usage("-o [opt]... 'some opt'"))
+ .arg(Arg::from_usage("[file] 'some file'"))
+ .get_matches_from_safe(vec!["", "-o=1", "some"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("o"));
+ assert_eq!(m.value_of("o").unwrap(), "1");
+ assert!(m.is_present("file"));
+ assert_eq!(m.value_of("file").unwrap(), "some");
+}
+
+#[test]
+fn multiple_vals_pos_arg_delim() {
+ let r = App::new("mvae")
+ .arg(Arg::from_usage("-o [opt]... 'some opt'"))
+ .arg(Arg::from_usage("[file] 'some file'"))
+ .get_matches_from_safe(vec!["", "-o", "1,2", "some"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("o"));
+ assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["1", "2"]);
+ assert!(m.is_present("file"));
+ assert_eq!(m.value_of("file").unwrap(), "some");
+}
+
+#[test]
+fn require_delims_no_delim() {
+ let r = App::new("mvae")
+ .arg(Arg::from_usage("-o [opt]... 'some opt'").require_delimiter(true))
+ .arg(Arg::from_usage("[file] 'some file'"))
+ .get_matches_from_safe(vec!["mvae", "-o", "1", "2", "some"]);
+ assert!(r.is_err());
+ let err = r.unwrap_err();
+ assert_eq!(err.kind, ErrorKind::UnknownArgument);
+}
+
+#[test]
+fn require_delims() {
+ let r = App::new("mvae")
+ .arg(Arg::from_usage("-o [opt]... 'some opt'").require_delimiter(true))
+ .arg(Arg::from_usage("[file] 'some file'"))
+ .get_matches_from_safe(vec!["", "-o", "1,2", "some"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("o"));
+ assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["1", "2"]);
+ assert!(m.is_present("file"));
+ assert_eq!(m.value_of("file").unwrap(), "some");
+}
+
+#[test]
+fn leading_hyphen_pass() {
+ let r = App::new("mvae")
+ .arg(Arg::from_usage("-o [opt]... 'some opt'").allow_hyphen_values(true))
+ .get_matches_from_safe(vec!["", "-o", "-2", "3"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("o"));
+ assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2", "3"]);
+}
+
+#[test]
+fn leading_hyphen_fail() {
+ let r = App::new("mvae")
+ .arg(Arg::from_usage("-o [opt] 'some opt'"))
+ .get_matches_from_safe(vec!["", "-o", "-2"]);
+ assert!(r.is_err());
+ let m = r.unwrap_err();
+ assert_eq!(m.kind, ErrorKind::UnknownArgument);
+}
+
+#[test]
+fn leading_hyphen_with_flag_after() {
+ let r = App::new("mvae")
+ .arg(Arg::from_usage("-o [opt]... 'some opt'").allow_hyphen_values(true))
+ .arg_from_usage("-f 'some flag'")
+ .get_matches_from_safe(vec!["", "-o", "-2", "-f"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("o"));
+ assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2", "-f"]);
+ assert!(!m.is_present("f"));
+}
+
+#[test]
+fn leading_hyphen_with_flag_before() {
+ let r = App::new("mvae")
+ .arg(Arg::from_usage("-o [opt]... 'some opt'").allow_hyphen_values(true))
+ .arg_from_usage("-f 'some flag'")
+ .get_matches_from_safe(vec!["", "-f", "-o", "-2"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("o"));
+ assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2"]);
+ assert!(m.is_present("f"));
+}
+
+#[test]
+fn leading_hyphen_with_only_pos_follows() {
+ let r = App::new("mvae")
+ .arg(Arg::from_usage("-o [opt]... 'some opt'").number_of_values(1).allow_hyphen_values(true))
+ .arg_from_usage("[arg] 'some arg'")
+ .get_matches_from_safe(vec!["", "-o", "-2", "--", "val"]);
+ assert!(r.is_ok(), "{:?}", r);
+ let m = r.unwrap();
+ assert!(m.is_present("o"));
+ assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2"]);
+ assert_eq!(m.value_of("arg"), Some("val"));
+}
+
+#[test]
+#[cfg(feature="suggestions")]
+fn did_you_mean() {
+ assert!(test::compare_output(test::complex_app(),
+ "clap-test --optio=foo",
+ DYM,
+ true));
+}
+
+#[test]
+fn issue_665() {
+ let res = App::new("tester")
+ .arg_from_usage("-v, --reroll-count=[N] 'Mark the patch series as PATCH vN'")
+ .arg(Arg::from_usage(
+"--subject-prefix [Subject-Prefix] 'Use [Subject-Prefix] instead of the standard [PATCH] prefix'")
+ .empty_values(false))
+ .get_matches_from_safe(vec!["test", "--subject-prefix", "-v", "2"]);
+
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
+}
+
+#[test]
+fn issue_1047_min_zero_vals_default_val() {
+ let m = App::new("foo")
+ .arg(
+ Arg::with_name("del")
+ .short("d")
+ .long("del")
+ .takes_value(true)
+ .require_equals(true)
+ .min_values(0)
+ .default_value("default"),
+ )
+ .get_matches_from(vec!["foo", "-d"]);
+ assert_eq!(m.occurrences_of("del"), 1);
+ assert_eq!(m.value_of("del"), Some("default"));
+}
+
+fn issue_1105_setup(argv: Vec<&'static str>) -> Result<ArgMatches<'static>, clap::Error> {
+ App::new("opts")
+ .arg_from_usage("-o, --option [opt] 'some option'")
+ .arg_from_usage("--flag 'some flag'")
+ .get_matches_from_safe(argv)
+}
+
+#[test]
+fn issue_1105_empty_value_long_fail() {
+ let r = issue_1105_setup(vec!["app", "--option", "--flag"]);
+ assert!(r.is_err());
+ assert_eq!(r.unwrap_err().kind, ErrorKind::EmptyValue);
+}
+
+#[test]
+fn issue_1105_empty_value_long_explicit() {
+ let r = issue_1105_setup(vec!["app", "--option", ""]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert_eq!(m.value_of("option"), Some(""));
+}
+
+#[test]
+fn issue_1105_empty_value_long_equals() {
+ let r = issue_1105_setup(vec!["app", "--option="]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert_eq!(m.value_of("option"), Some(""));
+}
+
+#[test]
+fn issue_1105_empty_value_short_fail() {
+ let r = issue_1105_setup(vec!["app", "-o", "--flag"]);
+ assert!(r.is_err());
+ assert_eq!(r.unwrap_err().kind, ErrorKind::EmptyValue);
+}
+
+#[test]
+fn issue_1105_empty_value_short_explicit() {
+ let r = issue_1105_setup(vec!["app", "-o", ""]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert_eq!(m.value_of("option"), Some(""));
+}
+
+#[test]
+fn issue_1105_empty_value_short_equals() {
+ let r = issue_1105_setup(vec!["app", "-o="]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert_eq!(m.value_of("option"), Some(""));
+}
+
+#[test]
+fn issue_1105_empty_value_short_explicit_no_space() {
+ let r = issue_1105_setup(vec!["app", "-o", ""]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert_eq!(m.value_of("option"), Some(""));
+}
diff --git a/clap/tests/positionals.rs b/clap/tests/positionals.rs
new file mode 100644
index 0000000..bf0f79f
--- /dev/null
+++ b/clap/tests/positionals.rs
@@ -0,0 +1,274 @@
+extern crate clap;
+
+use clap::{App, Arg, ErrorKind};
+
+#[test]
+fn only_pos_follow() {
+ 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"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert!(!m.is_present("f"));
+ assert_eq!(m.value_of("arg").unwrap(), "-f");
+}
+
+#[test]
+fn issue_946() {
+ let r = App::new("compiletest")
+ .setting(clap::AppSettings::AllowLeadingHyphen)
+ .args_from_usage("--exact 'filters match exactly'")
+ .arg(clap::Arg::with_name("filter")
+ .index(1)
+ .takes_value(true)
+ .help("filters to apply to output"))
+ .get_matches_from_safe(vec!["compiletest", "--exact"]);
+ assert!(r.is_ok(), "{:#?}", r);
+ let matches = r.unwrap();
+
+ assert!(matches.is_present("exact"));
+ assert!(matches.value_of("filter").is_none());
+}
+
+#[test]
+fn positional() {
+ let r = App::new("positional")
+ .args(&[
+ Arg::from_usage("-f, --flag 'some flag'"),
+ Arg::with_name("positional")
+ .index(1)
+ ])
+ .get_matches_from_safe(vec!["", "-f", "test"]);
+ assert!(r.is_ok(), "{:#?}", r);
+ let m = r.unwrap();
+ assert!(m.is_present("positional"));
+ assert!(m.is_present("flag"));
+ assert_eq!(m.value_of("positional").unwrap(), "test");
+
+ let m = App::new("positional")
+ .args(&[
+ Arg::from_usage("-f, --flag 'some flag'"),
+ Arg::with_name("positional")
+ .index(1)
+ ])
+ .get_matches_from(vec!["", "test", "--flag"]);
+ assert!(m.is_present("positional"));
+ assert!(m.is_present("flag"));
+ assert_eq!(m.value_of("positional").unwrap(), "test");
+}
+
+#[test]
+fn lots_o_vals() {
+ let r = App::new("opts")
+ .arg(
+ Arg::from_usage("[opt]... 'some pos'"),
+ )
+ .get_matches_from_safe(vec!["",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ ]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("opt"));
+ assert_eq!(m.values_of("opt").unwrap().collect::<Vec<_>>().len(), 297); // i.e. more than u8
+}
+
+#[test]
+fn positional_multiple() {
+ let r = App::new("positional_multiple")
+ .args(&[
+ Arg::from_usage("-f, --flag 'some flag'"),
+ Arg::with_name("positional")
+ .index(1)
+ .multiple(true)
+ ])
+ .get_matches_from_safe(vec!["", "-f", "test1", "test2", "test3"]);
+ assert!(r.is_ok(), "{:#?}", r);
+ let m = r.unwrap();
+ assert!(m.is_present("positional"));
+ assert!(m.is_present("flag"));
+ assert_eq!(&*m.values_of("positional").unwrap().collect::<Vec<_>>(), &["test1", "test2", "test3"]);
+}
+
+#[test]
+fn positional_multiple_3() {
+ let r = App::new("positional_multiple")
+ .args(&[
+ Arg::from_usage("-f, --flag 'some flag'"),
+ Arg::with_name("positional")
+ .index(1)
+ .multiple(true)
+ ])
+ .get_matches_from_safe(vec!["", "test1", "test2", "test3", "--flag"]);
+ assert!(r.is_ok(), "{:#?}", r);
+ let m = r.unwrap();
+ assert!(m.is_present("positional"));
+ assert!(m.is_present("flag"));
+ assert_eq!(&*m.values_of("positional").unwrap().collect::<Vec<_>>(), &["test1", "test2", "test3"]);
+}
+
+#[test]
+fn positional_multiple_2() {
+ let result = App::new("positional_multiple")
+ .args(&[
+ Arg::from_usage("-f, --flag 'some flag'"),
+ Arg::with_name("positional")
+ .index(1)
+ ])
+ .get_matches_from_safe(vec!["", "-f", "test1", "test2", "test3"]);
+ assert!(result.is_err());
+ let err = result.err().unwrap();
+ assert_eq!(err.kind, ErrorKind::UnknownArgument);
+}
+
+#[test]
+fn positional_possible_values() {
+ let r = App::new("positional_possible_values")
+ .args(&[
+ Arg::from_usage("-f, --flag 'some flag'"),
+ Arg::with_name("positional")
+ .index(1)
+ .possible_value("test123")
+ ])
+ .get_matches_from_safe(vec!["", "-f", "test123"]);
+ assert!(r.is_ok(), "{:#?}", r);
+ let m = r.unwrap();
+ assert!(m.is_present("positional"));
+ assert!(m.is_present("flag"));
+ assert_eq!(&*m.values_of("positional").unwrap().collect::<Vec<_>>(), &["test123"]);
+}
+
+#[test]
+fn create_positional() {
+ let _ = App::new("test")
+ .arg(Arg::with_name("test")
+ .index(1)
+ .help("testing testing"))
+ .get_matches_from(vec![""]);
+}
+
+#[test]
+fn positional_hyphen_does_not_panic() {
+ let _ = App::new("test")
+ .arg(Arg::with_name("dummy"))
+ .get_matches_from(vec!["test", "-"]);
+}
+
+#[test]
+fn single_positional_usage_string() {
+ let m = App::new("test").arg_from_usage("[FILE] 'some file'").get_matches_from(vec!["test"]);
+ assert_eq!(m.usage(), "USAGE:\n test [FILE]");
+}
+
+#[test]
+fn single_positional_multiple_usage_string() {
+ let m = App::new("test").arg_from_usage("[FILE]... 'some file'").get_matches_from(vec!["test"]);
+ assert_eq!(m.usage(), "USAGE:\n test [FILE]...");
+}
+
+#[test]
+fn multiple_positional_usage_string() {
+ let m = App::new("test")
+ .arg_from_usage("[FILE] 'some file'")
+ .arg_from_usage("[FILES]... 'some file'")
+ .get_matches_from(vec!["test"]);
+ assert_eq!(m.usage(), "USAGE:\n test [ARGS]");
+}
+
+#[test]
+fn multiple_positional_one_required_usage_string() {
+ let m = App::new("test")
+ .arg_from_usage("<FILE> 'some file'")
+ .arg_from_usage("[FILES]... 'some file'")
+ .get_matches_from(vec!["test", "file"]);
+ assert_eq!(m.usage(), "USAGE:\n test <FILE> [FILES]...");
+}
+
+#[test]
+fn single_positional_required_usage_string() {
+ let m = App::new("test")
+ .arg_from_usage("<FILE> 'some file'")
+ .get_matches_from(vec!["test", "file"]);
+ assert_eq!(m.usage(), "USAGE:\n test <FILE>");
+}
+
+#[test]
+#[should_panic]
+fn missing_required() {
+ let r = App::new("test")
+ .arg_from_usage("[FILE1] 'some file'")
+ .arg_from_usage("<FILE2> 'some file'")
+ .get_matches_from_safe(vec!["test", "file"]);
+ assert!(r.is_err());
+ assert_eq!(r.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn missing_required_2() {
+ let r = App::new("test")
+ .arg_from_usage("<FILE1> 'some file'")
+ .arg_from_usage("<FILE2> 'some file'")
+ .get_matches_from_safe(vec!["test", "file"]);
+ assert!(r.is_err());
+ assert_eq!(r.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn last_positional() {
+ let r = App::new("test")
+ .arg_from_usage("<TARGET> 'some target'")
+ .arg_from_usage("[CORPUS] 'some corpus'")
+ .arg(Arg::from_usage("[ARGS]... 'some file'").last(true))
+ .get_matches_from_safe(vec!["test", "tgt", "--", "arg"]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert_eq!(m.values_of("ARGS").unwrap().collect::<Vec<_>>(), &["arg"]);
+}
+
+#[test]
+fn last_positional_no_double_dash() {
+ let r = App::new("test")
+ .arg_from_usage("<TARGET> 'some target'")
+ .arg_from_usage("[CORPUS] 'some corpus'")
+ .arg(Arg::from_usage("[ARGS]... 'some file'").last(true))
+ .get_matches_from_safe(vec!["test", "tgt", "crp", "arg"]);
+ assert!(r.is_err());
+ assert_eq!(r.unwrap_err().kind, ErrorKind::UnknownArgument);
+}
+
+#[test]
+fn last_positional_second_to_last_mult() {
+ let r = App::new("test")
+ .arg_from_usage("<TARGET> 'some target'")
+ .arg_from_usage("[CORPUS]... 'some corpus'")
+ .arg(Arg::from_usage("[ARGS]... 'some file'").last(true))
+ .get_matches_from_safe(vec!["test", "tgt", "crp1", "crp2", "--", "arg"]);
+ assert!(r.is_ok(), "{:?}", r.unwrap_err().kind);
+}
diff --git a/clap/tests/posix_compatible.rs b/clap/tests/posix_compatible.rs
new file mode 100644
index 0000000..26d9f71
--- /dev/null
+++ b/clap/tests/posix_compatible.rs
@@ -0,0 +1,292 @@
+extern crate clap;
+
+use clap::{App, Arg, ErrorKind};
+
+#[test]
+fn flag_overrides_itself() {
+ let res = App::new("posix")
+ .arg(Arg::from_usage("--flag 'some flag'").overrides_with("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 mult_flag_overrides_itself() {
+ let res = App::new("posix")
+ .arg(Arg::from_usage("--flag... 'some flag'").overrides_with("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 option_overrides_itself() {
+ let res = App::new("posix")
+ .arg(Arg::from_usage("--opt [val] 'some option'").overrides_with("opt"))
+ .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 mult_option_require_delim_overrides_itself() {
+ let res = App::new("posix")
+ .arg(Arg::from_usage("--opt [val]... 'some option'")
+ .overrides_with("opt")
+ .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::<Vec<_>>(), &["some", "other", "one", "two"]);
+}
+
+#[test]
+fn mult_option_overrides_itself() {
+ let res = App::new("posix")
+ .arg(Arg::from_usage("--opt [val]... 'some option'")
+ .overrides_with("opt"))
+ .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::<Vec<_>>(), &["first", "overides", "some", "other", "val"]);
+}
+
+#[test]
+fn option_use_delim_false_override_itself() {
+
+ let m = App::new("posix")
+ .arg(Arg::from_usage("--opt [val] 'some option'")
+ .overrides_with("opt")
+ .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::<Vec<_>>(), &["one,two"]);
+}
+
+#[test]
+fn pos_mult_overrides_itself() {
+ // opts with multiple
+ let res = App::new("posix")
+ .arg(Arg::from_usage("[val]... 'some pos'").overrides_with("val"))
+ .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::<Vec<_>>(), &["some", "other", "value"]);
+}
+
+#[test]
+fn posix_compatible_flags_long() {
+ let m = App::new("posix")
+ .arg(Arg::from_usage("--flag 'some flag'").overrides_with("color"))
+ .arg(Arg::from_usage("--color 'some other flag'"))
+ .get_matches_from(vec!["", "--flag", "--color"]);
+ assert!(m.is_present("color"));
+ assert!(!m.is_present("flag"));
+
+ let m = App::new("posix")
+ .arg(Arg::from_usage("--flag 'some flag'").overrides_with("color"))
+ .arg(Arg::from_usage("--color 'some other flag'"))
+ .get_matches_from(vec!["", "--color", "--flag"]);
+ assert!(!m.is_present("color"));
+ assert!(m.is_present("flag"));
+}
+
+#[test]
+fn posix_compatible_flags_short() {
+ let m = App::new("posix")
+ .arg(Arg::from_usage("-f, --flag 'some flag'").overrides_with("color"))
+ .arg(Arg::from_usage("-c, --color 'some other flag'"))
+ .get_matches_from(vec!["", "-f", "-c"]);
+ assert!(m.is_present("color"));
+ assert!(!m.is_present("flag"));
+
+ let m = App::new("posix")
+ .arg(Arg::from_usage("-f, --flag 'some flag'").overrides_with("color"))
+ .arg(Arg::from_usage("-c, --color 'some other flag'"))
+ .get_matches_from(vec!["", "-c", "-f"]);
+ assert!(!m.is_present("color"));
+ assert!(m.is_present("flag"));
+}
+
+#[test]
+fn posix_compatible_opts_long() {
+ let m = App::new("posix")
+ .arg(Arg::from_usage("--flag [flag] 'some flag'").overrides_with("color"))
+ .arg(Arg::from_usage("--color [color] 'some other flag'"))
+ .get_matches_from(vec!["", "--flag", "some" ,"--color", "other"]);
+ assert!(m.is_present("color"));
+ assert_eq!(m.value_of("color").unwrap(), "other");
+ assert!(!m.is_present("flag"));
+
+ let m = App::new("posix")
+ .arg(Arg::from_usage("--flag [flag] 'some flag'").overrides_with("color"))
+ .arg(Arg::from_usage("--color [color] 'some other flag'"))
+ .get_matches_from(vec!["", "--color", "some" ,"--flag", "other"]);
+ assert!(!m.is_present("color"));
+ assert!(m.is_present("flag"));
+ assert_eq!(m.value_of("flag").unwrap(), "other");
+}
+
+#[test]
+fn posix_compatible_opts_long_equals() {
+ let m = App::new("posix")
+ .arg(Arg::from_usage("--flag [flag] 'some flag'").overrides_with("color"))
+ .arg(Arg::from_usage("--color [color] 'some other flag'"))
+ .get_matches_from(vec!["", "--flag=some" ,"--color=other"]);
+ assert!(m.is_present("color"));
+ assert_eq!(m.value_of("color").unwrap(), "other");
+ assert!(!m.is_present("flag"));
+
+ let m = App::new("posix")
+ .arg(Arg::from_usage("--flag [flag] 'some flag'").overrides_with("color"))
+ .arg(Arg::from_usage("--color [color] 'some other flag'"))
+ .get_matches_from(vec!["", "--color=some" ,"--flag=other"]);
+ assert!(!m.is_present("color"));
+ assert!(m.is_present("flag"));
+ assert_eq!(m.value_of("flag").unwrap(), "other");
+}
+
+#[test]
+fn posix_compatible_opts_short() {
+ let m = App::new("posix")
+ .arg(Arg::from_usage("-f [flag] 'some flag'").overrides_with("c"))
+ .arg(Arg::from_usage("-c [color] 'some other flag'"))
+ .get_matches_from(vec!["", "-f", "some", "-c", "other"]);
+ assert!(m.is_present("c"));
+ assert_eq!(m.value_of("c").unwrap(), "other");
+ assert!(!m.is_present("f"));
+
+ let m = App::new("posix")
+ .arg(Arg::from_usage("-f [flag] 'some flag'").overrides_with("c"))
+ .arg(Arg::from_usage("-c [color] 'some other flag'"))
+ .get_matches_from(vec!["", "-c", "some", "-f", "other"]);
+ assert!(!m.is_present("c"));
+ assert!(m.is_present("f"));
+ assert_eq!(m.value_of("f").unwrap(), "other");
+}
+
+#[test]
+fn conflict_overriden() {
+ let m = App::new("conflict_overriden")
+ .arg(Arg::from_usage("-f, --flag 'some flag'")
+ .conflicts_with("debug"))
+ .arg(Arg::from_usage("-d, --debug 'other flag'"))
+ .arg(Arg::from_usage("-c, --color 'third flag'")
+ .overrides_with("flag"))
+ .get_matches_from(vec!["", "-f", "-c", "-d"]);
+ assert!(m.is_present("color"));
+ assert!(!m.is_present("flag"));
+ assert!(m.is_present("debug"));
+}
+
+#[test]
+fn conflict_overriden_2() {
+ let result = App::new("conflict_overriden")
+ .arg(Arg::from_usage("-f, --flag 'some flag'")
+ .conflicts_with("debug"))
+ .arg(Arg::from_usage("-d, --debug 'other flag'"))
+ .arg(Arg::from_usage("-c, --color 'third flag'")
+ .overrides_with("flag"))
+ .get_matches_from_safe(vec!["", "-f", "-d", "-c"]);
+ assert!(result.is_ok());
+ let m = result.unwrap();
+ assert!(m.is_present("color"));
+ assert!(m.is_present("debug"));
+ assert!(!m.is_present("flag"));
+}
+
+#[test]
+fn conflict_overriden_3() {
+ let result = App::new("conflict_overriden")
+ .arg(Arg::from_usage("-f, --flag 'some flag'")
+ .conflicts_with("debug"))
+ .arg(Arg::from_usage("-d, --debug 'other flag'"))
+ .arg(Arg::from_usage("-c, --color 'third flag'")
+ .overrides_with("flag"))
+ .get_matches_from_safe(vec!["", "-d", "-c", "-f"]);
+ assert!(result.is_err());
+ let err = result.err().unwrap();
+ assert_eq!(err.kind, ErrorKind::ArgumentConflict);
+}
+
+#[test]
+fn conflict_overriden_4() {
+ let m = App::new("conflict_overriden")
+ .arg(Arg::from_usage("-f, --flag 'some flag'")
+ .conflicts_with("debug"))
+ .arg(Arg::from_usage("-d, --debug 'other flag'"))
+ .arg(Arg::from_usage("-c, --color 'third flag'")
+ .overrides_with("flag"))
+ .get_matches_from(vec!["", "-d", "-f", "-c"]);
+ assert!(m.is_present("color"));
+ assert!(!m.is_present("flag"));
+ assert!(m.is_present("debug"));
+}
+
+#[test]
+fn pos_required_overridden_by_flag() {
+ let result = App::new("require_overriden")
+ .arg(Arg::with_name("pos")
+ .index(1)
+ .required(true))
+ .arg(Arg::from_usage("-c, --color 'some flag'")
+ .overrides_with("pos"))
+ .get_matches_from_safe(vec!["", "test", "-c"]);
+ assert!(result.is_ok(), "{:?}", result.unwrap_err());
+}
+
+#[test]
+fn require_overriden_2() {
+ let m = App::new("require_overriden")
+ .arg(Arg::with_name("req_pos")
+ .required(true))
+ .arg(Arg::from_usage("-c, --color 'other flag'")
+ .overrides_with("req_pos"))
+ .get_matches_from(vec!["", "-c", "req_pos"]);
+ assert!(!m.is_present("color"));
+ assert!(m.is_present("req_pos"));
+}
+
+#[test]
+fn require_overriden_3() {
+ let m = App::new("require_overriden")
+ .arg(Arg::from_usage("-f, --flag 'some flag'")
+ .requires("debug"))
+ .arg(Arg::from_usage("-d, --debug 'other flag'"))
+ .arg(Arg::from_usage("-c, --color 'third flag'")
+ .overrides_with("flag"))
+ .get_matches_from(vec!["", "-f", "-c"]);
+ assert!(m.is_present("color"));
+ assert!(!m.is_present("flag"));
+ assert!(!m.is_present("debug"));
+}
+
+#[test]
+fn require_overriden_4() {
+ let result = App::new("require_overriden")
+ .arg(Arg::from_usage("-f, --flag 'some flag'")
+ .requires("debug"))
+ .arg(Arg::from_usage("-d, --debug 'other flag'"))
+ .arg(Arg::from_usage("-c, --color 'third flag'")
+ .overrides_with("flag"))
+ .get_matches_from_safe(vec!["", "-c", "-f"]);
+ assert!(result.is_err());
+ let err = result.err().unwrap();
+ assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
+}
diff --git a/clap/tests/possible_values.rs b/clap/tests/possible_values.rs
new file mode 100644
index 0000000..80772bd
--- /dev/null
+++ b/clap/tests/possible_values.rs
@@ -0,0 +1,266 @@
+extern crate clap;
+extern crate regex;
+
+include!("../clap-test.rs");
+
+#[allow(deprecated, unused_imports)]
+use std::ascii::AsciiExt;
+
+use clap::{App, Arg, ErrorKind};
+
+#[cfg(feature = "suggestions")]
+static PV_ERROR: &'static str = "error: 'slo' isn't a valid value for '--Option <option3>'
+\t[possible values: fast, slow]
+
+\tDid you mean 'slow'?
+
+USAGE:
+ clap-test --Option <option3>
+
+For more information try --help";
+
+#[cfg(not(feature = "suggestions"))]
+static PV_ERROR: &'static str = "error: 'slo' isn't a valid value for '--Option <option3>'
+\t[possible values: fast, slow]
+
+
+USAGE:
+ clap-test --Option <option3>
+
+For more information try --help";
+
+#[test]
+fn possible_values_of_positional() {
+ let m = App::new("possible_values")
+ .arg(
+ Arg::with_name("positional")
+ .index(1)
+ .possible_value("test123"),
+ )
+ .get_matches_from_safe(vec!["myprog", "test123"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("positional"));
+ assert_eq!(m.value_of("positional"), Some("test123"));
+}
+
+#[test]
+fn possible_values_of_positional_fail() {
+ let m = App::new("possible_values")
+ .arg(
+ Arg::with_name("positional")
+ .index(1)
+ .possible_value("test123"),
+ )
+ .get_matches_from_safe(vec!["myprog", "notest"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidValue);
+}
+
+#[test]
+fn possible_values_of_positional_multiple() {
+ let m = App::new("possible_values")
+ .arg(
+ Arg::with_name("positional")
+ .index(1)
+ .possible_value("test123")
+ .possible_value("test321")
+ .multiple(true),
+ )
+ .get_matches_from_safe(vec!["myprog", "test123", "test321"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("positional"));
+ assert_eq!(
+ m.values_of("positional").unwrap().collect::<Vec<_>>(),
+ vec!["test123", "test321"]
+ );
+}
+
+#[test]
+fn possible_values_of_positional_multiple_fail() {
+ let m = App::new("possible_values")
+ .arg(
+ Arg::with_name("positional")
+ .index(1)
+ .possible_value("test123")
+ .possible_value("test321")
+ .multiple(true),
+ )
+ .get_matches_from_safe(vec!["myprog", "test123", "notest"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidValue);
+}
+
+#[test]
+fn possible_values_of_option() {
+ let m = App::new("possible_values")
+ .arg(
+ Arg::with_name("option")
+ .short("-o")
+ .long("--option")
+ .takes_value(true)
+ .possible_value("test123"),
+ )
+ .get_matches_from_safe(vec!["myprog", "--option", "test123"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(m.value_of("option"), Some("test123"));
+}
+
+#[test]
+fn possible_values_of_option_fail() {
+ let m = App::new("possible_values")
+ .arg(
+ Arg::with_name("option")
+ .short("-o")
+ .long("--option")
+ .takes_value(true)
+ .possible_value("test123"),
+ )
+ .get_matches_from_safe(vec!["myprog", "--option", "notest"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidValue);
+}
+
+#[test]
+fn possible_values_of_option_multiple() {
+ let m = App::new("possible_values")
+ .arg(
+ Arg::with_name("option")
+ .short("-o")
+ .long("--option")
+ .takes_value(true)
+ .possible_value("test123")
+ .possible_value("test321")
+ .multiple(true),
+ )
+ .get_matches_from_safe(vec!["", "--option", "test123", "--option", "test321"]);
+
+ assert!(m.is_ok());
+ let m = m.unwrap();
+
+ assert!(m.is_present("option"));
+ assert_eq!(
+ m.values_of("option").unwrap().collect::<Vec<_>>(),
+ vec!["test123", "test321"]
+ );
+}
+
+#[test]
+fn possible_values_of_option_multiple_fail() {
+ let m = App::new("possible_values")
+ .arg(
+ Arg::with_name("option")
+ .short("-o")
+ .long("--option")
+ .takes_value(true)
+ .possible_value("test123")
+ .possible_value("test321")
+ .multiple(true),
+ )
+ .get_matches_from_safe(vec!["", "--option", "test123", "--option", "notest"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidValue);
+}
+
+#[test]
+fn possible_values_output() {
+ assert!(test::compare_output(
+ test::complex_app(),
+ "clap-test -O slo",
+ PV_ERROR,
+ true
+ ));
+}
+
+#[test]
+fn case_insensitive() {
+ let m = App::new("pv")
+ .arg(
+ Arg::with_name("option")
+ .short("-o")
+ .long("--option")
+ .takes_value(true)
+ .possible_value("test123")
+ .possible_value("test321")
+ .case_insensitive(true),
+ )
+ .get_matches_from_safe(vec!["pv", "--option", "TeSt123"]);
+
+ assert!(m.is_ok());
+ assert!(
+ m.unwrap()
+ .value_of("option")
+ .unwrap()
+ .eq_ignore_ascii_case("test123")
+ );
+}
+
+#[test]
+fn case_insensitive_faili() {
+ let m = App::new("pv")
+ .arg(
+ Arg::with_name("option")
+ .short("-o")
+ .long("--option")
+ .takes_value(true)
+ .possible_value("test123")
+ .possible_value("test321"),
+ )
+ .get_matches_from_safe(vec!["pv", "--option", "TeSt123"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidValue);
+}
+
+#[test]
+fn case_insensitive_multiple() {
+ let m = App::new("pv")
+ .arg(
+ Arg::with_name("option")
+ .short("-o")
+ .long("--option")
+ .takes_value(true)
+ .possible_value("test123")
+ .possible_value("test321")
+ .multiple(true)
+ .case_insensitive(true),
+ )
+ .get_matches_from_safe(vec!["pv", "--option", "TeSt123", "teST123", "tESt321"]);
+
+ assert!(m.is_ok());
+ assert_eq!(
+ m.unwrap().values_of("option").unwrap().collect::<Vec<_>>(),
+ &["TeSt123", "teST123", "tESt321"]
+ );
+}
+
+#[test]
+fn case_insensitive_multiple_fail() {
+ let m = App::new("pv")
+ .arg(
+ Arg::with_name("option")
+ .short("-o")
+ .long("--option")
+ .takes_value(true)
+ .possible_value("test123")
+ .possible_value("test321")
+ .multiple(true),
+ )
+ .get_matches_from_safe(vec!["pv", "--option", "test123", "teST123", "test321"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidValue);
+}
diff --git a/clap/tests/propagate_globals.rs b/clap/tests/propagate_globals.rs
new file mode 100644
index 0000000..ee77ce0
--- /dev/null
+++ b/clap/tests/propagate_globals.rs
@@ -0,0 +1,148 @@
+extern crate clap;
+extern crate regex;
+
+#[cfg(test)]
+mod tests {
+ include!("../clap-test.rs");
+ use clap::{App, Arg, SubCommand, ArgMatches};
+
+ 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")))
+ }
+
+ fn get_matches(app: App<'static, 'static>, argv: &'static str) -> ArgMatches<'static> {
+ app.get_matches_from(argv.split(' ').collect::<Vec<_>>())
+ }
+
+ fn get_outer_matches<'a>(m: &'a ArgMatches<'static>) -> &'a ArgMatches<'static> {
+ m.subcommand_matches("outer").expect("could not access outer subcommand")
+ }
+
+ fn get_inner_matches<'a>(m: &'a ArgMatches<'static>) -> &'a ArgMatches<'static> {
+ get_outer_matches(m).subcommand_matches("inner").expect("could not access inner subcommand")
+ }
+
+ fn top_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
+ m.value_of("GLOBAL_ARG") == val.into()
+ }
+
+ fn inner_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
+ get_inner_matches(m).value_of("GLOBAL_ARG") == val.into()
+ }
+
+ fn outer_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
+ get_outer_matches(m).value_of("GLOBAL_ARG") == val.into()
+ }
+
+ fn top_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
+ (m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
+ }
+
+ fn inner_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
+ let m = get_inner_matches(m);
+ (m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
+ }
+
+ fn outer_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
+ let m = get_outer_matches(m);
+ (m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
+ }
+
+ #[test]
+ fn global_arg_used_top_level() {
+ let m = get_matches(get_app(), "myprog --global-arg=some_value outer inner");
+
+ assert!(top_can_access_arg(&m, "some_value"));
+ assert!(inner_can_access_arg(&m, "some_value"));
+ assert!(outer_can_access_arg(&m, "some_value"));
+ }
+
+ #[test]
+ fn global_arg_used_outer() {
+ let m = get_matches(get_app(), "myprog outer --global-arg=some_value inner");
+
+ assert!(top_can_access_arg(&m, "some_value"));
+ assert!(inner_can_access_arg(&m, "some_value"));
+ assert!(outer_can_access_arg(&m, "some_value"));
+ }
+
+ #[test]
+ fn global_arg_used_inner() {
+ let m = get_matches(get_app(), "myprog outer inner --global-arg=some_value");
+
+ assert!(top_can_access_arg(&m, "some_value"));
+ assert!(inner_can_access_arg(&m, "some_value"));
+ assert!(outer_can_access_arg(&m, "some_value"));
+ }
+
+ #[test]
+ fn global_arg_default_value() {
+ let m = get_matches(get_app(), "myprog outer inner");
+
+ assert!(top_can_access_arg(&m, "default_value"));
+ assert!(inner_can_access_arg(&m, "default_value"));
+ assert!(outer_can_access_arg(&m, "default_value"));
+ }
+
+ #[test]
+ fn global_flag_used_top_level() {
+ let m = get_matches(get_app(), "myprog --global-flag outer inner");
+
+ assert!(top_can_access_flag(&m, true, 1));
+ assert!(inner_can_access_flag(&m, true, 1));
+ assert!(outer_can_access_flag(&m, true, 1));
+ }
+
+ #[test]
+ fn global_flag_used_outer() {
+ let m = get_matches(get_app(), "myprog outer --global-flag inner");
+
+ assert!(top_can_access_flag(&m, true, 1));
+ assert!(inner_can_access_flag(&m, true, 1));
+ assert!(outer_can_access_flag(&m, true, 1));
+ }
+
+ #[test]
+ fn global_flag_used_inner() {
+ let m = get_matches(get_app(), "myprog outer inner --global-flag");
+
+ assert!(top_can_access_flag(&m, true, 1));
+ assert!(inner_can_access_flag(&m, true, 1));
+ assert!(outer_can_access_flag(&m, true, 1));
+ }
+
+ #[test]
+ fn global_flag_2x_used_top_level() {
+ let m = get_matches(get_app(), "myprog --global-flag --global-flag outer inner");
+
+ assert!(top_can_access_flag(&m, true, 2));
+ assert!(inner_can_access_flag(&m, true, 2));
+ assert!(outer_can_access_flag(&m, true, 2));
+ }
+
+ #[test]
+ fn global_flag_2x_used_inner() {
+ let m = get_matches(get_app(), "myprog outer inner --global-flag --global-flag");
+
+ assert!(top_can_access_flag(&m, true, 2));
+ assert!(inner_can_access_flag(&m, true, 2));
+ assert!(outer_can_access_flag(&m, true, 2));
+ }
+}
diff --git a/clap/tests/require.rs b/clap/tests/require.rs
new file mode 100644
index 0000000..7121aa5
--- /dev/null
+++ b/clap/tests/require.rs
@@ -0,0 +1,688 @@
+extern crate clap;
+extern crate regex;
+
+include!("../clap-test.rs");
+
+use clap::{App, Arg, ErrorKind, ArgGroup};
+
+static REQUIRE_EQUALS: &'static str = "error: The following required arguments were not provided:
+ --opt=<FILE>
+
+USAGE:
+ clap-test --opt=<FILE>
+
+For more information try --help";
+
+static MISSING_REQ: &'static str = "error: The following required arguments were not provided:
+ <positional2>
+ --long-option-2 <option2>
+
+USAGE:
+ clap-test <positional2> -F --long-option-2 <option2>
+
+For more information try --help";
+
+static COND_REQ_IN_USAGE: &'static str = "error: The following required arguments were not provided:
+ --output <output>
+
+USAGE:
+ test --input <input> --output <output> --target <target>
+
+For more information try --help";
+
+static ISSUE_1158: &'static str = "error: The following required arguments were not provided:
+ -x <X>
+ -y <Y>
+ -z <Z>
+
+USAGE:
+ example [OPTIONS] <ID> -x <X> -y <Y> -z <Z>
+
+For more information try --help";
+
+#[test]
+fn issue_1158_conflicting_requirements() {
+ let app = App::new("example")
+ .arg(Arg::from_usage("-c, --config [FILE] 'Custom config file.'")
+ .required_unless("ID")
+ .conflicts_with("ID"))
+ .arg(Arg::from_usage("[ID] 'ID'")
+ .required_unless("config")
+ .conflicts_with("config")
+ .requires_all(&["x", "y", "z"]))
+ .arg(Arg::from_usage("-x [X] 'X'"))
+ .arg(Arg::from_usage("-y [Y] 'Y'"))
+ .arg(Arg::from_usage("-z [Z] 'Z'"));
+
+ assert!(test::compare_output(app, "example id", ISSUE_1158, true));
+}
+
+#[test]
+fn issue_1158_conflicting_requirements_rev() {
+ let res = App::new("example")
+ .arg(Arg::from_usage("-c, --config [FILE] 'Custom config file.'")
+ .required_unless("ID")
+ .conflicts_with("ID"))
+ .arg(Arg::from_usage("[ID] 'ID'")
+ .required_unless("config")
+ .conflicts_with("config")
+ .requires_all(&["x", "y", "z"]))
+ .arg(Arg::from_usage("-x [X] 'X'"))
+ .arg(Arg::from_usage("-y [Y] 'Y'"))
+ .arg(Arg::from_usage("-z [Z] 'Z'"))
+ .get_matches_from_safe(vec!["example", "--config", "some"]);
+
+ assert!(res.is_ok());
+}
+
+#[test]
+fn flag_required() {
+ let result = App::new("flag_required")
+ .arg(Arg::from_usage("-f, --flag 'some flag'").requires("color"))
+ .arg(Arg::from_usage("-c, --color 'third flag'"))
+ .get_matches_from_safe(vec!["", "-f"]);
+ assert!(result.is_err());
+ let err = result.err().unwrap();
+ assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn flag_required_2() {
+ let m = App::new("flag_required")
+ .arg(Arg::from_usage("-f, --flag 'some flag'").requires("color"))
+ .arg(Arg::from_usage("-c, --color 'third flag'"))
+ .get_matches_from(vec!["", "-f", "-c"]);
+ assert!(m.is_present("color"));
+ assert!(m.is_present("flag"));
+}
+
+#[test]
+fn option_required() {
+ let result = App::new("option_required")
+ .arg(Arg::from_usage("-f [flag] 'some flag'").requires("c"))
+ .arg(Arg::from_usage("-c [color] 'third flag'"))
+ .get_matches_from_safe(vec!["", "-f", "val"]);
+ assert!(result.is_err());
+ let err = result.err().unwrap();
+ assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn option_required_2() {
+ let m = App::new("option_required")
+ .arg(Arg::from_usage("-f [flag] 'some flag'").requires("c"))
+ .arg(Arg::from_usage("-c [color] 'third flag'"))
+ .get_matches_from(vec!["", "-f", "val", "-c", "other_val"]);
+ assert!(m.is_present("c"));
+ assert_eq!(m.value_of("c").unwrap(), "other_val");
+ assert!(m.is_present("f"));
+ assert_eq!(m.value_of("f").unwrap(), "val");
+}
+
+#[test]
+fn positional_required() {
+ let result = App::new("positional_required")
+ .arg(Arg::with_name("flag")
+ .index(1)
+ .required(true))
+ .get_matches_from_safe(vec![""]);
+ assert!(result.is_err());
+ let err = result.err().unwrap();
+ assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn positional_required_2() {
+ let m = App::new("positional_required")
+ .arg(Arg::with_name("flag")
+ .index(1)
+ .required(true))
+ .get_matches_from(vec!["", "someval"]);
+ assert!(m.is_present("flag"));
+ assert_eq!(m.value_of("flag").unwrap(), "someval");
+}
+
+#[test]
+fn group_required() {
+ let result = App::new("group_required")
+ .arg(Arg::from_usage("-f, --flag 'some flag'"))
+ .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!["", "-f"]);
+ assert!(result.is_err());
+ let err = result.err().unwrap();
+ assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn group_required_2() {
+ let m = App::new("group_required")
+ .arg(Arg::from_usage("-f, --flag 'some flag'"))
+ .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(vec!["", "-f", "--some"]);
+ assert!(m.is_present("some"));
+ assert!(!m.is_present("other"));
+ assert!(m.is_present("flag"));
+}
+
+#[test]
+fn group_required_3() {
+ let m = App::new("group_required")
+ .arg(Arg::from_usage("-f, --flag 'some flag'"))
+ .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(vec!["", "-f", "--other"]);
+ assert!(!m.is_present("some"));
+ assert!(m.is_present("other"));
+ assert!(m.is_present("flag"));
+}
+
+#[test]
+fn arg_require_group() {
+ let result = App::new("arg_require_group")
+ .arg(Arg::from_usage("-f, --flag 'some flag'").requires("gr"))
+ .group(ArgGroup::with_name("gr")
+ .arg("some")
+ .arg("other"))
+ .arg(Arg::from_usage("--some 'some arg'"))
+ .arg(Arg::from_usage("--other 'other arg'"))
+ .get_matches_from_safe(vec!["", "-f"]);
+ assert!(result.is_err());
+ let err = result.err().unwrap();
+ assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn arg_require_group_2() {
+ let m = App::new("arg_require_group")
+ .arg(Arg::from_usage("-f, --flag 'some flag'").requires("gr"))
+ .group(ArgGroup::with_name("gr")
+ .arg("some")
+ .arg("other"))
+ .arg(Arg::from_usage("--some 'some arg'"))
+ .arg(Arg::from_usage("--other 'other arg'"))
+ .get_matches_from(vec!["", "-f", "--some"]);
+ assert!(m.is_present("some"));
+ assert!(!m.is_present("other"));
+ assert!(m.is_present("flag"));
+}
+
+#[test]
+fn arg_require_group_3() {
+ let m = App::new("arg_require_group")
+ .arg(Arg::from_usage("-f, --flag 'some flag'").requires("gr"))
+ .group(ArgGroup::with_name("gr")
+ .arg("some")
+ .arg("other"))
+ .arg(Arg::from_usage("--some 'some arg'"))
+ .arg(Arg::from_usage("--other 'other arg'"))
+ .get_matches_from(vec!["", "-f", "--other"]);
+ assert!(!m.is_present("some"));
+ assert!(m.is_present("other"));
+ assert!(m.is_present("flag"));
+}
+
+// REQUIRED_UNLESS
+
+#[test]
+fn issue_753() {
+ let m = App::new("test")
+ .arg(Arg::from_usage("-l, --list 'List available interfaces (and stop there)'"))
+ .arg(Arg::from_usage("-i, --iface=[INTERFACE] 'Ethernet interface for fetching NTP packets'")
+ .required_unless("list"))
+ .arg(Arg::from_usage("-f, --file=[TESTFILE] 'Fetch NTP packets from pcap file'")
+ .conflicts_with("iface")
+ .required_unless("list"))
+ .arg(Arg::from_usage("-s, --server=[SERVER_IP] 'NTP server IP address'")
+ .required_unless("list"))
+ .arg(Arg::from_usage("-p, --port=[SERVER_PORT] 'NTP server port'")
+ .default_value("123"))
+ .get_matches_from_safe(vec!["test", "--list"]);
+ assert!(m.is_ok());
+}
+
+#[test]
+fn required_unless() {
+ let res = App::new("unlesstest")
+ .arg(Arg::with_name("cfg")
+ .required_unless("dbg")
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("dbg").long("debug"))
+ .get_matches_from_safe(vec!["unlesstest", "--debug"]);
+
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("dbg"));
+ assert!(!m.is_present("cfg"));
+}
+
+#[test]
+fn required_unless_err() {
+ let res = App::new("unlesstest")
+ .arg(Arg::with_name("cfg")
+ .required_unless("dbg")
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("dbg").long("debug"))
+ .get_matches_from_safe(vec!["unlesstest"]);
+
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+// REQUIRED_UNLESS_ALL
+
+#[test]
+fn required_unless_all() {
+ let res = App::new("unlessall")
+ .arg(Arg::with_name("cfg")
+ .required_unless_all(&["dbg", "infile"])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("dbg").long("debug"))
+ .arg(Arg::with_name("infile")
+ .short("i")
+ .takes_value(true))
+ .get_matches_from_safe(vec!["unlessall", "--debug", "-i", "file"]);
+
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("dbg"));
+ assert!(m.is_present("infile"));
+ assert!(!m.is_present("cfg"));
+}
+
+#[test]
+fn required_unless_all_err() {
+ let res = App::new("unlessall")
+ .arg(Arg::with_name("cfg")
+ .required_unless_all(&["dbg", "infile"])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("dbg").long("debug"))
+ .arg(Arg::with_name("infile")
+ .short("i")
+ .takes_value(true))
+ .get_matches_from_safe(vec!["unlessall", "--debug"]);
+
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+// REQUIRED_UNLESS_ONE
+
+#[test]
+fn required_unless_one() {
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("cfg")
+ .required_unless_one(&["dbg", "infile"])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("dbg").long("debug"))
+ .arg(Arg::with_name("infile")
+ .short("i")
+ .takes_value(true))
+ .get_matches_from_safe(vec!["unlessone", "--debug"]);
+
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("dbg"));
+ assert!(!m.is_present("cfg"));
+}
+
+#[test]
+fn required_unless_one_2() {
+ // This tests that the required_unless_one works when the second arg in the array is used
+ // instead of the first.
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("cfg")
+ .required_unless_one(&["dbg", "infile"])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("dbg").long("debug"))
+ .arg(Arg::with_name("infile")
+ .short("i")
+ .takes_value(true))
+ .get_matches_from_safe(vec!["unlessone", "-i", "file"]);
+
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(m.is_present("infile"));
+ assert!(!m.is_present("cfg"));
+}
+
+#[test]
+fn required_unless_one_works_with_short() {
+ // GitHub issue: https://github.com/clap-rs/clap/issues/1135
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("a").conflicts_with("b").short("a"))
+ .arg(Arg::with_name("b").short("b"))
+ .arg(
+ Arg::with_name("x")
+ .short("x")
+ .required_unless_one(&["a", "b"])
+ ).get_matches_from_safe(vec!["unlessone", "-a"]);
+
+ assert!(res.is_ok());
+}
+
+#[test]
+fn required_unless_one_works_with_short_err() {
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("a").conflicts_with("b").short("a"))
+ .arg(Arg::with_name("b").short("b"))
+ .arg(
+ Arg::with_name("x")
+ .short("x")
+ .required_unless_one(&["a", "b"])
+ ).get_matches_from_safe(vec!["unlessone"]);
+
+ assert!(!res.is_ok());
+}
+
+#[test]
+fn required_unless_one_works_without() {
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("a").conflicts_with("b").short("a"))
+ .arg(Arg::with_name("b").short("b"))
+ .arg(
+ Arg::with_name("x")
+ .required_unless_one(&["a", "b"])
+ ).get_matches_from_safe(vec!["unlessone", "-a"]);
+
+ assert!(res.is_ok());
+}
+
+#[test]
+fn required_unless_one_works_with_long() {
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("a").conflicts_with("b").short("a"))
+ .arg(Arg::with_name("b").short("b"))
+ .arg(
+ Arg::with_name("x")
+ .long("x_is_the_option")
+ .required_unless_one(&["a", "b"])
+ ).get_matches_from_safe(vec!["unlessone", "-a"]);
+
+ assert!(res.is_ok());
+}
+
+#[test]
+fn required_unless_one_1() {
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("cfg")
+ .required_unless_one(&["dbg", "infile"])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("dbg").long("debug"))
+ .arg(Arg::with_name("infile")
+ .short("i")
+ .takes_value(true))
+ .get_matches_from_safe(vec!["unlessone", "--debug"]);
+
+ assert!(res.is_ok());
+ let m = res.unwrap();
+ assert!(!m.is_present("infile"));
+ assert!(!m.is_present("cfg"));
+ assert!(m.is_present("dbg"));
+}
+
+#[test]
+fn required_unless_one_err() {
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("cfg")
+ .required_unless_one(&["dbg", "infile"])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("dbg").long("debug"))
+ .arg(Arg::with_name("infile")
+ .short("i")
+ .takes_value(true))
+ .get_matches_from_safe(vec!["unlessone"]);
+
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn missing_required_output() {
+ assert!(test::compare_output(test::complex_app(), "clap-test -F", MISSING_REQ, true));
+}
+
+// Conditional external requirements
+
+#[test]
+fn requires_if_present_val() {
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("cfg")
+ .requires_if("my.cfg", "extra")
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("extra").long("extra"))
+ .get_matches_from_safe(vec!["unlessone", "--config=my.cfg"]);
+
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn requires_if_present_mult() {
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("cfg")
+ .requires_ifs(&[("my.cfg", "extra"), ("other.cfg", "other")])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("extra").long("extra"))
+ .arg(Arg::with_name("other").long("other"))
+ .get_matches_from_safe(vec!["unlessone", "--config=other.cfg"]);
+
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn requires_if_present_mult_pass() {
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("cfg")
+ .requires_ifs(&[("my.cfg", "extra"), ("other.cfg", "other")])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("extra").long("extra"))
+ .arg(Arg::with_name("other").long("other"))
+ .get_matches_from_safe(vec!["unlessone", "--config=some.cfg"]);
+
+ assert!(res.is_ok());
+ // assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn requires_if_present_val_no_present_pass() {
+ let res = App::new("unlessone")
+ .arg(Arg::with_name("cfg")
+ .requires_if("my.cfg", "extra")
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("extra").long("extra"))
+ .get_matches_from_safe(vec!["unlessone"]);
+
+ assert!(res.is_ok());
+}
+
+// Conditionally required
+
+#[test]
+fn required_if_val_present_pass() {
+ let res = App::new("ri")
+ .arg(Arg::with_name("cfg")
+ .required_if("extra", "val")
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("extra")
+ .takes_value(true)
+ .long("extra"))
+ .get_matches_from_safe(vec!["ri", "--extra", "val", "--config", "my.cfg"]);
+
+ assert!(res.is_ok());
+}
+
+#[test]
+fn required_if_val_present_fail() {
+ let res = App::new("ri")
+ .arg(Arg::with_name("cfg")
+ .required_if("extra", "val")
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("extra")
+ .takes_value(true)
+ .long("extra"))
+ .get_matches_from_safe(vec!["ri", "--extra", "val"]);
+
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn required_if_val_present_fail_error_output() {
+ let app = App::new("Test app")
+ .version("1.0")
+ .author("F0x06")
+ .about("Arg test")
+ .arg(Arg::with_name("target")
+ .takes_value(true)
+ .required(true)
+ .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"));
+
+ assert!(test::compare_output(app,
+ "test --input somepath --target file",
+ COND_REQ_IN_USAGE,
+ true));
+}
+
+#[test]
+fn required_if_wrong_val() {
+ let res = App::new("ri")
+ .arg(Arg::with_name("cfg")
+ .required_if("extra", "val")
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("extra")
+ .takes_value(true)
+ .long("extra"))
+ .get_matches_from_safe(vec!["ri", "--extra", "other"]);
+
+ assert!(res.is_ok());
+}
+
+#[test]
+fn required_ifs_val_present_pass() {
+ let res = App::new("ri")
+ .arg(Arg::with_name("cfg")
+ .required_ifs(&[("extra", "val"), ("option", "spec")])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("option")
+ .takes_value(true)
+ .long("option"))
+ .arg(Arg::with_name("extra")
+ .takes_value(true)
+ .long("extra"))
+ .get_matches_from_safe(vec!["ri", "--option", "spec", "--config", "my.cfg"]);
+
+ assert!(res.is_ok());
+ // assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn required_ifs_val_present_fail() {
+ let res = App::new("ri")
+ .arg(Arg::with_name("cfg")
+ .required_ifs(&[("extra", "val"), ("option", "spec")])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("extra")
+ .takes_value(true)
+ .long("extra"))
+ .arg(Arg::with_name("option")
+ .takes_value(true)
+ .long("option"))
+ .get_matches_from_safe(vec!["ri", "--option", "spec"]);
+
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[test]
+fn required_ifs_wrong_val() {
+ let res = App::new("ri")
+ .arg(Arg::with_name("cfg")
+ .required_ifs(&[("extra", "val"), ("option", "spec")])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("extra")
+ .takes_value(true)
+ .long("extra"))
+ .arg(Arg::with_name("option")
+ .takes_value(true)
+ .long("option"))
+ .get_matches_from_safe(vec!["ri", "--option", "other"]);
+
+ assert!(res.is_ok());
+}
+
+#[test]
+fn required_ifs_wrong_val_mult_fail() {
+ let res = App::new("ri")
+ .arg(Arg::with_name("cfg")
+ .required_ifs(&[("extra", "val"), ("option", "spec")])
+ .takes_value(true)
+ .long("config"))
+ .arg(Arg::with_name("extra")
+ .takes_value(true)
+ .long("extra"))
+ .arg(Arg::with_name("option")
+ .takes_value(true)
+ .long("option"))
+ .get_matches_from_safe(vec!["ri", "--extra", "other", "--option", "spec"]);
+
+ assert!(res.is_err());
+ assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
+}
+
+#[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", REQUIRE_EQUALS, true));
+}
diff --git a/clap/tests/subcommands.rs b/clap/tests/subcommands.rs
new file mode 100644
index 0000000..6257aaf
--- /dev/null
+++ b/clap/tests/subcommands.rs
@@ -0,0 +1,216 @@
+extern crate clap;
+extern crate regex;
+
+include!("../clap-test.rs");
+
+use clap::{App, Arg, SubCommand, ErrorKind};
+
+static VISIBLE_ALIAS_HELP: &'static str = "clap-test 2.6
+
+USAGE:
+ clap-test [SUBCOMMAND]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+SUBCOMMANDS:
+ help Prints this message or the help of the given subcommand(s)
+ test Some help [aliases: dongle, done]";
+
+static INVISIBLE_ALIAS_HELP: &'static str = "clap-test 2.6
+
+USAGE:
+ clap-test [SUBCOMMAND]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+SUBCOMMANDS:
+ help Prints this message or the help of the given subcommand(s)
+ test Some help";
+
+#[cfg(feature = "suggestions")]
+static DYM_SUBCMD: &'static str = "error: The subcommand 'subcm' wasn't recognized
+ Did you mean 'subcmd'?
+
+If you believe you received this message in error, try re-running with 'dym -- subcm'
+
+USAGE:
+ dym [SUBCOMMAND]
+
+For more information try --help";
+
+#[test]
+fn subcommand() {
+ let m = App::new("test")
+ .subcommand(SubCommand::with_name("some")
+ .arg(Arg::with_name("test")
+ .short("t")
+ .long("test")
+ .takes_value(true)
+ .help("testing testing")))
+ .arg(Arg::with_name("other").long("other"))
+ .get_matches_from(vec!["myprog", "some", "--test", "testing"]);
+
+ assert_eq!(m.subcommand_name().unwrap(), "some");
+ let sub_m = m.subcommand_matches("some").unwrap();
+ assert!(sub_m.is_present("test"));
+ assert_eq!(sub_m.value_of("test").unwrap(), "testing");
+}
+
+#[test]
+fn subcommand_none_given() {
+ let m = App::new("test")
+ .subcommand(SubCommand::with_name("some")
+ .arg(Arg::with_name("test")
+ .short("t")
+ .long("test")
+ .takes_value(true)
+ .help("testing testing")))
+ .arg(Arg::with_name("other").long("other"))
+ .get_matches_from(vec![""]);
+
+ assert!(m.subcommand_name().is_none());
+}
+
+#[test]
+fn subcommand_multiple() {
+ let m = App::new("test")
+ .subcommands(vec![
+ SubCommand::with_name("some")
+ .arg(Arg::with_name("test")
+ .short("t")
+ .long("test")
+ .takes_value(true)
+ .help("testing testing")),
+ SubCommand::with_name("add")
+ .arg(Arg::with_name("roster").short("r"))
+ ])
+ .arg(Arg::with_name("other").long("other"))
+ .get_matches_from(vec!["myprog", "some", "--test", "testing"]);
+
+ assert!(m.subcommand_matches("some").is_some());
+ assert!(m.subcommand_matches("add").is_none());
+ assert_eq!(m.subcommand_name().unwrap(), "some");
+ let sub_m = m.subcommand_matches("some").unwrap();
+ assert!(sub_m.is_present("test"));
+ assert_eq!(sub_m.value_of("test").unwrap(), "testing");
+}
+
+#[test]
+fn single_alias() {
+ let m = App::new("myprog")
+ .subcommand(SubCommand::with_name("test")
+ .alias("do-stuff"))
+ .get_matches_from(vec!["myprog", "do-stuff"]);
+ assert_eq!(m.subcommand_name(), Some("test"));
+}
+
+#[test]
+fn multiple_aliases() {
+ let m = App::new("myprog")
+ .subcommand(SubCommand::with_name("test")
+ .aliases(&["do-stuff", "test-stuff"]))
+ .get_matches_from(vec!["myprog", "test-stuff"]);
+ assert_eq!(m.subcommand_name(), Some("test"));
+}
+
+#[test]
+#[cfg(feature="suggestions")]
+fn subcmd_did_you_mean_output() {
+ let app = App::new("dym")
+ .subcommand(SubCommand::with_name("subcmd"));
+ assert!(test::compare_output(app, "dym subcm", DYM_SUBCMD, true));
+}
+
+#[test]
+#[cfg(feature="suggestions")]
+fn subcmd_did_you_mean_output_arg() {
+ static EXPECTED: &'static str = "error: Found argument '--subcmarg' which wasn't expected, or isn't valid in this context
+\tDid you mean to put '--subcmdarg' after the subcommand 'subcmd'?
+
+USAGE:
+ dym [SUBCOMMAND]
+
+For more information try --help";
+
+ let app = App::new("dym")
+ .subcommand(SubCommand::with_name("subcmd")
+ .arg_from_usage("-s --subcmdarg [subcmdarg] 'tests'") );
+ assert!(test::compare_output(app, "dym --subcmarg subcmd", EXPECTED, true));
+}
+
+#[test]
+#[cfg(feature="suggestions")]
+fn subcmd_did_you_mean_output_arg_false_positives() {
+ static EXPECTED: &'static str = "error: Found argument '--subcmarg' which wasn't expected, or isn't valid in this context
+
+USAGE:
+ dym [SUBCOMMAND]
+
+For more information try --help";
+
+ let app = App::new("dym")
+ .subcommand(SubCommand::with_name("subcmd")
+ .arg_from_usage("-s --subcmdarg [subcmdarg] 'tests'") );
+ assert!(test::compare_output(app, "dym --subcmarg foo", EXPECTED, true));
+}
+
+#[test]
+fn alias_help() {
+ let m = App::new("myprog")
+ .subcommand(SubCommand::with_name("test")
+ .alias("do-stuff"))
+ .get_matches_from_safe(vec!["myprog", "help", "do-stuff"]);
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
+}
+
+#[test]
+fn visible_aliases_help_output() {
+ let app = App::new("clap-test")
+ .version("2.6")
+ .subcommand(SubCommand::with_name("test")
+ .about("Some help")
+ .alias("invisible")
+ .visible_alias("dongle")
+ .visible_alias("done"));
+ assert!(test::compare_output(app, "clap-test --help", VISIBLE_ALIAS_HELP, false));
+}
+
+#[test]
+fn invisible_aliases_help_output() {
+ let app = App::new("clap-test")
+ .version("2.6")
+ .subcommand(SubCommand::with_name("test")
+ .about("Some help")
+ .alias("invisible"));
+ assert!(test::compare_output(app, "clap-test --help", INVISIBLE_ALIAS_HELP, false));
+}
+
+#[test]
+fn issue_1031_args_with_same_name() {
+ let res = App::new("prog")
+ .arg(Arg::from_usage("--ui-path=<PATH>"))
+ .subcommand(SubCommand::with_name("signer"))
+ .get_matches_from_safe(vec!["prog", "--ui-path", "signer"]);
+
+ assert!(res.is_ok(), "{:?}", res.unwrap_err().kind);
+ let m = res.unwrap();
+ assert_eq!(m.value_of("ui-path"), Some("signer"));
+}
+
+#[test]
+fn issue_1031_args_with_same_name_no_more_vals() {
+ let res = App::new("prog")
+ .arg(Arg::from_usage("--ui-path=<PATH>"))
+ .subcommand(SubCommand::with_name("signer"))
+ .get_matches_from_safe(vec!["prog", "--ui-path", "value", "signer"]);
+
+ assert!(res.is_ok(), "{:?}", res.unwrap_err().kind);
+ let m = res.unwrap();
+ assert_eq!(m.value_of("ui-path"), Some("value"));
+ assert_eq!(m.subcommand_name(), Some("signer"));
+}
diff --git a/clap/tests/template_help.rs b/clap/tests/template_help.rs
new file mode 100644
index 0000000..b1a546a
--- /dev/null
+++ b/clap/tests/template_help.rs
@@ -0,0 +1,117 @@
+extern crate clap;
+extern crate regex;
+
+use clap::{App, SubCommand};
+
+include!("../clap-test.rs");
+
+static EXAMPLE1_TMPL_S : &'static str = include_str!("example1_tmpl_simple.txt");
+static EXAMPLE1_TMPS_F : &'static str = include_str!("example1_tmpl_full.txt");
+
+static CUSTOM_TEMPL_HELP: &'static str = "MyApp 1.0
+Kevin K. <kbknapp@gmail.com>
+Does awesome things
+
+USAGE:
+ MyApp [FLAGS] [OPTIONS] <output> [SUBCOMMAND]
+
+FLAGS:
+ -d Turn debugging information on
+ -h, --help Prints help information
+ -V, --version Prints version information
+OPTIONS:
+ -c, --config <FILE> Sets a custom config file
+ARGS:
+ <output> Sets an optional output file
+SUBCOMMANDS:
+ help Prints this message or the help of the given subcommand(s)
+ test does testing things";
+
+static SIMPLE_TEMPLATE: &'static str = "MyApp 1.0
+Kevin K. <kbknapp@gmail.com>
+Does awesome things
+
+USAGE:
+ MyApp [FLAGS] [OPTIONS] <output> [SUBCOMMAND]
+
+FLAGS:
+ -d Turn debugging information on
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -c, --config <FILE> Sets a custom config file
+
+ARGS:
+ <output> Sets an optional output file
+
+SUBCOMMANDS:
+ help Prints this message or the help of the given subcommand(s)
+ test does testing things";
+
+#[test]
+fn with_template() {
+ let app = app_example1().template(EXAMPLE1_TMPL_S);
+ assert!(test::compare_output(app, "MyApp --help", SIMPLE_TEMPLATE, false));
+}
+
+#[test]
+fn custom_template() {
+ let app = app_example1().template(EXAMPLE1_TMPS_F);
+ assert!(test::compare_output(app, "MyApp --help", CUSTOM_TEMPL_HELP, false));
+}
+
+#[test]
+fn template_empty() {
+ let app = App::new("MyApp")
+ .version("1.0")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .about("Does awesome things")
+ .template("");
+ assert!(test::compare_output(app, "MyApp --help", "", false));
+}
+
+#[test]
+fn template_notag() {
+ let app = App::new("MyApp")
+ .version("1.0")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .about("Does awesome things")
+ .template("test no tag test");
+ assert!(test::compare_output(app, "MyApp --help", "test no tag test", false));
+}
+
+#[test]
+fn template_unknowntag() {
+ let app = App::new("MyApp")
+ .version("1.0")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .about("Does awesome things")
+ .template("test {unknown_tag} test");
+ assert!(test::compare_output(app, "MyApp --help", "test {unknown_tag} test", false));
+}
+
+#[test]
+fn template_author_version() {
+ let app = App::new("MyApp")
+ .version("1.0")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .about("Does awesome things")
+ .template("{author}\n{version}\n{about}\n{bin}");
+ assert!(test::compare_output(app, "MyApp --help", "Kevin K. <kbknapp@gmail.com>\n1.0\nDoes awesome things\nMyApp", false));
+}
+
+// ----------
+
+fn app_example1<'b, 'c>() -> App<'b, 'c> {
+ App::new("MyApp")
+ .version("1.0")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .about("Does awesome things")
+ .args_from_usage("-c, --config=[FILE] 'Sets a custom config file'
+ <output> 'Sets an optional output file'
+ -d... 'Turn debugging information on'")
+ .subcommand(SubCommand::with_name("test")
+ .about("does testing things")
+ .arg_from_usage("-l, --list 'lists test values'"))
+}
diff --git a/clap/tests/tests.rs b/clap/tests/tests.rs
new file mode 100644
index 0000000..0ad825a
--- /dev/null
+++ b/clap/tests/tests.rs
@@ -0,0 +1,435 @@
+#[macro_use]
+extern crate clap;
+extern crate regex;
+
+use std::io::Write;
+use std::str;
+
+include!("../clap-test.rs");
+
+use clap::{App, Arg};
+
+static SCF2OP: &'static str = "flag present 2 times
+option NOT present
+positional NOT present
+flag2 NOT present
+option2 maybe present with value of: Nothing
+positional2 maybe present with value of: Nothing
+option3 NOT present
+positional3 NOT present
+option NOT present
+positional NOT present
+subcmd present
+flag present 2 times
+scoption present with value: some
+An scoption: some
+scpositional present with value: value
+";
+
+static SCFOP: &'static str = "flag present 1 times
+option NOT present
+positional NOT present
+flag2 NOT present
+option2 maybe present with value of: Nothing
+positional2 maybe present with value of: Nothing
+option3 NOT present
+positional3 NOT present
+option NOT present
+positional NOT present
+subcmd present
+flag present 1 times
+scoption present with value: some
+An scoption: some
+scpositional present with value: value
+";
+
+static O2P: &'static str = "flag NOT present
+option present 2 times with value: some
+An option: some
+An option: other
+positional present with value: value
+flag2 NOT present
+option2 maybe present with value of: Nothing
+positional2 maybe present with value of: Nothing
+option3 NOT present
+positional3 NOT present
+option present 2 times with value: some
+An option: some
+An option: other
+positional present with value: value
+subcmd NOT present
+";
+
+static F2OP: &'static str = "flag present 2 times
+option present 1 times with value: some
+An option: some
+positional present with value: value
+flag2 NOT present
+option2 maybe present with value of: Nothing
+positional2 maybe present with value of: Nothing
+option3 NOT present
+positional3 NOT present
+option present 1 times with value: some
+An option: some
+positional present with value: value
+subcmd NOT present
+";
+
+static FOP: &'static str = "flag present 1 times
+option present 1 times with value: some
+An option: some
+positional present with value: value
+flag2 NOT present
+option2 maybe present with value of: Nothing
+positional2 maybe present with value of: Nothing
+option3 NOT present
+positional3 NOT present
+option present 1 times with value: some
+An option: some
+positional present with value: value
+subcmd NOT present
+";
+
+pub fn check_complex_output(args: &str, out: &str) {
+ let mut w = vec![];
+ let matches = test::complex_app().get_matches_from(args.split(' ').collect::<Vec<_>>());
+ if matches.is_present("flag") {
+ writeln!(w, "flag present {} times", matches.occurrences_of("flag")).unwrap();
+ } else {
+ writeln!(w, "flag NOT present").unwrap();
+ }
+
+ if matches.is_present("option") {
+ if let Some(v) = matches.value_of("option") {
+ writeln!(w, "option present {} times with value: {}",matches.occurrences_of("option"), v).unwrap();
+ }
+ if let Some(ov) = matches.values_of("option") {
+ for o in ov {
+ writeln!(w, "An option: {}", o).unwrap();
+ }
+ }
+ } else {
+ writeln!(w, "option NOT present").unwrap();
+ }
+
+ if let Some(p) = matches.value_of("positional") {
+ writeln!(w, "positional present with value: {}", p).unwrap();
+ } else {
+ writeln!(w, "positional NOT present").unwrap();
+ }
+
+ if matches.is_present("flag2") {
+ writeln!(w, "flag2 present").unwrap();
+ writeln!(w, "option2 present with value of: {}", matches.value_of("long-option-2").unwrap()).unwrap();
+ writeln!(w, "positional2 present with value of: {}", matches.value_of("positional2").unwrap()).unwrap();
+ } else {
+ writeln!(w, "flag2 NOT present").unwrap();
+ writeln!(w, "option2 maybe present with value of: {}", matches.value_of("long-option-2").unwrap_or("Nothing")).unwrap();
+ writeln!(w, "positional2 maybe present with value of: {}", matches.value_of("positional2").unwrap_or("Nothing")).unwrap();
+ }
+
+ let _ = match matches.value_of("Option3").unwrap_or("") {
+ "fast" => writeln!(w, "option3 present quickly"),
+ "slow" => writeln!(w, "option3 present slowly"),
+ _ => writeln!(w, "option3 NOT present")
+ };
+
+ let _ = match matches.value_of("positional3").unwrap_or("") {
+ "vi" => writeln!(w, "positional3 present in vi mode"),
+ "emacs" => writeln!(w, "positional3 present in emacs mode"),
+ _ => writeln!(w, "positional3 NOT present")
+ };
+
+ if matches.is_present("option") {
+ if let Some(v) = matches.value_of("option") {
+ writeln!(w, "option present {} times with value: {}",matches.occurrences_of("option"), v).unwrap();
+ }
+ if let Some(ov) = matches.values_of("option") {
+ for o in ov {
+ writeln!(w, "An option: {}", o).unwrap();
+ }
+ }
+ } else {
+ writeln!(w, "option NOT present").unwrap();
+ }
+
+ if let Some(p) = matches.value_of("positional") {
+ writeln!(w, "positional present with value: {}", p).unwrap();
+ } else {
+ writeln!(w, "positional NOT present").unwrap();
+ }
+ if matches.is_present("subcmd") {
+ writeln!(w, "subcmd present").unwrap();
+ if let Some(matches) = matches.subcommand_matches("subcmd") {
+ if matches.is_present("flag") {
+ writeln!(w, "flag present {} times", matches.occurrences_of("flag")).unwrap();
+ } else {
+ writeln!(w, "flag NOT present").unwrap();
+ }
+
+ if matches.is_present("option") {
+ if let Some(v) = matches.value_of("option") {
+ writeln!(w, "scoption present with value: {}", v).unwrap();
+ }
+ if let Some(ov) = matches.values_of("option") {
+ for o in ov {
+ writeln!(w, "An scoption: {}", o).unwrap();
+ }
+ }
+ } else {
+ writeln!(w, "scoption NOT present").unwrap();
+ }
+
+ if let Some(p) = matches.value_of("scpositional") {
+ writeln!(w, "scpositional present with value: {}", p).unwrap();
+ }
+ }
+ } else {
+ writeln!(w, "subcmd NOT present").unwrap();
+ }
+
+ let res = str::from_utf8(&w).unwrap();
+ assert_eq!(res, out);
+}
+
+arg_enum!{
+ #[derive(Debug)]
+ enum Val1 {
+ ValOne,
+ ValTwo
+ }
+}
+arg_enum!{
+ #[derive(Debug)]
+ pub enum Val2 {
+ ValOne,
+ ValTwo
+ }
+}
+arg_enum!{
+ enum Val3 {
+ ValOne,
+ ValTwo
+ }
+}
+arg_enum!{
+ pub enum Val4 {
+ ValOne,
+ ValTwo
+ }
+}
+
+#[test]
+fn test_enums() {
+ let v1_lower = "valone";
+ let v1_camel = "ValOne";
+
+ let v1_lp = v1_lower.parse::<Val1>().unwrap();
+ let v1_cp = v1_camel.parse::<Val1>().unwrap();
+ match v1_lp {
+ Val1::ValOne => (),
+ _ => panic!("Val1 didn't parse correctly"),
+ }
+ match v1_cp {
+ Val1::ValOne => (),
+ _ => panic!("Val1 didn't parse correctly"),
+ }
+ let v1_lp = v1_lower.parse::<Val2>().unwrap();
+ let v1_cp = v1_camel.parse::<Val2>().unwrap();
+ match v1_lp {
+ Val2::ValOne => (),
+ _ => panic!("Val1 didn't parse correctly"),
+ }
+ match v1_cp {
+ Val2::ValOne => (),
+ _ => panic!("Val1 didn't parse correctly"),
+ }
+ let v1_lp = v1_lower.parse::<Val3>().unwrap();
+ let v1_cp = v1_camel.parse::<Val3>().unwrap();
+ match v1_lp {
+ Val3::ValOne => (),
+ _ => panic!("Val1 didn't parse correctly"),
+ }
+ match v1_cp {
+ Val3::ValOne => (),
+ _ => panic!("Val1 didn't parse correctly"),
+ }
+ let v1_lp = v1_lower.parse::<Val4>().unwrap();
+ let v1_cp = v1_camel.parse::<Val4>().unwrap();
+ match v1_lp {
+ Val4::ValOne => (),
+ _ => panic!("Val1 didn't parse correctly"),
+ }
+ match v1_cp {
+ Val4::ValOne => (),
+ _ => panic!("Val1 didn't parse correctly"),
+ }
+}
+
+#[test]
+fn create_app() {
+ let _ =
+ App::new("test").version("1.0").author("kevin").about("does awesome things").get_matches_from(vec![""]);
+}
+
+#[test]
+fn add_multiple_arg() {
+ let _ = App::new("test")
+ .args(&[
+ Arg::with_name("test").short("s"),
+ Arg::with_name("test2").short("l")])
+ .get_matches_from(vec![""]);
+}
+#[test]
+fn flag_x2_opt() {
+ check_complex_output("clap-test value -f -f -o some",
+"flag present 2 times
+option present 1 times with value: some
+An option: some
+positional present with value: value
+flag2 NOT present
+option2 maybe present with value of: Nothing
+positional2 maybe present with value of: Nothing
+option3 NOT present
+positional3 NOT present
+option present 1 times with value: some
+An option: some
+positional present with value: value
+subcmd NOT present
+");
+}
+
+#[test]
+fn long_opt_x2_pos() {
+ check_complex_output("clap-test value --option some --option other", O2P);
+}
+
+#[test]
+fn long_opt_eq_x2_pos() {
+ check_complex_output("clap-test value --option=some --option=other", O2P);
+}
+
+#[test]
+fn short_opt_x2_pos() {
+ check_complex_output("clap-test value -o some -o other", O2P);
+}
+
+#[test]
+fn short_opt_eq_x2_pos() {
+ check_complex_output("clap-test value -o=some -o=other", O2P);
+}
+
+#[test]
+fn short_flag_x2_comb_short_opt_pos() {
+ check_complex_output("clap-test value -ff -o some", F2OP);
+}
+
+#[test]
+fn short_flag_short_opt_pos() {
+ check_complex_output("clap-test value -f -o some", FOP);
+}
+
+#[test]
+fn long_flag_long_opt_pos() {
+ check_complex_output("clap-test value --flag --option some", FOP);
+}
+
+#[test]
+fn long_flag_long_opt_eq_pos() {
+ check_complex_output("clap-test value --flag --option=some", FOP);
+}
+
+#[test]
+fn sc_long_flag_long_opt() {
+ check_complex_output("clap-test subcmd value --flag --option some", SCFOP);
+}
+
+#[test]
+fn sc_long_flag_short_opt_pos() {
+ check_complex_output("clap-test subcmd value --flag -o some", SCFOP);
+}
+
+#[test]
+fn sc_long_flag_long_opt_eq_pos() {
+ check_complex_output("clap-test subcmd value --flag --option=some", SCFOP);
+}
+
+#[test]
+fn sc_short_flag_long_opt_pos() {
+ check_complex_output("clap-test subcmd value -f --option some", SCFOP);
+}
+
+#[test]
+fn sc_short_flag_short_opt_pos() {
+ check_complex_output("clap-test subcmd value -f -o some", SCFOP);
+}
+
+#[test]
+fn sc_short_flag_short_opt_eq_pos() {
+ check_complex_output("clap-test subcmd value -f -o=some", SCFOP);
+}
+
+#[test]
+fn sc_short_flag_long_opt_eq_pos() {
+ check_complex_output("clap-test subcmd value -f --option=some", SCFOP);
+}
+
+#[test]
+fn sc_short_flag_x2_comb_long_opt_pos() {
+ check_complex_output("clap-test subcmd value -ff --option some", SCF2OP);
+}
+
+#[test]
+fn sc_short_flag_x2_comb_short_opt_pos() {
+ check_complex_output("clap-test subcmd value -ff -o some", SCF2OP);
+}
+
+#[test]
+fn sc_short_flag_x2_comb_long_opt_eq_pos() {
+ check_complex_output("clap-test subcmd value -ff --option=some", SCF2OP);
+}
+
+#[test]
+fn sc_short_flag_x2_comb_short_opt_eq_pos() {
+ check_complex_output("clap-test subcmd value -ff -o=some", SCF2OP);
+}
+
+#[test]
+fn sc_long_flag_x2_long_opt_pos() {
+ check_complex_output("clap-test subcmd value --flag --flag --option some", SCF2OP);
+}
+
+#[test]
+fn sc_long_flag_x2_short_opt_pos() {
+ check_complex_output("clap-test subcmd value --flag --flag -o some", SCF2OP);
+}
+
+#[test]
+fn sc_long_flag_x2_short_opt_eq_pos() {
+ check_complex_output("clap-test subcmd value --flag --flag -o=some", SCF2OP);
+}
+
+#[test]
+fn sc_long_flag_x2_long_opt_eq_pos() {
+ check_complex_output("clap-test subcmd value --flag --flag --option=some", SCF2OP);
+}
+
+#[test]
+fn sc_short_flag_x2_long_opt_pos() {
+ check_complex_output("clap-test subcmd value -f -f --option some", SCF2OP);
+}
+
+#[test]
+fn sc_short_flag_x2_short_opt_pos() {
+ check_complex_output("clap-test subcmd value -f -f -o some", SCF2OP);
+}
+
+#[test]
+fn sc_short_flag_x2_short_opt_eq_pos() {
+ check_complex_output("clap-test subcmd value -f -f -o=some", SCF2OP);
+}
+
+#[test]
+fn sc_short_flag_x2_long_opt_eq_pos() {
+ check_complex_output("clap-test subcmd value -f -f --option=some", SCF2OP);
+}
diff --git a/clap/tests/unique_args.rs b/clap/tests/unique_args.rs
new file mode 100644
index 0000000..8710248
--- /dev/null
+++ b/clap/tests/unique_args.rs
@@ -0,0 +1,22 @@
+extern crate clap;
+
+use clap::{App, Arg};
+
+#[test]
+#[should_panic]
+fn unique_arg_names() {
+ App::new("some").args(&[Arg::with_name("arg").short("a"), Arg::with_name("arg").short("b")]);
+}
+
+#[test]
+#[should_panic]
+fn unique_arg_shorts() {
+ App::new("some").args(&[Arg::with_name("arg1").short("a"), Arg::with_name("arg2").short("a")]);
+}
+
+#[test]
+#[should_panic]
+fn unique_arg_longs() {
+ App::new("some")
+ .args(&[Arg::with_name("arg1").long("long"), Arg::with_name("arg2").long("long")]);
+}
diff --git a/clap/tests/utf8.rs b/clap/tests/utf8.rs
new file mode 100644
index 0000000..dfa382e
--- /dev/null
+++ b/clap/tests/utf8.rs
@@ -0,0 +1,223 @@
+#![cfg(not(windows))]
+
+extern crate clap;
+
+use std::ffi::OsString;
+use std::os::unix::ffi::OsStringExt;
+use clap::{App, Arg, AppSettings, ErrorKind};
+
+#[test]
+fn invalid_utf8_strict_positional() {
+ let m = App::new("bad_utf8")
+ .arg(Arg::from_usage("<arg> 'some arg'"))
+ .setting(AppSettings::StrictUtf8)
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0xe9])]);
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidUtf8);
+}
+
+#[test]
+fn invalid_utf8_strict_option_short_space() {
+ let m = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .setting(AppSettings::StrictUtf8)
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from("-a"),
+ OsString::from_vec(vec![0xe9])]);
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidUtf8);
+}
+
+#[test]
+fn invalid_utf8_strict_option_short_equals() {
+ let m = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .setting(AppSettings::StrictUtf8)
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9])]);
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidUtf8);
+}
+
+#[test]
+fn invalid_utf8_strict_option_short_no_space() {
+ let m = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .setting(AppSettings::StrictUtf8)
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0x2d, 0x61, 0xe9])]);
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidUtf8);
+}
+
+#[test]
+fn invalid_utf8_strict_option_long_space() {
+ let m = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .setting(AppSettings::StrictUtf8)
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from("--arg"),
+ OsString::from_vec(vec![0xe9])]);
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidUtf8);
+}
+
+#[test]
+fn invalid_utf8_strict_option_long_equals() {
+ let m = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .setting(AppSettings::StrictUtf8)
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9])]);
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidUtf8);
+}
+
+#[test]
+fn invalid_utf8_lossy_positional() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("<arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
+}
+
+#[test]
+fn invalid_utf8_lossy_option_short_space() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from("-a"),
+ OsString::from_vec(vec![0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
+}
+
+#[test]
+fn invalid_utf8_lossy_option_short_equals() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
+}
+
+#[test]
+fn invalid_utf8_lossy_option_short_no_space() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0x2d, 0x61, 0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
+}
+
+#[test]
+fn invalid_utf8_lossy_option_long_space() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from("--arg"),
+ OsString::from_vec(vec![0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
+}
+
+#[test]
+fn invalid_utf8_lossy_option_long_equals() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_lossy("arg").unwrap(), "\u{FFFD}");
+}
+
+#[test]
+fn invalid_utf8_positional() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("<arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_os("arg").unwrap(), &*OsString::from_vec(vec![0xe9]));
+}
+
+#[test]
+fn invalid_utf8_option_short_space() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from("-a"),
+ OsString::from_vec(vec![0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_os("arg").unwrap(), &*OsString::from_vec(vec![0xe9]));
+}
+
+#[test]
+fn invalid_utf8_option_short_equals() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_os("arg").unwrap(), &*OsString::from_vec(vec![0xe9]));
+}
+
+#[test]
+fn invalid_utf8_option_short_no_space() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0x2d, 0x61, 0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_os("arg").unwrap(), &*OsString::from_vec(vec![0xe9]));
+}
+
+#[test]
+fn invalid_utf8_option_long_space() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from("--arg"),
+ OsString::from_vec(vec![0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_os("arg").unwrap(), &*OsString::from_vec(vec![0xe9]));
+}
+
+#[test]
+fn invalid_utf8_option_long_equals() {
+ let r = App::new("bad_utf8")
+ .arg(Arg::from_usage("-a, --arg <arg> 'some arg'"))
+ .get_matches_from_safe(vec![OsString::from(""),
+ OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9])]);
+ assert!(r.is_ok());
+ let m = r.unwrap();
+ assert!(m.is_present("arg"));
+ assert_eq!(&*m.value_of_os("arg").unwrap(), &*OsString::from_vec(vec![0xe9]));
+}
diff --git a/clap/tests/version-numbers.rs b/clap/tests/version-numbers.rs
new file mode 100644
index 0000000..411eea5
--- /dev/null
+++ b/clap/tests/version-numbers.rs
@@ -0,0 +1,12 @@
+#[macro_use]
+extern crate version_sync;
+
+#[test]
+fn test_readme_deps() {
+ assert_markdown_deps_updated!("README.md");
+}
+
+#[test]
+fn test_html_root_url() {
+ assert_html_root_url_updated!("src/lib.rs");
+}
diff --git a/clap/tests/version.rs b/clap/tests/version.rs
new file mode 100644
index 0000000..8bbd474
--- /dev/null
+++ b/clap/tests/version.rs
@@ -0,0 +1,58 @@
+extern crate clap;
+extern crate regex;
+
+use std::str;
+
+use clap::{App, Arg, ErrorKind};
+
+include!("../clap-test.rs");
+
+static VERSION: &'static str = "clap-test v1.4.8";
+
+#[test]
+fn version_short() {
+ let m = App::new("test")
+ .author("Kevin K.")
+ .about("tests stuff")
+ .version("1.3")
+ .get_matches_from_safe(vec!["myprog", "-V"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::VersionDisplayed);
+}
+
+#[test]
+fn version_long() {
+ let m = App::new("test")
+ .author("Kevin K.")
+ .about("tests stuff")
+ .version("1.3")
+ .get_matches_from_safe(vec!["myprog", "--version"]);
+
+ assert!(m.is_err());
+ assert_eq!(m.unwrap_err().kind, ErrorKind::VersionDisplayed);
+}
+
+#[test]
+fn complex_version_output() {
+ let mut a = App::new("clap-test").version("v1.4.8");
+ let _ = a.get_matches_from_safe_borrow(vec![""]);
+
+ // Now we check the output of print_version()
+ let mut ver = vec![];
+ a.write_version(&mut ver).unwrap();
+ assert_eq!(str::from_utf8(&ver).unwrap(), VERSION);
+}
+
+#[test]
+fn override_ver() {
+ let m = App::new("test")
+ .author("Kevin K.")
+ .about("tests stuff")
+ .version("1.3")
+ .arg(Arg::from_usage("-v, --version 'some version'"))
+ .get_matches_from_safe(vec!["test", "--version"]);
+
+ assert!(m.is_ok());
+ assert!(m.unwrap().is_present("version"));
+}
diff --git a/clap/tests/yaml.rs b/clap/tests/yaml.rs
new file mode 100644
index 0000000..279b987
--- /dev/null
+++ b/clap/tests/yaml.rs
@@ -0,0 +1,40 @@
+#![cfg(feature="yaml")]
+
+#[macro_use]
+extern crate clap;
+
+use clap::App;
+
+#[test]
+fn create_app_from_yaml() {
+ let yml = load_yaml!("app.yml");
+ App::from_yaml(yml);
+}
+
+#[test]
+fn help_message() {
+ let yml = load_yaml!("app.yml");
+ let mut app = App::from_yaml(yml);
+ // Generate the full help message!
+ let _ = app.get_matches_from_safe_borrow(Vec::<String>::new());
+
+ let mut help_buffer = Vec::new();
+ app.write_help(&mut help_buffer).unwrap();
+ let help_string = String::from_utf8(help_buffer).unwrap();
+ assert!(help_string.contains(
+ "-h, --help prints help with a nonstandard description\n"));
+}
+
+#[test]
+fn author() {
+ let yml = load_yaml!("app.yml");
+ let mut app = App::from_yaml(yml);
+ // Generate the full help message!
+ let _ = app.get_matches_from_safe_borrow(Vec::<String>::new());
+
+ let mut help_buffer = Vec::new();
+ app.write_help(&mut help_buffer).unwrap();
+ let help_string = String::from_utf8(help_buffer).unwrap();
+ assert!(help_string.contains(
+ "Kevin K. <kbknapp@gmail.com>"));
+}