mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 14:54:15 +00:00
parent
92fcec8fb7
commit
d6c3ed54d2
6 changed files with 203 additions and 134 deletions
|
@ -27,18 +27,18 @@ OPTIONS:
|
|||
--multvalsmo <one> <two> Tests mutliple values, not mult occs
|
||||
-o, --option <opt>... tests options
|
||||
--long-option-2 <option2> tests long options with exclusions
|
||||
-O, --Option <option3> tests options with specific value sets [values: fast slow]
|
||||
-O, --Option <option3> tests options with specific value sets [values: fast, slow]
|
||||
|
||||
POSITIONAL ARGUMENTS:
|
||||
positional tests positionals
|
||||
positional2 tests positionals with exclusions
|
||||
positional3... tests positionals with specific values [values: emacs vi]
|
||||
positional3... tests positionals with specific values [values: emacs, vi]
|
||||
|
||||
SUBCOMMANDS:
|
||||
help Prints this message
|
||||
subcmd tests subcommands'''
|
||||
|
||||
_sc_dym_usage = '''The subcommand 'subcm' isn't valid
|
||||
_sc_dym_usage = '''error: The subcommand 'subcm' isn't valid
|
||||
Did you mean 'subcmd' ?
|
||||
|
||||
If you received this message in error, try re-running with 'claptests -- subcm'
|
||||
|
@ -48,7 +48,7 @@ USAGE:
|
|||
|
||||
For more information try --help'''
|
||||
|
||||
_arg_dym_usage = '''The argument --optio isn't valid
|
||||
_arg_dym_usage = '''error: The argument '--optio' isn't valid
|
||||
Did you mean --option ?
|
||||
|
||||
USAGE:
|
||||
|
@ -56,8 +56,9 @@ USAGE:
|
|||
|
||||
For more information try --help'''
|
||||
|
||||
_pv_dym_usage = '''"slo" isn't a valid value for '--Option <option3>'
|
||||
_pv_dym_usage = '''error: 'slo' isn't a valid value for '--Option <option3>'
|
||||
[valid values: fast slow]
|
||||
|
||||
Did you mean 'slow' ?
|
||||
|
||||
USAGE:
|
||||
|
@ -65,21 +66,21 @@ USAGE:
|
|||
|
||||
For more information try --help'''
|
||||
|
||||
_excluded = '''The argument '--flag' cannot be used with '-F'
|
||||
_excluded = '''error: The argument '--flag' cannot be used with '-F'
|
||||
|
||||
USAGE:
|
||||
\tclaptests [positional2] -F --long-option-2 <option2>
|
||||
|
||||
For more information try --help'''
|
||||
|
||||
_excluded_l = '''The argument -f cannot be used '-F'
|
||||
_excluded_l = '''error: The argument '-f' cannot be used '-F'
|
||||
|
||||
USAGE:
|
||||
claptests [positional2] -F --long-option-2 <option2>
|
||||
|
||||
For more information try --help'''
|
||||
|
||||
_required = '''The following required arguments were not supplied:
|
||||
_required = '''error: The following required arguments were not supplied:
|
||||
\t'[positional2]'
|
||||
\t'--long-option-2 <option2>'
|
||||
|
||||
|
@ -182,7 +183,7 @@ scoption present with value: some
|
|||
An scoption: some
|
||||
scpositional present with value: value'''
|
||||
|
||||
_min_vals_few = '''The argument '--minvals2 <minvals>...' requires at least 2 values, but 1 was provided
|
||||
_min_vals_few = '''error: The argument '--minvals2 <minvals>...' requires at least 2 values, but 1 was provided
|
||||
|
||||
USAGE:
|
||||
\tclaptests --minvals2 <minvals>...
|
||||
|
@ -213,21 +214,21 @@ option NOT present
|
|||
positional present with value: too
|
||||
subcmd NOT present'''
|
||||
|
||||
_mult_vals_more = '''The argument --multvals was supplied more than once, but does not support multiple values
|
||||
_mult_vals_more = '''error: The argument '--multvals' was supplied more than once, but does not support multiple values
|
||||
|
||||
USAGE:
|
||||
\tclaptests --multvals <one> <two>
|
||||
|
||||
For more information try --help'''
|
||||
|
||||
_mult_vals_few = '''The argument '--multvals <one> <two>' requires a value but none was supplied
|
||||
_mult_vals_few = '''error: The argument '--multvals <one> <two>' requires a value but none was supplied
|
||||
|
||||
USAGE:
|
||||
\tclaptests --multvals <one> <two>
|
||||
|
||||
For more information try --help'''
|
||||
|
||||
_mult_vals_2m1 = '''The argument '--multvalsmo <one> <two>' requires 2 values, but 1 was provided
|
||||
_mult_vals_2m1 = '''error: The argument '--multvalsmo <one> <two>' requires 2 values, but 1 was provided
|
||||
|
||||
USAGE:
|
||||
claptests --multvalsmo <one> <two>
|
||||
|
|
208
src/app.rs
208
src/app.rs
|
@ -11,11 +11,10 @@ use std::process;
|
|||
use args::{ ArgMatches, Arg, SubCommand, MatchedArg};
|
||||
use args::{ FlagBuilder, OptBuilder, PosBuilder};
|
||||
use args::ArgGroup;
|
||||
use fmt::Format;
|
||||
|
||||
#[cfg(feature = "suggestions")]
|
||||
use strsim;
|
||||
#[cfg(feature = "color")]
|
||||
use ansi_term::Colour::Red;
|
||||
|
||||
/// Produces a string from a given list of possible values which is similar to
|
||||
/// the passed in value `v` with a certain confidence.
|
||||
|
@ -1037,7 +1036,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
fn print_usage(&self, more_info: bool, matches: Option<Vec<&str>>) {
|
||||
print!("{}",self.create_usage(matches));
|
||||
if more_info {
|
||||
println!("\n\nFor more information try --help");
|
||||
println!("\n\nFor more information try {}", Format::Good("--help"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1243,16 +1242,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
|
||||
// Reports and error to the users screen along with an optional usage statement and quits
|
||||
#[cfg(not(feature = "color"))]
|
||||
fn report_error(&self, msg: String, usage: bool, quit: bool, matches: Option<Vec<&str>>) {
|
||||
println!("{}\n", msg);
|
||||
if usage { self.print_usage(true, matches); }
|
||||
if quit { self.exit(1); }
|
||||
}
|
||||
|
||||
#[cfg(feature = "color")]
|
||||
fn report_error(&self, msg: String, usage: bool, quit: bool, matches: Option<Vec<&str>>) {
|
||||
println!("{}\n", Red.paint(&msg[..]));
|
||||
println!("{} {}\n", Format::Error("error:"), msg);
|
||||
if usage { self.print_usage(true, matches); }
|
||||
if quit { self.exit(1); }
|
||||
}
|
||||
|
@ -1330,10 +1321,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
Some(candidate) => {
|
||||
let mut suffix = "\n\tDid you mean ".to_string();
|
||||
match style {
|
||||
DidYouMeanMessageStyle::LongFlag => suffix.push_str("--"),
|
||||
DidYouMeanMessageStyle::LongFlag => suffix.push_str(&Format::Good("--").to_string()[..]),
|
||||
DidYouMeanMessageStyle::EnumValue => suffix.push('\''),
|
||||
}
|
||||
suffix.push_str(candidate);
|
||||
suffix.push_str(&Format::Good(candidate).to_string()[..]);
|
||||
if let DidYouMeanMessageStyle::EnumValue = style {
|
||||
suffix.push('\'');
|
||||
}
|
||||
|
@ -1349,10 +1340,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
let suffix = App::did_you_mean_suffix(arg, p_vals.iter(),
|
||||
DidYouMeanMessageStyle::EnumValue);
|
||||
|
||||
self.report_error(format!("\"{}\" isn't a valid value for '{}'{}{}",
|
||||
arg,
|
||||
opt,
|
||||
format!("\n\t[valid values:{}]",
|
||||
self.report_error(format!("'{}' isn't a valid value for '{}'{}{}",
|
||||
Format::Warning(arg),
|
||||
Format::Warning(opt),
|
||||
format!("\n\t[valid values:{}]\n",
|
||||
p_vals.iter()
|
||||
.fold(String::new(), |acc, name| {
|
||||
acc + &format!(" {}",name)[..]
|
||||
|
@ -1395,9 +1386,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if num == vals.len() as u8 && !opt.multiple {
|
||||
self.report_error(format!("The argument '{}' was found, \
|
||||
but '{}' only expects {} values",
|
||||
arg,
|
||||
opt,
|
||||
vals.len()),
|
||||
Format::Warning(&arg),
|
||||
Format::Warning(opt.to_string()),
|
||||
Format::Good(vals.len().to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(
|
||||
|
@ -1413,7 +1404,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
matches.args.contains_key(opt.name) &&
|
||||
arg.is_empty() {
|
||||
self.report_error(format!("The argument '{}' does not allow empty \
|
||||
values, but one was found.", opt),
|
||||
values, but one was found.", Format::Warning(opt.to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys()
|
||||
|
@ -1455,7 +1446,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if let Some(ref o) = self.opts.get(name) {
|
||||
if !o.multiple {
|
||||
self.report_error(
|
||||
format!("The argument '{}' requires a value but none was supplied", o),
|
||||
format!("The argument '{}' requires a value but none was supplied",
|
||||
Format::Warning(o.to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect() ) );
|
||||
|
@ -1490,10 +1482,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
self.report_error(
|
||||
format!("The subcommand '{}' isn't valid\n\tDid you mean '{}' ?\n\n\
|
||||
If you received this message in error, try \
|
||||
re-running with '{} -- {}'",
|
||||
arg,
|
||||
candidate_subcommand,
|
||||
re-running with '{} {} {}'",
|
||||
Format::Warning(&arg),
|
||||
Format::Good(candidate_subcommand),
|
||||
self.bin_name.clone().unwrap_or(self.name.clone()),
|
||||
Format::Good("--"),
|
||||
arg),
|
||||
true,
|
||||
true,
|
||||
|
@ -1503,8 +1496,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
|
||||
if self.positionals_idx.is_empty() {
|
||||
self.report_error(
|
||||
format!("Found argument \"{}\", but {} wasn't expecting any",
|
||||
arg,
|
||||
format!("Found argument '{}', but {} wasn't expecting any",
|
||||
Format::Warning(&arg),
|
||||
self.bin_name.clone().unwrap_or(self.name.clone())),
|
||||
true,
|
||||
true,
|
||||
|
@ -1517,9 +1510,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if self.blacklist.contains(p.name) {
|
||||
matches.args.remove(p.name);
|
||||
self.report_error(format!("The argument '{}' cannot be used with {}",
|
||||
p,
|
||||
Format::Warning(p.to_string()),
|
||||
match self.blacklisted_from(p.name, &matches) {
|
||||
Some(name) => format!("'{}'", name),
|
||||
Some(name) => format!("'{}'", Format::Warning(name)),
|
||||
None => "one or more of the other specified \
|
||||
arguments".to_owned()
|
||||
}),
|
||||
|
@ -1544,7 +1537,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if let Some(ref vals) = ma.values {
|
||||
if vals.len() as u8 == num {
|
||||
self.report_error(format!("The argument '{}' was found, \
|
||||
but '{}' wasn't expecting any more values", arg, p),
|
||||
but '{}' wasn't expecting any more values",
|
||||
Format::Warning(&arg),
|
||||
Format::Warning(p.to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys()
|
||||
|
@ -1555,7 +1550,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
if !p.empty_vals && matches.args.contains_key(p.name) && arg.is_empty() {
|
||||
self.report_error(format!("The argument '{}' does not allow empty \
|
||||
values, but one was found.", p),
|
||||
values, but one was found.", Format::Warning(p.to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys()
|
||||
|
@ -1579,7 +1574,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
let mut bm = BTreeMap::new();
|
||||
if !p.empty_vals && arg.is_empty() {
|
||||
self.report_error(format!("The argument '{}' does not allow empty \
|
||||
values, but one was found.", p),
|
||||
values, but one was found.", Format::Warning(p.to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys()
|
||||
|
@ -1614,7 +1609,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
|
||||
} else {
|
||||
self.report_error(format!("The argument '{}' was found, but '{}' wasn't \
|
||||
expecting any", arg,
|
||||
expecting any", Format::Warning(&arg),
|
||||
self.bin_name.clone().unwrap_or(self.name.clone())),
|
||||
true,
|
||||
true,
|
||||
|
@ -1632,8 +1627,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
};
|
||||
if should_err {
|
||||
self.report_error(
|
||||
format!("The argument '{}' requires a value but none was \
|
||||
supplied", o),
|
||||
format!("The argument '{}' requires a value but there wasn't any \
|
||||
supplied", Format::Warning(o.to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect() ) );
|
||||
|
@ -1641,7 +1636,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
else if !o.multiple {
|
||||
self.report_error(
|
||||
format!("The argument '{}' requires a value but none was supplied", o),
|
||||
format!("The argument '{}' requires a value but none was supplied",
|
||||
Format::Warning(o.to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect() ) );
|
||||
|
@ -1653,7 +1649,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
.map(|s| *s)
|
||||
.collect::<Vec<_>>())
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| acc + &format!("\n\t'{}'",s)[..])),
|
||||
.fold(String::new(), |acc, s| acc + &format!("\n\t'{}'",
|
||||
Format::Error(s.to_string()))[..])),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -1661,8 +1658,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
} else {
|
||||
self.report_error(
|
||||
format!("The argument '{}' requires a value but none was supplied",
|
||||
format!("{}", self.positionals_idx.get(
|
||||
self.positionals_name.get(a).unwrap()).unwrap())),
|
||||
Format::Warning(format!("{}", self.positionals_idx.get(
|
||||
self.positionals_name.get(a).unwrap()).unwrap()))),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -1715,13 +1712,14 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
} else if self.no_sc_error {
|
||||
let bn = self.bin_name.clone().unwrap_or(self.name.clone());
|
||||
self.report_error(format!("'{}' requires a subcommand but none was provided", &bn[..]),
|
||||
self.report_error(format!("'{}' requires a subcommand but none was provided",
|
||||
Format::Warning(&bn[..])),
|
||||
if self.usage_str.is_some() { true } else { false },
|
||||
if self.usage_str.is_some() { true } else { false },
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
||||
println!("USAGE:\n\t{} [SUBCOMMAND]\n\nFor more information re-run with '--help' or \
|
||||
'help'", &bn[..]);
|
||||
println!("USAGE:\n\t{} [SUBCOMMAND]\n\nFor more information re-run with {} or \
|
||||
'{}'", &bn[..], Format::Good("--help"), Format::Good("help"));
|
||||
self.exit(1);
|
||||
}
|
||||
if !self.required.is_empty() && !self.subcmds_neg_reqs {
|
||||
|
@ -1732,7 +1730,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
.map(|s| *s)
|
||||
.collect::<Vec<_>>())
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| acc + &format!("\n\t'{}'",s)[..])),
|
||||
.fold(String::new(), |acc, s| acc + &format!("\n\t'{}'",
|
||||
Format::Error(s))[..])),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -1837,8 +1836,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
arg = arg_vec[0];
|
||||
// prevents "--config= value" typo
|
||||
if arg_vec[1].len() == 0 {
|
||||
self.report_error(format!("The argument --{} requires a value, but none was \
|
||||
supplied", arg),
|
||||
self.report_error(format!("The argument '{}' requires a value, but none was \
|
||||
supplied", Format::Warning(format!("--{}", arg))),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -1852,15 +1851,16 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
// Ensure this option isn't on the master mutually excludes list
|
||||
if self.blacklist.contains(v.name) {
|
||||
matches.args.remove(v.name);
|
||||
self.report_error(format!("The argument --{} cannot be used with one or more of \
|
||||
the other specified arguments", arg),
|
||||
self.report_error(format!("The argument '{}' cannot be used with one or more of \
|
||||
the other specified arguments", Format::Warning(format!("--{}", arg))),
|
||||
true, true, Some(matches.args.keys().map(|k| *k).collect()));
|
||||
}
|
||||
|
||||
if matches.args.contains_key(v.name) {
|
||||
if !v.multiple {
|
||||
self.report_error(format!("The argument --{} was supplied more than once, but \
|
||||
does not support multiple values", arg),
|
||||
self.report_error(format!("The argument '{}' was supplied more than once, but \
|
||||
does not support multiple values",
|
||||
Format::Warning(format!("--{}", arg))),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -1877,7 +1877,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if arg_val.is_some() {
|
||||
if !v.empty_vals && arg.is_empty() && matches.args.contains_key(v.name) {
|
||||
self.report_error(format!("The argument '{}' does not allow empty \
|
||||
values, but one was found.", v),
|
||||
values, but one was found.", Format::Warning(v.to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys()
|
||||
|
@ -1894,7 +1894,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
} else {
|
||||
if !v.empty_vals && arg_val.is_some() && arg_val.clone().unwrap().is_empty() {
|
||||
self.report_error(format!("The argument '{}' does not allow empty \
|
||||
values, but one was found.", v),
|
||||
values, but one was found.", Format::Warning(v.to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys()
|
||||
|
@ -1946,11 +1946,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if self.blacklist.contains(v.name) {
|
||||
matches.args.remove(v.name);
|
||||
self.report_error(format!("The argument '{}' cannot be used with {}",
|
||||
v,
|
||||
match self.blacklisted_from(v.name, matches) {
|
||||
Some(name) => format!("'{}'", name),
|
||||
None => "one or more of the specified arguments".to_owned()
|
||||
}),
|
||||
Format::Warning(v.to_string()),
|
||||
match self.blacklisted_from(v.name, matches) {
|
||||
Some(name) => format!("'{}'", Format::Warning(name)),
|
||||
None => "one or more of the specified arguments".to_owned()
|
||||
}),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -1959,7 +1959,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
// Make sure this isn't one being added multiple times if it doesn't suppor it
|
||||
if matches.args.contains_key(v.name) && !v.multiple {
|
||||
self.report_error(format!("The argument '{}' was supplied more than once, but does \
|
||||
not support multiple values", v),
|
||||
not support multiple values", Format::Warning(v.to_string())),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -2038,7 +2038,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
}
|
||||
|
||||
self.report_error(format!("The argument --{} isn't valid{}", arg, suffix.0),
|
||||
self.report_error(format!("The argument '{}' isn't valid{}",
|
||||
Format::Warning(format!("--{}", arg)),
|
||||
suffix.0),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -2054,7 +2056,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
for c in arg.chars() {
|
||||
self.check_for_help_and_version(c);
|
||||
if !self.parse_single_short_flag(matches, c) {
|
||||
self.report_error(format!("The argument -{} isn't valid",arg),
|
||||
self.report_error(format!("The argument '{}' isn't valid",
|
||||
Format::Warning(format!("-{}", c))),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -2079,10 +2082,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
// Ensure this option isn't on the master mutually excludes list
|
||||
if self.blacklist.contains(v.name) {
|
||||
matches.args.remove(v.name);
|
||||
self.report_error(format!("The argument -{} cannot be used with {}",
|
||||
arg,
|
||||
self.report_error(format!("The argument '{}' cannot be used with {}",
|
||||
Format::Warning(format!("-{}", arg)),
|
||||
match self.blacklisted_from(v.name, matches) {
|
||||
Some(name) => format!("'{}'", name),
|
||||
Some(name) => format!("'{}'", Format::Warning(name)),
|
||||
None => "one or more of the other specified arguments".to_owned()
|
||||
}),
|
||||
true,
|
||||
|
@ -2092,8 +2095,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
|
||||
if matches.args.contains_key(v.name) {
|
||||
if !v.multiple {
|
||||
self.report_error(format!("The argument -{} was supplied more than once, but \
|
||||
does not support multiple values", arg),
|
||||
self.report_error(format!("The argument '{}' was supplied more than once, but \
|
||||
does not support multiple values",
|
||||
Format::Warning(format!("-{}", arg))),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -2130,7 +2134,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
|
||||
// Didn't match a flag or option, must be invalid
|
||||
self.report_error(format!("The argument -{} isn't valid",arg_c),
|
||||
self.report_error(format!("The argument '{}' isn't valid",
|
||||
Format::Warning(format!("-{}", arg_c))),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -2145,10 +2150,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
// Ensure this flag isn't on the mutually excludes list
|
||||
if self.blacklist.contains(v.name) {
|
||||
matches.args.remove(v.name);
|
||||
self.report_error(format!("The argument -{} cannot be used {}",
|
||||
arg,
|
||||
self.report_error(format!("The argument '{}' cannot be used {}",
|
||||
Format::Warning(format!("-{}", arg)),
|
||||
match self.blacklisted_from(v.name, matches) {
|
||||
Some(name) => format!("'{}'", name),
|
||||
Some(name) => format!("'{}'", Format::Warning(name)),
|
||||
None => "with one or more of the other specified \
|
||||
arguments".to_owned()
|
||||
}),
|
||||
|
@ -2159,8 +2164,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
|
||||
// Make sure this isn't one being added multiple times if it doesn't suppor it
|
||||
if matches.args.contains_key(v.name) && !v.multiple {
|
||||
self.report_error(format!("The argument -{} was supplied more than once, but does \
|
||||
not support multiple values", arg),
|
||||
self.report_error(format!("The argument '{}' was supplied more than once, but does \
|
||||
not support multiple values",
|
||||
Format::Warning(format!("-{}", arg))),
|
||||
true,
|
||||
true,
|
||||
Some(matches.args.keys().map(|k| *k).collect()));
|
||||
|
@ -2213,16 +2219,16 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
matches.args.remove(name);
|
||||
self.report_error(format!("The argument '{}' cannot be used with {}",
|
||||
if let Some(ref flag) = self.flags.get(name) {
|
||||
format!("{}", flag)
|
||||
format!("{}", Format::Warning(flag.to_string()))
|
||||
} else if let Some(ref opt) = self.opts.get(name) {
|
||||
format!("{}", opt)
|
||||
format!("{}", Format::Warning(opt.to_string()))
|
||||
} else {
|
||||
match self.positionals_idx.values().filter(|p| p.name == *name).next() {
|
||||
Some(pos) => format!("{}", pos),
|
||||
None => format!("\"{}\"", name)
|
||||
Some(pos) => format!("{}", Format::Warning(pos.to_string())),
|
||||
None => format!("\"{}\"", Format::Warning(name))
|
||||
}
|
||||
}, match self.blacklisted_from(name, matches) {
|
||||
Some(name) => format!("'{}'", name),
|
||||
Some(name) => format!("'{}'", Format::Warning(name)),
|
||||
None => "one or more of the other specified arguments".to_owned()
|
||||
}), true, true, Some(matches.args.keys().map(|k| *k).collect()));
|
||||
} else if self.groups.contains_key(name) {
|
||||
|
@ -2232,15 +2238,15 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
self.report_error(format!("The argument '{}' cannot be used with one or \
|
||||
more of the other specified arguments",
|
||||
if let Some(ref flag) = self.flags.get(n) {
|
||||
format!("{}", flag)
|
||||
format!("{}", Format::Warning(flag.to_string()))
|
||||
} else if let Some(ref opt) = self.opts.get(n) {
|
||||
format!("{}", opt)
|
||||
format!("{}", Format::Warning(opt.to_string()))
|
||||
} else {
|
||||
match self.positionals_idx.values()
|
||||
.filter(|p| p.name == *name)
|
||||
.next() {
|
||||
Some(pos) => format!("{}", pos),
|
||||
None => format!("\"{}\"", n)
|
||||
Some(pos) => format!("{}", Format::Warning(pos.to_string())),
|
||||
None => format!("\"{}\"", Format::Warning(n))
|
||||
}
|
||||
}),
|
||||
true,
|
||||
|
@ -2265,13 +2271,13 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if should_err {
|
||||
self.report_error(format!("The argument '{}' requires {} values, \
|
||||
but {} w{} provided",
|
||||
f,
|
||||
num,
|
||||
if f.multiple {
|
||||
vals.len() % num as usize
|
||||
Format::Warning(f.to_string()),
|
||||
Format::Good(num.to_string()),
|
||||
Format::Error(if f.multiple {
|
||||
(vals.len() % num as usize).to_string()
|
||||
} else {
|
||||
vals.len()
|
||||
},
|
||||
vals.len().to_string()
|
||||
}),
|
||||
if vals.len() == 1 ||
|
||||
( f.multiple &&
|
||||
( vals.len() % num as usize) == 1) {"as"}else{"ere"}),
|
||||
|
@ -2284,9 +2290,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if (vals.len() as u8) > num {
|
||||
self.report_error(format!("The argument '{}' requires no more than {} \
|
||||
values, but {} w{} provided",
|
||||
f,
|
||||
num,
|
||||
vals.len(),
|
||||
Format::Warning(f.to_string()),
|
||||
Format::Good(num.to_string()),
|
||||
Format::Error(vals.len().to_string()),
|
||||
if vals.len() == 1 {"as"}else{"ere"}),
|
||||
true,
|
||||
true,
|
||||
|
@ -2297,9 +2303,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if (vals.len() as u8) < num {
|
||||
self.report_error(format!("The argument '{}' requires at least {} \
|
||||
values, but {} w{} provided",
|
||||
f,
|
||||
num,
|
||||
vals.len(),
|
||||
Format::Warning(f.to_string()),
|
||||
Format::Good(num.to_string()),
|
||||
Format::Error(vals.len().to_string()),
|
||||
if vals.len() == 1 {"as"}else{"ere"}),
|
||||
true,
|
||||
true,
|
||||
|
@ -2312,9 +2318,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if num != vals.len() as u8 {
|
||||
self.report_error(format!("The argument '{}' requires {} values, \
|
||||
but {} w{} provided",
|
||||
f,
|
||||
num,
|
||||
vals.len(),
|
||||
Format::Warning(f.to_string()),
|
||||
Format::Good(num.to_string()),
|
||||
Format::Error(vals.len().to_string()),
|
||||
if vals.len() == 1 {"as"}else{"ere"}),
|
||||
true,
|
||||
true,
|
||||
|
@ -2325,9 +2331,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if num > vals.len() as u8 {
|
||||
self.report_error(format!("The argument '{}' requires no more than {} \
|
||||
values, but {} w{} provided",
|
||||
f,
|
||||
num,
|
||||
vals.len(),
|
||||
Format::Warning(f.to_string()),
|
||||
Format::Good(num.to_string()),
|
||||
Format::Error(vals.len().to_string()),
|
||||
if vals.len() == 1 {"as"}else{"ere"}),
|
||||
true,
|
||||
true,
|
||||
|
@ -2338,9 +2344,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if num < vals.len() as u8 {
|
||||
self.report_error(format!("The argument '{}' requires at least {} \
|
||||
values, but {} w{} provided",
|
||||
f,
|
||||
num,
|
||||
vals.len(),
|
||||
Format::Warning(f.to_string()),
|
||||
Format::Good(num.to_string()),
|
||||
Format::Error(vals.len().to_string()),
|
||||
if vals.len() == 1 {"as"}else{"ere"}),
|
||||
true,
|
||||
true,
|
||||
|
|
50
src/fmt.rs
Normal file
50
src/fmt.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
use std::fmt;
|
||||
|
||||
#[cfg(feature = "color")]
|
||||
use ansi_term::Colour::{Red, Green, Yellow};
|
||||
#[cfg(feature = "color")]
|
||||
use ansi_term::ANSIString;
|
||||
|
||||
|
||||
pub enum Format<T> {
|
||||
Error(T),
|
||||
Warning(T),
|
||||
Good(T),
|
||||
}
|
||||
|
||||
#[cfg(feature = "color")]
|
||||
impl<T: AsRef<str>> Format<T> {
|
||||
fn format(&self) -> ANSIString {
|
||||
match *self {
|
||||
Format::Error(ref e) => Red.bold().paint(e.as_ref()),
|
||||
Format::Warning(ref e) => Yellow.paint(e.as_ref()),
|
||||
Format::Good(ref e) => Green.paint(e.as_ref()),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(feature = "color")]
|
||||
impl<T: AsRef<str>> fmt::Display for Format<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", &self.format())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "color"))]
|
||||
impl<T: fmt::Display> Format<T> {
|
||||
fn format(&self) -> &T {
|
||||
match *self {
|
||||
Format::Error(ref e) => e,
|
||||
Format::Warning(ref e) => e,
|
||||
Format::Good(ref e) => e,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "color"))]
|
||||
impl<T: fmt::Display> fmt::Display for Format<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", &self.format())
|
||||
}
|
||||
}
|
|
@ -383,12 +383,14 @@ extern crate ansi_term;
|
|||
|
||||
pub use args::{Arg, SubCommand, ArgMatches, ArgGroup};
|
||||
pub use app::App;
|
||||
pub use fmt::Format;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod app;
|
||||
mod args;
|
||||
mod usageparser;
|
||||
mod fmt;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
|
@ -5,10 +5,12 @@ macro_rules! get_help {
|
|||
format!("{}{}", h,
|
||||
if let Some(ref pv) = $opt.possible_vals {
|
||||
let mut pv_s = pv.iter().fold(String::with_capacity(50), |acc, name| {
|
||||
acc + &format!(" {}",name)[..]
|
||||
acc + &format!(" {},",name)[..]
|
||||
});
|
||||
pv_s.shrink_to_fit();
|
||||
format!(" [values:{}]", &pv_s[..])
|
||||
// pv_s = one, two, three, four,
|
||||
// Needs to remove trailing comma (',')
|
||||
format!(" [values:{}]", &pv_s[..pv_s.len()-1])
|
||||
}else{"".to_owned()})
|
||||
} else {
|
||||
" ".to_owned()
|
||||
|
@ -144,10 +146,10 @@ macro_rules! value_t {
|
|||
Some(v) => {
|
||||
match v.parse::<$t>() {
|
||||
Ok(val) => Ok(val),
|
||||
Err(_) => Err(format!("'{}' isn't a valid value",v)),
|
||||
Err(_) => Err(format!("'{}' isn't a valid value", ::clap::Format::Warning(v))),
|
||||
}
|
||||
},
|
||||
None => Err(format!("The argument '{}' not found", $v))
|
||||
None => Err(format!("The argument '{}' not found", ::clap::Format::Warning($v)))
|
||||
}
|
||||
};
|
||||
($m:ident.values_of($v:expr), $t:ty) => {
|
||||
|
@ -159,7 +161,7 @@ macro_rules! value_t {
|
|||
match pv.parse::<$t>() {
|
||||
Ok(rv) => tmp.push(rv),
|
||||
Err(e) => {
|
||||
err = Some(format!("'{}' isn't a valid value\n\t{}",pv,e));
|
||||
err = Some(format!("'{}' isn't a valid value\n\t{}", ::clap::Format::Warning(pv),e));
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +171,7 @@ macro_rules! value_t {
|
|||
None => Ok(tmp)
|
||||
}
|
||||
},
|
||||
None => Err(format!("The argument '{}' was not found", $v))
|
||||
None => Err(format!("The argument '{}' was not found", ::clap::Format::Warning($v)))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -227,20 +229,24 @@ macro_rules! value_t_or_exit {
|
|||
match v.parse::<$t>() {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
println!("'{}' isn't a valid value\n\t{}\n\n{}\n\nPlease re-run with --help for \
|
||||
println!("{} '{}' isn't a valid value\n\t{}\n\n{}\n\nPlease re-run with {} for \
|
||||
more information",
|
||||
v,
|
||||
::clap::Format::Error("error:"),
|
||||
::clap::Format::Warning(v.to_string()),
|
||||
e,
|
||||
$m.usage());
|
||||
$m.usage(),
|
||||
::clap::Format::Good("--help"));
|
||||
::std::process::exit(1);
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
println!("The argument '{}' was not found or is not valid\n\n{}\n\nPlease re-run with \
|
||||
--help for more information",
|
||||
$v,
|
||||
$m.usage());
|
||||
println!("{} The argument '{}' was not found or is not valid\n\n{}\n\nPlease re-run with \
|
||||
{} for more information",
|
||||
::clap::Format::Error("error:"),
|
||||
::clap::Format::Warning($v.to_string()),
|
||||
$m.usage(),
|
||||
::clap::Format::Good("--help"));
|
||||
::std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -253,10 +259,12 @@ macro_rules! value_t_or_exit {
|
|||
match pv.parse::<$t>() {
|
||||
Ok(rv) => tmp.push(rv),
|
||||
Err(_) => {
|
||||
println!("'{}' isn't a valid value\n\t{}\n\nPlease re-run with --help for more \
|
||||
println!("{} '{}' isn't a valid value\n\t{}\n\nPlease re-run with {} for more \
|
||||
information",
|
||||
pv,
|
||||
$m.usage());
|
||||
::clap::Format::Error("error:"),
|
||||
::clap::Format::Warning(pv),
|
||||
$m.usage(),
|
||||
::clap::Format::Good("--help"));
|
||||
::std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -264,10 +272,12 @@ macro_rules! value_t_or_exit {
|
|||
tmp
|
||||
},
|
||||
None => {
|
||||
println!("The argument '{}' not found or is not valid\n\n{}\n\nPlease re-run with \
|
||||
--help for more information",
|
||||
$v,
|
||||
$m.usage());
|
||||
println!("{} The argument '{}' not found or is not valid\n\n{}\n\nPlease re-run with \
|
||||
{} for more information",
|
||||
::clap::Format::Error("error:"),
|
||||
::clap::Format::Warning($v.to_string()),
|
||||
$m.usage(),
|
||||
::clap::Format::Good("--help"));
|
||||
::std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ impl<'u> Iterator for UsageParser<'u> {
|
|||
}
|
||||
if mult { return Some(UsageToken::Multiple) }
|
||||
},
|
||||
Some(' ') | Some('=') | Some(']') | Some('>') | Some('\t') => {
|
||||
Some(' ') | Some('=') | Some(']') | Some('>') | Some('\t') | Some(',') => {
|
||||
self.e += 1;
|
||||
continue
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue