mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 06:44:16 +00:00
tests(v2): fixing more tests on the new v2 base
This commit is contained in:
parent
0031d78564
commit
c3e96232c9
19 changed files with 404 additions and 238 deletions
|
@ -1,7 +1,7 @@
|
|||
#[macro_use]
|
||||
extern crate clap;
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
#[cfg(feature = "unstable")]
|
||||
fn main() {
|
||||
// This example shows how to create an application with several arguments using macro builder.
|
||||
// It combines the simplicity of the from_usage methods and the performance of the Builder Pattern.
|
||||
|
@ -74,3 +74,6 @@ fn main() {
|
|||
|
||||
// more program logic goes here...
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unstable"))]
|
||||
fn main() {}
|
||||
|
|
|
@ -38,13 +38,13 @@ fn main() {
|
|||
//
|
||||
// Using other methods such as unwrap_or_else(|e| println!("{}",e))
|
||||
// are possible too.
|
||||
let len = value_t!(matches.value_of("len"), u32).unwrap_or(10);
|
||||
let len = value_t!(matches, "len", u32).unwrap_or(10);
|
||||
|
||||
println!("len ({}) + 2 = {}", len, len + 2);
|
||||
|
||||
// This code loops through all the values provided to "seq" and adds 2
|
||||
// If seq fails to parse, the program exits, you don't have an option
|
||||
for v in value_t_or_exit!(matches.values_of("seq"), u32) {
|
||||
for v in values_t!(matches, "seq", u32).unwrap_or_else(|e| e.exit()) {
|
||||
println!("Sequence part {} + 2: {}", v, v + 2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ fn main() {
|
|||
.possible_values(&enum_vals))
|
||||
.get_matches();
|
||||
|
||||
let t = value_t!(m.value_of("type"), Vals).or_else(|e| e.exit());
|
||||
let t = value_t!(m, "type", Vals).unwrap_or_else(|e| e.exit());
|
||||
|
||||
// Now we can use our enum like normal.
|
||||
match t {
|
||||
|
|
|
@ -4,7 +4,7 @@ extern crate clap;
|
|||
// Note, there isn't a need for "use clap::{ ... };" Because the clap_app! macro uses
|
||||
// $crate:: internally
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
#[cfg(feature = "unstable")]
|
||||
fn main() {
|
||||
|
||||
// Validation example testing that a file exists
|
||||
|
@ -80,6 +80,8 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Continued program logic goes here...
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unstable"))]
|
||||
fn main() {}
|
||||
|
|
|
@ -56,40 +56,51 @@ macro_rules! arg_post_processing(
|
|||
($me:ident, $arg:ident, $matcher:ident) => ({
|
||||
use args::AnyArg;
|
||||
// Handle POSIX overrides
|
||||
debug!("Is '{}' in overrides...", $arg.to_string());
|
||||
if $me.overrides.contains(&$arg.name()) {
|
||||
if let Some(ref name) = $me.overriden_from(&*$arg.name(), $matcher) {
|
||||
if let Some(ref name) = $me.overriden_from($arg.name(), $matcher) {
|
||||
sdebugln!("Yes by {}", name);
|
||||
$matcher.remove(name);
|
||||
remove_overriden!($me, name);
|
||||
}
|
||||
}
|
||||
} else { sdebugln!("No"); }
|
||||
|
||||
// Add overrides
|
||||
debug!("Does '{}' have overrides...", $arg.to_string());
|
||||
if let Some(or) = $arg.overrides() {
|
||||
for pa in or {
|
||||
sdebugln!("\tYes '{}'", pa);
|
||||
$matcher.remove(&*pa);
|
||||
remove_overriden!($me, pa);
|
||||
$me.overrides.push(pa);
|
||||
vec_remove!($me.required, pa);
|
||||
}
|
||||
}
|
||||
} else { sdebugln!("No"); }
|
||||
|
||||
// Handle conflicts
|
||||
debugln!("Does '{}' have conflicts...", $arg.to_string());
|
||||
if let Some(bl) = $arg.blacklist() {
|
||||
for name in bl {
|
||||
sdebugln!("\tYes '{}'", name);
|
||||
$me.blacklist.push(name);
|
||||
vec_remove!($me.overrides, name);
|
||||
vec_remove!($me.required, name);
|
||||
}
|
||||
}
|
||||
} else { sdebugln!("No"); }
|
||||
|
||||
// Add all required args which aren't already found in matcher to the master
|
||||
// list
|
||||
debug!("Does '{}' have requirements...", $arg.to_string());
|
||||
if let Some(reqs) = $arg.requires() {
|
||||
for n in reqs {
|
||||
if $matcher.contains(&*n) {
|
||||
if $matcher.contains(&n) {
|
||||
sdebugln!("\tYes '{}' but it's already met", n);
|
||||
continue;
|
||||
}
|
||||
} else { sdebugln!("\tYes '{}'", n); }
|
||||
|
||||
$me.required.push(n);
|
||||
}
|
||||
}
|
||||
} else { sdebugln!("No"); }
|
||||
|
||||
_handle_group_reqs!($me, $arg);
|
||||
})
|
||||
|
@ -128,3 +139,12 @@ macro_rules! _handle_group_reqs{
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! validate_multiples {
|
||||
($_self:ident, $a:ident, $m:ident) => {
|
||||
if $m.contains(&$a.name) && !$a.settings.is_set(ArgSettings::Multiple) {
|
||||
// Not the first time, and we don't allow multiples
|
||||
return Err(Error::unexpected_multiple_usage($a, &*$_self.create_current_usage($m)))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -423,8 +423,8 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// # use clap::{App, Arg};
|
||||
/// App::new("myprog")
|
||||
/// .args(
|
||||
/// vec![Arg::from_usage("[debug] -d 'turns on debugging info"),
|
||||
/// Arg::with_name("input").index(1).help("the input file to use")]
|
||||
/// &[Arg::from_usage("[debug] -d 'turns on debugging info"),
|
||||
/// Arg::with_name("input").index(1).help("the input file to use")]
|
||||
/// )
|
||||
/// # ;
|
||||
/// ```
|
||||
|
|
|
@ -34,7 +34,7 @@ pub struct Parser<'a, 'b> where 'a: 'b {
|
|||
positionals: VecMap<PosBuilder<'a, 'b>>,
|
||||
// A list of subcommands
|
||||
subcommands: Vec<App<'a, 'b>>,
|
||||
groups: HashMap<&'b str, ArgGroup<'a>>,
|
||||
groups: HashMap<&'a str, ArgGroup<'a>>,
|
||||
global_args: Vec<Arg<'a, 'b>>,
|
||||
overrides: Vec<&'b str>,
|
||||
help_short: Option<char>,
|
||||
|
@ -491,7 +491,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
|
||||
|
||||
if let Some(p) = self.positionals.get(&pos_counter) {
|
||||
try!(self.validate_arg(p, matcher));
|
||||
validate_multiples!(self, p, matcher);
|
||||
|
||||
try!(self.add_val_to_arg(p, &arg_os, matcher));
|
||||
|
||||
|
@ -640,21 +640,21 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
for k in matcher.arg_names() {
|
||||
if let Some(f) = self.flags.iter().filter(|f| &f.name == &k).next() {
|
||||
if let Some(ref bl) = f.blacklist {
|
||||
if bl.contains(&name.into()) {
|
||||
if bl.contains(&name) {
|
||||
return Some(format!("{}", f));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(o) = self.opts.iter().filter(|o| &o.name == &k).next() {
|
||||
if let Some(ref bl) = o.blacklist {
|
||||
if bl.contains(&name.into()) {
|
||||
if bl.contains(&name) {
|
||||
return Some(format!("{}", o));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(pos) = self.positionals.values().filter(|p| &p.name == &k).next() {
|
||||
if let Some(ref bl) = pos.blacklist {
|
||||
if bl.contains(&name.into()) {
|
||||
if bl.contains(&name) {
|
||||
return Some(format!("{}", pos));
|
||||
}
|
||||
}
|
||||
|
@ -691,12 +691,21 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
}
|
||||
|
||||
fn groups_for_arg(&self, name: &str) -> Option<Vec<&'a str>> {
|
||||
debugln!("fn=groups_for_arg;");
|
||||
|
||||
if self.groups.is_empty() {
|
||||
debugln!("No groups defined");
|
||||
return None;
|
||||
}
|
||||
let mut res = vec![];
|
||||
for (_, grp) in &self.groups {
|
||||
res.extend(grp.args.iter().filter(|&g| g == &name).map(|&g| g).collect::<Vec<_>>());
|
||||
debugln!("Searching through groups...");
|
||||
for (gn, grp) in &self.groups {
|
||||
for a in &grp.args {
|
||||
if a == &name {
|
||||
sdebugln!("\tFound '{}'", gn);
|
||||
res.push(*gn);
|
||||
}
|
||||
}
|
||||
}
|
||||
if res.is_empty() {
|
||||
return None;
|
||||
|
@ -841,19 +850,23 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
}
|
||||
|
||||
fn check_for_help_and_version_str(&self, arg: &OsStr) -> ClapResult<()> {
|
||||
debug!("Checking if --{} is help or version...", arg.to_str().unwrap());
|
||||
if arg == "help" && self.settings.is_set(AppSettings::NeedsLongHelp) {
|
||||
try!(self._help());
|
||||
}
|
||||
if arg == "version" && self.settings.is_set(AppSettings::NeedsLongVersion) {
|
||||
try!(self._version());
|
||||
}
|
||||
sdebugln!("Neither");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_for_help_and_version_char(&self, arg: char) -> ClapResult<()> {
|
||||
debug!("Checking if -{} is help or version...", arg);
|
||||
if let Some(h) = self.help_short { if arg == h { try!(self._help()); } }
|
||||
if let Some(v) = self.version_short { if arg == v { try!(self._version()); } }
|
||||
sdebugln!("Neither");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -881,12 +894,16 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
matcher: &mut ArgMatcher<'a>,
|
||||
full_arg: &OsStr)
|
||||
-> ClapResult<Option<&'b str>> { // maybe here lifetime should be 'a
|
||||
debugln!("fn=parse_long_arg;");
|
||||
let mut val = None;
|
||||
debug!("Does it contain '='...");
|
||||
let arg = if full_arg.contains_byte(b'=') {
|
||||
let (p0, p1) = full_arg.trim_left_matches(b'-').split_at_byte(b'=');
|
||||
sdebugln!("Yes '{:?}'", p1);
|
||||
val = Some(p1);
|
||||
p0
|
||||
} else {
|
||||
sdebugln!("No");
|
||||
full_arg.trim_left_matches(b'-')
|
||||
};
|
||||
|
||||
|
@ -894,6 +911,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
.iter()
|
||||
.filter(|v| v.long.is_some() && &*v.long.unwrap() == arg)
|
||||
.next() {
|
||||
debugln!("Found valid opt '{}'", opt.to_string());
|
||||
let ret = try!(self.parse_opt(val, opt, matcher));
|
||||
arg_post_processing!(self, opt, matcher);
|
||||
|
||||
|
@ -902,6 +920,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
.iter()
|
||||
.filter(|v| v.long.is_some() && &*v.long.unwrap() == arg)
|
||||
.next() {
|
||||
debugln!("Found valid flag '{}'", flag.to_string());
|
||||
// Only flags could be help or version, and we need to check the raw long
|
||||
// so this is the first point to check
|
||||
try!(self.check_for_help_and_version_str(&arg));
|
||||
|
@ -914,6 +933,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
debugln!("Didn't match anything");
|
||||
self.did_you_mean_error(arg.to_str().expect(INVALID_UTF8), matcher).map(|_| None)
|
||||
}
|
||||
|
||||
|
@ -921,6 +941,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
matcher: &mut ArgMatcher<'a>,
|
||||
full_arg: &OsStr)
|
||||
-> ClapResult<Option<&'a str>> {
|
||||
debugln!("fn=parse_short_arg;");
|
||||
// let mut utf8 = true;
|
||||
let arg_os = full_arg.trim_left_matches(b'-');
|
||||
let arg = arg_os.to_string_lossy();
|
||||
|
@ -934,19 +955,24 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
.iter()
|
||||
.filter(|&v| v.short.is_some() && v.short.unwrap() == c)
|
||||
.next() {
|
||||
debugln!("Found valid short opt -{} in '{}'", c, arg);
|
||||
// Check for trailing concatenated value
|
||||
let val = {
|
||||
let i = arg.splitn(2, c).next().unwrap().as_bytes().len() - 1;
|
||||
full_arg.split_at(i).1
|
||||
let p: Vec<_> = arg.splitn(2, c).collect();
|
||||
let i = p[0].as_bytes().len();
|
||||
let val = if i != 0 {
|
||||
Some(full_arg.split_at(i + 1).1)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Default to "we're expecting a value later"
|
||||
let ret = try!(self.parse_opt(Some(val), opt, matcher));
|
||||
let ret = try!(self.parse_opt(val, opt, matcher));
|
||||
|
||||
arg_post_processing!(self, opt, matcher);
|
||||
|
||||
return Ok(ret);
|
||||
} else if let Some(flag) = self.flags.iter().filter(|&v| v.short.is_some() && v.short.unwrap() == c).next() {
|
||||
debugln!("Found valid short flag -{}", c);
|
||||
// Only flags can be help or version
|
||||
try!(self.check_for_help_and_version_char(c));
|
||||
try!(self.parse_flag(flag, matcher));
|
||||
|
@ -969,26 +995,21 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
opt: &OptBuilder<'a, 'b>,
|
||||
matcher: &mut ArgMatcher<'a>)
|
||||
-> ClapResult<Option<&'a str>> {
|
||||
try!(self.validate_arg(opt, matcher));
|
||||
debugln!("fn=parse_opt;");
|
||||
validate_multiples!(self, opt, matcher);
|
||||
|
||||
if matcher.contains(&*opt.name) && !opt.settings.is_set(ArgSettings::Multiple) {
|
||||
// Not the first time, but we don't allow multiples
|
||||
return Err(
|
||||
Error::unexpected_multiple_usage(opt, &*self.create_current_usage(matcher)));
|
||||
}
|
||||
|
||||
if val.is_none() || val.unwrap().len() == 0 {
|
||||
if opt.is_set(ArgSettings::EmptyValues) {
|
||||
try!(self.add_val_to_arg(opt, val.unwrap(), matcher));
|
||||
return Ok(None);
|
||||
debug!("Checking for val...");
|
||||
if let Some(v) = val {
|
||||
if !opt.is_set(ArgSettings::EmptyValues) && v.len() == 0 {
|
||||
sdebugln!("Found Empty - Error");
|
||||
return Err(Error::empty_value(opt, &*self.create_current_usage(matcher)));
|
||||
}
|
||||
return Err(Error::empty_value(opt, &*self.create_current_usage(matcher)));
|
||||
}
|
||||
sdebugln!("Found");
|
||||
try!(self.add_val_to_arg(opt, v, matcher));
|
||||
} else { sdebugln!("None"); }
|
||||
|
||||
// If it doesn't allow mutliples, (or a specific number of values), or we don't have any
|
||||
// values yet, we want to return the name of this arg so the next arg is parsed as a value
|
||||
// otherwise we're done getting values
|
||||
if opt.settings.is_set(ArgSettings::Multiple) || opt.num_vals.is_some() || !matcher.contains(&*opt.name) {
|
||||
if (opt.is_set(ArgSettings::Multiple) || opt.num_vals().is_some())
|
||||
|| val.is_none() {
|
||||
return Ok(Some(opt.name));
|
||||
}
|
||||
Ok(None)
|
||||
|
@ -1077,79 +1098,88 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
|
|||
}
|
||||
|
||||
fn parse_flag(&self, flag: &FlagBuilder<'a, 'b>, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
|
||||
// Validate that we can actually accept this arg
|
||||
try!(self.validate_arg(flag, matcher));
|
||||
debugln!("fn=parse_flag;");
|
||||
validate_multiples!(self, flag, matcher);
|
||||
|
||||
// First occurrence or not?
|
||||
if !matcher.contains(&*flag.name) {
|
||||
// If this is the first, then add this flag itself
|
||||
matcher.insert(&*flag.name.clone());
|
||||
} else if !flag.settings.is_set(ArgSettings::Multiple) {
|
||||
// Not the first time, but we don't allow multiples
|
||||
return Err(
|
||||
Error::unexpected_multiple_usage(flag, &*self.create_current_usage(matcher)));
|
||||
} else {
|
||||
matcher.inc_occurrence_of(&*flag.name.clone());
|
||||
}
|
||||
matcher.inc_occurrence_of(&*flag.name.clone());
|
||||
|
||||
// Increment or create the group "args"
|
||||
self.groups_for_arg(&*flag.name).and_then(|vec| Some(matcher.inc_occurrences_of(&*vec)));
|
||||
self.groups_for_arg(flag.name).and_then(|vec| Some(matcher.inc_occurrences_of(&*vec)));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_arg<A>(&self, arg: &A, matcher: &mut ArgMatcher) -> ClapResult<()>
|
||||
where A: AnyArg<'a, 'b> + Display {
|
||||
// Ensure this arg isn't on the mutually excludes list
|
||||
if self.blacklist.contains(&arg.name()) {
|
||||
matcher.remove(&*arg.name());
|
||||
return Err(
|
||||
Error::argument_conflict(arg,
|
||||
self.blacklisted_from(&*arg.name(), &matcher),
|
||||
&*self.create_current_usage(matcher)));
|
||||
}
|
||||
|
||||
// Make sure this isn't one being added multiple times if it doesn't support it
|
||||
if matcher.contains(&*arg.name()) && !arg.is_set(ArgSettings::Multiple) {
|
||||
return Err(
|
||||
Error::unexpected_multiple_usage(arg, &*self.create_current_usage(matcher)));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// fn validate_arg<A>(&self, arg: &A, matcher: &mut ArgMatcher) -> ClapResult<()>
|
||||
// where A: AnyArg<'a, 'b> + Display {
|
||||
// debugln!("fn=validate_arg;");
|
||||
//
|
||||
// /*
|
||||
// Might not be required if we validate the blacklist later on as well too...
|
||||
//
|
||||
// debug!("Can we use '{}'...", arg.to_string());
|
||||
// // Ensure this arg isn't on the mutually excludes list
|
||||
// if self.blacklist.contains(&arg.name()) {
|
||||
// sdebugln!("No");
|
||||
// matcher.remove(&*arg.name());
|
||||
// return Err(
|
||||
// Error::argument_conflict(arg,
|
||||
// self.blacklisted_from(&*arg.name(), &matcher),
|
||||
// &*self.create_current_usage(matcher)));
|
||||
// }
|
||||
// sdebugln!("Yes");
|
||||
// */
|
||||
//
|
||||
// // Make sure this isn't one being added multiple times if it doesn't support it
|
||||
// if matcher.contains(&*arg.name()) && !arg.is_set(ArgSettings::Multiple) {
|
||||
// return Err(
|
||||
// Error::unexpected_multiple_usage(arg, &*self.create_current_usage(matcher)));
|
||||
// }
|
||||
//
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
|
||||
fn validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
|
||||
macro_rules! build_err {
|
||||
($me:ident, $name:ident, $matcher:ident) => ({
|
||||
($me:ident, $name:expr, $matcher:ident) => ({
|
||||
let c_with = $me.blacklisted_from($name, &$matcher);
|
||||
debugln!("'{:?}' conflicts with '{}'", c_with, $name);
|
||||
let usg = $me.create_current_usage($matcher);
|
||||
if let Some(f) = $me.flags.iter().filter(|f| &f.name == $name).next() {
|
||||
|
||||
if let Some(f) = $me.flags.iter().filter(|f| f.name == $name).next() {
|
||||
debugln!("It was a flag...");
|
||||
Error::argument_conflict(f, c_with, &*usg)
|
||||
} else if let Some(o) = $me.opts.iter()
|
||||
.filter(|o| &o.name == $name)
|
||||
.filter(|o| o.name == $name)
|
||||
.next() {
|
||||
debugln!("It was an option...");
|
||||
Error::argument_conflict(o, c_with, &*usg)
|
||||
} else {
|
||||
match $me.positionals.values()
|
||||
.filter(|p| p.name == *$name)
|
||||
.filter(|p| p.name == $name)
|
||||
.next() {
|
||||
Some(p) => Error::argument_conflict(p, c_with, &*usg),
|
||||
Some(p) => {
|
||||
debugln!("It was a positional...");
|
||||
Error::argument_conflict(p, c_with, &*usg)
|
||||
},
|
||||
None => panic!(INTERNAL_ERROR_MSG)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
for name in self.blacklist.iter() {
|
||||
if matcher.contains(name) {
|
||||
return Err(build_err!(self, name, matcher));
|
||||
} else if self.groups.contains_key(name) {
|
||||
for name in &self.blacklist {
|
||||
debugln!("Checking blacklisted name: {}", name);
|
||||
if self.groups.contains_key(name) {
|
||||
debugln!("groups contains it...");
|
||||
for n in self.arg_names_in_group(name) {
|
||||
if matcher.contains(&*n) {
|
||||
return Err(build_err!(self, name, matcher));
|
||||
debugln!("Checking arg '{}' in group...", n);
|
||||
if matcher.contains(&n) {
|
||||
debugln!("matcher contains it...");
|
||||
return Err(build_err!(self, n, matcher));
|
||||
}
|
||||
}
|
||||
} else if matcher.contains(name) {
|
||||
debugln!("matcher contains it...");
|
||||
return Err(build_err!(self, *name, matcher));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -268,9 +268,9 @@ pub enum AppSettings {
|
|||
/// let m = App::new("myprog")
|
||||
/// .setting(AppSettings::TrailingVarArg)
|
||||
/// .arg(Arg::from_usage("<cmd>... 'commands to run'"))
|
||||
/// .get_matches_from(vec!vec!["myprog", "some_command", "-r", "set"]);
|
||||
/// .get_matches_from(vec!["myprog", "some_command", "-r", "set"]);
|
||||
///
|
||||
/// assert_eq!(m.values_of("cmd").unwrap(), &["some_command", "-r", "set"]);
|
||||
/// assert_eq!(m.values_of("cmd").unwrap().collect::<Vec<_>>(), &["some_command", "-r", "set"]);
|
||||
/// ```
|
||||
TrailingVarArg,
|
||||
/// Specifies that the parser should not assume the first argument passed is the binary name.
|
||||
|
@ -289,36 +289,40 @@ pub enum AppSettings {
|
|||
/// .arg(Arg::from_usage("<cmd>... 'commands to run'"))
|
||||
/// .get_matches_from(vec!["some_command", "-r", "set"]);
|
||||
///
|
||||
/// assert_eq!(m.values_of("cmd").unwrap(), &["some_command", "-r", "set"]);
|
||||
/// assert_eq!(m.values_of("cmd").unwrap().collect::<Vec<_>>(), &["some_command", "-r", "set"]);
|
||||
/// ```
|
||||
NoBinaryName,
|
||||
/// Specifies that an unexpected argument positional arguments which would otherwise cause a
|
||||
/// `ErrorKind::UnexpectedArgument` error, should instead be treated as a subcommand in the
|
||||
/// `ErrorKind::UnknownArgument` error, should instead be treated as a subcommand in the
|
||||
/// `ArgMatches` struct.
|
||||
///
|
||||
/// **NOTE:** Use this setting with caution, as a truly unexpected argument (i.e. one that is
|
||||
/// **NOT** an external subcommand, will not cause an error, and you shoud inform the user
|
||||
/// appropriatly)
|
||||
/// *NOT* an external subcommand) will not cause an error and instead be treatd as a potential
|
||||
/// subcommand. You shoud inform the user appropriatly.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg, AppSettings};
|
||||
/// # use std::process::Command;
|
||||
/// // Assume there is a third party subcommand installed to $PATH named myprog-subcmd
|
||||
/// use std::process::{self, Command};
|
||||
///
|
||||
/// // Assume there is a third party subcommand named myprog-subcmd
|
||||
/// let m = App::new("myprog")
|
||||
/// .setting(AppSettings::AllowExternalSubcommands)
|
||||
/// .get_matches_from(vec!vec!["myprog", "subcmd", "--option", "value"]);
|
||||
/// .get_matches_from(vec!["myprog", "subcmd", "--option", "value"]);
|
||||
///
|
||||
/// // All trailing arguments will be stored under the subcommands sub-matches under a value
|
||||
/// // of their runtime name (in this case "subcmd")
|
||||
/// match m.subcommand() {
|
||||
/// ("", Some(sub_m)) => {
|
||||
/// let unk_subcmd = sub_m.subcommand_name().unwrap();
|
||||
/// let cmd = Command::new(format!("myprog-{}", unk_subcmd))
|
||||
/// .args(sub_m.values_of(unk_subcmd).unwrap());
|
||||
/// let exit_status = cmd.status().unwrap_or_else(|e| {
|
||||
/// (external, Some(ext_m)) => {
|
||||
/// let args: Vec<&str> = ext_m.values_of(external).unwrap().collect();
|
||||
/// let exit_status = Command::new(format!("myprog-{}", external))
|
||||
/// .args(&*args)
|
||||
/// .status()
|
||||
/// .unwrap_or_else(|e| {
|
||||
/// // Invalid subcommand. Here you would probably inform the user and list valid
|
||||
/// // subcommands for them to try...but in this example we just panic!
|
||||
/// panic!("failed to execute process: {}", e)
|
||||
/// process::exit(1);
|
||||
/// });
|
||||
/// },
|
||||
/// _ => unreachable!()
|
||||
|
|
|
@ -25,19 +25,15 @@ use usageparser::{UsageParser, UsageToken};
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # let matches = App::new("myprog")
|
||||
/// # .arg(
|
||||
/// # use clap::Arg;
|
||||
/// // Using the traditional builder pattern and setting each option manually
|
||||
/// Arg::with_name("config")
|
||||
/// let cfg = Arg::with_name("config")
|
||||
/// .short("c")
|
||||
/// .long("config")
|
||||
/// .takes_value(true)
|
||||
/// .help("Provides a config file to myprog")
|
||||
/// # ).arg(
|
||||
/// .help("Provides a config file to myprog");
|
||||
/// // Using a usage string (setting a similar argument to the one above)
|
||||
/// Arg::from_usage("-i --input=[input] 'Provides an input file to the program'")
|
||||
/// # ).get_matches();
|
||||
/// let input = Arg::from_usage("-i --input=[input] 'Provides an input file to the program'");
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct Arg<'a, 'b> where 'a: 'b {
|
||||
/// The unique name of the argument
|
||||
|
|
|
@ -334,7 +334,7 @@ mod test {
|
|||
.requires_all(&["r2", "r3"])
|
||||
.requires("r4");
|
||||
|
||||
let args = vec!["a1", "a2", "a3", "a4"];
|
||||
let args = vec!["a1", "a4", "a2", "a3"];
|
||||
let reqs = vec!["r1", "r2", "r3", "r4"];
|
||||
let confs = vec!["c1", "c2", "c3", "c4"];
|
||||
|
||||
|
|
|
@ -21,14 +21,14 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("speed")
|
||||
/// .possible_value("fast")
|
||||
/// .possible_value("slow"))
|
||||
/// .get_matches_from_safe(vec!vec!["myprog", "other"]);
|
||||
/// .get_matches_from_safe(vec!["myprog", "other"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err(), Error::InvalidValue);
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidValue);
|
||||
/// ```
|
||||
InvalidValue,
|
||||
/// Occurs when a user provides a flag, option, or argument which wasn't defined
|
||||
|
@ -36,10 +36,10 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::from_usage("--flag 'some flag'"))
|
||||
/// .get_matches_from_safe(vec!vec!["myprog", "--other"]);
|
||||
/// .get_matches_from_safe(vec!["myprog", "--other"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::UnknownArgument);
|
||||
/// ```
|
||||
|
@ -51,14 +51,14 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg, SubCommand};
|
||||
/// # use clap::{App, Arg, ErrorKind, SubCommand};
|
||||
/// let result = App::new("myprog")
|
||||
/// .subcommand(SubCommand::with_name("config")
|
||||
/// .about("Used for configuration")
|
||||
/// .arg(Arg::with_name("config_file")
|
||||
/// .help("The configuration file to use")
|
||||
/// .index(1)))
|
||||
/// .get_matches_from_safe(vec!vec!["myprog", "other"]);
|
||||
/// .get_matches_from_safe(vec!["myprog", "other"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidSubcommand);
|
||||
/// ```
|
||||
|
@ -68,7 +68,7 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .empty_values(false))
|
||||
|
@ -83,7 +83,7 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// fn is_numeric(val: String) -> Result<(), String> {
|
||||
/// match val.parse::<i64>() {
|
||||
/// Ok(..) => Ok(()),
|
||||
|
@ -94,7 +94,7 @@ pub enum ErrorKind {
|
|||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("num")
|
||||
/// .validator(is_numeric))
|
||||
/// .get_matches_from_safe(vec!vec!["myprog", "NotANumber"]);
|
||||
/// .get_matches_from_safe(vec!["myprog", "NotANumber"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::ValueValidation);
|
||||
/// ```
|
||||
|
@ -105,13 +105,13 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("some_opt")
|
||||
/// .long("opt")
|
||||
/// .takes_value(true)
|
||||
/// .max_values(2))
|
||||
/// .get_matches_from_safe(vec!vec!["myprog", "--opt", "too", "many", "values"]);
|
||||
/// .get_matches_from_safe(vec!["myprog", "--opt", "too", "many", "values"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::TooManyValues);
|
||||
/// ```
|
||||
|
@ -122,12 +122,12 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("some_opt")
|
||||
/// .long("opt")
|
||||
/// .min_values(3))
|
||||
/// .get_matches_from_safe(vec!vec!["myprog", "--opt", "too", "few"]);
|
||||
/// .get_matches_from_safe(vec!["myprog", "--opt", "too", "few"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::TooFewValues);
|
||||
/// ```
|
||||
|
@ -138,13 +138,13 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("some_opt")
|
||||
/// .long("opt")
|
||||
/// .takes_value(true)
|
||||
/// .number_of_values(2))
|
||||
/// .get_matches_from_safe(vec!vec!["myprog", "--opt", "wrong", "number", "of", "vals"]);
|
||||
/// .get_matches_from_safe(vec!["myprog", "--opt", "wrong", "number", "of", "vals"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
|
||||
/// ```
|
||||
|
@ -154,14 +154,14 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("debug")
|
||||
/// .long("debug")
|
||||
/// .conflicts_with("color"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .long("color"))
|
||||
/// .get_matches_from_safe(vec!vec!["myprog", "--debug", "--color"]);
|
||||
/// .get_matches_from_safe(vec!["myprog", "--debug", "--color"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::ArgumentConflict);
|
||||
/// ```
|
||||
|
@ -171,7 +171,7 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("debug")
|
||||
/// .required(true))
|
||||
|
@ -186,7 +186,7 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg, AppSettings, SubCommand};
|
||||
/// # use clap::{App, Arg, AppSettings, ErrorKind, SubCommand};
|
||||
/// let result = App::new("myprog")
|
||||
/// .setting(AppSettings::SubcommandRequired)
|
||||
/// .subcommand(SubCommand::with_name("config")
|
||||
|
@ -204,7 +204,7 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg, AppSettings, SubCommand};
|
||||
/// # use clap::{App, Arg, AppSettings, ErrorKind, SubCommand};
|
||||
/// let result = App::new("myprog")
|
||||
/// .setting(AppSettings::ArgRequiredElseHelp)
|
||||
/// .subcommand(SubCommand::with_name("config")
|
||||
|
@ -222,11 +222,11 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("debug")
|
||||
/// .multiple(false))
|
||||
/// .get_matches_from_safe(vec!vec!["myprog", "--debug", "--debug"]);
|
||||
/// .get_matches_from_safe(vec!["myprog", "--debug", "--debug"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage);
|
||||
/// ```
|
||||
|
@ -244,7 +244,7 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// # use std::os::unix::ffi::OsStringExt;
|
||||
/// # use std::ffi::OsString;
|
||||
/// let result = App::new("myprog")
|
||||
|
@ -267,12 +267,11 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::ErrorType;
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .get_matches_from_safe(vec!vec!["myprog", "--help"]);
|
||||
/// .get_matches_from_safe(vec!["myprog", "--help"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorType::HelpDisplayed);
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::HelpDisplayed);
|
||||
/// ```
|
||||
HelpDisplayed,
|
||||
/// Not a true "error" as it means `--version` or similar was used. The message will be sent
|
||||
|
@ -281,14 +280,17 @@ pub enum ErrorKind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg};
|
||||
/// # use clap::ErrorType;
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .get_matches_from_safe(vec!["myprog", "--version"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorType::VersionDisplayed);
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::VersionDisplayed);
|
||||
/// ```
|
||||
VersionDisplayed,
|
||||
/// Occurs when using the `value_t!` and `values_t!` macros to convert an argument value into
|
||||
/// type `T`, but the argument you requested wasn't used. I.e. you asked for an argument with
|
||||
/// name `config` to be converted, but `config` wasn't used by the user.
|
||||
ArgumentNotFound,
|
||||
/// Represents an I/O error, typically white writing to stderr or stdout
|
||||
Io,
|
||||
/// Represents an Rust Display Format error, typically white writing to stderr or stdout
|
||||
|
@ -612,6 +614,18 @@ impl Error {
|
|||
info: Some(vec![a]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn argument_not_found<A>(arg: A) -> Self
|
||||
where A: Into<String>,
|
||||
{
|
||||
let a = arg.into();
|
||||
Error {
|
||||
message: format!("{} The argument '{}' wasn't found", Format::Error("error:"), a.clone()),
|
||||
kind: ErrorKind::ArgumentNotFound,
|
||||
info: Some(vec![a]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StdError for Error {
|
||||
|
|
|
@ -291,7 +291,7 @@
|
|||
//! the `from_usage`
|
||||
//! methods and the performance of the Builder Pattern.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! ```ignore
|
||||
//! // (Full example with detailed comments in examples/01c_quick_example.rs)
|
||||
//! //
|
||||
//! // This example demonstrates clap's "usage strings" method of creating
|
||||
|
|
174
src/macros.rs
174
src/macros.rs
|
@ -129,9 +129,9 @@ macro_rules! for_match {
|
|||
($it:ident, $($p:pat => $($e:expr);+),*) => {
|
||||
for i in $it {
|
||||
match i {
|
||||
$(
|
||||
$p => { $($e)+ }
|
||||
)*
|
||||
$(
|
||||
$p => { $($e)+ }
|
||||
)*
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -147,6 +147,47 @@ macro_rules! for_match {
|
|||
/// **NOTE:** Be cautious, as since this a macro invocation it's not exactly like
|
||||
/// standard syntax.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #[macro_use]
|
||||
/// # extern crate clap;
|
||||
/// # use clap::App;
|
||||
/// # fn main() {
|
||||
/// let matches = App::new("myapp")
|
||||
/// .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'")
|
||||
/// .get_matches();
|
||||
///
|
||||
/// let len = value_t!(matches.value_of("length"), u32).unwrap_or_else(|e| e.exit());
|
||||
/// let also_len = value_t!(matches, "length", u32).unwrap_or_else(|e| e.exit());
|
||||
///
|
||||
/// println!("{} + 2: {}", len, len + 2);
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! value_t {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
value_t!($m.value_of($v), $t)
|
||||
};
|
||||
($m:ident.value_of($v:expr), $t:ty) => {
|
||||
if let Some(v) = $m.value_of($v) {
|
||||
match v.parse::<$t>() {
|
||||
Ok(val) => Ok(val),
|
||||
Err(_) =>
|
||||
Err(::clap::Error::value_validation(
|
||||
format!("The argument '{}' isn't a valid value", v))),
|
||||
}
|
||||
} else {
|
||||
Err(::clap::Error::argument_not_found($v))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr` or
|
||||
/// exiting upon error.
|
||||
///
|
||||
/// **NOTE:** This macro is for backwards compatibility sake. Prefer
|
||||
/// `value_t!(/* ... */).unwrap_or_else(|e| e.exit())`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -158,41 +199,35 @@ macro_rules! for_match {
|
|||
/// let matches = App::new("myapp")
|
||||
/// .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'")
|
||||
/// .get_matches();
|
||||
/// let len = value_t!(matches.value_of("length"), u32)
|
||||
/// .unwrap_or_else(|e|{
|
||||
/// println!("{}",e);
|
||||
/// std::process::exit(1)
|
||||
/// });
|
||||
///
|
||||
/// let len = value_t_or_exit!(matches.value_of("length"), u32);
|
||||
/// let also_len = value_t_or_exit!(matches, "length", u32);
|
||||
///
|
||||
/// println!("{} + 2: {}", len, len + 2);
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! value_t {
|
||||
(@callback $c:ident $m:ident.value_of($v:expr), $t:ty) => {
|
||||
$c!($m.value_of($e), $t);
|
||||
};
|
||||
macro_rules! value_t_or_exit {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
value_t!(@callback value_t $m.value_of($v), $t)
|
||||
value_t!($m.value_of($v), $t)
|
||||
};
|
||||
($m:ident.value_of($v:expr), $t:ty) => {
|
||||
if let Some(v) = $m.value_of($v) {
|
||||
match v.parse::<$t>() {
|
||||
Ok(val) => Ok(val),
|
||||
Ok(val) => val,
|
||||
Err(_) =>
|
||||
Err(::clap::Error::value_validation(
|
||||
format!("The argument '{}' isn't a valid value", v))),
|
||||
::clap::Error::value_validation(
|
||||
format!("The argument '{}' isn't a valid value", v)).exit(),
|
||||
}
|
||||
} else {
|
||||
Err(::clap::Error::value_validation(format!("The argument '{}' was not found", $v)))
|
||||
::clap::Error::argument_not_found($v).exit()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr`
|
||||
/// This macro returns a `Result<T,String>` which allows you as the developer to decide
|
||||
/// what you'd like to do on a failed parse. There are two types of errors, parse failures
|
||||
/// and those where the argument wasn't present (such as a non-required argument).
|
||||
/// This macro returns a `clap::Result<T>` (`Result<T, clap::Error>`) which allows you as the
|
||||
/// developer to decide what you'd like to do on a failed parse.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -204,47 +239,92 @@ macro_rules! value_t {
|
|||
/// let matches = App::new("myapp")
|
||||
/// .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'")
|
||||
/// .get_matches();
|
||||
/// for v in value_t!(matches.values_of("seq"), u32)
|
||||
/// .unwrap_or_else(|e|{
|
||||
/// println!("{}",e);
|
||||
/// std::process::exit(1)
|
||||
/// }) {
|
||||
///
|
||||
/// let vals = values_t!(matches.values_of("seq"), u32).unwrap_or_else(|e| e.exit());
|
||||
/// for v in &vals {
|
||||
/// println!("{} + 2: {}", v, v + 2);
|
||||
/// }
|
||||
///
|
||||
/// let vals = values_t!(matches, "seq", u32).unwrap_or_else(|e| e.exit());
|
||||
/// for v in &vals {
|
||||
/// println!("{} + 2: {}", v, v + 2);
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! values_t {
|
||||
($m:expr, $v:expr, $t:ty) => {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
values_t!($m.values_of($v), $t)
|
||||
};
|
||||
($m:ident.values_of($v:expr), $t:ty) => {
|
||||
match $m {
|
||||
Some(ref v) => values_t!(v, $t),
|
||||
None =>
|
||||
Err(::clap::Error::value_validation(format!("The argument was not found", v))),
|
||||
}
|
||||
};
|
||||
($v:ident, $t:ty) => {
|
||||
let mut tmp = Vec::with_capacity($v.len());
|
||||
let mut err = None;
|
||||
for pv in &$v {
|
||||
match pv.parse::<$t>() {
|
||||
Ok(rv) => tmp.push(rv),
|
||||
Err(e) => {
|
||||
err = Some(::clap::Error::value_validation(
|
||||
format!("The argument '{}' isn't a valid value", v)));
|
||||
break
|
||||
if let Some(vals) = $m.values_of($v) {
|
||||
let mut tmp = vec![];
|
||||
let mut err = None;
|
||||
for pv in vals {
|
||||
match pv.parse::<$t>() {
|
||||
Ok(rv) => tmp.push(rv),
|
||||
Err(..) => {
|
||||
err = Some(::clap::Error::value_validation(
|
||||
format!("The argument '{}' isn't a valid value", pv)));
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
match err {
|
||||
Some(e) => Err(e),
|
||||
None => Ok(tmp)
|
||||
match err {
|
||||
Some(e) => Err(e),
|
||||
None => Ok(tmp),
|
||||
}
|
||||
} else {
|
||||
Err(::clap::Error::argument_not_found($v))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr` or
|
||||
/// exiting upon error.
|
||||
///
|
||||
/// **NOTE:** This macro is for backwards compatibility sake. Prefer
|
||||
/// `value_t!(/* ... */).unwrap_or_else(|e| e.exit())`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #[macro_use]
|
||||
/// # extern crate clap;
|
||||
/// # use clap::App;
|
||||
/// # fn main() {
|
||||
/// let matches = App::new("myapp")
|
||||
/// .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'")
|
||||
/// .get_matches();
|
||||
///
|
||||
/// let vals = values_t_or_exit!(matches.values_of("seq"), u32);
|
||||
/// for v in &vals {
|
||||
/// println!("{} + 2: {}", v, v + 2);
|
||||
/// }
|
||||
///
|
||||
/// // type for example only
|
||||
/// let vals: Vec<u32> = values_t_or_exit!(matches, "seq", u32);
|
||||
/// for v in &vals {
|
||||
/// println!("{} + 2: {}", v, v + 2);
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! values_t_or_exit {
|
||||
($m:ident, $v:expr, $t:ty) => {
|
||||
values_t_or_exit!($m.values_of($v), $t)
|
||||
};
|
||||
($m:ident.values_of($v:expr), $t:ty) => {
|
||||
if let Some(vals) = $m.values_of($v) {
|
||||
vals.map(|v| v.parse::<$t>().unwrap_or_else(|_|{
|
||||
::clap::Error::value_validation(
|
||||
format!("One or more arguments aren't valid values")).exit()
|
||||
})).collect::<Vec<$t>>()
|
||||
} else {
|
||||
::clap::Error::argument_not_found($v).exit()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Convenience macro to generate more complete enums with variants to be used as a type when
|
||||
/// parsing arguments. This enum also provides a `variants()` function which can be used to retrieve a
|
||||
|
@ -277,7 +357,7 @@ macro_rules! values_t {
|
|||
/// let m = App::new("app")
|
||||
/// .arg_from_usage("<foo> 'the foo'")
|
||||
/// .get_matches();
|
||||
/// let f = value_t_or_exit!(m.value_of("foo"), Foo);
|
||||
/// let f = value_t!(m, "foo", Foo).unwrap_or_else(|e| e.exit());
|
||||
///
|
||||
/// // Use f like any other Foo variant...
|
||||
/// }
|
||||
|
|
|
@ -31,7 +31,7 @@ impl OsStrExt2 for OsStr {
|
|||
fn split_at_byte(&self, byte: u8) -> (&OsStr, &OsStr) {
|
||||
let mut i = 0;
|
||||
for b in self.as_bytes() {
|
||||
if b == &byte { return (OsStr::from_bytes(&self.as_bytes()[..i]), OsStr::from_bytes(&self.as_bytes()[i..])); }
|
||||
if b == &byte { return (OsStr::from_bytes(&self.as_bytes()[..i]), OsStr::from_bytes(&self.as_bytes()[i+1..])); }
|
||||
i += 1;
|
||||
}
|
||||
(&*self, OsStr::from_bytes(&self.as_bytes()[self.len()..self.len()]))
|
||||
|
|
|
@ -18,12 +18,14 @@ fn required_group_missing_arg() {
|
|||
|
||||
#[test]
|
||||
fn group_single_value() {
|
||||
let m = App::new("group")
|
||||
let r = App::new("group")
|
||||
.args_from_usage("-f, --flag 'some flag'
|
||||
-c, --color [color] 'some option'")
|
||||
.group(ArgGroup::with_name("grp")
|
||||
.args(&["flag", "color"]))
|
||||
.get_matches_from(vec!["myprog", "-c", "blue"]);
|
||||
.get_matches_from_safe(vec!["myprog", "-c", "blue"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("grp"));
|
||||
assert_eq!(m.value_of("grp").unwrap(), "blue");
|
||||
}
|
||||
|
@ -68,12 +70,14 @@ fn group_reqired_flags_empty() {
|
|||
|
||||
#[test]
|
||||
fn group_multi_value_single_arg() {
|
||||
let m = App::new("group")
|
||||
let r = App::new("group")
|
||||
.args_from_usage("-f, --flag 'some flag'
|
||||
-c, --color [color]... 'some option'")
|
||||
.group(ArgGroup::with_name("grp")
|
||||
.args(&["flag", "color"]))
|
||||
.get_matches_from(vec!["myprog", "-c", "blue", "red", "green"]);
|
||||
.get_matches_from_safe(vec!["myprog", "-c", "blue", "red", "green"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("grp"));
|
||||
assert_eq!(m.values_of("grp").unwrap().collect::<Vec<_>>(), &["blue", "red", "green"]);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ fn multiple_values_of_option_short() {
|
|||
|
||||
assert!(m.is_present("option"));
|
||||
assert_eq!(m.occurrences_of("option"), 3);
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]));
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -70,7 +70,7 @@ fn multiple_values_of_option_mixed() {
|
|||
|
||||
assert!(m.is_present("option"));
|
||||
assert_eq!(m.occurrences_of("option"), 4);
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3", "val4"]));
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3", "val4"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -94,7 +94,7 @@ fn multiple_values_of_option_exact_exact() {
|
|||
|
||||
assert!(m.is_present("option"));
|
||||
assert_eq!(m.occurrences_of("option"), 3);
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]));
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -113,7 +113,7 @@ fn multiple_values_of_option_exact_less() {
|
|||
]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumValues);
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -134,7 +134,7 @@ fn multiple_values_of_option_exact_more() {
|
|||
]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumValues);
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -157,7 +157,7 @@ fn multiple_values_of_option_min_exact() {
|
|||
|
||||
assert!(m.is_present("option"));
|
||||
assert_eq!(m.occurrences_of("option"), 3);
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]));
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -199,7 +199,7 @@ fn multiple_values_of_option_min_more() {
|
|||
|
||||
assert!(m.is_present("option"));
|
||||
assert_eq!(m.occurrences_of("option"), 4);
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3", "val4"]));
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3", "val4"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -222,7 +222,7 @@ fn multiple_values_of_option_max_exact() {
|
|||
|
||||
assert!(m.is_present("option"));
|
||||
assert_eq!(m.occurrences_of("option"), 3);
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]));
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -244,7 +244,7 @@ fn multiple_values_of_option_max_less() {
|
|||
|
||||
assert!(m.is_present("option"));
|
||||
assert_eq!(m.occurrences_of("option"), 2);
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2"]));
|
||||
assert_eq!(m.values_of("option").unwrap().collect::<Vec<_>>(), vec!["val1", "val2"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -281,7 +281,7 @@ fn multiple_values_of_positional() {
|
|||
|
||||
assert!(m.is_present("pos"));
|
||||
assert_eq!(m.occurrences_of("pos"), 3);
|
||||
assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]));
|
||||
assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -299,7 +299,7 @@ fn multiple_values_of_positional_exact_exact() {
|
|||
|
||||
assert!(m.is_present("pos"));
|
||||
assert_eq!(m.occurrences_of("pos"), 3);
|
||||
assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]));
|
||||
assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -313,7 +313,7 @@ fn multiple_values_of_positional_exact_less() {
|
|||
.get_matches_from_safe(vec!["myprog", "val1", "val2"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumValues);
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -327,7 +327,7 @@ fn multiple_values_of_positional_exact_more() {
|
|||
.get_matches_from_safe(vec!["myprog", "val1", "val2", "val3", "val4"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumValues);
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -344,7 +344,7 @@ fn multiple_values_of_positional_min_exact() {
|
|||
|
||||
assert!(m.is_present("pos"));
|
||||
assert_eq!(m.occurrences_of("pos"), 3);
|
||||
assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]));
|
||||
assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -374,7 +374,7 @@ fn multiple_values_of_positional_min_more() {
|
|||
|
||||
assert!(m.is_present("pos"));
|
||||
assert_eq!(m.occurrences_of("pos"), 4);
|
||||
assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3", "val4"]));
|
||||
assert_eq!(m.values_of("pos").unwrap().collect::<Vec<_>>(), vec!["val1", "val2", "val3", "val4"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -4,12 +4,14 @@ use clap::{App, Arg};
|
|||
|
||||
#[test]
|
||||
fn opts_using_short() {
|
||||
let m = App::new("opts")
|
||||
let r = App::new("opts")
|
||||
.args(&mut [
|
||||
Arg::from_usage("-f [flag] 'some flag'"),
|
||||
Arg::from_usage("-c [color] 'some other flag'")
|
||||
])
|
||||
.get_matches_from(vec!["myprog", "-f", "some", "-c", "other"]);
|
||||
.get_matches_from_safe(vec!["myprog", "-f", "some", "-c", "other"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("flag"));
|
||||
assert_eq!(m.value_of("flag").unwrap(), "some");
|
||||
assert!(m.is_present("color"));
|
||||
|
@ -18,12 +20,14 @@ fn opts_using_short() {
|
|||
|
||||
#[test]
|
||||
fn opts_using_long_space() {
|
||||
let m = App::new("opts")
|
||||
let r = App::new("opts")
|
||||
.args(&[
|
||||
Arg::from_usage("--flag [flag] 'some flag'"),
|
||||
Arg::from_usage("--color [color] 'some other flag'")
|
||||
])
|
||||
.get_matches_from(vec!["myprog", "--flag", "some", "--color", "other"]);
|
||||
.get_matches_from_safe(vec!["myprog", "--flag", "some", "--color", "other"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("flag"));
|
||||
assert_eq!(m.value_of("flag").unwrap(), "some");
|
||||
assert!(m.is_present("color"));
|
||||
|
@ -32,12 +36,14 @@ fn opts_using_long_space() {
|
|||
|
||||
#[test]
|
||||
fn opts_using_long_equals() {
|
||||
let m = App::new("opts")
|
||||
let r = App::new("opts")
|
||||
.args(&[
|
||||
Arg::from_usage("--flag [flag] 'some flag'"),
|
||||
Arg::from_usage("--color [color] 'some other flag'")
|
||||
])
|
||||
.get_matches_from(vec!["myprog", "--flag=some", "--color=other"]);
|
||||
.get_matches_from_safe(vec!["myprog", "--flag=some", "--color=other"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("flag"));
|
||||
assert_eq!(m.value_of("flag").unwrap(), "some");
|
||||
assert!(m.is_present("color"));
|
||||
|
@ -46,23 +52,30 @@ fn opts_using_long_equals() {
|
|||
|
||||
#[test]
|
||||
fn opts_using_mixed() {
|
||||
let m = App::new("opts")
|
||||
let r = App::new("opts")
|
||||
.args(&[
|
||||
Arg::from_usage("-f, --flag [flag] 'some flag'"),
|
||||
Arg::from_usage("-c, --color [color] 'some other flag'")
|
||||
])
|
||||
.get_matches_from(vec!["myprog", "-f", "some", "--color", "other"]);
|
||||
assert!(m.is_present("flag"));
|
||||
assert_eq!(m.value_of("flag").unwrap(), "some");
|
||||
assert!(m.is_present("color"));
|
||||
assert_eq!(m.value_of("color").unwrap(), "other");
|
||||
|
||||
let m = App::new("opts")
|
||||
.args(&[
|
||||
Arg::from_usage("-f, --flag [flag] 'some flag'"),
|
||||
Arg::from_usage("-c, --color [color] 'some other flag'")
|
||||
])
|
||||
.get_matches_from(vec!["myprog", "--flag=some", "-c", "other"]);
|
||||
.get_matches_from_safe(vec!["myprog", "-f", "some", "--color", "other"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("flag"));
|
||||
assert_eq!(m.value_of("flag").unwrap(), "some");
|
||||
assert!(m.is_present("color"));
|
||||
assert_eq!(m.value_of("color").unwrap(), "other");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opts_using_mixed2() {
|
||||
let r = App::new("opts")
|
||||
.args(&[
|
||||
Arg::from_usage("-f, --flag [flag] 'some flag'"),
|
||||
Arg::from_usage("-c, --color [color] 'some other flag'")
|
||||
])
|
||||
.get_matches_from_safe(vec!["myprog", "--flag=some", "-c", "other"]);
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("flag"));
|
||||
assert_eq!(m.value_of("flag").unwrap(), "some");
|
||||
assert!(m.is_present("color"));
|
||||
|
|
|
@ -13,7 +13,7 @@ fn positional() {
|
|||
.get_matches_from(vec!["myprog", "-f", "test"]);
|
||||
assert!(m.is_present("positional"));
|
||||
assert!(m.is_present("flag"));
|
||||
assert_eq!(m.value_of("positional"), "test");
|
||||
assert_eq!(m.value_of("positional"), Some("test"));
|
||||
|
||||
let m = App::new("positional")
|
||||
.args(&[
|
||||
|
@ -24,7 +24,7 @@ fn positional() {
|
|||
.get_matches_from(vec!["myprog", "test", "--flag"]);
|
||||
assert!(m.is_present("positional"));
|
||||
assert!(m.is_present("flag"));
|
||||
assert_eq!(m.value_of("positional"), "test");
|
||||
assert_eq!(m.value_of("positional"), Some("test"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -65,5 +65,5 @@ fn positional_multiple_2() {
|
|||
.get_matches_from_safe(vec!["myprog", "-f", "test1", "test2", "test3"]);
|
||||
assert!(result.is_err());
|
||||
let err = result.err().unwrap();
|
||||
assert_eq!(err.kind, ErrorKind::UnexpectedArgument);
|
||||
assert_eq!(err.kind, ErrorKind::UnknownArgument);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ extern crate clap;
|
|||
|
||||
use std::ffi::OsString;
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
use clap::{App, Arg, ErrorKind};
|
||||
use clap::{App, Arg, AppSettings, ErrorKind};
|
||||
|
||||
#[test]
|
||||
fn invalid_unicode_safe() {
|
||||
|
@ -20,11 +20,11 @@ fn invalid_unicode_safe() {
|
|||
|
||||
#[test]
|
||||
fn invalid_unicode_lossy() {
|
||||
App::new("bad_unicode")
|
||||
let m = App::new("bad_unicode")
|
||||
.arg(Arg::from_usage("<arg> 'some arg'"))
|
||||
.setting(AppSetting::AllowInvalidUtf8)
|
||||
.get_matches_from_safe(vec![OsString::from_vec(vec![0x20]),
|
||||
OsString::from_vec(vec![0xe9])]) {
|
||||
.setting(AppSettings::AllowInvalidUtf8)
|
||||
.get_matches_from(vec![OsString::from_vec(vec![0x20]),
|
||||
OsString::from_vec(vec![0xe9])]);
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.value_of("arg").unwrap(), "\u{FFFD}");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue