Merge pull request #132 from kbknapp/next

Next
This commit is contained in:
Kevin K. 2015-05-22 22:38:15 -05:00
commit ace4f1acf8
14 changed files with 322 additions and 159 deletions

View file

@ -7,3 +7,4 @@ from-latest-tag = true
Performance = ["perf"]
Improvements = ["impr", "im", "imp"]
Documentation = ["docs"]
Deprecations = ["depr"]

View file

@ -53,6 +53,7 @@ Below are a few of the features which `clap` supports, full descriptions and usa
* **Typed Values**: You can use several convenience macros provided by `clap` to get typed values (i.e. `i32`, `u8`, etc.) from positional or option arguments so long as the type you request implements `std::str::FromStr` See the `examples/12_TypedValues.rs`. You can also use `clap`s `simple_enum!` or `arg_enum!` macro to create an enum with variants that automatically implements `std::str::FromStr`. See `examples/13a_EnumValuesAutomatic.rs` for details and performs an ascii case insensitive parse from a `string`->`enum`.
* **Suggestions**: Suggests corrections when the user enter's a typo. For example, if you defined a `--myoption <value>` argument, and the user mistakenly typed `--moyption value` (notice `y` and `o` switched), they would receive a `Did you mean '--myoption' ?` error and exit gracefully. This also works for subcommands and flags. (Thanks to [Byron](https://github.com/Byron) for the implementation) (This feature can optionally be disabled, see 'Optional Dependencies / Features')
* **Colorized (Red) Errors**: Error message are printed in red text (this feature can optionally be disabled, see 'Optional Dependencies / Features').
* **Global Arguments**: Arguments can optionally be defined once, and be available to all child subcommands.
## Quick Example
@ -369,7 +370,10 @@ Although I do my best to keep breaking changes to a minimum, being that this a s
Old method names will be left around for some time.
* As of 0.10.0
- `SubCommand::new()` -> `SubCommand::with_name()`
- `App::error_on_no_subcommand()` -> `App::subcommand_required()`
* As of 0.6.8
- `Arg::new()` -> `Arg::with_name()`
- `Arg::mutually_excludes()` -> `Arg::conflicts_with()`
- `Arg::mutually_excludes_all()` -> `Arg::conflicts_with_all()`
- `Arg::new()` -> `Arg::with_name()`
- `Arg::mutually_excludes()` -> `Arg::conflicts_with()`
- `Arg::mutually_excludes_all()` -> `Arg::conflicts_with_all()`

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>'
@ -140,8 +141,8 @@ USAGE:
claptests subcmd [POSITIONAL] [FLAGS] [OPTIONS]
FLAGS:
-h, --help Prints help information
-f, --flag tests flags
-h, --help Prints help information
-v, --version Prints version information
OPTIONS:
@ -161,7 +162,7 @@ positional3 NOT present
option NOT present
positional NOT present
subcmd present
scflag present 1 times
flag present 1 times
scoption present with value: some
An scoption: some
scpositional present with value: value'''
@ -177,12 +178,12 @@ positional3 NOT present
option NOT present
positional NOT present
subcmd present
scflag present 2 times
flag present 2 times
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

@ -6,8 +6,7 @@ use clap::{App, Arg, SubCommand};
fn main() {
let m_val_names = ["one", "two"];
let args = "-f --flag... 'tests flags'
-o --option=[opt]... 'tests options'
let args = "-o --option=[opt]... 'tests options'
[positional] 'tests positionals'";
let opt3_vals = ["fast", "slow"];
let pos3_vals = ["vi", "emacs"];
@ -17,6 +16,8 @@ fn main() {
.about("tests clap library")
.author("Kevin K. <kbknapp@gmail.com>")
.args_from_usage(args)
.arg(Arg::from_usage("-f --flag... 'tests flags'")
.global(true))
.args(vec![
Arg::from_usage("[flag2] -F 'tests flags with exclusions'").mutually_excludes("flag").requires("option2"),
Arg::from_usage("--long-option-2 [option2] 'tests long options with exclusions'").mutually_excludes("option").requires("positional2"),
@ -32,7 +33,6 @@ fn main() {
.about("tests subcommands")
.version("0.1")
.author("Kevin K. <kbknapp@gmail.com>")
.arg_from_usage("[scflag] -f --flag... 'tests flags'")
.arg_from_usage("-o --option [scoption]... 'tests options'")
.arg_from_usage("[scpositional] 'tests positionals'"))
.get_matches();
@ -105,10 +105,10 @@ fn main() {
if matches.is_present("subcmd") {
println!("subcmd present");
if let Some(matches) = matches.subcommand_matches("subcmd") {
if matches.is_present("scflag") {
println!("scflag present {} times", matches.occurrences_of("scflag"));
if matches.is_present("flag") {
println!("flag present {} times", matches.occurrences_of("flag"));
} else {
println!("scflag NOT present");
println!("flag NOT present");
}
if matches.is_present("scoption") {

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.
@ -118,6 +117,7 @@ pub struct App<'a, 'v, 'ab, 'u, 'h, 'ar> {
bin_name: Option<String>,
usage: Option<String>,
groups: HashMap<&'ar str, ArgGroup<'ar, 'ar>>,
global_args: Vec<Arg<'ar, 'ar, 'ar, 'ar, 'ar, 'ar>>,
no_sc_error: bool
}
@ -161,6 +161,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
bin_name: None,
groups: HashMap::new(),
subcmds_neg_reqs: false,
global_args: vec![],
no_sc_error: false
}
}
@ -234,6 +235,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
self
}
/// **WARNING:** This method is deprecated. Use `.subcommand_required(true)` instead.
///
/// Allows specifying that if no subcommand is present at runtime, error and exit gracefully
///
/// **NOTE:** This defaults to false (subcommands do *not* need to be present)
@ -251,6 +254,23 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
self
}
/// Allows specifying that if no subcommand is present at runtime, error and exit gracefully
///
/// **NOTE:** This defaults to false (subcommands do *not* need to be present)
///
/// # Example
///
/// ```no_run
/// # use clap::App;
/// # let app = App::new("myprog")
/// .subcommands_negate_reqs(true)
/// # .get_matches();
/// ```
pub fn subcommand_required(mut self, n: bool) -> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
self.no_sc_error = n;
self
}
/// Sets a string of the version number to be displayed when displaying version or help
/// information.
///
@ -400,6 +420,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
min_vals: a.min_vals,
max_vals: a.max_vals,
help: a.help,
global: a.global,
empty_vals: a.empty_vals
};
if pb.min_vals.is_some() && !pb.multiple {
@ -451,11 +472,12 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
multiple: a.multiple,
blacklist: None,
help: a.help,
global: a.global,
possible_vals: None,
num_vals: a.num_vals,
min_vals: a.min_vals,
max_vals: a.max_vals,
val_names: a.val_names,
val_names: a.val_names.clone(),
requires: None,
required: a.required,
empty_vals: a.empty_vals
@ -521,6 +543,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
long: a.long,
help: a.help,
blacklist: None,
global: a.global,
multiple: a.multiple,
requires: None,
};
@ -541,6 +564,12 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
}
self.flags.insert(a.name, fb);
}
if a.global {
if a.required {
panic!("Global arguments cannot be required.\n\n\t'{}' is marked as global and required", a.name);
}
self.global_args.push(a);
}
self
}
@ -730,9 +759,14 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
/// // Additional subcommand configuration goes here, such as other arguments...
/// # .get_matches();
/// ```
pub fn subcommand(mut self, subcmd: App<'a, 'v, 'ab, 'u, 'h, 'ar>)
pub fn subcommand(mut self, mut subcmd: App<'a, 'v, 'ab, 'u, 'h, 'ar>)
-> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
if subcmd.name == "help" { self.needs_subcmd_help = false; }
{
while let Some(a) = self.global_args.pop() {
subcmd = subcmd.arg(a);
}
}
self.subcommands.insert(subcmd.name.clone(), subcmd);
self
}
@ -1002,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"));
}
}
@ -1208,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); }
}
@ -1295,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('\'');
}
@ -1314,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)[..]
@ -1360,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(
@ -1378,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()
@ -1420,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() ) );
@ -1455,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,
@ -1468,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,
@ -1482,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()
}),
@ -1509,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()
@ -1520,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()
@ -1544,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()
@ -1579,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,
@ -1597,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() ) );
@ -1606,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() ) );
@ -1618,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()));
@ -1626,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()));
@ -1680,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 {
@ -1697,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()));
@ -1744,6 +1778,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
help: Some("Prints help information"),
blacklist: None,
multiple: false,
global: false,
requires: None,
};
if self.needs_short_help {
@ -1761,6 +1796,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
help: Some("Prints version information"),
blacklist: None,
multiple: false,
global: false,
requires: None,
};
if self.needs_short_version {
@ -1800,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()));
@ -1815,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()));
@ -1840,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()
@ -1857,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()
@ -1909,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()));
@ -1922,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()));
@ -2001,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()));
@ -2017,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()));
@ -2042,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,
@ -2055,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()));
@ -2093,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()));
@ -2108,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()
}),
@ -2122,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()));
@ -2176,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) {
@ -2195,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,
@ -2228,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"}),
@ -2247,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,
@ -2260,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,
@ -2275,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,
@ -2288,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,
@ -2301,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,

View file

@ -88,10 +88,14 @@ pub struct Arg<'n, 'l, 'h, 'g, 'p, 'r> {
#[doc(hidden)]
pub min_vals: Option<u8>,
#[doc(hidden)]
pub empty_vals: bool
pub empty_vals: bool,
#[doc(hidden)]
pub global: bool
}
impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
/// **WARNING:** This function is deprecated. Use `Arg::with_name()` instead.
///
/// Creates a new instace of `Arg` using a unique string name.
/// The name will be used by the library consumer to get information about
/// whether or not the argument was used at runtime.
@ -100,8 +104,6 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
/// and positional arguments (i.e. those without a `-` or `--`) the name will also
/// be displayed when the user prints the usage/help information of the program.
///
/// **NOTE:** this function is deprecated in favor of Arg::with_name() to stay consistent with
/// Rust APIs
///
///
/// # Example
@ -131,6 +133,7 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
val_names: None,
max_vals: None,
min_vals: None,
global: false,
empty_vals: true,
}
}
@ -171,6 +174,7 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
max_vals: None,
val_names: None,
group: None,
global: false,
empty_vals: true
}
}
@ -328,6 +332,7 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
max_vals: None,
min_vals: None,
group: None,
global: false,
empty_vals: true
}
}
@ -423,6 +428,8 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
self
}
/// **WARNING:** This method is deprecated. Use `.conflicts_with()` instead.
///
/// Sets a mutually exclusive argument by name. I.e. when using this argument,
/// the following argument can't be present.
///
@ -430,9 +437,6 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
/// by default. Mutually exclusive rules only need to be set for one of the two
/// arguments, they do not need to be set for each.
///
/// **NOTE:** This method is deprecated in favor of `conflicts_with()`
///
///
/// # Example
///
/// ```no_run
@ -450,6 +454,8 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
self
}
/// **WARNING:** This method is deprecated. Use `conflicts_with_all()` instead.
///
/// Sets a mutually exclusive arguments by names. I.e. when using this argument,
/// the following argument can't be present.
///
@ -457,9 +463,6 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
/// by default. Mutually exclusive rules only need to be set for one of the two
/// arguments, they do not need to be set for each.
///
/// **NOTE:** This method is deprecated in favor of `conflicts_with_all()`
///
///
/// # Example
///
/// ```no_run
@ -646,6 +649,31 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
self
}
/// Specifies that an argument can be matched to all child subcommands.
///
/// **NOTE:** Global arguments *only* propagate down, **not** up (to parent commands)
///
/// **NOTE:** Global arguments *cannot* be required.
///
/// **NOTE:** Global arguments, when matched, *only* exist in the command's matches that they
/// were matched to. For example, if you defined a `--flag` global argument in the top most
/// parent command, but the user supplied the arguments `top cmd1 cmd2 --flag` *only* `cmd2`'s
/// `ArgMatches` would return `true` if tested for `.is_present("flag")`.
///
/// # Example
///
/// ```no_run
/// # use clap::{App, Arg};
/// # let matches = App::new("myprog")
/// # .arg(
/// # Arg::with_name("debug")
/// .global(true)
/// # ).get_matches();
pub fn global(mut self, g: bool) -> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
self.global = g;
self
}
/// Allows an argument to accept explicit empty values. An empty value must be specified at the
/// command line with an explicit `""`, or `''`
///

View file

@ -24,6 +24,7 @@ pub struct FlagBuilder<'n> {
/// The short version (i.e. single character)
/// of the argument, no preceding `-`
pub short: Option<char>,
pub global: bool,
}
impl<'n> Display for FlagBuilder<'n> {

View file

@ -29,7 +29,8 @@ pub struct OptBuilder<'n> {
pub min_vals: Option<u8>,
pub max_vals: Option<u8>,
pub val_names: Option<Vec<&'n str>>,
pub empty_vals: bool
pub empty_vals: bool,
pub global: bool,
}
impl<'n> Display for OptBuilder<'n> {

View file

@ -26,7 +26,8 @@ pub struct PosBuilder<'n> {
pub num_vals: Option<u8>,
pub max_vals: Option<u8>,
pub min_vals: Option<u8>,
pub empty_vals: bool
pub empty_vals: bool,
pub global: bool
}
impl<'n> Display for PosBuilder<'n> {

View file

@ -28,6 +28,23 @@ pub struct SubCommand<'n, 'a> {
}
impl<'n, 'a> SubCommand<'n, 'a> {
/// Creates a new instance of a subcommand requiring a name. Will be displayed
/// to the user when they print version or help and usage information.
///
/// # Example
///
/// ```no_run
/// # use clap::{App, Arg, SubCommand};
/// # let prog = App::new("myprog").subcommand(
/// SubCommand::new("config")
/// # ).get_matches();
/// ```
pub fn with_name<'au, 'v, 'ab, 'u, 'h, 'ar>(name: &'ar str) -> App<'au, 'v, 'ab, 'u, 'h, 'ar> {
App::new(name)
}
/// **WARNING:** This function is deprecated. Use `SubCommand::with_name()` instead.
///
/// Creates a new instance of a subcommand requiring a name. Will be displayed
/// to the user when they print version or help and usage information.
///

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

@ -56,6 +56,7 @@
//! * **Typed Values**: You can use several convenience macros provided by `clap` to get typed values (i.e. `i32`, `u8`, etc.) from positional or option arguments so long as the type you request implements `std::str::FromStr` See the `examples/12_TypedValues.rs`. You can also use `clap`s `simple_enum!` or `arg_enum!` macro to create an enum with variants that automatically implements `std::str::FromStr`. See `examples/13a_EnumValuesAutomatic.rs` for details and performs an ascii case insensitive parse from a `string`->`enum`.
//! * **Suggestions**: Suggests corrections when the user enter's a typo. For example, if you defined a `--myoption <value>` argument, and the user mistakenly typed `--moyption value` (notice `y` and `o` switched), they would receive a `Did you mean '--myoption' ?` error and exit gracefully. This also works for subcommands and flags. (Thanks to [Byron](https://github.com/Byron) for the implementation) (This feature can optionally be disabled, see 'Optional Dependencies / Features')
//! * **Colorized (Red) Errors**: Error message are printed in red text (this feature can optionally be disabled, see 'Optional Dependencies / Features').
//! * **Global Arguments**: Arguments can optionally be defined once, and be available to all child subcommands.
//!
//! ## Quick Example
//!
@ -372,6 +373,9 @@
//!
//! Old method names will be left around for some time.
//!
//! * As of 0.10.0
//! - `SubCommand::new()` -> `SubCommand::with_name()`
//! - `App::error_on_no_subcommand()` -> `App::subcommand_required()`
//! * As of 0.6.8
//! - `Arg::new()` -> `Arg::with_name()`
//! - `Arg::mutually_excludes()` -> `Arg::conflicts_with()`
@ -383,12 +387,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
},