mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
refactor: changes some arg fields to flags internally
This commit is contained in:
parent
7005cf8c47
commit
b01667ebb3
9 changed files with 257 additions and 230 deletions
125
src/app/app.rs
125
src/app/app.rs
|
@ -12,6 +12,7 @@ use yaml_rust::Yaml;
|
|||
|
||||
use args::{ArgMatches, Arg, SubCommand, MatchedArg};
|
||||
use args::{FlagBuilder, OptBuilder, PosBuilder};
|
||||
use args::settings::{ArgSettings, ArgFlags};
|
||||
use args::ArgGroup;
|
||||
use fmt::Format;
|
||||
use super::settings::{AppSettings, AppFlags};
|
||||
|
@ -790,7 +791,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
}
|
||||
if let Some(l) = a.long {
|
||||
// self.long_list.dedup();
|
||||
if self.long_list.contains(&l) {
|
||||
panic!("Argument long must be unique\n\n\t--{} is already in use", l);
|
||||
} else {
|
||||
|
@ -1084,7 +1084,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
}
|
||||
}
|
||||
res.dedup();
|
||||
if res.is_empty() { return None }
|
||||
|
||||
Some(res)
|
||||
|
@ -1112,7 +1111,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
}
|
||||
|
||||
g_vec.dedup();
|
||||
if !g_vec.is_empty() {
|
||||
for av in g_vec.iter().map(|g| self.get_group_members(g)) {
|
||||
for a in av {
|
||||
|
@ -1145,7 +1143,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
}
|
||||
|
||||
g_vec.dedup();
|
||||
if !g_vec.is_empty() {
|
||||
for av in g_vec.iter().map(|g| self.get_group_members_names(g)) {
|
||||
for a in av {
|
||||
|
@ -1159,10 +1156,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
|
||||
fn get_required_from(&self,
|
||||
mut reqs: Vec<&'ar str>,
|
||||
reqs: Vec<&'ar str>,
|
||||
matches: Option<&ArgMatches>)
|
||||
-> VecDeque<String> {
|
||||
reqs.dedup();
|
||||
let mut c_flags = vec![];
|
||||
let mut c_pos = vec![];
|
||||
let mut c_opt = vec![];
|
||||
|
@ -1318,7 +1314,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
reqs.push(p.name);
|
||||
continue;
|
||||
}
|
||||
if p.required {
|
||||
if p.settings.is_set(&ArgSettings::Required) {
|
||||
found = true;
|
||||
reqs.push(p.name);
|
||||
}
|
||||
|
@ -1336,19 +1332,19 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
usage.push_str(" [OPTIONS]");
|
||||
}
|
||||
if !self.settings.is_set(&AppSettings::UnifiedHelpMessage) && !self.opts.is_empty() &&
|
||||
self.opts.values().any(|a| !a.required) {
|
||||
self.opts.values().any(|a| !a.settings.is_set(&ArgSettings::Required)) {
|
||||
usage.push_str(" [OPTIONS]");
|
||||
}
|
||||
// places a '--' in the usage string if there are args and options
|
||||
// supporting multiple values
|
||||
if !self.positionals_idx.is_empty() && self.opts.values().any(|a| a.multiple ) &&
|
||||
!self.opts.values().any(|a| a.required) &&
|
||||
if !self.positionals_idx.is_empty() && self.opts.values().any(|a| a.settings.is_set(&ArgSettings::Multiple)) &&
|
||||
!self.opts.values().any(|a| a.settings.is_set(&ArgSettings::Required)) &&
|
||||
self.subcommands.is_empty() {
|
||||
usage.push_str(" [--]")
|
||||
}
|
||||
if !self.positionals_idx.is_empty() &&
|
||||
self.positionals_idx.values()
|
||||
.any(|a| !a.required) {
|
||||
.any(|a| !a.settings.is_set(&ArgSettings::Required)) {
|
||||
usage.push_str(" [ARGS]");
|
||||
}
|
||||
|
||||
|
@ -1412,7 +1408,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
let mut longest_flag = 0;
|
||||
for fl in self.flags
|
||||
.values()
|
||||
.filter(|f| f.long.is_some() && !f.hidden)
|
||||
.filter(|f| f.long.is_some() && !f.settings.is_set(&ArgSettings::Hidden))
|
||||
// 2='--'
|
||||
.map(|a| a.to_string().len() ) {
|
||||
if fl > longest_flag {
|
||||
|
@ -1422,7 +1418,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
let mut longest_opt = 0;
|
||||
for ol in self.opts
|
||||
.values()
|
||||
.filter(|o| !o.hidden)
|
||||
.filter(|o| !o.settings.is_set(&ArgSettings::Hidden))
|
||||
.map(|a|
|
||||
a.to_string().len()
|
||||
) {
|
||||
|
@ -1433,7 +1429,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
let mut longest_pos = 0;
|
||||
for pl in self.positionals_idx
|
||||
.values()
|
||||
.filter(|p| !p.hidden)
|
||||
.filter(|p| !p.settings.is_set(&ArgSettings::Hidden))
|
||||
.map(|f| f.to_string().len() ) {
|
||||
if pl > longest_pos {
|
||||
longest_pos = pl;
|
||||
|
@ -1471,7 +1467,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
for v in self.flags
|
||||
.values()
|
||||
.filter(|f| !f.hidden) {
|
||||
.filter(|f| !f.settings.is_set(&ArgSettings::Hidden)) {
|
||||
try!(write!(w, "{}", tab));
|
||||
if let Some(s) = v.short {
|
||||
try!(write!(w, "-{}",s));
|
||||
|
@ -1530,7 +1526,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
for v in self.opts
|
||||
.values()
|
||||
.filter(|o| !o.hidden) {
|
||||
.filter(|o| !o.settings.is_set(&ArgSettings::Hidden)) {
|
||||
// if it supports multiple we add '...' i.e. 3 to the name length
|
||||
try!(write!(w, "{}", tab));
|
||||
if let Some(s) = v.short {
|
||||
|
@ -1550,7 +1546,13 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
try!(write!(w, " <{}>", v.name));
|
||||
}
|
||||
} else {
|
||||
try!(write!(w, " <{}>{}", v.name, if v.multiple{"..."} else {""}));
|
||||
try!(write!(w, " <{}>{}", v.name,
|
||||
if v.settings.is_set(&ArgSettings::Multiple) {
|
||||
"..."
|
||||
} else {
|
||||
""
|
||||
}
|
||||
));
|
||||
}
|
||||
if v.long.is_some() {
|
||||
try!(self.print_spaces(
|
||||
|
@ -1568,11 +1570,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
try!(write!(w, "\nARGS:\n"));
|
||||
for v in self.positionals_idx
|
||||
.values()
|
||||
.filter(|p| !p.hidden) {
|
||||
// let mult = if v.multiple { 3 } else { 0 };
|
||||
.filter(|p| !p.settings.is_set(&ArgSettings::Hidden)) {
|
||||
try!(write!(w, "{}", tab));
|
||||
try!(write!(w, "{}", v.name));
|
||||
if v.multiple {
|
||||
if v.settings.is_set(&ArgSettings::Multiple) {
|
||||
try!(write!(w, "..."));
|
||||
}
|
||||
try!(self.print_spaces((longest_pos + 4) - (v.to_string().len()), w));
|
||||
|
@ -2024,7 +2025,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
}
|
||||
if let Some(ref p) = self.positionals_idx.values()
|
||||
.filter(|a| a.multiple)
|
||||
.filter(|a| a.settings.is_set(&ArgSettings::Multiple))
|
||||
.filter(|a| {
|
||||
a.index as usize != self.positionals_idx.len()
|
||||
})
|
||||
|
@ -2037,11 +2038,11 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
let mut found = false;
|
||||
for (_, p) in self.positionals_idx.iter_mut().rev() {
|
||||
if found {
|
||||
p.required = true;
|
||||
p.settings.set(&ArgSettings::Required);
|
||||
self.required.push(p.name);
|
||||
continue;
|
||||
}
|
||||
if p.required {
|
||||
if p.settings.is_set(&ArgSettings::Required) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
@ -2152,7 +2153,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if let Some(num) = opt.num_vals {
|
||||
if let Some(ref ma) = matches.args.get(opt.name) {
|
||||
if let Some(ref vals) = ma.values {
|
||||
if num == vals.len() as u8 && !opt.multiple {
|
||||
if num == vals.len() as u8 && !opt.settings.is_set(&ArgSettings::Multiple) {
|
||||
return Err(self.report_error(format!("The argument '{}' \
|
||||
was found, but '{}' only expects {} values",
|
||||
Format::Warning(arg_slice),
|
||||
|
@ -2166,7 +2167,7 @@ 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.empty_vals && matches.args.contains_key(opt.name) &&
|
||||
if !opt.settings.is_set(&ArgSettings::EmptyValues) && matches.args.contains_key(opt.name) &&
|
||||
arg_slice.is_empty() {
|
||||
return Err(self.report_error(
|
||||
format!("The argument '{}' does not allow empty values, but one \
|
||||
|
@ -2178,7 +2179,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if let Some(ref vec) = self.groups_for(opt.name) {
|
||||
for grp in vec {
|
||||
if let Some(ref mut o) = matches.args.get_mut(grp) {
|
||||
o.occurrences = if opt.multiple {
|
||||
o.occurrences = if opt.settings.is_set(&ArgSettings::Multiple) {
|
||||
o.occurrences + 1
|
||||
} else {
|
||||
1
|
||||
|
@ -2196,7 +2197,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if let Some(ref mut o) = matches.args.get_mut(opt.name) {
|
||||
// if it's multiple; the occurrences are increased when originally
|
||||
// found
|
||||
o.occurrences = if opt.multiple {
|
||||
o.occurrences = if opt.settings.is_set(&ArgSettings::Multiple) {
|
||||
o.occurrences + 1
|
||||
} else {
|
||||
skip = true;
|
||||
|
@ -2232,7 +2233,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
continue
|
||||
}
|
||||
} else if let Some(num) = opt.num_vals {
|
||||
if opt.multiple {
|
||||
if opt.settings.is_set(&ArgSettings::Multiple) {
|
||||
val_counter += 1;
|
||||
if val_counter != num {
|
||||
continue
|
||||
|
@ -2263,7 +2264,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
} else if let Some(ref name) = needs_val_of {
|
||||
// We've reached more values for an option than it possibly accepts
|
||||
if let Some(ref o) = self.opts.get(name) {
|
||||
if !o.multiple {
|
||||
if !o.settings.is_set(&ArgSettings::Multiple) {
|
||||
return Err(self.report_error(
|
||||
format!("The argument '{}' requires a value but none was supplied",
|
||||
Format::Warning(o.to_string())),
|
||||
|
@ -2340,12 +2341,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
Some(matches.args.keys().map(|k| *k).collect())));
|
||||
} else if let Some(p) = self.positionals_idx.get(&pos_counter) {
|
||||
// Make sure this one doesn't conflict with anything
|
||||
self.blacklist.dedup();
|
||||
if self.blacklist.contains(&p.name) {
|
||||
// we shouldn't need to remove this arg...since it should be matched yet
|
||||
// anyways
|
||||
// matches.args.remove(p.name);
|
||||
|
||||
return Err(self.report_error(format!("The argument '{}' cannot be used \
|
||||
with {}",
|
||||
Format::Warning(p.to_string()),
|
||||
|
@ -2369,7 +2365,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
|
||||
// Have we made the update yet?
|
||||
let mut done = false;
|
||||
if p.multiple {
|
||||
if p.settings.is_set(&ArgSettings::Multiple) {
|
||||
if let Some(num) = p.num_vals {
|
||||
if let Some(ref ma) = matches.args.get(p.name) {
|
||||
if let Some(ref vals) = ma.values {
|
||||
|
@ -2384,7 +2380,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
}
|
||||
}
|
||||
if !p.empty_vals && matches.args.contains_key(p.name) &&
|
||||
if !p.settings.is_set(&ArgSettings::EmptyValues) && matches.args.contains_key(p.name) &&
|
||||
arg_slice.is_empty() {
|
||||
return Err(self.report_error(format!("The argument '{}' does not \
|
||||
allow empty values, but one was found.",
|
||||
|
@ -2407,7 +2403,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
// Was an update made, or is this the first occurrence?
|
||||
if !done {
|
||||
self.overrides.dedup();
|
||||
if self.overrides.contains(&p.name) {
|
||||
if let Some(name) = self.overriden_from(p.name, matches) {
|
||||
matches.args.remove(&*name);
|
||||
|
@ -2422,7 +2417,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
}
|
||||
let mut bm = BTreeMap::new();
|
||||
if !p.empty_vals && arg_slice.is_empty() {
|
||||
if !p.settings.is_set(&ArgSettings::EmptyValues) && arg_slice.is_empty() {
|
||||
return Err(self.report_error(format!("The argument '{}' does not \
|
||||
allow empty values, but one was found.",
|
||||
Format::Warning(p.to_string())),
|
||||
|
@ -2483,7 +2478,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
if let Some(ref a) = needs_val_of {
|
||||
if let Some(o) = self.opts.get(a) {
|
||||
if o.multiple && self.required.is_empty() {
|
||||
if o.settings.is_set(&ArgSettings::Multiple) && self.required.is_empty() {
|
||||
let should_err = match matches.values_of(o.name) {
|
||||
Some(ref v) => v.is_empty(),
|
||||
None => true,
|
||||
|
@ -2495,7 +2490,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
ClapErrorType::EmptyValue,
|
||||
Some(matches.args.keys().map(|k| *k).collect())));
|
||||
}
|
||||
} else if !o.multiple {
|
||||
} else if !o.settings.is_set(&ArgSettings::Multiple) {
|
||||
return Err(self.report_error(
|
||||
format!("The argument '{}' requires a value but none was supplied",
|
||||
Format::Warning(o.to_string())),
|
||||
|
@ -2517,10 +2512,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
.map(|k| *k)
|
||||
.filter(|k| {
|
||||
if let Some(o) = self.opts.get(k) {
|
||||
!o.required
|
||||
!o.settings.is_set(&ArgSettings::Required)
|
||||
} else if let Some(p) = self.positionals_name.get(k) {
|
||||
if let Some(p) = self.positionals_idx.get(p) {
|
||||
!p.required
|
||||
!p.settings.is_set(&ArgSettings::Required)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
@ -2632,10 +2627,10 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
.map(|k| *k)
|
||||
.filter(|k| {
|
||||
if let Some(o) = self.opts.get(k) {
|
||||
!o.required
|
||||
!o.settings.is_set(&ArgSettings::Required)
|
||||
} else if let Some(p) = self.positionals_name.get(k) {
|
||||
if let Some(p) = self.positionals_idx.get(p) {
|
||||
!p.required
|
||||
!p.settings.is_set(&ArgSettings::Required)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
@ -2740,11 +2735,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
long: Some("help"),
|
||||
help: Some("Prints help information"),
|
||||
blacklist: None,
|
||||
multiple: false,
|
||||
global: false,
|
||||
requires: None,
|
||||
overrides: None,
|
||||
hidden: false,
|
||||
settings: ArgFlags::new()
|
||||
};
|
||||
self.long_list.push("help");
|
||||
self.flags.insert("hclap_help", arg);
|
||||
|
@ -2763,11 +2756,9 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
long: Some("version"),
|
||||
help: Some("Prints version information"),
|
||||
blacklist: None,
|
||||
multiple: false,
|
||||
global: false,
|
||||
requires: None,
|
||||
overrides: None,
|
||||
hidden: false,
|
||||
settings: ArgFlags::new()
|
||||
};
|
||||
self.long_list.push("version");
|
||||
self.flags.insert("vclap_version", arg);
|
||||
|
@ -2838,7 +2829,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
.filter(|&v| v.long.is_some())
|
||||
.filter(|&v| v.long.unwrap() == arg).nth(0) {
|
||||
// prevents "--config= value" typo
|
||||
if arg_vec[1].len() == 0 && !v.empty_vals {
|
||||
if arg_vec[1].len() == 0 && !v.settings.is_set(&ArgSettings::EmptyValues) {
|
||||
if let Some(ref vec) = self.groups_for(v.name) {
|
||||
for grp in vec {
|
||||
matches.args.insert(grp, MatchedArg{
|
||||
|
@ -2872,8 +2863,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
ClapErrorType::ArgumentConflict,
|
||||
Some(matches.args.keys().map(|k| *k).collect())));
|
||||
}
|
||||
self.overrides.dedup();
|
||||
debugln!("checking if {} is in overrides", v.name);
|
||||
if self.overrides.contains(&v.name) {
|
||||
debugln!("it is...");
|
||||
debugln!("checking who defined it...");
|
||||
|
@ -2902,7 +2891,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
|
||||
if matches.args.contains_key(v.name) {
|
||||
if !v.multiple {
|
||||
if !v.settings.is_set(&ArgSettings::Multiple) {
|
||||
return Err(self.report_error(format!("The argument '{}' was supplied more \
|
||||
than once, but does not support multiple values",
|
||||
Format::Warning(format!("--{}", arg))),
|
||||
|
@ -3006,7 +2995,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
.filter(|&v| v.long.is_some())
|
||||
.filter(|&v| v.long.unwrap() == arg).nth(0) {
|
||||
// Ensure this flag isn't on the mutually excludes list
|
||||
self.blacklist.dedup();
|
||||
if self.blacklist.contains(&v.name) {
|
||||
matches.args.remove(v.name);
|
||||
return Err(self.report_error(format!("The argument '{}' cannot be used with {}",
|
||||
|
@ -3018,8 +3006,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
ClapErrorType::ArgumentConflict,
|
||||
Some(matches.args.keys().map(|k| *k).collect())));
|
||||
}
|
||||
self.overrides.dedup();
|
||||
debugln!("checking if {} is in overrides", v.name);
|
||||
if self.overrides.contains(&v.name) {
|
||||
debugln!("it is...");
|
||||
debugln!("checking who defined it...");
|
||||
|
@ -3038,7 +3024,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
|
||||
// Make sure this isn't one being added multiple times if it doesn't suppor it
|
||||
if matches.args.contains_key(v.name) && !v.multiple {
|
||||
if matches.args.contains_key(v.name) && !v.settings.is_set(&ArgSettings::Multiple) {
|
||||
return Err(self.report_error(format!("The argument '{}' was supplied more than \
|
||||
once, but does not support multiple values",
|
||||
Format::Warning(v.to_string())),
|
||||
|
@ -3050,7 +3036,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
done = false;
|
||||
if let Some(ref mut f) = matches.args.get_mut(v.name) {
|
||||
done = true;
|
||||
f.occurrences = if v.multiple {
|
||||
f.occurrences = if v.settings.is_set(&ArgSettings::Multiple) {
|
||||
f.occurrences + 1
|
||||
} else {
|
||||
1
|
||||
|
@ -3169,7 +3155,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
return Err(self.possible_values_error(av, &v.to_string(), p_vals, matches));
|
||||
}
|
||||
}
|
||||
if !v.empty_vals && av.is_empty() && matches.args.contains_key(v.name) {
|
||||
if !v.settings.is_set(&ArgSettings::EmptyValues) && av.is_empty() && matches.args.contains_key(v.name) {
|
||||
return Err(self.report_error(format!("The argument '{}' does not allow empty \
|
||||
values, but one was found.", Format::Warning(v.to_string())),
|
||||
ClapErrorType::EmptyValue,
|
||||
|
@ -3244,7 +3230,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
.filter(|&v| v.short.is_some())
|
||||
.filter(|&v| v.short.unwrap() == arg_c).nth(0) {
|
||||
// Ensure this option isn't on the master mutually excludes list
|
||||
self.blacklist.dedup();
|
||||
if self.blacklist.contains(&v.name) {
|
||||
matches.args.remove(v.name);
|
||||
return Err(self.report_error(format!("The argument '{}' cannot be used with {}",
|
||||
|
@ -3256,7 +3241,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
ClapErrorType::ArgumentConflict,
|
||||
Some(matches.args.keys().map(|k| *k).collect())));
|
||||
}
|
||||
self.overrides.dedup();
|
||||
if self.overrides.contains(&v.name) {
|
||||
if let Some(name) = self.overriden_from(v.name, matches) {
|
||||
matches.args.remove(&*name);
|
||||
|
@ -3272,7 +3256,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
|
||||
if matches.args.contains_key(v.name) {
|
||||
if !v.multiple {
|
||||
if !v.settings.is_set(&ArgSettings::Multiple) {
|
||||
return Err(self.report_error(format!("The argument '{}' was supplied more \
|
||||
than once, but does not support multiple values",
|
||||
Format::Warning(format!("-{}", arg))),
|
||||
|
@ -3334,7 +3318,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
.filter(|&v| v.short.is_some())
|
||||
.filter(|&v| v.short.unwrap() == arg).nth(0) {
|
||||
// Ensure this flag isn't on the mutually excludes list
|
||||
self.blacklist.dedup();
|
||||
if self.blacklist.contains(&v.name) {
|
||||
matches.args.remove(v.name);
|
||||
return Err(self.report_error(format!("The argument '{}' cannot be used {}",
|
||||
|
@ -3347,8 +3330,6 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
ClapErrorType::ArgumentConflict,
|
||||
Some(matches.args.keys().map(|k| *k).collect())));
|
||||
}
|
||||
self.overrides.dedup();
|
||||
debugln!("checking if {} is in overrides", v.name);
|
||||
if self.overrides.contains(&v.name) {
|
||||
debugln!("it is...");
|
||||
debugln!("checking who defined it...");
|
||||
|
@ -3367,7 +3348,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
}
|
||||
|
||||
// Make sure this isn't one being added multiple times if it doesn't suppor it
|
||||
if matches.args.contains_key(v.name) && !v.multiple {
|
||||
if matches.args.contains_key(v.name) && !v.settings.is_set(&ArgSettings::Multiple) {
|
||||
return Err(self.report_error(format!("The argument '{}' was supplied more than \
|
||||
once, but does not support multiple values",
|
||||
Format::Warning(format!("-{}", arg))),
|
||||
|
@ -3378,7 +3359,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
if let Some(ref vec) = self.groups_for(v.name) {
|
||||
for grp in vec {
|
||||
if let Some(ref mut f) = matches.args.get_mut(grp) {
|
||||
f.occurrences = if v.multiple {
|
||||
f.occurrences = if v.settings.is_set(&ArgSettings::Multiple) {
|
||||
f.occurrences + 1
|
||||
} else {
|
||||
1
|
||||
|
@ -3389,7 +3370,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
let mut done = false;
|
||||
if let Some(ref mut f) = matches.args.get_mut(v.name) {
|
||||
done = true;
|
||||
f.occurrences = if v.multiple {
|
||||
f.occurrences = if v.settings.is_set(&ArgSettings::Multiple) {
|
||||
f.occurrences + 1
|
||||
} else {
|
||||
1
|
||||
|
@ -3495,7 +3476,7 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
} else if let Some(ref vals) = ma.values {
|
||||
if let Some(f) = self.opts.get(name) {
|
||||
if let Some(num) = f.num_vals {
|
||||
let should_err = if f.multiple {
|
||||
let should_err = if f.settings.is_set(&ArgSettings::Multiple) {
|
||||
((vals.len() as u8) % num) != 0
|
||||
} else {
|
||||
num != (vals.len() as u8)
|
||||
|
@ -3505,13 +3486,13 @@ impl<'a, 'v, 'ab, 'u, 'h, 'ar> App<'a, 'v, 'ab, 'u, 'h, 'ar>{
|
|||
values, but {} w{} provided",
|
||||
Format::Warning(f.to_string()),
|
||||
Format::Good(num.to_string()),
|
||||
Format::Error(if f.multiple {
|
||||
Format::Error(if f.settings.is_set(&ArgSettings::Multiple) {
|
||||
(vals.len() % num as usize).to_string()
|
||||
} else {
|
||||
vals.len().to_string()
|
||||
}),
|
||||
if vals.len() == 1 ||
|
||||
( f.multiple &&
|
||||
( f.settings.is_set(&ArgSettings::Multiple) &&
|
||||
( vals.len() % num as usize) == 1) {"as"}else{"ere"}),
|
||||
ClapErrorType::EmptyValue,
|
||||
Some(matches.args.keys().map(|k| *k).collect())));
|
||||
|
|
|
@ -85,7 +85,7 @@ pub struct Arg<'n, 'l, 'h, 'g, 'p, 'r> {
|
|||
pub min_vals: Option<u8>,
|
||||
/// Specifies whether or not this argument accepts explicit empty values such as `--option ""`
|
||||
pub empty_vals: bool,
|
||||
/// Specifies whether or not this argument is global and should be propogated through all
|
||||
/// Specifies whether or not this argument is global and should be propagated through all
|
||||
/// child subcommands
|
||||
pub global: bool,
|
||||
/// A function used to check the validity of an argument value. Failing this validation results
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::fmt::{Display, Formatter, Result};
|
|||
use std::convert::From;
|
||||
|
||||
use Arg;
|
||||
use args::settings::{ArgFlags, ArgSettings};
|
||||
|
||||
pub struct FlagBuilder<'n> {
|
||||
pub name: &'n str,
|
||||
|
@ -13,10 +14,6 @@ pub struct FlagBuilder<'n> {
|
|||
/// the user when the application's `help`
|
||||
/// text is displayed
|
||||
pub help: Option<&'n str>,
|
||||
/// Determines if multiple instances of the same
|
||||
/// flag are allowed
|
||||
/// I.e. `-v -v -v` or `-vvv`
|
||||
pub multiple: bool,
|
||||
/// A list of names for other arguments that
|
||||
/// *may not* be used with this flag
|
||||
pub blacklist: Option<Vec<&'n str>>,
|
||||
|
@ -27,10 +24,24 @@ pub struct FlagBuilder<'n> {
|
|||
/// The short version (i.e. single character)
|
||||
/// of the argument, no preceding `-`
|
||||
pub short: Option<char>,
|
||||
pub global: bool,
|
||||
/// A list of names for other arguments that *mutually override* this flag
|
||||
pub overrides: Option<Vec<&'n str>>,
|
||||
pub hidden: bool
|
||||
pub settings: ArgFlags,
|
||||
}
|
||||
|
||||
impl<'n> FlagBuilder<'n> {
|
||||
pub fn new(name: &'n str) -> Self {
|
||||
FlagBuilder {
|
||||
name: name,
|
||||
short: None,
|
||||
long: None,
|
||||
help: None,
|
||||
blacklist: None,
|
||||
requires: None,
|
||||
overrides: None,
|
||||
settings: ArgFlags::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'a> From<&'a Arg<'n, 'n, 'n, 'n, 'n, 'n>> for FlagBuilder<'n> {
|
||||
|
@ -60,12 +71,19 @@ impl<'n, 'a> From<&'a Arg<'n, 'n, 'n, 'n, 'n, 'n>> for FlagBuilder<'n> {
|
|||
long: a.long,
|
||||
help: a.help,
|
||||
blacklist: None,
|
||||
global: a.global,
|
||||
multiple: a.multiple,
|
||||
requires: None,
|
||||
overrides: None,
|
||||
hidden: a.hidden
|
||||
settings: ArgFlags::new()
|
||||
};
|
||||
if a.multiple {
|
||||
fb.settings.set(&ArgSettings::Multiple);
|
||||
}
|
||||
if a.global {
|
||||
fb.settings.set(&ArgSettings::Global);
|
||||
}
|
||||
if a.hidden {
|
||||
fb.settings.set(&ArgSettings::Hidden);
|
||||
}
|
||||
// Check if there is anything in the blacklist (mutually excludes list) and add any
|
||||
// values
|
||||
if let Some(ref bl) = a.blacklist {
|
||||
|
@ -74,7 +92,6 @@ impl<'n, 'a> From<&'a Arg<'n, 'n, 'n, 'n, 'n, 'n>> for FlagBuilder<'n> {
|
|||
for n in bl {
|
||||
bhs.push(*n);
|
||||
}
|
||||
bhs.dedup();
|
||||
fb.blacklist = Some(bhs);
|
||||
}
|
||||
// Check if there is anything in the requires list and add any values
|
||||
|
@ -84,7 +101,6 @@ impl<'n, 'a> From<&'a Arg<'n, 'n, 'n, 'n, 'n, 'n>> for FlagBuilder<'n> {
|
|||
for n in r {
|
||||
rhs.push(*n);
|
||||
}
|
||||
rhs.dedup();
|
||||
fb.requires = Some(rhs);
|
||||
}
|
||||
if let Some(ref or) = a.overrides {
|
||||
|
@ -93,7 +109,6 @@ impl<'n, 'a> From<&'a Arg<'n, 'n, 'n, 'n, 'n, 'n>> for FlagBuilder<'n> {
|
|||
for n in or {
|
||||
bhs.push(*n);
|
||||
}
|
||||
bhs.dedup();
|
||||
fb.overrides = Some(bhs);
|
||||
}
|
||||
|
||||
|
@ -115,36 +130,18 @@ impl<'n> Display for FlagBuilder<'n> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::FlagBuilder;
|
||||
use args::settings::ArgSettings;
|
||||
|
||||
#[test]
|
||||
fn flagbuilder_display() {
|
||||
let f = FlagBuilder {
|
||||
name: "flg",
|
||||
short: None,
|
||||
long: Some("flag"),
|
||||
help: None,
|
||||
multiple: true,
|
||||
blacklist: None,
|
||||
requires: None,
|
||||
global: false,
|
||||
overrides: None,
|
||||
hidden: false,
|
||||
};
|
||||
let mut f = FlagBuilder::new("flg");
|
||||
f.settings.set(&ArgSettings::Multiple);
|
||||
f.long = Some("flag");
|
||||
|
||||
assert_eq!(&*format!("{}", f), "--flag");
|
||||
|
||||
let f2 = FlagBuilder {
|
||||
name: "flg",
|
||||
short: Some('f'),
|
||||
long: None,
|
||||
help: None,
|
||||
multiple: false,
|
||||
blacklist: None,
|
||||
requires: None,
|
||||
global: false,
|
||||
overrides: None,
|
||||
hidden: false,
|
||||
};
|
||||
let mut f2 = FlagBuilder::new("flg");
|
||||
f2.short = Some('f');
|
||||
|
||||
assert_eq!(&*format!("{}", f2), "-f");
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ pub use self::flag::FlagBuilder;
|
|||
pub use self::option::OptBuilder;
|
||||
pub use self::positional::PosBuilder;
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod flag;
|
||||
#[allow(dead_code)]
|
||||
mod positional;
|
||||
#[allow(dead_code)]
|
||||
mod option;
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::fmt::{Display, Formatter, Result};
|
|||
use std::result::Result as StdResult;
|
||||
|
||||
use Arg;
|
||||
use args::settings::{ArgFlags, ArgSettings};
|
||||
|
||||
pub struct OptBuilder<'n> {
|
||||
pub name: &'n str,
|
||||
|
@ -14,15 +15,8 @@ pub struct OptBuilder<'n> {
|
|||
/// The string of text that will displayed to the user when the application's
|
||||
/// `help` text is displayed
|
||||
pub help: Option<&'n str>,
|
||||
/// Allow multiple occurrences of an option argument such as "-c some -c other"
|
||||
pub multiple: bool,
|
||||
/// A list of names for other arguments that *may not* be used with this flag
|
||||
pub blacklist: Option<Vec<&'n str>>,
|
||||
/// If this is a required by default when using the command line program
|
||||
/// i.e. a configuration file that's required for the program to function
|
||||
/// **NOTE:** required by default means, it is required *until* mutually
|
||||
/// exclusive arguments are evaluated.
|
||||
pub required: bool,
|
||||
/// A list of possible values for this argument
|
||||
pub possible_vals: Option<Vec<&'n str>>,
|
||||
/// A list of names of other arguments that are *required* to be used when
|
||||
|
@ -32,15 +26,32 @@ pub struct OptBuilder<'n> {
|
|||
pub min_vals: Option<u8>,
|
||||
pub max_vals: Option<u8>,
|
||||
pub val_names: Option<BTreeSet<&'n str>>,
|
||||
pub empty_vals: bool,
|
||||
pub global: bool,
|
||||
pub validator: Option<Rc<Fn(String) -> StdResult<(), String>>>,
|
||||
/// A list of names for other arguments that *mutually override* this flag
|
||||
pub overrides: Option<Vec<&'n str>>,
|
||||
pub hidden: bool
|
||||
pub settings: ArgFlags,
|
||||
}
|
||||
|
||||
impl<'n> OptBuilder<'n> {
|
||||
pub fn new(name: &'n str) -> Self {
|
||||
OptBuilder {
|
||||
name: name,
|
||||
short: None,
|
||||
long: None,
|
||||
help: None,
|
||||
blacklist: None,
|
||||
possible_vals: None,
|
||||
requires: None,
|
||||
num_vals: None,
|
||||
min_vals: None,
|
||||
max_vals: None,
|
||||
val_names: None,
|
||||
validator: None,
|
||||
overrides: None,
|
||||
settings: ArgFlags::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_arg(a: &Arg<'n, 'n, 'n, 'n, 'n,'n>,
|
||||
reqs: &mut Vec<&'n str>) -> Self {
|
||||
if a.short.is_none() && a.long.is_none() {
|
||||
|
@ -52,30 +63,41 @@ impl<'n> OptBuilder<'n> {
|
|||
name: a.name,
|
||||
short: a.short,
|
||||
long: a.long,
|
||||
multiple: a.multiple,
|
||||
blacklist: None,
|
||||
help: a.help,
|
||||
global: a.global,
|
||||
possible_vals: None,
|
||||
num_vals: a.num_vals,
|
||||
min_vals: a.min_vals,
|
||||
max_vals: a.max_vals,
|
||||
val_names: a.val_names.clone(),
|
||||
requires: None,
|
||||
required: a.required,
|
||||
empty_vals: a.empty_vals,
|
||||
validator: None,
|
||||
overrides: None,
|
||||
hidden: a.hidden
|
||||
settings: ArgFlags::new()
|
||||
};
|
||||
if a.multiple {
|
||||
ob.settings.set(&ArgSettings::Multiple);
|
||||
}
|
||||
if a.required {
|
||||
ob.settings.set(&ArgSettings::Required);
|
||||
}
|
||||
if a.global {
|
||||
ob.settings.set(&ArgSettings::Global);
|
||||
}
|
||||
if !a.empty_vals {
|
||||
ob.settings.unset(&ArgSettings::Global);
|
||||
}
|
||||
if a.hidden {
|
||||
ob.settings.set(&ArgSettings::Hidden);
|
||||
}
|
||||
if let Some(ref vec) = ob.val_names {
|
||||
ob.num_vals = Some(vec.len() as u8);
|
||||
}
|
||||
if ob.min_vals.is_some() && !ob.multiple {
|
||||
if ob.min_vals.is_some() && !a.multiple {
|
||||
panic!("Argument \"{}\" does not allow multiple values, yet it is expecting {} \
|
||||
values", ob.name, ob.num_vals.unwrap());
|
||||
}
|
||||
if ob.max_vals.is_some() && !ob.multiple {
|
||||
if ob.max_vals.is_some() && !a.multiple {
|
||||
panic!("Argument \"{}\" does not allow multiple values, yet it is expecting {} \
|
||||
values", ob.name, ob.num_vals.unwrap());
|
||||
}
|
||||
|
@ -87,7 +109,6 @@ impl<'n> OptBuilder<'n> {
|
|||
for n in bl {
|
||||
bhs.push(*n);
|
||||
}
|
||||
bhs.dedup();
|
||||
ob.blacklist = Some(bhs);
|
||||
}
|
||||
if let Some(ref p) = a.validator {
|
||||
|
@ -99,11 +120,10 @@ impl<'n> OptBuilder<'n> {
|
|||
// without derefing n = &&str
|
||||
for n in r {
|
||||
rhs.push(*n);
|
||||
if ob.required {
|
||||
if a.required {
|
||||
reqs.push(*n);
|
||||
}
|
||||
}
|
||||
rhs.dedup();
|
||||
ob.requires = Some(rhs);
|
||||
}
|
||||
if let Some(ref or) = a.overrides {
|
||||
|
@ -112,7 +132,6 @@ impl<'n> OptBuilder<'n> {
|
|||
for n in or {
|
||||
bhs.push(*n);
|
||||
}
|
||||
bhs.dedup();
|
||||
ob.overrides = Some(bhs);
|
||||
}
|
||||
// Check if there is anything in the possible values and add those as well
|
||||
|
@ -150,7 +169,7 @@ impl<'n> Display for OptBuilder<'n> {
|
|||
for _ in (0..num) {
|
||||
try!(write!(f, " <{}>", self.name));
|
||||
}
|
||||
if self.multiple && num == 1 {
|
||||
if self.settings.is_set(&ArgSettings::Multiple) && num == 1 {
|
||||
try!(write!(f, "..."));
|
||||
}
|
||||
}
|
||||
|
@ -163,29 +182,13 @@ impl<'n> Display for OptBuilder<'n> {
|
|||
mod test {
|
||||
use super::OptBuilder;
|
||||
use std::collections::BTreeSet;
|
||||
use args::settings::ArgSettings;
|
||||
|
||||
#[test]
|
||||
fn optbuilder_display() {
|
||||
let o = OptBuilder {
|
||||
name: "opt",
|
||||
short: None,
|
||||
long: Some("option"),
|
||||
help: None,
|
||||
multiple: true,
|
||||
blacklist: None,
|
||||
required: false,
|
||||
possible_vals: None,
|
||||
requires: None,
|
||||
num_vals: None,
|
||||
min_vals: None,
|
||||
max_vals: None,
|
||||
val_names: None,
|
||||
empty_vals: true,
|
||||
global: false,
|
||||
validator: None,
|
||||
overrides: None,
|
||||
hidden: false,
|
||||
};
|
||||
let mut o = OptBuilder::new("opt");
|
||||
o.long = Some("option");
|
||||
o.settings.set(&ArgSettings::Multiple);
|
||||
|
||||
assert_eq!(&*format!("{}", o), "--option <opt>...");
|
||||
|
||||
|
@ -193,26 +196,9 @@ mod test {
|
|||
v_names.insert("file");
|
||||
v_names.insert("name");
|
||||
|
||||
let o2 = OptBuilder {
|
||||
name: "opt",
|
||||
short: Some('o'),
|
||||
long: None,
|
||||
help: None,
|
||||
multiple: false,
|
||||
blacklist: None,
|
||||
required: false,
|
||||
possible_vals: None,
|
||||
requires: None,
|
||||
num_vals: None,
|
||||
min_vals: None,
|
||||
max_vals: None,
|
||||
val_names: Some(v_names),
|
||||
empty_vals: true,
|
||||
global: false,
|
||||
validator: None,
|
||||
overrides: None,
|
||||
hidden: false,
|
||||
};
|
||||
let mut o2 = OptBuilder::new("opt");
|
||||
o2.short = Some('o');
|
||||
o2.val_names = Some(v_names);
|
||||
|
||||
assert_eq!(&*format!("{}", o2), "-o <file> <name>");
|
||||
}
|
||||
|
|
|
@ -3,19 +3,13 @@ use std::result::Result as StdResult;
|
|||
use std::rc::Rc;
|
||||
|
||||
use Arg;
|
||||
use args::settings::{ArgFlags, ArgSettings};
|
||||
|
||||
pub struct PosBuilder<'n> {
|
||||
pub name: &'n str,
|
||||
/// The string of text that will displayed to the user when the application's
|
||||
/// `help` text is displayed
|
||||
pub help: Option<&'n str>,
|
||||
/// If this is a required by default when using the command line program
|
||||
/// i.e. a configuration file that's required for the program to function
|
||||
/// **NOTE:** required by default means, it is required *until* mutually
|
||||
/// exclusive arguments are evaluated.
|
||||
pub required: bool,
|
||||
/// Allow multiple occurrences of an option argument such as "-c some -c other"
|
||||
pub multiple: bool,
|
||||
/// A list of names of other arguments that are *required* to be used when
|
||||
/// this flag is used
|
||||
pub requires: Option<Vec<&'n str>>,
|
||||
|
@ -28,15 +22,30 @@ pub struct PosBuilder<'n> {
|
|||
pub num_vals: Option<u8>,
|
||||
pub max_vals: Option<u8>,
|
||||
pub min_vals: Option<u8>,
|
||||
pub empty_vals: bool,
|
||||
pub global: bool,
|
||||
pub validator: Option<Rc<Fn(String) -> StdResult<(), String>>>,
|
||||
/// A list of names for other arguments that *mutually override* this flag
|
||||
pub overrides: Option<Vec<&'n str>>,
|
||||
pub hidden: bool
|
||||
pub settings: ArgFlags,
|
||||
}
|
||||
|
||||
impl<'n> PosBuilder<'n> {
|
||||
pub fn new(name: &'n str, idx: u8) -> Self {
|
||||
PosBuilder {
|
||||
name: name,
|
||||
index: idx,
|
||||
help: None,
|
||||
blacklist: None,
|
||||
possible_vals: None,
|
||||
requires: None,
|
||||
num_vals: None,
|
||||
min_vals: None,
|
||||
max_vals: None,
|
||||
validator: None,
|
||||
overrides: None,
|
||||
settings: ArgFlags::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_arg(a: &Arg<'n, 'n, 'n, 'n, 'n, 'n>,
|
||||
idx: u8,
|
||||
reqs: &mut Vec<&'n str>) -> Self {
|
||||
|
@ -61,8 +70,6 @@ impl<'n> PosBuilder<'n> {
|
|||
let mut pb = PosBuilder {
|
||||
name: a.name,
|
||||
index: idx,
|
||||
required: a.required,
|
||||
multiple: a.multiple,
|
||||
blacklist: None,
|
||||
requires: None,
|
||||
possible_vals: None,
|
||||
|
@ -70,17 +77,27 @@ impl<'n> PosBuilder<'n> {
|
|||
min_vals: a.min_vals,
|
||||
max_vals: a.max_vals,
|
||||
help: a.help,
|
||||
global: a.global,
|
||||
empty_vals: a.empty_vals,
|
||||
validator: None,
|
||||
overrides: None,
|
||||
hidden: a.hidden
|
||||
settings: ArgFlags::new()
|
||||
};
|
||||
if pb.min_vals.is_some() && !pb.multiple {
|
||||
if a.multiple {
|
||||
pb.settings.set(&ArgSettings::Multiple);
|
||||
}
|
||||
if a.required {
|
||||
pb.settings.set(&ArgSettings::Required);
|
||||
}
|
||||
if a.global {
|
||||
pb.settings.set(&ArgSettings::Global);
|
||||
}
|
||||
if a.hidden {
|
||||
pb.settings.set(&ArgSettings::Hidden);
|
||||
}
|
||||
if pb.min_vals.is_some() && !a.multiple {
|
||||
panic!("Argument \"{}\" does not allow multiple values, yet it is expecting {} \
|
||||
values", pb.name, pb.num_vals.unwrap());
|
||||
}
|
||||
if pb.max_vals.is_some() && !pb.multiple {
|
||||
if pb.max_vals.is_some() && !a.multiple {
|
||||
panic!("Argument \"{}\" does not allow multiple values, yet it is expecting {} \
|
||||
values", pb.name, pb.num_vals.unwrap());
|
||||
}
|
||||
|
@ -92,7 +109,6 @@ impl<'n> PosBuilder<'n> {
|
|||
for n in bl {
|
||||
bhs.push(*n);
|
||||
}
|
||||
bhs.dedup();
|
||||
pb.blacklist = Some(bhs);
|
||||
}
|
||||
if let Some(ref or) = a.overrides {
|
||||
|
@ -101,7 +117,6 @@ impl<'n> PosBuilder<'n> {
|
|||
for n in or {
|
||||
bhs.push(*n);
|
||||
}
|
||||
bhs.dedup();
|
||||
pb.overrides = Some(bhs);
|
||||
}
|
||||
// Check if there is anything in the possible values and add those as well
|
||||
|
@ -122,11 +137,10 @@ impl<'n> PosBuilder<'n> {
|
|||
// without derefing n = &&str
|
||||
for n in r {
|
||||
rhs.push(*n);
|
||||
if pb.required {
|
||||
if a.required {
|
||||
reqs.push(*n);
|
||||
}
|
||||
}
|
||||
rhs.dedup();
|
||||
pb.requires = Some(rhs);
|
||||
}
|
||||
|
||||
|
@ -138,12 +152,12 @@ impl<'n> Display for PosBuilder<'n> {
|
|||
fn fmt(&self,
|
||||
f: &mut Formatter)
|
||||
-> Result {
|
||||
if self.required {
|
||||
if self.settings.is_set(&ArgSettings::Required) {
|
||||
try!(write!(f, "<{}>", self.name));
|
||||
} else {
|
||||
try!(write!(f, "[{}]", self.name));
|
||||
}
|
||||
if self.multiple {
|
||||
if self.settings.is_set(&ArgSettings::Multiple) {
|
||||
try!(write!(f, "..."));
|
||||
}
|
||||
|
||||
|
@ -153,48 +167,17 @@ impl<'n> Display for PosBuilder<'n> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::PosBuilder;
|
||||
use args::settings::ArgSettings;
|
||||
|
||||
#[test]
|
||||
fn posbuilder_display() {
|
||||
let p = PosBuilder {
|
||||
name: "pos",
|
||||
help: None,
|
||||
multiple: true,
|
||||
blacklist: None,
|
||||
required: false,
|
||||
possible_vals: None,
|
||||
requires: None,
|
||||
num_vals: None,
|
||||
min_vals: None,
|
||||
max_vals: None,
|
||||
index: 1,
|
||||
empty_vals: true,
|
||||
global: false,
|
||||
validator: None,
|
||||
overrides: None,
|
||||
hidden: false,
|
||||
};
|
||||
let mut p = PosBuilder::new("pos", 1);
|
||||
p.settings.set(&ArgSettings::Multiple);
|
||||
|
||||
assert_eq!(&*format!("{}", p), "[pos]...");
|
||||
|
||||
let p2 = PosBuilder {
|
||||
name: "pos",
|
||||
help: None,
|
||||
multiple: false,
|
||||
blacklist: None,
|
||||
required: true,
|
||||
possible_vals: None,
|
||||
requires: None,
|
||||
num_vals: None,
|
||||
min_vals: None,
|
||||
max_vals: None,
|
||||
index: 1,
|
||||
empty_vals: true,
|
||||
global: false,
|
||||
validator: None,
|
||||
overrides: None,
|
||||
hidden: false,
|
||||
};
|
||||
let mut p2 = PosBuilder::new("pos", 1);
|
||||
p2.settings.set(&ArgSettings::Required);
|
||||
|
||||
assert_eq!(&*format!("{}", p2), "<pos>");
|
||||
}
|
||||
|
|
|
@ -11,3 +11,5 @@ mod subcommand;
|
|||
mod argbuilder;
|
||||
mod matchedarg;
|
||||
mod group;
|
||||
#[allow(dead_code)]
|
||||
pub mod settings;
|
74
src/args/settings.rs
Normal file
74
src/args/settings.rs
Normal file
|
@ -0,0 +1,74 @@
|
|||
use std::str::FromStr;
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
bitflags! {
|
||||
flags Flags: u8 {
|
||||
const REQUIRED = 0b000001,
|
||||
const MULTIPLE = 0b000100,
|
||||
const EMPTY_VALS = 0b001000,
|
||||
const GLOBAL = 0b010000,
|
||||
const HIDDEN = 0b100000,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ArgFlags(Flags);
|
||||
|
||||
impl ArgFlags {
|
||||
pub fn new() -> Self {
|
||||
ArgFlags(EMPTY_VALS)
|
||||
}
|
||||
|
||||
pub fn set(&mut self, s: &ArgSettings) {
|
||||
match *s {
|
||||
ArgSettings::Required => self.0.insert(REQUIRED),
|
||||
ArgSettings::Multiple => self.0.insert(MULTIPLE),
|
||||
ArgSettings::EmptyValues => self.0.insert(EMPTY_VALS),
|
||||
ArgSettings::Global => self.0.insert(GLOBAL),
|
||||
ArgSettings::Hidden => self.0.insert(HIDDEN),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unset(&mut self, s: &ArgSettings) {
|
||||
match *s {
|
||||
ArgSettings::Required => self.0.remove(REQUIRED),
|
||||
ArgSettings::Multiple => self.0.remove(MULTIPLE),
|
||||
ArgSettings::EmptyValues => self.0.remove(EMPTY_VALS),
|
||||
ArgSettings::Global => self.0.remove(GLOBAL),
|
||||
ArgSettings::Hidden => self.0.remove(HIDDEN),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_set(&self, s: &ArgSettings) -> bool {
|
||||
match *s {
|
||||
ArgSettings::Required => self.0.contains(REQUIRED),
|
||||
ArgSettings::Multiple => self.0.contains(MULTIPLE),
|
||||
ArgSettings::EmptyValues => self.0.contains(EMPTY_VALS),
|
||||
ArgSettings::Global => self.0.contains(GLOBAL),
|
||||
ArgSettings::Hidden => self.0.contains(HIDDEN),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ArgSettings {
|
||||
Required,
|
||||
Multiple,
|
||||
EmptyValues,
|
||||
Global,
|
||||
Hidden,
|
||||
}
|
||||
|
||||
impl FromStr for ArgSettings {
|
||||
type Err = String;
|
||||
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
|
||||
match &*s.to_ascii_lowercase() {
|
||||
"required" => Ok(ArgSettings::Required),
|
||||
"multiple" => Ok(ArgSettings::Multiple),
|
||||
"global" => Ok(ArgSettings::Global),
|
||||
"emptyvalues" => Ok(ArgSettings::EmptyValues),
|
||||
"hidden" => Ok(ArgSettings::Hidden),
|
||||
_ => Err("unknown ArgSetting, cannot convert from str".to_owned())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@ macro_rules! vec_remove {
|
|||
}
|
||||
}
|
||||
if let Some(i) = ix {
|
||||
$vec.dedup();
|
||||
$vec.remove(i);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue