This commit is contained in:
Kevin K 2015-02-27 14:54:01 -05:00
parent 3ab13ff0d1
commit e753b020e6
5 changed files with 62 additions and 4 deletions

View file

@ -26,7 +26,7 @@ pub struct App {
needs_short_version: bool, needs_short_version: bool,
required: HashSet<&'static str>, required: HashSet<&'static str>,
arg_list: HashSet<&'static str>, arg_list: HashSet<&'static str>,
// blacklist: HashMap<&'static str, Vec<&'static str>> blacklist: HashSet<&'static str>
} }
impl App { impl App {
@ -45,7 +45,8 @@ impl App {
needs_short_help: true, needs_short_help: true,
needs_short_version: true, needs_short_version: true,
required: HashSet::new(), required: HashSet::new(),
arg_list: HashSet::new() arg_list: HashSet::new(),
blacklist: HashSet::new()
} }
} }
@ -204,6 +205,10 @@ impl App {
if s != arg { continue; } if s != arg { continue; }
if !matches.flags.contains_key(k) { if !matches.flags.contains_key(k) {
if self.blacklist.contains(k) {
self.report_error(&format!("The argument -{} is mutually exclusive with one or more other arguments", arg),
false, true);
}
matches.flags.insert(k, v.clone()); matches.flags.insert(k, v.clone());
if self.required.contains(k) { if self.required.contains(k) {
self.required.remove(k); self.required.remove(k);
@ -218,6 +223,13 @@ impl App {
} }
} }
} }
if let Some(ref bl) = v.blacklist {
if ! bl.is_empty() {
for name in bl.iter() {
self.blacklist.insert(k);
}
}
}
} else if matches.flags.get(k).unwrap().multiple { } else if matches.flags.get(k).unwrap().multiple {
matches.flags.get_mut(k).unwrap().occurrences += 1 matches.flags.get_mut(k).unwrap().occurrences += 1
} }
@ -249,6 +261,10 @@ impl App {
for (k, v) in self.opts.iter() { for (k, v) in self.opts.iter() {
if let Some(ref l) = v.long { if let Some(ref l) = v.long {
if *l == arg { if *l == arg {
if self.blacklist.contains(k) {
self.report_error(&format!("The argument --{} is mutually exclusive with one or more other arguments", arg),
false, true);
}
matches.opts.insert(k, OptArg{ matches.opts.insert(k, OptArg{
name: v.name, name: v.name,
short: v.short, short: v.short,
@ -279,10 +295,21 @@ impl App {
// so the 'if let' must finish it's scope first // so the 'if let' must finish it's scope first
// before calling .insert() // before calling .insert()
if ! multi { if ! multi {
if self.blacklist.contains(k) {
self.report_error(&format!("The argument --{} is mutually exclusive with one or more other arguments", arg),
false, true);
}
matches.flags.insert(k, v.clone()); matches.flags.insert(k, v.clone());
if self.required.contains(k) { if self.required.contains(k) {
self.required.remove(k); self.required.remove(k);
} }
if let Some(ref bl) = v.blacklist {
if ! bl.is_empty() {
for name in bl.iter() {
self.blacklist.insert(k);
}
}
}
} }
if let Some(ref reqs) = v.requires { if let Some(ref reqs) = v.requires {
if ! reqs.is_empty() { if ! reqs.is_empty() {
@ -360,6 +387,15 @@ impl App {
let mut skip = false; let mut skip = false;
if let Some(ref nvo) = needs_val_of { if let Some(ref nvo) = needs_val_of {
if let Some(ref opt) = self.opts.get(nvo) { if let Some(ref opt) = self.opts.get(nvo) {
if self.blacklist.contains(opt.name) {
self.report_error(
&format!("The argument {} is mutually exclusive with one or more other arguments",
if let Some(long) = opt.long {
format!("--{}",long)
}else{
format!("-{}",opt.short.unwrap())
}),false, true);
}
matches.opts.insert(nvo, OptArg{ matches.opts.insert(nvo, OptArg{
name: opt.name, name: opt.name,
short: opt.short, short: opt.short,
@ -369,6 +405,13 @@ impl App {
required: opt.required, required: opt.required,
value: Some(arg.clone()) value: Some(arg.clone())
}); });
if let Some(ref bl) = opt.blacklist {
if ! bl.is_empty() {
for name in bl.iter() {
self.blacklist.insert(opt.name);
}
}
}
if self.required.contains(opt.name) { if self.required.contains(opt.name) {
self.required.remove(opt.name); self.required.remove(opt.name);
} }
@ -404,6 +447,10 @@ impl App {
false, true); false, true);
} }
if let Some(ref p) = self.positionals_idx.get(&pos_counter) { if let Some(ref p) = self.positionals_idx.get(&pos_counter) {
if self.blacklist.contains(p.name) {
self.report_error(&format!("The argument \"{}\" is mutually exclusive with one or more other arguments", arg),
false, true);
}
matches.positionals.insert(p.name, PosArg{ matches.positionals.insert(p.name, PosArg{
name: p.name, name: p.name,
help: p.help, help: p.help,
@ -412,6 +459,13 @@ impl App {
value: Some(arg.clone()), value: Some(arg.clone()),
index: pos_counter index: pos_counter
}); });
if let Some(ref bl) = p.blacklist {
if ! bl.is_empty() {
for name in bl.iter() {
self.blacklist.insert(p.name);
}
}
}
if self.required.contains(p.name) { if self.required.contains(p.name) {
self.required.remove(p.name); self.required.remove(p.name);
} }

View file

@ -1,11 +1,12 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::HashSet;
use app::App; use app::App;
use args::{ FlagArg, OptArg, PosArg }; use args::{ FlagArg, OptArg, PosArg };
pub struct ArgMatches { pub struct ArgMatches {
pub required: Vec<&'static str>, pub required: Vec<&'static str>,
pub blacklist: Vec<&'static str>, pub blacklist: HashSet<&'static str>,
pub about: Option<&'static str>, pub about: Option<&'static str>,
pub name: &'static str, pub name: &'static str,
pub author: Option<&'static str>, pub author: Option<&'static str>,
@ -22,7 +23,7 @@ impl ArgMatches {
opts: HashMap::new(), opts: HashMap::new(),
positionals: HashMap::new(), positionals: HashMap::new(),
required: vec![], required: vec![],
blacklist: vec![], blacklist: HashSet::new(),
about: app.about, about: app.about,
name: app.name, name: app.name,
author: app.author, author: app.author,

View file

@ -6,5 +6,6 @@ pub struct FlagArg {
pub help: Option<&'static str>, pub help: Option<&'static str>,
pub multiple: bool, pub multiple: bool,
pub occurrences: u8, pub occurrences: u8,
pub blacklist: Option<Vec<&'static str>>,
pub requires: Option<Vec<&'static str>> pub requires: Option<Vec<&'static str>>
} }

View file

@ -5,5 +5,6 @@ pub struct OptArg {
pub help: Option<&'static str>, pub help: Option<&'static str>,
pub required: bool, pub required: bool,
pub requires: Option<Vec<&'static str>>, pub requires: Option<Vec<&'static str>>,
pub blacklist: Option<Vec<&'static str>>,
pub value: Option<String> pub value: Option<String>
} }

View file

@ -3,6 +3,7 @@ pub struct PosArg {
pub help: Option<&'static str>, pub help: Option<&'static str>,
pub required: bool, pub required: bool,
pub requires: Option<Vec<&'static str>>, pub requires: Option<Vec<&'static str>>,
pub blacklist: Option<Vec<&'static str>>,
pub value: Option<String>, pub value: Option<String>,
pub index: u8 pub index: u8
} }