Skip to content

Commit

Permalink
imp(ArgMatcher): huge refactor and deduplication of code
Browse files Browse the repository at this point in the history
Tons of code has been moved into functions, deduplicated, made much
easier to read, maintain, and understand. Comments still need to be
added, but that will happen shortly. Modules have also been moved around
to follow Rust conventions and best practices.

All functionality remains exactly the same
  • Loading branch information
kbknapp committed Nov 11, 2015
1 parent 5800cde commit 8988853
Show file tree
Hide file tree
Showing 17 changed files with 887 additions and 1,167 deletions.
2 changes: 1 addition & 1 deletion benches/03_complex.rs
Expand Up @@ -212,7 +212,7 @@ fn parse_sc_positional(b: &mut Bencher) {

#[bench]
fn parse_complex1(b: &mut Bencher) {
b.iter(|| create_app!().get_matches_from(vec!["", "-ff", "-o", "option1", "arg1", "-O", "fast", "arg2", "--multvals", "one", "two", "three"]));
b.iter(|| create_app!().get_matches_from(vec!["", "-ff", "-o", "option1", "arg1", "-O", "fast", "arg2", "--multvals", "one", "two", "emacs"]));
}

#[bench]
Expand Down
4 changes: 2 additions & 2 deletions clap-tests/run_tests.py
Expand Up @@ -217,14 +217,14 @@
positional present with value: too
subcmd NOT present'''

_mult_vals_more = '''error: The argument '--multvals' was supplied more than once, but does not support multiple values
_mult_vals_more = '''error: The argument '--multvals <one> <two>' was supplied more than once, but does not support multiple occurrences
USAGE:
\tclaptests --multvals <one> <two>
For more information try --help'''

_mult_vals_few = '''error: The argument '--multvals <one> <two>' requires a value but none was supplied
_mult_vals_few = '''error: The argument '--multvals <one> <two>' requires 2 values, but 1 was provided
USAGE:
\tclaptests --multvals <one> <two>
Expand Down
130 changes: 130 additions & 0 deletions src/app/macros.rs
@@ -0,0 +1,130 @@
macro_rules! remove_overriden {
($me:ident, $name:expr) => ({
if let Some(ref o) = $me.opts.iter().filter(|o| &o.name == $name).next() {
if let Some(ref ora) = o.requires {
for a in ora {
vec_remove!($me.required, a);
}
}
if let Some(ref ora) = o.blacklist {
for a in ora {
vec_remove!($me.blacklist, a);
}
}
if let Some(ref ora) = o.overrides {
for a in ora {
vec_remove!($me.overrides, a);
}
}
} else if let Some(ref o) = $me.flags.iter().filter(|f| &f.name == $name).next() {
if let Some(ref ora) = o.requires {
for a in ora {
vec_remove!($me.required, a);
}
}
if let Some(ref ora) = o.blacklist {
for a in ora {
vec_remove!($me.blacklist, a);
}
}
if let Some(ref ora) = o.overrides {
for a in ora {
vec_remove!($me.overrides, a);
}
}
} else if let Some(p) = $me.positionals.values().filter(|p| &&p.name == &$name).next() {
if let Some(ref ora) = p.requires {
for a in ora {
vec_remove!($me.required, a);
}
}
if let Some(ref ora) = p.blacklist {
for a in ora {
vec_remove!($me.blacklist, a);
}
}
if let Some(ref ora) = p.overrides {
for a in ora {
vec_remove!($me.overrides, a);
}
}
}
})
}

macro_rules! arg_post_processing(
($me:ident, $arg:ident, $matcher:ident) => ({
use args::AnyArg;
// Handle POSIX overrides
if $me.overrides.contains(&$arg.name()) {
if let Some(ref name) = $me.overriden_from($arg.name(), $matcher) {
$matcher.remove(name);
remove_overriden!($me, name);
}
}
if let Some(or) = $arg.overrides() {
for pa in or {
$matcher.remove(pa);
remove_overriden!($me, pa);
$me.overrides.push(pa);
vec_remove!($me.required, pa);
}
}
// Handle conflicts
if let Some(bl) = $arg.blacklist() {
for name in bl {
$me.blacklist.push(name);
vec_remove!($me.overrides, name);
vec_remove!($me.required, name);
}
}

// Add all required args which aren't already found in matcher to the master
// list
if let Some(reqs) = $arg.requires() {
for n in reqs {
if $matcher.contains(n) {
continue;
}

$me.required.push(n);
}
}

_handle_group_reqs!($me, $arg);
})
);

macro_rules! _handle_group_reqs{
($me:ident, $arg:ident) => ({
use args::AnyArg;
for grp in $me.groups.values() {
let mut found = false;
for name in grp.args.iter() {
if name == &$arg.name() {
vec_remove!($me.required, name);
if let Some(ref reqs) = grp.requires {
for r in reqs {
$me.required.push(r);
}
}
if let Some(ref bl) = grp.conflicts {
for b in bl {
$me.blacklist.push(b);
}
}
found = true;
break;
}
}
if found {
for name in grp.args.iter() {
if name == &$arg.name() { continue }
vec_remove!($me.required, name);

$me.blacklist.push(name);
}
}
}
})
}

0 comments on commit 8988853

Please sign in to comment.