mirror of
https://github.com/clap-rs/clap
synced 2025-03-04 15:27:16 +00:00
commit
ace4f1acf8
14 changed files with 322 additions and 159 deletions
|
@ -7,3 +7,4 @@ from-latest-tag = true
|
|||
Performance = ["perf"]
|
||||
Improvements = ["impr", "im", "imp"]
|
||||
Documentation = ["docs"]
|
||||
Deprecations = ["depr"]
|
||||
|
|
10
README.md
10
README.md
|
@ -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()`
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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") {
|
||||
|
|
249
src/app.rs
249
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.
|
||||
|
@ -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,
|
||||
|
|
|
@ -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 `''`
|
||||
///
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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
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())
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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…
Add table
Reference in a new issue