imp(Colors): implements more structured colored output

Closes #129
This commit is contained in:
Kevin K 2015-05-22 18:17:57 -04:00
parent 92fcec8fb7
commit d6c3ed54d2
6 changed files with 203 additions and 134 deletions

View file

@ -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>

View file

@ -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
View 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())
}
}

View file

@ -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 {

View file

@ -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);
}
}

View file

@ -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
},