style: rustfmt run

This commit is contained in:
Kevin K 2015-11-09 02:22:12 -05:00
parent c6858f7875
commit bf4d8417b8
4 changed files with 340 additions and 286 deletions

View file

@ -1,2 +1,4 @@
format_strings = false
reorder_imports = true
chain_overflow_last = false
same_line_if_else = true

View file

@ -18,7 +18,7 @@ use fmt::Format;
use super::settings::{AppFlags, AppSettings};
use super::suggestions::{DidYouMeanMessageStyle, did_you_mean};
use super::errors::{ClapError, ClapResult, ClapErrorType, error_builder};
use super::errors::{ClapError, ClapErrorType, ClapResult, error_builder};
const INTERNAL_ERROR_MSG: &'static str = "Fatal internal error. Please consider filing a bug \
@ -732,8 +732,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
// actually adds the arguments
fn add_arg(&mut self, a: Arg<'ar, 'ar, 'ar, 'ar, 'ar, 'ar>) {
if self.flags.iter().any(|f| &f.name == &a.name) ||
self.opts.iter().any(|o| o.name == a.name) ||
self.positionals.values().any(|p| p.name == a.name) {
self.opts.iter().any(|o| o.name == a.name) ||
self.positionals.values().any(|p| p.name == a.name) {
panic!("Non-unique argument name: {} is already in use", a.name);
}
if let Some(grp) = a.group {
@ -1042,7 +1042,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
let reqs = self.required.iter().map(|n| *n).collect::<Vec<_>>();
let req_strings = self.get_required_from(&reqs, None);
let req_string = req_strings.iter()
.fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]);
.fold(String::new(), |a, s| a + &format!(" {}", s)[..]);
if !self.flags.is_empty() && !self.settings.is_set(&AppSettings::UnifiedHelpMessage) {
usage.push_str(" [FLAGS]");
@ -1086,7 +1086,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
Ok(usage)
}
// Creates a context aware usage string, or "smart usage" from currently used args, and
// Creates a context aware usage string, or "smart usage" from currently used
// args, and
// requirements
fn usage_from_matches(&self, usage: &mut String, matches: &[&'ar str]) -> ClapResult<()> {
use std::fmt::Write;
@ -1099,11 +1100,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
let r_string = reqs.iter().fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]);
try!(write!(usage,
"{}{}",
self.usage
.as_ref()
.unwrap_or(self.bin_name.as_ref().unwrap_or(&self.name)),
r_string));
"{}{}",
self.usage
.as_ref()
.unwrap_or(self.bin_name.as_ref().unwrap_or(&self.name)),
r_string));
if self.settings.is_set(&AppSettings::SubcommandRequired) {
try!(write!(usage, " <SUBCOMMAND>"));
}
@ -1203,7 +1204,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
}
let tab = " ";
let longest = if !unified_help || longest_opt == 0 { longest_flag } else { longest_opt };
let longest = if !unified_help || longest_opt == 0 {
longest_flag
} else {
longest_opt
};
if unified_help && (flags || opts) {
try!(write!(w, "\nOPTIONS:\n"));
let mut combined = BTreeMap::new();
@ -1223,36 +1228,40 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
} else {
if flags {
try!(write!(w, "\nFLAGS:\n"));
for (_, f) in self.flags.iter()
for (_, f) in self.flags
.iter()
.filter(|f| !f.settings.is_set(&ArgSettings::Hidden))
.map(|f| (f.name, f))
.collect::<BTreeMap<_,_>>() {
.collect::<BTreeMap<_, _>>() {
try!(f.write_help(w, tab, longest));
}
}
if opts {
try!(write!(w, "\nOPTIONS:\n"));
for (_, o) in self.opts.iter()
.filter(|o| !o.settings.is_set(&ArgSettings::Hidden))
.map(|o| (o.name, o))
.collect::<BTreeMap<_,_>>() {
for (_, o) in self.opts
.iter()
.filter(|o| !o.settings.is_set(&ArgSettings::Hidden))
.map(|o| (o.name, o))
.collect::<BTreeMap<_, _>>() {
try!(o.write_help(w, tab, longest_opt));
}
}
}
if pos {
try!(write!(w, "\nARGS:\n"));
for v in self.positionals.values()
.filter(|p| !p.settings.is_set(&ArgSettings::Hidden)) {
for v in self.positionals
.values()
.filter(|p| !p.settings.is_set(&ArgSettings::Hidden)) {
try!(v.write_help(w, tab, longest_pos));
}
}
if subcmds {
try!(write!(w, "\nSUBCOMMANDS:\n"));
for (name, sc) in self.subcommands.iter()
.filter(|s| !s.settings.is_set(&AppSettings::Hidden))
.map(|s| (s.name_slice, s))
.collect::<BTreeMap<_,_>>() {
for (name, sc) in self.subcommands
.iter()
.filter(|s| !s.settings.is_set(&AppSettings::Hidden))
.map(|s| (s.name_slice, s))
.collect::<BTreeMap<_, _>>() {
try!(write!(w, "{}{}", tab, name));
write_spaces!((longest_sc + 4) - (name.len()), w);
if let Some(a) = sc.about {
@ -1501,9 +1510,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
/// .get_matches_from_safe(arg_vec)
/// .unwrap_or_else( |e| { panic!("An error occurs: {}", e) });
/// ```
pub fn get_matches_from_safe_lossy<I, T>(mut self,
itr: I)
-> ClapResult<ArgMatches<'ar, 'ar>>
pub fn get_matches_from_safe_lossy<I, T>(mut self, itr: I) -> ClapResult<ArgMatches<'ar, 'ar>>
where I: IntoIterator<Item = T>,
T: AsRef<OsStr>
{
@ -1537,9 +1544,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
/// let matches = app.get_matches_from_safe_borrow(arg_vec)
/// .unwrap_or_else( |e| { panic!("An error occurs: {}", e) });
/// ```
pub fn get_matches_from_safe_borrow<I, T>(&mut self,
itr: I)
-> ClapResult<ArgMatches<'ar, 'ar>>
pub fn get_matches_from_safe_borrow<I, T>(&mut self, itr: I) -> ClapResult<ArgMatches<'ar, 'ar>>
where I: IntoIterator<Item = T>,
T: AsRef<OsStr>
{
@ -1651,7 +1656,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
None => {
if !lossy {
return Err(
error_builder::InvalidUnicode(&*try!(self.create_current_usage(matches)))
error_builder::InvalidUnicode(
&*try!(self.create_current_usage(matches)))
);
}
arg.as_ref().to_string_lossy()
@ -1677,7 +1683,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
// pos_only is determined later, and set true when a user uses the Unix
// standard of
// '--' to mean only positionals follow
if !pos_only && !new_arg && !self.subcommands.iter().any(|s| s.name_slice == arg_slice) {
if !pos_only && !new_arg &&
!self.subcommands.iter().any(|s| s.name_slice == arg_slice) {
// Check to see if parsing a value from an option
if let Some(nvo) = needs_val_of {
// get the OptBuilder so we can check the settings
@ -1814,9 +1821,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
}
subcmd_name = Some(arg_slice.to_owned());
break;
} else if let Some(candidate_subcommand) = did_you_mean(
arg_slice,
self.subcommands.iter().map(|s| &s.name)) {
} else if let Some(candidate_subcommand) = did_you_mean(arg_slice,
self.subcommands
.iter()
.map(|s| &s.name)) {
return Err(error_builder::InvalidSubcommand(
arg_slice,
candidate_subcommand,
@ -1987,13 +1995,13 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
try!(self.create_current_usage(matches))));
}
} else {
return Err(error_builder::EmptyValue(
&*format!("{}", self.positionals.values()
.filter(|p| &p.name == a)
.next()
.unwrap()),
&*try!(self.create_current_usage(matches))
));
return Err(error_builder::EmptyValue(&*format!("{}",
self.positionals
.values()
.filter(|p| &p.name == a)
.next()
.unwrap()),
&*try!(self.create_current_usage(matches))));
}
}
@ -2024,9 +2032,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
}
}
mid_string.push_str(" ");
if let Some(ref mut sc) = self.subcommands.iter_mut()
.filter(|s| s.name_slice == &sc_name)
.next() {
if let Some(ref mut sc) = self.subcommands
.iter_mut()
.filter(|s| s.name_slice == &sc_name)
.next() {
let mut new_matches = ArgMatches::new();
// bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by
// a space
@ -2056,16 +2065,14 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
}
} else if self.settings.is_set(&AppSettings::SubcommandRequired) {
let bn = self.bin_name.as_ref().unwrap_or(&self.name);
return Err(error_builder::MissingSubcommand(
bn,
&try!(self.create_current_usage(matches))));
return Err(error_builder::MissingSubcommand(bn,
&try!(self.create_current_usage(matches))));
} else if self.settings.is_set(&AppSettings::SubcommandRequiredElseHelp) {
let mut out = vec![];
try!(self.write_help(&mut out));
return Err(
ClapError {
error: String::from_utf8_lossy(&*out).into_owned(),
error_type: ClapErrorType::MissingArgumentOrSubcommand,
return Err(ClapError {
error: String::from_utf8_lossy(&*out).into_owned(),
error_type: ClapErrorType::MissingArgumentOrSubcommand,
});
}
if (!self.settings.is_set(&AppSettings::SubcommandsNegateReqs) ||
@ -2081,17 +2088,18 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
self.settings.is_set(&AppSettings::ArgRequiredElseHelp) {
let mut out = vec![];
try!(self.write_help(&mut out));
return Err(
ClapError {
error: String::from_utf8_lossy(&*out).into_owned(),
error_type: ClapErrorType::MissingArgumentOrSubcommand,
return Err(ClapError {
error: String::from_utf8_lossy(&*out).into_owned(),
error_type: ClapErrorType::MissingArgumentOrSubcommand,
});
}
Ok(())
}
// basically re-implements ClapError::exit except it checks if we should wait for input before
// exiting since ClapError doesn't have that info and the error message must be printed before
// basically re-implements ClapError::exit except it checks if we should wait
// for input before
// exiting since ClapError doesn't have that info and the error message must be
// printed before
// exiting
fn maybe_wait_for_exit(&self, e: ClapError) -> ! {
if e.use_stderr() {
@ -2122,21 +2130,25 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
}
fn create_current_usage(&self, matches: &ArgMatches) -> ClapResult<String> {
self.create_usage(
&matches.args.keys()
.filter(|k| {
if let Some(o) = self.opts.iter().filter(|o| &&o.name == k).next() {
!o.settings.is_set(&ArgSettings::Required)
} else if let Some(p) = self.positionals.values()
.filter(|p| &&p.name == k)
.next() {
!p.settings.is_set(&ArgSettings::Required)
} else {
true
}
})
.map(|k| *k)
.collect::<Vec<_>>())
self.create_usage(&matches.args
.keys()
.filter(|k| {
if let Some(o) = self.opts
.iter()
.filter(|o| &&o.name == k)
.next() {
!o.settings.is_set(&ArgSettings::Required)
} else if let Some(p) = self.positionals
.values()
.filter(|p| &&p.name == k)
.next() {
!p.settings.is_set(&ArgSettings::Required)
} else {
true
}
})
.map(|k| *k)
.collect::<Vec<_>>())
}
fn groups_for_arg(&self, name: &str) -> Option<Vec<&'ar str>> {
@ -2170,9 +2182,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
} else if self.groups.contains_key(n) {
g_vec.push(*n);
} else {
if let Some(p) = self.positionals.values()
.filter(|p| &p.name == n)
.next() {
if let Some(p) = self.positionals
.values()
.filter(|p| &p.name == n)
.next() {
args.push(p.to_string());
}
}
@ -2225,8 +2238,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
fn get_required_from(&self,
reqs: &[&'ar str],
matches: Option<&ArgMatches>)
-> VecDeque<String>
{
-> VecDeque<String> {
let mut c_flags = vec![];
let mut c_pos = vec![];
let mut c_opt = vec![];
@ -2330,19 +2342,23 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
if matches.is_some() && matches.as_ref().unwrap().is_present(f) {
continue;
}
ret_val.push_back(format!("{}", self.flags.iter()
.filter(|flg| &flg.name == f)
.next()
.unwrap()));
ret_val.push_back(format!("{}",
self.flags
.iter()
.filter(|flg| &flg.name == f)
.next()
.unwrap()));
}
for o in c_opt.into_iter() {
if matches.is_some() && matches.as_ref().unwrap().is_present(o) {
continue;
}
ret_val.push_back(format!("{}", self.opts.iter()
.filter(|opt| &opt.name == o)
.next()
.unwrap()));
ret_val.push_back(format!("{}",
self.opts
.iter()
.filter(|opt| &opt.name == o)
.next()
.unwrap()));
}
for g in grps.into_iter() {
let g_string = self.args_in_group(g)
@ -2355,12 +2371,12 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
}
fn verify_positionals(&mut self) {
// Because you must wait until all arguments have been supplied, this is the
// first chance to make assertions on positional argument indexes
// Because you must wait until all arguments have been supplied, this is the first chance
// to make assertions on positional argument indexes
//
// Firt we verify that the index highest supplied index, is equal to the number
// of positional arguments to verify there are no gaps (i.e. supplying an index of
// 1 and 3 but no 2)
// Firt we verify that the index highest supplied index, is equal to the number of
// positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3
// but no 2)
if let Some((idx, ref p)) = self.positionals.iter().rev().next() {
if idx != self.positionals.len() {
panic!("Found positional argument \"{}\" who's index is {} but there are only {} \
@ -2372,20 +2388,29 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
}
// Next we verify that only the highest index has a .multiple(true) (if any)
assert!(!self.positionals.values()
.any(|a| a.settings.is_set(&ArgSettings::Multiple) &&
(a.index as usize != self.positionals.len())),
assert!(!self.positionals
.values()
.any(|a| {
a.settings.is_set(&ArgSettings::Multiple) &&
(a.index as usize != self.positionals.len())
}),
"Only the positional argument with the highest index may accept multiple values");
// If it's required we also need to ensure all previous positionals are required too
// If it's required we also need to ensure all previous positionals are
// required too
let mut found = false;
for p in self.positionals.values().rev() {
if !found {
if p.settings.is_set(&ArgSettings::Required) { found = true; continue; }
if p.settings.is_set(&ArgSettings::Required) {
found = true;
continue;
}
} else {
assert!(p.settings.is_set(&ArgSettings::Required),
"Found positional argument which is not required with a lower index than a \
required positional argument: {:?} index {}", p.name, p.index);
required positional argument: {:?} index {}",
p.name,
p.index);
}
}
}
@ -2410,8 +2435,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
opt: &str,
p_vals: &[&str],
matches: &ArgMatches<'ar, 'ar>)
-> ClapError
{
-> ClapError {
let suffix = App::did_you_mean_suffix(arg,
p_vals.iter(),
DidYouMeanMessageStyle::EnumValue);
@ -2425,14 +2449,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
.fold(String::new(), |acc, name| acc + &format!(" {}", name)[..]);
let usage = match self.create_current_usage(matches) {
Ok(s) => s,
Err(e) => return e
Err(e) => return e,
};
error_builder::InvalidValue(
arg,
opt,
&*valid_values,
&*suffix.0,
&*usage)
error_builder::InvalidValue(arg, opt, &*valid_values, &*suffix.0, &*usage)
}
fn blacklisted_from(&self, name: &str, matches: &ArgMatches) -> Option<String> {
@ -2527,8 +2546,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
self.long_list.push("version");
self.flags.push(arg);
}
if !self.subcommands.is_empty() && !self.subcommands.iter()
.any(|a| a.name_slice == "help") {
if !self.subcommands.is_empty() &&
!self.subcommands
.iter()
.any(|a| a.name_slice == "help") {
self.subcommands.push(App::new("help").about("Prints this message"));
}
}
@ -2537,10 +2558,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
if let Some(h) = self.help_short {
if h == arg {
try!(self.print_help());
return Err(
ClapError {
error: String::new(),
error_type: ClapErrorType::HelpDisplayed,
return Err(ClapError {
error: String::new(),
error_type: ClapErrorType::HelpDisplayed,
});
}
}
@ -2549,10 +2569,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
let out = io::stdout();
let mut buf_w = BufWriter::new(out.lock());
try!(self.print_version(&mut buf_w));
return Err(
ClapError {
error: String::new(),
error_type: ClapErrorType::VersionDisplayed,
return Err(ClapError {
error: String::new(),
error_type: ClapErrorType::VersionDisplayed,
});
}
}
@ -2563,25 +2582,22 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
fn parse_long_arg<'av>(&mut self,
matches: &mut ArgMatches<'ar, 'ar>,
full_arg: &'av str)
-> ClapResult<Option<&'ar str>>
{
-> ClapResult<Option<&'ar str>> {
let mut arg = full_arg.trim_left_matches(|c| c == '-');
if arg == "help" && self.settings.is_set(&AppSettings::NeedsLongHelp) {
try!(self.print_help());
return Err(
ClapError {
error: String::new(),
error_type: ClapErrorType::HelpDisplayed,
return Err(ClapError {
error: String::new(),
error_type: ClapErrorType::HelpDisplayed,
});
} else if arg == "version" && self.settings.is_set(&AppSettings::NeedsLongVersion) {
let out = io::stdout();
let mut buf_w = BufWriter::new(out.lock());
try!(self.print_version(&mut buf_w));
return Err(
ClapError {
error: String::new(),
error_type: ClapErrorType::VersionDisplayed,
return Err(ClapError {
error: String::new(),
error_type: ClapErrorType::VersionDisplayed,
});
}
@ -2768,7 +2784,7 @@ 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);
return Err(error_builder::ArgumentConflict(
return Err(error_builder::ArgumentConflict(
v.to_string(),
self.blacklisted_from(v.name, &matches),
try!(self.create_current_usage(matches))));
@ -2910,18 +2926,12 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
}
}
Err(error_builder::InvalidArgument(
&*format!("--{}", arg),
Some(&*suffix.0),
&*try!(self.create_current_usage(matches))))
Err(error_builder::InvalidArgument(&*format!("--{}", arg),
Some(&*suffix.0),
&*try!(self.create_current_usage(matches))))
}
fn validate_value(&self,
v: &OptBuilder,
av: &str,
matches: &ArgMatches)
-> ClapResult<()>
{
fn validate_value(&self, v: &OptBuilder, av: &str, matches: &ArgMatches) -> ClapResult<()> {
if let Some(ref p_vals) = v.possible_vals {
if !p_vals.contains(&av) {
return Err(self.possible_values_error(av, &v.to_string(), p_vals, matches));
@ -2929,9 +2939,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
}
if !v.settings.is_set(&ArgSettings::EmptyValues) && av.is_empty() &&
matches.args.contains_key(v.name) {
return Err(error_builder::EmptyValue(
&*v.to_string(),
&*try!(self.create_current_usage(matches))));
return Err(error_builder::EmptyValue(&*v.to_string(),
&*try!(self.create_current_usage(matches))));
}
if let Some(ref vtor) = v.validator {
if let Err(e) = vtor(av.to_owned()) {
@ -2944,8 +2953,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
fn parse_short_arg(&mut self,
matches: &mut ArgMatches<'ar, 'ar>,
full_arg: &str)
-> ClapResult<Option<&'ar str>>
{
-> ClapResult<Option<&'ar str>> {
let arg = &full_arg[..].trim_left_matches(|c| c == '-');
for c in arg.chars() {
try!(self.check_for_help_and_version(c));
@ -3064,8 +3072,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
fn parse_single_short_flag(&mut self,
matches: &mut ArgMatches<'ar, 'ar>,
arg: char)
-> ClapResult<bool>
{
-> ClapResult<bool> {
if let Some(v) = self.flags
.iter()
.filter(|&v| v.short.is_some() && v.short.unwrap() == arg)
@ -3227,9 +3234,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
if self.groups.contains_key(name) {
continue;
} else if let Some(ref vals) = ma.values {
if let Some(f) = self.opts.iter()
.filter(|o| &o.name == name)
.next() {
if let Some(f) = self.opts
.iter()
.filter(|o| &o.name == name)
.next() {
if let Some(num) = f.num_vals {
let should_err = if f.settings.is_set(&ArgSettings::Multiple) {
((vals.len() as u8) % num) != 0
@ -3275,9 +3283,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
&*try!(self.create_current_usage(matches))));
}
}
} else if let Some(f) = self.positionals.values()
.filter(|p| &p.name == name)
.next() {
} else if let Some(f) = self.positionals
.values()
.filter(|p| &p.name == name)
.next() {
if let Some(num) = f.num_vals {
if num != vals.len() as u8 {
return Err(error_builder::WrongNumValues(
@ -3416,7 +3425,8 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
fn validate_option(&self,
opt: &OptBuilder,
arg_slice: &str,
matches: &ArgMatches) -> ClapResult<()> {
matches: &ArgMatches)
-> ClapResult<()> {
// Check the possible values
if let Some(ref p_vals) = opt.possible_vals {
if !p_vals.contains(&arg_slice) {
@ -3446,14 +3456,13 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar> {
// if it's an empty value, and we don't allow that, report the error
if !opt.settings.is_set(&ArgSettings::EmptyValues) &&
matches.args.contains_key(opt.name) && arg_slice.is_empty() {
return Err(error_builder::EmptyValue(
&*opt.to_string(),
&*try!(self.create_current_usage(matches))));
return Err(error_builder::EmptyValue(&*opt.to_string(),
&*try!(self.create_current_usage(matches))));
}
if let Some(ref vtor) = opt.validator {
if let Err(e) = vtor(arg_slice.to_owned()) {
return Err(error_builder::ValueValidationError(&*e))
return Err(error_builder::ValueValidationError(&*e));
}
}

View file

@ -16,44 +16,50 @@ pub mod error_builder {
use fmt::Format;
/// Error occurs when clap find two ore more conflicting arguments
pub fn ArgumentConflict<S>(arg: S, other: Option<S>, usage: S) -> ClapError where S: AsRef<str> {
pub fn ArgumentConflict<S>(arg: S, other: Option<S>, usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} The argument '{}' cannot be used with {}\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(arg.as_ref()),
match other {
Some(name) => format!("'{}'", Format::Warning(name)),
None => "one or more of the other specified arguments".to_owned(),
},
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(arg.as_ref()),
match other {
Some(name) => format!("'{}'", Format::Warning(name)),
None => "one or more of the other specified arguments".to_owned(),
},
usage.as_ref(),
Format::Good("--help")),
error_type: cet::ArgumentConflict,
}
}
/// Error occurs when option does not allow empty values but some was found
pub fn EmptyValue<S>(arg: S, usage: S) -> ClapError where S: AsRef<str> {
pub fn EmptyValue<S>(arg: S, usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} The argument '{}' requires a value but none was supplied\
\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(arg.as_ref()),
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(arg.as_ref()),
usage.as_ref(),
Format::Good("--help")),
error_type: cet::InvalidValue,
}
}
/// Error occurs when some possible values were set, but clap found unexpected value
pub fn InvalidValue<S>(bad_val: S,
arg: S,
valid_vals: S,
did_you_mean: S,
usage: S) -> ClapError where S: AsRef<str>
arg: S,
valid_vals: S,
did_you_mean: S,
usage: S)
-> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} '{}' isn't a valid value for '{}'\n\t\
@ -61,44 +67,41 @@ pub mod error_builder {
{}\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(bad_val.as_ref()),
Format::Warning(arg.as_ref()),
valid_vals.as_ref(),
did_you_mean.as_ref(),
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(bad_val.as_ref()),
Format::Warning(arg.as_ref()),
valid_vals.as_ref(),
did_you_mean.as_ref(),
usage.as_ref(),
Format::Good("--help")),
error_type: cet::InvalidValue,
}
}
/// Error occurs when clap found unexpected flag or option
pub fn InvalidArgument<S>(arg: S,
did_you_mean: Option<S>,
usage: S) -> ClapError where S: AsRef<str>
pub fn InvalidArgument<S>(arg: S, did_you_mean: Option<S>, usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} The argument '{}' isn't valid{}\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(arg),
if did_you_mean.is_some() {
format!("{}\n", did_you_mean.unwrap().as_ref())
} else {
"".to_owned()
},
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(arg),
if did_you_mean.is_some() {
format!("{}\n", did_you_mean.unwrap().as_ref())
} else {
"".to_owned()
},
usage.as_ref(),
Format::Good("--help")),
error_type: cet::InvalidArgument,
}
}
/// Error occurs when clap found unexpected subcommand
pub fn InvalidSubcommand<S>(subcmd: S,
did_you_mean: S,
name: S,
usage: S) -> ClapError where S: AsRef<str>
pub fn InvalidSubcommand<S>(subcmd: S, did_you_mean: S, name: S, usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} The subcommand '{}' isn't valid\n\t\
@ -107,157 +110,173 @@ pub mod error_builder {
re-running with '{} {} {}'\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(subcmd.as_ref()),
Format::Good(did_you_mean.as_ref()),
name.as_ref(),
Format::Good("--"),
subcmd.as_ref(),
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(subcmd.as_ref()),
Format::Good(did_you_mean.as_ref()),
name.as_ref(),
Format::Good("--"),
subcmd.as_ref(),
usage.as_ref(),
Format::Good("--help")),
error_type: cet::InvalidSubcommand,
}
}
/// Error occurs when one or more required arguments missing
pub fn MissingRequiredArgument<S>(required: S, usage: S) -> ClapError where S: AsRef<str> {
pub fn MissingRequiredArgument<S>(required: S, usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} The following required arguments were not supplied:{}\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
required.as_ref(),
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
required.as_ref(),
usage.as_ref(),
Format::Good("--help")),
error_type: cet::MissingRequiredArgument,
}
}
/// Error occurs when required subcommand missing
pub fn MissingSubcommand<S>(name: S, usage: S) -> ClapError where S: AsRef<str> {
pub fn MissingSubcommand<S>(name: S, usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} '{}' requires a subcommand but none was provided\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(name),
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(name),
usage.as_ref(),
Format::Good("--help")),
error_type: cet::MissingSubcommand,
}
}
/// Error occurs when argument contains invalid unicode characters
pub fn InvalidUnicode<S>(usage: S) -> ClapError where S: AsRef<str> {
pub fn InvalidUnicode<S>(usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} Invalid unicode character in one or more arguments\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
usage.as_ref(),
Format::Good("--help")),
error_type: cet::InvalidUnicode,
}
}
/// Error occurs when argument got more values then were expected
pub fn TooManyValues<S>(val: S, arg: S, usage: S) -> ClapError where S: AsRef<str> {
pub fn TooManyValues<S>(val: S, arg: S, usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} The argument '{}' was found, but '{}' wasn't expecting \
any more values\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(val),
Format::Warning(arg),
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(val),
Format::Warning(arg),
usage.as_ref(),
Format::Good("--help")),
error_type: cet::TooManyValues,
}
}
/// Error occurs when argument got less values then were expected
pub fn TooFewValues<S>(arg: S,
min_vals: u8,
curr_vals: usize,
usage: S) -> ClapError where S: AsRef<str>
pub fn TooFewValues<S>(arg: S, min_vals: u8, curr_vals: usize, usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} The argument '{}' requires at least {} values, but {} w{} \
provided\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(arg.as_ref()),
Format::Warning(min_vals.to_string()),
Format::Warning(curr_vals.to_string()),
if curr_vals > 1 { "ere" } else { "as" },
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(arg.as_ref()),
Format::Warning(min_vals.to_string()),
Format::Warning(curr_vals.to_string()),
if curr_vals > 1 {
"ere"
} else {
"as"
},
usage.as_ref(),
Format::Good("--help")),
error_type: cet::TooFewValues,
}
}
/// Option fails validation of a custom validator
pub fn ValueValidationError<S>(err: S) -> ClapError where S: AsRef<str> {
pub fn ValueValidationError<S>(err: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} {}",
Format::Error("error:"),
err.as_ref()),
error: format!("{} {}", Format::Error("error:"), err.as_ref()),
error_type: cet::ValueValidationError,
}
}
/// Error occurs when argument got a different number of values then were expected
pub fn WrongNumValues<S>(arg: S,
num_vals: u8,
curr_vals: usize,
suffix: S,
usage: S) -> ClapError where S: AsRef<str>
num_vals: u8,
curr_vals: usize,
suffix: S,
usage: S)
-> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} The argument '{}' requires {} values, but {} w{} \
provided\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(arg.as_ref()),
Format::Warning(num_vals.to_string()),
Format::Warning(curr_vals.to_string()),
suffix.as_ref(),
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(arg.as_ref()),
Format::Warning(num_vals.to_string()),
Format::Warning(curr_vals.to_string()),
suffix.as_ref(),
usage.as_ref(),
Format::Good("--help")),
error_type: cet::InvalidSubcommand,
}
}
/// Error occurs when clap find argument while is was not expecting any
pub fn UnexpectedArgument<S>(arg: S, name: S, usage: S) -> ClapError where S: AsRef<str> {
pub fn UnexpectedArgument<S>(arg: S, name: S, usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} Found argument '{}', but {} wasn't expecting any\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(arg),
Format::Warning(name),
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(arg),
Format::Warning(name),
usage.as_ref(),
Format::Good("--help")),
error_type: cet::UnexpectedArgument,
}
}
/// Error occurs when argument was used multiple times and was not set as multiple.
pub fn UnexpectedMultipleUsage<S>(arg: S, usage: S) -> ClapError where S: AsRef<str> {
pub fn UnexpectedMultipleUsage<S>(arg: S, usage: S) -> ClapError
where S: AsRef<str>
{
ClapError {
error: format!("{} The argument '{}' was supplied more than once, but does \
not support multiple values\n\n\
{}\n\n\
For more information try {}",
Format::Error("error:"),
Format::Warning(arg),
usage.as_ref(),
Format::Good("--help")),
Format::Error("error:"),
Format::Warning(arg),
usage.as_ref(),
Format::Good("--help")),
error_type: cet::UnexpectedMultipleUsage,
}
}
@ -535,7 +554,7 @@ impl ClapError {
pub fn use_stderr(&self) -> bool {
match self.error_type {
ClapErrorType::HelpDisplayed | ClapErrorType::VersionDisplayed => false,
_ => true
_ => true,
}
}
/// Prints the error to `stderr` and exits with a status of `1`
@ -557,7 +576,7 @@ impl Error for ClapError {
fn cause(&self) -> Option<&Error> {
match self.error_type {
_ => None
_ => None,
}
}
}

View file

@ -38,31 +38,43 @@
//!
//! ### Comparisons
//!
//! First, let me say that these comparisons are highly subjective, and not meant
//! First, let me say that these comparisons are highly subjective, and not
//! meant
//! in a critical or harsh manner. All the argument parsing libraries out there
//! (to include `clap`) have their own strengths and weaknesses. Sometimes it just
//! comes down to personal taste when all other factors are equal. When in doubt,
//! try them all and pick one that you enjoy :) There's plenty of room in the Rust
//! (to include `clap`) have their own strengths and weaknesses. Sometimes it
//! just
//! comes down to personal taste when all other factors are equal. When in
//! doubt,
//! try them all and pick one that you enjoy :) There's plenty of room in the
//! Rust
//! community for multiple implementations!
//!
//! #### How does `clap` compare to `getopts`?
//!
//! [getopts](https://github.com/rust-lang-nursery/getopts) is a very basic, fairly
//! [getopts](https://github.com/rust-lang-nursery/getopts) is a very basic,
//! fairly
//! minimalist argument parsing library. This isn't a bad thing, sometimes you
//! don't need tons of features, you just want to parse some simple arguments, and
//! don't need tons of features, you just want to parse some simple arguments,
//! and
//! have some help text generated for you based on valid arguments you specify.
//! When using `getopts` you must manually implement most of the common features
//! (such as checking to display help messages, usage strings, etc.). If you want a
//! highly custom argument parser, and don't mind writing most the argument parser
//! (such as checking to display help messages, usage strings, etc.). If you
//! want a
//! highly custom argument parser, and don't mind writing most the argument
//! parser
//! yourself, `getopts` is an excellent base.
//!
//! Due to it's lack of features, `getopts` also doesn't allocate much, or at all.
//! Due to it's lack of features, `getopts` also doesn't allocate much, or at
//! all.
//! This gives it somewhat of a performance boost. Although, as you start
//! implementing those features you need manually, that boost quickly disappears.
//! implementing those features you need manually, that boost quickly
//! disappears.
//!
//! Personally, I find many, many people that use `getopts` are manually
//! implementing features that `clap` has by default. Using `clap` simplifies your
//! codebase allowing you to focus on your application, and not argument parsing.
//! implementing features that `clap` has by default. Using `clap` simplifies
//! your
//! codebase allowing you to focus on your application, and not argument
//! parsing.
//!
//! Reasons to use `getopts` instead of `clap`
//!
@ -75,28 +87,39 @@
//!
//! I first want to say I'm a big a fan of BurntSushi's work, the creator of
//! [Docopt.rs](https://github.com/docopt/docopt.rs). I aspire to produce the
//! quality of libraries that this man does! When it comes to comparing these two
//! quality of libraries that this man does! When it comes to comparing these
//! two
//! libraries they are very different. `docopt` tasks you with writing a help
//! message, and then it parsers that message for you to determine all valid
//! arguments and their use. Some people LOVE this, others not so much. If you're
//! willing to write a detailed help message, it's nice that you can stick that in
//! your program and have `docopt` do the rest. On the downside, it's somewhat less
//! flexible than other options out there, and requires the help message change if
//! arguments and their use. Some people LOVE this, others not so much. If
//! you're
//! willing to write a detailed help message, it's nice that you can stick that
//! in
//! your program and have `docopt` do the rest. On the downside, it's somewhat
//! less
//! flexible than other options out there, and requires the help message change
//! if
//! you need to make changes.
//!
//! `docopt` is also excellent at translating arguments into Rust types
//! automatically. There is even a syntax extension which will do all this for you,
//! ifou to manually translate from arguments to Rust types). To use BurntSushi's
//! words, `docopt` is also somewhat of a black box. You get what you get, and it's
//! automatically. There is even a syntax extension which will do all this for
//! you,
//! ifou to manually translate from arguments to Rust types). To use
//! BurntSushi's
//! words, `docopt` is also somewhat of a black box. You get what you get, and
//! it's
//! hard to tweak implementation or customise your experience for your use case.
//!
//! Because `docopt` is doing a ton of work to parse your help messages and
//! determine what you were trying to communicate as valid arguments, it's also one
//! of the more heavy weight parsers performance-wise. For most applications this
//! determine what you were trying to communicate as valid arguments, it's also
//! one
//! of the more heavy weight parsers performance-wise. For most applications
//! this
//! isn't a concern, but it's something to keep in mind.
//!
//! Reasons to use `docopt` instead of `clap`
//! * You want automatic translation from arguments to Rust types, and are using a
//! * You want automatic translation from arguments to Rust types, and are
//! using a
//! nightly compiler
//! * Performance isn't a concern
//! * You don't have any complex relationships between arguments
@ -105,7 +128,8 @@
//!
//! `clap` is fast, and as lightweight as possible while still giving all the
//! features you'd expect from a modern argument parser. If you use `clap` when
//! just need some simple arguments parsed, you'll find it a walk in the park. But
//! just need some simple arguments parsed, you'll find it a walk in the park.
//! But
//! `clap` also makes it possible to represent extremely complex, and advanced
//! requirements, without too much thought. `clap` aims to be intuitive, easy to
//! use, and fully capable for wide variety use cases and needs.