Merge pull request #1154 from kbknapp/v3-prep

v3 Prep
This commit is contained in:
Kevin K 2018-01-25 23:15:17 -05:00 committed by GitHub
commit 7372359c9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
93 changed files with 6821 additions and 6891 deletions

View file

@ -23,6 +23,7 @@ appveyor = { repository = "kbknapp/clap-rs" }
bitflags = "1.0"
unicode-width = "0.1.4"
textwrap = "0.9.0"
ordermap = "0.3.5"
strsim = { version = "0.7.0", optional = true }
ansi_term = { version = "0.10.0", optional = true }
yaml-rust = { version = "0.3.5", optional = true }

19
TODO.md Normal file
View file

@ -0,0 +1,19 @@
- [ ] update-todo.sh
- [ ] src/lib.rs
-[ ] 578:@TODO @release @docs
-[ ] 580:@TODO @release @docs
-[ ] 583:@TODO @release @docs
-[ ] 592:@TODO @release @docs
-[ ] 598:@TODO @release @docs
-[ ] 608:@TODO @release @docs
-[ ] 610:@TODO @release @docs
-[ ] 614:@TODO @release @docs
-[ ] 616:@TODO @release @docs
-[ ] 619:@TODO @release @docs
-[ ] 623:@TODO @release @docs
- [ ] src/app/parser.rs
-[ ] 678:@TODO @perf: cloning all these Apps ins't great, but since it's just displaying the help
- [ ] src/app/mod.rs
-[ ] 1760:@TODO @v3-alpha @perf: should only propagate globals to subcmd we find, or for help
- [ ] src/args/arg.rs
-[ ] 3545:@TODO @p2 @docs @release: write docs

View file

@ -8,11 +8,7 @@ use clap::App;
use test::Bencher;
#[bench]
fn build_app(b: &mut Bencher) {
b.iter(|| App::new("claptests"));
}
fn build_app(b: &mut Bencher) { b.iter(|| App::new("claptests")); }
#[bench]
fn parse_clean(b: &mut Bencher) {
b.iter(|| App::new("claptests").get_matches_from(vec![""]));
}
fn parse_clean(b: &mut Bencher) { b.iter(|| App::new("claptests").get_matches_from(vec![""])); }

View file

@ -20,25 +20,18 @@ macro_rules! create_app {
}
#[bench]
fn build_app(b: &mut Bencher) {
b.iter(|| create_app!());
}
fn build_app(b: &mut Bencher) { b.iter(|| create_app!()); }
#[bench]
fn add_flag(b: &mut Bencher) {
fn build_app() -> App<'static, 'static> {
App::new("claptests")
}
fn build_app() -> App<'static, 'static> { App::new("claptests") }
b.iter(|| build_app().arg(Arg::from_usage("-s, --some 'something'")));
}
#[bench]
fn add_flag_ref(b: &mut Bencher) {
fn build_app() -> App<'static, 'static> {
App::new("claptests")
}
fn build_app() -> App<'static, 'static> { App::new("claptests") }
b.iter(|| {
let arg = Arg::from_usage("-s, --some 'something'");
@ -48,18 +41,14 @@ fn add_flag_ref(b: &mut Bencher) {
#[bench]
fn add_opt(b: &mut Bencher) {
fn build_app() -> App<'static, 'static> {
App::new("claptests")
}
fn build_app() -> App<'static, 'static> { App::new("claptests") }
b.iter(|| build_app().arg(Arg::from_usage("-s, --some <FILE> 'something'")));
}
#[bench]
fn add_opt_ref(b: &mut Bencher) {
fn build_app() -> App<'static, 'static> {
App::new("claptests")
}
fn build_app() -> App<'static, 'static> { App::new("claptests") }
b.iter(|| {
let arg = Arg::from_usage("-s, --some <FILE> 'something'");
@ -69,18 +58,14 @@ fn add_opt_ref(b: &mut Bencher) {
#[bench]
fn add_pos(b: &mut Bencher) {
fn build_app() -> App<'static, 'static> {
App::new("claptests")
}
fn build_app() -> App<'static, 'static> { App::new("claptests") }
b.iter(|| build_app().arg(Arg::with_name("some")));
}
#[bench]
fn add_pos_ref(b: &mut Bencher) {
fn build_app() -> App<'static, 'static> {
App::new("claptests")
}
fn build_app() -> App<'static, 'static> { App::new("claptests") }
b.iter(|| {
let arg = Arg::with_name("some");
@ -89,14 +74,10 @@ fn add_pos_ref(b: &mut Bencher) {
}
#[bench]
fn parse_clean(b: &mut Bencher) {
b.iter(|| create_app!().get_matches_from(vec![""]));
}
fn parse_clean(b: &mut Bencher) { b.iter(|| create_app!().get_matches_from(vec![""])); }
#[bench]
fn parse_flag(b: &mut Bencher) {
b.iter(|| create_app!().get_matches_from(vec!["myprog", "-f"]));
}
fn parse_flag(b: &mut Bencher) { b.iter(|| create_app!().get_matches_from(vec!["myprog", "-f"])); }
#[bench]
fn parse_option(b: &mut Bencher) {

View file

@ -4,7 +4,7 @@
extern crate clap;
extern crate test;
use clap::{App, Arg, SubCommand, AppSettings};
use clap::{App, AppSettings, Arg, SubCommand};
use test::Bencher;
@ -43,10 +43,7 @@ macro_rules! create_app {
}
#[bench]
fn create_app_from_usage(b: &mut Bencher) {
b.iter(|| create_app!());
}
fn create_app_from_usage(b: &mut Bencher) { b.iter(|| create_app!()); }
#[bench]
fn create_app_builder(b: &mut Bencher) {
@ -55,82 +52,112 @@ fn create_app_builder(b: &mut Bencher) {
.version("0.1")
.about("tests clap library")
.author("Kevin K. <kbknapp@gmail.com>")
.arg(Arg::with_name("opt")
.arg(
Arg::with_name("opt")
.help("tests options")
.short("o")
.long("option")
.takes_value(true)
.multiple(true))
.arg(Arg::with_name("positional")
.multiple(true),
)
.arg(
Arg::with_name("positional")
.help("tests positionals")
.index(1))
.arg(Arg::with_name("flag")
.index(1),
)
.arg(
Arg::with_name("flag")
.short("f")
.help("tests flags")
.long("flag")
.multiple(true)
.global(true))
.arg(Arg::with_name("flag2")
.global(true),
)
.arg(
Arg::with_name("flag2")
.short("F")
.help("tests flags with exclusions")
.conflicts_with("flag")
.requires("option2"))
.arg(Arg::with_name("option2")
.requires("option2"),
)
.arg(
Arg::with_name("option2")
.help("tests long options with exclusions")
.conflicts_with("option")
.requires("positional2")
.takes_value(true)
.long("long-option-2"))
.arg(Arg::with_name("positional2")
.long("long-option-2"),
)
.arg(
Arg::with_name("positional2")
.index(3)
.help("tests positionals with exclusions"))
.arg(Arg::with_name("option3")
.help("tests positionals with exclusions"),
)
.arg(
Arg::with_name("option3")
.short("O")
.long("Option")
.takes_value(true)
.help("tests options with specific value sets")
.possible_values(&OPT3_VALS))
.arg(Arg::with_name("positional3")
.possible_values(&OPT3_VALS),
)
.arg(
Arg::with_name("positional3")
.multiple(true)
.help("tests positionals with specific values")
.index(4)
.possible_values(&POS3_VALS))
.arg(Arg::with_name("multvals")
.possible_values(&POS3_VALS),
)
.arg(
Arg::with_name("multvals")
.long("multvals")
.takes_value(true)
.help("Tests mutliple values, not mult occs")
.value_names(&["one", "two"]))
.arg(Arg::with_name("multvalsmo")
.value_names(&["one", "two"]),
)
.arg(
Arg::with_name("multvalsmo")
.long("multvalsmo")
.takes_value(true)
.multiple(true)
.help("Tests mutliple values, not mult occs")
.value_names(&["one", "two"]))
.arg(Arg::with_name("minvals")
.value_names(&["one", "two"]),
)
.arg(
Arg::with_name("minvals")
.long("minvals2")
.multiple(true)
.takes_value(true)
.help("Tests 2 min vals")
.min_values(2))
.arg(Arg::with_name("maxvals")
.min_values(2),
)
.arg(
Arg::with_name("maxvals")
.long("maxvals3")
.takes_value(true)
.multiple(true)
.help("Tests 3 max vals")
.max_values(3))
.subcommand(SubCommand::with_name("subcmd")
.max_values(3),
)
.subcommand(
SubCommand::with_name("subcmd")
.about("tests subcommands")
.version("0.1")
.author("Kevin K. <kbknapp@gmail.com>")
.arg(Arg::with_name("scoption")
.arg(
Arg::with_name("scoption")
.short("o")
.long("option")
.multiple(true)
.takes_value(true)
.help("tests options"))
.arg(Arg::with_name("scpositional")
.help("tests options"),
)
.arg(
Arg::with_name("scpositional")
.index(1)
.help("tests positionals")));
.help("tests positionals"),
),
);
});
}
@ -170,14 +197,10 @@ fn create_app_macros(b: &mut Bencher) {
}
#[bench]
fn parse_clean(b: &mut Bencher) {
b.iter(|| create_app!().get_matches_from(vec![""]));
}
fn parse_clean(b: &mut Bencher) { b.iter(|| create_app!().get_matches_from(vec![""])); }
#[bench]
fn parse_flag(b: &mut Bencher) {
b.iter(|| create_app!().get_matches_from(vec!["myprog", "-f"]));
}
fn parse_flag(b: &mut Bencher) { b.iter(|| create_app!().get_matches_from(vec!["myprog", "-f"])); }
#[bench]
fn parse_option(b: &mut Bencher) {
@ -211,20 +234,75 @@ fn parse_sc_positional(b: &mut Bencher) {
#[bench]
fn parse_complex1(b: &mut Bencher) {
b.iter(|| create_app!().get_matches_from(vec!["myprog", "-ff", "-o", "option1", "arg1", "-O", "fast", "arg2", "--multvals", "one", "two", "emacs"]));
b.iter(|| {
create_app!().get_matches_from(vec![
"myprog",
"-ff",
"-o",
"option1",
"arg1",
"-O",
"fast",
"arg2",
"--multvals",
"one",
"two",
"emacs",
])
});
}
#[bench]
fn parse_complex2(b: &mut Bencher) {
b.iter(|| create_app!().get_matches_from(vec!["myprog", "arg1", "-f", "arg2", "--long-option-2", "some", "-O", "slow", "--multvalsmo", "one", "two", "--minvals2", "3", "2", "1"]));
b.iter(|| {
create_app!().get_matches_from(vec![
"myprog",
"arg1",
"-f",
"arg2",
"--long-option-2",
"some",
"-O",
"slow",
"--multvalsmo",
"one",
"two",
"--minvals2",
"3",
"2",
"1",
])
});
}
#[bench]
fn parse_complex2_with_args_negate_scs(b: &mut Bencher) {
b.iter(|| create_app!().setting(AppSettings::ArgsNegateSubcommands).get_matches_from(vec!["myprog", "arg1", "-f", "arg2", "--long-option-2", "some", "-O", "slow", "--multvalsmo", "one", "two", "--minvals2", "3", "2", "1"]));
b.iter(|| {
create_app!()
.setting(AppSettings::ArgsNegateSubcommands)
.get_matches_from(vec![
"myprog",
"arg1",
"-f",
"arg2",
"--long-option-2",
"some",
"-O",
"slow",
"--multvalsmo",
"one",
"two",
"--minvals2",
"3",
"2",
"1",
])
});
}
#[bench]
fn parse_sc_complex(b: &mut Bencher) {
b.iter(|| create_app!().get_matches_from(vec!["myprog", "subcmd", "-f", "-o", "option1", "arg1"]));
b.iter(|| {
create_app!().get_matches_from(vec!["myprog", "subcmd", "-f", "-o", "option1", "arg1"])
});
}

View file

@ -10,7 +10,7 @@ use std::io::Cursor;
use clap::App;
use clap::{Arg, SubCommand};
fn build_help(app: &App) -> String {
fn build_help(app: &mut App) -> String {
let mut buf = Cursor::new(Vec::with_capacity(50));
app.write_help(&mut buf).unwrap();
let content = buf.into_inner();
@ -22,12 +22,16 @@ fn app_example1<'b, 'c>() -> App<'b, 'c> {
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.args_from_usage("-c, --config=[FILE] 'Sets a custom config file'
.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")
-d... 'Turn debugging information on'",
)
.subcommand(
SubCommand::with_name("test")
.about("does testing things")
.arg_from_usage("-l, --list 'lists test values'"))
.arg_from_usage("-l, --list 'lists test values'"),
)
}
fn app_example2<'b, 'c>() -> App<'b, 'c> {
@ -39,10 +43,13 @@ fn app_example2<'b, 'c>() -> App<'b, 'c> {
fn app_example3<'b, 'c>() -> App<'b, 'c> {
App::new("MyApp")
.arg(Arg::with_name("debug")
.arg(
Arg::with_name("debug")
.help("turn on debugging information")
.short("d"))
.args(&[Arg::with_name("config")
.short("d"),
)
.args(&[
Arg::with_name("config")
.help("sets the config file to use")
.takes_value(true)
.short("c")
@ -50,10 +57,13 @@ fn app_example3<'b, 'c>() -> App<'b, 'c> {
Arg::with_name("input")
.help("the input file to use")
.index(1)
.required(true)])
.required(true),
])
.arg_from_usage("--license 'display the license file'")
.args_from_usage("[output] 'Supply an output file to use'
-i, --int=[IFACE] 'Set an interface to use'")
.args_from_usage(
"[output] 'Supply an output file to use'
-i, --int=[IFACE] 'Set an interface to use'",
)
}
fn app_example4<'b, 'c>() -> App<'b, 'c> {
@ -61,48 +71,61 @@ fn app_example4<'b, 'c>() -> App<'b, 'c> {
.about("Parses an input file to do awesome things")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.arg(Arg::with_name("debug")
.arg(
Arg::with_name("debug")
.help("turn on debugging information")
.short("d")
.long("debug"))
.arg(Arg::with_name("config")
.long("debug"),
)
.arg(
Arg::with_name("config")
.help("sets the config file to use")
.short("c")
.long("config"))
.arg(Arg::with_name("input")
.long("config"),
)
.arg(
Arg::with_name("input")
.help("the input file to use")
.index(1)
.required(true))
.required(true),
)
}
fn app_example5<'b, 'c>() -> App<'b, 'c> {
App::new("MyApp").arg(Arg::with_name("awesome")
App::new("MyApp").arg(
Arg::with_name("awesome")
.help("turns up the awesome")
.short("a")
.long("awesome")
.multiple(true)
.requires("config")
.conflicts_with("output"))
.conflicts_with("output"),
)
}
fn app_example6<'b, 'c>() -> App<'b, 'c> {
App::new("MyApp")
.arg(Arg::with_name("input")
.arg(
Arg::with_name("input")
.help("the input file to use")
.index(1)
.requires("config")
.conflicts_with("output")
.required(true))
.arg(Arg::with_name("config")
.required(true),
)
.arg(
Arg::with_name("config")
.help("the config file to use")
.index(2))
.index(2),
)
}
fn app_example7<'b, 'c>() -> App<'b, 'c> {
App::new("MyApp")
.arg(Arg::with_name("config"))
.arg(Arg::with_name("output"))
.arg(Arg::with_name("input")
.arg(
Arg::with_name("input")
.help("the input file to use")
.takes_value(true)
.short("i")
@ -110,14 +133,16 @@ fn app_example7<'b, 'c>() -> App<'b, 'c> {
.multiple(true)
.required(true)
.requires("config")
.conflicts_with("output"))
.conflicts_with("output"),
)
}
fn app_example8<'b, 'c>() -> App<'b, 'c> {
App::new("MyApp")
.arg(Arg::with_name("config"))
.arg(Arg::with_name("output"))
.arg(Arg::with_name("input")
.arg(
Arg::with_name("input")
.help("the input file to use")
.takes_value(true)
.short("i")
@ -125,74 +150,75 @@ fn app_example8<'b, 'c>() -> App<'b, 'c> {
.multiple(true)
.required(true)
.requires("config")
.conflicts_with("output"))
.conflicts_with("output"),
)
}
fn app_example10<'b, 'c>() -> App<'b, 'c> {
App::new("myapp")
.about("does awesome things")
.arg(Arg::with_name("CONFIG")
App::new("myapp").about("does awesome things").arg(
Arg::with_name("CONFIG")
.help("The config file to use (default is \"config.json\")")
.short("c")
.takes_value(true))
.takes_value(true),
)
}
#[bench]
fn example1(b: &mut Bencher) {
let app = app_example1();
b.iter(|| build_help(&app));
let mut app = app_example1();
b.iter(|| build_help(&mut app));
}
#[bench]
fn example2(b: &mut Bencher) {
let app = app_example2();
b.iter(|| build_help(&app));
let mut app = app_example2();
b.iter(|| build_help(&mut app));
}
#[bench]
fn example3(b: &mut Bencher) {
let app = app_example3();
b.iter(|| build_help(&app));
let mut app = app_example3();
b.iter(|| build_help(&mut app));
}
#[bench]
fn example4(b: &mut Bencher) {
let app = app_example4();
b.iter(|| build_help(&app));
let mut app = app_example4();
b.iter(|| build_help(&mut app));
}
#[bench]
fn example5(b: &mut Bencher) {
let app = app_example5();
b.iter(|| build_help(&app));
let mut app = app_example5();
b.iter(|| build_help(&mut app));
}
#[bench]
fn example6(b: &mut Bencher) {
let app = app_example6();
b.iter(|| build_help(&app));
let mut app = app_example6();
b.iter(|| build_help(&mut app));
}
#[bench]
fn example7(b: &mut Bencher) {
let app = app_example7();
b.iter(|| build_help(&app));
let mut app = app_example7();
b.iter(|| build_help(&mut app));
}
#[bench]
fn example8(b: &mut Bencher) {
let app = app_example8();
b.iter(|| build_help(&app));
let mut app = app_example8();
b.iter(|| build_help(&mut app));
}
#[bench]
fn example10(b: &mut Bencher) {
let app = app_example10();
b.iter(|| build_help(&app));
let mut app = app_example10();
b.iter(|| build_help(&mut app));
}
#[bench]
fn example4_template(b: &mut Bencher) {
let app = app_example4().template("{bin} {version}\n{author}\n{about}\n\nUSAGE:\n {usage}\n\nFLAGS:\n{flags}\n\nARGS:\n{args}\n");
b.iter(|| build_help(&app));
let mut app = app_example4().template("{bin} {version}\n{author}\n{about}\n\nUSAGE:\n {usage}\n\nFLAGS:\n{flags}\n\nARGS:\n{args}\n");
b.iter(|| build_help(&mut app));
}

View file

@ -6,9 +6,9 @@
#![feature(test)]
extern crate clap;
extern crate test;
#[macro_use]
extern crate lazy_static;
extern crate test;
use clap::{App, AppSettings, Arg, ArgSettings};
@ -24,14 +24,14 @@ fn build_app_long(b: &mut Bencher) { b.iter(|| app_long()); }
#[bench]
fn build_help_short(b: &mut Bencher) {
let app = app_short();
b.iter(|| build_help(&app));
let mut app = app_short();
b.iter(|| build_help(&mut app));
}
#[bench]
fn build_help_long(b: &mut Bencher) {
let app = app_long();
b.iter(|| build_help(&app));
let mut app = app_long();
b.iter(|| build_help(&mut app));
}
#[bench]
@ -40,7 +40,8 @@ fn parse_clean(b: &mut Bencher) { b.iter(|| app_short().get_matches_from(vec!["r
#[bench]
fn parse_complex(b: &mut Bencher) {
b.iter(|| {
app_short().get_matches_from(vec!["rg",
app_short().get_matches_from(vec![
"rg",
"pat",
"-cFlN",
"-pqr=some",
@ -50,234 +51,176 @@ fn parse_complex(b: &mut Bencher) {
"-SH",
"-C5",
"--follow",
"-e some"])
"-e some",
])
});
}
#[bench]
fn parse_lots(b: &mut Bencher) {
b.iter(|| {
app_short()
.get_matches_from(vec!["rg", "pat", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some"])
app_short().get_matches_from(vec![
"rg", "pat", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "some", "some", "some", "some", "some",
])
});
}
@ -317,16 +260,14 @@ pub fn app_short() -> App<'static, 'static> { app(false, |k| USAGES[k].short) }
/// Build a clap application with long help strings.
pub fn app_long() -> App<'static, 'static> { app(true, |k| USAGES[k].long) }
/// Build the help text of an application.
fn build_help(app: &App) -> String {
fn build_help(app: &mut App) -> String {
let mut buf = Cursor::new(Vec::with_capacity(50));
app.write_help(&mut buf).unwrap();
let content = buf.into_inner();
String::from_utf8(content).unwrap()
}
/// Build a clap application parameterized by usage strings.
///
/// The function given should take a clap argument name and return a help
@ -335,9 +276,14 @@ fn build_help(app: &App) -> String {
/// This is an intentionally stand-alone module so that it can be used easily
/// in a `build.rs` script to build shell completion files.
fn app<F>(next_line_help: bool, doc: F) -> App<'static, 'static>
where F: Fn(&'static str) -> &'static str
where
F: Fn(&'static str) -> &'static str,
{
let arg = |name| Arg::with_name(name).help(doc(name)).next_line_help(next_line_help);
let arg = |name| {
Arg::with_name(name)
.help(doc(name))
.next_line_help(next_line_help)
};
let flag = |name| arg(name).long(name);
App::new("ripgrep")
@ -773,5 +719,7 @@ lazy_static! {
}
fn validate_number(s: String) -> Result<(), String> {
s.parse::<usize>().map(|_| ()).map_err(|err| err.to_string())
s.parse::<usize>()
.map(|_| ())
.map_err(|err| err.to_string())
}

View file

@ -7,7 +7,7 @@
extern crate clap;
extern crate test;
use clap::{App, AppSettings, Arg, Shell, SubCommand, ArgGroup};
use clap::{App, AppSettings, Arg, ArgGroup, Shell, SubCommand};
use test::Bencher;

View file

@ -36,9 +36,11 @@ mod test {
err.write_to(&mut buf).unwrap();
let content = buf.into_inner();
let left = String::from_utf8(content).unwrap();
assert_eq!(stderr, err.use_stderr());
assert_eq!(stderr, err.use_stderr(),
"Should Use STDERR failed. Should be {} but is {}", stderr, err.use_stderr());
compare(left, right)
}
pub fn compare_output2(l: App, args: &str, right1: &str, right2: &str, stderr: bool) -> bool {
let mut buf = Cursor::new(Vec::with_capacity(50));
let res = l.get_matches_from_safe(args.split(' ').collect::<Vec<_>>());

17
etc/count-tests.sh Executable file
View file

@ -0,0 +1,17 @@
#!/bin/bash
IFS=$'\n'
touch .tmp.out
echo -n "Testing"
for TEST in $(find tests/ -type f -name "*.rs" -exec basename {} .rs \;); do
echo -n "."
echo -n -e "$TEST:\t" >> .tmp.out
cargo test --test $TEST 2>&1 | grep -o -e '[0-9]* failed;' >> .tmp.out
done
echo "Done"
column -t < .tmp.out
rm .tmp.out
unset IFS

18
etc/update-todo.sh Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
rg -h 1>/dev/null || (echo "ripgrep not found" && false)
IFS=$'\n'
mv TODO.md TODO.bak || true
touch TODO.md
for FILE in $(rg '@TODO' --ignore-file='update-todo.sh' --files-with-matches); do
echo "- [ ] $FILE" >> TODO.md
for LINE in $(rg -noe '@TODO([ @a-zA-Z-]+):?(.*)$' $FILE); do
echo " -[ ] $LINE" >> TODO.md
done;
done;
unset IFS
rm TODO.bak || true

View file

@ -3,7 +3,6 @@ extern crate clap;
use clap::{App, SubCommand};
fn main() {
// This example shows how to create an application with several arguments using usage strings, which can be
// far less verbose that shown in 01b_QuickExample.rs, but is more readable. The downside is you cannot set
// the more advanced configuration options using this method (well...actually you can, you'll see ;) )
@ -36,12 +35,16 @@ fn main() {
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.args_from_usage("-c, --config=[FILE] 'Sets a custom config file'
.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")
-d... 'Turn debugging information on'",
)
.subcommand(
SubCommand::with_name("test")
.about("does testing things")
.arg_from_usage("-l, --list 'lists test values'"))
.arg_from_usage("-l, --list 'lists test values'"),
)
.get_matches();
// You can check the value provided by positional arguments, or option arguments
@ -74,6 +77,5 @@ fn main() {
}
}
// Continued program logic goes here...
}

View file

@ -3,7 +3,6 @@ extern crate clap;
use clap::{App, Arg, SubCommand};
fn main() {
// This method shows the traditional, and slightly more configurable way to set up arguments. This method is
// more verbose, but allows setting more configuration options, and even supports easier dynamic generation.
//
@ -38,24 +37,30 @@ fn main() {
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(Arg::with_name("config")
.arg(
Arg::with_name("config")
.short("c")
.long("config")
.value_name("FILE")
.help("Sets a custom config file")
.takes_value(true))
.arg(Arg::with_name("output")
.takes_value(true),
)
.arg(
Arg::with_name("output")
.help("Sets an optional output file")
.index(1))
.arg(Arg::with_name("debug")
.index(1),
)
.arg(
Arg::with_name("debug")
.short("d")
.multiple(true)
.help("Turn debugging information on"))
.subcommand(SubCommand::with_name("test")
.help("Turn debugging information on"),
)
.subcommand(
SubCommand::with_name("test")
.about("does testing things")
.arg(Arg::with_name("list")
.short("l")
.help("lists test values")))
.arg(Arg::with_name("list").short("l").help("lists test values")),
)
.get_matches();
// You can check the value provided by positional arguments, or option arguments
@ -88,6 +93,5 @@ fn main() {
}
}
// Continued program logic goes here...
}

View file

@ -65,7 +65,14 @@ fn main() {
// an example, and may be somewhat contrived
//
// First we check if debugging should be on or not
println!("Debugging mode is: {}", if matches.is_present("debug") { "ON" } else { "OFF" });
println!(
"Debugging mode is: {}",
if matches.is_present("debug") {
"ON"
} else {
"OFF"
}
);
// Next we print the config file we're using, if any was defined with either -c <file> or
// --config <file>

View file

@ -3,7 +3,6 @@ extern crate clap;
use clap::{App, Arg};
fn main() {
// Once all App settings (including all arguments) have been set, you call get_matches() which
// parses the string provided by the user, and returns all the valid matches to the ones you
// specified.
@ -21,18 +20,24 @@ fn main() {
.about("Parses an input file to do awesome things")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.arg(Arg::with_name("debug")
.arg(
Arg::with_name("debug")
.help("turn on debugging information")
.short("d")
.long("debug"))
.arg(Arg::with_name("config")
.long("debug"),
)
.arg(
Arg::with_name("config")
.help("sets the config file to use")
.short("c")
.long("config"))
.arg(Arg::with_name("input")
.long("config"),
)
.arg(
Arg::with_name("input")
.help("the input file to use")
.index(1)
.required(true))
.required(true),
)
.get_matches();
// We can find out whether or not debugging was turned on
@ -48,7 +53,10 @@ fn main() {
// Because "input" is required we can safely call unwrap() because had the user NOT
// specified a value, clap would have explained the error the user, and exited.
println!("Doing real work with file: {}", matches.value_of("input").unwrap() );
println!(
"Doing real work with file: {}",
matches.value_of("input").unwrap()
);
// Continued program logic goes here...
}

View file

@ -3,7 +3,6 @@ extern crate clap;
use clap::{App, Arg};
fn main() {
// Of the three argument types, flags are the most simple. Flags are simple switches which can
// be either "on" or "off"
//

View file

@ -3,7 +3,6 @@ extern crate clap;
use clap::{App, Arg};
fn main() {
// Positional arguments are those values after the program name which are not preceded by any
// identifier (such as "myapp some_file"). Positionals support many of the same options as
// flags, as well as a few additional ones.
@ -50,7 +49,11 @@ fn main() {
// We can also get the values for those arguments
if let Some(ref in_file) = matches.value_of("input") {
// It's safe to call unwrap() because of the required options we set above
println!("Doing work with {} and {}", in_file, matches.value_of("config").unwrap());
println!(
"Doing work with {} and {}",
in_file,
matches.value_of("config").unwrap()
);
}
// Continued program logic goes here...
}

View file

@ -3,7 +3,6 @@ extern crate clap;
use clap::{App, Arg};
fn main() {
// Option arguments are those that take an additional value, such as "-c value". In clap they
// support three types of specification, those with short() as "-o some", or those with long()
// as "--option value" or "--option=value"
@ -65,7 +64,10 @@ fn main() {
// NOTE: Just like with flags, if we did not specify the multiple() setting this will only
// return 1 no matter how many times the argument was used (unless it wasn't used at all, in
// in which case 0 is returned)
println!("The \"input\" argument was used {} times", matches.occurrences_of("input"));
println!(
"The \"input\" argument was used {} times",
matches.occurrences_of("input")
);
// Continued program logic goes here...
}

View file

@ -3,7 +3,6 @@ extern crate clap;
use clap::{App, Arg, SubCommand};
fn main() {
// SubCommands function exactly like sub-Apps, because that's exactly what they are. Each
// instance of a SubCommand can have it's own version, author(s), Args, and even it's own
// subcommands.

View file

@ -12,22 +12,25 @@ fn main() {
//
// For this example, assume you want one positional argument of either "fast" or "slow"
// i.e. the only possible ways to run the program are "myprog fast" or "myprog slow"
let matches = App::new("myapp").about("does awesome things")
.arg(Arg::with_name("MODE")
let matches = App::new("myapp")
.about("does awesome things")
.arg(
Arg::with_name("MODE")
.help("What mode to run the program in")
.index(1)
.possible_values(&["fast", "slow"])
.required(true))
.required(true),
)
.get_matches();
// Note, it's safe to call unwrap() because the arg is required
match matches.value_of("MODE").unwrap() {
"fast" => {
// Do fast things...
},
}
"slow" => {
// Do slow things...
},
_ => unreachable!()
}
_ => unreachable!(),
}
}

View file

@ -55,12 +55,11 @@ fn main() {
let t = value_t!(m.value_of("foo"), Foo).unwrap_or_else(|e| e.exit());
let t2 = value_t!(m.value_of("oof"), Oof).unwrap_or_else(|e| e.exit());
// Now we can use our enum like normal.
match t {
Foo::Bar => println!("Found a Bar"),
Foo::Baz => println!("Found a Baz"),
Foo::Qux => println!("Found a Qux")
Foo::Qux => println!("Found a Qux"),
}
// Since our Oof derives Debug, we can do this:

View file

@ -15,7 +15,7 @@ enum Vals {
Foo,
Bar,
Baz,
Qux
Qux,
}
// Implement the trait
@ -28,7 +28,7 @@ impl FromStr for Vals {
"Bar" => Ok(Vals::Bar),
"Baz" => Ok(Vals::Baz),
"Qux" => Ok(Vals::Qux),
_ => Err("no match")
_ => Err("no match"),
}
}
}
@ -49,6 +49,6 @@ fn main() {
Vals::Foo => println!("Found a Foo"),
Vals::Bar => println!("Found a Bar"),
Vals::Baz => println!("Found a Baz"),
Vals::Qux => println!("Found a Qux")
Vals::Qux => println!("Found a Qux"),
}
}

View file

@ -20,7 +20,6 @@
/// of the three numbers. So you create three flags `--major`, `--minor`, and `--patch`. All of
/// these arguments shouldn't be used at one time but you want to specify that *at least one* of
/// them is used. For this, you can create a group.
extern crate clap;
use clap::{App, Arg, ArgGroup};
@ -61,9 +60,11 @@ fn main() {
format!("{}", ver)
} else {
// Increment the one requested (in a real program, we'd reset the lower numbers)
let (maj, min, pat) = (matches.is_present("major"),
let (maj, min, pat) = (
matches.is_present("major"),
matches.is_present("minor"),
matches.is_present("patch"));
matches.is_present("patch"),
);
match (maj, min, pat) {
(true, _, _) => major += 1,
(_, true, _) => minor += 1,
@ -77,11 +78,13 @@ fn main() {
// Check for usage of -c
if matches.is_present("config") {
let input = matches.value_of("INPUT_FILE").unwrap_or(matches.value_of("SPEC_IN").unwrap());
println!("Doing work using input {} and config {}",
let input = matches
.value_of("INPUT_FILE")
.unwrap_or(matches.value_of("SPEC_IN").unwrap());
println!(
"Doing work using input {} and config {}",
input,
matches.value_of("config").unwrap());
matches.value_of("config").unwrap()
);
}
}

View file

@ -36,6 +36,6 @@ fn main() {
match matches.subcommand() {
("test", _) => println!("The 'test' subcommand was used"),
_ => unreachable!()
_ => unreachable!(),
}
}

View file

@ -11,7 +11,6 @@
// [dependencies]
// clap = { features = ["yaml"] }
// Using yaml requires calling a clap macro `load_yaml!()` so we must use the '#[macro_use]'
// directive
#[macro_use]
@ -38,7 +37,7 @@ fn main() {
match mode {
"vi" => println!("You are using vi"),
"emacs" => println!("You are using emacs..."),
_ => unreachable!()
_ => unreachable!(),
}
} else {
println!("--mode <MODE> wasn't used...");

View file

@ -5,7 +5,6 @@ extern crate clap;
// $crate:: internally
fn main() {
// Validation example testing that a file exists
let file_exists = |path| {
if std::fs::metadata(path).is_ok() {

View file

@ -41,31 +41,36 @@
extern crate clap;
use clap::{App, Arg, SubCommand, AppSettings};
use clap::{App, AppSettings, Arg, SubCommand};
fn main() {
let matches = App::new("git")
.about("A fictional versioning CLI")
.version("1.0")
.author("Me")
.subcommand(SubCommand::with_name("clone")
.about("clones repos")
.arg(Arg::with_name("repo")
.subcommand(
SubCommand::with_name("clone").about("clones repos").arg(
Arg::with_name("repo")
.help("The repo to clone")
.required(true)))
.subcommand(SubCommand::with_name("push")
.required(true),
),
)
.subcommand(
SubCommand::with_name("push")
.about("pushes things")
.setting(AppSettings::SubcommandRequiredElseHelp)
.subcommand(SubCommand::with_name("remote") // Subcommands can have thier own subcommands,
.subcommand(
SubCommand::with_name("remote") // Subcommands can have thier own subcommands,
// which in turn have their own subcommands
.about("pushes remote things")
.arg(Arg::with_name("repo")
.required(true)
.help("The remote repo to push things to")))
.subcommand(SubCommand::with_name("local")
.about("pushes local things")))
.subcommand(SubCommand::with_name("add")
.help("The remote repo to push things to")),
)
.subcommand(SubCommand::with_name("local").about("pushes local things")),
)
.subcommand(
SubCommand::with_name("add")
.about("adds things")
.author("Someone Else") // Subcommands can list different authors
.version("v2.0 (I'm versioned differently") // or different version from their parents
@ -74,7 +79,8 @@ fn main() {
.long("stuff")
.help("Stuff to add")
.takes_value(true)
.multiple(true)))
.multiple(true)),
)
.get_matches();
// At this point, the matches we have point to git. Keep this in mind...
@ -114,27 +120,34 @@ fn main() {
// The most common way to handle subcommands is via a combined approach using
// `ArgMatches::subcommand` which returns a tuple of both the name and matches
match matches.subcommand() {
("clone", Some(clone_matches)) =>{
("clone", Some(clone_matches)) => {
// Now we have a reference to clone's matches
println!("Cloning {}", clone_matches.value_of("repo").unwrap());
},
("push", Some(push_matches)) =>{
}
("push", Some(push_matches)) => {
// Now we have a reference to push's matches
match push_matches.subcommand() {
("remote", Some(remote_matches)) =>{
("remote", Some(remote_matches)) => {
// Now we have a reference to remote's matches
println!("Pushing to {}", remote_matches.value_of("repo").unwrap());
},
("local", Some(_)) =>{
}
("local", Some(_)) => {
println!("'git push local' was used");
},
}
_ => unreachable!(),
}
},
("add", Some(add_matches)) =>{
}
("add", Some(add_matches)) => {
// Now we have a reference to add's matches
println!("Adding {}", add_matches.values_of("stuff").unwrap().collect::<Vec<_>>().join(", "));
},
println!(
"Adding {}",
add_matches
.values_of("stuff")
.unwrap()
.collect::<Vec<_>>()
.join(", ")
);
}
("", None) => println!("No subcommand was used"), // If no subcommand was usd it'll match the tuple ("", None)
_ => unreachable!(), // If all subcommands are defined above, anything else is unreachabe!()
}

View file

@ -3,17 +3,19 @@ extern crate clap;
use clap::{App, Arg, SubCommand};
fn main() {
let matches = App::new("MyApp")
.subcommand(SubCommand::with_name("ls")
.subcommand(
SubCommand::with_name("ls")
.aliases(&["list", "dir"])
.about("Adds files to myapp")
.version("0.1")
.author("Kevin K.")
.arg(Arg::with_name("input")
.arg(
Arg::with_name("input")
.help("the file to add")
.index(1)
.required(true))
.required(true),
),
)
.get_matches();

View file

@ -4,22 +4,20 @@ use clap::{App, Arg};
/// myprog -f -p=bob -- sloppy slop slop
fn main() {
let matches = App::new("myprog")
.arg(Arg::with_name("eff")
.short("f"))
.arg(Arg::with_name("pea")
.short("p")
.takes_value(true))
.arg(Arg::with_name("slop")
.multiple(true)
.last(true))
.arg(Arg::with_name("eff").short("f"))
.arg(Arg::with_name("pea").short("p").takes_value(true))
.arg(Arg::with_name("slop").multiple(true).last(true))
.get_matches();
println!("-f used: {:?}", matches.is_present("eff"));
println!("-p's value: {:?}", matches.value_of("pea"));
println!("'slops' values: {:?}", matches.values_of("slop").map(|vals| vals.collect::<Vec<_>>()));
println!(
"'slops' values: {:?}",
matches
.values_of("slop")
.map(|vals| vals.collect::<Vec<_>>())
);
// Continued program logic goes here...
}

View file

@ -1,3 +1,4 @@
@update-contributors:
echo 'Removing old CONTRIBUTORS.md'
mv CONTRIBUTORS.md CONTRIBUTORS.md.bak
@ -11,11 +12,11 @@
echo "This list was generated by [mgechev/github-contributors-list](https://github.com/mgechev/github-contributors-list)" >> CONTRIBUTORS.md
rm CONTRIBUTORS.md.bak
run-test TEST:
cargo test --test {{TEST}}
run-test TESTG TEST="":
cargo test --test {{TESTG}} -- {{TEST}}
debug TEST:
cargo test --test {{TEST}} --features debug
debug TESTG TEST="":
cargo test --test {{TESTG}} --features debug -- {{TEST}}
run-tests:
cargo test --features "yaml unstable"
@ -37,3 +38,24 @@ clean:
find . -type f -name "*.orig" -exec rm {} \;
find . -type f -name "*.bk" -exec rm {} \;
find . -type f -name ".*~" -exec rm {} \;
top-errors NUM="95":
@cargo check 2>&1 | head -n {{NUM}}
count-errors:
@cargo check 2>&1 | grep -e '^error' | wc -l
find-errors:
@cargo check 2>&1 | grep --only-matching -e '-->[^:]*' | sort | uniq -c | sort -nr
count-warnings:
@cargo check 2>&1 | grep -e '^warning' | wc -l
find-warnings:
@cargo check 2>&1 | grep -A1 -e 'warning' | grep --only-matching -e '-->[^:]*' | sort | uniq -c | sort -nr
@update-todo:
./etc/update-todo.sh
@count-failures:
./etc/count-tests.sh

View file

@ -1,4 +1,2 @@
format_strings = false
chain_overflow_last = false
same_line_if_else = true
fn_single_line = true

View file

@ -2,17 +2,16 @@
use std::borrow::Cow;
use std::cmp;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::io::{self, Cursor, Read, Write};
use std::usize;
// Internal
use app::{App, AppSettings};
use app::parser::Parser;
use args::{AnyArg, ArgSettings, DispOrder};
use args::{Arg, ArgSettings};
use errors::{Error, Result as ClapResult};
use fmt::{Colorizer, ColorizerOption, Format};
use app::usage;
use app::usage::Usage;
use map::VecMap;
use INTERNAL_ERROR_MSG;
@ -31,29 +30,16 @@ fn str_width(s: &str) -> usize { UnicodeWidthStr::width(s) }
const TAB: &'static str = " ";
// These are just convenient traits to make the code easier to read.
trait ArgWithDisplay<'b, 'c>: AnyArg<'b, 'c> + Display {}
impl<'b, 'c, T> ArgWithDisplay<'b, 'c> for T
where
T: AnyArg<'b, 'c> + Display,
{
}
trait ArgWithOrder<'b, 'c>: ArgWithDisplay<'b, 'c> + DispOrder {
fn as_base(&self) -> &ArgWithDisplay<'b, 'c>;
}
impl<'b, 'c, T> ArgWithOrder<'b, 'c> for T
where
T: ArgWithDisplay<'b, 'c> + DispOrder,
{
fn as_base(&self) -> &ArgWithDisplay<'b, 'c> { self }
}
fn as_arg_trait<'a, 'b, T: ArgWithOrder<'a, 'b>>(x: &T) -> &ArgWithOrder<'a, 'b> { x }
impl<'b, 'c> DispOrder for App<'b, 'c> {
fn disp_ord(&self) -> usize { 999 }
}
// trait ArgWithOrder<'b, 'c>: Display + DispOrder {
// fn as_base(&self) -> &Arg<'b, 'c>;
// }
// impl<'b, 'c, T> ArgWithOrder<'b, 'c> for T
// where
// T: Display + DispOrder,
// {
// fn as_base(&self) -> &Arg<'b, 'c> { self }
// }
// fn as_arg_trait<'w, 'b, T: ArgWithOrder<'w, 'b>>(x: &T) -> &ArgWithOrder<'w, 'b> { x }
macro_rules! color {
($_self:ident, $s:expr, $c:ident) => {
@ -75,8 +61,8 @@ macro_rules! color {
/// `clap` Help Writer.
///
/// Wraps a writer stream providing different methods to generate help for `clap` objects.
pub struct Help<'a> {
writer: &'a mut Write,
pub struct Help<'w> {
writer: &'w mut Write,
next_line_help: bool,
hide_pv: bool,
term_w: usize,
@ -88,11 +74,11 @@ pub struct Help<'a> {
}
// Public Functions
impl<'a> Help<'a> {
impl<'w> Help<'w> {
/// Create a new `Help` instance.
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
pub fn new(
w: &'a mut Write,
w: &'w mut Write,
next_line_help: bool,
hide_pv: bool,
color: bool,
@ -128,16 +114,9 @@ impl<'a> Help<'a> {
}
}
/// Reads help settings from an App
/// and write its help to the wrapped stream.
pub fn write_app_help(w: &'a mut Write, app: &App, use_long: bool) -> ClapResult<()> {
debugln!("Help::write_app_help;");
Self::write_parser_help(w, &app.p, use_long)
}
/// Reads help settings from a Parser
/// and write its help to the wrapped stream.
pub fn write_parser_help(w: &'a mut Write, parser: &Parser, use_long: bool) -> ClapResult<()> {
pub fn write_parser_help(w: &'w mut Write, parser: &Parser, use_long: bool) -> ClapResult<()> {
debugln!("Help::write_parser_help;");
Self::_write_parser_help(w, parser, false, use_long)
}
@ -145,14 +124,14 @@ impl<'a> Help<'a> {
/// Reads help settings from a Parser
/// and write its help to the wrapped stream which will be stderr. This method prevents
/// formatting when required.
pub fn write_parser_help_to_stderr(w: &'a mut Write, parser: &Parser) -> ClapResult<()> {
pub fn write_parser_help_to_stderr(w: &'w mut Write, parser: &Parser) -> ClapResult<()> {
debugln!("Help::write_parser_help;");
Self::_write_parser_help(w, parser, true, false)
}
#[doc(hidden)]
pub fn _write_parser_help(
w: &'a mut Write,
w: &'w mut Write,
parser: &Parser,
stderr: bool,
use_long: bool,
@ -163,7 +142,7 @@ impl<'a> Help<'a> {
let color = parser.is_set(AppSettings::ColoredHelp);
let cizer = Colorizer::new(ColorizerOption {
use_stderr: stderr,
when: parser.color(),
when: parser.app.color(),
});
Self::new(
w,
@ -171,8 +150,8 @@ impl<'a> Help<'a> {
hide_v,
color,
cizer,
parser.meta.term_w,
parser.meta.max_w,
parser.app.term_w,
parser.app.max_w,
use_long,
).write_help(parser)
}
@ -180,9 +159,9 @@ impl<'a> Help<'a> {
/// Writes the parser help to the wrapped stream.
pub fn write_help(&mut self, parser: &Parser) -> ClapResult<()> {
debugln!("Help::write_help;");
if let Some(h) = parser.meta.help_str {
if let Some(h) = parser.app.help_str {
write!(self.writer, "{}", h).map_err(Error::from)?;
} else if let Some(tmpl) = parser.meta.template {
} else if let Some(tmpl) = parser.app.template {
self.write_templated_help(parser, tmpl)?;
} else {
self.write_default_help(parser)?;
@ -191,12 +170,13 @@ impl<'a> Help<'a> {
}
}
// Methods to write AnyArg help.
impl<'a> Help<'a> {
// Methods to write Arg help.
impl<'w> Help<'w> {
/// Writes help for each argument in the order they were declared to the wrapped stream.
fn write_args_unsorted<'b: 'd, 'c: 'd, 'd, I: 'd>(&mut self, args: I) -> io::Result<()>
fn write_args_unsorted<'a, 'b, I>(&mut self, args: I) -> io::Result<()>
where
I: Iterator<Item = &'d ArgWithOrder<'b, 'c>>,
'a: 'b,
I: Iterator<Item = &'b Arg<'a, 'b>>,
{
debugln!("Help::write_args_unsorted;");
// The shortest an arg can legally be is 2 (i.e. '-x')
@ -217,15 +197,16 @@ impl<'a> Help<'a> {
} else {
self.writer.write_all(b"\n")?;
}
self.write_arg(arg.as_base())?;
self.write_arg(arg)?;
}
Ok(())
}
/// Sorts arguments by length and display order and write their help to the wrapped stream.
fn write_args<'b: 'd, 'c: 'd, 'd, I: 'd>(&mut self, args: I) -> io::Result<()>
fn write_args<'a, 'b, I>(&mut self, args: I) -> io::Result<()>
where
I: Iterator<Item = &'d ArgWithOrder<'b, 'c>>,
'a: 'b,
I: Iterator<Item = &'b Arg<'a, 'b>>,
{
debugln!("Help::write_args;");
// The shortest an arg can legally be is 2 (i.e. '-x')
@ -233,8 +214,8 @@ impl<'a> Help<'a> {
let mut ord_m = VecMap::new();
// Determine the longest
for arg in args.filter(|arg| {
// If it's NextLineHelp, but we don't care to compute how long because it may be
// NextLineHelp on purpose *because* it's so long and would throw off all other
// If it's NextLineHelp we don't care to compute how long it is because it may be
// NextLineHelp on purpose simply *because* it's so long and would throw off all other
// args alignment
!arg.is_set(ArgSettings::Hidden) || arg.is_set(ArgSettings::NextLineHelp)
}) {
@ -243,8 +224,8 @@ impl<'a> Help<'a> {
self.longest = cmp::max(self.longest, str_width(arg.to_string().as_str()));
debugln!("Help::write_args: New Longest...{}", self.longest);
}
let btm = ord_m.entry(arg.disp_ord()).or_insert(BTreeMap::new());
btm.insert(arg.name(), arg);
let btm = ord_m.entry(arg.disp_ord).or_insert(BTreeMap::new());
btm.insert(arg.name, arg);
}
let mut first = true;
for btm in ord_m.values() {
@ -254,14 +235,14 @@ impl<'a> Help<'a> {
} else {
self.writer.write_all(b"\n")?;
}
self.write_arg(arg.as_base())?;
self.write_arg(arg)?;
}
}
Ok(())
}
/// Writes help for an argument to the wrapped stream.
fn write_arg<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> {
fn write_arg<'b, 'c>(&mut self, arg: &Arg<'b, 'c>) -> io::Result<()> {
debugln!("Help::write_arg;");
self.short(arg)?;
self.long(arg)?;
@ -271,10 +252,10 @@ impl<'a> Help<'a> {
}
/// Writes argument's short command to the wrapped stream.
fn short<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> {
fn short<'b, 'c>(&mut self, arg: &Arg<'b, 'c>) -> io::Result<()> {
debugln!("Help::short;");
write!(self.writer, "{}", TAB)?;
if let Some(s) = arg.short() {
if let Some(s) = arg.short {
color!(self, "-{}", s, good)
} else if arg.has_switch() {
write!(self.writer, "{}", TAB)
@ -284,14 +265,14 @@ impl<'a> Help<'a> {
}
/// Writes argument's long command to the wrapped stream.
fn long<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> io::Result<()> {
fn long<'b, 'c>(&mut self, arg: &Arg<'b, 'c>) -> io::Result<()> {
debugln!("Help::long;");
if !arg.has_switch() {
return Ok(());
}
if arg.takes_value() {
if let Some(l) = arg.long() {
if arg.short().is_some() {
if arg.is_set(ArgSettings::TakesValue) {
if let Some(l) = arg.long {
if arg.short.is_some() {
write!(self.writer, ", ")?;
}
color!(self, "--{}", l, good)?
@ -303,8 +284,8 @@ impl<'a> Help<'a> {
" "
};
write!(self.writer, "{}", sep)?;
} else if let Some(l) = arg.long() {
if arg.short().is_some() {
} else if let Some(l) = arg.long {
if arg.short.is_some() {
write!(self.writer, ", ")?;
}
color!(self, "--{}", l, good)?;
@ -313,15 +294,15 @@ impl<'a> Help<'a> {
}
/// Writes argument's possible values to the wrapped stream.
fn val<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>) -> Result<String, io::Error> {
debugln!("Help::val: arg={}", arg);
if arg.takes_value() {
fn val<'b, 'c>(&mut self, arg: &Arg<'b, 'c>) -> Result<String, io::Error> {
debugln!("Help::val: arg={}", arg.name);
if arg.is_set(ArgSettings::TakesValue) {
let delim = if arg.is_set(ArgSettings::RequireDelimiter) {
arg.val_delim().expect(INTERNAL_ERROR_MSG)
arg.val_delim.expect(INTERNAL_ERROR_MSG)
} else {
' '
};
if let Some(vec) = arg.val_names() {
if let Some(ref vec) = arg.val_names {
let mut it = vec.iter().peekable();
while let Some((_, val)) = it.next() {
color!(self, "<{}>", val, good)?;
@ -333,10 +314,10 @@ impl<'a> Help<'a> {
if arg.is_set(ArgSettings::Multiple) && num == 1 {
color!(self, "...", good)?;
}
} else if let Some(num) = arg.num_vals() {
} else if let Some(num) = arg.num_vals {
let mut it = (0..num).peekable();
while let Some(_) = it.next() {
color!(self, "<{}>", arg.name(), good)?;
color!(self, "<{}>", arg.name, good)?;
if it.peek().is_some() {
write!(self.writer, "{}", delim)?;
}
@ -345,7 +326,7 @@ impl<'a> Help<'a> {
color!(self, "...", good)?;
}
} else if arg.has_switch() {
color!(self, "<{}>", arg.name(), good)?;
color!(self, "<{}>", arg.name, good)?;
if arg.is_set(ArgSettings::Multiple) {
color!(self, "...", good)?;
}
@ -355,7 +336,7 @@ impl<'a> Help<'a> {
}
let spec_vals = self.spec_vals(arg);
let h = arg.help().unwrap_or("");
let h = arg.help.unwrap_or("");
let h_w = str_width(h) + str_width(&*spec_vals);
let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp);
let taken = self.longest + 12;
@ -384,7 +365,7 @@ impl<'a> Help<'a> {
let mut spcs = self.longest - self_len;
// Since we're writing spaces from the tab point we first need to know if we
// had a long and short, or just short
if arg.long().is_some() {
if arg.long.is_some() {
// Only account 4 after the val
spcs += 4;
} else {
@ -440,12 +421,12 @@ impl<'a> Help<'a> {
}
/// Writes argument's help to the wrapped stream.
fn help<'b, 'c>(&mut self, arg: &ArgWithDisplay<'b, 'c>, spec_vals: &str) -> io::Result<()> {
fn help<'b, 'c>(&mut self, arg: &Arg<'b, 'c>, spec_vals: &str) -> io::Result<()> {
debugln!("Help::help;");
let h = if self.use_long {
arg.long_help().unwrap_or_else(|| arg.help().unwrap_or(""))
arg.long_help.unwrap_or_else(|| arg.help.unwrap_or(""))
} else {
arg.help().unwrap_or_else(|| arg.long_help().unwrap_or(""))
arg.help.unwrap_or_else(|| arg.long_help.unwrap_or(""))
};
let mut help = String::from(h) + spec_vals;
let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp) || self.use_long;
@ -496,29 +477,30 @@ impl<'a> Help<'a> {
Ok(())
}
fn spec_vals(&self, a: &ArgWithDisplay) -> String {
fn spec_vals(&self, a: &Arg) -> String {
debugln!("Help::spec_vals: a={}", a);
let mut spec_vals = vec![];
if let Some(ref env) = a.env() {
if let Some(ref env) = a.env {
debugln!(
"Help::spec_vals: Found environment variable...[{:?}:{:?}]",
env.0,
env.1
);
let env_val = if !a.is_set(ArgSettings::HideEnvValues) {
format!("={}", env.1.map_or(Cow::Borrowed(""), |val| val.to_string_lossy()))
format!(
"={}",
env.1
.as_ref()
.map_or(Cow::Borrowed(""), |val| val.to_string_lossy())
)
} else {
String::new()
};
let env_info = format!(
" [env: {}{}]",
env.0.to_string_lossy(),
env_val
);
let env_info = format!(" [env: {}{}]", env.0.to_string_lossy(), env_val);
spec_vals.push(env_info);
}
if !a.is_set(ArgSettings::HideDefaultValue) {
if let Some(pv) = a.default_val() {
if let Some(pv) = a.default_val {
debugln!("Help::spec_vals: Found default value...[{:?}]", pv);
spec_vals.push(format!(
" [default: {}]",
@ -530,23 +512,29 @@ impl<'a> Help<'a> {
));
}
}
if let Some(ref aliases) = a.aliases() {
if let Some(ref aliases) = a.aliases {
debugln!("Help::spec_vals: Found aliases...{:?}", aliases);
spec_vals.push(format!(
" [aliases: {}]",
if self.color {
let als = if self.color {
aliases
.iter()
.map(|v| format!("{}", self.cizer.good(v)))
.filter(|&als| als.1) // visible
.map(|&als| format!("{}", self.cizer.good(als.0))) // name
.collect::<Vec<_>>()
.join(", ")
} else {
aliases.join(", ")
aliases
.iter()
.filter(|&als| als.1)
.map(|&als| als.0)
.collect::<Vec<_>>()
.join(", ")
};
if !als.is_empty() {
spec_vals.push(format!(" [aliases: {}]", als));
}
));
}
if !self.hide_pv && !a.is_set(ArgSettings::HidePossibleValues) {
if let Some(pv) = a.possible_vals() {
if let Some(ref pv) = a.possible_vals {
debugln!("Help::spec_vals: Found possible vals...{:?}", pv);
spec_vals.push(if self.color {
format!(
@ -565,9 +553,121 @@ impl<'a> Help<'a> {
}
}
/// Methods to write a single subcommand
impl<'w> Help<'w> {
fn write_subcommand<'a, 'b>(&mut self, app: &App<'a, 'b>) -> io::Result<()> {
debugln!("Help::write_subcommand;");
write!(self.writer, "{}", TAB)?;
color!(self, "{}", app.name, good)?;
let spec_vals = self.sc_val(app)?;
self.sc_help(app, &*spec_vals)?;
Ok(())
}
fn sc_val<'a, 'b>(&mut self, app: &App<'a, 'b>) -> Result<String, io::Error> {
debugln!("Help::sc_val: app={}", app.name);
let spec_vals = self.sc_spec_vals(app);
let h = app.about.unwrap_or("");
let h_w = str_width(h) + str_width(&*spec_vals);
let nlh = self.next_line_help;
let taken = self.longest + 12;
self.force_next_line = !nlh && self.term_w >= taken
&& (taken as f32 / self.term_w as f32) > 0.40
&& h_w > (self.term_w - taken);
if !(nlh || self.force_next_line) {
write_nspaces!(
self.writer,
self.longest + 4 - (str_width(app.to_string().as_str()))
);
}
Ok(spec_vals)
}
fn sc_spec_vals(&self, a: &App) -> String {
debugln!("Help::sc_spec_vals: a={}", a.name);
let mut spec_vals = vec![];
if let Some(ref aliases) = a.aliases {
debugln!("Help::spec_vals: Found aliases...{:?}", aliases);
let als = if self.color {
aliases
.iter()
.filter(|&als| als.1) // visible
.map(|&als| format!("{}", self.cizer.good(als.0))) // name
.collect::<Vec<_>>()
.join(", ")
} else {
aliases
.iter()
.filter(|&als| als.1)
.map(|&als| als.0)
.collect::<Vec<_>>()
.join(", ")
};
if !als.is_empty() {
spec_vals.push(format!(" [aliases: {}]", als));
}
}
spec_vals.join(" ")
}
fn sc_help<'a, 'b>(&mut self, app: &App<'a, 'b>, spec_vals: &str) -> io::Result<()> {
debugln!("Help::sc_help;");
let h = if self.use_long {
app.long_about.unwrap_or_else(|| app.about.unwrap_or(""))
} else {
app.about.unwrap_or_else(|| app.long_about.unwrap_or(""))
};
let mut help = String::from(h) + spec_vals;
let nlh = self.next_line_help || self.use_long;
debugln!("Help::sc_help: Next Line...{:?}", nlh);
let spcs = if nlh || self.force_next_line {
12 // "tab" * 3
} else {
self.longest + 12
};
let too_long = spcs + str_width(h) + str_width(&*spec_vals) >= self.term_w;
// Is help on next line, if so then indent
if nlh || self.force_next_line {
write!(self.writer, "\n{}{}{}", TAB, TAB, TAB)?;
}
debug!("Help::sc_help: Too long...");
if too_long && spcs <= self.term_w || h.contains("{n}") {
sdebugln!("Yes");
debugln!("Help::sc_help: help...{}", help);
debugln!("Help::sc_help: help width...{}", str_width(&*help));
// Determine how many newlines we need to insert
let avail_chars = self.term_w - spcs;
debugln!("Help::sc_help: Usable space...{}", avail_chars);
help = wrap_help(&help.replace("{n}", "\n"), avail_chars);
} else {
sdebugln!("No");
}
if let Some(part) = help.lines().next() {
write!(self.writer, "{}", part)?;
}
for part in help.lines().skip(1) {
write!(self.writer, "\n")?;
if nlh || self.force_next_line {
write!(self.writer, "{}{}{}", TAB, TAB, TAB)?;
} else {
write_nspaces!(self.writer, self.longest + 8);
}
write!(self.writer, "{}", part)?;
}
if !help.contains('\n') && (nlh || self.force_next_line) {
write!(self.writer, "\n")?;
}
Ok(())
}
}
// Methods to write Parser help.
impl<'a> Help<'a> {
impl<'w> Help<'w> {
/// Writes help for all arguments (options, flags, args, subcommands)
/// including titles of a Parser Object to the wrapped stream.
#[cfg_attr(feature = "lints", allow(useless_let_if_seq))]
@ -575,10 +675,14 @@ impl<'a> Help<'a> {
pub fn write_all_args(&mut self, parser: &Parser) -> ClapResult<()> {
debugln!("Help::write_all_args;");
let flags = parser.has_flags();
let pos = parser
.positionals()
.filter(|arg| !arg.is_set(ArgSettings::Hidden))
.count() > 0;
// Strange filter/count vs fold... https://github.com/rust-lang/rust/issues/33038
let pos = positionals!(parser.app).fold(0, |acc, arg| {
if arg.is_set(ArgSettings::Hidden) {
acc
} else {
acc + 1
}
}) > 0;
let opts = parser.has_opts();
let subcmds = parser.has_visible_subcommands();
@ -587,17 +691,14 @@ impl<'a> Help<'a> {
let mut first = true;
if unified_help && (flags || opts) {
let opts_flags = parser
.flags()
.map(as_arg_trait)
.chain(parser.opts().map(as_arg_trait));
let opts_flags = args!(parser.app).filter(|a| a.has_switch());
color!(self, "OPTIONS:\n", warning)?;
self.write_args(opts_flags)?;
first = false;
} else {
if flags {
color!(self, "FLAGS:\n", warning)?;
self.write_args(parser.flags().map(as_arg_trait))?;
self.write_args(flags!(parser.app))?;
first = false;
}
if opts {
@ -605,7 +706,7 @@ impl<'a> Help<'a> {
self.writer.write_all(b"\n\n")?;
}
color!(self, "OPTIONS:\n", warning)?;
self.write_args(parser.opts().map(as_arg_trait))?;
self.write_args(opts!(parser.app))?;
first = false;
}
}
@ -615,7 +716,7 @@ impl<'a> Help<'a> {
self.writer.write_all(b"\n\n")?;
}
color!(self, "ARGS:\n", warning)?;
self.write_args_unsorted(parser.positionals().map(as_arg_trait))?;
self.write_args_unsorted(positionals!(parser.app))?;
first = false;
}
@ -624,27 +725,23 @@ impl<'a> Help<'a> {
self.writer.write_all(b"\n\n")?;
}
color!(self, "SUBCOMMANDS:\n", warning)?;
self.write_subcommands(parser)?;
self.write_subcommands(&parser.app)?;
}
Ok(())
}
/// Writes help for subcommands of a Parser Object to the wrapped stream.
fn write_subcommands(&mut self, parser: &Parser) -> io::Result<()> {
fn write_subcommands(&mut self, app: &App) -> io::Result<()> {
debugln!("Help::write_subcommands;");
// The shortest an arg can legally be is 2 (i.e. '-x')
self.longest = 2;
let mut ord_m = VecMap::new();
for sc in parser
.subcommands
.iter()
.filter(|s| !s.p.is_set(AppSettings::Hidden))
{
let btm = ord_m.entry(sc.p.meta.disp_ord).or_insert(BTreeMap::new());
self.longest = cmp::max(self.longest, str_width(sc.p.meta.name.as_str()));
for sc in subcommands!(app).filter(|s| !s.is_set(AppSettings::Hidden)) {
let btm = ord_m.entry(sc.disp_ord).or_insert(BTreeMap::new());
self.longest = cmp::max(self.longest, str_width(sc.name.as_str()));
//self.longest = cmp::max(self.longest, sc.p.meta.name.len());
btm.insert(sc.p.meta.name.clone(), sc.clone());
btm.insert(sc.name.clone(), sc.clone());
}
let mut first = true;
@ -655,7 +752,7 @@ impl<'a> Help<'a> {
} else {
self.writer.write_all(b"\n")?;
}
self.write_arg(sc)?;
self.write_subcommand(sc)?;
}
}
Ok(())
@ -664,7 +761,7 @@ impl<'a> Help<'a> {
/// Writes version of a Parser Object to the wrapped stream.
fn write_version(&mut self, parser: &Parser) -> io::Result<()> {
debugln!("Help::write_version;");
write!(self.writer, "{}", parser.meta.version.unwrap_or(""))?;
write!(self.writer, "{}", parser.app.version.unwrap_or(""))?;
Ok(())
}
@ -673,12 +770,12 @@ impl<'a> Help<'a> {
debugln!("Help::write_bin_name;");
macro_rules! write_name {
() => {{
let mut name = parser.meta.name.clone();
let mut name = parser.app.name.clone();
name = name.replace("{n}", "\n");
color!(self, wrap_help(&name, self.term_w), good)?;
}};
}
if let Some(bn) = parser.meta.bin_name.as_ref() {
if let Some(bn) = parser.app.bin_name.as_ref() {
if bn.contains(' ') {
// Incase we're dealing with subcommands i.e. git mv is translated to git-mv
color!(self, bn.replace(" ", "-"), good)?
@ -694,7 +791,7 @@ impl<'a> Help<'a> {
/// Writes default help for a Parser Object to the wrapped stream.
pub fn write_default_help(&mut self, parser: &Parser) -> ClapResult<()> {
debugln!("Help::write_default_help;");
if let Some(h) = parser.meta.pre_help {
if let Some(h) = parser.app.pre_help {
self.write_before_after_help(h)?;
self.writer.write_all(b"\n\n")?;
}
@ -712,21 +809,21 @@ impl<'a> Help<'a> {
self.writer.write_all(b" ")?;
self.write_version(parser)?;
self.writer.write_all(b"\n")?;
if let Some(author) = parser.meta.author {
if let Some(author) = parser.app.author {
write_thing!(author)
}
if self.use_long {
if let Some(about) = parser.meta.long_about {
if let Some(about) = parser.app.long_about {
debugln!("Help::write_default_help: writing long about");
write_thing!(about)
} else if let Some(about) = parser.meta.about {
} else if let Some(about) = parser.app.about {
debugln!("Help::write_default_help: writing about");
write_thing!(about)
}
} else if let Some(about) = parser.meta.about {
} else if let Some(about) = parser.app.about {
debugln!("Help::write_default_help: writing about");
write_thing!(about)
} else if let Some(about) = parser.meta.long_about {
} else if let Some(about) = parser.app.long_about {
debugln!("Help::write_default_help: writing long about");
write_thing!(about)
}
@ -736,7 +833,7 @@ impl<'a> Help<'a> {
self.writer,
"\n{}{}\n\n",
TAB,
usage::create_usage_no_title(parser, &[])
Usage::new(parser).create_usage_no_title(&[])
)?;
let flags = parser.has_flags();
@ -748,7 +845,7 @@ impl<'a> Help<'a> {
self.write_all_args(parser)?;
}
if let Some(h) = parser.meta.more_help {
if let Some(h) = parser.app.more_help {
if flags || opts || pos || subcmds {
self.writer.write_all(b"\n\n")?;
}
@ -856,9 +953,8 @@ fn copy_and_capture<R: Read, W: Write>(
}
}
// Methods to write Parser help using templates.
impl<'a> Help<'a> {
impl<'w> Help<'w> {
/// Write help to stream for the parser in the format defined by the template.
///
/// Tags arg given inside curly brackets:
@ -917,67 +1013,68 @@ impl<'a> Help<'a> {
write!(
self.writer,
"{}",
parser.meta.version.unwrap_or("unknown version")
parser.app.version.unwrap_or("unknown version")
)?;
}
b"author" => {
write!(
self.writer,
"{}",
parser.meta.author.unwrap_or("unknown author")
parser.app.author.unwrap_or("unknown author")
)?;
}
b"about" => {
write!(
self.writer,
"{}",
parser.meta.about.unwrap_or("unknown about")
parser.app.about.unwrap_or("unknown about")
)?;
}
b"long-about" => {
write!(
self.writer,
"{}",
parser.meta.long_about.unwrap_or("unknown about")
parser.app.long_about.unwrap_or("unknown about")
)?;
}
b"usage" => {
write!(self.writer, "{}", usage::create_usage_no_title(parser, &[]))?;
write!(
self.writer,
"{}",
Usage::new(parser).create_usage_no_title(&[])
)?;
}
b"all-args" => {
self.write_all_args(parser)?;
}
b"unified" => {
let opts_flags = parser
.flags()
.map(as_arg_trait)
.chain(parser.opts().map(as_arg_trait));
let opts_flags = parser.app.args.iter().filter(|a| a.has_switch());
self.write_args(opts_flags)?;
}
b"flags" => {
self.write_args(parser.flags().map(as_arg_trait))?;
self.write_args(flags!(parser.app))?;
}
b"options" => {
self.write_args(parser.opts().map(as_arg_trait))?;
self.write_args(opts!(parser.app))?;
}
b"positionals" => {
self.write_args(parser.positionals().map(as_arg_trait))?;
self.write_args(positionals!(parser.app))?;
}
b"subcommands" => {
self.write_subcommands(parser)?;
self.write_subcommands(parser.app)?;
}
b"after-help" => {
write!(
self.writer,
"{}",
parser.meta.more_help.unwrap_or("unknown after-help")
parser.app.more_help.unwrap_or("unknown after-help")
)?;
}
b"before-help" => {
write!(
self.writer,
"{}",
parser.meta.pre_help.unwrap_or("unknown before-help")
parser.app.pre_help.unwrap_or("unknown before-help")
)?;
}
// Unknown tag, write it back.

View file

@ -1,33 +0,0 @@
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[derive(Default, Clone)]
pub struct AppMeta<'b> {
pub name: String,
pub bin_name: Option<String>,
pub author: Option<&'b str>,
pub version: Option<&'b str>,
pub long_version: Option<&'b str>,
pub about: Option<&'b str>,
pub long_about: Option<&'b str>,
pub more_help: Option<&'b str>,
pub pre_help: Option<&'b str>,
pub aliases: Option<Vec<(&'b str, bool)>>, // (name, visible)
pub usage_str: Option<&'b str>,
pub usage: Option<String>,
pub help_str: Option<&'b str>,
pub disp_ord: usize,
pub term_w: Option<usize>,
pub max_w: Option<usize>,
pub template: Option<&'b str>,
}
impl<'b> AppMeta<'b> {
pub fn new() -> Self { Default::default() }
pub fn with_name(s: String) -> Self {
AppMeta {
name: s,
disp_ord: 999,
..Default::default()
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -3,35 +3,37 @@ use std::collections::{BTreeMap, VecDeque};
// Internal
use INTERNAL_ERROR_MSG;
use args::{AnyArg, ArgMatcher, PosBuilder};
use args::{Arg, ArgMatcher};
use args::settings::ArgSettings;
use app::settings::AppSettings as AS;
use app::parser::Parser;
// Creates a usage string for display. This happens just after all arguments were parsed, but before
// any subcommands have been parsed (so as to give subcommands their own usage recursively)
pub fn create_usage_with_title(p: &Parser, used: &[&str]) -> String {
pub struct Usage<'a, 'b, 'c, 'z>(&'z Parser<'a, 'b, 'c>)
where
'a: 'b,
'b: 'c,
'c: 'z;
impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
pub fn new(p: &'z Parser<'a, 'b, 'c>) -> Self { Usage(p) }
// Creates a usage string for display. This happens just after all arguments were parsed, but before
// any subcommands have been parsed (so as to give subcommands their own usage recursively)
pub fn create_usage_with_title(&self, used: &[&str]) -> String {
debugln!("usage::create_usage_with_title;");
let mut usage = String::with_capacity(75);
usage.push_str("USAGE:\n ");
usage.push_str(&*create_usage_no_title(p, used));
usage.push_str(&*self.create_usage_no_title(used));
usage
}
}
// Creates a usage string to be used in error message (i.e. one with currently used args)
pub fn create_error_usage<'a, 'b>(
p: &Parser<'a, 'b>,
matcher: &'b ArgMatcher<'a>,
extra: Option<&str>,
) -> String {
// Creates a usage string to be used in error message (i.e. one with currently used args)
pub fn create_error_usage(&self, matcher: &ArgMatcher<'a>, extra: Option<&str>) -> String {
let mut args: Vec<_> = matcher
.arg_names()
.iter()
.filter(|n| {
if let Some(o) = find_by_name!(p, **n, opts, iter) {
!o.b.is_set(ArgSettings::Required) && !o.b.is_set(ArgSettings::Hidden)
} else if let Some(p) = find_by_name!(p, **n, positionals, values) {
!p.b.is_set(ArgSettings::Required) && p.b.is_set(ArgSettings::Hidden)
.filter(|ref n| {
if let Some(a) = find!(self.0.app, **n) {
!a.is_set(ArgSettings::Required) && !a.is_set(ArgSettings::Hidden)
} else {
true // flags can't be required, so they're always true
}
@ -41,88 +43,83 @@ pub fn create_error_usage<'a, 'b>(
if let Some(r) = extra {
args.push(r);
}
create_usage_with_title(p, &*args)
}
self.create_usage_with_title(&*args)
}
// Creates a usage string (*without title*) if one was not provided by the user manually.
pub fn create_usage_no_title(p: &Parser, used: &[&str]) -> String {
// Creates a usage string (*without title*) if one was not provided by the user manually.
pub fn create_usage_no_title(&self, used: &[&str]) -> String {
debugln!("usage::create_usage_no_title;");
if let Some(u) = p.meta.usage_str {
if let Some(u) = self.0.app.usage_str {
String::from(&*u)
} else if used.is_empty() {
create_help_usage(p, true)
self.create_help_usage(true)
} else {
create_smart_usage(p, used)
self.create_smart_usage(used)
}
}
}
// Creates a usage string for display in help messages (i.e. not for errors)
pub fn create_help_usage(p: &Parser, incl_reqs: bool) -> String {
// Creates a usage string for display in help messages (i.e. not for errors)
pub fn create_help_usage(&self, incl_reqs: bool) -> String {
let mut usage = String::with_capacity(75);
let name = p.meta
let name = self.0
.app
.usage
.as_ref()
.unwrap_or_else(|| p.meta.bin_name.as_ref().unwrap_or(&p.meta.name));
.unwrap_or_else(|| self.0.app.bin_name.as_ref().unwrap_or(&self.0.app.name));
usage.push_str(&*name);
let req_string = if incl_reqs {
let mut reqs: Vec<&str> = p.required().map(|r| &**r).collect();
let mut reqs: Vec<&str> = self.0.required().map(|r| &**r).collect();
reqs.sort();
reqs.dedup();
get_required_usage_from(p, &reqs, None, None, false)
self.get_required_usage_from(&reqs, None, None, false)
.iter()
.fold(String::new(), |a, s| a + &format!(" {}", s)[..])
} else {
String::new()
};
let flags = needs_flags_tag(p);
if flags && !p.is_set(AS::UnifiedHelpMessage) {
let flags = self.needs_flags_tag();
if flags && !self.0.is_set(AS::UnifiedHelpMessage) {
usage.push_str(" [FLAGS]");
} else if flags {
usage.push_str(" [OPTIONS]");
}
if !p.is_set(AS::UnifiedHelpMessage) && p.opts.iter().any(|o| {
!o.is_set(ArgSettings::Required) && !o.is_set(ArgSettings::Hidden)
}) {
if !self.0.is_set(AS::UnifiedHelpMessage)
&& opts!(self.0.app)
.any(|o| !o.is_set(ArgSettings::Required) && !o.is_set(ArgSettings::Hidden))
{
usage.push_str(" [OPTIONS]");
}
usage.push_str(&req_string[..]);
let has_last = p.positionals.values().any(|p| p.is_set(ArgSettings::Last));
let has_last = positionals!(self.0.app).any(|p| p.is_set(ArgSettings::Last));
// places a '--' in the usage string if there are args and options
// supporting multiple values
if p.opts.iter().any(|o| o.is_set(ArgSettings::Multiple))
&& p.positionals
.values()
.any(|p| !p.is_set(ArgSettings::Required))
&& !(p.has_visible_subcommands() || p.is_set(AS::AllowExternalSubcommands))
&& !has_last
if opts!(self.0.app).any(|o| o.is_set(ArgSettings::Multiple))
&& positionals!(self.0.app).any(|p| !p.is_set(ArgSettings::Required))
&& !(self.0.app.has_visible_subcommands()
|| self.0.is_set(AS::AllowExternalSubcommands)) && !has_last
{
usage.push_str(" [--]");
}
let not_req_or_hidden = |p: &PosBuilder| {
let not_req_or_hidden = |p: &Arg| {
(!p.is_set(ArgSettings::Required) || p.is_set(ArgSettings::Last))
&& !p.is_set(ArgSettings::Hidden)
};
if p.has_positionals() && p.positionals.values().any(not_req_or_hidden) {
if let Some(args_tag) = get_args_tag(p, incl_reqs) {
if positionals!(self.0.app).any(not_req_or_hidden) {
if let Some(args_tag) = self.get_args_tag(incl_reqs) {
usage.push_str(&*args_tag);
} else {
usage.push_str(" [ARGS]");
}
if has_last && incl_reqs {
let pos = p.positionals
.values()
.find(|p| p.b.is_set(ArgSettings::Last))
let pos = positionals!(self.0.app)
.find(|p| p.is_set(ArgSettings::Last))
.expect(INTERNAL_ERROR_MSG);
debugln!("usage::create_help_usage: '{}' has .last(true)", pos.name());
debugln!("usage::create_help_usage: '{}' has .last(true)", pos.name);
let req = pos.is_set(ArgSettings::Required);
if req
&& p.positionals
.values()
.any(|p| !p.is_set(ArgSettings::Required))
{
if req && positionals!(self.0.app).any(|p| !p.is_set(ArgSettings::Required)) {
usage.push_str(" -- <");
} else if req {
usage.push_str(" [--] <");
@ -139,18 +136,23 @@ pub fn create_help_usage(p: &Parser, incl_reqs: bool) -> String {
}
// incl_reqs is only false when this function is called recursively
if p.has_visible_subcommands() && incl_reqs || p.is_set(AS::AllowExternalSubcommands) {
if p.is_set(AS::SubcommandsNegateReqs) || p.is_set(AS::ArgsNegateSubcommands) {
if !p.is_set(AS::ArgsNegateSubcommands) {
if self.0.app.has_visible_subcommands() && incl_reqs
|| self.0.is_set(AS::AllowExternalSubcommands)
{
if self.0.is_set(AS::SubcommandsNegateReqs) || self.0.is_set(AS::ArgsNegateSubcommands)
{
if !self.0.is_set(AS::ArgsNegateSubcommands) {
usage.push_str("\n ");
usage.push_str(&*create_help_usage(p, false));
usage.push_str(&*self.create_help_usage(false));
usage.push_str(" <SUBCOMMAND>");
} else {
usage.push_str("\n ");
usage.push_str(&*name);
usage.push_str(" <SUBCOMMAND>");
}
} else if p.is_set(AS::SubcommandRequired) || p.is_set(AS::SubcommandRequiredElseHelp) {
} else if self.0.is_set(AS::SubcommandRequired)
|| self.0.is_set(AS::SubcommandRequiredElseHelp)
{
usage.push_str(" <SUBCOMMAND>");
} else {
usage.push_str(" [SUBCOMMAND]");
@ -159,50 +161,50 @@ pub fn create_help_usage(p: &Parser, incl_reqs: bool) -> String {
usage.shrink_to_fit();
debugln!("usage::create_help_usage: usage={}", usage);
usage
}
}
// Creates a context aware usage string, or "smart usage" from currently used
// args, and requirements
fn create_smart_usage(p: &Parser, used: &[&str]) -> String {
// Creates a context aware usage string, or "smart usage" from currently used
// args, and requirements
fn create_smart_usage(&self, used: &[&str]) -> String {
debugln!("usage::smart_usage;");
let mut usage = String::with_capacity(75);
let mut hs: Vec<&str> = p.required().map(|s| &**s).collect();
let mut hs: Vec<&str> = self.0.required().map(|s| &**s).collect();
hs.extend_from_slice(used);
let r_string = get_required_usage_from(p, &hs, None, None, false)
let r_string = self.get_required_usage_from(&hs, None, None, false)
.iter()
.fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]);
usage.push_str(
&p.meta
&self.0
.app
.usage
.as_ref()
.unwrap_or_else(|| p.meta.bin_name.as_ref().unwrap_or(&p.meta.name))[..],
.unwrap_or_else(|| self.0.app.bin_name.as_ref().unwrap_or(&self.0.app.name))[..],
);
usage.push_str(&*r_string);
if p.is_set(AS::SubcommandRequired) {
if self.0.is_set(AS::SubcommandRequired) {
usage.push_str(" <SUBCOMMAND>");
}
usage.shrink_to_fit();
usage
}
}
// Gets the `[ARGS]` tag for the usage string
fn get_args_tag(p: &Parser, incl_reqs: bool) -> Option<String> {
// Gets the `[ARGS]` tag for the usage string
fn get_args_tag(&self, incl_reqs: bool) -> Option<String> {
debugln!("usage::get_args_tag;");
let mut count = 0;
'outer: for pos in p.positionals
.values()
'outer: for pos in positionals!(self.0.app)
.filter(|pos| !pos.is_set(ArgSettings::Required))
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
.filter(|pos| !pos.is_set(ArgSettings::Last))
{
debugln!("usage::get_args_tag:iter:{}:", pos.b.name);
if let Some(g_vec) = p.groups_for_arg(pos.b.name) {
debugln!("usage::get_args_tag:iter:{}:", pos.name);
if let Some(g_vec) = self.0.groups_for_arg(pos.name) {
for grp_s in &g_vec {
debugln!("usage::get_args_tag:iter:{}:iter:{};", pos.b.name, grp_s);
debugln!("usage::get_args_tag:iter:{}:iter:{};", pos.name, grp_s);
// if it's part of a required group we don't want to count it
if p.groups.iter().any(|g| g.required && (&g.name == grp_s)) {
if groups!(self.0.app).any(|g| g.required && (&g.name == grp_s)) {
continue 'outer;
}
}
@ -213,12 +215,11 @@ fn get_args_tag(p: &Parser, incl_reqs: bool) -> Option<String> {
count
);
}
if !p.is_set(AS::DontCollapseArgsInUsage) && count > 1 {
if !self.0.is_set(AS::DontCollapseArgsInUsage) && count > 1 {
debugln!("usage::get_args_tag:iter: More than one, returning [ARGS]");
return None; // [ARGS]
} else if count == 1 && incl_reqs {
let pos = p.positionals
.values()
let pos = positionals!(self.0.app)
.find(|pos| {
!pos.is_set(ArgSettings::Required) && !pos.is_set(ArgSettings::Hidden)
&& !pos.is_set(ArgSettings::Last)
@ -226,45 +227,42 @@ fn get_args_tag(p: &Parser, incl_reqs: bool) -> Option<String> {
.expect(INTERNAL_ERROR_MSG);
debugln!(
"usage::get_args_tag:iter: Exactly one, returning '{}'",
pos.name()
pos.name
);
return Some(format!(
" [{}]{}",
pos.name_no_brackets(),
pos.multiple_str()
));
} else if p.is_set(AS::DontCollapseArgsInUsage) && !p.positionals.is_empty() && incl_reqs {
} else if self.0.is_set(AS::DontCollapseArgsInUsage) && self.0.has_positionals()
&& incl_reqs
{
debugln!("usage::get_args_tag:iter: Don't collapse returning all");
return Some(
p.positionals
.values()
positionals!(self.0.app)
.filter(|pos| !pos.is_set(ArgSettings::Required))
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
.filter(|pos| !pos.is_set(ArgSettings::Last))
.map(|pos| {
format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str())
})
.map(|pos| format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str()))
.collect::<Vec<_>>()
.join(""),
);
} else if !incl_reqs {
debugln!("usage::get_args_tag:iter: incl_reqs=false, building secondary usage string");
let highest_req_pos = p.positionals
.iter()
.filter_map(|(idx, pos)| {
if pos.b.is_set(ArgSettings::Required) && !pos.b.is_set(ArgSettings::Last) {
Some(idx)
let highest_req_pos = positionals!(self.0.app)
.filter_map(|pos| {
if pos.is_set(ArgSettings::Required) && !pos.is_set(ArgSettings::Last) {
Some(pos.index)
} else {
None
}
})
.max()
.unwrap_or_else(|| p.positionals.len());
.unwrap_or_else(|| Some(positionals!(self.0.app).count() as u64));
return Some(
p.positionals
.iter()
.filter_map(|(idx, pos)| {
if idx <= highest_req_pos {
positionals!(self.0.app)
.filter_map(|pos| {
if pos.index <= highest_req_pos {
Some(pos)
} else {
None
@ -273,31 +271,29 @@ fn get_args_tag(p: &Parser, incl_reqs: bool) -> Option<String> {
.filter(|pos| !pos.is_set(ArgSettings::Required))
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
.filter(|pos| !pos.is_set(ArgSettings::Last))
.map(|pos| {
format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str())
})
.map(|pos| format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str()))
.collect::<Vec<_>>()
.join(""),
);
}
Some("".into())
}
}
// Determines if we need the `[FLAGS]` tag in the usage string
fn needs_flags_tag(p: &Parser) -> bool {
// Determines if we need the `[FLAGS]` tag in the usage string
fn needs_flags_tag(&self) -> bool {
debugln!("usage::needs_flags_tag;");
'outer: for f in &p.flags {
debugln!("usage::needs_flags_tag:iter: f={};", f.b.name);
if let Some(l) = f.s.long {
'outer: for f in flags!(self.0.app) {
debugln!("usage::needs_flags_tag:iter: f={};", f.name);
if let Some(l) = f.long {
if l == "help" || l == "version" {
// Don't print `[FLAGS]` just for help or version
continue;
}
}
if let Some(g_vec) = p.groups_for_arg(f.b.name) {
if let Some(g_vec) = self.0.groups_for_arg(f.name) {
for grp_s in &g_vec {
debugln!("usage::needs_flags_tag:iter:iter: grp_s={};", grp_s);
if p.groups.iter().any(|g| &g.name == grp_s && g.required) {
if groups!(self.0.app).any(|g| &g.name == grp_s && g.required) {
debugln!("usage::needs_flags_tag:iter:iter: Group is required");
continue 'outer;
}
@ -312,16 +308,16 @@ fn needs_flags_tag(p: &Parser) -> bool {
debugln!("usage::needs_flags_tag: [FLAGS] not required");
false
}
}
// Returns the required args in usage string form by fully unrolling all groups
pub fn get_required_usage_from<'a, 'b>(
p: &Parser<'a, 'b>,
reqs: &[&'a str],
// Returns the required args in usage string form by fully unrolling all groups
pub fn get_required_usage_from(
&self,
reqs: &[&str],
matcher: Option<&ArgMatcher<'a>>,
extra: Option<&str>,
incl_last: bool,
) -> VecDeque<String> {
) -> VecDeque<String> {
debugln!(
"usage::get_required_usage_from: reqs={:?}, extra={:?}",
reqs,
@ -332,7 +328,7 @@ pub fn get_required_usage_from<'a, 'b>(
let mut new_reqs: Vec<&str> = vec![];
macro_rules! get_requires {
(@group $a: ident, $v:ident, $p:ident) => {{
if let Some(rl) = p.groups.iter()
if let Some(rl) = groups!(self.0.app)
.filter(|g| g.requires.is_some())
.find(|g| &g.name == $a)
.map(|g| g.requires.as_ref().unwrap()) {
@ -346,10 +342,10 @@ pub fn get_required_usage_from<'a, 'b>(
}
}};
($a:ident, $what:ident, $how:ident, $v:ident, $p:ident) => {{
if let Some(rl) = p.$what.$how()
.filter(|a| a.b.requires.is_some())
.find(|arg| &arg.b.name == $a)
.map(|a| a.b.requires.as_ref().unwrap()) {
if let Some(rl) = $what!(self.0.app)
.filter(|a| a.requires.is_some())
.find(|arg| &arg.name == $a)
.map(|a| a.requires.as_ref().unwrap()) {
for &(_, r) in rl.iter() {
if !$p.contains(&r) {
debugln!("usage::get_required_usage_from:iter:{}: adding arg req={:?}",
@ -406,31 +402,30 @@ pub fn get_required_usage_from<'a, 'b>(
desc_reqs
);
let mut ret_val = VecDeque::new();
let args_in_groups = p.groups
.iter()
let args_in_groups = groups!(self.0.app)
.filter(|gn| desc_reqs.contains(&gn.name))
.flat_map(|g| p.arg_names_in_group(g.name))
.flat_map(|g| self.0.arg_names_in_group(g.name))
.collect::<Vec<_>>();
let pmap = if let Some(m) = matcher {
desc_reqs
.iter()
.filter(|a| p.positionals.values().any(|p| &&p.b.name == a))
.filter(|a| self.0.positionals.values().any(|p| &p == a))
.filter(|&pos| !m.contains(pos))
.filter_map(|pos| p.positionals.values().find(|x| &x.b.name == pos))
.filter_map(|pos| find!(self.0.app, pos))
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
.filter(|pos| !args_in_groups.contains(&pos.b.name))
.map(|pos| (pos.index, pos))
.collect::<BTreeMap<u64, &PosBuilder>>() // sort by index
.filter(|pos| !args_in_groups.contains(&pos.name))
.map(|pos| (pos.index.unwrap(), pos))
.collect::<BTreeMap<u64, &Arg>>() // sort by index
} else {
desc_reqs
.iter()
.filter(|a| p.positionals.values().any(|pos| &&pos.b.name == a))
.filter_map(|pos| p.positionals.values().find(|x| &x.b.name == pos))
.filter(|a| self.0.positionals.values().any(|p| &p == a))
.filter_map(|pos| find!(self.0.app, pos))
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
.filter(|pos| !args_in_groups.contains(&pos.b.name))
.map(|pos| (pos.index, pos))
.collect::<BTreeMap<u64, &PosBuilder>>() // sort by index
.filter(|pos| !args_in_groups.contains(&pos.name))
.map(|pos| (pos.index.unwrap(), pos))
.collect::<BTreeMap<u64, &Arg>>() // sort by index
};
debugln!(
"usage::get_required_usage_from: args_in_groups={:?}",
@ -444,28 +439,23 @@ pub fn get_required_usage_from<'a, 'b>(
}
for a in desc_reqs
.iter()
.filter(|name| !p.positionals.values().any(|p| &&p.b.name == name))
.filter(|name| !p.groups.iter().any(|g| &&g.name == name))
.filter(|name| !positionals!(self.0.app).any(|p| &&p.name == name))
.filter(|name| !groups!(self.0.app).any(|g| &&g.name == name))
.filter(|name| !args_in_groups.contains(name))
.filter(|name| {
!(matcher.is_some() && matcher.as_ref().unwrap().contains(name))
}) {
.filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(name)))
{
debugln!("usage::get_required_usage_from:iter:{}:", a);
let arg = find_by_name!(p, *a, flags, iter)
let arg = find!(self.0.app, a)
.map(|f| f.to_string())
.unwrap_or_else(|| {
find_by_name!(p, *a, opts, iter)
.map(|o| o.to_string())
.expect(INTERNAL_ERROR_MSG)
});
.expect(INTERNAL_ERROR_MSG);
ret_val.push_back(arg);
}
let mut g_vec: Vec<String> = vec![];
for g in desc_reqs
.iter()
.filter(|n| p.groups.iter().any(|g| &&g.name == n))
.filter(|n| groups!(self.0.app).any(|g| &&g.name == n))
{
let g_string = p.args_in_group(g).join("|");
let g_string = self.0.args_in_group(g).join("|");
let elem = format!("<{}>", &g_string[..g_string.len()]);
if !g_vec.contains(&elem) {
g_vec.push(elem);
@ -476,4 +466,5 @@ pub fn get_required_usage_from<'a, 'b>(
}
ret_val
}
}

View file

@ -1,12 +1,11 @@
// std
use std::fmt::Display;
#[allow(unused_imports)]
use std::ascii::AsciiExt;
// Internal
use INTERNAL_ERROR_MSG;
use INVALID_UTF8;
use args::{AnyArg, ArgMatcher, MatchedArg};
use args::{Arg, ArgMatcher, MatchedArg};
use args::settings::ArgSettings;
use errors::{Error, ErrorKind};
use errors::Result as ClapResult;
@ -14,15 +13,16 @@ use osstringext::OsStrExt2;
use app::settings::AppSettings as AS;
use app::parser::{ParseResult, Parser};
use fmt::{Colorizer, ColorizerOption};
use app::usage;
use app::usage::Usage;
pub struct Validator<'a, 'b, 'z>(&'z mut Parser<'a, 'b>)
pub struct Validator<'a, 'b, 'c, 'z>(&'z mut Parser<'a, 'b, 'c>)
where
'a: 'b,
'b: 'z;
'b: 'c,
'c: 'z;
impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
pub fn new(p: &'z mut Parser<'a, 'b>) -> Self { Validator(p) }
impl<'a, 'b, 'c, 'z> Validator<'a, 'b, 'c, 'z> {
pub fn new(p: &'z mut Parser<'a, 'b, 'c>) -> Self { Validator(p) }
pub fn validate(
&mut self,
@ -36,23 +36,19 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
self.0.add_defaults(matcher)?;
if let ParseResult::Opt(a) = needs_val_of {
debugln!("Validator::validate: needs_val_of={:?}", a);
let o = self.0
.opts
.iter()
.find(|o| o.b.name == a)
.expect(INTERNAL_ERROR_MSG);
let o = find!(self.0.app, &a).expect(INTERNAL_ERROR_MSG);
self.validate_required(matcher)?;
reqs_validated = true;
let should_err = if let Some(v) = matcher.0.args.get(&*o.b.name) {
v.vals.is_empty() && !(o.v.min_vals.is_some() && o.v.min_vals.unwrap() == 0)
let should_err = if let Some(v) = matcher.0.args.get(&*o.name) {
v.vals.is_empty() && !(o.min_vals.is_some() && o.min_vals.unwrap() == 0)
} else {
true
};
if should_err {
return Err(Error::empty_value(
o,
&*usage::create_error_usage(self.0, matcher, None),
self.0.color(),
&*Usage::new(self.0).create_error_usage(matcher, None),
self.0.app.color(),
));
}
}
@ -73,21 +69,18 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
self.validate_required(matcher)?;
}
self.validate_matched_args(matcher)?;
matcher.usage(usage::create_usage_with_title(self.0, &[]));
matcher.usage(Usage::new(self.0).create_usage_with_title(&[]));
Ok(())
}
fn validate_arg_values<A>(
fn validate_arg_values(
&self,
arg: &A,
arg: &Arg,
ma: &MatchedArg,
matcher: &ArgMatcher<'a>,
) -> ClapResult<()>
where
A: AnyArg<'a, 'b> + Display,
{
debugln!("Validator::validate_arg_values: arg={:?}", arg.name());
) -> ClapResult<()> {
debugln!("Validator::validate_arg_values: arg={:?}", arg.name);
for val in &ma.vals {
if self.0.is_set(AS::StrictUtf8) && val.to_str().is_none() {
debugln!(
@ -95,11 +88,11 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
val
);
return Err(Error::invalid_utf8(
&*usage::create_error_usage(self.0, matcher, None),
self.0.color(),
&*Usage::new(self.0).create_error_usage(matcher, None),
self.0.app.color(),
));
}
if let Some(p_vals) = arg.possible_vals() {
if let Some(ref p_vals) = arg.possible_vals {
debugln!("Validator::validate_arg_values: possible_vals={:?}", p_vals);
let val_str = val.to_string_lossy();
let ok = if arg.is_set(ArgSettings::CaseInsensitive) {
@ -112,38 +105,38 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
val_str,
p_vals,
arg,
&*usage::create_error_usage(self.0, matcher, None),
self.0.color(),
&*Usage::new(self.0).create_error_usage(matcher, None),
self.0.app.color(),
));
}
}
if !arg.is_set(ArgSettings::EmptyValues) && val.is_empty_()
&& matcher.contains(&*arg.name())
&& matcher.contains(&*arg.name)
{
debugln!("Validator::validate_arg_values: illegal empty val found");
return Err(Error::empty_value(
arg,
&*usage::create_error_usage(self.0, matcher, None),
self.0.color(),
&*Usage::new(self.0).create_error_usage(matcher, None),
self.0.app.color(),
));
}
if let Some(vtor) = arg.validator() {
if let Some(ref vtor) = arg.validator {
debug!("Validator::validate_arg_values: checking validator...");
if let Err(e) = vtor(val.to_string_lossy().into_owned()) {
sdebugln!("error");
return Err(Error::value_validation(Some(arg), e, self.0.color()));
return Err(Error::value_validation(Some(arg), e, self.0.app.color()));
} else {
sdebugln!("good");
}
}
if let Some(vtor) = arg.validator_os() {
if let Some(ref vtor) = arg.validator_os {
debug!("Validator::validate_arg_values: checking validator_os...");
if let Err(e) = vtor(val) {
sdebugln!("error");
return Err(Error::value_validation(
Some(arg),
(*e).to_string_lossy().to_string(),
self.0.color(),
self.0.app.color(),
));
} else {
sdebugln!("good");
@ -153,106 +146,50 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
Ok(())
}
fn build_err(&self, name: &str, matcher: &ArgMatcher) -> ClapResult<()> {
fn build_conflict_err(&self, name: &str, matcher: &ArgMatcher<'a>) -> ClapResult<()> {
debugln!("build_err!: name={}", name);
let mut c_with = find_from!(self.0, &name, blacklist, &matcher);
c_with = c_with.or(
self.0.find_any_arg(&name).map_or(None, |aa| aa.blacklist())
.map_or(None,
|bl| bl.iter().find(|arg| matcher.contains(arg)))
.map_or(None, |an| self.0.find_any_arg(an))
.map_or(None, |aa| Some(format!("{}", aa)))
);
let mut c_with = find_from!(self.0.app, &name, blacklist, &matcher);
c_with = c_with.or(find!(self.0.app, &name)
.map_or(None, |ref aa| aa.blacklist.as_ref())
.map_or(None, |ref bl| bl.iter().find(|arg| matcher.contains(arg)))
.map_or(None, |an| find!(self.0.app, an))
.map_or(None, |aa| Some(format!("{}", aa))));
debugln!("build_err!: '{:?}' conflicts with '{}'", c_with, &name);
// matcher.remove(&name);
let usg = usage::create_error_usage(self.0, matcher, None);
if let Some(f) = find_by_name!(self.0, name, flags, iter) {
// matcher.remove(&name);
let usg = Usage::new(self.0).create_error_usage(matcher, None);
if let Some(f) = find!(self.0.app, &name) {
debugln!("build_err!: It was a flag...");
Err(Error::argument_conflict(f, c_with, &*usg, self.0.color()))
} else if let Some(o) = find_by_name!(self.0, name, opts, iter) {
debugln!("build_err!: It was an option...");
Err(Error::argument_conflict(o, c_with, &*usg, self.0.color()))
Err(Error::argument_conflict(
f,
c_with,
&*usg,
self.0.app.color(),
))
} else {
match find_by_name!(self.0, name, positionals, values) {
Some(p) => {
debugln!("build_err!: It was a positional...");
Err(Error::argument_conflict(p, c_with, &*usg, self.0.color()))
},
None => panic!(INTERNAL_ERROR_MSG)
}
panic!(INTERNAL_ERROR_MSG);
}
}
fn validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
fn validate_blacklist(&self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
debugln!("Validator::validate_blacklist;");
let mut conflicts: Vec<&str> = vec![];
for (&name, _) in matcher.iter() {
for name in &self.gather_conflicts(matcher) {
debugln!("Validator::validate_blacklist:iter:{};", name);
if let Some(grps) = self.0.groups_for_arg(name) {
for grp in &grps {
if let Some(g) = self.0.groups.iter().find(|g| &g.name == grp) {
if !g.multiple {
for arg in &g.args {
if arg == &name {
continue;
}
conflicts.push(arg);
}
}
if let Some(ref gc) = g.conflicts {
conflicts.extend(&*gc);
}
}
}
}
if let Some(arg) = find_any_by_name!(self.0, name) {
if let Some(bl) = arg.blacklist() {
for conf in bl {
if matcher.get(conf).is_some() {
conflicts.push(conf);
}
}
}
} else {
debugln!("Validator::validate_blacklist:iter:{}:group;", name);
let args = self.0.arg_names_in_group(name);
for arg in &args {
debugln!("Validator::validate_blacklist:iter:{}:group:iter:{};", name, arg);
if let Some(bl) = find_any_by_name!(self.0, *arg).unwrap().blacklist() {
for conf in bl {
if matcher.get(conf).is_some() {
conflicts.push(conf);
}
}
}
}
}
}
for name in &conflicts {
debugln!(
"Validator::validate_blacklist:iter:{}: Checking blacklisted arg",
name
);
let mut should_err = false;
if self.0.groups.iter().any(|g| &g.name == name) {
debugln!(
"Validator::validate_blacklist:iter:{}: groups contains it...",
name
);
if groups!(self.0.app).any(|g| &g.name == name) {
debugln!("Validator::validate_blacklist:iter:{}:group;", name);
for n in self.0.arg_names_in_group(name) {
debugln!(
"Validator::validate_blacklist:iter:{}:iter:{}: looking in group...",
"Validator::validate_blacklist:iter:{}:group:iter:{};",
name,
n
);
if matcher.contains(n) {
debugln!(
"Validator::validate_blacklist:iter:{}:iter:{}: matcher contains it...",
"Validator::validate_blacklist:iter:{}:group:iter:{}: found;",
name,
n
);
return self.build_err(n, matcher);
return self.build_conflict_err(n, matcher);
}
}
} else if let Some(ma) = matcher.get(name) {
@ -263,12 +200,66 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
should_err = ma.occurs > 0;
}
if should_err {
return self.build_err(*name, matcher);
return self.build_conflict_err(*name, matcher);
}
}
Ok(())
}
fn gather_conflicts(&self, matcher: &mut ArgMatcher<'a>) -> Vec<&'a str> {
debugln!("Validator::gather_conflicts;");
let mut conflicts = vec![];
for name in matcher.arg_names() {
debugln!("Validator::gather_conflicts:iter:{};", name);
if let Some(arg) = find!(self.0.app, name) {
if let Some(ref bl) = arg.blacklist {
for conf in bl {
if matcher.get(conf).is_some() {
conflicts.push(*conf);
}
}
}
if let Some(grps) = self.0.groups_for_arg(name) {
for grp in &grps {
if let Some(g) = find!(self.0.app, grp, groups) {
if !g.multiple {
for g_arg in &g.args {
if &g_arg == &name {
continue;
}
conflicts.push(g_arg);
}
}
if let Some(ref gc) = g.conflicts {
conflicts.extend(&*gc);
}
}
}
}
} else {
debugln!("Validator::gather_conflicts:iter:{}:group;", name);
let args = self.0.arg_names_in_group(name);
for arg in &args {
debugln!(
"Validator::gather_conflicts:iter:{}:group:iter:{};",
name,
arg
);
if let Some(ref bl) =
find!(self.0.app, arg).expect(INTERNAL_ERROR_MSG).blacklist
{
for conf in bl {
if matcher.get(conf).is_some() {
conflicts.push(conf);
}
}
}
}
}
}
conflicts
}
fn validate_matched_args(&self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
debugln!("Validator::validate_matched_args;");
for (name, ma) in matcher.iter() {
@ -277,25 +268,13 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
name,
ma.vals
);
if let Some(opt) = find_by_name!(self.0, *name, opts, iter) {
self.validate_arg_num_vals(opt, ma, matcher)?;
self.validate_arg_values(opt, ma, matcher)?;
self.validate_arg_requires(opt, ma, matcher)?;
self.validate_arg_num_occurs(opt, ma, matcher)?;
} else if let Some(flag) = find_by_name!(self.0, *name, flags, iter) {
self.validate_arg_requires(flag, ma, matcher)?;
self.validate_arg_num_occurs(flag, ma, matcher)?;
} else if let Some(pos) = find_by_name!(self.0, *name, positionals, values) {
self.validate_arg_num_vals(pos, ma, matcher)?;
self.validate_arg_num_occurs(pos, ma, matcher)?;
self.validate_arg_values(pos, ma, matcher)?;
self.validate_arg_requires(pos, ma, matcher)?;
if let Some(arg) = find!(self.0.app, name) {
self.validate_arg_num_vals(arg, ma, matcher)?;
self.validate_arg_values(arg, ma, matcher)?;
self.validate_arg_requires(arg, ma, matcher)?;
self.validate_arg_num_occurs(arg, ma, matcher)?;
} else {
let grp = self.0
.groups
.iter()
.find(|g| &g.name == name)
.expect(INTERNAL_ERROR_MSG);
let grp = find!(self.0.app, name, groups).expect(INTERNAL_ERROR_MSG);
if let Some(ref g_reqs) = grp.requires {
if g_reqs.iter().any(|&n| !matcher.contains(n)) {
return self.missing_required_error(matcher, None);
@ -306,38 +285,32 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
Ok(())
}
fn validate_arg_num_occurs<A>(
fn validate_arg_num_occurs(
&self,
a: &A,
a: &Arg,
ma: &MatchedArg,
matcher: &ArgMatcher,
) -> ClapResult<()>
where
A: AnyArg<'a, 'b> + Display,
{
debugln!("Validator::validate_arg_num_occurs: a={};", a.name());
matcher: &ArgMatcher<'a>,
) -> ClapResult<()> {
debugln!("Validator::validate_arg_num_occurs: a={};", a.name);
if ma.occurs > 1 && !a.is_set(ArgSettings::Multiple) {
// Not the first time, and we don't allow multiples
return Err(Error::unexpected_multiple_usage(
a,
&*usage::create_error_usage(self.0, matcher, None),
self.0.color(),
&*Usage::new(self.0).create_error_usage(matcher, None),
self.0.app.color(),
));
}
Ok(())
}
fn validate_arg_num_vals<A>(
fn validate_arg_num_vals(
&self,
a: &A,
a: &Arg,
ma: &MatchedArg,
matcher: &ArgMatcher,
) -> ClapResult<()>
where
A: AnyArg<'a, 'b> + Display,
{
matcher: &ArgMatcher<'a>,
) -> ClapResult<()> {
debugln!("Validator::validate_arg_num_vals;");
if let Some(num) = a.num_vals() {
if let Some(num) = a.num_vals {
debugln!("Validator::validate_arg_num_vals: num_vals set...{}", num);
let should_err = if a.is_set(ArgSettings::Multiple) {
((ma.vals.len() as u64) % num) != 0
@ -361,12 +334,12 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
} else {
"ere"
},
&*usage::create_error_usage(self.0, matcher, None),
self.0.color(),
&*Usage::new(self.0).create_error_usage(matcher, None),
self.0.app.color(),
));
}
}
if let Some(num) = a.max_vals() {
if let Some(num) = a.max_vals {
debugln!("Validator::validate_arg_num_vals: max_vals set...{}", num);
if (ma.vals.len() as u64) > num {
debugln!("Validator::validate_arg_num_vals: Sending error TooManyValues");
@ -378,12 +351,12 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
.to_str()
.expect(INVALID_UTF8),
a,
&*usage::create_error_usage(self.0, matcher, None),
self.0.color(),
&*Usage::new(self.0).create_error_usage(matcher, None),
self.0.app.color(),
));
}
}
let min_vals_zero = if let Some(num) = a.min_vals() {
let min_vals_zero = if let Some(num) = a.min_vals {
debugln!("Validator::validate_arg_num_vals: min_vals set: {}", num);
if (ma.vals.len() as u64) < num && num != 0 {
debugln!("Validator::validate_arg_num_vals: Sending error TooFewValues");
@ -391,8 +364,8 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
a,
num,
ma.vals.len(),
&*usage::create_error_usage(self.0, matcher, None),
self.0.color(),
&*Usage::new(self.0).create_error_usage(matcher, None),
self.0.app.color(),
));
}
num == 0
@ -401,27 +374,24 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
};
// Issue 665 (https://github.com/kbknapp/clap-rs/issues/665)
// Issue 1105 (https://github.com/kbknapp/clap-rs/issues/1105)
if a.takes_value() && !min_vals_zero && ma.vals.is_empty() {
if a.is_set(ArgSettings::TakesValue) && !min_vals_zero && ma.vals.is_empty() {
return Err(Error::empty_value(
a,
&*usage::create_error_usage(self.0, matcher, None),
self.0.color(),
&*Usage::new(self.0).create_error_usage(matcher, None),
self.0.app.color(),
));
}
Ok(())
}
fn validate_arg_requires<A>(
fn validate_arg_requires(
&self,
a: &A,
a: &Arg,
ma: &MatchedArg,
matcher: &ArgMatcher,
) -> ClapResult<()>
where
A: AnyArg<'a, 'b> + Display,
{
debugln!("Validator::validate_arg_requires:{};", a.name());
if let Some(a_reqs) = a.requires() {
matcher: &ArgMatcher<'a>,
) -> ClapResult<()> {
debugln!("Validator::validate_arg_requires:{};", a.name);
if let Some(ref a_reqs) = a.requires {
for &(val, name) in a_reqs.iter().filter(|&&(val, _)| val.is_some()) {
let missing_req =
|v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(name);
@ -438,7 +408,7 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
Ok(())
}
fn validate_required(&self, matcher: &ArgMatcher) -> ClapResult<()> {
fn validate_required(&self, matcher: &ArgMatcher<'a>) -> ClapResult<()> {
debugln!(
"Validator::validate_required: required={:?};",
self.0.required
@ -449,7 +419,7 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
if matcher.contains(name) {
continue 'outer;
}
if let Some(a) = find_any_by_name!(self.0, *name) {
if let Some(a) = find!(self.0.app, name) {
if self.is_missing_required_ok(a, matcher) {
continue 'outer;
}
@ -468,28 +438,32 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
Ok(())
}
fn validate_arg_conflicts(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool> {
debugln!("Validator::validate_arg_conflicts: a={:?};", a.name());
a.blacklist().map(|bl| {
bl.iter().any(|conf| {
fn is_missing_required_ok(&self, a: &Arg<'a, 'b>, matcher: &ArgMatcher<'a>) -> bool {
debugln!("Validator::is_missing_required_ok: a={}", a.name);
self.validate_arg_conflicts(a, matcher).unwrap_or(false)
|| self.validate_required_unless(a, matcher).unwrap_or(false)
|| self.0.overriden.contains(&a.name)
}
fn validate_arg_conflicts(&self, a: &Arg<'a, 'b>, matcher: &ArgMatcher<'a>) -> Option<bool> {
debugln!("Validator::validate_arg_conflicts: a={:?};", a.name);
a.blacklist.as_ref().map(|bl| {
bl.iter().any(|ref conf| {
matcher.contains(conf)
|| self.0
.groups
.iter()
.find(|g| &g.name == conf)
|| find!(self.0.app, *conf, groups)
.map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg)))
})
})
}
fn validate_required_unless(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool> {
debugln!("Validator::validate_required_unless: a={:?};", a.name());
fn validate_required_unless(&self, a: &Arg<'a, 'b>, matcher: &ArgMatcher<'a>) -> Option<bool> {
debugln!("Validator::validate_required_unless: a={:?};", a.name);
macro_rules! check {
($how:ident, $_self:expr, $a:ident, $m:ident) => {{
$a.required_unless().map(|ru| {
$a.r_unless.as_ref().map(|ru| {
ru.iter().$how(|n| {
$m.contains(n) || {
if let Some(grp) = $_self.groups.iter().find(|g| &g.name == n) {
if let Some(grp) = find!($_self.app, n, groups) {
grp.args.iter().any(|arg| $m.contains(arg))
} else {
false
@ -506,11 +480,15 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
}
}
fn missing_required_error(&self, matcher: &ArgMatcher, extra: Option<&str>) -> ClapResult<()> {
fn missing_required_error(
&self,
matcher: &ArgMatcher<'a>,
extra: Option<&str>,
) -> ClapResult<()> {
debugln!("Validator::missing_required_error: extra={:?}", extra);
let c = Colorizer::new(ColorizerOption {
use_stderr: true,
when: self.0.color(),
when: self.0.app.color(),
});
let mut reqs = self.0.required.iter().map(|&r| &*r).collect::<Vec<_>>();
if let Some(r) = extra {
@ -519,8 +497,8 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
reqs.retain(|n| !matcher.contains(n));
reqs.dedup();
debugln!("Validator::missing_required_error: reqs={:#?}", reqs);
let req_args =
usage::get_required_usage_from(self.0, &reqs[..], Some(matcher), extra, true)
let req_args = Usage::new(self.0)
.get_required_usage_from(&reqs[..], Some(matcher), extra, true)
.iter()
.fold(String::new(), |acc, s| {
acc + &format!("\n {}", c.error(s))[..]
@ -531,15 +509,8 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
);
Err(Error::missing_required_argument(
&*req_args,
&*usage::create_error_usage(self.0, matcher, extra),
self.0.color(),
&*Usage::new(self.0).create_error_usage(matcher, extra),
self.0.app.color(),
))
}
#[inline]
fn is_missing_required_ok(&self, a: &AnyArg, matcher: &ArgMatcher) -> bool {
debugln!("Validator::is_missing_required_ok: a={}", a.name());
self.validate_arg_conflicts(a, matcher).unwrap_or(false)
|| self.validate_required_unless(a, matcher).unwrap_or(false)
}
}

View file

@ -1,74 +0,0 @@
// Std
use std::rc::Rc;
use std::fmt as std_fmt;
use std::ffi::{OsStr, OsString};
// Internal
use args::settings::ArgSettings;
use map::{self, VecMap};
use INTERNAL_ERROR_MSG;
#[doc(hidden)]
pub trait AnyArg<'n, 'e>: std_fmt::Display {
fn name(&self) -> &'n str;
fn overrides(&self) -> Option<&[&'e str]>;
fn aliases(&self) -> Option<Vec<&'e str>>;
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]>;
fn blacklist(&self) -> Option<&[&'e str]>;
fn required_unless(&self) -> Option<&[&'e str]>;
fn is_set(&self, ArgSettings) -> bool;
fn set(&mut self, ArgSettings);
fn has_switch(&self) -> bool;
fn max_vals(&self) -> Option<u64>;
fn min_vals(&self) -> Option<u64>;
fn num_vals(&self) -> Option<u64>;
fn possible_vals(&self) -> Option<&[&'e str]>;
fn validator(&self) -> Option<&Rc<Fn(String) -> Result<(), String>>>;
fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> Result<(), OsString>>>;
fn short(&self) -> Option<char>;
fn long(&self) -> Option<&'e str>;
fn val_delim(&self) -> Option<char>;
fn takes_value(&self) -> bool;
fn val_names(&self) -> Option<&VecMap<&'e str>>;
fn help(&self) -> Option<&'e str>;
fn long_help(&self) -> Option<&'e str>;
fn default_val(&self) -> Option<&'e OsStr>;
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>>;
fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)>;
fn longest_filter(&self) -> bool;
fn val_terminator(&self) -> Option<&'e str>;
}
pub trait DispOrder {
fn disp_ord(&self) -> usize;
}
impl<'n, 'e, 'z, T: ?Sized> AnyArg<'n, 'e> for &'z T where T: AnyArg<'n, 'e> + 'z {
fn name(&self) -> &'n str { (*self).name() }
fn overrides(&self) -> Option<&[&'e str]> { (*self).overrides() }
fn aliases(&self) -> Option<Vec<&'e str>> { (*self).aliases() }
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> { (*self).requires() }
fn blacklist(&self) -> Option<&[&'e str]> { (*self).blacklist() }
fn required_unless(&self) -> Option<&[&'e str]> { (*self).required_unless() }
fn is_set(&self, a: ArgSettings) -> bool { (*self).is_set(a) }
fn set(&mut self, _: ArgSettings) { panic!(INTERNAL_ERROR_MSG) }
fn has_switch(&self) -> bool { (*self).has_switch() }
fn max_vals(&self) -> Option<u64> { (*self).max_vals() }
fn min_vals(&self) -> Option<u64> { (*self).min_vals() }
fn num_vals(&self) -> Option<u64> { (*self).num_vals() }
fn possible_vals(&self) -> Option<&[&'e str]> { (*self).possible_vals() }
fn validator(&self) -> Option<&Rc<Fn(String) -> Result<(), String>>> { (*self).validator() }
fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> Result<(), OsString>>> { (*self).validator_os() }
fn short(&self) -> Option<char> { (*self).short() }
fn long(&self) -> Option<&'e str> { (*self).long() }
fn val_delim(&self) -> Option<char> { (*self).val_delim() }
fn takes_value(&self) -> bool { (*self).takes_value() }
fn val_names(&self) -> Option<&VecMap<&'e str>> { (*self).val_names() }
fn help(&self) -> Option<&'e str> { (*self).help() }
fn long_help(&self) -> Option<&'e str> { (*self).long_help() }
fn default_val(&self) -> Option<&'e OsStr> { (*self).default_val() }
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> { (*self).default_vals_ifs() }
fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> { (*self).env() }
fn longest_filter(&self) -> bool { (*self).longest_filter() }
fn val_terminator(&self) -> Option<&'e str> { (*self).val_terminator() }
}

View file

@ -1,20 +1,23 @@
#[cfg(feature = "yaml")]
use std::collections::BTreeMap;
use std::rc::Rc;
use std::borrow::Cow;
use std::fmt::{self, Display, Formatter};
use std::ffi::{OsStr, OsString};
#[cfg(target_os = "windows")]
use osstringext::OsStrExt3;
#[cfg(not(target_os = "windows"))]
use std::os::unix::ffi::OsStrExt;
use std::env;
use std::cmp::{Ord, Ordering};
#[cfg(feature = "yaml")]
use yaml_rust::Yaml;
use map::VecMap;
use usage_parser::UsageParser;
use args::settings::ArgSettings;
use args::arg_builder::{Base, Switched, Valued};
use args::settings::{ArgFlags, ArgSettings};
use INTERNAL_ERROR_MSG;
/// The abstract representation of a command line argument. Used to set all the options and
/// relationships that define a valid argument for the program.
@ -44,11 +47,62 @@ pub struct Arg<'a, 'b>
where
'a: 'b,
{
#[doc(hidden)] pub b: Base<'a, 'b>,
#[doc(hidden)] pub s: Switched<'b>,
#[doc(hidden)] pub v: Valued<'a, 'b>,
#[doc(hidden)] pub index: Option<u64>,
#[doc(hidden)] pub r_ifs: Option<Vec<(&'a str, &'b str)>>,
#[doc(hidden)]
pub name: &'a str,
#[doc(hidden)]
pub help: Option<&'b str>,
#[doc(hidden)]
pub long_help: Option<&'b str>,
#[doc(hidden)]
pub blacklist: Option<Vec<&'a str>>,
#[doc(hidden)]
pub settings: ArgFlags,
#[doc(hidden)]
pub r_unless: Option<Vec<&'a str>>,
#[doc(hidden)]
pub overrides: Option<Vec<&'a str>>,
#[doc(hidden)]
pub groups: Option<Vec<&'a str>>,
#[doc(hidden)]
pub requires: Option<Vec<(Option<&'b str>, &'a str)>>,
#[doc(hidden)]
pub short: Option<char>,
#[doc(hidden)]
pub long: Option<&'b str>,
#[doc(hidden)]
pub aliases: Option<Vec<(&'b str, bool)>>, // (name, visible)
#[doc(hidden)]
pub disp_ord: usize,
#[doc(hidden)]
pub unified_ord: usize,
#[doc(hidden)]
pub possible_vals: Option<Vec<&'b str>>,
#[doc(hidden)]
pub val_names: Option<VecMap<&'b str>>,
#[doc(hidden)]
pub num_vals: Option<u64>,
#[doc(hidden)]
pub max_vals: Option<u64>,
#[doc(hidden)]
pub min_vals: Option<u64>,
#[doc(hidden)]
pub validator: Option<Rc<Fn(String) -> Result<(), String>>>,
#[doc(hidden)]
pub validator_os: Option<Rc<Fn(&OsStr) -> Result<(), OsString>>>,
#[doc(hidden)]
pub val_delim: Option<char>,
#[doc(hidden)]
pub default_val: Option<&'b OsStr>,
#[doc(hidden)]
pub default_vals_ifs: Option<VecMap<(&'a str, Option<&'b OsStr>, &'b OsStr)>>,
#[doc(hidden)]
pub env: Option<(&'a OsStr, Option<OsString>)>,
#[doc(hidden)]
pub terminator: Option<&'b str>,
#[doc(hidden)]
pub index: Option<u64>,
#[doc(hidden)]
pub r_ifs: Option<Vec<(&'a str, &'b str)>>,
}
impl<'a, 'b> Arg<'a, 'b> {
@ -71,7 +125,9 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`Arg`]: ./struct.Arg.html
pub fn with_name(n: &'a str) -> Self {
Arg {
b: Base::new(n),
name: n,
disp_ord: 999,
unified_ord: 999,
..Default::default()
}
}
@ -146,8 +202,7 @@ impl<'a, 'b> Arg<'a, 'b> {
}
s => panic!(
"Unknown Arg setting '{}' in YAML file for arg '{}'",
s,
name_str
s, name_str
),
}
}
@ -328,7 +383,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// ```
/// [`short`]: ./struct.Arg.html#method.short
pub fn short<S: AsRef<str>>(mut self, s: S) -> Self {
self.s.short = s.as_ref().trim_left_matches(|c| c == '-').chars().nth(0);
self.short = s.as_ref().trim_left_matches(|c| c == '-').chars().nth(0);
self
}
@ -368,7 +423,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// assert!(m.is_present("cfg"));
/// ```
pub fn long(mut self, l: &'b str) -> Self {
self.s.long = Some(l.trim_left_matches(|c| c == '-'));
self.long = Some(l.trim_left_matches(|c| c == '-'));
self
}
@ -394,10 +449,10 @@ impl<'a, 'b> Arg<'a, 'b> {
/// ```
/// [`Arg`]: ./struct.Arg.html
pub fn alias<S: Into<&'b str>>(mut self, name: S) -> Self {
if let Some(ref mut als) = self.s.aliases {
if let Some(ref mut als) = self.aliases {
als.push((name.into(), false));
} else {
self.s.aliases = Some(vec![(name.into(), false)]);
self.aliases = Some(vec![(name.into(), false)]);
}
self
}
@ -424,12 +479,12 @@ impl<'a, 'b> Arg<'a, 'b> {
/// ```
/// [`Arg`]: ./struct.Arg.html
pub fn aliases(mut self, names: &[&'b str]) -> Self {
if let Some(ref mut als) = self.s.aliases {
if let Some(ref mut als) = self.aliases {
for n in names {
als.push((n, false));
}
} else {
self.s.aliases = Some(names.iter().map(|n| (*n, false)).collect::<Vec<_>>());
self.aliases = Some(names.iter().map(|n| (*n, false)).collect::<Vec<_>>());
}
self
}
@ -455,10 +510,10 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`Arg`]: ./struct.Arg.html
/// [`App::alias`]: ./struct.Arg.html#method.alias
pub fn visible_alias<S: Into<&'b str>>(mut self, name: S) -> Self {
if let Some(ref mut als) = self.s.aliases {
if let Some(ref mut als) = self.aliases {
als.push((name.into(), true));
} else {
self.s.aliases = Some(vec![(name.into(), true)]);
self.aliases = Some(vec![(name.into(), true)]);
}
self
}
@ -482,12 +537,12 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`Arg`]: ./struct.Arg.html
/// [`App::aliases`]: ./struct.Arg.html#method.aliases
pub fn visible_aliases(mut self, names: &[&'b str]) -> Self {
if let Some(ref mut als) = self.s.aliases {
if let Some(ref mut als) = self.aliases {
for n in names {
als.push((n, true));
}
} else {
self.s.aliases = Some(names.iter().map(|n| (*n, true)).collect::<Vec<_>>());
self.aliases = Some(names.iter().map(|n| (*n, true)).collect::<Vec<_>>());
}
self
}
@ -543,7 +598,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// ```
/// [`Arg::long_help`]: ./struct.Arg.html#method.long_help
pub fn help(mut self, h: &'b str) -> Self {
self.b.help = Some(h);
self.help = Some(h);
self
}
@ -614,7 +669,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// ```
/// [`Arg::help`]: ./struct.Arg.html#method.help
pub fn long_help(mut self, h: &'b str) -> Self {
self.b.long_help = Some(h);
self.long_help = Some(h);
self
}
@ -940,10 +995,10 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`Arg::required`]: ./struct.Arg.html#method.required
/// [`Arg::required_unless(name)`]: ./struct.Arg.html#method.required_unless
pub fn required_unless(mut self, name: &'a str) -> Self {
if let Some(ref mut vec) = self.b.r_unless {
if let Some(ref mut vec) = self.r_unless {
vec.push(name);
} else {
self.b.r_unless = Some(vec![name]);
self.r_unless = Some(vec![name]);
}
self.required(true)
}
@ -1012,12 +1067,12 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`Arg::required_unless_one`]: ./struct.Arg.html#method.required_unless_one
/// [`Arg::required_unless_all(names)`]: ./struct.Arg.html#method.required_unless_all
pub fn required_unless_all(mut self, names: &[&'a str]) -> Self {
if let Some(ref mut vec) = self.b.r_unless {
if let Some(ref mut vec) = self.r_unless {
for s in names {
vec.push(s);
}
} else {
self.b.r_unless = Some(names.iter().map(|s| *s).collect::<Vec<_>>());
self.r_unless = Some(names.iter().map(|s| *s).collect::<Vec<_>>());
}
self.setb(ArgSettings::RequiredUnlessAll);
self.required(true)
@ -1088,12 +1143,12 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`Arg::required_unless_one(names)`]: ./struct.Arg.html#method.required_unless_one
/// [`Arg::required_unless_all`]: ./struct.Arg.html#method.required_unless_all
pub fn required_unless_one(mut self, names: &[&'a str]) -> Self {
if let Some(ref mut vec) = self.b.r_unless {
if let Some(ref mut vec) = self.r_unless {
for s in names {
vec.push(s);
}
} else {
self.b.r_unless = Some(names.iter().map(|s| *s).collect::<Vec<_>>());
self.r_unless = Some(names.iter().map(|s| *s).collect::<Vec<_>>());
}
self.required(true)
}
@ -1136,10 +1191,10 @@ impl<'a, 'b> Arg<'a, 'b> {
/// assert_eq!(res.unwrap_err().kind, ErrorKind::ArgumentConflict);
/// ```
pub fn conflicts_with(mut self, name: &'a str) -> Self {
if let Some(ref mut vec) = self.b.blacklist {
if let Some(ref mut vec) = self.blacklist {
vec.push(name);
} else {
self.b.blacklist = Some(vec![name]);
self.blacklist = Some(vec![name]);
}
self
}
@ -1186,12 +1241,12 @@ impl<'a, 'b> Arg<'a, 'b> {
/// ```
/// [`Arg::conflicts_with`]: ./struct.Arg.html#method.conflicts_with
pub fn conflicts_with_all(mut self, names: &[&'a str]) -> Self {
if let Some(ref mut vec) = self.b.blacklist {
if let Some(ref mut vec) = self.blacklist {
for s in names {
vec.push(s);
}
} else {
self.b.blacklist = Some(names.iter().map(|s| *s).collect::<Vec<_>>());
self.blacklist = Some(names.iter().map(|s| *s).collect::<Vec<_>>());
}
self
}
@ -1223,10 +1278,10 @@ impl<'a, 'b> Arg<'a, 'b> {
/// assert!(!m.is_present("flag"));
/// ```
pub fn overrides_with(mut self, name: &'a str) -> Self {
if let Some(ref mut vec) = self.b.overrides {
if let Some(ref mut vec) = self.overrides {
vec.push(name.as_ref());
} else {
self.b.overrides = Some(vec![name.as_ref()]);
self.overrides = Some(vec![name.as_ref()]);
}
self
}
@ -1259,12 +1314,12 @@ impl<'a, 'b> Arg<'a, 'b> {
/// assert!(!m.is_present("flag"));
/// ```
pub fn overrides_with_all(mut self, names: &[&'a str]) -> Self {
if let Some(ref mut vec) = self.b.overrides {
if let Some(ref mut vec) = self.overrides {
for s in names {
vec.push(s);
}
} else {
self.b.overrides = Some(names.iter().map(|s| *s).collect::<Vec<_>>());
self.overrides = Some(names.iter().map(|s| *s).collect::<Vec<_>>());
}
self
}
@ -1325,12 +1380,12 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
/// [override]: ./struct.Arg.html#method.overrides_with
pub fn requires(mut self, name: &'a str) -> Self {
if let Some(ref mut vec) = self.b.requires {
if let Some(ref mut vec) = self.requires {
vec.push((None, name));
} else {
let mut vec = vec![];
vec.push((None, name));
self.b.requires = Some(vec);
self.requires = Some(vec);
}
self
}
@ -1395,10 +1450,10 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
/// [override]: ./struct.Arg.html#method.overrides_with
pub fn requires_if(mut self, val: &'b str, arg: &'a str) -> Self {
if let Some(ref mut vec) = self.b.requires {
if let Some(ref mut vec) = self.requires {
vec.push((Some(val), arg));
} else {
self.b.requires = Some(vec![(Some(val), arg)]);
self.requires = Some(vec![(Some(val), arg)]);
}
self
}
@ -1455,7 +1510,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
/// [override]: ./struct.Arg.html#method.overrides_with
pub fn requires_ifs(mut self, ifs: &[(&'b str, &'a str)]) -> Self {
if let Some(ref mut vec) = self.b.requires {
if let Some(ref mut vec) = self.requires {
for &(val, arg) in ifs {
vec.push((Some(val), arg));
}
@ -1464,7 +1519,7 @@ impl<'a, 'b> Arg<'a, 'b> {
for &(val, arg) in ifs {
vec.push((Some(val), arg));
}
self.b.requires = Some(vec);
self.requires = Some(vec);
}
self
}
@ -1699,7 +1754,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [override]: ./struct.Arg.html#method.overrides_with
/// [`Arg::requires_all(&[arg, arg2])`]: ./struct.Arg.html#method.requires_all
pub fn requires_all(mut self, names: &[&'a str]) -> Self {
if let Some(ref mut vec) = self.b.requires {
if let Some(ref mut vec) = self.requires {
for s in names {
vec.push((None, s));
}
@ -1708,7 +1763,7 @@ impl<'a, 'b> Arg<'a, 'b> {
for s in names {
vec.push((None, *s));
}
self.b.requires = Some(vec);
self.requires = Some(vec);
}
self
}
@ -2127,7 +2182,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`max_values`]: ./struct.Arg.html#method.max_values
pub fn value_terminator(mut self, term: &'b str) -> Self {
self.setb(ArgSettings::TakesValue);
self.v.terminator = Some(term);
self.terminator = Some(term);
self
}
@ -2319,12 +2374,12 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [options]: ./struct.Arg.html#method.takes_value
/// [positional arguments]: ./struct.Arg.html#method.index
pub fn possible_values(mut self, names: &[&'b str]) -> Self {
if let Some(ref mut vec) = self.v.possible_vals {
if let Some(ref mut vec) = self.possible_vals {
for s in names {
vec.push(s);
}
} else {
self.v.possible_vals = Some(names.iter().map(|s| *s).collect::<Vec<_>>());
self.possible_vals = Some(names.iter().map(|s| *s).collect::<Vec<_>>());
}
self
}
@ -2383,10 +2438,10 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [options]: ./struct.Arg.html#method.takes_value
/// [positional arguments]: ./struct.Arg.html#method.index
pub fn possible_value(mut self, name: &'b str) -> Self {
if let Some(ref mut vec) = self.v.possible_vals {
if let Some(ref mut vec) = self.possible_vals {
vec.push(name);
} else {
self.v.possible_vals = Some(vec![name]);
self.possible_vals = Some(vec![name]);
}
self
}
@ -2475,10 +2530,10 @@ impl<'a, 'b> Arg<'a, 'b> {
/// ```
/// [`ArgGroup`]: ./struct.ArgGroup.html
pub fn group(mut self, name: &'a str) -> Self {
if let Some(ref mut vec) = self.b.groups {
if let Some(ref mut vec) = self.groups {
vec.push(name);
} else {
self.b.groups = Some(vec![name]);
self.groups = Some(vec![name]);
}
self
}
@ -2515,12 +2570,12 @@ impl<'a, 'b> Arg<'a, 'b> {
/// ```
/// [`ArgGroup`]: ./struct.ArgGroup.html
pub fn groups(mut self, names: &[&'a str]) -> Self {
if let Some(ref mut vec) = self.b.groups {
if let Some(ref mut vec) = self.groups {
for s in names {
vec.push(s);
}
} else {
self.b.groups = Some(names.into_iter().map(|s| *s).collect::<Vec<_>>());
self.groups = Some(names.into_iter().map(|s| *s).collect::<Vec<_>>());
}
self
}
@ -2563,7 +2618,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
pub fn number_of_values(mut self, qty: u64) -> Self {
self.setb(ArgSettings::TakesValue);
self.v.num_vals = Some(qty);
self.num_vals = Some(qty);
self
}
@ -2607,7 +2662,7 @@ impl<'a, 'b> Arg<'a, 'b> {
where
F: Fn(String) -> Result<(), String> + 'static,
{
self.v.validator = Some(Rc::new(f));
self.validator = Some(Rc::new(f));
self
}
@ -2645,7 +2700,7 @@ impl<'a, 'b> Arg<'a, 'b> {
where
F: Fn(&OsStr) -> Result<(), OsString> + 'static,
{
self.v.validator_os = Some(Rc::new(f));
self.validator_os = Some(Rc::new(f));
self
}
@ -2707,7 +2762,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
pub fn max_values(mut self, qty: u64) -> Self {
self.setb(ArgSettings::TakesValue);
self.v.max_vals = Some(qty);
self.max_vals = Some(qty);
self
}
@ -2769,7 +2824,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// ```
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
pub fn min_values(mut self, qty: u64) -> Self {
self.v.min_vals = Some(qty);
self.min_vals = Some(qty);
self.set(ArgSettings::TakesValue)
}
@ -2821,14 +2876,14 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`Arg::value_delimiter`]: ./struct.Arg.html#method.value_delimiter
pub fn use_delimiter(mut self, d: bool) -> Self {
if d {
if self.v.val_delim.is_none() {
self.v.val_delim = Some(',');
if self.val_delim.is_none() {
self.val_delim = Some(',');
}
self.setb(ArgSettings::TakesValue);
self.setb(ArgSettings::UseValueDelimiter);
self.unset(ArgSettings::ValueDelimiterNotSet)
} else {
self.v.val_delim = None;
self.val_delim = None;
self.unsetb(ArgSettings::UseValueDelimiter);
self.unset(ArgSettings::ValueDelimiterNotSet)
}
@ -2946,7 +3001,7 @@ impl<'a, 'b> Arg<'a, 'b> {
self.unsetb(ArgSettings::ValueDelimiterNotSet);
self.setb(ArgSettings::TakesValue);
self.setb(ArgSettings::UseValueDelimiter);
self.v.val_delim = Some(
self.val_delim = Some(
d.chars()
.nth(0)
.expect("Failed to get value_delimiter from arg"),
@ -3019,7 +3074,7 @@ impl<'a, 'b> Arg<'a, 'b> {
self.unsetb(ArgSettings::ValueDelimiterNotSet);
self.setb(ArgSettings::UseValueDelimiter);
}
if let Some(ref mut vals) = self.v.val_names {
if let Some(ref mut vals) = self.val_names {
let mut l = vals.len();
for s in names {
vals.insert(l, s);
@ -3030,7 +3085,7 @@ impl<'a, 'b> Arg<'a, 'b> {
for (i, n) in names.iter().enumerate() {
vm.insert(i, *n);
}
self.v.val_names = Some(vm);
self.val_names = Some(vm);
}
self
}
@ -3083,13 +3138,13 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
pub fn value_name(mut self, name: &'b str) -> Self {
self.setb(ArgSettings::TakesValue);
if let Some(ref mut vals) = self.v.val_names {
if let Some(ref mut vals) = self.val_names {
let l = vals.len();
vals.insert(l, name);
} else {
let mut vm = VecMap::new();
vm.insert(0, name);
self.v.val_names = Some(vm);
self.val_names = Some(vm);
}
self
}
@ -3167,7 +3222,7 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
pub fn default_value_os(mut self, val: &'a OsStr) -> Self {
self.setb(ArgSettings::TakesValue);
self.v.default_val = Some(val);
self.default_val = Some(val);
self
}
@ -3286,13 +3341,13 @@ impl<'a, 'b> Arg<'a, 'b> {
default: &'b OsStr,
) -> Self {
self.setb(ArgSettings::TakesValue);
if let Some(ref mut vm) = self.v.default_vals_ifs {
if let Some(ref mut vm) = self.default_vals_ifs {
let l = vm.len();
vm.insert(l, (arg, val, default));
} else {
let mut vm = VecMap::new();
vm.insert(0, (arg, val, default));
self.v.default_vals_ifs = Some(vm);
self.default_vals_ifs = Some(vm);
}
self
}
@ -3511,7 +3566,7 @@ impl<'a, 'b> Arg<'a, 'b> {
pub fn env_os(mut self, name: &'a OsStr) -> Self {
self.setb(ArgSettings::TakesValue);
self.v.env = Some((name, env::var_os(name)));
self.env = Some((name, env::var_os(name)));
self
}
@ -3634,13 +3689,13 @@ impl<'a, 'b> Arg<'a, 'b> {
/// [positional arguments]: ./struct.Arg.html#method.index
/// [index]: ./struct.Arg.html#method.index
pub fn display_order(mut self, ord: usize) -> Self {
self.s.disp_ord = ord;
self.disp_ord = ord;
self
}
/// Checks if one of the [`ArgSettings`] settings is set for the argument
/// [`ArgSettings`]: ./enum.ArgSettings.html
pub fn is_set(&self, s: ArgSettings) -> bool { self.b.is_set(s) }
pub fn is_set(&self, s: ArgSettings) -> bool { self.settings.is_set(s) }
/// Sets one of the [`ArgSettings`] settings for the argument
/// [`ArgSettings`]: ./enum.ArgSettings.html
@ -3657,24 +3712,373 @@ impl<'a, 'b> Arg<'a, 'b> {
}
#[doc(hidden)]
pub fn setb(&mut self, s: ArgSettings) { self.b.set(s); }
pub fn _build(&mut self) {
if self.index.is_some() || (self.short.is_none() && self.long.is_none()) {
if self.max_vals.is_some() || self.min_vals.is_some()
|| (self.num_vals.is_some() && self.num_vals.unwrap() > 1)
{
self.setb(ArgSettings::Multiple);
}
} else if self.is_set(ArgSettings::TakesValue) {
if let Some(ref vec) = self.val_names {
if vec.len() > 1 {
self.num_vals = Some(vec.len() as u64);
}
}
}
}
#[doc(hidden)]
pub fn unsetb(&mut self, s: ArgSettings) { self.b.unset(s); }
pub fn setb(&mut self, s: ArgSettings) { self.settings.set(s); }
#[doc(hidden)]
pub fn unsetb(&mut self, s: ArgSettings) { self.settings.unset(s); }
#[doc(hidden)]
pub fn has_switch(&self) -> bool { self.short.is_some() || self.long.is_some() }
#[doc(hidden)]
pub fn longest_filter(&self) -> bool {
self.is_set(ArgSettings::TakesValue) || self.long.is_some() || self.short.is_none()
}
// Used for positionals when printing
#[doc(hidden)]
pub fn multiple_str(&self) -> &str {
let mult_vals = self.val_names
.as_ref()
.map_or(true, |names| names.len() < 2);
if self.is_set(ArgSettings::Multiple) && mult_vals {
"..."
} else {
""
}
}
// Used for positionals when printing
#[doc(hidden)]
pub fn name_no_brackets(&self) -> Cow<str> {
debugln!("PosBuilder::name_no_brackets:{}", self.name);
let mut delim = String::new();
delim.push(if self.is_set(ArgSettings::RequireDelimiter) {
self.val_delim.expect(INTERNAL_ERROR_MSG)
} else {
' '
});
if let Some(ref names) = self.val_names {
debugln!("PosBuilder:name_no_brackets: val_names={:#?}", names);
if names.len() > 1 {
Cow::Owned(
names
.values()
.map(|n| format!("<{}>", n))
.collect::<Vec<_>>()
.join(&*delim),
)
} else {
Cow::Borrowed(names.values().next().expect(INTERNAL_ERROR_MSG))
}
} else {
debugln!("PosBuilder:name_no_brackets: just name");
Cow::Borrowed(self.name)
}
}
}
impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for Arg<'a, 'b> {
fn from(a: &'z Arg<'a, 'b>) -> Self {
Arg {
b: a.b.clone(),
v: a.v.clone(),
s: a.s.clone(),
index: a.index,
r_ifs: a.r_ifs.clone(),
}
}
fn from(a: &'z Arg<'a, 'b>) -> Self { a.clone() }
}
impl<'n, 'e> PartialEq for Arg<'n, 'e> {
fn eq(&self, other: &Arg<'n, 'e>) -> bool { self.b == other.b }
fn eq(&self, other: &Arg<'n, 'e>) -> bool { self.name == other.name }
}
impl<'n, 'e> Display for Arg<'n, 'e> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if self.index.is_some() || (self.long.is_none() && self.short.is_none()) {
// Positional
let mut delim = String::new();
delim.push(if self.is_set(ArgSettings::RequireDelimiter) {
self.val_delim.expect(INTERNAL_ERROR_MSG)
} else {
' '
});
if let Some(ref names) = self.val_names {
write!(
f,
"{}",
names
.values()
.map(|n| format!("<{}>", n))
.collect::<Vec<_>>()
.join(&*delim)
)?;
} else {
write!(f, "<{}>", self.name)?;
}
if self.settings.is_set(ArgSettings::Multiple)
&& (self.val_names.is_none()
|| (self.val_names.is_some()
&& self.val_names.as_ref().unwrap().len() == 1))
{
write!(f, "...")?;
}
return Ok(());
} else if !self.is_set(ArgSettings::TakesValue) {
// Flag
if let Some(l) = self.long {
write!(f, "--{}", l)?;
} else if let Some(s) = self.short {
write!(f, "-{}", s)?;
}
return Ok(());
}
let sep = if self.is_set(ArgSettings::RequireEquals) {
"="
} else {
" "
};
// Write the name such --long or -l
if let Some(l) = self.long {
write!(f, "--{}{}", l, sep)?;
} else {
write!(f, "-{}{}", self.short.unwrap(), sep)?;
}
let delim = if self.is_set(ArgSettings::RequireDelimiter) {
self.val_delim.expect(INTERNAL_ERROR_MSG)
} else {
' '
};
// Write the values such as <name1> <name2>
if let Some(ref vec) = self.val_names {
let mut it = vec.iter().peekable();
while let Some((_, val)) = it.next() {
write!(f, "<{}>", val)?;
if it.peek().is_some() {
write!(f, "{}", delim)?;
}
}
let num = vec.len();
if self.is_set(ArgSettings::Multiple) && num == 1 {
write!(f, "...")?;
}
} else if let Some(num) = self.num_vals {
let mut it = (0..num).peekable();
while let Some(_) = it.next() {
write!(f, "<{}>", self.name)?;
if it.peek().is_some() {
write!(f, "{}", delim)?;
}
}
if self.is_set(ArgSettings::Multiple) && num == 1 {
write!(f, "...")?;
}
} else {
write!(
f,
"<{}>{}",
self.name,
if self.is_set(ArgSettings::Multiple) {
"..."
} else {
""
}
)?;
}
Ok(())
}
}
impl<'n, 'e> PartialOrd for Arg<'n, 'e> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
}
impl<'n, 'e> Ord for Arg<'n, 'e> {
fn cmp(&self, other: &Arg) -> Ordering { self.name.cmp(&other.name) }
}
impl<'n, 'e> Eq for Arg<'n, 'e> {}
impl<'n, 'e> fmt::Debug for Arg<'n, 'e> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(
f,
"Arg {{ name: {:?}, help: {:?}, long_help: {:?}, conflicts_with: {:?}, \
settings: {:?}, required_unless: {:?}, overrides_with: {:?}, groups: {:?}, \
requires: {:?}, requires_ifs: {:?}, short: {:?}, index: {:?}, long: {:?}, \
aliases: {:?}, possible_values: {:?}, value_names: {:?}, number_of_values: {:?}, \
max_values: {:?}, min_values: {:?}, value_delimiter: {:?}, default_value_ifs: {:?}, \
value_terminator: {:?}, display_order: {:?}, env: {:?}, unified_ord: {:?}, \
default_value: {:?}, validator: {}, validator_os: {} \
}}",
self.name,
self.help,
self.long_help,
self.blacklist,
self.settings,
self.r_unless,
self.overrides,
self.groups,
self.requires,
self.r_ifs,
self.short,
self.index,
self.long,
self.aliases,
self.possible_vals,
self.val_names,
self.num_vals,
self.max_vals,
self.min_vals,
self.val_delim,
self.default_vals_ifs,
self.terminator,
self.disp_ord,
self.env,
self.unified_ord,
self.default_val,
self.validator.as_ref().map_or("None", |_| "Some(Fn)"),
self.validator_os.as_ref().map_or("None", |_| "Some(Fn)")
)
}
}
// Flags
#[cfg(test)]
mod test {
use map::VecMap;
use args::settings::ArgSettings;
use super::Arg;
#[test]
fn flag_display() {
let mut f = Arg::with_name("flg");
f.settings.set(ArgSettings::Multiple);
f.long = Some("flag");
assert_eq!(&*format!("{}", f), "--flag");
let mut f2 = Arg::with_name("flg");
f2.short = Some('f');
assert_eq!(&*format!("{}", f2), "-f");
}
#[test]
fn flag_display_single_alias() {
let mut f = Arg::with_name("flg");
f.long = Some("flag");
f.aliases = Some(vec![("als", true)]);
assert_eq!(&*format!("{}", f), "--flag");
}
#[test]
fn flag_display_multiple_aliases() {
let mut f = Arg::with_name("flg");
f.short = Some('f');
f.aliases = Some(vec![
("alias_not_visible", false),
("f2", true),
("f3", true),
("f4", true),
]);
assert_eq!(&*format!("{}", f), "-f");
}
// Options
#[test]
fn option_display1() {
let o = Arg::with_name("opt")
.long("option")
.takes_value(true)
.multiple(true);
assert_eq!(&*format!("{}", o), "--option <opt>...");
}
#[test]
fn option_display2() {
let o2 = Arg::with_name("opt")
.short("o")
.value_names(&["file", "name"]);
assert_eq!(&*format!("{}", o2), "-o <file> <name>");
}
#[test]
fn option_display3() {
let o2 = Arg::with_name("opt")
.short("o")
.multiple(true)
.value_names(&["file", "name"]);
assert_eq!(&*format!("{}", o2), "-o <file> <name>");
}
#[test]
fn option_display_single_alias() {
let o = Arg::with_name("opt")
.takes_value(true)
.long("option")
.visible_alias("als");
assert_eq!(&*format!("{}", o), "--option <opt>");
}
#[test]
fn option_display_multiple_aliases() {
let o = Arg::with_name("opt")
.long("option")
.takes_value(true)
.visible_aliases(&["als2", "als3", "als4"])
.alias("als_not_visible");
assert_eq!(&*format!("{}", o), "--option <opt>");
}
// Positionals
#[test]
fn positiona_display_mult() {
let mut p = Arg::with_name("pos").index(1);
p.settings.set(ArgSettings::Multiple);
assert_eq!(&*format!("{}", p), "<pos>...");
}
#[test]
fn positional_display_required() {
let mut p2 = Arg::with_name("pos").index(1);
p2.settings.set(ArgSettings::Required);
assert_eq!(&*format!("{}", p2), "<pos>");
}
#[test]
fn positional_display_val_names() {
let mut p2 = Arg::with_name("pos").index(1);
let mut vm = VecMap::new();
vm.insert(0, "file1");
vm.insert(1, "file2");
p2.val_names = Some(vm);
assert_eq!(&*format!("{}", p2), "<file1> <file2>");
}
#[test]
fn positional_display_val_names_req() {
let mut p2 = Arg::with_name("pos").index(1);
p2.settings.set(ArgSettings::Required);
let mut vm = VecMap::new();
vm.insert(0, "file1");
vm.insert(1, "file2");
p2.val_names = Some(vm);
assert_eq!(&*format!("{}", p2), "<file1> <file2>");
}
}

View file

@ -1,38 +0,0 @@
use args::{Arg, ArgFlags, ArgSettings};
#[derive(Debug, Clone, Default)]
pub struct Base<'a, 'b>
where
'a: 'b,
{
pub name: &'a str,
pub help: Option<&'b str>,
pub long_help: Option<&'b str>,
pub blacklist: Option<Vec<&'a str>>,
pub settings: ArgFlags,
pub r_unless: Option<Vec<&'a str>>,
pub overrides: Option<Vec<&'a str>>,
pub groups: Option<Vec<&'a str>>,
pub requires: Option<Vec<(Option<&'b str>, &'a str)>>,
}
impl<'n, 'e> Base<'n, 'e> {
pub fn new(name: &'n str) -> Self {
Base {
name: name,
..Default::default()
}
}
pub fn set(&mut self, s: ArgSettings) { self.settings.set(s); }
pub fn unset(&mut self, s: ArgSettings) { self.settings.unset(s); }
pub fn is_set(&self, s: ArgSettings) -> bool { self.settings.is_set(s) }
}
impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Base<'n, 'e> {
fn from(a: &'z Arg<'n, 'e>) -> Self { a.b.clone() }
}
impl<'n, 'e> PartialEq for Base<'n, 'e> {
fn eq(&self, other: &Base<'n, 'e>) -> bool { self.name == other.name }
}

View file

@ -1,159 +0,0 @@
// Std
use std::convert::From;
use std::fmt::{Display, Formatter, Result};
use std::rc::Rc;
use std::result::Result as StdResult;
use std::ffi::{OsStr, OsString};
use std::mem;
// Internal
use Arg;
use args::{AnyArg, ArgSettings, Base, DispOrder, Switched};
use map::{self, VecMap};
#[derive(Default, Clone, Debug)]
#[doc(hidden)]
pub struct FlagBuilder<'n, 'e>
where
'n: 'e,
{
pub b: Base<'n, 'e>,
pub s: Switched<'e>,
}
impl<'n, 'e> FlagBuilder<'n, 'e> {
pub fn new(name: &'n str) -> Self {
FlagBuilder {
b: Base::new(name),
..Default::default()
}
}
}
impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for FlagBuilder<'a, 'b> {
fn from(a: &'z Arg<'a, 'b>) -> Self {
FlagBuilder {
b: Base::from(a),
s: Switched::from(a),
}
}
}
impl<'a, 'b> From<Arg<'a, 'b>> for FlagBuilder<'a, 'b> {
fn from(mut a: Arg<'a, 'b>) -> Self {
FlagBuilder {
b: mem::replace(&mut a.b, Base::default()),
s: mem::replace(&mut a.s, Switched::default()),
}
}
}
impl<'n, 'e> Display for FlagBuilder<'n, 'e> {
fn fmt(&self, f: &mut Formatter) -> Result {
if let Some(l) = self.s.long {
write!(f, "--{}", l)?;
} else {
write!(f, "-{}", self.s.short.unwrap())?;
}
Ok(())
}
}
impl<'n, 'e> AnyArg<'n, 'e> for FlagBuilder<'n, 'e> {
fn name(&self) -> &'n str { self.b.name }
fn overrides(&self) -> Option<&[&'e str]> { self.b.overrides.as_ref().map(|o| &o[..]) }
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
self.b.requires.as_ref().map(|o| &o[..])
}
fn blacklist(&self) -> Option<&[&'e str]> { self.b.blacklist.as_ref().map(|o| &o[..]) }
fn required_unless(&self) -> Option<&[&'e str]> { self.b.r_unless.as_ref().map(|o| &o[..]) }
fn is_set(&self, s: ArgSettings) -> bool { self.b.settings.is_set(s) }
fn has_switch(&self) -> bool { true }
fn takes_value(&self) -> bool { false }
fn set(&mut self, s: ArgSettings) { self.b.settings.set(s) }
fn max_vals(&self) -> Option<u64> { None }
fn val_names(&self) -> Option<&VecMap<&'e str>> { None }
fn num_vals(&self) -> Option<u64> { None }
fn possible_vals(&self) -> Option<&[&'e str]> { None }
fn validator(&self) -> Option<&Rc<Fn(String) -> StdResult<(), String>>> { None }
fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> StdResult<(), OsString>>> { None }
fn min_vals(&self) -> Option<u64> { None }
fn short(&self) -> Option<char> { self.s.short }
fn long(&self) -> Option<&'e str> { self.s.long }
fn val_delim(&self) -> Option<char> { None }
fn help(&self) -> Option<&'e str> { self.b.help }
fn long_help(&self) -> Option<&'e str> { self.b.long_help }
fn val_terminator(&self) -> Option<&'e str> { None }
fn default_val(&self) -> Option<&'e OsStr> { None }
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
None
}
fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> { None }
fn longest_filter(&self) -> bool { self.s.long.is_some() }
fn aliases(&self) -> Option<Vec<&'e str>> {
if let Some(ref aliases) = self.s.aliases {
let vis_aliases: Vec<_> = aliases
.iter()
.filter_map(|&(n, v)| if v { Some(n) } else { None })
.collect();
if vis_aliases.is_empty() {
None
} else {
Some(vis_aliases)
}
} else {
None
}
}
}
impl<'n, 'e> DispOrder for FlagBuilder<'n, 'e> {
fn disp_ord(&self) -> usize { self.s.disp_ord }
}
impl<'n, 'e> PartialEq for FlagBuilder<'n, 'e> {
fn eq(&self, other: &FlagBuilder<'n, 'e>) -> bool { self.b == other.b }
}
#[cfg(test)]
mod test {
use args::settings::ArgSettings;
use super::FlagBuilder;
#[test]
fn flagbuilder_display() {
let mut f = FlagBuilder::new("flg");
f.b.settings.set(ArgSettings::Multiple);
f.s.long = Some("flag");
assert_eq!(&*format!("{}", f), "--flag");
let mut f2 = FlagBuilder::new("flg");
f2.s.short = Some('f');
assert_eq!(&*format!("{}", f2), "-f");
}
#[test]
fn flagbuilder_display_single_alias() {
let mut f = FlagBuilder::new("flg");
f.s.long = Some("flag");
f.s.aliases = Some(vec![("als", true)]);
assert_eq!(&*format!("{}", f), "--flag");
}
#[test]
fn flagbuilder_display_multiple_aliases() {
let mut f = FlagBuilder::new("flg");
f.s.short = Some('f');
f.s.aliases = Some(vec![
("alias_not_visible", false),
("f2", true),
("f3", true),
("f4", true),
]);
assert_eq!(&*format!("{}", f), "-f");
}
}

View file

@ -1,13 +0,0 @@
pub use self::flag::FlagBuilder;
pub use self::option::OptBuilder;
pub use self::positional::PosBuilder;
pub use self::base::Base;
pub use self::switched::Switched;
pub use self::valued::Valued;
mod flag;
mod positional;
mod option;
mod base;
mod valued;
mod switched;

View file

@ -1,244 +0,0 @@
// Std
use std::fmt::{Display, Formatter, Result};
use std::rc::Rc;
use std::result::Result as StdResult;
use std::ffi::{OsStr, OsString};
use std::mem;
// Internal
use args::{AnyArg, Arg, ArgSettings, Base, DispOrder, Switched, Valued};
use map::{self, VecMap};
use INTERNAL_ERROR_MSG;
#[allow(missing_debug_implementations)]
#[doc(hidden)]
#[derive(Default, Clone)]
pub struct OptBuilder<'n, 'e>
where
'n: 'e,
{
pub b: Base<'n, 'e>,
pub s: Switched<'e>,
pub v: Valued<'n, 'e>,
}
impl<'n, 'e> OptBuilder<'n, 'e> {
pub fn new(name: &'n str) -> Self {
OptBuilder {
b: Base::new(name),
..Default::default()
}
}
}
impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for OptBuilder<'n, 'e> {
fn from(a: &'z Arg<'n, 'e>) -> Self {
OptBuilder {
b: Base::from(a),
s: Switched::from(a),
v: Valued::from(a),
}
}
}
impl<'n, 'e> From<Arg<'n, 'e>> for OptBuilder<'n, 'e> {
fn from(mut a: Arg<'n, 'e>) -> Self {
a.v.fill_in();
OptBuilder {
b: mem::replace(&mut a.b, Base::default()),
s: mem::replace(&mut a.s, Switched::default()),
v: mem::replace(&mut a.v, Valued::default()),
}
}
}
impl<'n, 'e> Display for OptBuilder<'n, 'e> {
fn fmt(&self, f: &mut Formatter) -> Result {
debugln!("OptBuilder::fmt:{}", self.b.name);
let sep = if self.b.is_set(ArgSettings::RequireEquals) {
"="
} else {
" "
};
// Write the name such --long or -l
if let Some(l) = self.s.long {
write!(f, "--{}{}", l, sep)?;
} else {
write!(f, "-{}{}", self.s.short.unwrap(), sep)?;
}
let delim = if self.is_set(ArgSettings::RequireDelimiter) {
self.v.val_delim.expect(INTERNAL_ERROR_MSG)
} else {
' '
};
// Write the values such as <name1> <name2>
if let Some(ref vec) = self.v.val_names {
let mut it = vec.iter().peekable();
while let Some((_, val)) = it.next() {
write!(f, "<{}>", val)?;
if it.peek().is_some() {
write!(f, "{}", delim)?;
}
}
let num = vec.len();
if self.is_set(ArgSettings::Multiple) && num == 1 {
write!(f, "...")?;
}
} else if let Some(num) = self.v.num_vals {
let mut it = (0..num).peekable();
while let Some(_) = it.next() {
write!(f, "<{}>", self.b.name)?;
if it.peek().is_some() {
write!(f, "{}", delim)?;
}
}
if self.is_set(ArgSettings::Multiple) && num == 1 {
write!(f, "...")?;
}
} else {
write!(
f,
"<{}>{}",
self.b.name,
if self.is_set(ArgSettings::Multiple) {
"..."
} else {
""
}
)?;
}
Ok(())
}
}
impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> {
fn name(&self) -> &'n str { self.b.name }
fn overrides(&self) -> Option<&[&'e str]> { self.b.overrides.as_ref().map(|o| &o[..]) }
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
self.b.requires.as_ref().map(|o| &o[..])
}
fn blacklist(&self) -> Option<&[&'e str]> { self.b.blacklist.as_ref().map(|o| &o[..]) }
fn required_unless(&self) -> Option<&[&'e str]> { self.b.r_unless.as_ref().map(|o| &o[..]) }
fn val_names(&self) -> Option<&VecMap<&'e str>> { self.v.val_names.as_ref() }
fn is_set(&self, s: ArgSettings) -> bool { self.b.settings.is_set(s) }
fn has_switch(&self) -> bool { true }
fn set(&mut self, s: ArgSettings) { self.b.settings.set(s) }
fn max_vals(&self) -> Option<u64> { self.v.max_vals }
fn val_terminator(&self) -> Option<&'e str> { self.v.terminator }
fn num_vals(&self) -> Option<u64> { self.v.num_vals }
fn possible_vals(&self) -> Option<&[&'e str]> { self.v.possible_vals.as_ref().map(|o| &o[..]) }
fn validator(&self) -> Option<&Rc<Fn(String) -> StdResult<(), String>>> {
self.v.validator.as_ref()
}
fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> StdResult<(), OsString>>> {
self.v.validator_os.as_ref()
}
fn min_vals(&self) -> Option<u64> { self.v.min_vals }
fn short(&self) -> Option<char> { self.s.short }
fn long(&self) -> Option<&'e str> { self.s.long }
fn val_delim(&self) -> Option<char> { self.v.val_delim }
fn takes_value(&self) -> bool { true }
fn help(&self) -> Option<&'e str> { self.b.help }
fn long_help(&self) -> Option<&'e str> { self.b.long_help }
fn default_val(&self) -> Option<&'e OsStr> { self.v.default_val }
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
self.v.default_vals_ifs.as_ref().map(|vm| vm.values())
}
fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> {
self.v
.env
.as_ref()
.map(|&(key, ref value)| (key, value.as_ref()))
}
fn longest_filter(&self) -> bool { true }
fn aliases(&self) -> Option<Vec<&'e str>> {
if let Some(ref aliases) = self.s.aliases {
let vis_aliases: Vec<_> = aliases
.iter()
.filter_map(|&(n, v)| if v { Some(n) } else { None })
.collect();
if vis_aliases.is_empty() {
None
} else {
Some(vis_aliases)
}
} else {
None
}
}
}
impl<'n, 'e> DispOrder for OptBuilder<'n, 'e> {
fn disp_ord(&self) -> usize { self.s.disp_ord }
}
impl<'n, 'e> PartialEq for OptBuilder<'n, 'e> {
fn eq(&self, other: &OptBuilder<'n, 'e>) -> bool { self.b == other.b }
}
#[cfg(test)]
mod test {
use args::settings::ArgSettings;
use super::OptBuilder;
use map::VecMap;
#[test]
fn optbuilder_display1() {
let mut o = OptBuilder::new("opt");
o.s.long = Some("option");
o.b.settings.set(ArgSettings::Multiple);
assert_eq!(&*format!("{}", o), "--option <opt>...");
}
#[test]
fn optbuilder_display2() {
let mut v_names = VecMap::new();
v_names.insert(0, "file");
v_names.insert(1, "name");
let mut o2 = OptBuilder::new("opt");
o2.s.short = Some('o');
o2.v.val_names = Some(v_names);
assert_eq!(&*format!("{}", o2), "-o <file> <name>");
}
#[test]
fn optbuilder_display3() {
let mut v_names = VecMap::new();
v_names.insert(0, "file");
v_names.insert(1, "name");
let mut o2 = OptBuilder::new("opt");
o2.s.short = Some('o');
o2.v.val_names = Some(v_names);
o2.b.settings.set(ArgSettings::Multiple);
assert_eq!(&*format!("{}", o2), "-o <file> <name>");
}
#[test]
fn optbuilder_display_single_alias() {
let mut o = OptBuilder::new("opt");
o.s.long = Some("option");
o.s.aliases = Some(vec![("als", true)]);
assert_eq!(&*format!("{}", o), "--option <opt>");
}
#[test]
fn optbuilder_display_multiple_aliases() {
let mut o = OptBuilder::new("opt");
o.s.long = Some("option");
o.s.aliases = Some(vec![
("als_not_visible", false),
("als2", true),
("als3", true),
("als4", true),
]);
assert_eq!(&*format!("{}", o), "--option <opt>");
}
}

View file

@ -1,229 +0,0 @@
// Std
use std::borrow::Cow;
use std::fmt::{Display, Formatter, Result};
use std::rc::Rc;
use std::result::Result as StdResult;
use std::ffi::{OsStr, OsString};
use std::mem;
// Internal
use Arg;
use args::{AnyArg, ArgSettings, Base, DispOrder, Valued};
use INTERNAL_ERROR_MSG;
use map::{self, VecMap};
#[allow(missing_debug_implementations)]
#[doc(hidden)]
#[derive(Clone, Default)]
pub struct PosBuilder<'n, 'e>
where
'n: 'e,
{
pub b: Base<'n, 'e>,
pub v: Valued<'n, 'e>,
pub index: u64,
}
impl<'n, 'e> PosBuilder<'n, 'e> {
pub fn new(name: &'n str, idx: u64) -> Self {
PosBuilder {
b: Base::new(name),
index: idx,
..Default::default()
}
}
pub fn from_arg_ref(a: &Arg<'n, 'e>, idx: u64) -> Self {
let mut pb = PosBuilder {
b: Base::from(a),
v: Valued::from(a),
index: idx,
};
if a.v.max_vals.is_some() || a.v.min_vals.is_some()
|| (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1)
{
pb.b.settings.set(ArgSettings::Multiple);
}
pb
}
pub fn from_arg(mut a: Arg<'n, 'e>, idx: u64) -> Self {
if a.v.max_vals.is_some() || a.v.min_vals.is_some()
|| (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1)
{
a.b.settings.set(ArgSettings::Multiple);
}
PosBuilder {
b: mem::replace(&mut a.b, Base::default()),
v: mem::replace(&mut a.v, Valued::default()),
index: idx,
}
}
pub fn multiple_str(&self) -> &str {
let mult_vals = self.v
.val_names
.as_ref()
.map_or(true, |names| names.len() < 2);
if self.is_set(ArgSettings::Multiple) && mult_vals {
"..."
} else {
""
}
}
pub fn name_no_brackets(&self) -> Cow<str> {
debugln!("PosBuilder::name_no_brackets;");
let mut delim = String::new();
delim.push(if self.is_set(ArgSettings::RequireDelimiter) {
self.v.val_delim.expect(INTERNAL_ERROR_MSG)
} else {
' '
});
if let Some(ref names) = self.v.val_names {
debugln!("PosBuilder:name_no_brackets: val_names={:#?}", names);
if names.len() > 1 {
Cow::Owned(
names
.values()
.map(|n| format!("<{}>", n))
.collect::<Vec<_>>()
.join(&*delim),
)
} else {
Cow::Borrowed(names.values().next().expect(INTERNAL_ERROR_MSG))
}
} else {
debugln!("PosBuilder:name_no_brackets: just name");
Cow::Borrowed(self.b.name)
}
}
}
impl<'n, 'e> Display for PosBuilder<'n, 'e> {
fn fmt(&self, f: &mut Formatter) -> Result {
let mut delim = String::new();
delim.push(if self.is_set(ArgSettings::RequireDelimiter) {
self.v.val_delim.expect(INTERNAL_ERROR_MSG)
} else {
' '
});
if let Some(ref names) = self.v.val_names {
write!(
f,
"{}",
names
.values()
.map(|n| format!("<{}>", n))
.collect::<Vec<_>>()
.join(&*delim)
)?;
} else {
write!(f, "<{}>", self.b.name)?;
}
if self.b.settings.is_set(ArgSettings::Multiple)
&& (self.v.val_names.is_none() || self.v.val_names.as_ref().unwrap().len() == 1)
{
write!(f, "...")?;
}
Ok(())
}
}
impl<'n, 'e> AnyArg<'n, 'e> for PosBuilder<'n, 'e> {
fn name(&self) -> &'n str { self.b.name }
fn overrides(&self) -> Option<&[&'e str]> { self.b.overrides.as_ref().map(|o| &o[..]) }
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
self.b.requires.as_ref().map(|o| &o[..])
}
fn blacklist(&self) -> Option<&[&'e str]> { self.b.blacklist.as_ref().map(|o| &o[..]) }
fn required_unless(&self) -> Option<&[&'e str]> { self.b.r_unless.as_ref().map(|o| &o[..]) }
fn val_names(&self) -> Option<&VecMap<&'e str>> { self.v.val_names.as_ref() }
fn is_set(&self, s: ArgSettings) -> bool { self.b.settings.is_set(s) }
fn set(&mut self, s: ArgSettings) { self.b.settings.set(s) }
fn has_switch(&self) -> bool { false }
fn max_vals(&self) -> Option<u64> { self.v.max_vals }
fn val_terminator(&self) -> Option<&'e str> { self.v.terminator }
fn num_vals(&self) -> Option<u64> { self.v.num_vals }
fn possible_vals(&self) -> Option<&[&'e str]> { self.v.possible_vals.as_ref().map(|o| &o[..]) }
fn validator(&self) -> Option<&Rc<Fn(String) -> StdResult<(), String>>> {
self.v.validator.as_ref()
}
fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> StdResult<(), OsString>>> {
self.v.validator_os.as_ref()
}
fn min_vals(&self) -> Option<u64> { self.v.min_vals }
fn short(&self) -> Option<char> { None }
fn long(&self) -> Option<&'e str> { None }
fn val_delim(&self) -> Option<char> { self.v.val_delim }
fn takes_value(&self) -> bool { true }
fn help(&self) -> Option<&'e str> { self.b.help }
fn long_help(&self) -> Option<&'e str> { self.b.long_help }
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
self.v.default_vals_ifs.as_ref().map(|vm| vm.values())
}
fn default_val(&self) -> Option<&'e OsStr> { self.v.default_val }
fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> {
self.v
.env
.as_ref()
.map(|&(key, ref value)| (key, value.as_ref()))
}
fn longest_filter(&self) -> bool { true }
fn aliases(&self) -> Option<Vec<&'e str>> { None }
}
impl<'n, 'e> DispOrder for PosBuilder<'n, 'e> {
fn disp_ord(&self) -> usize { self.index as usize }
}
impl<'n, 'e> PartialEq for PosBuilder<'n, 'e> {
fn eq(&self, other: &PosBuilder<'n, 'e>) -> bool { self.b == other.b }
}
#[cfg(test)]
mod test {
use args::settings::ArgSettings;
use super::PosBuilder;
use map::VecMap;
#[test]
fn display_mult() {
let mut p = PosBuilder::new("pos", 1);
p.b.settings.set(ArgSettings::Multiple);
assert_eq!(&*format!("{}", p), "<pos>...");
}
#[test]
fn display_required() {
let mut p2 = PosBuilder::new("pos", 1);
p2.b.settings.set(ArgSettings::Required);
assert_eq!(&*format!("{}", p2), "<pos>");
}
#[test]
fn display_val_names() {
let mut p2 = PosBuilder::new("pos", 1);
let mut vm = VecMap::new();
vm.insert(0, "file1");
vm.insert(1, "file2");
p2.v.val_names = Some(vm);
assert_eq!(&*format!("{}", p2), "<file1> <file2>");
}
#[test]
fn display_val_names_req() {
let mut p2 = PosBuilder::new("pos", 1);
p2.b.settings.set(ArgSettings::Required);
let mut vm = VecMap::new();
vm.insert(0, "file1");
vm.insert(1, "file2");
p2.v.val_names = Some(vm);
assert_eq!(&*format!("{}", p2), "<file1> <file2>");
}
}

View file

@ -1,38 +0,0 @@
use Arg;
#[derive(Debug)]
pub struct Switched<'b> {
pub short: Option<char>,
pub long: Option<&'b str>,
pub aliases: Option<Vec<(&'b str, bool)>>, // (name, visible)
pub disp_ord: usize,
pub unified_ord: usize,
}
impl<'e> Default for Switched<'e> {
fn default() -> Self {
Switched {
short: None,
long: None,
aliases: None,
disp_ord: 999,
unified_ord: 999,
}
}
}
impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Switched<'e> {
fn from(a: &'z Arg<'n, 'e>) -> Self { a.s.clone() }
}
impl<'e> Clone for Switched<'e> {
fn clone(&self) -> Self {
Switched {
short: self.short,
long: self.long,
aliases: self.aliases.clone(),
disp_ord: self.disp_ord,
unified_ord: self.unified_ord,
}
}
}

View file

@ -1,67 +0,0 @@
use std::rc::Rc;
use std::ffi::{OsStr, OsString};
use map::VecMap;
use Arg;
#[allow(missing_debug_implementations)]
#[derive(Clone)]
pub struct Valued<'a, 'b>
where
'a: 'b,
{
pub possible_vals: Option<Vec<&'b str>>,
pub val_names: Option<VecMap<&'b str>>,
pub num_vals: Option<u64>,
pub max_vals: Option<u64>,
pub min_vals: Option<u64>,
pub validator: Option<Rc<Fn(String) -> Result<(), String>>>,
pub validator_os: Option<Rc<Fn(&OsStr) -> Result<(), OsString>>>,
pub val_delim: Option<char>,
pub default_val: Option<&'b OsStr>,
pub default_vals_ifs: Option<VecMap<(&'a str, Option<&'b OsStr>, &'b OsStr)>>,
pub env: Option<(&'a OsStr, Option<OsString>)>,
pub terminator: Option<&'b str>,
}
impl<'n, 'e> Default for Valued<'n, 'e> {
fn default() -> Self {
Valued {
possible_vals: None,
num_vals: None,
min_vals: None,
max_vals: None,
val_names: None,
validator: None,
validator_os: None,
val_delim: None,
default_val: None,
default_vals_ifs: None,
env: None,
terminator: None,
}
}
}
impl<'n, 'e> Valued<'n, 'e> {
pub fn fill_in(&mut self) {
if let Some(ref vec) = self.val_names {
if vec.len() > 1 {
self.num_vals = Some(vec.len() as u64);
}
}
}
}
impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Valued<'n, 'e> {
fn from(a: &'z Arg<'n, 'e>) -> Self {
let mut v = a.v.clone();
if let Some(ref vec) = a.v.val_names {
if vec.len() > 1 {
v.num_vals = Some(vec.len() as u64);
}
}
v
}
}

View file

@ -1,13 +1,13 @@
// Std
use std::collections::hash_map::{Entry, Iter};
use std::collections::HashMap;
use std::ffi::OsStr;
use std::ops::Deref;
use std::collections::HashMap;
use std::mem;
// Third Party
use ordermap;
// Internal
use args::{ArgMatches, MatchedArg, SubCommand};
use args::AnyArg;
use args::{Arg, ArgMatches, MatchedArg, SubCommand};
use args::settings::ArgSettings;
#[doc(hidden)]
@ -21,36 +21,13 @@ impl<'a> Default for ArgMatcher<'a> {
impl<'a> ArgMatcher<'a> {
pub fn new() -> Self { ArgMatcher::default() }
pub fn process_arg_overrides<'b>(&mut self, a: Option<&AnyArg<'a, 'b>>, overrides: &mut Vec<(&'b str, &'a str)>, required: &mut Vec<&'a str>) {
debugln!("ArgMatcher::process_arg_overrides:{:?};", a.map_or(None, |a| Some(a.name())));
if let Some(aa) = a {
if let Some(a_overrides) = aa.overrides() {
for overr in a_overrides {
debugln!("ArgMatcher::process_arg_overrides:iter:{};", overr);
if self.is_present(overr) {
debugln!("ArgMatcher::process_arg_overrides:iter:{}: removing from matches;", overr);
self.remove(overr);
for i in (0 .. required.len()).rev() {
if &required[i] == overr {
debugln!("ArgMatcher::process_arg_overrides:iter:{}: removing required;", overr);
required.swap_remove(i);
break;
}
}
} else {
overrides.push((overr, aa.name()));
}
}
}
}
}
pub fn is_present(&self, name: &str) -> bool {
self.0.is_present(name)
}
pub fn is_present(&self, name: &str) -> bool { self.0.is_present(name) }
pub fn propagate_globals(&mut self, global_arg_vec: &[&'a str]) {
debugln!( "ArgMatcher::get_global_values: global_arg_vec={:?}", global_arg_vec );
debugln!(
"ArgMatcher::get_global_values: global_arg_vec={:?}",
global_arg_vec
);
let mut vals_map = HashMap::new();
self.fill_in_global_values(global_arg_vec, &mut vals_map);
}
@ -97,6 +74,7 @@ impl<'a> ArgMatcher<'a> {
pub fn remove(&mut self, arg: &str) { self.0.args.remove(arg); }
#[allow(dead_code)]
pub fn remove_all(&mut self, args: &[&str]) {
for &arg in args {
self.0.args.remove(arg);
@ -111,15 +89,17 @@ impl<'a> ArgMatcher<'a> {
pub fn usage(&mut self, usage: String) { self.0.usage = Some(usage); }
pub fn arg_names(&'a self) -> Vec<&'a str> { self.0.args.keys().map(Deref::deref).collect() }
pub fn arg_names(&'a self) -> ordermap::Keys<&'a str, MatchedArg> { self.0.args.keys() }
pub fn entry(&mut self, arg: &'a str) -> Entry<&'a str, MatchedArg> { self.0.args.entry(arg) }
pub fn entry(&mut self, arg: &'a str) -> ordermap::Entry<&'a str, MatchedArg> {
self.0.args.entry(arg)
}
pub fn subcommand(&mut self, sc: SubCommand<'a>) { self.0.subcommand = Some(Box::new(sc)); }
pub fn subcommand_name(&self) -> Option<&str> { self.0.subcommand_name() }
pub fn iter(&self) -> Iter<&str, MatchedArg> { self.0.args.iter() }
pub fn iter(&self) -> ordermap::Iter<&str, MatchedArg> { self.0.args.iter() }
pub fn inc_occurrence_of(&mut self, arg: &'a str) {
debugln!("ArgMatcher::inc_occurrence_of: arg={}", arg);
@ -147,23 +127,20 @@ impl<'a> ArgMatcher<'a> {
ma.vals.push(val.to_owned());
}
pub fn needs_more_vals<'b, A>(&self, o: &A) -> bool
where
A: AnyArg<'a, 'b>,
{
debugln!("ArgMatcher::needs_more_vals: o={}", o.name());
if let Some(ma) = self.get(o.name()) {
if let Some(num) = o.num_vals() {
pub fn needs_more_vals<'b>(&self, o: &Arg) -> bool {
debugln!("ArgMatcher::needs_more_vals: o={}", o.name);
if let Some(ma) = self.get(o.name) {
if let Some(num) = o.num_vals {
debugln!("ArgMatcher::needs_more_vals: num_vals...{}", num);
return if o.is_set(ArgSettings::Multiple) {
((ma.vals.len() as u64) % num) != 0
} else {
num != (ma.vals.len() as u64)
};
} else if let Some(num) = o.max_vals() {
} else if let Some(num) = o.max_vals {
debugln!("ArgMatcher::needs_more_vals: max_vals...{}", num);
return !((ma.vals.len() as u64) > num);
} else if o.min_vals().is_some() {
} else if o.min_vals.is_some() {
debugln!("ArgMatcher::needs_more_vals: min_vals...true");
return true;
}

View file

@ -1,10 +1,12 @@
// Std
use std::borrow::Cow;
use std::collections::HashMap;
use std::ffi::{OsStr, OsString};
use std::iter::Map;
use std::slice::Iter;
// Third Party
use ordermap::OrderMap;
// Internal
use INVALID_UTF8;
use args::MatchedArg;
@ -59,15 +61,18 @@ use args::SubCommand;
/// [`App::get_matches`]: ./struct.App.html#method.get_matches
#[derive(Debug, Clone)]
pub struct ArgMatches<'a> {
#[doc(hidden)] pub args: HashMap<&'a str, MatchedArg>,
#[doc(hidden)] pub subcommand: Option<Box<SubCommand<'a>>>,
#[doc(hidden)] pub usage: Option<String>,
#[doc(hidden)]
pub args: OrderMap<&'a str, MatchedArg>,
#[doc(hidden)]
pub subcommand: Option<Box<SubCommand<'a>>>,
#[doc(hidden)]
pub usage: Option<String>,
}
impl<'a> Default for ArgMatches<'a> {
fn default() -> Self {
ArgMatches {
args: HashMap::new(),
args: OrderMap::new(),
subcommand: None,
usage: None,
}
@ -536,7 +541,6 @@ impl<'a> ArgMatches<'a> {
pub fn usage(&self) -> &str { self.usage.as_ref().map_or("", |u| &u[..]) }
}
// The following were taken and adapated from vec_map source
// repo: https://github.com/contain-rs/vec-map
// commit: be5e1fa3c26e351761b33010ddbdaf5f05dbcc33

View file

@ -79,12 +79,18 @@ use yaml_rust::Yaml;
/// [requirement]: ./struct.Arg.html#method.requires
#[derive(Default)]
pub struct ArgGroup<'a> {
#[doc(hidden)] pub name: &'a str,
#[doc(hidden)] pub args: Vec<&'a str>,
#[doc(hidden)] pub required: bool,
#[doc(hidden)] pub requires: Option<Vec<&'a str>>,
#[doc(hidden)] pub conflicts: Option<Vec<&'a str>>,
#[doc(hidden)] pub multiple: bool,
#[doc(hidden)]
pub name: &'a str,
#[doc(hidden)]
pub args: Vec<&'a str>,
#[doc(hidden)]
pub required: bool,
#[doc(hidden)]
pub requires: Option<Vec<&'a str>>,
#[doc(hidden)]
pub conflicts: Option<Vec<&'a str>>,
#[doc(hidden)]
pub multiple: bool,
}
impl<'a> ArgGroup<'a> {
@ -431,11 +437,7 @@ impl<'a> Debug for ArgGroup<'a> {
\trequires: {:?},\n\
\tconflicts: {:?},\n\
}}",
self.name,
self.args,
self.required,
self.requires,
self.conflicts
self.name, self.args, self.required, self.requires, self.conflicts
)
}
}
@ -494,8 +496,7 @@ impl<'a> From<&'a BTreeMap<Yaml, Yaml>> for ArgGroup<'a> {
s => panic!(
"Unknown ArgGroup setting '{}' in YAML file for \
ArgGroup '{}'",
s,
a.name
s, a.name
),
}
}

View file

@ -4,8 +4,10 @@ use std::ffi::OsString;
#[doc(hidden)]
#[derive(Debug, Clone)]
pub struct MatchedArg {
#[doc(hidden)] pub occurs: u64,
#[doc(hidden)] pub vals: Vec<OsString>,
#[doc(hidden)]
pub occurs: u64,
#[doc(hidden)]
pub vals: Vec<OsString>,
}
impl Default for MatchedArg {

View file

@ -1,6 +1,4 @@
pub use self::any_arg::{AnyArg, DispOrder};
pub use self::arg::Arg;
pub use self::arg_builder::{Base, FlagBuilder, OptBuilder, PosBuilder, Switched, Valued};
pub use self::arg_matcher::ArgMatcher;
pub use self::arg_matches::{ArgMatches, OsValues, Values};
pub use self::group::ArgGroup;
@ -11,11 +9,9 @@ pub use self::subcommand::SubCommand;
#[macro_use]
mod macros;
mod arg;
pub mod any_arg;
mod arg_matches;
mod arg_matcher;
mod subcommand;
mod arg_builder;
mod matched_arg;
mod group;
pub mod settings;

View file

@ -29,8 +29,10 @@ use ArgMatches;
/// [arguments]: ./struct.Arg.html
#[derive(Debug, Clone)]
pub struct SubCommand<'a> {
#[doc(hidden)] pub name: String,
#[doc(hidden)] pub matches: ArgMatches<'a>,
#[doc(hidden)]
pub name: String,
#[doc(hidden)]
pub matches: ArgMatches<'a>,
}
impl<'a> SubCommand<'a> {

View file

@ -2,19 +2,16 @@
use std::io::Write;
// Internal
use app::parser::Parser;
use args::{ArgSettings, OptBuilder};
use app::App;
use args::{Arg, ArgSettings};
use completions;
pub struct BashGen<'a, 'b>
pub struct BashGen<'a, 'b>(&'b App<'a, 'b>)
where
'a: 'b,
{
p: &'b Parser<'a, 'b>,
}
'a: 'b;
impl<'a, 'b> BashGen<'a, 'b> {
pub fn new(p: &'b Parser<'a, 'b>) -> Self { BashGen { p: p } }
pub fn new(app: &'b App<'a, 'b>) -> Self { BashGen(app) }
pub fn generate_to<W: Write>(&self, buf: &mut W) {
w!(
@ -62,10 +59,9 @@ impl<'a, 'b> BashGen<'a, 'b> {
complete -F _{name} -o bashdefault -o default {name}
",
name = self.p.meta.bin_name.as_ref().unwrap(),
name_opts = self.all_options_for_path(self.p.meta.bin_name.as_ref().unwrap()),
name_opts_details =
self.option_details_for_path(self.p.meta.bin_name.as_ref().unwrap()),
name = self.0.bin_name.as_ref().unwrap(),
name_opts = self.all_options_for_path(self.0.bin_name.as_ref().unwrap()),
name_opts_details = self.option_details_for_path(self.0.bin_name.as_ref().unwrap()),
subcmds = self.all_subcommands(),
subcmd_details = self.subcommand_details()
).as_bytes()
@ -75,7 +71,7 @@ complete -F _{name} -o bashdefault -o default {name}
fn all_subcommands(&self) -> String {
debugln!("BashGen::all_subcommands;");
let mut subcmds = String::new();
let scs = completions::all_subcommand_names(self.p);
let scs = completions::all_subcommand_names(self.0);
for sc in &scs {
subcmds = format!(
@ -95,7 +91,7 @@ complete -F _{name} -o bashdefault -o default {name}
fn subcommand_details(&self) -> String {
debugln!("BashGen::subcommand_details;");
let mut subcmd_dets = String::new();
let mut scs = completions::get_all_subcommand_paths(self.p, true);
let mut scs = completions::get_all_subcommand_paths(self.0, true);
scs.sort();
scs.dedup();
@ -130,14 +126,14 @@ complete -F _{name} -o bashdefault -o default {name}
fn option_details_for_path(&self, path: &str) -> String {
debugln!("BashGen::option_details_for_path: path={}", path);
let mut p = self.p;
let mut p = self.0;
for sc in path.split("__").skip(1) {
debugln!("BashGen::option_details_for_path:iter: sc={}", sc);
p = &find_subcmd!(p, sc).unwrap().p;
p = &find_subcmd!(p, sc).unwrap();
}
let mut opts = String::new();
for o in p.opts() {
if let Some(l) = o.s.long {
for o in opts!(p) {
if let Some(l) = o.long {
opts = format!(
"{}
--{})
@ -149,7 +145,7 @@ complete -F _{name} -o bashdefault -o default {name}
self.vals_for(o)
);
}
if let Some(s) = o.s.short {
if let Some(s) = o.short {
opts = format!(
"{}
-{})
@ -165,15 +161,14 @@ complete -F _{name} -o bashdefault -o default {name}
opts
}
fn vals_for(&self, o: &OptBuilder) -> String {
debugln!("BashGen::vals_for: o={}", o.b.name);
use args::AnyArg;
fn vals_for(&self, o: &Arg) -> String {
debugln!("BashGen::vals_for: o={}", o.name);
let mut ret = String::new();
let mut needs_quotes = true;
if let Some(vals) = o.possible_vals() {
if let Some(ref vals) = o.possible_vals {
needs_quotes = false;
ret = format!("$(compgen -W \"{}\" -- ${{cur}})", vals.join(" "));
} else if let Some(vec) = o.val_names() {
} else if let Some(ref vec) = o.val_names {
let mut it = vec.iter().peekable();
while let Some((_, val)) = it.next() {
ret = format!(
@ -187,13 +182,13 @@ complete -F _{name} -o bashdefault -o default {name}
if o.is_set(ArgSettings::Multiple) && num == 1 {
ret = format!("{}...", ret);
}
} else if let Some(num) = o.num_vals() {
} else if let Some(num) = o.num_vals {
let mut it = (0..num).peekable();
while let Some(_) = it.next() {
ret = format!(
"{}<{}>{}",
ret,
o.name(),
o.name,
if it.peek().is_some() { " " } else { "" }
);
}
@ -201,7 +196,7 @@ complete -F _{name} -o bashdefault -o default {name}
ret = format!("{}...", ret);
}
} else {
ret = format!("<{}>", o.name());
ret = format!("<{}>", o.name);
if o.is_set(ArgSettings::Multiple) {
ret = format!("{}...", ret);
}
@ -213,43 +208,20 @@ complete -F _{name} -o bashdefault -o default {name}
}
fn all_options_for_path(&self, path: &str) -> String {
debugln!("BashGen::all_options_for_path: path={}", path);
let mut p = self.p;
let mut p = self.0;
for sc in path.split("__").skip(1) {
debugln!("BashGen::all_options_for_path:iter: sc={}", sc);
p = &find_subcmd!(p, sc).unwrap().p;
p = &find_subcmd!(p, sc).unwrap();
}
let mut opts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s));
opts = format!(
"{} {}",
opts,
longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l))
let opts = format!(
"{shorts} {longs} {pos} {subcmds}",
shorts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s)),
// Handles aliases too
longs = longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l)),
pos = positionals!(p).fold(String::new(), |acc, p| format!("{} {}", acc, p)),
// Handles aliases too
subcmds = sc_names!(p).fold(String::new(), |acc, s| format!("{} {}", acc, s))
);
opts = format!(
"{} {}",
opts,
p.positionals
.values()
.fold(String::new(), |acc, p| format!("{} {}", acc, p))
);
opts = format!(
"{} {}",
opts,
p.subcommands
.iter()
.fold(String::new(), |acc, s| format!("{} {}", acc, s.p.meta.name))
);
for sc in &p.subcommands {
if let Some(ref aliases) = sc.p.meta.aliases {
opts = format!(
"{} {}",
opts,
aliases
.iter()
.map(|&(n, _)| n)
.fold(String::new(), |acc, a| format!("{} {}", acc, a))
);
}
}
opts
}
}

View file

@ -2,20 +2,17 @@
use std::io::Write;
// Internal
use app::parser::Parser;
use app::App;
pub struct FishGen<'a, 'b>
pub struct FishGen<'a, 'b>(&'b App<'a, 'b>)
where
'a: 'b,
{
p: &'b Parser<'a, 'b>,
}
'a: 'b;
impl<'a, 'b> FishGen<'a, 'b> {
pub fn new(p: &'b Parser<'a, 'b>) -> Self { FishGen { p: p } }
pub fn new(app: &'b App<'a, 'b>) -> Self { FishGen(app) }
pub fn generate_to<W: Write>(&self, buf: &mut W) {
let command = self.p.meta.bin_name.as_ref().unwrap();
let command = self.0.bin_name.as_ref().unwrap();
// function to detect subcommand
let detect_subcommand_function = r#"function __fish_using_command
@ -58,48 +55,47 @@ fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, parent_cmds: &str, buf
let basic_template = format!(
"complete -c {} -n \"__fish_using_command {}\"",
root_command,
parent_cmds
root_command, parent_cmds
);
for option in comp_gen.p.opts() {
for option in opts!(comp_gen.0) {
let mut template = basic_template.clone();
if let Some(data) = option.s.short {
if let Some(data) = option.short {
template.push_str(format!(" -s {}", data).as_str());
}
if let Some(data) = option.s.long {
if let Some(data) = option.long {
template.push_str(format!(" -l {}", data).as_str());
}
if let Some(data) = option.b.help {
if let Some(data) = option.help {
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
}
if let Some(ref data) = option.v.possible_vals {
if let Some(ref data) = option.possible_vals {
template.push_str(format!(" -r -f -a \"{}\"", data.join(" ")).as_str());
}
buffer.push_str(template.as_str());
buffer.push_str("\n");
}
for flag in comp_gen.p.flags() {
for flag in flags!(comp_gen.0) {
let mut template = basic_template.clone();
if let Some(data) = flag.s.short {
if let Some(data) = flag.short {
template.push_str(format!(" -s {}", data).as_str());
}
if let Some(data) = flag.s.long {
if let Some(data) = flag.long {
template.push_str(format!(" -l {}", data).as_str());
}
if let Some(data) = flag.b.help {
if let Some(data) = flag.help {
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
}
buffer.push_str(template.as_str());
buffer.push_str("\n");
}
for subcommand in &comp_gen.p.subcommands {
for subcommand in subcommands!(comp_gen.0) {
let mut template = basic_template.clone();
template.push_str(" -f");
template.push_str(format!(" -a \"{}\"", &subcommand.p.meta.name).as_str());
if let Some(data) = subcommand.p.meta.about {
template.push_str(format!(" -a \"{}\"", &subcommand.name).as_str());
if let Some(data) = subcommand.about {
template.push_str(format!(" -d '{}'", escape_string(data)).as_str())
}
buffer.push_str(template.as_str());
@ -107,14 +103,14 @@ fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, parent_cmds: &str, buf
}
// generate options of subcommands
for subcommand in &comp_gen.p.subcommands {
let sub_comp_gen = FishGen::new(&subcommand.p);
for subcommand in subcommands!(comp_gen.0) {
let sub_comp_gen = FishGen::new(&subcommand);
// make new "parent_cmds" for different subcommands
let mut sub_parent_cmds = parent_cmds.to_string();
if !sub_parent_cmds.is_empty() {
sub_parent_cmds.push_str(" ");
}
sub_parent_cmds.push_str(&subcommand.p.meta.name);
sub_parent_cmds.push_str(&subcommand.name);
gen_fish_inner(root_command, &sub_comp_gen, &sub_parent_cmds, buffer);
}
}

View file

@ -8,15 +8,15 @@ macro_rules! w {
}
macro_rules! get_zsh_arg_conflicts {
($p:ident, $arg:ident, $msg:ident) => {
if let Some(conf_vec) = $arg.blacklist() {
($app:expr, $arg:ident, $msg:ident) => {
if let Some(ref conf_vec) = $arg.blacklist {
let mut v = vec![];
for arg_name in conf_vec {
let arg = $p.find_any_arg(arg_name).expect($msg);
if let Some(s) = arg.short() {
let arg = find!($app, arg_name).expect($msg);
if let Some(s) = arg.short {
v.push(format!("-{}", s));
}
if let Some(l) = arg.long() {
if let Some(l) = arg.long {
v.push(format!("--{}", l));
}
}

View file

@ -10,29 +10,26 @@ mod shell;
use std::io::Write;
// Internal
use app::parser::Parser;
use app::App;
use self::bash::BashGen;
use self::fish::FishGen;
use self::zsh::ZshGen;
use self::powershell::PowerShellGen;
pub use self::shell::Shell;
pub struct ComplGen<'a, 'b>
pub struct ComplGen<'a, 'b>(&'b App<'a, 'b>)
where
'a: 'b,
{
p: &'b Parser<'a, 'b>,
}
'a: 'b;
impl<'a, 'b> ComplGen<'a, 'b> {
pub fn new(p: &'b Parser<'a, 'b>) -> Self { ComplGen { p: p } }
pub fn new(app: &'b App<'a, 'b>) -> Self { ComplGen(app) }
pub fn generate<W: Write>(&self, for_shell: Shell, buf: &mut W) {
match for_shell {
Shell::Bash => BashGen::new(self.p).generate_to(buf),
Shell::Fish => FishGen::new(self.p).generate_to(buf),
Shell::Zsh => ZshGen::new(self.p).generate_to(buf),
Shell::PowerShell => PowerShellGen::new(self.p).generate_to(buf),
Shell::Bash => BashGen::new(self.0).generate_to(buf),
Shell::Fish => FishGen::new(self.0).generate_to(buf),
Shell::Zsh => ZshGen::new(self.0).generate_to(buf),
Shell::PowerShell => PowerShellGen::new(self.0).generate_to(buf),
}
}
}
@ -43,13 +40,13 @@ impl<'a, 'b> ComplGen<'a, 'b> {
//
// Also note, aliases are treated as their own subcommands but duplicates of whatever they're
// aliasing.
pub fn all_subcommand_names(p: &Parser) -> Vec<String> {
pub fn all_subcommand_names(p: &App) -> Vec<String> {
debugln!("all_subcommand_names;");
let mut subcmds: Vec<_> = subcommands_of(p)
.iter()
.map(|&(ref n, _)| n.clone())
.collect();
for sc_v in p.subcommands.iter().map(|s| all_subcommand_names(&s.p)) {
for sc_v in subcommands!(p).map(|s| all_subcommand_names(&s)) {
subcmds.extend(sc_v);
}
subcmds.sort();
@ -63,10 +60,10 @@ pub fn all_subcommand_names(p: &Parser) -> Vec<String> {
//
// Also note, aliases are treated as their own subcommands but duplicates of whatever they're
// aliasing.
pub fn all_subcommands(p: &Parser) -> Vec<(String, String)> {
pub fn all_subcommands(p: &App) -> Vec<(String, String)> {
debugln!("all_subcommands;");
let mut subcmds: Vec<_> = subcommands_of(p);
for sc_v in p.subcommands.iter().map(|s| all_subcommands(&s.p)) {
for sc_v in subcommands!(p).map(|s| all_subcommands(&s)) {
subcmds.extend(sc_v);
}
subcmds
@ -78,11 +75,11 @@ pub fn all_subcommands(p: &Parser) -> Vec<(String, String)> {
//
// Also note, aliases are treated as their own subcommands but duplicates of whatever they're
// aliasing.
pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
pub fn subcommands_of(p: &App) -> Vec<(String, String)> {
debugln!(
"subcommands_of: name={}, bin_name={}",
p.meta.name,
p.meta.bin_name.as_ref().unwrap()
p.name,
p.bin_name.as_ref().unwrap()
);
let mut subcmds = vec![];
@ -93,11 +90,10 @@ pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
if !p.has_subcommands() {
let mut ret = vec![];
debugln!("subcommands_of: Looking for aliases...");
if let Some(ref aliases) = p.meta.aliases {
if let Some(ref aliases) = p.aliases {
for &(n, _) in aliases {
debugln!("subcommands_of:iter:iter: Found alias...{}", n);
let mut als_bin_name: Vec<_> =
p.meta.bin_name.as_ref().unwrap().split(' ').collect();
let mut als_bin_name: Vec<_> = p.bin_name.as_ref().unwrap().split(' ').collect();
als_bin_name.push(n);
let old = als_bin_name.len() - 2;
als_bin_name.swap_remove(old);
@ -106,42 +102,38 @@ pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
}
return ret;
}
for sc in &p.subcommands {
for sc in subcommands!(p) {
debugln!(
"subcommands_of:iter: name={}, bin_name={}",
sc.p.meta.name,
sc.p.meta.bin_name.as_ref().unwrap()
sc.name,
sc.bin_name.as_ref().unwrap()
);
debugln!("subcommands_of:iter: Looking for aliases...");
if let Some(ref aliases) = sc.p.meta.aliases {
if let Some(ref aliases) = sc.aliases {
for &(n, _) in aliases {
debugln!("subcommands_of:iter:iter: Found alias...{}", n);
let mut als_bin_name: Vec<_> =
p.meta.bin_name.as_ref().unwrap().split(' ').collect();
let mut als_bin_name: Vec<_> = p.bin_name.as_ref().unwrap().split(' ').collect();
als_bin_name.push(n);
let old = als_bin_name.len() - 2;
als_bin_name.swap_remove(old);
subcmds.push((n.to_owned(), als_bin_name.join(" ")));
}
}
subcmds.push((
sc.p.meta.name.clone(),
sc.p.meta.bin_name.as_ref().unwrap().clone(),
));
subcmds.push((sc.name.clone(), sc.bin_name.as_ref().unwrap().clone()));
}
subcmds
}
pub fn get_all_subcommand_paths(p: &Parser, first: bool) -> Vec<String> {
pub fn get_all_subcommand_paths(p: &App, first: bool) -> Vec<String> {
debugln!("get_all_subcommand_paths;");
let mut subcmds = vec![];
if !p.has_subcommands() {
if !first {
let name = &*p.meta.name;
let path = p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "__");
let name = &*p.name;
let path = p.bin_name.as_ref().unwrap().clone().replace(" ", "__");
let mut ret = vec![path.clone()];
if let Some(ref aliases) = p.meta.aliases {
if let Some(ref aliases) = p.aliases {
for &(n, _) in aliases {
ret.push(path.replace(name, n));
}
@ -150,26 +142,17 @@ pub fn get_all_subcommand_paths(p: &Parser, first: bool) -> Vec<String> {
}
return vec![];
}
for sc in &p.subcommands {
let name = &*sc.p.meta.name;
let path = sc.p
.meta
.bin_name
.as_ref()
.unwrap()
.clone()
.replace(" ", "__");
for sc in subcommands!(p) {
let name = &*sc.name;
let path = sc.bin_name.as_ref().unwrap().clone().replace(" ", "__");
subcmds.push(path.clone());
if let Some(ref aliases) = sc.p.meta.aliases {
if let Some(ref aliases) = sc.aliases {
for &(n, _) in aliases {
subcmds.push(path.replace(name, n));
}
}
}
for sc_v in p.subcommands
.iter()
.map(|s| get_all_subcommand_paths(&s.p, false))
{
for sc_v in subcommands!(p).map(|s| get_all_subcommand_paths(&s, false)) {
subcmds.extend(sc_v);
}
subcmds

View file

@ -2,25 +2,22 @@
use std::io::Write;
// Internal
use app::parser::Parser;
use app::App;
use INTERNAL_ERROR_MSG;
pub struct PowerShellGen<'a, 'b>
pub struct PowerShellGen<'a, 'b>(&'b App<'a, 'b>)
where
'a: 'b,
{
p: &'b Parser<'a, 'b>,
}
'a: 'b;
impl<'a, 'b> PowerShellGen<'a, 'b> {
pub fn new(p: &'b Parser<'a, 'b>) -> Self { PowerShellGen { p: p } }
pub fn new(app: &'b App<'a, 'b>) -> Self { PowerShellGen(app) }
pub fn generate_to<W: Write>(&self, buf: &mut W) {
let bin_name = self.p.meta.bin_name.as_ref().unwrap();
let bin_name = self.0.bin_name.as_ref().unwrap();
let mut names = vec![];
let (subcommands_detection_cases, subcommands_cases) =
generate_inner(self.p, "", &mut names);
generate_inner(self.0, "", &mut names);
let mut bin_names = vec![bin_name.to_string(), format!("./{0}", bin_name)];
if cfg!(windows) {
@ -76,7 +73,7 @@ impl<'a, 'b> PowerShellGen<'a, 'b> {
}
fn generate_inner<'a, 'b, 'p>(
p: &'p Parser<'a, 'b>,
p: &'p App<'a, 'b>,
previous_command_name: &str,
names: &mut Vec<&'p str>,
) -> (String, String) {
@ -85,14 +82,14 @@ fn generate_inner<'a, 'b, 'p>(
format!(
"{}_{}",
previous_command_name,
&p.meta.bin_name.as_ref().expect(INTERNAL_ERROR_MSG)
&p.bin_name.as_ref().expect(INTERNAL_ERROR_MSG)
)
} else {
format!("{}_{}", previous_command_name, &p.meta.name)
format!("{}_{}", previous_command_name, &p.name)
};
let mut subcommands_detection_cases = if !names.contains(&&*p.meta.name) {
names.push(&*p.meta.name);
let mut subcommands_detection_cases = if !names.contains(&&*p.name) {
names.push(&*p.name);
format!(
r"
'{0}' {{
@ -100,7 +97,7 @@ fn generate_inner<'a, 'b, 'p>(
break
}}
",
&p.meta.name
&p.name
)
} else {
String::new()
@ -108,7 +105,7 @@ fn generate_inner<'a, 'b, 'p>(
let mut completions = String::new();
for subcommand in &p.subcommands {
completions.push_str(&format!("'{}', ", &subcommand.p.meta.name));
completions.push_str(&format!("'{}', ", &subcommand.name));
}
for short in shorts!(p) {
completions.push_str(&format!("'-{}', ", short));
@ -127,9 +124,9 @@ fn generate_inner<'a, 'b, 'p>(
completions.trim_right_matches(", ")
);
for subcommand in &p.subcommands {
for subcommand in subcommands!(p) {
let (subcommand_subcommands_detection_cases, subcommand_subcommands_cases) =
generate_inner(&subcommand.p, &command_name, names);
generate_inner(&subcommand, &command_name, names);
subcommands_detection_cases.push_str(&subcommand_subcommands_detection_cases);
subcommands_cases.push_str(&subcommand_subcommands_cases);
}

View file

@ -5,22 +5,18 @@ use std::ascii::AsciiExt;
// Internal
use app::App;
use app::parser::Parser;
use args::{AnyArg, ArgSettings};
use args::ArgSettings;
use completions;
use INTERNAL_ERROR_MSG;
pub struct ZshGen<'a, 'b>
pub struct ZshGen<'a, 'b>(&'b App<'a, 'b>)
where
'a: 'b,
{
p: &'b Parser<'a, 'b>,
}
'a: 'b;
impl<'a, 'b> ZshGen<'a, 'b> {
pub fn new(p: &'b Parser<'a, 'b>) -> Self {
pub fn new(app: &'b App<'a, 'b>) -> Self {
debugln!("ZshGen::new;");
ZshGen { p: p }
ZshGen(app)
}
pub fn generate_to<W: Write>(&self, buf: &mut W) {
@ -52,10 +48,10 @@ _{name}() {{
{subcommand_details}
_{name} \"$@\"",
name = self.p.meta.bin_name.as_ref().unwrap(),
initial_args = get_args_of(self.p),
subcommands = get_subcommands_of(self.p),
subcommand_details = subcommand_details(self.p)
name = self.0.bin_name.as_ref().unwrap(),
initial_args = get_args_of(self.0),
subcommands = get_subcommands_of(self.0),
subcommand_details = subcommand_details(self.0)
).as_bytes()
);
}
@ -88,7 +84,7 @@ _{name} \"$@\"",
// )
// _describe -t commands 'rustup commands' commands "$@"
//
fn subcommand_details(p: &Parser) -> String {
fn subcommand_details(p: &App) -> String {
debugln!("ZshGen::subcommand_details;");
// First we do ourself
let mut ret = vec![
@ -101,8 +97,8 @@ _{bin_name_underscore}_commands() {{
)
_describe -t commands '{bin_name} commands' commands \"$@\"
}}",
bin_name_underscore = p.meta.bin_name.as_ref().unwrap().replace(" ", "__"),
bin_name = p.meta.bin_name.as_ref().unwrap(),
bin_name_underscore = p.bin_name.as_ref().unwrap().replace(" ", "__"),
bin_name = p.bin_name.as_ref().unwrap(),
subcommands_and_args = subcommands_of(p)
),
];
@ -142,7 +138,7 @@ _{bin_name_underscore}_commands() {{
// A snippet from rustup:
// 'show:Show the active and installed toolchains'
// 'update:Update Rust toolchains'
fn subcommands_of(p: &Parser) -> String {
fn subcommands_of(p: &App) -> String {
debugln!("ZshGen::subcommands_of;");
let mut ret = vec![];
fn add_sc(sc: &App, n: &str, ret: &mut Vec<String>) {
@ -150,9 +146,7 @@ fn subcommands_of(p: &Parser) -> String {
let s = format!(
"\"{name}:{help}\" \\",
name = n,
help = sc.p
.meta
.about
help = sc.about
.unwrap_or("")
.replace("[", "\\[")
.replace("]", "\\]")
@ -163,13 +157,10 @@ fn subcommands_of(p: &Parser) -> String {
}
// The subcommands
for sc in p.subcommands() {
debugln!(
"ZshGen::subcommands_of:iter: subcommand={}",
sc.p.meta.name
);
add_sc(sc, &sc.p.meta.name, &mut ret);
if let Some(ref v) = sc.p.meta.aliases {
for sc in subcommands!(p) {
debugln!("ZshGen::subcommands_of:iter: subcommand={}", sc.name);
add_sc(sc, &sc.name, &mut ret);
if let Some(ref v) = sc.aliases {
for alias in v.iter().filter(|&&(_, vis)| vis).map(|&(n, _)| n) {
add_sc(sc, alias, &mut ret);
}
@ -208,7 +199,7 @@ fn subcommands_of(p: &Parser) -> String {
// [name_hyphen] = The full space deliniated bin_name, but replace spaces with hyphens
// [repeat] = From the same recursive calls, but for all subcommands
// [subcommand_args] = The same as zsh::get_args_of
fn get_subcommands_of(p: &Parser) -> String {
fn get_subcommands_of(p: &App) -> String {
debugln!("get_subcommands_of;");
debugln!(
@ -247,19 +238,20 @@ fn get_subcommands_of(p: &Parser) -> String {
esac
;;
esac",
name = p.meta.name,
name_hyphen = p.meta.bin_name.as_ref().unwrap().replace(" ", "-"),
name = p.name,
name_hyphen = p.bin_name.as_ref().unwrap().replace(" ", "-"),
subcommands = subcmds.join("\n"),
pos = p.positionals().len() + 1
pos = positionals!(p).count() + 1
)
}
fn parser_of<'a, 'b>(p: &'b Parser<'a, 'b>, sc: &str) -> &'b Parser<'a, 'b> {
fn parser_of<'a, 'b>(p: &'b App<'a, 'b>, mut sc: &str) -> &'b App<'a, 'b> {
debugln!("parser_of: sc={}", sc);
if sc == p.meta.bin_name.as_ref().unwrap_or(&String::new()) {
if sc == p.bin_name.as_ref().unwrap_or(&String::new()) {
return p;
}
&p.find_subcommand(sc).expect(INTERNAL_ERROR_MSG).p
sc = sc.split(" ").last().unwrap();
find_subcmd!(p, sc).expect(INTERNAL_ERROR_MSG)
}
// Writes out the args section, which ends up being the flags, opts and postionals, and a jump to
@ -282,7 +274,7 @@ fn parser_of<'a, 'b>(p: &'b Parser<'a, 'b>, sc: &str) -> &'b Parser<'a, 'b> {
// -C: modify the $context internal variable
// -s: Allow stacking of short args (i.e. -a -b -c => -abc)
// -S: Do not complete anything after '--' and treat those as argument values
fn get_args_of(p: &Parser) -> String {
fn get_args_of(p: &App) -> String {
debugln!("get_args_of;");
let mut ret = vec![String::from("_arguments \"${_arguments_options[@]}\" \\")];
let opts = write_opts_of(p);
@ -291,13 +283,13 @@ fn get_args_of(p: &Parser) -> String {
let sc_or_a = if p.has_subcommands() {
format!(
"\":: :_{name}_commands\" \\",
name = p.meta.bin_name.as_ref().unwrap().replace(" ", "__")
name = p.bin_name.as_ref().unwrap().replace(" ", "__")
)
} else {
String::new()
};
let sc = if p.has_subcommands() {
format!("\"*::: :->{name}\" \\", name = p.meta.name)
format!("\"*::: :->{name}\" \\", name = p.name)
} else {
String::new()
};
@ -341,12 +333,12 @@ fn escape_value(string: &str) -> String {
.replace(" ", "\\ ")
}
fn write_opts_of(p: &Parser) -> String {
fn write_opts_of(p: &App) -> String {
debugln!("write_opts_of;");
let mut ret = vec![];
for o in p.opts() {
debugln!("write_opts_of:iter: o={}", o.name());
let help = o.help().map_or(String::new(), escape_help);
for o in opts!(p) {
debugln!("write_opts_of:iter: o={}", o.name);
let help = o.help.map_or(String::new(), escape_help);
let mut conflicts = get_zsh_arg_conflicts!(p, o, INTERNAL_ERROR_MSG);
conflicts = if conflicts.is_empty() {
String::new()
@ -359,13 +351,19 @@ fn write_opts_of(p: &Parser) -> String {
} else {
""
};
let pv = if let Some(pv_vec) = o.possible_vals() {
format!(": :({})", pv_vec.iter().map(
|v| escape_value(*v)).collect::<Vec<String>>().join(" "))
let pv = if let Some(ref pv_vec) = o.possible_vals {
format!(
": :({})",
pv_vec
.iter()
.map(|v| escape_value(*v))
.collect::<Vec<String>>()
.join(" ")
)
} else {
String::new()
};
if let Some(short) = o.short() {
if let Some(short) = o.short {
let s = format!(
"'{conflicts}{multiple}-{arg}+[{help}]{possible_values}' \\",
conflicts = conflicts,
@ -378,7 +376,7 @@ fn write_opts_of(p: &Parser) -> String {
debugln!("write_opts_of:iter: Wrote...{}", &*s);
ret.push(s);
}
if let Some(long) = o.long() {
if let Some(long) = o.long {
let l = format!(
"'{conflicts}{multiple}--{arg}=[{help}]{possible_values}' \\",
conflicts = conflicts,
@ -396,12 +394,12 @@ fn write_opts_of(p: &Parser) -> String {
ret.join("\n")
}
fn write_flags_of(p: &Parser) -> String {
fn write_flags_of(p: &App) -> String {
debugln!("write_flags_of;");
let mut ret = vec![];
for f in p.flags() {
debugln!("write_flags_of:iter: f={}", f.name());
let help = f.help().map_or(String::new(), escape_help);
for f in flags!(p) {
debugln!("write_flags_of:iter: f={}", f.name);
let help = f.help.map_or(String::new(), escape_help);
let mut conflicts = get_zsh_arg_conflicts!(p, f, INTERNAL_ERROR_MSG);
conflicts = if conflicts.is_empty() {
String::new()
@ -414,7 +412,7 @@ fn write_flags_of(p: &Parser) -> String {
} else {
""
};
if let Some(short) = f.short() {
if let Some(short) = f.short {
let s = format!(
"'{conflicts}{multiple}-{arg}[{help}]' \\",
multiple = multiple,
@ -427,7 +425,7 @@ fn write_flags_of(p: &Parser) -> String {
ret.push(s);
}
if let Some(long) = f.long() {
if let Some(long) = f.long {
let l = format!(
"'{conflicts}{multiple}--{arg}[{help}]' \\",
conflicts = conflicts,
@ -444,24 +442,33 @@ fn write_flags_of(p: &Parser) -> String {
ret.join("\n")
}
fn write_positionals_of(p: &Parser) -> String {
fn write_positionals_of(p: &App) -> String {
debugln!("write_positionals_of;");
let mut ret = vec![];
for arg in p.positionals() {
debugln!("write_positionals_of:iter: arg={}", arg.b.name);
for arg in positionals!(p) {
debugln!("write_positionals_of:iter: arg={}", arg.name);
let a = format!(
"'{optional}:{name}{help}:{action}' \\",
optional = if !arg.b.is_set(ArgSettings::Required) { ":" } else { "" },
name = arg.b.name,
help = arg.b
.help
optional = if !arg.is_set(ArgSettings::Required) {
":"
} else {
""
},
name = arg.name,
help = arg.help
.map_or("".to_owned(), |v| " -- ".to_owned() + v)
.replace("[", "\\[")
.replace("]", "\\]"),
action = arg.possible_vals().map_or("_files".to_owned(), |values| {
format!("({})",
values.iter().map(|v| escape_value(*v)).collect::<Vec<String>>().join(" "))
})
action = arg.possible_vals
.as_ref()
.map_or("_files".to_owned(), |values| format!(
"({})",
values
.iter()
.map(|v| escape_value(*v))
.collect::<Vec<String>>()
.join(" ")
))
);
debugln!("write_positionals_of:iter: Wrote...{}", a);

View file

@ -8,7 +8,7 @@ use std::process;
use std::result::Result as StdResult;
// Internal
use args::AnyArg;
use args::Arg;
use fmt::{ColorWhen, Colorizer, ColorizerOption};
use suggestions;
@ -405,7 +405,7 @@ impl Error {
#[doc(hidden)]
pub fn argument_conflict<'a, 'b, O, U>(
arg: &AnyArg,
arg: &Arg,
other: Option<O>,
usage: U,
color: ColorWhen,
@ -414,7 +414,7 @@ impl Error {
O: Into<String>,
U: Display,
{
let mut v = vec![arg.name().to_owned()];
let mut v = vec![arg.name.to_owned()];
let c = Colorizer::new(ColorizerOption {
use_stderr: true,
when: color,
@ -443,7 +443,7 @@ impl Error {
}
#[doc(hidden)]
pub fn empty_value<'a, 'b, U>(arg: &AnyArg, usage: U, color: ColorWhen) -> Self
pub fn empty_value<'a, 'b, U>(arg: &Arg, usage: U, color: ColorWhen) -> Self
where
U: Display,
{
@ -463,7 +463,7 @@ impl Error {
c.good("--help")
),
kind: ErrorKind::EmptyValue,
info: Some(vec![arg.name().to_owned()]),
info: Some(vec![arg.name.to_owned()]),
}
}
@ -471,7 +471,7 @@ impl Error {
pub fn invalid_value<'a, 'b, B, G, U>(
bad_val: B,
good_vals: &[G],
arg: &AnyArg,
arg: &Arg,
usage: U,
color: ColorWhen,
) -> Self
@ -509,7 +509,7 @@ impl Error {
c.good("--help")
),
kind: ErrorKind::InvalidValue,
info: Some(vec![arg.name().to_owned(), bad_val.as_ref().to_owned()]),
info: Some(vec![arg.name.to_owned(), bad_val.as_ref().to_owned()]),
}
}
@ -632,7 +632,6 @@ impl Error {
}
}
#[doc(hidden)]
pub fn invalid_utf8<U>(usage: U, color: ColorWhen) -> Self
where
@ -657,7 +656,7 @@ impl Error {
}
#[doc(hidden)]
pub fn too_many_values<'a, 'b, V, U>(val: V, arg: &AnyArg, usage: U, color: ColorWhen) -> Self
pub fn too_many_values<'a, 'b, V, U>(val: V, arg: &Arg, usage: U, color: ColorWhen) -> Self
where
V: AsRef<str> + Display + ToOwned,
U: Display,
@ -680,13 +679,13 @@ impl Error {
c.good("--help")
),
kind: ErrorKind::TooManyValues,
info: Some(vec![arg.name().to_owned(), v.to_owned()]),
info: Some(vec![arg.name.to_owned(), v.to_owned()]),
}
}
#[doc(hidden)]
pub fn too_few_values<'a, 'b, U>(
arg: &AnyArg,
arg: &Arg,
min_vals: u64,
curr_vals: usize,
usage: U,
@ -714,13 +713,12 @@ impl Error {
c.good("--help")
),
kind: ErrorKind::TooFewValues,
info: Some(vec![arg.name().to_owned()]),
info: Some(vec![arg.name.to_owned()]),
}
}
#[doc(hidden)]
pub fn value_validation<'a, 'b>(arg: Option<&AnyArg>, err: String, color: ColorWhen) -> Self
{
pub fn value_validation<'a, 'b>(arg: Option<&Arg>, err: String, color: ColorWhen) -> Self {
let c = Colorizer::new(ColorizerOption {
use_stderr: true,
when: color,
@ -743,13 +741,13 @@ impl Error {
#[doc(hidden)]
pub fn value_validation_auto(err: String) -> Self {
let n: Option<&AnyArg> = None;
let n: Option<&Arg> = None;
Error::value_validation(n, err, ColorWhen::Auto)
}
#[doc(hidden)]
pub fn wrong_number_of_values<'a, 'b, S, U>(
arg: &AnyArg,
arg: &Arg,
num_vals: u64,
curr_vals: usize,
suffix: S,
@ -779,12 +777,12 @@ impl Error {
c.good("--help")
),
kind: ErrorKind::WrongNumberOfValues,
info: Some(vec![arg.name().to_owned()]),
info: Some(vec![arg.name.to_owned()]),
}
}
#[doc(hidden)]
pub fn unexpected_multiple_usage<'a, 'b, U>(arg: &AnyArg, usage: U, color: ColorWhen) -> Self
pub fn unexpected_multiple_usage<'a, 'b, U>(arg: &Arg, usage: U, color: ColorWhen) -> Self
where
U: Display,
{
@ -804,7 +802,7 @@ impl Error {
c.good("--help")
),
kind: ErrorKind::UnexpectedMultipleUsage,
info: Some(vec![arg.name().to_owned()]),
info: Some(vec![arg.name.to_owned()]),
}
}

View file

@ -152,7 +152,6 @@ impl<T: fmt::Display> Format<T> {
}
}
#[cfg(all(feature = "color", not(target_os = "windows")))]
impl<T: AsRef<str>> fmt::Display for Format<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", &self.format()) }

View file

@ -534,6 +534,7 @@ extern crate ansi_term;
extern crate atty;
#[macro_use]
extern crate bitflags;
extern crate ordermap;
#[cfg(feature = "suggestions")]
extern crate strsim;
#[cfg(feature = "wrap_help")]
@ -548,7 +549,7 @@ extern crate yaml_rust;
#[cfg(feature = "yaml")]
pub use yaml_rust::YamlLoader;
pub use args::{Arg, ArgGroup, ArgMatches, ArgSettings, OsValues, SubCommand, Values};
pub use app::{App, AppSettings};
pub use app::{App, AppSettings, Propagation};
pub use fmt::Format;
pub use errors::{Error, ErrorKind, Result};
pub use completions::Shell;
@ -594,7 +595,6 @@ mod derive {
Self::try_from_argmatches(Self::into_app().get_matches_safe()?)
}
/// @TODO @release @docs
fn try_parse_from<I, T>(argv: I) -> Result<Self, clap::Error>
where

View file

@ -852,38 +852,120 @@ macro_rules! write_nspaces {
})
}
// convenience macro for remove an item from a vec
//macro_rules! vec_remove_all {
// ($vec:expr, $to_rem:expr) => {
// debugln!("vec_remove_all! to_rem={:?}", $to_rem);
// for i in (0 .. $vec.len()).rev() {
// let should_remove = $to_rem.any(|name| name == &$vec[i]);
// if should_remove { $vec.swap_remove(i); }
// }
// };
//}
macro_rules! args {
($app:expr, $how:ident) => {
$app.args.$how()
};
($app:expr) => {
args!($app, iter)
}
}
macro_rules! args_mut {
($app:expr) => {
args!($app, iter_mut)
}
}
macro_rules! flags {
($app:expr, $how:ident) => {
$app.args.$how()
.filter(|a| !a.settings.is_set(::args::settings::ArgSettings::TakesValue))
.filter(|a| a.short.is_some() || a.long.is_some())
};
($app:expr) => {
flags!($app, iter)
}
}
#[allow(unused_macros)]
macro_rules! flags_mut {
($app:expr) => {
flags!($app, iter_mut)
}
}
macro_rules! opts {
($app:expr, $how:ident) => {
$app.args.$how()
.filter(|a| a.settings.is_set(::args::settings::ArgSettings::TakesValue))
.filter(|a| a.short.is_some() || a.long.is_some())
};
($app:expr) => {
opts!($app, iter)
}
}
#[allow(unused_macros)]
macro_rules! opts_mut {
($app:expr) => {
opts!($app, iter_mut)
}
}
macro_rules! positionals {
($app:expr, $how:ident) => {
$app.args.$how().filter(|a| !(a.short.is_some() || a.long.is_some()))
};
($app:expr) => {
positionals!($app, iter)
}
}
#[allow(unused_macros)]
macro_rules! positionals_mut {
($app:expr) => {
positionals!($app, iter_mut)
}
}
macro_rules! subcommands_cloned {
($app:expr, $how:ident) => {
$app.subcommands.$how().cloned()
};
($app:expr) => {
subcommands_cloned!($app, iter)
}
}
macro_rules! subcommands {
($app:expr, $how:ident) => {
$app.subcommands.$how()
};
($app:expr) => {
subcommands!($app, iter)
}
}
macro_rules! subcommands_mut {
($app:expr) => {
subcommands!($app, iter_mut)
}
}
macro_rules! groups {
($app:expr, $how:ident) => {
$app.groups.$how()
};
($app:expr) => {
groups!($app, iter)
}
}
macro_rules! groups_mut {
($app:expr) => {
groups!($app, iter_mut)
}
}
macro_rules! find_from {
($_self:expr, $arg_name:expr, $from:ident, $matcher:expr) => {{
($app:expr, $arg_name:expr, $from:ident, $matcher:expr) => {{
let mut ret = None;
for k in $matcher.arg_names() {
if let Some(f) = find_by_name!($_self, k, flags, iter) {
if let Some(ref v) = f.$from() {
if let Some(a) = find!($app, k) {
if let Some(ref v) = a.$from {
if v.contains($arg_name) {
ret = Some(f.to_string());
}
}
}
if let Some(o) = find_by_name!($_self, k, opts, iter) {
if let Some(ref v) = o.$from() {
if v.contains(&$arg_name) {
ret = Some(o.to_string());
}
}
}
if let Some(pos) = find_by_name!($_self, k, positionals, values) {
if let Some(ref v) = pos.$from() {
if v.contains($arg_name) {
ret = Some(pos.b.name.to_owned());
ret = Some(a.to_string());
}
}
}
@ -892,188 +974,114 @@ macro_rules! find_from {
}};
}
//macro_rules! find_name_from {
// ($_self:expr, $arg_name:expr, $from:ident, $matcher:expr) => {{
// let mut ret = None;
// for k in $matcher.arg_names() {
// if let Some(f) = find_by_name!($_self, k, flags, iter) {
// if let Some(ref v) = f.$from() {
// if v.contains($arg_name) {
// ret = Some(f.b.name);
// }
// }
// }
// if let Some(o) = find_by_name!($_self, k, opts, iter) {
// if let Some(ref v) = o.$from() {
// if v.contains(&$arg_name) {
// ret = Some(o.b.name);
// }
// }
// }
// if let Some(pos) = find_by_name!($_self, k, positionals, values) {
// if let Some(ref v) = pos.$from() {
// if v.contains($arg_name) {
// ret = Some(pos.b.name);
// }
// }
// }
// }
// ret
// }};
//}
macro_rules! find_any_by_name {
($p:expr, $name:expr) => {
{
fn as_trait_obj<'a, 'b, T: AnyArg<'a, 'b>>(x: &T) -> &AnyArg<'a, 'b> { x }
find_by_name!($p, $name, flags, iter).map(as_trait_obj).or(
find_by_name!($p, $name, opts, iter).map(as_trait_obj).or(
find_by_name!($p, $name, positionals, values).map(as_trait_obj)
)
)
}
}
}
// Finds an arg by name
macro_rules! find_by_name {
($p:expr, $name:expr, $what:ident, $how:ident) => {
$p.$what.$how().find(|o| o.b.name == $name)
macro_rules! find {
($app:expr, $name:expr, $what:ident) => {
$what!($app).find(|a| &a.name == $name)
};
($app:expr, $name:expr) => {
$app.args.iter().find(|a| &a.name == $name)
}
}
// Finds an option including if it's aliasesed
macro_rules! find_opt_by_long {
(@os $_self:ident, $long:expr) => {{
_find_by_long!($_self, $long, opts)
macro_rules! find_by_long {
($app:expr, $long:expr, $what:ident) => {{
$what!($app)
.filter(|a| a.long.is_some())
.find(|a| match_alias!(a, $long, a.long.unwrap()))
}};
($_self:ident, $long:expr) => {{
_find_by_long!($_self, $long, opts)
($app:expr, $long:expr) => {{
$app.args.iter()
.filter(|a| a.long.is_some())
.find(|a| match_alias!(a, $long, a.long.unwrap()))
}};
}
macro_rules! find_flag_by_long {
(@os $_self:ident, $long:expr) => {{
_find_by_long!($_self, $long, flags)
macro_rules! find_by_short {
($app:expr, $short:expr, $what:ident) => {{
$what!($app)
.find(|a| a.short == Some($short))
}};
($_self:ident, $long:expr) => {{
_find_by_long!($_self, $long, flags)
($app:expr, $short:expr) => {{
$app.args.iter()
.find(|a| a.short == Some($short))
}}
}
macro_rules! find_subcmd_cloned {
($_self:expr, $sc:expr) => {{
subcommands_cloned!($_self)
.find(|a| match_alias!(a, $sc, &*a.name))
}};
}
macro_rules! _find_by_long {
($_self:ident, $long:expr, $what:ident) => {{
$_self.$what
.iter()
.filter(|a| a.s.long.is_some())
.find(|a| {
a.s.long.unwrap() == $long ||
(a.s.aliases.is_some() &&
a.s
.aliases
.as_ref()
.unwrap()
.iter()
.any(|&(alias, _)| alias == $long))
})
}}
}
// Finds an option
macro_rules! find_opt_by_short {
($_self:ident, $short:expr) => {{
_find_by_short!($_self, $short, opts)
}}
}
macro_rules! find_flag_by_short {
($_self:ident, $short:expr) => {{
_find_by_short!($_self, $short, flags)
}}
}
macro_rules! _find_by_short {
($_self:ident, $short:expr, $what:ident) => {{
$_self.$what
.iter()
.filter(|a| a.s.short.is_some())
.find(|a| a.s.short.unwrap() == $short)
}}
}
macro_rules! find_subcmd {
($_self:expr, $sc:expr) => {{
$_self.subcommands
.iter()
.find(|s| {
&*s.p.meta.name == $sc ||
(s.p.meta.aliases.is_some() &&
s.p
.meta
.aliases
.as_ref()
.unwrap()
.iter()
.any(|&(n, _)| n == $sc))
})
($app:expr, $sc:expr) => {{
subcommands!($app)
.find(|a| match_alias!(a, $sc, &*a.name))
}};
}
macro_rules! shorts {
($_self:ident) => {{
_shorts_longs!($_self, short)
($app:expr) => {{
_shorts_longs!($app, short)
}};
}
macro_rules! longs {
($_self:ident) => {{
_shorts_longs!($_self, long)
($app:expr) => {{
$app.args.iter()
.filter(|a| a.long.is_some())
.map(|a| a.long.unwrap())
.chain($app.args.iter()
.filter(|a| a.aliases.is_some())
.flat_map(|a| a.aliases.as_ref().unwrap().iter().map(|als| als.0)))
}};
}
macro_rules! _shorts_longs {
($_self:ident, $what:ident) => {{
$_self.flags
.iter()
.filter(|f| f.s.$what.is_some())
.map(|f| f.s.$what.as_ref().unwrap())
.chain($_self.opts.iter()
.filter(|o| o.s.$what.is_some())
.map(|o| o.s.$what.as_ref().unwrap()))
}};
}
macro_rules! arg_names {
($_self:ident) => {{
_names!(@args $_self)
}};
}
macro_rules! sc_names {
($_self:ident) => {{
_names!(@sc $_self)
($app:expr, $what:ident) => {{
$app.args.iter().filter_map(|a| a.$what)
}};
}
macro_rules! _names {
(@args $_self:ident) => {{
$_self.flags
.iter()
.map(|f| &*f.b.name)
.chain($_self.opts.iter()
.map(|o| &*o.b.name)
.chain($_self.positionals.values()
.map(|p| &*p.b.name)))
(@args $app:expr) => {{
$app.args.iter().map(|a| &*a.name)
}};
(@sc $_self:ident) => {{
$_self.subcommands
(@sc $app:expr) => {{
$app.subcommands
.iter()
.map(|s| &*s.p.meta.name)
.chain($_self.subcommands
.map(|s| &*s.name)
.chain($app.subcommands
.iter()
.filter(|s| s.p.meta.aliases.is_some())
.flat_map(|s| s.p.meta.aliases.as_ref().unwrap().iter().map(|&(n, _)| n)))
.filter(|s| s.aliases.is_some())
.flat_map(|s| s.aliases.as_ref().unwrap().iter().map(|&(n, _)| n)))
}}
}
macro_rules! arg_names {
($app:expr) => {{
_names!(@args $app)
}};
}
macro_rules! sc_names {
($app:expr) => {{
_names!(@sc $app)
}};
}
macro_rules! match_alias {
($a:expr, $to:expr, $what:expr) => {{
$what == $to ||
($a.aliases.is_some() &&
$a.aliases
.as_ref()
.unwrap()
.iter()
.any(|alias| alias.0 == $to))
}}
}

View file

@ -1,10 +1,10 @@
use app::App;
// Third Party
#[cfg(feature = "suggestions")]
use strsim;
// Internal
use fmt::Format;
use app::App;
/// Produces a string from a given list of possible values which is similar to
/// the passed in value `v` with a certain confidence.
@ -42,14 +42,13 @@ where
/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
pub fn did_you_mean_flag_suffix<'z, T, I>(
pub fn did_you_mean_flag_suffix<'z, I>(
arg: &str,
longs: I,
subcommands: &'z [App],
) -> (String, Option<&'z str>)
where
T: AsRef<str> + 'z,
I: IntoIterator<Item = &'z T>,
I: IntoIterator<Item = &'z str>,
{
match did_you_mean(arg, longs) {
Some(candidate) => {
@ -61,14 +60,9 @@ where
return (suffix, Some(candidate));
}
None => for subcommand in subcommands {
let opts = subcommand
.p
.flags
.iter()
.filter_map(|f| f.s.long)
.chain(subcommand.p.opts.iter().filter_map(|o| o.s.long));
let longs = longs!(subcommand);
if let Some(candidate) = did_you_mean(arg, opts) {
if let Some(candidate) = did_you_mean(arg, longs) {
let suffix = format!(
"\n\tDid you mean to put '{}{}' after the subcommand '{}'?",
Format::Good("--"),

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
extern crate clap;
extern crate regex;
use clap::{App, Arg, SubCommand, AppSettings, ErrorKind};
use clap::{App, AppSettings, Arg, ErrorKind, Propagation, SubCommand};
include!("../clap-test.rs");
@ -77,9 +77,7 @@ ARGS:
fn sub_command_negate_required() {
App::new("sub_command_negate")
.setting(AppSettings::SubcommandsNegateReqs)
.arg(Arg::with_name("test")
.required(true)
.index(1))
.arg(Arg::with_name("test").required(true).index(1))
.subcommand(SubCommand::with_name("sub1"))
.get_matches_from(vec!["myprog", "sub1"]);
}
@ -90,17 +88,15 @@ fn 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"));
app._propagate(Propagation::NextLevel);
assert_eq!(app.subcommands[0].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))
.arg(Arg::with_name("test").required(true).index(1))
.subcommand(SubCommand::with_name("sub1"))
.get_matches_from_safe(vec![""]);
assert!(result.is_err());
@ -123,8 +119,7 @@ fn sub_command_required() {
fn arg_required_else_help() {
let result = App::new("arg_required")
.setting(AppSettings::ArgRequiredElseHelp)
.arg(Arg::with_name("test")
.index(1))
.arg(Arg::with_name("test").index(1))
.get_matches_from_safe(vec![""]);
assert!(result.is_err());
let err = result.err().unwrap();
@ -135,8 +130,7 @@ fn arg_required_else_help() {
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))
.arg(Arg::with_name("test").index(1).required(true))
.get_matches_from_safe(vec![""]);
assert!(result.is_err());
let err = result.err().unwrap();
@ -150,9 +144,7 @@ fn infer_subcommands_fail_no_args() {
.setting(AppSettings::InferSubcommands)
.subcommand(SubCommand::with_name("test"))
.subcommand(SubCommand::with_name("temp"))
.get_matches_from_safe(vec![
"prog", "te"
]);
.get_matches_from_safe(vec!["prog", "te"]);
assert!(m.is_err(), "{:#?}", m.unwrap());
assert_eq!(m.unwrap_err().kind, ErrorKind::UnrecognizedSubcommand);
}
@ -164,9 +156,7 @@ fn infer_subcommands_fail_no_args() {
.setting(AppSettings::InferSubcommands)
.subcommand(SubCommand::with_name("test"))
.subcommand(SubCommand::with_name("temp"))
.get_matches_from_safe(vec![
"prog", "te"
]);
.get_matches_from_safe(vec!["prog", "te"]);
assert!(m.is_err(), "{:#?}", m.unwrap());
assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidSubcommand);
}
@ -178,9 +168,7 @@ fn infer_subcommands_fail_with_args() {
.arg(Arg::with_name("some"))
.subcommand(SubCommand::with_name("test"))
.subcommand(SubCommand::with_name("temp"))
.get_matches_from_safe(vec![
"prog", "t"
]);
.get_matches_from_safe(vec!["prog", "t"]);
assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
assert_eq!(m.unwrap().value_of("some"), Some("t"));
}
@ -192,9 +180,7 @@ fn infer_subcommands_fail_with_args2() {
.arg(Arg::with_name("some"))
.subcommand(SubCommand::with_name("test"))
.subcommand(SubCommand::with_name("temp"))
.get_matches_from_safe(vec![
"prog", "te"
]);
.get_matches_from_safe(vec!["prog", "te"]);
assert!(m.is_ok(), "{:?}", m.unwrap_err().kind);
assert_eq!(m.unwrap().value_of("some"), Some("te"));
}
@ -204,9 +190,7 @@ fn infer_subcommands_pass() {
let m = App::new("prog")
.setting(AppSettings::InferSubcommands)
.subcommand(SubCommand::with_name("test"))
.get_matches_from(vec![
"prog", "te"
]);
.get_matches_from(vec!["prog", "te"]);
assert_eq!(m.subcommand_name(), Some("test"));
}
@ -216,9 +200,7 @@ fn infer_subcommands_pass_close() {
.setting(AppSettings::InferSubcommands)
.subcommand(SubCommand::with_name("test"))
.subcommand(SubCommand::with_name("temp"))
.get_matches_from(vec![
"prog", "tes"
]);
.get_matches_from(vec!["prog", "tes"]);
assert_eq!(m.subcommand_name(), Some("test"));
}
@ -229,9 +211,7 @@ fn infer_subcommands_fail_suggestions() {
.setting(AppSettings::InferSubcommands)
.subcommand(SubCommand::with_name("test"))
.subcommand(SubCommand::with_name("temp"))
.get_matches_from_safe(vec![
"prog", "temps"
]);
.get_matches_from_safe(vec!["prog", "temps"]);
assert!(m.is_err(), "{:#?}", m.unwrap());
assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidSubcommand);
}
@ -243,9 +223,7 @@ fn infer_subcommands_fail_suggestions() {
.setting(AppSettings::InferSubcommands)
.subcommand(SubCommand::with_name("test"))
.subcommand(SubCommand::with_name("temp"))
.get_matches_from_safe(vec![
"prog", "temps"
]);
.get_matches_from_safe(vec!["prog", "temps"]);
assert!(m.is_err(), "{:#?}", m.unwrap());
assert_eq!(m.unwrap_err().kind, ErrorKind::UnrecognizedSubcommand);
}
@ -254,9 +232,7 @@ fn infer_subcommands_fail_suggestions() {
fn no_bin_name() {
let result = App::new("arg_required")
.setting(AppSettings::NoBinaryName)
.arg(Arg::with_name("test")
.required(true)
.index(1))
.arg(Arg::with_name("test").required(true).index(1))
.get_matches_from_safe(vec!["testing"]);
assert!(result.is_ok());
let matches = result.unwrap();
@ -271,11 +247,18 @@ fn unified_help() {
.about("tests stuff")
.version("1.3")
.setting(AppSettings::UnifiedHelpMessage)
.args_from_usage("-f, --flag 'some flag'
.args_from_usage(
"-f, --flag 'some flag'
[arg1] 'some pos arg'
--option [opt] 'some option'");
--option [opt] 'some option'",
);
assert!(test::compare_output(app, "test --help", UNIFIED_HELP, false));
assert!(test::compare_output(
app,
"test --help",
UNIFIED_HELP,
false
));
}
#[test]
@ -285,10 +268,17 @@ fn skip_possible_values() {
.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"])]);
.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));
assert!(test::compare_output(
app,
"test --help",
SKIP_POS_VALS,
false
));
}
#[test]
@ -296,17 +286,15 @@ 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
app._propagate(Propagation::NextLevel);
assert!(
app.subcommands
.iter()
.filter(|s| s.p
.meta
.name == "subcmd")
.filter(|s| s.name == "subcmd")
.next()
.unwrap()
.p
.is_set(AppSettings::ColoredHelp));
.is_set(AppSettings::ColoredHelp)
);
}
#[test]
@ -314,42 +302,42 @@ 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
app._propagate(Propagation::NextLevel);
assert!(
app.subcommands
.iter()
.filter(|s| s.p
.meta
.name == "subcmd")
.filter(|s| s.name == "subcmd")
.next()
.unwrap()
.p
.is_set(AppSettings::ColoredHelp));
assert!(app.p
.subcommands
.is_set(AppSettings::ColoredHelp)
);
assert!(
app.subcommands
.iter()
.filter(|s| s.p
.meta
.name == "subcmd")
.filter(|s| s.name == "subcmd")
.next()
.unwrap()
.p
.is_set(AppSettings::TrailingVarArg));
.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'")])
.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"]);
assert_eq!(
m.values_of("arg").unwrap().collect::<Vec<_>>(),
&["-f", "-g,x"]
);
}
#[test]
@ -357,62 +345,75 @@ fn dont_delim_values_trailingvararg() {
let m = App::new("positional")
.setting(AppSettings::TrailingVarArg)
.setting(AppSettings::DontDelimitTrailingValues)
.arg(
Arg::from_usage("[opt]... 'some pos'"),
)
.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"]);
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'")])
.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"]);
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'"),
)
.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"]);
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)])
.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"]);
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),
)
.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"]);
assert_eq!(
m.values_of("opt").unwrap().collect::<Vec<_>>(),
&["test", "--foo", "-Wl", "-bar"]
);
}
#[test]
@ -420,8 +421,7 @@ fn leading_hyphen_short() {
let res = App::new("leadhy")
.setting(AppSettings::AllowLeadingHyphen)
.arg(Arg::with_name("some"))
.arg(Arg::with_name("other")
.short("o"))
.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();
@ -435,8 +435,7 @@ fn leading_hyphen_long() {
let res = App::new("leadhy")
.setting(AppSettings::AllowLeadingHyphen)
.arg(Arg::with_name("some"))
.arg(Arg::with_name("other")
.short("o"))
.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();
@ -449,11 +448,8 @@ fn leading_hyphen_long() {
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"))
.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();
@ -467,9 +463,7 @@ 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))
.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();
@ -482,9 +476,7 @@ 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))
.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)
@ -495,33 +487,33 @@ fn leading_double_hyphen_trailingvararg() {
let m = App::new("positional")
.setting(AppSettings::TrailingVarArg)
.setting(AppSettings::AllowLeadingHyphen)
.arg(
Arg::from_usage("[opt]... 'some pos'"),
)
.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"]);
assert_eq!(
m.values_of("opt").unwrap().collect::<Vec<_>>(),
&["--foo", "-Wl", "bar"]
);
}
#[test]
fn test_unset_setting() {
fn unset_setting() {
let m = App::new("unset_setting");
assert!(m.p.is_set(AppSettings::AllowInvalidUtf8));
assert!(m.is_set(AppSettings::AllowInvalidUtf8));
let m = m.unset_setting(AppSettings::AllowInvalidUtf8);
assert!(!m.p.is_set(AppSettings::AllowInvalidUtf8));
assert!(!m.is_set(AppSettings::AllowInvalidUtf8));
}
#[test]
fn test_unset_settings() {
fn unset_settings() {
let m = App::new("unset_settings");
assert!(&m.p.is_set(AppSettings::AllowInvalidUtf8));
assert!(&m.p.is_set(AppSettings::ColorAuto));
assert!(&m.is_set(AppSettings::AllowInvalidUtf8));
assert!(&m.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));
let m = m.unset_settings(&[AppSettings::AllowInvalidUtf8, AppSettings::ColorAuto]);
assert!(!m.is_set(AppSettings::AllowInvalidUtf8), "{:?}", m.settings);
assert!(!m.is_set(AppSettings::ColorAuto));
}
#[test]
@ -545,14 +537,17 @@ fn dont_collapse_args() {
Arg::with_name("arg2").help("some"),
Arg::with_name("arg3").help("some"),
]);
assert!(test::compare_output(app, "clap-test --help", DONT_COLLAPSE_ARGS, false));
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(
let app = App::new("clap-test").version("v1.4.8").arg(
Arg::with_name("opt")
.long("opt")
.short("o")
@ -561,21 +556,25 @@ fn require_eq() {
.value_name("FILE")
.help("some"),
);
assert!(test::compare_output(app, "clap-test --help", REQUIRE_EQUALS, false));
assert!(test::compare_output(
app,
"clap-test --help",
REQUIRE_EQUALS,
false
));
}
#[test]
fn args_negate_subcommands_one_level() {
let res = App::new("disablehelp")
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"))
)
)
.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();
@ -589,20 +588,23 @@ fn args_negate_subcommands_two_levels() {
.global_setting(AppSettings::SubcommandsNegateReqs)
.arg_from_usage("<arg1> 'some arg'")
.arg_from_usage("<arg2> 'some arg'")
.subcommand(SubCommand::with_name("sub1")
.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"))
)
.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"));
assert_eq!(
m.subcommand_matches("sub1").unwrap().value_of("arg2"),
Some("sub2")
);
}
#[test]
fn propagate_vals_down() {
let m = App::new("myprog")
@ -667,5 +669,10 @@ 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));
assert!(test::compare_output(
app,
"clap-test --help",
ALLOW_EXT_SC,
false
));
}

View file

@ -36,14 +36,14 @@ OPTIONS:
#[test]
fn single_alias_of_option() {
let a = App::new("single_alias")
.arg(Arg::with_name("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"
]);
.alias("new-opt"),
)
.get_matches_from_safe(vec!["", "--new-opt", "cool"]);
assert!(a.is_ok());
let a = a.unwrap();
assert!(a.is_present("alias"));
@ -52,37 +52,30 @@ fn single_alias_of_option() {
#[test]
fn multiple_aliases_of_option() {
let a = App::new("multiple_aliases")
.arg(Arg::with_name("aliases")
let a = App::new("multiple_aliases").arg(
Arg::with_name("aliases")
.long("aliases")
.takes_value(true)
.help("multiple aliases")
.aliases(&vec![
"alias1",
"alias2",
"alias3"
]));
let long = a.clone().get_matches_from_safe(vec![
"", "--aliases", "value"
]);
.aliases(&vec!["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"
]);
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"
]);
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"
]);
let als3 = a.clone()
.get_matches_from_safe(vec!["", "--alias3", "value"]);
assert!(als3.is_ok());
let als3 = als3.unwrap();
@ -99,9 +92,7 @@ fn multiple_aliases_of_option() {
#[test]
fn single_alias_of_flag() {
let a = App::new("test")
.arg(Arg::with_name("flag")
.long("flag")
.alias("alias"))
.arg(Arg::with_name("flag").long("flag").alias("alias"))
.get_matches_from_safe(vec!["", "--alias"]);
assert!(a.is_ok());
let a = a.unwrap();
@ -110,12 +101,13 @@ fn single_alias_of_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 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());
@ -142,19 +134,22 @@ fn multiple_aliases_of_flag() {
#[test]
fn alias_on_a_subcommand_option() {
let m = App::new("test")
.subcommand(SubCommand::with_name("some")
.arg(Arg::with_name("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")
.help("testing testing"),
),
)
.arg(
Arg::with_name("other")
.long("other")
.aliases(&vec!["o1", "o2", "o3"]))
.get_matches_from(vec![
"test", "some", "--opt", "awesome"
]);
.aliases(&vec!["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();
@ -164,37 +159,52 @@ fn alias_on_a_subcommand_option() {
#[test]
fn invisible_arg_aliases_help_output() {
let app = App::new("ct")
.author("Salim Afiune")
.subcommand(SubCommand::with_name("test")
let app = App::new("ct").author("Salim Afiune").subcommand(
SubCommand::with_name("test")
.about("Some help")
.version("1.2")
.arg(Arg::with_name("opt")
.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));
.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")
let app = App::new("ct").author("Salim Afiune").subcommand(
SubCommand::with_name("test")
.about("Some help")
.version("1.2")
.arg(Arg::with_name("opt")
.arg(
Arg::with_name("opt")
.long("opt")
.short("o")
.takes_value(true)
.alias("invisible")
.visible_alias("visible"))
.arg(Arg::with_name("flg")
.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));
.visible_aliases(&["v_flg", "flag2", "flg3"]),
),
);
assert!(test::compare_output(
app,
"ct test --help",
SC_VISIBLE_ALIAS_HELP,
false
));
}

View file

@ -7,8 +7,14 @@ 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 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)

View file

@ -1,7 +1,7 @@
extern crate regex;
extern crate clap;
extern crate regex;
use clap::{App, Arg, SubCommand, Shell};
use clap::{App, Arg, Shell, SubCommand};
use regex::Regex;
static BASH: &'static str = r#"_myapp() {
@ -63,7 +63,7 @@ static BASH: &'static str = r#"_myapp() {
return 0
;;
myapp__test)
opts=" -h -V --help --version --case "
opts=" -h -V --case --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
@ -189,7 +189,8 @@ complete -c myapp -n "__fish_using_command myapp help" -s h -l help -d 'Prints h
complete -c myapp -n "__fish_using_command myapp help" -s V -l version -d 'Prints version information'
"#;
#[cfg(not(target_os="windows"))]
#[cfg_attr(not(target_os = "windows"), allow(dead_code))]
#[cfg(not(target_os = "windows"))]
static POWERSHELL: &'static str = r#"
@('myapp', './myapp') | %{
Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
@ -240,7 +241,8 @@ static POWERSHELL: &'static str = r#"
}
"#;
#[cfg(target_os="windows")]
#[cfg_attr(target_os = "windows", allow(dead_code))]
#[cfg(target_os = "windows")]
static POWERSHELL: &'static str = r#"
@('myapp', './myapp', 'myapp.exe', '.\myapp', '.\myapp.exe', './myapp.exe') | %{
Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
@ -280,7 +282,8 @@ static POWERSHELL: &'static str = r#"
}
"#;
#[cfg(not(target_os="windows"))]
#[cfg_attr(not(target_os = "windows"), allow(dead_code))]
#[cfg(not(target_os = "windows"))]
static POWERSHELL_SPECIAL_CMDS: &'static str = r#"
@('my_app', './my_app') | %{
Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
@ -340,7 +343,8 @@ static POWERSHELL_SPECIAL_CMDS: &'static str = r#"
}
"#;
#[cfg(target_os="windows")]
#[cfg_attr(target_os = "windows", allow(dead_code))]
#[cfg(target_os = "windows")]
static POWERSHELL_SPECIAL_CMDS: &'static str = r#"
@('my_app', './my_app', 'my_app.exe', '.\my_app', '.\my_app.exe', './my_app.exe') | %{
Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
@ -609,7 +613,7 @@ static BASH_SPECIAL_CMDS: &'static str = r#"_my_app() {
return 0
;;
my_app__some_cmd)
opts=" -h -V --help --version --config "
opts=" -h -V --config --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
@ -628,7 +632,7 @@ static BASH_SPECIAL_CMDS: &'static str = r#"_my_app() {
return 0
;;
my_app__test)
opts=" -h -V --help --version --case "
opts=" -h -V --case --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
@ -738,45 +742,63 @@ 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")
.subcommand(
SubCommand::with_name("test").about("tests things").arg(
Arg::with_name("case")
.long("case")
.takes_value(true)
.help("the case to test")))
.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")
.subcommand(
SubCommand::with_name("some_cmd")
.about("tests other things")
.arg(Arg::with_name("config")
.arg(
Arg::with_name("config")
.long("--config")
.takes_value(true)
.help("the other case to test")))
.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")
.arg(
Arg::with_name("single-quotes")
.long("single-quotes")
.help("Can be 'always', 'auto', or 'never'"))
.arg(Arg::with_name("double-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")
.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")
.help("For more information see `echo test`"),
)
.arg(
Arg::with_name("backslash")
.long("backslash")
.help("Avoid '\\n'"))
.arg(Arg::with_name("brackets")
.help("Avoid '\\n'"),
)
.arg(
Arg::with_name("brackets")
.long("brackets")
.help("List packages [filter]"))
.arg(Arg::with_name("expansions")
.help("List packages [filter]"),
)
.arg(
Arg::with_name("expansions")
.long("expansions")
.help("Execute the shell command with $SHELL"))
.help("Execute the shell command with $SHELL"),
)
}
#[test]

View file

@ -3,7 +3,7 @@ extern crate regex;
include!("../clap-test.rs");
use clap::{App, Arg, ErrorKind, ArgGroup};
use clap::{App, Arg, ArgGroup, ErrorKind};
static CONFLICT_ERR: &'static str = "error: The argument '-F' cannot be used with '--flag'
@ -22,8 +22,7 @@ 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("-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());
@ -34,8 +33,7 @@ fn flag_conflict() {
#[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("-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());
@ -46,12 +44,13 @@ fn flag_conflict_2() {
#[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")
.arg(Arg::from_usage("-f, --flag 'some flag'").conflicts_with("gr"))
.group(
ArgGroup::with_name("gr")
.required(true)
.arg("some")
.arg("other"))
.arg("other"),
)
.arg(Arg::from_usage("--some 'some arg'"))
.arg(Arg::from_usage("--other 'other arg'"))
.get_matches_from_safe(vec!["myprog", "--other", "-f"]);
@ -63,12 +62,13 @@ fn group_conflict() {
#[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")
.arg(Arg::from_usage("-f, --flag 'some flag'").conflicts_with("gr"))
.group(
ArgGroup::with_name("gr")
.required(true)
.arg("some")
.arg("other"))
.arg("other"),
)
.arg(Arg::from_usage("--some 'some arg'"))
.arg(Arg::from_usage("--other 'other arg'"))
.get_matches_from_safe(vec!["myprog", "-f", "--some"]);
@ -79,21 +79,29 @@ fn group_conflict_2() {
#[test]
fn conflict_output() {
test::compare_output(test::complex_app(), "clap-test val1 --flag --long-option-2 val2 -F", CONFLICT_ERR, true);
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::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"))
.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();

View file

@ -8,9 +8,7 @@ use clap::{App, Arg, ErrorKind};
#[test]
fn opts() {
let r = App::new("df")
.arg(
Arg::from_usage("-o [opt] 'some opt'").default_value("default"),
)
.arg(Arg::from_usage("-o [opt] 'some opt'").default_value("default"))
.get_matches_from_safe(vec![""]);
assert!(r.is_ok());
let m = r.unwrap();
@ -21,9 +19,7 @@ fn opts() {
#[test]
fn opt_user_override() {
let r = App::new("df")
.arg(
Arg::from_usage("--opt [FILE] 'some arg'").default_value("default"),
)
.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();
@ -61,9 +57,7 @@ fn osstr_opts() {
let expected = OsStr::new("default");
let r = App::new("df")
.arg(
Arg::from_usage("-o [opt] 'some opt'").default_value_os(expected),
)
.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();
@ -77,9 +71,7 @@ fn osstr_opt_user_override() {
let default = OsStr::new("default");
let r = App::new("df")
.arg(
Arg::from_usage("--opt [FILE] 'some arg'").default_value_os(default),
)
.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();
@ -93,9 +85,7 @@ fn osstr_positionals() {
let expected = OsStr::new("default");
let r = App::new("df")
.arg(
Arg::from_usage("[arg] 'some opt'").default_value_os(expected),
)
.arg(Arg::from_usage("[arg] 'some opt'").default_value_os(expected))
.get_matches_from_safe(vec![""]);
assert!(r.is_ok());
let m = r.unwrap();
@ -109,9 +99,7 @@ fn osstr_positional_user_override() {
let default = OsStr::new("default");
let r = App::new("df")
.arg(
Arg::from_usage("[arg] 'some arg'").default_value_os(default),
)
.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();
@ -125,11 +113,7 @@ fn osstr_positional_user_override() {
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",
))
.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();
@ -141,11 +125,7 @@ fn default_if_arg_present_no_default() {
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",
))
.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();
@ -223,11 +203,7 @@ fn default_if_arg_present_no_arg_with_default_user_override() {
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",
))
.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();
@ -239,11 +215,7 @@ fn default_if_arg_present_with_value_no_default() {
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",
))
.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();
@ -255,11 +227,7 @@ fn default_if_arg_present_with_value_no_default_fail() {
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",
))
.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();

View file

@ -5,13 +5,8 @@ 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",
]);
.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();
@ -24,13 +19,8 @@ fn opt_default_no_delim() {
#[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",
]);
.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();
@ -43,13 +33,8 @@ fn opt_eq_no_delim() {
#[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",
]);
.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();
@ -62,13 +47,8 @@ fn opt_s_eq_no_delim() {
#[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",
]);
.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();
@ -81,13 +61,8 @@ fn opt_s_default_no_delim() {
#[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",
]);
.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();
@ -100,14 +75,13 @@ fn opt_s_no_space_no_delim() {
#[test]
fn opt_s_no_space_mult_no_delim() {
let m = App::new("no_delim")
.arg(Arg::with_name("option")
.arg(
Arg::with_name("option")
.short("o")
.multiple(true)
.takes_value(true))
.get_matches_from_safe(vec![
"",
"-o", "val1,val2,val3",
]);
.takes_value(true),
)
.get_matches_from_safe(vec!["", "-o", "val1,val2,val3"]);
assert!(m.is_ok());
let m = m.unwrap();
@ -120,20 +94,22 @@ fn opt_s_no_space_mult_no_delim() {
#[test]
fn opt_eq_mult_def_delim() {
let m = App::new("no_delim")
.arg(Arg::with_name("option")
.arg(
Arg::with_name("option")
.long("opt")
.multiple(true)
.use_delimiter(true)
.takes_value(true))
.get_matches_from_safe(vec![
"",
"--opt=val1,val2,val3",
]);
.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"]);
assert_eq!(
m.values_of("option").unwrap().collect::<Vec<_>>(),
&["val1", "val2", "val3"]
);
}

View file

@ -3,7 +3,7 @@ extern crate regex;
use std::str;
use clap::{App, Arg, SubCommand, AppSettings};
use clap::{App, AppSettings, Arg, SubCommand};
include!("../clap-test.rs");
@ -119,16 +119,25 @@ OPTIONS:
#[test]
fn no_derive_order() {
let app = App::new("test")
.version("1.2")
.args(&[
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("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"),
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));
assert!(test::compare_output(
app,
"test --help",
NO_DERIVE_ORDER,
false
));
}
#[test]
@ -138,12 +147,23 @@ fn derive_order() {
.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("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"),
Arg::with_name("option_a")
.long("option_a")
.takes_value(true)
.help("second option"),
]);
assert!(test::compare_output(app, "test --help", DERIVE_ORDER, false));
assert!(test::compare_output(
app,
"test --help",
DERIVE_ORDER,
false
));
}
#[test]
@ -153,12 +173,23 @@ fn unified_help() {
.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("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"),
Arg::with_name("option_a")
.long("option_a")
.takes_value(true)
.help("second option"),
]);
assert!(test::compare_output(app, "test --help", UNIFIED_HELP, false));
assert!(test::compare_output(
app,
"test --help",
UNIFIED_HELP,
false
));
}
#[test]
@ -169,12 +200,23 @@ fn unified_help_and_derive_order() {
.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("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"),
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));
assert!(test::compare_output(
app,
"test --help",
UNIFIED_HELP_AND_DERIVE,
false
));
}
#[test]
@ -182,32 +224,54 @@ 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(&[
.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("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"),
]));
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));
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(&[
.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("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"),
]));
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));
assert!(test::compare_output(
app,
"test sub --help",
UNIFIED_SC_PROP,
false
));
}
#[test]
@ -215,16 +279,27 @@ 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(&[
.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("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"),
]));
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));
assert!(test::compare_output(
app,
"test sub --help",
UNIFIED_DERIVE_SC_PROP,
false
));
}
#[test]
@ -232,14 +307,28 @@ fn unified_help_and_derive_order_subcommand_propagate_with_explicit_display_orde
let app = App::new("test")
.global_setting(AppSettings::DeriveDisplayOrder)
.global_setting(AppSettings::UnifiedHelpMessage)
.subcommand(SubCommand::with_name("sub")
.version("1.2")
.args(&[
.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"),
]));
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));
assert!(test::compare_output(
app,
"test sub --help",
UNIFIED_DERIVE_SC_PROP_EXPLICIT_ORDER,
false
));
}

View file

@ -25,9 +25,7 @@ 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")),
)
.arg(Arg::from_usage("[arg] 'some opt'").env_os(OsStr::new("CLP_TEST_ENV")))
.get_matches_from_safe(vec![""]);
assert!(r.is_ok());
@ -78,9 +76,7 @@ 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"),
)
.arg(Arg::from_usage("--arg [FILE] 'some arg'").env("CLP_TEST_ENV"))
.get_matches_from_safe(vec!["", "--arg", "opt"]);
assert!(r.is_ok());
@ -204,7 +200,6 @@ fn possible_value() {
assert_eq!(m.value_of("arg").unwrap(), "env");
}
#[test]
fn not_possible_value() {
env::set_var("CLP_TEST_ENV", "env");
@ -228,10 +223,12 @@ fn validator() {
.arg(
Arg::from_usage("[arg] 'some opt'")
.env("CLP_TEST_ENV")
.validator(|s| if s == "env" {
.validator(|s| {
if s == "env" {
Ok(())
} else {
Err("not equal".to_string())
}
}),
)
.get_matches_from_safe(vec![""]);
@ -251,10 +248,12 @@ fn validator_invalid() {
.arg(
Arg::from_usage("[arg] 'some opt'")
.env("CLP_TEST_ENV")
.validator(|s| if s != "env" {
.validator(|s| {
if s != "env" {
Ok(())
} else {
Err("is equal".to_string())
}
}),
)
.get_matches_from_safe(vec![""]);

View file

@ -7,7 +7,7 @@ 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'")
Arg::from_usage("-c, --color 'some other flag'"),
])
.get_matches_from(vec!["", "-f", "-c"]);
assert!(m.is_present("flag"));
@ -17,37 +17,30 @@ fn flag_using_short() {
#[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",
.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();
@ -58,10 +51,9 @@ fn lots_o_flags_sep() {
#[test]
fn lots_o_flags_combined() {
let r = App::new("opts")
.arg(
Arg::from_usage("-o... 'some flag'"),
)
.get_matches_from_safe(vec!["",
.arg(Arg::from_usage("-o... 'some flag'"))
.get_matches_from_safe(vec![
"",
"-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
"-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
"-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
@ -79,7 +71,7 @@ fn flag_using_long() {
let m = App::new("flag")
.args(&[
Arg::from_usage("--flag 'some flag'"),
Arg::from_usage("--color 'some other flag'")
Arg::from_usage("--color 'some other flag'"),
])
.get_matches_from(vec!["", "--flag", "--color"]);
assert!(m.is_present("flag"));
@ -91,7 +83,7 @@ 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'")
Arg::from_usage("-c, --color 'some other flag'"),
])
.get_matches_from(vec!["", "-f", "--color"]);
assert!(m.is_present("flag"));
@ -100,7 +92,7 @@ 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'")
Arg::from_usage("-c, --color 'some other flag'"),
])
.get_matches_from(vec!["", "--flag", "-c"]);
assert!(m.is_present("flag"));
@ -113,7 +105,7 @@ fn multiple_flags_in_single() {
.args(&[
Arg::from_usage("-f, --flag 'some flag'"),
Arg::from_usage("-c, --color 'some other flag'"),
Arg::from_usage("-d, --debug 'another other flag'")
Arg::from_usage("-d, --debug 'another other flag'"),
])
.get_matches_from(vec!["", "-fcd"]);
assert!(m.is_present("flag"));
@ -124,24 +116,23 @@ fn multiple_flags_in_single() {
#[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_eq!(a.name, "flag");
assert_eq!(a.short.unwrap(), 'f');
assert_eq!(a.long.unwrap(), "flag");
assert_eq!(a.help.unwrap(), "some flag");
assert!(!a.is_set(ArgSettings::Multiple));
assert!(a.v.val_names.is_none());
assert!(a.v.num_vals.is_none());
assert!(a.val_names.is_none());
assert!(a.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_eq!(a.name, "f");
assert_eq!(a.short.unwrap(), 'f');
assert!(a.long.is_none());
assert_eq!(a.help.unwrap(), "some flag");
assert!(!a.is_set(ArgSettings::Multiple));
assert!(a.v.val_names.is_none());
assert!(a.v.num_vals.is_none());
assert!(a.val_names.is_none());
assert!(a.num_vals.is_none());
}

View file

@ -8,30 +8,29 @@ mod tests {
fn get_app() -> App<'static, 'static> {
App::new("myprog")
.arg(Arg::with_name("GLOBAL_ARG")
.arg(
Arg::with_name("GLOBAL_ARG")
.long("global-arg")
.help(
"Specifies something needed by the subcommands",
)
.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",
.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")))
.global(true),
)
.subcommand(SubCommand::with_name("outer").subcommand(SubCommand::with_name("inner")))
}
#[test]
fn issue_1076() {
let mut app = get_app();
app.get_matches_from_safe_borrow(vec!["myprog"]);
app.get_matches_from_safe_borrow(vec!["myprog"]);
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"]);
let _ = app.get_matches_from_safe_borrow(vec!["myprog"]);
}
}

View file

@ -13,14 +13,16 @@ USAGE:
For more information try --help";
static REQ_GROUP_CONFLICT_USAGE: &'static str = "error: The argument '<base>' cannot be used with '--delete'
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'
static REQ_GROUP_CONFLICT_REV: &'static str =
"error: The argument '--delete' cannot be used with 'base'
USAGE:
clap-test <base|--delete>
@ -30,11 +32,15 @@ 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_from_usage(
"-f, --flag 'some flag'
-c, --color 'some other flag'",
)
.group(
ArgGroup::with_name("req")
.args(&["flag", "color"])
.required(true))
.required(true),
)
.get_matches_from_safe(vec![""]);
assert!(result.is_err());
let err = result.err().unwrap();
@ -45,21 +51,26 @@ fn required_group_missing_arg() {
#[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_from_usage(
"-f, --flag 'some flag'
-c, --color 'some other flag'",
)
.group(
ArgGroup::with_name("req")
.args(&["flg", "color"])
.required(true))
.required(true),
)
.get_matches_from_safe(vec![""]);
}
#[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"]))
.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());
@ -71,10 +82,11 @@ fn group_single_value() {
#[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"]))
.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());
@ -86,10 +98,11 @@ fn group_single_flag() {
#[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"]))
.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());
@ -101,11 +114,15 @@ fn group_empty() {
#[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")
.args_from_usage(
"-f, --flag 'some flag'
-c, --color 'some option'",
)
.group(
ArgGroup::with_name("grp")
.required(true)
.args(&["flag", "color"]))
.args(&["flag", "color"]),
)
.get_matches_from_safe(vec![""]);
assert!(result.is_err());
let err = result.err().unwrap();
@ -115,24 +132,27 @@ fn group_reqired_flags_empty() {
#[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"]))
.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"]);
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))
.group(ArgGroup::with_name("vers").required(true))
.get_matches_from_safe(vec!["empty_prog"]);
assert!(r.is_err());
let err = r.err().unwrap();
@ -142,36 +162,59 @@ fn empty_group() {
#[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_from_usage(
"[base] 'Base commit'
-d, --delete 'Remove the base commit information'",
)
.group(
ArgGroup::with_name("base_or_delete")
.args(&["base", "delete"])
.required(true));
.required(true),
);
assert!(test::compare_output(app, "clap-test", REQ_GROUP_USAGE, 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")
.arg(Arg::from_usage(
"-d, --delete 'Remove the base commit information'",
))
.group(
ArgGroup::with_name("base_or_delete")
.args(&["base", "delete"])
.required(true));
.required(true),
);
assert!(test::compare_output2(app, "clap-test --delete base", REQ_GROUP_CONFLICT_REV, REQ_GROUP_CONFLICT_USAGE, 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_from_usage(
"-f, --flag 'some flag'
-c, --color 'some other flag'",
)
.group(
ArgGroup::with_name("req")
.args(&["flag", "color"])
.required(true)
.multiple(true))
.multiple(true),
)
.get_matches_from_safe(vec!["group", "-f", "-c"]);
assert!(result.is_ok());
let m = result.unwrap();
@ -182,10 +225,11 @@ fn required_group_multiple_args() {
#[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"]))
.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();

View file

@ -4,7 +4,7 @@ extern crate regex;
include!("../clap-test.rs");
use clap::{App, AppSettings, SubCommand, ErrorKind, Arg};
use clap::{App, AppSettings, Arg, ErrorKind, SubCommand};
static REQUIRE_DELIM_HELP: &'static str = "test 1.3
Kevin K.
@ -180,7 +180,6 @@ 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
@ -526,8 +525,7 @@ fn setup() -> App<'static, 'static> {
#[test]
fn help_short() {
let m = setup()
.get_matches_from_safe(vec!["myprog", "-h"]);
let m = setup().get_matches_from_safe(vec!["myprog", "-h"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
@ -535,8 +533,7 @@ fn help_short() {
#[test]
fn help_long() {
let m = setup()
.get_matches_from_safe(vec!["myprog", "--help"]);
let m = setup().get_matches_from_safe(vec!["myprog", "--help"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
@ -544,8 +541,7 @@ fn help_long() {
#[test]
fn help_no_subcommand() {
let m = setup()
.get_matches_from_safe(vec!["myprog", "help"]);
let m = setup().get_matches_from_safe(vec!["myprog", "help"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind, ErrorKind::UnknownArgument);
@ -554,9 +550,11 @@ fn help_no_subcommand() {
#[test]
fn help_subcommand() {
let m = setup()
.subcommand(SubCommand::with_name("test")
.subcommand(
SubCommand::with_name("test")
.about("tests things")
.arg_from_usage("-v --verbose 'with verbosity'"))
.arg_from_usage("-v --verbose 'with verbosity'"),
)
.get_matches_from_safe(vec!["myprog", "help"]);
assert!(m.is_err());
@ -570,7 +568,12 @@ fn req_last_arg_usage() {
(@arg FIRST: ... * "First")
(@arg SECOND: ... * +last "Second")
);
assert!(test::compare_output(app, "example --help", LAST_ARG_REQ_MULT, false));
assert!(test::compare_output(
app,
"example --help",
LAST_ARG_REQ_MULT,
false
));
}
#[test]
@ -578,38 +581,48 @@ fn args_with_last_usage() {
let app = App::new("flamegraph")
.version("0.1")
.setting(AppSettings::TrailingVarArg)
.arg(Arg::with_name("verbose")
.arg(
Arg::with_name("verbose")
.help("Prints out more stuff.")
.short("v")
.long("verbose")
.multiple(true)
.multiple(true),
)
.arg(Arg::with_name("timeout")
.arg(
Arg::with_name("timeout")
.help("Timeout in seconds.")
.short("t")
.long("timeout")
.value_name("SECONDS")
.takes_value(true)
.takes_value(true),
)
.arg(Arg::with_name("frequency")
.arg(
Arg::with_name("frequency")
.help("The sampling frequency.")
.short("f")
.long("frequency")
.value_name("HERTZ")
.takes_value(true)
.takes_value(true),
)
.arg(Arg::with_name("binary path")
.arg(
Arg::with_name("binary path")
.help("The path of the binary to be profiled. for a binary.")
.takes_value(true)
.value_name("BINFILE")
.value_name("BINFILE"),
)
.arg(Arg::with_name("pass through args")
.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)
.multiple(true),
);
assert!(test::compare_output(app, "flamegraph --help", LAST_ARG_USAGE, false));
assert!(test::compare_output(
app,
"flamegraph --help",
LAST_ARG_USAGE,
false
));
}
#[test]
@ -638,7 +651,12 @@ fn subcommand_help_rev() {
#[test]
fn complex_help_output() {
assert!(test::compare_output(test::complex_app(), "clap-test --help", HELP, false));
assert!(test::compare_output(
test::complex_app(),
"clap-test --help",
HELP,
false
));
}
#[test]
@ -648,83 +666,123 @@ fn after_and_before_help_output() {
.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));
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")
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));
.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));
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));
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));
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")
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 \
.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));
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")
.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")
.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));
.takes_value(true),
);
assert!(test::compare_output(
app,
"ctest --help",
HIDE_POS_VALS,
false
));
}
#[test]
@ -740,7 +798,12 @@ fn issue_626_panic() {
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));
assert!(test::compare_output(
app,
"ctest --help",
ISSUE_626_PANIC,
false
));
}
#[test]
@ -764,29 +827,44 @@ fn issue_626_variable_panic() {
#[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));
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}\
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));
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")
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));
.help("Some help with some wrapping{n}(Defaults to something)"),
);
assert!(test::compare_output(
app,
"ctest --help",
OLD_NEWLINE_CHARS,
false
));
}
#[test]
@ -834,25 +912,29 @@ fn issue_702_multiple_values() {
.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")
.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")
.takes_value(true),
)
.arg(
Arg::with_name("other")
.help("some other option")
.short("o")
.long("other")
.takes_value(true))
.arg(Arg::with_name("label")
.takes_value(true),
)
.arg(
Arg::with_name("label")
.help("a label")
.short("l")
.long("label")
.multiple(true)
.takes_value(true));
.takes_value(true),
);
assert!(test::compare_output(app, "myapp --help", ISSUE_702, false));
}
@ -862,7 +944,9 @@ fn long_about() {
.version("1.0")
.author("foo")
.about("bar")
.long_about("something really really long, with\nmultiple lines of text\nthat should be displayed")
.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));
}
@ -871,29 +955,33 @@ fn long_about() {
fn issue_760() {
let app = App::new("ctest")
.version("0.1")
.arg(Arg::with_name("option")
.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")
.number_of_values(1),
)
.arg(
Arg::with_name("opt")
.help("tests options")
.short("O")
.long("opt")
.takes_value(true));
.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> ...]
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");
rg [OPTIONS] --type-list",
);
assert!(test::compare_output(app, "rg --help", RIPGREP_USAGE, false));
}
@ -902,18 +990,22 @@ fn ripgrep_usage() {
fn ripgrep_usage_using_templates() {
let app = App::new("ripgrep")
.version("0.5")
.usage("
.usage(
"
rg [OPTIONS] <pattern> [<path> ...]
rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
rg [OPTIONS] --files [<path> ...]
rg [OPTIONS] --type-list")
.template("\
rg [OPTIONS] --type-list",
)
.template(
"\
{bin} {version}
USAGE:{usage}
FLAGS:
{flags}");
{flags}",
);
assert!(test::compare_output(app, "rg --help", RIPGREP_USAGE, false));
}
@ -926,15 +1018,22 @@ fn sc_negates_reqs() {
.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));
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'")
.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));
}
@ -944,22 +1043,36 @@ 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'")
.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));
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'")
.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));
assert!(test::compare_output(
app,
"prog --help",
ISSUE_1046_HIDDEN_SCS,
false
));
}
#[test]
@ -982,7 +1095,12 @@ fn customize_version_and_help() {
.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));
assert!(test::compare_output(
app,
"customize --help",
CUSTOM_VERSION_AND_HELP,
false
));
}
#[test]
@ -991,7 +1109,12 @@ fn last_arg_mult_usage() {
.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"));
.arg(
Arg::with_name("ARGS")
.multiple(true)
.last(true)
.help("some"),
);
assert!(test::compare_output(app, "last --help", LAST_ARG, false));
}
@ -1001,8 +1124,19 @@ fn last_arg_mult_usage_req() {
.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));
.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]
@ -1012,9 +1146,20 @@ fn last_arg_mult_usage_req_with_sc() {
.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"))
.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));
assert!(test::compare_output(
app,
"last --help",
LAST_ARG_REQ_SC,
false
));
}
#[test]
@ -1024,32 +1169,44 @@ fn last_arg_mult_usage_with_sc() {
.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"))
.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")
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));
.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")
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));
.default_value("default-argument"),
);
assert!(test::compare_output(
app2,
"default --help",
HIDE_DEFAULT_VAL,
false
));
}
fn issue_1112_setup() -> App<'static, 'static> {
@ -1058,14 +1215,12 @@ fn issue_1112_setup() -> App<'static, 'static> {
.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'")))
.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"]);
let m = issue_1112_setup().get_matches_from_safe(vec!["test", "--help"]);
assert!(m.is_ok());
assert!(m.unwrap().is_present("help"));
@ -1073,8 +1228,7 @@ fn issue_1112_override_help_long() {
#[test]
fn issue_1112_override_help_short() {
let m = issue_1112_setup()
.get_matches_from_safe(vec!["test", "-h"]);
let m = issue_1112_setup().get_matches_from_safe(vec!["test", "-h"]);
assert!(m.is_ok());
assert!(m.unwrap().is_present("help"));
@ -1082,20 +1236,28 @@ fn issue_1112_override_help_short() {
#[test]
fn issue_1112_override_help_subcmd_long() {
let m = issue_1112_setup()
.get_matches_from_safe(vec!["test", "foo", "--help"]);
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"));
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"]);
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"));
assert!(
m.unwrap()
.subcommand_matches("foo")
.unwrap()
.is_present("help")
);
}
#[test]
@ -1104,9 +1266,18 @@ fn issue_1052_require_delim_help() {
.author("Kevin K.")
.about("tests stuff")
.version("1.3")
.arg(Arg::from_usage("-f, --fake <some> <val> 'some help'").require_delimiter(true).value_delimiter(":"));
.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));
assert!(test::compare_output(
app,
"test --help",
REQUIRE_DELIM_HELP,
false
));
}
#[test]
@ -1116,22 +1287,31 @@ fn hide_env_vals() {
env::set_var("ENVVAR", "MYVAL");
let app = App::new("ctest")
.version("0.1")
.arg(Arg::with_name("pos")
.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")
.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));
.takes_value(true),
);
assert!(test::compare_output(
app,
"ctest --help",
HIDE_ENV_VALS,
false
));
}
#[test]
@ -1141,20 +1321,29 @@ fn show_env_vals() {
env::set_var("ENVVAR", "MYVAL");
let app = App::new("ctest")
.version("0.1")
.arg(Arg::with_name("pos")
.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")
.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));
.takes_value(true),
);
assert!(test::compare_output(
app,
"ctest --help",
SHOW_ENV_VALS,
false
));
}

View file

@ -26,9 +26,11 @@ fn hidden_args() {
.author("Kevin K.")
.about("tests stuff")
.version("1.4")
.args(&[Arg::from_usage("-f, --flag 'some flag'").hidden(true),
.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)]);
Arg::with_name("DUMMY").required(false).hidden(true),
]);
assert!(test::compare_output(app, "test --help", HIDDEN_ARGS, false));
}

View file

@ -36,7 +36,7 @@ fn basic() {
#[test]
fn quoted_app_name() {
let app = clap_app!(("app name with spaces-and-hyphens") =>
let mut app = clap_app!(("app name with spaces-and-hyphens") =>
(version: "0.1")
(about: "tests clap library")
(author: "Kevin K. <kbknapp@gmail.com>")
@ -66,10 +66,11 @@ fn quoted_app_name() {
(@arg scpositional: index(1) "tests positionals"))
);
assert_eq!(app.p.meta.name, "app name with spaces-and-hyphens");
assert_eq!(app.name, "app name with spaces-and-hyphens");
let mut help_text = vec![];
app.write_help(&mut help_text).expect("Could not write help text.");
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"));
}
@ -106,7 +107,8 @@ fn quoted_arg_long_name() {
(@arg scpositional: index(1) "tests positionals"))
);
let matches = app.get_matches_from_safe(vec!["bin_name", "value1", "value2", "--long-option-2"])
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"));
}
@ -143,7 +145,8 @@ fn quoted_arg_name() {
(@arg scpositional: index(1) "tests positionals"))
);
let matches = app.get_matches_from_safe(vec!["bin_name", "value1", "value2", "--long-option-2"])
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"));
}

View file

@ -5,15 +5,9 @@ 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("--multflag 'allowed multiple flag'").multiple(true))
.arg(Arg::from_usage("--flag 'disallowed multiple flag'"))
.get_matches_from(vec![
"",
"--multflag",
"--flag",
"--multflag"
]);
.get_matches_from(vec!["", "--multflag", "--flag", "--multflag"]);
assert!(m.is_present("multflag"));
assert_eq!(m.occurrences_of("multflag"), 2);
assert!(m.is_present("flag"));
@ -23,15 +17,9 @@ fn multiple_occurrences_of_flags_long() {
#[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("-m --multflag 'allowed multiple flag'").multiple(true))
.arg(Arg::from_usage("-f --flag 'disallowed multiple flag'"))
.get_matches_from(vec![
"",
"-m",
"-f",
"-m"
]);
.get_matches_from(vec!["", "-m", "-f", "-m"]);
assert!(m.is_present("multflag"));
assert_eq!(m.occurrences_of("multflag"), 2);
assert!(m.is_present("flag"));
@ -41,10 +29,8 @@ fn multiple_occurrences_of_flags_short() {
#[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("-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![
"",
@ -53,7 +39,7 @@ fn multiple_occurrences_of_flags_mixed() {
"-n",
"--multflag1",
"-m",
"--multflag2"
"--multflag2",
]);
assert!(m.is_present("multflag1"));
assert_eq!(m.occurrences_of("multflag1"), 3);
@ -65,10 +51,12 @@ fn multiple_occurrences_of_flags_mixed() {
#[test]
fn multiple_occurrences_of_flags_large_quantity() {
let args : Vec<&str> = vec![""].into_iter().chain(vec!["-m"; 1024].into_iter()).collect();
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))
.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);

File diff suppressed because it is too large Load diff

View file

@ -3,10 +3,11 @@ extern crate regex;
include!("../clap-test.rs");
use clap::{App, ArgMatches, Arg, ErrorKind};
use clap::{App, Arg, ArgMatches, ErrorKind};
#[cfg(feature = "suggestions")]
static DYM: &'static str = "error: Found argument '--optio' which wasn't expected, or isn't valid in this context
static DYM: &'static str =
"error: Found argument '--optio' which wasn't expected, or isn't valid in this context
\tDid you mean --option?
USAGE:
@ -17,13 +18,13 @@ For more information try --help";
#[test]
fn require_equals_fail() {
let res = App::new("prog")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.require_equals(true)
.takes_value(true)
.long("config"))
.get_matches_from_safe(vec![
"prog", "--config", "file.conf"
]);
.long("config"),
)
.get_matches_from_safe(vec!["prog", "--config", "file.conf"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
}
@ -31,15 +32,15 @@ fn require_equals_fail() {
#[test]
fn require_equals_min_values_zero() {
let res = App::new("prog")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.require_equals(true)
.takes_value(true)
.min_values(0)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("cmd"))
.get_matches_from_safe(vec![
"prog", "--config", "cmd"
]);
.get_matches_from_safe(vec!["prog", "--config", "cmd"]);
assert!(res.is_ok());
let m = res.unwrap();
assert!(m.is_present("cfg"));
@ -49,13 +50,13 @@ fn require_equals_min_values_zero() {
#[test]
fn double_hyphen_as_value() {
let res = App::new("prog")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.takes_value(true)
.allow_hyphen_values(true)
.long("config"))
.get_matches_from_safe(vec![
"prog", "--config", "--"
]);
.long("config"),
)
.get_matches_from_safe(vec!["prog", "--config", "--"]);
assert!(res.is_ok(), "{:?}", res);
assert_eq!(res.unwrap().value_of("cfg"), Some("--"));
}
@ -63,14 +64,14 @@ fn double_hyphen_as_value() {
#[test]
fn require_equals_no_empty_values_fail() {
let res = App::new("prog")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.require_equals(true)
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("some"))
.get_matches_from_safe(vec![
"prog", "--config=", "file.conf"
]);
.get_matches_from_safe(vec!["prog", "--config=", "file.conf"]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
}
@ -78,27 +79,27 @@ fn require_equals_no_empty_values_fail() {
#[test]
fn require_equals_empty_vals_pass() {
let res = App::new("prog")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.require_equals(true)
.takes_value(true)
.empty_values(true)
.long("config"))
.get_matches_from_safe(vec![
"prog", "--config="
]);
.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")
.arg(
Arg::with_name("cfg")
.require_equals(true)
.takes_value(true)
.long("config"))
.get_matches_from_safe(vec![
"prog", "--config=file.conf"
]);
.long("config"),
)
.get_matches_from_safe(vec!["prog", "--config=file.conf"]);
assert!(res.is_ok());
}
@ -116,8 +117,10 @@ fn stdin_char() {
#[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'")])
.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();
@ -131,49 +134,36 @@ fn opts_using_short() {
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"]);
.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"));
@ -183,8 +173,10 @@ fn lots_o_vals() {
#[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'")])
.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();
@ -197,8 +189,10 @@ fn opts_using_long_space() {
#[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'")])
.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();
@ -211,8 +205,10 @@ fn opts_using_long_equals() {
#[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'")])
.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();
@ -225,8 +221,10 @@ fn opts_using_mixed() {
#[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'")])
.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();
@ -350,7 +348,11 @@ fn leading_hyphen_with_flag_before() {
#[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(
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);
@ -361,12 +363,14 @@ fn leading_hyphen_with_only_pos_follows() {
}
#[test]
#[cfg(feature="suggestions")]
#[cfg(feature = "suggestions")]
fn did_you_mean() {
assert!(test::compare_output(test::complex_app(),
assert!(test::compare_output(
test::complex_app(),
"clap-test --optio=foo",
DYM,
true));
true
));
}
#[test]

View file

@ -5,8 +5,10 @@ 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'")])
.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();
@ -20,10 +22,12 @@ 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")
.arg(
clap::Arg::with_name("filter")
.index(1)
.takes_value(true)
.help("filters to apply to output"))
.help("filters to apply to output"),
)
.get_matches_from_safe(vec!["compiletest", "--exact"]);
assert!(r.is_ok(), "{:#?}", r);
let matches = r.unwrap();
@ -37,8 +41,7 @@ fn positional() {
let r = App::new("positional")
.args(&[
Arg::from_usage("-f, --flag 'some flag'"),
Arg::with_name("positional")
.index(1)
Arg::with_name("positional").index(1),
])
.get_matches_from_safe(vec!["", "-f", "test"]);
assert!(r.is_ok(), "{:#?}", r);
@ -50,8 +53,7 @@ fn positional() {
let m = App::new("positional")
.args(&[
Arg::from_usage("-f, --flag 'some flag'"),
Arg::with_name("positional")
.index(1)
Arg::with_name("positional").index(1),
])
.get_matches_from(vec!["", "test", "--flag"]);
assert!(m.is_present("positional"));
@ -62,11 +64,9 @@ fn positional() {
#[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",
.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",
@ -93,6 +93,7 @@ fn lots_o_vals() {
"some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "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();
@ -105,16 +106,17 @@ 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)
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"]);
assert_eq!(
&*m.values_of("positional").unwrap().collect::<Vec<_>>(),
&["test1", "test2", "test3"]
);
}
#[test]
@ -122,16 +124,17 @@ 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)
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"]);
assert_eq!(
&*m.values_of("positional").unwrap().collect::<Vec<_>>(),
&["test1", "test2", "test3"]
);
}
#[test]
@ -139,8 +142,7 @@ fn positional_multiple_2() {
let result = App::new("positional_multiple")
.args(&[
Arg::from_usage("-f, --flag 'some flag'"),
Arg::with_name("positional")
.index(1)
Arg::with_name("positional").index(1),
])
.get_matches_from_safe(vec!["", "-f", "test1", "test2", "test3"]);
assert!(result.is_err());
@ -155,22 +157,23 @@ fn positional_possible_values() {
Arg::from_usage("-f, --flag 'some flag'"),
Arg::with_name("positional")
.index(1)
.possible_value("test123")
.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"]);
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"))
.arg(Arg::with_name("test").index(1).help("testing testing"))
.get_matches_from(vec![""]);
}
@ -183,13 +186,17 @@ fn positional_hyphen_does_not_panic() {
#[test]
fn single_positional_usage_string() {
let m = App::new("test").arg_from_usage("[FILE] 'some file'").get_matches_from(vec!["test"]);
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"]);
let m = App::new("test")
.arg_from_usage("[FILE]... 'some file'")
.get_matches_from(vec!["test"]);
assert_eq!(m.usage(), "USAGE:\n test [FILE]...");
}

View file

@ -10,7 +10,10 @@ fn posix_compatible_flags_long() {
.get_matches_from(vec!["", "--flag", "--color"]);
assert!(m.is_present("color"));
assert!(!m.is_present("flag"));
}
#[test]
fn posix_compatible_flags_long_rev() {
let m = App::new("posix")
.arg(Arg::from_usage("--flag 'some flag'").overrides_with("color"))
.arg(Arg::from_usage("--color 'some other flag'"))
@ -27,7 +30,10 @@ fn posix_compatible_flags_short() {
.get_matches_from(vec!["", "-f", "-c"]);
assert!(m.is_present("color"));
assert!(!m.is_present("flag"));
}
#[test]
fn posix_compatible_flags_short_rev() {
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'"))
@ -41,15 +47,18 @@ 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"]);
.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"));
}
#[test]
fn posix_compatible_opts_long_rev() {
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"]);
.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");
@ -60,15 +69,18 @@ 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"]);
.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"));
}
#[test]
fn posix_compatible_opts_long_equals_rev() {
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"]);
.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");
@ -83,7 +95,10 @@ fn posix_compatible_opts_short() {
assert!(m.is_present("c"));
assert_eq!(m.value_of("c").unwrap(), "other");
assert!(!m.is_present("f"));
}
#[test]
fn posix_compatible_opts_short_rev() {
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'"))
@ -96,11 +111,9 @@ fn posix_compatible_opts_short() {
#[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("-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"))
.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"));
@ -110,11 +123,9 @@ fn conflict_overriden() {
#[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("-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"))
.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();
@ -126,11 +137,9 @@ fn conflict_overriden_2() {
#[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("-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"))
.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();
@ -140,11 +149,9 @@ fn conflict_overriden_3() {
#[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("-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"))
.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"));
@ -154,11 +161,8 @@ fn conflict_overriden_4() {
#[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"))
.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());
}
@ -166,10 +170,8 @@ fn pos_required_overridden_by_flag() {
#[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"))
.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"));
@ -178,11 +180,9 @@ fn require_overriden_2() {
#[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("-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"))
.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"));
@ -192,11 +192,9 @@ fn require_overriden_3() {
#[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("-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"))
.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();

View file

@ -4,27 +4,26 @@ extern crate regex;
#[cfg(test)]
mod tests {
include!("../clap-test.rs");
use clap::{App, Arg, SubCommand, ArgMatches};
use clap::{App, Arg, ArgMatches, SubCommand};
fn get_app() -> App<'static, 'static> {
App::new("myprog")
.arg(Arg::with_name("GLOBAL_ARG")
.arg(
Arg::with_name("GLOBAL_ARG")
.long("global-arg")
.help(
"Specifies something needed by the subcommands",
)
.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",
.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")))
.global(true),
)
.subcommand(SubCommand::with_name("outer").subcommand(SubCommand::with_name("inner")))
}
fn get_matches(app: App<'static, 'static>, argv: &'static str) -> ArgMatches<'static> {
@ -32,22 +31,31 @@ mod tests {
}
fn get_outer_matches<'a>(m: &'a ArgMatches<'static>) -> &'a ArgMatches<'static> {
m.subcommand_matches("outer").expect("could not access outer subcommand")
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")
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 {
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 {
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()
}

View file

@ -3,7 +3,7 @@ extern crate regex;
include!("../clap-test.rs");
use clap::{App, Arg, ErrorKind, ArgGroup};
use clap::{App, Arg, ArgGroup, ErrorKind};
static REQUIRE_EQUALS: &'static str = "error: The following required arguments were not provided:
--opt=<FILE>
@ -22,7 +22,8 @@ USAGE:
For more information try --help";
static COND_REQ_IN_USAGE: &'static str = "error: The following required arguments were not provided:
static COND_REQ_IN_USAGE: &'static str =
"error: The following required arguments were not provided:
--output <output>
USAGE:
@ -77,9 +78,7 @@ fn option_required_2() {
#[test]
fn positional_required() {
let result = App::new("positional_required")
.arg(Arg::with_name("flag")
.index(1)
.required(true))
.arg(Arg::with_name("flag").index(1).required(true))
.get_matches_from_safe(vec![""]);
assert!(result.is_err());
let err = result.err().unwrap();
@ -89,9 +88,7 @@ fn positional_required() {
#[test]
fn positional_required_2() {
let m = App::new("positional_required")
.arg(Arg::with_name("flag")
.index(1)
.required(true))
.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");
@ -101,10 +98,12 @@ fn positional_required_2() {
fn group_required() {
let result = App::new("group_required")
.arg(Arg::from_usage("-f, --flag 'some flag'"))
.group(ArgGroup::with_name("gr")
.group(
ArgGroup::with_name("gr")
.required(true)
.arg("some")
.arg("other"))
.arg("other"),
)
.arg(Arg::from_usage("--some 'some arg'"))
.arg(Arg::from_usage("--other 'other arg'"))
.get_matches_from_safe(vec!["", "-f"]);
@ -117,10 +116,12 @@ fn group_required() {
fn group_required_2() {
let m = App::new("group_required")
.arg(Arg::from_usage("-f, --flag 'some flag'"))
.group(ArgGroup::with_name("gr")
.group(
ArgGroup::with_name("gr")
.required(true)
.arg("some")
.arg("other"))
.arg("other"),
)
.arg(Arg::from_usage("--some 'some arg'"))
.arg(Arg::from_usage("--other 'other arg'"))
.get_matches_from(vec!["", "-f", "--some"]);
@ -133,10 +134,12 @@ fn group_required_2() {
fn group_required_3() {
let m = App::new("group_required")
.arg(Arg::from_usage("-f, --flag 'some flag'"))
.group(ArgGroup::with_name("gr")
.group(
ArgGroup::with_name("gr")
.required(true)
.arg("some")
.arg("other"))
.arg("other"),
)
.arg(Arg::from_usage("--some 'some arg'"))
.arg(Arg::from_usage("--other 'other arg'"))
.get_matches_from(vec!["", "-f", "--other"]);
@ -149,9 +152,7 @@ fn group_required_3() {
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"))
.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"]);
@ -164,9 +165,7 @@ fn arg_require_group() {
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"))
.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"]);
@ -179,9 +178,7 @@ fn arg_require_group_2() {
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"))
.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"]);
@ -195,16 +192,24 @@ fn arg_require_group_3() {
#[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'")
.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"))
.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());
}
@ -212,10 +217,12 @@ fn issue_753() {
#[test]
fn required_unless() {
let res = App::new("unlesstest")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.required_unless("dbg")
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("dbg").long("debug"))
.get_matches_from_safe(vec!["unlesstest", "--debug"]);
@ -228,10 +235,12 @@ fn required_unless() {
#[test]
fn required_unless_err() {
let res = App::new("unlesstest")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.required_unless("dbg")
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("dbg").long("debug"))
.get_matches_from_safe(vec!["unlesstest"]);
@ -244,14 +253,14 @@ fn required_unless_err() {
#[test]
fn required_unless_all() {
let res = App::new("unlessall")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.required_unless_all(&["dbg", "infile"])
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
.arg(Arg::with_name("infile").short("i").takes_value(true))
.get_matches_from_safe(vec!["unlessall", "--debug", "-i", "file"]);
assert!(res.is_ok());
@ -264,14 +273,14 @@ fn required_unless_all() {
#[test]
fn required_unless_all_err() {
let res = App::new("unlessall")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.required_unless_all(&["dbg", "infile"])
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
.arg(Arg::with_name("infile").short("i").takes_value(true))
.get_matches_from_safe(vec!["unlessall", "--debug"]);
assert!(res.is_err());
@ -283,14 +292,14 @@ fn required_unless_all_err() {
#[test]
fn required_unless_one() {
let res = App::new("unlessone")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.required_unless_one(&["dbg", "infile"])
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
.arg(Arg::with_name("infile").short("i").takes_value(true))
.get_matches_from_safe(vec!["unlessone", "--debug"]);
assert!(res.is_ok());
@ -304,14 +313,14 @@ 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")
.arg(
Arg::with_name("cfg")
.required_unless_one(&["dbg", "infile"])
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
.arg(Arg::with_name("infile").short("i").takes_value(true))
.get_matches_from_safe(vec!["unlessone", "-i", "file"]);
assert!(res.is_ok());
@ -329,8 +338,9 @@ fn required_unless_one_works_with_short() {
.arg(
Arg::with_name("x")
.short("x")
.required_unless_one(&["a", "b"])
).get_matches_from_safe(vec!["unlessone", "-a"]);
.required_unless_one(&["a", "b"]),
)
.get_matches_from_safe(vec!["unlessone", "-a"]);
assert!(res.is_ok());
}
@ -343,8 +353,9 @@ fn required_unless_one_works_with_short_err() {
.arg(
Arg::with_name("x")
.short("x")
.required_unless_one(&["a", "b"])
).get_matches_from_safe(vec!["unlessone"]);
.required_unless_one(&["a", "b"]),
)
.get_matches_from_safe(vec!["unlessone"]);
assert!(!res.is_ok());
}
@ -354,10 +365,8 @@ 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"]);
.arg(Arg::with_name("x").required_unless_one(&["a", "b"]))
.get_matches_from_safe(vec!["unlessone", "-a"]);
assert!(res.is_ok());
}
@ -370,8 +379,9 @@ fn required_unless_one_works_with_long() {
.arg(
Arg::with_name("x")
.long("x_is_the_option")
.required_unless_one(&["a", "b"])
).get_matches_from_safe(vec!["unlessone", "-a"]);
.required_unless_one(&["a", "b"]),
)
.get_matches_from_safe(vec!["unlessone", "-a"]);
assert!(res.is_ok());
}
@ -379,14 +389,14 @@ fn required_unless_one_works_with_long() {
#[test]
fn required_unless_one_1() {
let res = App::new("unlessone")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.required_unless_one(&["dbg", "infile"])
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
.arg(Arg::with_name("infile").short("i").takes_value(true))
.get_matches_from_safe(vec!["unlessone", "--debug"]);
assert!(res.is_ok());
@ -399,14 +409,14 @@ fn required_unless_one_1() {
#[test]
fn required_unless_one_err() {
let res = App::new("unlessone")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.required_unless_one(&["dbg", "infile"])
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("dbg").long("debug"))
.arg(Arg::with_name("infile")
.short("i")
.takes_value(true))
.arg(Arg::with_name("infile").short("i").takes_value(true))
.get_matches_from_safe(vec!["unlessone"]);
assert!(res.is_err());
@ -415,7 +425,12 @@ fn required_unless_one_err() {
#[test]
fn missing_required_output() {
assert!(test::compare_output(test::complex_app(), "clap-test -F", MISSING_REQ, true));
assert!(test::compare_output(
test::complex_app(),
"clap-test -F",
MISSING_REQ,
true
));
}
// Conditional external requirements
@ -423,10 +438,12 @@ fn missing_required_output() {
#[test]
fn requires_if_present_val() {
let res = App::new("unlessone")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.requires_if("my.cfg", "extra")
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("extra").long("extra"))
.get_matches_from_safe(vec!["unlessone", "--config=my.cfg"]);
@ -437,10 +454,12 @@ fn requires_if_present_val() {
#[test]
fn requires_if_present_mult() {
let res = App::new("unlessone")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.requires_ifs(&[("my.cfg", "extra"), ("other.cfg", "other")])
.takes_value(true)
.long("config"))
.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"]);
@ -452,10 +471,12 @@ fn requires_if_present_mult() {
#[test]
fn requires_if_present_mult_pass() {
let res = App::new("unlessone")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.requires_ifs(&[("my.cfg", "extra"), ("other.cfg", "other")])
.takes_value(true)
.long("config"))
.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"]);
@ -467,10 +488,12 @@ fn requires_if_present_mult_pass() {
#[test]
fn requires_if_present_val_no_present_pass() {
let res = App::new("unlessone")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.requires_if("my.cfg", "extra")
.takes_value(true)
.long("config"))
.long("config"),
)
.arg(Arg::with_name("extra").long("extra"))
.get_matches_from_safe(vec!["unlessone"]);
@ -482,13 +505,13 @@ fn requires_if_present_val_no_present_pass() {
#[test]
fn required_if_val_present_pass() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.required_if("extra", "val")
.takes_value(true)
.long("config"))
.arg(Arg::with_name("extra")
.takes_value(true)
.long("extra"))
.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());
@ -497,13 +520,13 @@ fn required_if_val_present_pass() {
#[test]
fn required_if_val_present_fail() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.required_if("extra", "val")
.takes_value(true)
.long("config"))
.arg(Arg::with_name("extra")
.takes_value(true)
.long("extra"))
.long("config"),
)
.arg(Arg::with_name("extra").takes_value(true).long("extra"))
.get_matches_from_safe(vec!["ri", "--extra", "val"]);
assert!(res.is_err());
@ -516,36 +539,44 @@ fn required_if_val_present_fail_error_output() {
.version("1.0")
.author("F0x06")
.about("Arg test")
.arg(Arg::with_name("target")
.arg(
Arg::with_name("target")
.takes_value(true)
.required(true)
.possible_values(&["file", "stdout"])
.long("target"))
.arg(Arg::with_name("input")
.long("target"),
)
.arg(
Arg::with_name("input")
.takes_value(true)
.required(true)
.long("input"))
.arg(Arg::with_name("output")
.long("input"),
)
.arg(
Arg::with_name("output")
.takes_value(true)
.required_if("target", "file")
.long("output"));
.long("output"),
);
assert!(test::compare_output(app,
assert!(test::compare_output(
app,
"test --input somepath --target file",
COND_REQ_IN_USAGE,
true));
true
));
}
#[test]
fn required_if_wrong_val() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
.arg(
Arg::with_name("cfg")
.required_if("extra", "val")
.takes_value(true)
.long("config"))
.arg(Arg::with_name("extra")
.takes_value(true)
.long("extra"))
.long("config"),
)
.arg(Arg::with_name("extra").takes_value(true).long("extra"))
.get_matches_from_safe(vec!["ri", "--extra", "other"]);
assert!(res.is_ok());
@ -554,16 +585,14 @@ fn required_if_wrong_val() {
#[test]
fn required_ifs_val_present_pass() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
.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"))
.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());
@ -573,16 +602,14 @@ fn required_ifs_val_present_pass() {
#[test]
fn required_ifs_val_present_fail() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
.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"))
.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());
@ -592,16 +619,14 @@ fn required_ifs_val_present_fail() {
#[test]
fn required_ifs_wrong_val() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
.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"))
.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());
@ -610,16 +635,14 @@ fn required_ifs_wrong_val() {
#[test]
fn required_ifs_wrong_val_mult_fail() {
let res = App::new("ri")
.arg(Arg::with_name("cfg")
.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"))
.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());
@ -628,16 +651,14 @@ fn required_ifs_wrong_val_mult_fail() {
#[test]
fn require_eq() {
let app = App::new("clap-test")
.version("v1.4.8")
.arg(
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")
.help("some"),
);
assert!(test::compare_output(app, "clap-test", REQUIRE_EQUALS, true));
}

View file

@ -3,7 +3,7 @@ extern crate regex;
include!("../clap-test.rs");
use clap::{App, Arg, SubCommand, ErrorKind};
use clap::{App, Arg, ErrorKind, SubCommand};
static VISIBLE_ALIAS_HELP: &'static str = "clap-test 2.6
@ -43,7 +43,8 @@ USAGE:
For more information try --help";
#[cfg(feature = "suggestions")]
static DYM_ARG: &'static str = "error: Found argument '--subcm' which wasn't expected, or isn't valid in this context
static DYM_ARG: &'static str =
"error: Found argument '--subcm' which wasn't expected, or isn't valid in this context
\tDid you mean to put '--subcmdarg' after the subcommand 'subcmd'?
USAGE:
@ -54,12 +55,15 @@ For more information try --help";
#[test]
fn subcommand() {
let m = App::new("test")
.subcommand(SubCommand::with_name("some")
.arg(Arg::with_name("test")
.subcommand(
SubCommand::with_name("some").arg(
Arg::with_name("test")
.short("t")
.long("test")
.takes_value(true)
.help("testing testing")))
.help("testing testing"),
),
)
.arg(Arg::with_name("other").long("other"))
.get_matches_from(vec!["myprog", "some", "--test", "testing"]);
@ -72,12 +76,15 @@ fn subcommand() {
#[test]
fn subcommand_none_given() {
let m = App::new("test")
.subcommand(SubCommand::with_name("some")
.arg(Arg::with_name("test")
.subcommand(
SubCommand::with_name("some").arg(
Arg::with_name("test")
.short("t")
.long("test")
.takes_value(true)
.help("testing testing")))
.help("testing testing"),
),
)
.arg(Arg::with_name("other").long("other"))
.get_matches_from(vec![""]);
@ -88,14 +95,14 @@ fn subcommand_none_given() {
fn subcommand_multiple() {
let m = App::new("test")
.subcommands(vec![
SubCommand::with_name("some")
.arg(Arg::with_name("test")
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"))
.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"]);
@ -111,8 +118,7 @@ fn subcommand_multiple() {
#[test]
fn single_alias() {
let m = App::new("myprog")
.subcommand(SubCommand::with_name("test")
.alias("do-stuff"))
.subcommand(SubCommand::with_name("test").alias("do-stuff"))
.get_matches_from(vec!["myprog", "do-stuff"]);
assert_eq!(m.subcommand_name(), Some("test"));
}
@ -120,34 +126,31 @@ fn single_alias() {
#[test]
fn multiple_aliases() {
let m = App::new("myprog")
.subcommand(SubCommand::with_name("test")
.aliases(&["do-stuff", "test-stuff"]))
.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")]
#[cfg(feature = "suggestions")]
fn subcmd_did_you_mean_output() {
let app = App::new("dym")
.subcommand(SubCommand::with_name("subcmd"));
let app = App::new("dym").subcommand(SubCommand::with_name("subcmd"));
assert!(test::compare_output(app, "dym subcm", DYM_SUBCMD, true));
}
#[test]
#[cfg(feature="suggestions")]
#[cfg(feature = "suggestions")]
fn subcmd_did_you_mean_output_arg() {
let app = App::new("dym")
.subcommand(SubCommand::with_name("subcmd")
.arg_from_usage("-s --subcmdarg [subcmdarg] 'tests'") );
let app = App::new("dym").subcommand(
SubCommand::with_name("subcmd").arg_from_usage("-s --subcmdarg [subcmdarg] 'tests'"),
);
assert!(test::compare_output(app, "dym --subcm foo", DYM_ARG, true));
}
#[test]
fn alias_help() {
let m = App::new("myprog")
.subcommand(SubCommand::with_name("test")
.alias("do-stuff"))
.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);
@ -155,24 +158,34 @@ fn alias_help() {
#[test]
fn visible_aliases_help_output() {
let app = App::new("clap-test")
.version("2.6")
.subcommand(SubCommand::with_name("test")
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));
.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")
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));
.alias("invisible"),
);
assert!(test::compare_output(
app,
"clap-test --help",
INVISIBLE_ALIAS_HELP,
false
));
}
#[test]

View file

@ -5,8 +5,8 @@ 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 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>
@ -52,13 +52,23 @@ SUBCOMMANDS:
#[test]
fn with_template() {
let app = app_example1().template(EXAMPLE1_TMPL_S);
assert!(test::compare_output(app, "MyApp --help", SIMPLE_TEMPLATE, false));
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));
assert!(test::compare_output(
app,
"MyApp --help",
CUSTOM_TEMPL_HELP,
false
));
}
#[test]
@ -78,7 +88,12 @@ fn template_notag() {
.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));
assert!(test::compare_output(
app,
"MyApp --help",
"test no tag test",
false
));
}
#[test]
@ -88,7 +103,12 @@ fn template_unknowntag() {
.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));
assert!(test::compare_output(
app,
"MyApp --help",
"test {unknown_tag} test",
false
));
}
#[test]
@ -98,7 +118,12 @@ fn template_author_version() {
.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));
assert!(test::compare_output(
app,
"MyApp --help",
"Kevin K. <kbknapp@gmail.com>\n1.0\nDoes awesome things\nMyApp",
false
));
}
// ----------
@ -108,10 +133,14 @@ fn app_example1<'b, 'c>() -> App<'b, 'c> {
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.args_from_usage("-c, --config=[FILE] 'Sets a custom config file'
.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")
-d... 'Turn debugging information on'",
)
.subcommand(
SubCommand::with_name("test")
.about("does testing things")
.arg_from_usage("-l, --list 'lists test values'"))
.arg_from_usage("-l, --list 'lists test values'"),
)
}

View file

@ -101,7 +101,12 @@ pub fn check_complex_output(args: &str, out: &str) {
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();
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 {
@ -120,29 +125,50 @@ pub fn check_complex_output(args: &str, out: &str) {
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();
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();
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")
_ => 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")
_ => 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();
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 {
@ -268,8 +294,11 @@ fn test_enums() {
#[test]
fn create_app() {
let _ =
App::new("test").version("1.0").author("kevin").about("does awesome things").get_matches_from(vec![""]);
let _ = App::new("test")
.version("1.0")
.author("kevin")
.about("does awesome things")
.get_matches_from(vec![""]);
}
#[test]
@ -277,13 +306,15 @@ fn add_multiple_arg() {
let _ = App::new("test")
.args(&mut [
Arg::with_name("test").short("s"),
Arg::with_name("test2").short("l")])
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
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
@ -296,13 +327,12 @@ 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);
}
fn long_opt_x2_pos() { check_complex_output("clap-test value --option some --option other", O2P); }
#[test]
fn long_opt_eq_x2_pos() {
@ -310,29 +340,19 @@ fn long_opt_eq_x2_pos() {
}
#[test]
fn short_opt_x2_pos() {
check_complex_output("clap-test value -o some -o other", O2P);
}
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);
}
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);
}
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);
}
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);
}
fn long_flag_long_opt_pos() { check_complex_output("clap-test value --flag --option some", FOP); }
#[test]
fn long_flag_long_opt_eq_pos() {

View file

@ -5,18 +5,32 @@ 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")]);
let _ = App::new("some")
.args(&[
Arg::with_name("arg").short("a"),
Arg::with_name("arg").short("b"),
])
.get_matches_safe();
}
#[test]
#[should_panic]
fn unique_arg_shorts() {
App::new("some").args(&[Arg::with_name("arg1").short("a"), Arg::with_name("arg2").short("a")]);
let _ = App::new("some")
.args(&[
Arg::with_name("arg1").short("a"),
Arg::with_name("arg2").short("a"),
])
.get_matches_safe();
}
#[test]
#[should_panic]
fn unique_arg_longs() {
App::new("some")
.args(&[Arg::with_name("arg1").long("long"), Arg::with_name("arg2").long("long")]);
let _ = App::new("some")
.args(&[
Arg::with_name("arg1").long("long"),
Arg::with_name("arg2").long("long"),
])
.get_matches_safe();
}

View file

@ -4,15 +4,14 @@ extern crate clap;
use std::ffi::OsString;
use std::os::unix::ffi::OsStringExt;
use clap::{App, Arg, AppSettings, ErrorKind};
use clap::{App, AppSettings, Arg, 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])]);
.get_matches_from_safe(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidUtf8);
}
@ -22,9 +21,11 @@ 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(""),
.get_matches_from_safe(vec![
OsString::from(""),
OsString::from("-a"),
OsString::from_vec(vec![0xe9])]);
OsString::from_vec(vec![0xe9]),
]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidUtf8);
}
@ -34,8 +35,10 @@ 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])]);
.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);
}
@ -45,8 +48,10 @@ 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])]);
.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);
}
@ -56,9 +61,11 @@ 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(""),
.get_matches_from_safe(vec![
OsString::from(""),
OsString::from("--arg"),
OsString::from_vec(vec![0xe9])]);
OsString::from_vec(vec![0xe9]),
]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind, ErrorKind::InvalidUtf8);
}
@ -68,8 +75,10 @@ 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])]);
.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);
}
@ -78,8 +87,7 @@ fn invalid_utf8_strict_option_long_equals() {
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])]);
.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"));
@ -90,9 +98,11 @@ fn invalid_utf8_lossy_positional() {
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(""),
.get_matches_from_safe(vec![
OsString::from(""),
OsString::from("-a"),
OsString::from_vec(vec![0xe9])]);
OsString::from_vec(vec![0xe9]),
]);
assert!(r.is_ok());
let m = r.unwrap();
assert!(m.is_present("arg"));
@ -103,8 +113,10 @@ fn invalid_utf8_lossy_option_short_space() {
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])]);
.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"));
@ -115,8 +127,10 @@ fn invalid_utf8_lossy_option_short_equals() {
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])]);
.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"));
@ -127,9 +141,11 @@ fn invalid_utf8_lossy_option_short_no_space() {
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(""),
.get_matches_from_safe(vec![
OsString::from(""),
OsString::from("--arg"),
OsString::from_vec(vec![0xe9])]);
OsString::from_vec(vec![0xe9]),
]);
assert!(r.is_ok());
let m = r.unwrap();
assert!(m.is_present("arg"));
@ -140,8 +156,10 @@ fn invalid_utf8_lossy_option_long_space() {
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])]);
.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"));
@ -152,72 +170,99 @@ fn invalid_utf8_lossy_option_long_equals() {
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])]);
.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]));
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(""),
.get_matches_from_safe(vec![
OsString::from(""),
OsString::from("-a"),
OsString::from_vec(vec![0xe9])]);
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]));
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])]);
.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]));
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])]);
.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]));
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(""),
.get_matches_from_safe(vec![
OsString::from(""),
OsString::from("--arg"),
OsString::from_vec(vec![0xe9])]);
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]));
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])]);
.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]));
assert_eq!(
&*m.value_of_os("arg").unwrap(),
&*OsString::from_vec(vec![0xe9])
);
}

View file

@ -1,4 +1,4 @@
#![cfg(feature="yaml")]
#![cfg(feature = "yaml")]
#[macro_use]
extern crate clap;
@ -21,8 +21,9 @@ fn help_message() {
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"));
assert!(
help_string.contains("-h, --help prints help with a nonstandard description\n")
);
}
#[test]
@ -35,6 +36,5 @@ fn author() {
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>"));
assert!(help_string.contains("Kevin K. <kbknapp@gmail.com>"));
}