mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 06:12:40 +00:00
refactor: moves usage string generation code into it's own module
This commit is contained in:
parent
44ed8b663c
commit
622b609c57
5 changed files with 435 additions and 314 deletions
|
@ -11,6 +11,7 @@ use app::parser::Parser;
|
|||
use args::{AnyArg, ArgSettings, DispOrder};
|
||||
use errors::{Error, Result as ClapResult};
|
||||
use fmt::{Format, Colorizer};
|
||||
use app::usage;
|
||||
|
||||
// Third Party
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
@ -682,7 +683,7 @@ impl<'a> Help<'a> {
|
|||
try!(write!(self.writer,
|
||||
"\n{}{}\n\n",
|
||||
TAB,
|
||||
parser.create_usage_no_title(&[])));
|
||||
usage::create_help_usage(parser)));
|
||||
|
||||
let flags = parser.has_flags();
|
||||
let pos = parser.has_positionals();
|
||||
|
@ -879,7 +880,7 @@ impl<'a> Help<'a> {
|
|||
parser.meta.about.unwrap_or("unknown about")));
|
||||
}
|
||||
b"usage" => {
|
||||
try!(write!(self.writer, "{}", parser.create_usage_no_title(&[])));
|
||||
try!(write!(self.writer, "{}", usage::create_help_usage(parser)));
|
||||
}
|
||||
b"all-args" => {
|
||||
try!(self.write_all_args(&parser));
|
||||
|
|
|
@ -5,6 +5,7 @@ pub mod parser;
|
|||
mod meta;
|
||||
mod help;
|
||||
mod validator;
|
||||
mod usage;
|
||||
|
||||
// Std
|
||||
use std::env;
|
||||
|
|
|
@ -32,6 +32,7 @@ use completions::Shell;
|
|||
use suggestions;
|
||||
use app::settings::AppSettings as AS;
|
||||
use app::validator::Validator;
|
||||
use app::usage;
|
||||
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[doc(hidden)]
|
||||
|
@ -98,7 +99,11 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
use std::error::Error;
|
||||
|
||||
let out_dir = PathBuf::from(od);
|
||||
let name = &*self.meta.bin_name.as_ref().unwrap().clone();
|
||||
let name = &*self.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.clone();
|
||||
let file_name = match for_shell {
|
||||
Shell::Bash => format!("{}.bash-completion", name),
|
||||
Shell::Fish => format!("{}.fish", name),
|
||||
|
@ -249,8 +254,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
}
|
||||
if self.groups.iter().any(|g| g.name == group.name) {
|
||||
let grp =
|
||||
self.groups.iter_mut().find(|g| g.name == group.name).expect(INTERNAL_ERROR_MSG);
|
||||
let grp = self.groups
|
||||
.iter_mut()
|
||||
.find(|g| g.name == group.name)
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
grp.args.extend_from_slice(&group.args);
|
||||
grp.requires = group.requires.clone();
|
||||
grp.conflicts = group.conflicts.clone();
|
||||
|
@ -290,7 +297,11 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
if vsc {
|
||||
sc.p.set(AS::DisableVersion);
|
||||
}
|
||||
if gv && sc.p.meta.version.is_none() && self.meta.version.is_some() {
|
||||
if gv &&
|
||||
sc.p
|
||||
.meta
|
||||
.version
|
||||
.is_none() && self.meta.version.is_some() {
|
||||
sc.p.set(AS::GlobalVersion);
|
||||
sc.p.meta.version = Some(self.meta.version.unwrap());
|
||||
}
|
||||
|
@ -306,21 +317,21 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
if self.is_set(AS::DeriveDisplayOrder) {
|
||||
let unified = self.is_set(AS::UnifiedHelpMessage);
|
||||
for (i, o) in self.opts
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref o)| o.s.disp_ord == 999) {
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref o)| o.s.disp_ord == 999) {
|
||||
o.s.disp_ord = if unified { o.s.unified_ord } else { i };
|
||||
}
|
||||
for (i, f) in self.flags
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref f)| f.s.disp_ord == 999) {
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref f)| f.s.disp_ord == 999) {
|
||||
f.s.disp_ord = if unified { f.s.unified_ord } else { i };
|
||||
}
|
||||
for (i, sc) in &mut self.subcommands
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref sc)| sc.p.meta.disp_ord == 999) {
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref sc)| sc.p.meta.disp_ord == 999) {
|
||||
sc.p.meta.disp_ord = i;
|
||||
}
|
||||
}
|
||||
|
@ -441,24 +452,25 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
}
|
||||
for a in desc_reqs.iter()
|
||||
.filter(|name| !self.positionals.values().any(|p| &&p.b.name == name))
|
||||
.filter(|name| !self.groups.iter().any(|g| &&g.name == name))
|
||||
.filter(|name| !args_in_groups.contains(name))
|
||||
.filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(name))) {
|
||||
.filter(|name| !self.positionals.values().any(|p| &&p.b.name == name))
|
||||
.filter(|name| !self.groups.iter().any(|g| &&g.name == name))
|
||||
.filter(|name| !args_in_groups.contains(name))
|
||||
.filter(|name| {
|
||||
!(matcher.is_some() && matcher.as_ref().unwrap().contains(name))
|
||||
}) {
|
||||
debugln!("Parser::get_required_from:iter:{}:", a);
|
||||
let arg = find_by_name!(self, a, flags, iter)
|
||||
.map(|f| f.to_string())
|
||||
.unwrap_or_else(|| {
|
||||
find_by_name!(self, a, opts, iter)
|
||||
.map(|o| o.to_string())
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
});
|
||||
find_by_name!(self, a, opts, iter)
|
||||
.map(|o| o.to_string())
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
});
|
||||
ret_val.push_back(arg);
|
||||
}
|
||||
let mut g_vec = vec![];
|
||||
for g in desc_reqs.iter().filter(|n| self.groups.iter().any(|g| &&g.name == n)) {
|
||||
let g_string = self.args_in_group(g)
|
||||
.join("|");
|
||||
let g_string = self.args_in_group(g).join("|");
|
||||
g_vec.push(format!("<{}>", &g_string[..g_string.len()]));
|
||||
}
|
||||
g_vec.sort();
|
||||
|
@ -474,8 +486,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
pub fn get_args_tag(&self) -> Option<String> {
|
||||
debugln!("Parser::get_args_tag;");
|
||||
let mut count = 0;
|
||||
'outer: for p in self.positionals.values().filter(|p| !p.is_set(ArgSettings::Required) &&
|
||||
!p.is_set(ArgSettings::Hidden)) {
|
||||
'outer: for p in self.positionals.values().filter(|p| {
|
||||
!p.is_set(ArgSettings::Required) &&
|
||||
!p.is_set(ArgSettings::Hidden)
|
||||
}) {
|
||||
debugln!("Parser::get_args_tag:iter:{}:", p.b.name);
|
||||
if let Some(g_vec) = self.groups_for_arg(p.b.name) {
|
||||
for grp_s in &g_vec {
|
||||
|
@ -487,7 +501,8 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
}
|
||||
count += 1;
|
||||
debugln!("Parser::get_args_tag:iter: {} Args not required or hidden", count);
|
||||
debugln!("Parser::get_args_tag:iter: {} Args not required or hidden",
|
||||
count);
|
||||
}
|
||||
if !self.is_set(AS::DontCollapseArgsInUsage) && count > 1 {
|
||||
return None; // [ARGS]
|
||||
|
@ -499,12 +514,14 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
return Some(format!(" [{}]{}", p.name_no_brackets(), p.multiple_str()));
|
||||
} else if self.is_set(AS::DontCollapseArgsInUsage) && !self.positionals.is_empty() {
|
||||
return Some(self.positionals
|
||||
.values()
|
||||
.filter(|p| !p.is_set(ArgSettings::Required))
|
||||
.filter(|p| !p.is_set(ArgSettings::Hidden))
|
||||
.map(|p| format!(" [{}]{}", p.name_no_brackets(), p.multiple_str()))
|
||||
.collect::<Vec<_>>()
|
||||
.join(""));
|
||||
.values()
|
||||
.filter(|p| !p.is_set(ArgSettings::Required))
|
||||
.filter(|p| !p.is_set(ArgSettings::Hidden))
|
||||
.map(|p| {
|
||||
format!(" [{}]{}", p.name_no_brackets(), p.multiple_str())
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(""));
|
||||
}
|
||||
Some("".into())
|
||||
}
|
||||
|
@ -558,26 +575,34 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
pub fn has_subcommands(&self) -> bool { !self.subcommands.is_empty() }
|
||||
|
||||
#[inline]
|
||||
pub fn has_visible_opts(&self) -> bool {
|
||||
if self.opts.is_empty() { return false; }
|
||||
pub fn has_visible_opts(&self) -> bool {
|
||||
if self.opts.is_empty() {
|
||||
return false;
|
||||
}
|
||||
self.opts.iter().any(|o| !o.is_set(ArgSettings::Hidden))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_visible_flags(&self) -> bool {
|
||||
if self.flags.is_empty() { return false; }
|
||||
pub fn has_visible_flags(&self) -> bool {
|
||||
if self.flags.is_empty() {
|
||||
return false;
|
||||
}
|
||||
self.flags.iter().any(|f| !f.is_set(ArgSettings::Hidden))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_visible_positionals(&self) -> bool {
|
||||
if self.positionals.is_empty() { return false; }
|
||||
pub fn has_visible_positionals(&self) -> bool {
|
||||
if self.positionals.is_empty() {
|
||||
return false;
|
||||
}
|
||||
self.positionals.values().any(|p| !p.is_set(ArgSettings::Hidden))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_visible_subcommands(&self) -> bool {
|
||||
if self.subcommands.is_empty() { return false; }
|
||||
pub fn has_visible_subcommands(&self) -> bool {
|
||||
if self.subcommands.is_empty() {
|
||||
return false;
|
||||
}
|
||||
self.subcommands.iter().any(|s| !s.p.is_set(AS::Hidden))
|
||||
}
|
||||
|
||||
|
@ -598,7 +623,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
// 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, p)) = self.positionals.iter().rev().next() {
|
||||
if let Some((idx, p)) = self.positionals
|
||||
.iter()
|
||||
.rev()
|
||||
.next() {
|
||||
debug_assert!(!(idx != self.positionals.len()),
|
||||
format!("Found positional argument \"{}\" who's index is {} but there \
|
||||
are only {} positional arguments defined",
|
||||
|
@ -608,12 +636,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
|
||||
// Next we verify that only the highest index has a .multiple(true) (if any)
|
||||
if
|
||||
self.positionals
|
||||
.values()
|
||||
.any(|a| {
|
||||
a.is_set(ArgSettings::Multiple) && (a.index as usize != self.positionals.len())
|
||||
}) {
|
||||
if self.positionals.values().any(|a| {
|
||||
a.is_set(ArgSettings::Multiple) &&
|
||||
(a.index as usize != self.positionals.len())
|
||||
}) {
|
||||
|
||||
debug_assert!({
|
||||
let mut it = self.positionals.values().rev();
|
||||
|
@ -628,7 +654,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
|
||||
debug_assert!({
|
||||
let num = self.positionals.len() - 1;
|
||||
self.positionals.get(num).unwrap().is_set(ArgSettings::Multiple)
|
||||
self.positionals
|
||||
.get(num)
|
||||
.unwrap()
|
||||
.is_set(ArgSettings::Multiple)
|
||||
},
|
||||
"Only the last positional argument, or second to last positional \
|
||||
argument may be set to .multiple(true)");
|
||||
|
@ -639,8 +668,9 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
debug_assert!(self.positionals
|
||||
.values()
|
||||
.filter(|p| {
|
||||
p.b.settings.is_set(ArgSettings::Multiple) && p.v.num_vals.is_none()
|
||||
})
|
||||
p.b.settings.is_set(ArgSettings::Multiple) &&
|
||||
p.v.num_vals.is_none()
|
||||
})
|
||||
.map(|_| 1)
|
||||
.sum::<u64>() <= 1,
|
||||
"Only one positional argument with .multiple(true) set is allowed per \
|
||||
|
@ -729,15 +759,18 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
.iter()
|
||||
.filter(|s| {
|
||||
starts(&s.p.meta.name[..], &*arg_os) ||
|
||||
(s.p.meta.aliases.is_some() &&
|
||||
(s.p
|
||||
.meta
|
||||
.aliases
|
||||
.is_some() &&
|
||||
s.p
|
||||
.meta
|
||||
.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter(|&&(a, _)| starts(a, &*arg_os))
|
||||
.count() == 1)
|
||||
.meta
|
||||
.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter(|&&(a, _)| starts(a, &*arg_os))
|
||||
.count() == 1)
|
||||
})
|
||||
.map(|sc| &sc.p.meta.name)
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -769,24 +802,21 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
help_help = true;
|
||||
}
|
||||
if let Some(c) = sc.subcommands
|
||||
.iter()
|
||||
.find(|s| &*s.p.meta.name == cmd)
|
||||
.map(|sc| &sc.p) {
|
||||
.iter()
|
||||
.find(|s| &*s.p.meta.name == cmd)
|
||||
.map(|sc| &sc.p) {
|
||||
sc = c;
|
||||
if i == cmds.len() - 1 {
|
||||
break;
|
||||
}
|
||||
} else if let Some(c) = sc.subcommands
|
||||
.iter()
|
||||
.find(|s| if let Some(ref als) = s.p
|
||||
.meta
|
||||
.aliases {
|
||||
als.iter()
|
||||
.any(|&(a, _)| &a == &&*cmd.to_string_lossy())
|
||||
} else {
|
||||
false
|
||||
})
|
||||
.map(|sc| &sc.p) {
|
||||
.iter()
|
||||
.find(|s| if let Some(ref als) = s.p.meta.aliases {
|
||||
als.iter().any(|&(a, _)| &a == &&*cmd.to_string_lossy())
|
||||
} else {
|
||||
false
|
||||
})
|
||||
.map(|sc| &sc.p) {
|
||||
sc = c;
|
||||
if i == cmds.len() - 1 {
|
||||
break;
|
||||
|
@ -957,7 +987,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
arg_os.to_string_lossy().parse::<f64>().is_ok()) {
|
||||
return Err(Error::unknown_argument(&*arg_os.to_string_lossy(),
|
||||
"",
|
||||
&*self.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self, matcher, None),
|
||||
self.color()));
|
||||
}
|
||||
} else if !self.is_set(AS::AllowLeadingHyphen) {
|
||||
|
@ -980,7 +1010,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&self.meta.name),
|
||||
&*self.create_current_usage(matcher,
|
||||
&*usage::create_error_usage(self, matcher,
|
||||
None),
|
||||
self.color()));
|
||||
}
|
||||
|
@ -1029,8 +1059,9 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
Some(s) => s.to_string(),
|
||||
None => {
|
||||
if !self.is_set(AS::StrictUtf8) {
|
||||
return Err(Error::invalid_utf8(&*self.create_current_usage(matcher,
|
||||
None),
|
||||
return Err(Error::invalid_utf8(&*usage::create_error_usage(self,
|
||||
matcher,
|
||||
None),
|
||||
self.color()));
|
||||
}
|
||||
arg_os.to_string_lossy().into_owned()
|
||||
|
@ -1042,59 +1073,73 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
while let Some(v) = it.next() {
|
||||
let a = v.into();
|
||||
if a.to_str().is_none() && !self.is_set(AS::StrictUtf8) {
|
||||
return Err(Error::invalid_utf8(&*self.create_current_usage(matcher, None),
|
||||
return Err(Error::invalid_utf8(&*usage::create_error_usage(self,
|
||||
matcher,
|
||||
None),
|
||||
self.color()));
|
||||
}
|
||||
sc_m.add_val_to("", &a);
|
||||
}
|
||||
|
||||
matcher.subcommand(SubCommand {
|
||||
name: sc_name,
|
||||
matches: sc_m.into(),
|
||||
});
|
||||
name: sc_name,
|
||||
matches: sc_m.into(),
|
||||
});
|
||||
} else if !(self.is_set(AS::AllowLeadingHyphen) ||
|
||||
self.is_set(AS::AllowNegativeNumbers)) &&
|
||||
!self.is_set(AS::InferSubcommands) {
|
||||
return Err(Error::unknown_argument(&*arg_os.to_string_lossy(),
|
||||
"",
|
||||
&*self.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self,
|
||||
matcher,
|
||||
None),
|
||||
self.color()));
|
||||
} else if !(has_args) && self.has_subcommands() {
|
||||
if let Some(cdate) = suggestions::did_you_mean(&*arg_os.to_string_lossy(),
|
||||
sc_names!(self)) {
|
||||
return Err(Error::invalid_subcommand(arg_os.to_string_lossy()
|
||||
.into_owned(),
|
||||
cdate,
|
||||
self.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&self.meta.name),
|
||||
&*self.create_current_usage(matcher,
|
||||
None),
|
||||
self.color()));
|
||||
return Err(Error::invalid_subcommand(arg_os.to_string_lossy().into_owned(),
|
||||
cdate,
|
||||
self.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&self.meta.name),
|
||||
&*usage::create_error_usage(self,
|
||||
matcher,
|
||||
None),
|
||||
self.color()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref pos_sc_name) = subcmd_name {
|
||||
let sc_name = {
|
||||
find_subcmd!(self, pos_sc_name).expect(INTERNAL_ERROR_MSG).p.meta.name.clone()
|
||||
find_subcmd!(self, pos_sc_name)
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.p
|
||||
.meta
|
||||
.name
|
||||
.clone()
|
||||
};
|
||||
try!(self.parse_subcommand(&*sc_name, matcher, it));
|
||||
} else if self.is_set(AS::SubcommandRequired) {
|
||||
let bn = self.meta.bin_name.as_ref().unwrap_or(&self.meta.name);
|
||||
let bn = self.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&self.meta.name);
|
||||
return Err(Error::missing_subcommand(bn,
|
||||
&self.create_current_usage(matcher, None),
|
||||
&usage::create_error_usage(self,
|
||||
matcher,
|
||||
None),
|
||||
self.color()));
|
||||
} else if self.is_set(AS::SubcommandRequiredElseHelp) {
|
||||
debugln!("parser::get_matches_with: SubcommandRequiredElseHelp=true");
|
||||
let mut out = vec![];
|
||||
try!(self.write_help_err(&mut out));
|
||||
return Err(Error {
|
||||
message: String::from_utf8_lossy(&*out).into_owned(),
|
||||
kind: ErrorKind::MissingArgumentOrSubcommand,
|
||||
info: None,
|
||||
});
|
||||
message: String::from_utf8_lossy(&*out).into_owned(),
|
||||
kind: ErrorKind::MissingArgumentOrSubcommand,
|
||||
info: None,
|
||||
});
|
||||
}
|
||||
|
||||
Validator::new(self).validate(needs_val_of, subcmd_name, matcher)
|
||||
|
@ -1113,7 +1158,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
debugln!("Parser::build_bin_names;");
|
||||
for sc in &mut self.subcommands {
|
||||
debug!("Parser::build_bin_names:iter: bin_name set...");
|
||||
if sc.p.meta.bin_name.is_none() {
|
||||
if sc.p
|
||||
.meta
|
||||
.bin_name
|
||||
.is_none() {
|
||||
sdebugln!("No");
|
||||
let bin_name = format!("{}{}{}",
|
||||
self.meta
|
||||
|
@ -1151,7 +1199,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
debugln!("Parser::parse_subcommand;");
|
||||
let mut mid_string = String::new();
|
||||
if !self.is_set(AS::SubcommandsNegateReqs) {
|
||||
let mut hs: Vec<&str> = self.required.iter().map(|n| &**n).collect();
|
||||
let mut hs: Vec<&str> = self.required
|
||||
.iter()
|
||||
.map(|n| &**n)
|
||||
.collect();
|
||||
for k in matcher.arg_names() {
|
||||
hs.push(k);
|
||||
}
|
||||
|
@ -1162,14 +1213,15 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
}
|
||||
mid_string.push_str(" ");
|
||||
if let Some(ref mut sc) = self.subcommands
|
||||
.iter_mut()
|
||||
.find(|s| &s.p.meta.name == &sc_name) {
|
||||
if let Some(ref mut sc) = self.subcommands.iter_mut().find(|s| &s.p.meta.name == &sc_name) {
|
||||
let mut sc_matcher = ArgMatcher::new();
|
||||
// bin_name should be parent's bin_name + [<reqs>] + the sc's name separated by
|
||||
// a space
|
||||
sc.p.meta.usage = Some(format!("{}{}{}",
|
||||
self.meta.bin_name.as_ref().unwrap_or(&String::new()),
|
||||
self.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&String::new()),
|
||||
if self.meta.bin_name.is_some() {
|
||||
&*mid_string
|
||||
} else {
|
||||
|
@ -1192,9 +1244,12 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
debugln!("Parser::parse_subcommand: sc settings={:#?}", sc.p.settings);
|
||||
try!(sc.p.get_matches_with(&mut sc_matcher, it));
|
||||
matcher.subcommand(SubCommand {
|
||||
name: sc.p.meta.name.clone(),
|
||||
matches: sc_matcher.into(),
|
||||
});
|
||||
name: sc.p
|
||||
.meta
|
||||
.name
|
||||
.clone(),
|
||||
matches: sc_matcher.into(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1228,14 +1283,16 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
let mut g_vec = vec![];
|
||||
let mut args = vec![];
|
||||
|
||||
for n in &self.groups.iter().find(|g| g.name == group).expect(INTERNAL_ERROR_MSG).args {
|
||||
for n in &self.groups
|
||||
.iter()
|
||||
.find(|g| g.name == group)
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.args {
|
||||
if let Some(f) = self.flags.iter().find(|f| &f.b.name == n) {
|
||||
args.push(f.to_string());
|
||||
} else if let Some(f) = self.opts.iter().find(|o| &o.b.name == n) {
|
||||
args.push(f.to_string());
|
||||
} else if let Some(p) = self.positionals
|
||||
.values()
|
||||
.find(|p| &p.b.name == n) {
|
||||
} else if let Some(p) = self.positionals.values().find(|p| &p.b.name == n) {
|
||||
args.push(p.b.name.to_owned());
|
||||
} else {
|
||||
g_vec.push(*n);
|
||||
|
@ -1253,7 +1310,11 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
let mut g_vec = vec![];
|
||||
let mut args = vec![];
|
||||
|
||||
for n in &self.groups.iter().find(|g| g.name == group).expect(INTERNAL_ERROR_MSG).args {
|
||||
for n in &self.groups
|
||||
.iter()
|
||||
.find(|g| g.name == group)
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.args {
|
||||
if self.groups.iter().any(|g| &g.name == &*n) {
|
||||
args.extend(self.arg_names_in_group(&*n));
|
||||
g_vec.push(*n);
|
||||
|
@ -1321,26 +1382,6 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
|
||||
// Retrieves the names of all args the user has supplied thus far, except required ones
|
||||
// because those will be listed in self.required
|
||||
pub fn create_current_usage(&self, matcher: &'b ArgMatcher<'a>, extra: Option<&str>) -> String {
|
||||
let mut args: Vec<_> = matcher.arg_names()
|
||||
.iter()
|
||||
.filter(|n| {
|
||||
if let Some(o) = find_by_name!(self, *n, opts, iter) {
|
||||
!o.b.settings.is_set(ArgSettings::Required)
|
||||
} else if let Some(p) = find_by_name!(self, *n, positionals, values) {
|
||||
!p.b.settings.is_set(ArgSettings::Required)
|
||||
} else {
|
||||
true // flags can't be required, so they're always true
|
||||
}
|
||||
})
|
||||
.map(|&n| n)
|
||||
.collect();
|
||||
if let Some(r) = extra {
|
||||
args.push(r);
|
||||
}
|
||||
self.create_usage(&*args)
|
||||
}
|
||||
|
||||
fn check_for_help_and_version_str(&self, arg: &OsStr) -> ClapResult<()> {
|
||||
debugln!("Parser::check_for_help_and_version_str;");
|
||||
debug!("Parser::check_for_help_and_version_str: Checking if --{} is help or version...",
|
||||
|
@ -1382,10 +1423,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
let mut buf = vec![];
|
||||
try!(Help::write_parser_help(&mut buf, self));
|
||||
Err(Error {
|
||||
message: unsafe { String::from_utf8_unchecked(buf) },
|
||||
kind: ErrorKind::HelpDisplayed,
|
||||
info: None,
|
||||
})
|
||||
message: unsafe { String::from_utf8_unchecked(buf) },
|
||||
kind: ErrorKind::HelpDisplayed,
|
||||
info: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn _version(&self) -> ClapResult<()> {
|
||||
|
@ -1393,10 +1434,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
let mut buf_w = BufWriter::new(out.lock());
|
||||
try!(self.print_version(&mut buf_w));
|
||||
Err(Error {
|
||||
message: String::new(),
|
||||
kind: ErrorKind::VersionDisplayed,
|
||||
info: None,
|
||||
})
|
||||
message: String::new(),
|
||||
kind: ErrorKind::VersionDisplayed,
|
||||
info: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_long_arg(&mut self,
|
||||
|
@ -1530,7 +1571,9 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
let arg = format!("-{}", c);
|
||||
return Err(Error::unknown_argument(&*arg,
|
||||
"",
|
||||
&*self.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self,
|
||||
matcher,
|
||||
None),
|
||||
self.color()));
|
||||
}
|
||||
}
|
||||
|
@ -1555,7 +1598,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
(v.len_() == 0 || (opt.is_set(ArgSettings::RequireEquals) && !has_eq)) {
|
||||
sdebugln!("Found Empty - Error");
|
||||
return Err(Error::empty_value(opt,
|
||||
&*self.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self, matcher, None),
|
||||
self.color()));
|
||||
}
|
||||
sdebugln!("Found - {:?}, len: {}", v, v.len_());
|
||||
|
@ -1566,7 +1609,7 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
} else if opt.is_set(ArgSettings::RequireEquals) && !opt.is_set(ArgSettings::EmptyValues) {
|
||||
sdebugln!("None, but requires equals...Error");
|
||||
return Err(Error::empty_value(opt,
|
||||
&*self.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self, matcher, None),
|
||||
self.color()));
|
||||
|
||||
} else {
|
||||
|
@ -1689,130 +1732,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
let used_arg = format!("--{}", arg);
|
||||
Err(Error::unknown_argument(&*used_arg,
|
||||
&*suffix.0,
|
||||
&*self.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self, matcher, None),
|
||||
self.color()))
|
||||
}
|
||||
|
||||
// Creates a usage string if one was not provided by the user manually. This happens just
|
||||
// after all arguments were parsed, but before any subcommands have been parsed
|
||||
// (so as to give subcommands their own usage recursively)
|
||||
pub fn create_usage(&self, used: &[&str]) -> String {
|
||||
debugln!("Parser::create_usage;");
|
||||
let mut usage = String::with_capacity(75);
|
||||
usage.push_str("USAGE:\n ");
|
||||
usage.push_str(&self.create_usage_no_title(used));
|
||||
usage
|
||||
}
|
||||
|
||||
// Creates a usage string (*without title*) if one was not provided by the user
|
||||
// manually. This happens just
|
||||
// after all arguments were parsed, but before any subcommands have been parsed
|
||||
// (so as to give subcommands their own usage recursively)
|
||||
pub fn create_usage_no_title(&self, used: &[&str]) -> String {
|
||||
debugln!("Parser::create_usage_no_title;");
|
||||
let mut usage = String::with_capacity(75);
|
||||
if let Some(u) = self.meta.usage_str {
|
||||
usage.push_str(&*u);
|
||||
} else if used.is_empty() {
|
||||
let name = self.meta
|
||||
.usage
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| {
|
||||
self.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&self.meta.name)
|
||||
});
|
||||
usage.push_str(&*name);
|
||||
let mut reqs: Vec<&str> = self.required().map(|r| &**r).collect();
|
||||
reqs.dedup();
|
||||
let req_string = self.get_required_from(&reqs, None, None)
|
||||
.iter()
|
||||
.fold(String::new(), |a, s| a + &format!(" {}", s)[..]);
|
||||
|
||||
let flags = self.needs_flags_tag();
|
||||
if flags && !self.is_set(AS::UnifiedHelpMessage) {
|
||||
usage.push_str(" [FLAGS]");
|
||||
} else if flags {
|
||||
usage.push_str(" [OPTIONS]");
|
||||
}
|
||||
if !self.is_set(AS::UnifiedHelpMessage) &&
|
||||
self.opts.iter().any(|o| !o.is_set(ArgSettings::Required) &&
|
||||
!o.is_set(ArgSettings::Hidden)) {
|
||||
usage.push_str(" [OPTIONS]");
|
||||
}
|
||||
|
||||
usage.push_str(&req_string[..]);
|
||||
|
||||
// places a '--' in the usage string if there are args and options
|
||||
// supporting multiple values
|
||||
if self.has_positionals() &&
|
||||
self.opts.iter().any(|o| o.is_set(ArgSettings::Multiple)) &&
|
||||
self.positionals.values().any(|p| !p.is_set(ArgSettings::Required)) &&
|
||||
!self.has_visible_subcommands() {
|
||||
usage.push_str(" [--]")
|
||||
}
|
||||
if self.has_positionals() &&
|
||||
self.positionals.values().any(|p| !p.is_set(ArgSettings::Required) &&
|
||||
!p.is_set(ArgSettings::Hidden)) {
|
||||
if let Some(args_tag) = self.get_args_tag() {
|
||||
usage.push_str(&*args_tag);
|
||||
} else {
|
||||
usage.push_str(" [ARGS]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if self.is_set(AS::SubcommandsNegateReqs) || self.is_set(AS::ArgsNegateSubcommands) {
|
||||
if self.has_visible_subcommands() {
|
||||
usage.push_str("\n ");
|
||||
usage.push_str(&*name);
|
||||
usage.push_str(" <SUBCOMMAND>");
|
||||
}
|
||||
} else {
|
||||
if self.has_visible_subcommands() && !self.is_set(AS::SubcommandRequired) {
|
||||
usage.push_str(" [SUBCOMMAND]");
|
||||
} else if (self.is_set(AS::SubcommandRequired) ||
|
||||
self.is_set(AS::SubcommandRequiredElseHelp)) && self.has_subcommands() {
|
||||
usage.push_str(" <SUBCOMMAND>");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.smart_usage(&mut usage, used);
|
||||
}
|
||||
|
||||
usage.shrink_to_fit();
|
||||
usage
|
||||
}
|
||||
|
||||
// Creates a context aware usage string, or "smart usage" from currently used
|
||||
// args, and requirements
|
||||
fn smart_usage(&self, usage: &mut String, used: &[&str]) {
|
||||
debugln!("Parser::smart_usage;");
|
||||
let mut hs: Vec<&str> = self.required().map(|s| &**s).collect();
|
||||
hs.extend_from_slice(used);
|
||||
|
||||
let r_string = self.get_required_from(&hs, None, None)
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]);
|
||||
|
||||
usage.push_str(&self.meta
|
||||
.usage
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| {
|
||||
self.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&self.meta
|
||||
.name)
|
||||
})
|
||||
[..]);
|
||||
usage.push_str(&*r_string);
|
||||
if self.is_set(AS::SubcommandRequired) {
|
||||
usage.push_str(" <SUBCOMMAND>");
|
||||
}
|
||||
}
|
||||
|
||||
// Prints the version to the user and exits if quit=true
|
||||
fn print_version<W: Write>(&self, w: &mut W) -> ClapResult<()> {
|
||||
try!(self.write_version(w));
|
||||
|
@ -1955,17 +1878,33 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
pub fn find_subcommand(&'b self, sc: &str) -> Option<&'b App<'a, 'b>> {
|
||||
debugln!("Parser::find_subcommand: sc={}", sc);
|
||||
debugln!("Parser::find_subcommand: Currently in Parser...{}",
|
||||
self.meta.bin_name.as_ref().unwrap());
|
||||
self.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap());
|
||||
for s in self.subcommands.iter() {
|
||||
if s.p.meta.bin_name.as_ref().unwrap_or(&String::new()) == sc ||
|
||||
(s.p.meta.aliases.is_some() &&
|
||||
if s.p
|
||||
.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&String::new()) == sc ||
|
||||
(s.p
|
||||
.meta
|
||||
.aliases
|
||||
.is_some() &&
|
||||
s.p
|
||||
.meta
|
||||
.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|&(s, _)| s == sc.split(' ').rev().next().expect(INTERNAL_ERROR_MSG))) {
|
||||
.meta
|
||||
.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|&(s, _)| {
|
||||
s ==
|
||||
sc.split(' ')
|
||||
.rev()
|
||||
.next()
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
})) {
|
||||
return Some(s);
|
||||
}
|
||||
if let Some(app) = s.p.find_subcommand(sc) {
|
||||
|
|
153
src/app/usage.rs
Normal file
153
src/app/usage.rs
Normal file
|
@ -0,0 +1,153 @@
|
|||
use args::{AnyArg, ArgMatcher};
|
||||
use args::settings::ArgSettings;
|
||||
use app::settings::AppSettings as AS;
|
||||
use app::parser::Parser;
|
||||
|
||||
// Creates a usage string for display. This happens just after all arguments were parsed, but before
|
||||
// any subcommands have been parsed (so as to give subcommands their own usage recursively)
|
||||
pub fn create_usage_with_title(p: &Parser, used: &[&str]) -> String {
|
||||
debugln!("Parser::create_usage_with_title;");
|
||||
let mut usage = String::with_capacity(75);
|
||||
usage.push_str("USAGE:\n ");
|
||||
usage.push_str(&*create_usage_no_title(p, used));
|
||||
usage
|
||||
}
|
||||
|
||||
// Creates a usage string to be used in error message (i.e. one with currently used args)
|
||||
pub fn create_error_usage<'a, 'b>(p: &Parser<'a, 'b>,
|
||||
matcher: &'b ArgMatcher<'a>,
|
||||
extra: Option<&str>)
|
||||
-> String {
|
||||
let mut args: Vec<_> = matcher.arg_names()
|
||||
.iter()
|
||||
.filter(|n| {
|
||||
if let Some(o) = find_by_name!(p, *n, opts, iter) {
|
||||
!o.b.is_set(ArgSettings::Required) && !o.b.is_set(ArgSettings::Hidden)
|
||||
} else if let Some(p) = find_by_name!(p, *n, positionals, values) {
|
||||
!p.b.is_set(ArgSettings::Required) && p.b.is_set(ArgSettings::Hidden)
|
||||
} else {
|
||||
true // flags can't be required, so they're always true
|
||||
}
|
||||
})
|
||||
.map(|&n| n)
|
||||
.collect();
|
||||
if let Some(r) = extra {
|
||||
args.push(r);
|
||||
}
|
||||
create_usage_with_title(p, &*args)
|
||||
}
|
||||
|
||||
// Creates a usage string (*without title*) if one was not provided by the user manually.
|
||||
fn create_usage_no_title(p: &Parser, used: &[&str]) -> String {
|
||||
debugln!("Parser::create_usage_no_title;");
|
||||
if let Some(u) = p.meta.usage_str {
|
||||
String::from(&*u)
|
||||
} else if used.is_empty() {
|
||||
create_help_usage(p)
|
||||
} else {
|
||||
create_smart_usage(p, used)
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a usage string for display in help messages (i.e. not for errors)
|
||||
pub fn create_help_usage(p: &Parser) -> String {
|
||||
let mut usage = String::with_capacity(75);
|
||||
let name = p.meta
|
||||
.usage
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| {
|
||||
p.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&p.meta.name)
|
||||
});
|
||||
usage.push_str(&*name);
|
||||
let mut reqs: Vec<&str> = p.required().map(|r| &**r).collect();
|
||||
reqs.dedup();
|
||||
let req_string =
|
||||
p.get_required_from(&reqs, None, None).iter().fold(String::new(),
|
||||
|a, s| a + &format!(" {}", s)[..]);
|
||||
|
||||
let flags = p.needs_flags_tag();
|
||||
if flags && !p.is_set(AS::UnifiedHelpMessage) {
|
||||
usage.push_str(" [FLAGS]");
|
||||
} else if flags {
|
||||
usage.push_str(" [OPTIONS]");
|
||||
}
|
||||
if !p.is_set(AS::UnifiedHelpMessage) &&
|
||||
p.opts.iter().any(|o| {
|
||||
!o.is_set(ArgSettings::Required) && !o.is_set(ArgSettings::Hidden)
|
||||
}) {
|
||||
usage.push_str(" [OPTIONS]");
|
||||
}
|
||||
|
||||
usage.push_str(&req_string[..]);
|
||||
|
||||
// places a '--' in the usage string if there are args and options
|
||||
// supporting multiple values
|
||||
if p.has_positionals() && p.opts.iter().any(|o| o.is_set(ArgSettings::Multiple)) &&
|
||||
p.positionals.values().any(|p| !p.is_set(ArgSettings::Required)) &&
|
||||
!p.has_visible_subcommands() {
|
||||
usage.push_str(" [--]")
|
||||
}
|
||||
if p.has_positionals() &&
|
||||
p.positionals.values().any(|p| {
|
||||
!p.is_set(ArgSettings::Required) &&
|
||||
!p.is_set(ArgSettings::Hidden)
|
||||
}) {
|
||||
if let Some(args_tag) = p.get_args_tag() {
|
||||
usage.push_str(&*args_tag);
|
||||
} else {
|
||||
usage.push_str(" [ARGS]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if p.is_set(AS::SubcommandsNegateReqs) || p.is_set(AS::ArgsNegateSubcommands) {
|
||||
if p.has_visible_subcommands() {
|
||||
usage.push_str("\n ");
|
||||
usage.push_str(&*name);
|
||||
usage.push_str(" <SUBCOMMAND>");
|
||||
}
|
||||
} else {
|
||||
if p.has_visible_subcommands() && !p.is_set(AS::SubcommandRequired) {
|
||||
usage.push_str(" [SUBCOMMAND]");
|
||||
} else if (p.is_set(AS::SubcommandRequired) ||
|
||||
p.is_set(AS::SubcommandRequiredElseHelp)) &&
|
||||
p.has_subcommands() {
|
||||
usage.push_str(" <SUBCOMMAND>");
|
||||
}
|
||||
}
|
||||
usage.shrink_to_fit();
|
||||
usage
|
||||
}
|
||||
|
||||
// Creates a context aware usage string, or "smart usage" from currently used
|
||||
// args, and requirements
|
||||
fn create_smart_usage(p: &Parser, used: &[&str]) -> String {
|
||||
debugln!("Parser::smart_usage;");
|
||||
let mut usage = String::with_capacity(75);
|
||||
let mut hs: Vec<&str> = p.required().map(|s| &**s).collect();
|
||||
hs.extend_from_slice(used);
|
||||
|
||||
let r_string = p.get_required_from(&hs, None, None).iter().fold(String::new(), |acc, s| {
|
||||
acc + &format!(" {}", s)[..]
|
||||
});
|
||||
|
||||
usage.push_str(&p.meta
|
||||
.usage
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| {
|
||||
p.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap_or(&p.meta.name)
|
||||
})
|
||||
[..]);
|
||||
usage.push_str(&*r_string);
|
||||
if p.is_set(AS::SubcommandRequired) {
|
||||
usage.push_str(" <SUBCOMMAND>");
|
||||
}
|
||||
usage.shrink_to_fit();
|
||||
usage
|
||||
}
|
|
@ -12,19 +12,20 @@ use osstringext::OsStrExt2;
|
|||
use app::settings::AppSettings as AS;
|
||||
use app::parser::Parser;
|
||||
use fmt::Colorizer;
|
||||
use app::usage;
|
||||
|
||||
pub struct Validator<'a, 'b, 'z>(&'z mut Parser<'a, 'b>) where 'a: 'b, 'b: 'z;
|
||||
pub struct Validator<'a, 'b, 'z>(&'z mut Parser<'a, 'b>)
|
||||
where 'a: 'b,
|
||||
'b: 'z;
|
||||
|
||||
impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
||||
pub fn new(p: &'z mut Parser<'a, 'b>) -> Self {
|
||||
Validator(p)
|
||||
}
|
||||
pub fn new(p: &'z mut Parser<'a, 'b>) -> Self { Validator(p) }
|
||||
|
||||
pub fn validate(&mut self,
|
||||
needs_val_of: Option<&'a str>,
|
||||
subcmd_name: Option<String>,
|
||||
matcher: &mut ArgMatcher<'a>)
|
||||
-> ClapResult<()> {
|
||||
needs_val_of: Option<&'a str>,
|
||||
subcmd_name: Option<String>,
|
||||
matcher: &mut ArgMatcher<'a>)
|
||||
-> ClapResult<()> {
|
||||
debugln!("Validator::validate;");
|
||||
let mut reqs_validated = false;
|
||||
try!(self.0.add_defaults(matcher));
|
||||
|
@ -40,7 +41,9 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
};
|
||||
if should_err {
|
||||
return Err(Error::empty_value(o,
|
||||
&*self.0.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self.0,
|
||||
matcher,
|
||||
None),
|
||||
self.0.color()));
|
||||
}
|
||||
}
|
||||
|
@ -51,17 +54,17 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
try!(self.validate_required(matcher));
|
||||
}
|
||||
try!(self.validate_matched_args(matcher));
|
||||
matcher.usage(self.0.create_usage(&[]));
|
||||
matcher.usage(usage::create_help_usage(self.0));
|
||||
|
||||
if matcher.is_empty() && matcher.subcommand_name().is_none() &&
|
||||
self.0.is_set(AS::ArgRequiredElseHelp) {
|
||||
let mut out = vec![];
|
||||
try!(self.0.write_help_err(&mut out));
|
||||
return Err(Error {
|
||||
message: String::from_utf8_lossy(&*out).into_owned(),
|
||||
kind: ErrorKind::MissingArgumentOrSubcommand,
|
||||
info: None,
|
||||
});
|
||||
message: String::from_utf8_lossy(&*out).into_owned(),
|
||||
kind: ErrorKind::MissingArgumentOrSubcommand,
|
||||
info: None,
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -78,7 +81,9 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
if self.0.is_set(AS::StrictUtf8) && val.to_str().is_none() {
|
||||
debugln!("Validator::validate_values: invalid UTF-8 found in val {:?}",
|
||||
val);
|
||||
return Err(Error::invalid_utf8(&*self.0.create_current_usage(matcher, None),
|
||||
return Err(Error::invalid_utf8(&*usage::create_error_usage(self.0,
|
||||
matcher,
|
||||
None),
|
||||
self.0.color()));
|
||||
}
|
||||
if let Some(p_vals) = arg.possible_vals() {
|
||||
|
@ -88,7 +93,9 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
return Err(Error::invalid_value(val_str,
|
||||
p_vals,
|
||||
arg,
|
||||
&*self.0.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self.0,
|
||||
matcher,
|
||||
None),
|
||||
self.0.color()));
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +103,7 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
matcher.contains(&*arg.name()) {
|
||||
debugln!("Validator::validate_values: illegal empty val found");
|
||||
return Err(Error::empty_value(arg,
|
||||
&*self.0.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color()));
|
||||
}
|
||||
if let Some(vtor) = arg.validator() {
|
||||
|
@ -124,7 +131,8 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
}
|
||||
|
||||
fn validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("Validator::validate_blacklist: blacklist={:?}", self.0.blacklist);
|
||||
debugln!("Validator::validate_blacklist: blacklist={:?}",
|
||||
self.0.blacklist);
|
||||
macro_rules! build_err {
|
||||
($p:expr, $name:expr, $matcher:ident) => ({
|
||||
debugln!("build_err!: name={}", $name);
|
||||
|
@ -138,7 +146,7 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
);
|
||||
debugln!("build_err!: '{:?}' conflicts with '{}'", c_with, $name);
|
||||
$matcher.remove($name);
|
||||
let usg = $p.create_current_usage($matcher, None);
|
||||
let usg = usage::create_error_usage($p, $matcher, None);
|
||||
if let Some(f) = find_by_name!($p, $name, flags, iter) {
|
||||
debugln!("build_err!: It was a flag...");
|
||||
Error::argument_conflict(f, c_with, &*usg, self.0.color())
|
||||
|
@ -160,7 +168,10 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
for name in &self.0.blacklist {
|
||||
debugln!("Validator::validate_blacklist:iter: Checking blacklisted name: {}",
|
||||
name);
|
||||
if self.0.groups.iter().any(|g| &g.name == name) {
|
||||
if self.0
|
||||
.groups
|
||||
.iter()
|
||||
.any(|g| &g.name == name) {
|
||||
debugln!("Validator::validate_blacklist:iter: groups contains it...");
|
||||
for n in self.0.arg_names_in_group(name) {
|
||||
debugln!("Validator::validate_blacklist:iter:iter: Checking arg '{}' in group...",
|
||||
|
@ -198,7 +209,11 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
try!(self.validate_values(pos, ma, matcher));
|
||||
try!(self.validate_arg_requires(pos, ma, matcher));
|
||||
} else {
|
||||
let grp = self.0.groups.iter().find(|g| &g.name == name).expect(INTERNAL_ERROR_MSG);
|
||||
let grp = self.0
|
||||
.groups
|
||||
.iter()
|
||||
.find(|g| &g.name == name)
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
if let Some(ref g_reqs) = grp.requires {
|
||||
if g_reqs.iter().any(|&n| !matcher.contains(n)) {
|
||||
return self.missing_required_error(matcher, None);
|
||||
|
@ -220,7 +235,9 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
if ma.occurs > 1 && !a.is_set(ArgSettings::Multiple) {
|
||||
// Not the first time, and we don't allow multiples
|
||||
return Err(Error::unexpected_multiple_usage(a,
|
||||
&*self.0.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self.0,
|
||||
matcher,
|
||||
None),
|
||||
self.0.color()));
|
||||
}
|
||||
Ok(())
|
||||
|
@ -258,7 +275,9 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
} else {
|
||||
"ere"
|
||||
},
|
||||
&*self.0.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self.0,
|
||||
matcher,
|
||||
None),
|
||||
self.0.color()));
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +292,7 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
.to_str()
|
||||
.expect(INVALID_UTF8),
|
||||
a,
|
||||
&*self.0.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color()));
|
||||
}
|
||||
}
|
||||
|
@ -284,14 +303,14 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
return Err(Error::too_few_values(a,
|
||||
num,
|
||||
ma.vals.len(),
|
||||
&*self.0.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color()));
|
||||
}
|
||||
}
|
||||
// Issue 665 (https://github.com/kbknapp/clap-rs/issues/665)
|
||||
if a.takes_value() && !a.is_set(ArgSettings::EmptyValues) && ma.vals.is_empty() {
|
||||
return Err(Error::empty_value(a,
|
||||
&*self.0.create_current_usage(matcher, None),
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color()));
|
||||
}
|
||||
Ok(())
|
||||
|
@ -307,9 +326,10 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
debugln!("Validator::validate_arg_requires;");
|
||||
if let Some(a_reqs) = a.requires() {
|
||||
for &(val, name) in a_reqs.iter().filter(|&&(val, _)| val.is_some()) {
|
||||
if ma.vals
|
||||
.iter()
|
||||
.any(|v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(name)) {
|
||||
if ma.vals.iter().any(|v| {
|
||||
v == val.expect(INTERNAL_ERROR_MSG) &&
|
||||
!matcher.contains(name)
|
||||
}) {
|
||||
return self.missing_required_error(matcher, None);
|
||||
}
|
||||
}
|
||||
|
@ -318,7 +338,8 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
}
|
||||
|
||||
fn validate_required(&self, matcher: &ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("Validator::validate_required: required={:?};", self.0.required);
|
||||
debugln!("Validator::validate_required: required={:?};",
|
||||
self.0.required);
|
||||
'outer: for name in &self.0.required {
|
||||
debugln!("Validator::validate_required:iter:{}:", name);
|
||||
if matcher.contains(name) {
|
||||
|
@ -360,7 +381,8 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
a.blacklist().map(|bl| {
|
||||
bl.iter().any(|conf| {
|
||||
matcher.contains(conf) ||
|
||||
self.0.groups
|
||||
self.0
|
||||
.groups
|
||||
.iter()
|
||||
.find(|g| &g.name == conf)
|
||||
.map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg)))
|
||||
|
@ -401,21 +423,26 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
use_stderr: true,
|
||||
when: self.0.color(),
|
||||
};
|
||||
let mut reqs = self.0.required.iter().map(|&r| &*r).collect::<Vec<_>>();
|
||||
let mut reqs = self.0
|
||||
.required
|
||||
.iter()
|
||||
.map(|&r| &*r)
|
||||
.collect::<Vec<_>>();
|
||||
if let Some(r) = extra {
|
||||
reqs.push(r);
|
||||
}
|
||||
reqs.retain(|n| !matcher.contains(n));
|
||||
reqs.dedup();
|
||||
debugln!("Validator::missing_required_error: reqs={:#?}", reqs);
|
||||
Err(Error::missing_required_argument(&*self.0.get_required_from(&reqs[..],
|
||||
Some(matcher),
|
||||
extra)
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| {
|
||||
acc + &format!("\n {}", c.error(s))[..]
|
||||
}),
|
||||
&*self.0.create_current_usage(matcher, extra),
|
||||
Err(Error::missing_required_argument(&*self.0
|
||||
.get_required_from(&reqs[..],
|
||||
Some(matcher),
|
||||
extra)
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| {
|
||||
acc + &format!("\n {}", c.error(s))[..]
|
||||
}),
|
||||
&*usage::create_error_usage(self.0, matcher, extra),
|
||||
self.0.color()))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue