macro_rules! remove_overriden {
- (@remove $_self:ident, $v:ident, $a:ident.$ov:ident) => {
- if let Some(ref ora) = $a.$ov() {
- vec_remove_all!($_self.$v, ora);
+ (@remove_requires $rem_from:expr, $a:ident.$ov:ident) => {
+ if let Some(ora) = $a.$ov() {
+ for i in (0 .. $rem_from.len()).rev() {
+ let should_remove = ora.iter().any(|&(_, ref name)| name == &$rem_from[i]);
+ if should_remove { $rem_from.swap_remove(i); }
+ }
+ }
+ };
+ (@remove $rem_from:expr, $a:ident.$ov:ident) => {
+ if let Some(ora) = $a.$ov() {
+ vec_remove_all!($rem_from, ora.iter());
}
};
(@arg $_self:ident, $arg:ident) => {
- remove_overriden!(@remove $_self, required, $arg.requires);
- remove_overriden!(@remove $_self, blacklist, $arg.blacklist);
- remove_overriden!(@remove $_self, overrides, $arg.overrides);
+ remove_overriden!(@remove_requires $_self.required, $arg.requires);
+ remove_overriden!(@remove $_self.blacklist, $arg.blacklist);
+ remove_overriden!(@remove $_self.overrides, $arg.overrides);
};
($_self:ident, $name:expr) => {
- debugln!("macro=remove_overriden!;");
- if let Some(ref o) = $_self.opts.iter().filter(|o| o.b.name == *$name).next() {
+ debugln!("remove_overriden!;");
+ if let Some(o) = $_self.opts.iter() .find(|o| o.b.name == *$name) {
remove_overriden!(@arg $_self, o);
- } else if let Some(ref f) = $_self.flags.iter().filter(|f| f.b.name == *$name).next() {
+ } else if let Some(f) = $_self.flags.iter() .find(|f| f.b.name == *$name) {
remove_overriden!(@arg $_self, f);
- } else if let Some(p) = $_self.positionals.values().filter(|p| p.b.name == *$name).next() {
+ } else {
+ let p = $_self.positionals.values()
+ .find(|p| p.b.name == *$name)
+ .expect(INTERNAL_ERROR_MSG);
remove_overriden!(@arg $_self, p);
}
};
macro_rules! arg_post_processing {
($me:ident, $arg:ident, $matcher:ident) => {
- debugln!("macro=arg_post_processing!;");
+ debugln!("arg_post_processing!;");
// Handle POSIX overrides
- debug!("Is '{}' in overrides...", $arg.to_string());
+ debug!("arg_post_processing!: Is '{}' in overrides...", $arg.to_string());
if $me.overrides.contains(&$arg.name()) {
if let Some(ref name) = find_name_from!($me, &$arg.name(), overrides, $matcher) {
sdebugln!("Yes by {}", name);
} else { sdebugln!("No"); }
// Add overrides
- debug!("Does '{}' have overrides...", $arg.to_string());
+ debug!("arg_post_processing!: Does '{}' have overrides...", $arg.to_string());
if let Some(or) = $arg.overrides() {
sdebugln!("Yes");
$matcher.remove_all(or);
for pa in or { remove_overriden!($me, pa); }
$me.overrides.extend(or);
- vec_remove_all!($me.required, or);
+ vec_remove_all!($me.required, or.iter());
} else { sdebugln!("No"); }
// Handle conflicts
- debug!("Does '{}' have conflicts...", $arg.to_string());
+ debug!("arg_post_processing!: Does '{}' have conflicts...", $arg.to_string());
if let Some(bl) = $arg.blacklist() {
sdebugln!("Yes");
-
+
for c in bl {
// Inject two-way conflicts
- debug!("Has '{}' already been matched...", c);
+ debug!("arg_post_processing!: Has '{}' already been matched...", c);
if $matcher.contains(c) {
sdebugln!("Yes");
// find who blacklisted us...
}
}
- $me.blacklist.extend(bl);
- vec_remove_all!($me.overrides, bl);
- vec_remove_all!($me.required, bl);
+ $me.blacklist.extend_from_slice(bl);
+ vec_remove_all!($me.overrides, bl.iter());
+ // vec_remove_all!($me.required, bl.iter());
} else { sdebugln!("No"); }
// Add all required args which aren't already found in matcher to the master
// list
- debug!("Does '{}' have requirements...", $arg.to_string());
+ debug!("arg_post_processing!: Does '{}' have requirements...", $arg.to_string());
if let Some(reqs) = $arg.requires() {
- for n in reqs {
- if $matcher.contains(&n) {
- sdebugln!("\tYes '{}' but it's already met", n);
- continue;
- } else { sdebugln!("\tYes '{}'", n); }
-
+ for n in reqs.iter()
+ .filter(|&&(val, _)| val.is_none())
+ .filter(|&&(_, req)| !$matcher.contains(&req))
+ .map(|&(_, name)| name) {
+
$me.required.push(n);
}
} else { sdebugln!("No"); }
macro_rules! _handle_group_reqs{
($me:ident, $arg:ident) => ({
use args::AnyArg;
- debugln!("macro=_handle_group_reqs!;");
- for grp in $me.groups.values() {
+ debugln!("_handle_group_reqs!;");
+ for grp in &$me.groups {
let found = if grp.args.contains(&$arg.name()) {
- vec_remove!($me.required, &$arg.name());
if let Some(ref reqs) = grp.requires {
+ debugln!("_handle_group_reqs!: Adding {:?} to the required list", reqs);
$me.required.extend(reqs);
}
if let Some(ref bl) = grp.conflicts {
} else {
false
};
- debugln!("iter;grp={};found={:?}", grp.name, found);
+ debugln!("_handle_group_reqs!:iter: grp={}, found={:?}", grp.name, found);
if found {
- vec_remove_all!($me.required, &grp.args);
- debugln!("Adding args from group to blacklist...{:?}", grp.args);
+ for i in (0 .. $me.required.len()).rev() {
+ let should_remove = grp.args.contains(&$me.required[i]);
+ if should_remove { $me.required.swap_remove(i); }
+ }
+ debugln!("_handle_group_reqs!:iter: Adding args from group to blacklist...{:?}", grp.args);
if !grp.multiple {
$me.blacklist.extend(&grp.args);
- vec_remove!($me.blacklist, &$arg.name());
+ debugln!("_handle_group_reqs!: removing {:?} from blacklist", $arg.name());
+ for i in (0 .. $me.blacklist.len()).rev() {
+ let should_remove = $me.blacklist[i] == $arg.name();
+ if should_remove { $me.blacklist.swap_remove(i); }
+ }
}
}
}
})
}
-macro_rules! validate_multiples {
- ($_self:ident, $a:ident, $m:ident) => {
- debugln!("macro=validate_multiples!;");
- if $m.contains(&$a.b.name) && !$a.b.settings.is_set(ArgSettings::Multiple) {
- // Not the first time, and we don't allow multiples
- return Err(Error::unexpected_multiple_usage($a,
- &*$_self.create_current_usage($m),
- $_self.color()))
- }
- };
-}
-
macro_rules! parse_positional {
(
$_self:ident,
$pos_counter:ident,
$matcher:ident
) => {
- debugln!("macro=parse_positional!;");
- validate_multiples!($_self, $p, $matcher);
+ debugln!("parse_positional!;");
- if !$_self.trailing_vals &&
- ($_self.settings.is_set(AppSettings::TrailingVarArg) &&
+ if !$_self.is_set(AS::TrailingValues) &&
+ ($_self.is_set(AS::TrailingVarArg) &&
$pos_counter == $_self.positionals.len()) {
- $_self.trailing_vals = true;
+ $_self.settings.set(AS::TrailingValues);
}
let _ = try!($_self.add_val_to_arg($p, &$arg_os, $matcher));
$matcher.inc_occurrence_of($p.b.name);
let _ = $_self.groups_for_arg($p.b.name)
.and_then(|vec| Some($matcher.inc_occurrences_of(&*vec)));
- arg_post_processing!($_self, $p, $matcher);
+ if $_self.cache.map_or(true, |name| name != $p.b.name) {
+ arg_post_processing!($_self, $p, $matcher);
+ $_self.cache = Some($p.b.name);
+ }
+
+ $_self.settings.set(AS::ValidArgFound);
// Only increment the positional counter if it doesn't allow multiples
if !$p.b.settings.is_set(ArgSettings::Multiple) {
$pos_counter += 1;
}
};
}
-
-macro_rules! find_from {
- ($_self:ident, $arg_name:expr, $from:ident, $matcher:expr) => {{
- let mut ret = None;
- for k in $matcher.arg_names() {
- if let Some(f) = find_by_name!($_self, &k, flags, iter) {
- if let Some(ref v) = f.$from() {
- if v.contains($arg_name) {
- ret = Some(f.to_string());
- }
- }
- }
- if let Some(o) = find_by_name!($_self, &k, opts, iter) {
- if let Some(ref v) = o.$from() {
- if v.contains(&$arg_name) {
- ret = Some(o.to_string());
- }
- }
- }
- if let Some(pos) = find_by_name!($_self, &k, positionals, values) {
- if let Some(ref v) = pos.$from() {
- if v.contains($arg_name) {
- ret = Some(pos.b.name.to_owned());
- }
- }
- }
- }
- ret
- }};
-}
-
-macro_rules! find_name_from {
- ($_self:ident, $arg_name:expr, $from:ident, $matcher:expr) => {{
- let mut ret = None;
- for k in $matcher.arg_names() {
- if let Some(f) = find_by_name!($_self, &k, flags, iter) {
- if let Some(ref v) = f.$from() {
- if v.contains($arg_name) {
- ret = Some(f.b.name);
- }
- }
- }
- if let Some(o) = find_by_name!($_self, &k, opts, iter) {
- if let Some(ref v) = o.$from() {
- if v.contains(&$arg_name) {
- ret = Some(o.b.name);
- }
- }
- }
- if let Some(pos) = find_by_name!($_self, &k, positionals, values) {
- if let Some(ref v) = pos.$from() {
- if v.contains($arg_name) {
- ret = Some(pos.b.name);
- }
- }
- }
- }
- ret
- }};
-}
-
-// Finds an arg by name
-macro_rules! find_by_name {
- ($_self:ident, $name:expr, $what:ident, $how:ident) => {
- $_self.$what.$how().find(|o| &o.b.name == $name)
- }
-}
-
-// Finds an option including if it's aliasesed
-macro_rules! find_by_long {
- ($_self:ident, $long:expr, $what:ident) => {
- $_self.$what
- .iter()
- .filter(|o| o.s.long.is_some())
- .find(|o| {
- &&o.s.long.unwrap() == &$long ||
- (o.s.aliases.is_some() &&
- o.s
- .aliases
- .as_ref()
- .unwrap()
- .iter()
- .any(|&(alias, _)| &&alias == &$long))
- })
- }
-}