Repository: kbknapp/clap-rs
Pull request #879 (2017-02-28 04:47:35)

Perf imp

coveralls: 
[![Coverage Status](https://coveralls.io/builds/10359776/badge)](https://coveralls.io/builds/10359776)

Coverage increased (+0.2%) to 91.552% when pulling **643ec547649d0547e9f290314e2d95e242bd045c on perf-imp** into **10c1d1bd3e5f1d7c358f378405362c20ec60203f on master**.


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index f6090695..e29abea9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 
 name = "clap"
-version = "2.20.5"
+version = "2.21.0"
 authors = ["Kevin K. <kbknapp@gmail.com>"]
 exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"]
 repository = "https://github.com/kbknapp/clap-rs.git"
@@ -30,6 +30,7 @@ atty      = { version = "0.2.2",  optional = true }
 
 [dev-dependencies]
 regex = "0.2"
+lazy_static = "0.2"
 
 [features]
 default     = ["suggestions", "color", "wrap_help"]
diff --git a/benches/04_new_help.rs b/benches/04_new_help.rs
index abc7a453..f033efb5 100644
--- a/benches/04_new_help.rs
+++ b/benches/04_new_help.rs
@@ -23,11 +23,11 @@ fn app_example1<'b, 'c>() -> App<'b, 'c> {
         .author("Kevin K. <kbknapp@gmail.com>")
         .about("Does awesome things")
         .args_from_usage("-c, --config=[FILE] 'Sets a custom config file'
-                                 <output> 'Sets an optional output file'
-                                 -d... 'Turn debugging information on'")
+                          <output> 'Sets an optional output file'
+                          -d... 'Turn debugging information on'")
         .subcommand(SubCommand::with_name("test")
-                        .about("does testing things")
-                        .arg_from_usage("-l, --list 'lists test values'"))
+            .about("does testing things")
+            .arg_from_usage("-l, --list 'lists test values'"))
 }
 
 fn app_example2<'b, 'c>() -> App<'b, 'c> {
@@ -39,37 +39,19 @@ fn app_example2<'b, 'c>() -> App<'b, 'c> {
 
 fn app_example3<'b, 'c>() -> App<'b, 'c> {
     App::new("MyApp")
-        // All application settings go here...
-
-        // A simple "Flag" argument example (i.e. "-d") using the builder pattern
         .arg(Arg::with_name("debug")
-                    .help("turn on debugging information")
-                    .short("d"))
-
-        // Two arguments, one "Option" argument (i.e. one that takes a value) such
-        // as "-c some", and one positional argument (i.e. "myapp some_file")
-        .args(&[
-            Arg::with_name("config")
+            .help("turn on debugging information")
+            .short("d"))
+        .args(&[Arg::with_name("config")
                     .help("sets the config file to use")
                     .takes_value(true)
                     .short("c")
                     .long("config"),
-            Arg::with_name("input")
+                Arg::with_name("input")
                     .help("the input file to use")
                     .index(1)
-                    .required(true)
-        ])
-
-        // *Note* the following two examples are convienience methods, if you wish
-        // to still get the full configurability of Arg::with_name() and the readability
-        // of arg_from_usage(), you can instantiate a new Arg with Arg::from_usage() and
-        // still be able to set all the additional properties, just like Arg::with_name()
-        //
-        //
-        // One "Flag" using a usage string
+                    .required(true)])
         .arg_from_usage("--license 'display the license file'")
-
-        // Two args, one "Positional", and one "Option" using a usage string
         .args_from_usage("[output] 'Supply an output file to use'
                           -i, --int=[IFACE] 'Set an interface to use'")
 }
@@ -80,142 +62,79 @@ fn app_example4<'b, 'c>() -> App<'b, 'c> {
         .version("1.0")
         .author("Kevin K. <kbknapp@gmail.com>")
         .arg(Arg::with_name("debug")
-                 .help("turn on debugging information")
-                 .short("d")
-                 .long("debug"))
+            .help("turn on debugging information")
+            .short("d")
+            .long("debug"))
         .arg(Arg::with_name("config")
-                 .help("sets the config file to use")
-                 .short("c")
-                 .long("config"))
+            .help("sets the config file to use")
+            .short("c")
+            .long("config"))
         .arg(Arg::with_name("input")
-                 .help("the input file to use")
-                 .index(1)
-                 .required(true))
+            .help("the input file to use")
+            .index(1)
+            .required(true))
 }
 
 fn app_example5<'b, 'c>() -> App<'b, 'c> {
-    App::new("MyApp")
-        // Regular App configuration goes here...
-
-        // We'll add a flag that represents an awesome meter...
-        //
-        // I'll explain each possible setting that "flags" accept. Keep in mind
-        // that you DO NOT need to set each of these for every flag, only the ones
-        // you want for your individual case.
-        .arg(Arg::with_name("awesome")
-                    .help("turns up the awesome") // Displayed when showing help info
-                    .short("a")                   // Trigger this arg with "-a"
-                    .long("awesome")              // Trigger this arg with "--awesome"
-                    .multiple(true)               // This flag should allow multiple
-                                                  // occurrences such as "-aaa" or "-a -a"
-                    .requires("config")           // Says, "If the user uses -a, they MUST
-                                                  // also use this other 'config' arg too"
-                                                  // Can also specifiy a list using
-                                                  // requires_all(Vec<&str>)
-                    .conflicts_with("output")     // Opposite of requires(), says "if the
-                                                  // user uses -a, they CANNOT use 'output'"
-                                                  // also has a mutually_excludes_all(Vec<&str>)
-        )
+    App::new("MyApp").arg(Arg::with_name("awesome")
+        .help("turns up the awesome")
+        .short("a")
+        .long("awesome")
+        .multiple(true)
+        .requires("config")
+        .conflicts_with("output"))
 }
 
 fn app_example6<'b, 'c>() -> App<'b, 'c> {
     App::new("MyApp")
-        // Regular App configuration goes here...
-
-        // We'll add two positional arguments, a input file, and a config file.
-        //
-        // I'll explain each possible setting that "positionals" accept. Keep in
-        // mind that you DO NOT need to set each of these for every flag, only the
-        // ones that apply to your individual case.
         .arg(Arg::with_name("input")
-                    .help("the input file to use") // Displayed when showing help info
-                    .index(1)                      // Set the order in which the user must
-                                                   // specify this argument (Starts at 1)
-                    .requires("config")            // Says, "If the user uses "input", they MUST
-                                                   // also use this other 'config' arg too"
-                                                   // Can also specifiy a list using
-                                                   // requires_all(Vec<&str>)
-                    .conflicts_with("output")      // Opposite of requires(), says "if the
-                                                   // user uses -a, they CANNOT use 'output'"
-                                                   // also has a mutually_excludes_all(Vec<&str>)
-                    .required(true)                // By default this argument MUST be present
-                                                   // NOTE: mutual exclusions take precedence over
-                                                   // required arguments
-        )
+            .help("the input file to use")
+            .index(1)
+            .requires("config")
+            .conflicts_with("output")
+            .required(true))
         .arg(Arg::with_name("config")
-                    .help("the config file to use")
-                    .index(2))                     // Note, we do not need to specify required(true)
-                                                   // if we don't want to, because "input" already
-                                                   // requires "config"
-                                                   // Note, we also do not need to specify requires("input")
-                                                   // because requires lists are automatically two-way
+            .help("the config file to use")
+            .index(2))
 }
 
 fn app_example7<'b, 'c>() -> App<'b, 'c> {
     App::new("MyApp")
-        // Regular App configuration goes here...
-
-        // Assume we an application that accepts an input file via the "-i file"
-        // or the "--input file" (as wel as "--input=file").
-        // Below every setting supported by option arguments is discussed.
-        // NOTE: You DO NOT need to specify each setting, only those which apply
-        // to your particular case.
+        .arg(Arg::with_name("config"))
+        .arg(Arg::with_name("output"))
         .arg(Arg::with_name("input")
-                    .help("the input file to use") // Displayed when showing help info
-                    .takes_value(true)             // MUST be set to true in order to be an "option" argument
-                    .short("i")                    // This argument is triggered with "-i"
-                    .long("input")                 // This argument is triggered with "--input"
-                    .multiple(true)                // Set to true if you wish to allow multiple occurrences
-                                                   // such as "-i file -i other_file -i third_file"
-                    .required(true)                // By default this argument MUST be present
-                                                   // NOTE: mutual exclusions take precedence over
-                                                   // required arguments
-                    .requires("config")            // Says, "If the user uses "input", they MUST
-                                                   // also use this other 'config' arg too"
-                                                   // Can also specifiy a list using
-                                                   // requires_all(Vec<&str>)
-                    .conflicts_with("output")      // Opposite of requires(), says "if the
-                                                   // user uses -a, they CANNOT use 'output'"
-                                                   // also has a conflicts_with_all(Vec<&str>)
-        )
+            .help("the input file to use")
+            .takes_value(true)
+            .short("i")
+            .long("input")
+            .multiple(true)
+            .required(true)
+            .requires("config")
+            .conflicts_with("output"))
 }
 
 fn app_example8<'b, 'c>() -> App<'b, 'c> {
     App::new("MyApp")
-                    // Regular App configuration goes here...
-
-                    // Assume we an application that accepts an input file via the "-i file"
-                    // or the "--input file" (as wel as "--input=file").
-                    // Below every setting supported by option arguments is discussed.
-                    // NOTE: You DO NOT need to specify each setting, only those which apply
-                    // to your particular case.
+        .arg(Arg::with_name("config"))
+        .arg(Arg::with_name("output"))
         .arg(Arg::with_name("input")
-                    .help("the input file to use") // Displayed when showing help info
-                    .takes_value(true)             // MUST be set to true in order to be an "option" argument
-                    .short("i")                    // This argument is triggered with "-i"
-                    .long("input")                 // This argument is triggered with "--input"
-                    .multiple(true)                // Set to true if you wish to allow multiple occurrences
-                                                   // such as "-i file -i other_file -i third_file"
-                    .required(true)                // By default this argument MUST be present
-                                                   // NOTE: mutual exclusions take precedence over
-                                                   // required arguments
-                    .requires("config")            // Says, "If the user uses "input", they MUST
-                                                   // also use this other 'config' arg too"
-                                                   // Can also specifiy a list using
-                                                   // requires_all(Vec<&str>)
-                    .conflicts_with("output")      // Opposite of requires(), says "if the
-                                                   // user uses -a, they CANNOT use 'output'"
-                                                   // also has a conflicts_with_all(Vec<&str>)
-            )
+            .help("the input file to use")
+            .takes_value(true)
+            .short("i")
+            .long("input")
+            .multiple(true)
+            .required(true)
+            .requires("config")
+            .conflicts_with("output"))
 }
 
 fn app_example10<'b, 'c>() -> App<'b, 'c> {
     App::new("myapp")
         .about("does awesome things")
         .arg(Arg::with_name("CONFIG")
-                 .help("The config file to use (default is \"config.json\")")
-                 .short("c")
-                 .takes_value(true))
+            .help("The config file to use (default is \"config.json\")")
+            .short("c")
+            .takes_value(true))
 }
 
 #[bench]
@@ -274,24 +193,6 @@ fn example10(b: &mut Bencher) {
 
 #[bench]
 fn example4_template(b: &mut Bencher) {
-/*
-MyApp 1.0
-Kevin K. <kbknapp@gmail.com>
-Parses an input file to do awesome things
-
-USAGE:
-    test [FLAGS] <input>
-
-FLAGS:
-    -c, --config     sets the config file to use
-    -d, --debug      turn on debugging information
-    -h, --help       Prints help information
-    -V, --version    Prints version information
-
-ARGS:
-    <input>    the input file to use
-*/
-
     let app = app_example4().template("{bin} {version}\n{author}\n{about}\n\nUSAGE:\n    {usage}\n\nFLAGS:\n{flags}\n\nARGS:\n{args}\n");
     b.iter(|| build_help(&app));
 }
diff --git a/benches/05_ripgrep.rs b/benches/05_ripgrep.rs
new file mode 100644
index 00000000..42a43c92
--- /dev/null
+++ b/benches/05_ripgrep.rs
@@ -0,0 +1,754 @@
+// Used to simulate a fairly large number of options/flags and parsing with thousands of positional
+// args
+//
+// CLI used is adapted from ripgrep 48a8a3a691220f9e5b2b08f4051abe8655ea7e8a
+
+#![feature(test)]
+
+extern crate clap;
+extern crate test;
+#[macro_use]
+extern crate lazy_static;
+
+use clap::{App, AppSettings, Arg, ArgSettings};
+
+use test::Bencher;
+use std::collections::HashMap;
+
+#[bench]
+fn build_app_short(b: &mut Bencher) { b.iter(|| app_short()); }
+
+#[bench]
+fn build_app_long(b: &mut Bencher) { b.iter(|| app_long()); }
+
+#[bench]
+fn parse_clean(b: &mut Bencher) { b.iter(|| app_short().get_matches_from(vec!["rg", "pat"])); }
+
+#[bench]
+fn parse_complex(b: &mut Bencher) {
+    b.iter(|| {
+        app_short().get_matches_from(vec!["rg",
+                                          "pat",
+                                          "-cFlN",
+                                          "-pqr",
+                                          "--null",
+                                          "--no-filename",
+                                          "--no-messages",
+                                          "-SH",
+                                          "-C5",
+                                          "--follow",
+                                          "-e some"])
+    });
+}
+
+#[bench]
+fn parse_lots(b: &mut Bencher) {
+    b.iter(|| {
+        app_short()
+            .get_matches_from(vec!["rg", "pat", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some", "some", "some", "some", "some",
+                                   "some", "some", "some", "some"])
+    });
+}
+
+const ABOUT: &'static str = "
+ripgrep (rg) recursively searches your current directory for a regex pattern.
+
+ripgrep's regex engine uses finite automata and guarantees linear time
+searching. Because of this, features like backreferences and arbitrary
+lookaround are not supported.
+
+Project home page: https://github.com/BurntSushi/ripgrep
+
+Use -h for short descriptions and --help for more details.";
+
+const USAGE: &'static str = "
+    rg [OPTIONS] <pattern> [<path> ...]
+    rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
+    rg [OPTIONS] --files [<path> ...]
+    rg [OPTIONS] --type-list";
+
+const TEMPLATE: &'static str = "\
+{bin} {version}
+{author}
+{about}
+
+USAGE:{usage}
+
+ARGS:
+{positionals}
+
+OPTIONS:
+{unified}";
+
+/// Build a clap application with short help strings.
+pub fn app_short() -> App<'static, 'static> { app(false, |k| USAGES[k].short) }
+
+/// Build a clap application with long help strings.
+pub fn app_long() -> App<'static, 'static> { app(true, |k| USAGES[k].long) }
+
+/// Build a clap application parameterized by usage strings.
+///
+/// The function given should take a clap argument name and return a help
+/// string. `app` will panic if a usage string is not defined.
+///
+/// This is an intentionally stand-alone module so that it can be used easily
+/// in a `build.rs` script to build shell completion files.
+fn app<F>(next_line_help: bool, doc: F) -> App<'static, 'static>
+    where F: Fn(&'static str) -> &'static str
+{
+    let arg = |name| Arg::with_name(name).help(doc(name)).next_line_help(next_line_help);
+    let flag = |name| arg(name).long(name);
+
+    App::new("ripgrep")
+        .author("BurntSushi") // simulating since it's only a bench
+        .version("0.4.0") // Simulating
+        .about(ABOUT)
+        .max_term_width(100)
+        .setting(AppSettings::UnifiedHelpMessage)
+        .usage(USAGE)
+        .template(TEMPLATE)
+        // Handle help/version manually to make their output formatting
+        // consistent with short/long views.
+        .arg(arg("help-short").short("h"))
+        .arg(flag("help"))
+        .arg(flag("version").short("V"))
+        // First, set up primary positional/flag arguments.
+        .arg(arg("pattern")
+             .required_unless_one(&[
+                "file", "files", "help-short", "help", "regexp", "type-list",
+                "version",
+             ]))
+        .arg(arg("path").multiple(true))
+        .arg(flag("regexp").short("e")
+             .takes_value(true).multiple(true).number_of_values(1)
+             .set(ArgSettings::AllowLeadingHyphen)
+             .value_name("pattern"))
+        .arg(flag("files")
+             // This should also conflict with `pattern`, but the first file
+             // path will actually be in `pattern`.
+             .conflicts_with_all(&["file", "regexp", "type-list"]))
+        .arg(flag("type-list")
+             .conflicts_with_all(&["file", "files", "pattern", "regexp"]))
+        // Second, set up common flags.
+        .arg(flag("text").short("a"))
+        .arg(flag("count").short("c"))
+        .arg(flag("color")
+             .value_name("WHEN")
+             .takes_value(true)
+             .hide_possible_values(true)
+             .possible_values(&["never", "auto", "always", "ansi"]))
+        .arg(flag("colors").value_name("SPEC")
+             .takes_value(true).multiple(true).number_of_values(1))
+        .arg(flag("fixed-strings").short("F"))
+        .arg(flag("glob").short("g")
+             .takes_value(true).multiple(true).number_of_values(1)
+             .value_name("GLOB"))
+        .arg(flag("ignore-case").short("i"))
+        .arg(flag("line-number").short("n"))
+        .arg(flag("no-line-number").short("N"))
+        .arg(flag("quiet").short("q"))
+        .arg(flag("type").short("t")
+             .takes_value(true).multiple(true).number_of_values(1)
+             .value_name("TYPE"))
+        .arg(flag("type-not").short("T")
+             .takes_value(true).multiple(true).number_of_values(1)
+             .value_name("TYPE"))
+        .arg(flag("unrestricted").short("u")
+             .multiple(true))
+        .arg(flag("invert-match").short("v"))
+        .arg(flag("word-regexp").short("w"))
+        // Third, set up less common flags.
+        .arg(flag("after-context").short("A")
+             .value_name("NUM").takes_value(true)
+             .validator(validate_number))
+        .arg(flag("before-context").short("B")
+             .value_name("NUM").takes_value(true)
+             .validator(validate_number))
+        .arg(flag("context").short("C")
+             .value_name("NUM").takes_value(true)
+             .validator(validate_number))
+        .arg(flag("column"))
+        .arg(flag("context-separator")
+             .value_name("SEPARATOR").takes_value(true))
+        .arg(flag("debug"))
+        .arg(flag("file").short("f")
+             .value_name("FILE").takes_value(true)
+             .multiple(true).number_of_values(1))
+        .arg(flag("files-with-matches").short("l"))
+        .arg(flag("files-without-match"))
+        .arg(flag("with-filename").short("H"))
+        .arg(flag("no-filename"))
+        .arg(flag("heading").overrides_with("no-heading"))
+        .arg(flag("no-heading").overrides_with("heading"))
+        .arg(flag("hidden"))
+        .arg(flag("ignore-file")
+             .value_name("FILE").takes_value(true)
+             .multiple(true).number_of_values(1))
+        .arg(flag("follow").short("L"))
+        .arg(flag("max-count")
+             .short("m").value_name("NUM").takes_value(true)
+             .validator(validate_number))
+        .arg(flag("maxdepth")
+             .value_name("NUM").takes_value(true)
+             .validator(validate_number))
+        .arg(flag("mmap"))
+        .arg(flag("no-messages"))
+        .arg(flag("no-mmap"))
+        .arg(flag("no-ignore"))
+        .arg(flag("no-ignore-parent"))
+        .arg(flag("no-ignore-vcs"))
+        .arg(flag("null"))
+        .arg(flag("path-separator").value_name("SEPARATOR").takes_value(true))
+        .arg(flag("pretty").short("p"))
+        .arg(flag("replace").short("r").value_name("ARG").takes_value(true))
+        .arg(flag("case-sensitive").short("s"))
+        .arg(flag("smart-case").short("S"))
+        .arg(flag("sort-files"))
+        .arg(flag("threads")
+             .short("j").value_name("ARG").takes_value(true)
+             .validator(validate_number))
+        .arg(flag("vimgrep"))
+        .arg(flag("type-add")
+             .value_name("TYPE").takes_value(true)
+             .multiple(true).number_of_values(1))
+        .arg(flag("type-clear")
+             .value_name("TYPE").takes_value(true)
+             .multiple(true).number_of_values(1))
+}
+
+struct Usage {
+    short: &'static str,
+    long: &'static str,
+}
+
+macro_rules! doc {
+    ($map:expr, $name:expr, $short:expr) => {
+        doc!($map, $name, $short, $short)
+    };
+    ($map:expr, $name:expr, $short:expr, $long:expr) => {
+        $map.insert($name, Usage {
+            short: $short,
+            long: concat!($long, "\n "),
+        });
+    };
+}
+
+lazy_static! {
+    static ref USAGES: HashMap<&'static str, Usage> = {
+        let mut h = HashMap::new();
+        doc!(h, "help-short",
+             "Show short help output.",
+             "Show short help output. Use --help to show more details.");
+        doc!(h, "help",
+             "Show verbose help output.",
+             "When given, more details about flags are provided.");
+        doc!(h, "version",
+             "Prints version information.");
+
+        doc!(h, "pattern",
+             "A regular expression used for searching.",
+             "A regular expression used for searching. Multiple patterns \
+              may be given. To match a pattern beginning with a -, use [-].");
+        doc!(h, "regexp",
+             "A regular expression used for searching.",
+             "A regular expression used for searching. Multiple patterns \
+              may be given. To match a pattern beginning with a -, use [-].");
+        doc!(h, "path",
+             "A file or directory to search.",
+             "A file or directory to search. Directories are searched \
+              recursively.");
+        doc!(h, "files",
+             "Print each file that would be searched.",
+             "Print each file that would be searched without actually \
+              performing the search. This is useful to determine whether a \
+              particular file is being searched or not.");
+        doc!(h, "type-list",
+             "Show all supported file types.",
+             "Show all supported file types and their corresponding globs.");
+
+        doc!(h, "text",
+             "Search binary files as if they were text.");
+        doc!(h, "count",
+             "Only show count of matches for each file.");
+        doc!(h, "color",
+             "When to use color. [default: auto]",
+             "When to use color in the output. The possible values are \
+              never, auto, always or ansi. The default is auto. When always \
+              is used, coloring is attempted based on your environment. When \
+              ansi used, coloring is forcefully done using ANSI escape color \
+              codes.");
+        doc!(h, "colors",
+             "Configure color settings and styles.",
+             "This flag specifies color settings for use in the output. \
+              This flag may be provided multiple times. Settings are applied \
+              iteratively. Colors are limited to one of eight choices: \
+              red, blue, green, cyan, magenta, yellow, white and black. \
+              Styles are limited to nobold, bold, nointense or intense.\n\n\
+              The format of the flag is {type}:{attribute}:{value}. {type} \
+              should be one of path, line or match. {attribute} can be fg, bg \
+              or style. {value} is either a color (for fg and bg) or a text \
+              style. A special format, {type}:none, will clear all color \
+              settings for {type}.\n\nFor example, the following command will \
+              change the match color to magenta and the background color for \
+              line numbers to yellow:\n\n\
+              rg --colors 'match:fg:magenta' --colors 'line:bg:yellow' foo.");
+        doc!(h, "fixed-strings",
+             "Treat the pattern as a literal string.",
+             "Treat the pattern as a literal string instead of a regular \
+              expression. When this flag is used, special regular expression \
+              meta characters such as (){}*+. do not need to be escaped.");
+        doc!(h, "glob",
+             "Include or exclude files/directories.",
+             "Include or exclude files/directories for searching that \
+              match the given glob. This always overrides any other \
+              ignore logic. Multiple glob flags may be used. Globbing \
+              rules match .gitignore globs. Precede a glob with a ! \
+              to exclude it.");
+        doc!(h, "ignore-case",
+             "Case insensitive search.",
+             "Case insensitive search. This is overridden by \
+              --case-sensitive.");
+        doc!(h, "line-number",
+             "Show line numbers.",
+             "Show line numbers (1-based). This is enabled by default when \
+              searching in a tty.");
+        doc!(h, "no-line-number",
+             "Suppress line numbers.",
+             "Suppress line numbers. This is enabled by default when NOT \
+              searching in a tty.");
+        doc!(h, "quiet",
+             "Do not print anything to stdout.",
+             "Do not print anything to stdout. If a match is found in a file, \
+              stop searching. This is useful when ripgrep is used only for \
+              its exit code.");
+        doc!(h, "type",
+             "Only search files matching TYPE.",
+             "Only search files matching TYPE. Multiple type flags may be \
+              provided. Use the --type-list flag to list all available \
+              types.");
+        doc!(h, "type-not",
+             "Do not search files matching TYPE.",
+             "Do not search files matching TYPE. Multiple type-not flags may \
+              be provided. Use the --type-list flag to list all available \
+              types.");
+        doc!(h, "unrestricted",
+             "Reduce the level of \"smart\" searching.",
+             "Reduce the level of \"smart\" searching. A single -u \
+              won't respect .gitignore (etc.) files. Two -u flags will \
+              additionally search hidden files and directories. Three \
+              -u flags will additionally search binary files. -uu is \
+              roughly equivalent to grep -r and -uuu is roughly \
+              equivalent to grep -a -r.");
+        doc!(h, "invert-match",
+             "Invert matching.",
+             "Invert matching. Show lines that don't match given patterns.");
+        doc!(h, "word-regexp",
+             "Only show matches surrounded by word boundaries.",
+             "Only show matches surrounded by word boundaries. This is \
+              equivalent to putting \\b before and after all of the search \
+              patterns.");
+
+        doc!(h, "after-context",
+             "Show NUM lines after each match.");
+        doc!(h, "before-context",
+             "Show NUM lines before each match.");
+        doc!(h, "context",
+             "Show NUM lines before and after each match.");
+        doc!(h, "column",
+             "Show column numbers",
+             "Show column numbers (1-based). This only shows the column \
+              numbers for the first match on each line. This does not try \
+              to account for Unicode. One byte is equal to one column. This \
+              implies --line-number.");
+        doc!(h, "context-separator",
+             "Set the context separator string. [default: --]",
+             "The string used to separate non-contiguous context lines in the \
+              output. Escape sequences like \\x7F or \\t may be used. The \
+              default value is --.");
+        doc!(h, "debug",
+             "Show debug messages.",
+             "Show debug messages. Please use this when filing a bug report.");
+        doc!(h, "file",
+             "Search for patterns from the given file.",
+             "Search for patterns from the given file, with one pattern per \
+              line. When this flag is used or multiple times or in \
+              combination with the -e/--regexp flag, then all patterns \
+              provided are searched. Empty pattern lines will match all input \
+              lines, and the newline is not counted as part of the pattern.");
+        doc!(h, "files-with-matches",
+             "Only show the path of each file with at least one match.");
+        doc!(h, "files-without-match",
+             "Only show the path of each file that contains zero matches.");
+        doc!(h, "with-filename",
+             "Show file name for each match.",
+             "Prefix each match with the file name that contains it. This is \
+              the default when more than one file is searched.");
+        doc!(h, "no-filename",
+             "Never show the file name for a match.",
+             "Never show the file name for a match. This is the default when \
+              one file is searched.");
+        doc!(h, "heading",
+             "Show matches grouped by each file.",
+             "This shows the file name above clusters of matches from each \
+              file instead of showing the file name for every match. This is \
+              the default mode at a tty.");
+        doc!(h, "no-heading",
+             "Don't group matches by each file.",
+             "Don't group matches by each file. If -H/--with-filename is \
+              enabled, then file names will be shown for every line matched. \
+              This is the default mode when not at a tty.");
+        doc!(h, "hidden",
+             "Search hidden files and directories.",
+             "Search hidden files and directories. By default, hidden files \
+              and directories are skipped.");
+        doc!(h, "ignore-file",
+             "Specify additional ignore files.",
+             "Specify additional ignore files for filtering file paths. \
+              Ignore files should be in the gitignore format and are matched \
+              relative to the current working directory. These ignore files \
+              have lower precedence than all other ignore files. When \
+              specifying multiple ignore files, earlier files have lower \
+              precedence than later files.");
+        doc!(h, "follow",
+             "Follow symbolic links.");
+        doc!(h, "max-count",
+             "Limit the number of matches.",
+             "Limit the number of matching lines per file searched to NUM.");
+        doc!(h, "maxdepth",
+             "Descend at most NUM directories.",
+             "Limit the depth of directory traversal to NUM levels beyond \
+              the paths given. A value of zero only searches the \
+              starting-points themselves.\n\nFor example, \
+              'rg --maxdepth 0 dir/' is a no-op because dir/ will not be \
+              descended into. 'rg --maxdepth 1 dir/' will search only the \
+              direct children of dir/.");
+        doc!(h, "mmap",
+             "Searching using memory maps when possible.",
+             "Search using memory maps when possible. This is enabled by \
+              default when ripgrep thinks it will be faster. Note that memory \
+              map searching doesn't currently support all options, so if an \
+              incompatible option (e.g., --context) is given with --mmap, \
+              then memory maps will not be used.");
+        doc!(h, "no-messages",
+             "Suppress all error messages.",
+             "Suppress all error messages. This is equivalent to redirecting \
+              stderr to /dev/null.");
+        doc!(h, "no-mmap",
+             "Never use memory maps.",
+             "Never use memory maps, even when they might be faster.");
+        doc!(h, "no-ignore",
+             "Don't respect ignore files.",
+             "Don't respect ignore files (.gitignore, .ignore, etc.). This \
+              implies --no-ignore-parent and --no-ignore-vcs.");
+        doc!(h, "no-ignore-parent",
+             "Don't respect ignore files in parent directories.",
+             "Don't respect ignore files (.gitignore, .ignore, etc.) in \
+              parent directories.");
+        doc!(h, "no-ignore-vcs",
+             "Don't respect VCS ignore files",
+             "Don't respect version control ignore files (.gitignore, etc.). \
+              This implies --no-ignore-parent. Note that .ignore files will \
+              continue to be respected.");
+        doc!(h, "null",
+             "Print NUL byte after file names",
+             "Whenever a file name is printed, follow it with a NUL byte. \
+              This includes printing file names before matches, and when \
+              printing a list of matching files such as with --count, \
+              --files-with-matches and --files. This option is useful for use \
+              with xargs.");
+        doc!(h, "path-separator",
+             "Path separator to use when printing file paths.",
+             "The path separator to use when printing file paths. This \
+              defaults to your platform's path separator, which is / on Unix \
+              and \\ on Windows. This flag is intended for overriding the \
+              default when the environment demands it (e.g., cygwin). A path \
+              separator is limited to a single byte.");
+        doc!(h, "pretty",
+             "Alias for --color always --heading -n.");
+        doc!(h, "replace",
+             "Replace matches with string given.",
+             "Replace every match with the string given when printing \
+              results. Neither this flag nor any other flag will modify your \
+              files.\n\nCapture group indices (e.g., $5) and names \
+              (e.g., $foo) are supported in the replacement string.\n\n\
+              Note that the replacement by default replaces each match, and \
+              NOT the entire line. To replace the entire line, you should \
+              match the entire line.");
+        doc!(h, "case-sensitive",
+             "Search case sensitively.",
+             "Search case sensitively. This overrides -i/--ignore-case and \
+              -S/--smart-case.");
+        doc!(h, "smart-case",
+             "Smart case search.",
+             "Searches case insensitively if the pattern is all lowercase. \
+              Search case sensitively otherwise. This is overridden by \
+              either -s/--case-sensitive or -i/--ignore-case.");
+        doc!(h, "sort-files",
+             "Sort results by file path. Implies --threads=1.",
+             "Sort results by file path. Note that this currently \
+              disables all parallelism and runs search in a single thread.");
+        doc!(h, "threads",
+             "The approximate number of threads to use.",
+             "The approximate number of threads to use. A value of 0 (which \
+              is the default) causes ripgrep to choose the thread count \
+              using heuristics.");
+        doc!(h, "vimgrep",
+             "Show results in vim compatible format.",
+             "Show results with every match on its own line, including \
+              line numbers and column numbers. With this option, a line with \
+              more than one match will be printed more than once.");
+
+        doc!(h, "type-add",
+             "Add a new glob for a file type.",
+             "Add a new glob for a particular file type. Only one glob can be \
+              added at a time. Multiple --type-add flags can be provided. \
+              Unless --type-clear is used, globs are added to any existing \
+              globs defined inside of ripgrep.\n\nNote that this MUST be \
+              passed to every invocation of ripgrep. Type settings are NOT \
+              persisted.\n\nExample: \
+              rg --type-add 'foo:*.foo' -tfoo PATTERN.\n\n\
+              --type-add can also be used to include rules from other types \
+              with the special include directive. The include directive \
+              permits specifying one or more other type names (separated by a \
+              comma) that have been defined and its rules will automatically \
+              be imported into the type specified. For example, to create a \
+              type called src that matches C++, Python and Markdown files, one \
+              can use:\n\n\
+              --type-add 'src:include:cpp,py,md'\n\n\
+              Additional glob rules can still be added to the src type by \
+              using the --type-add flag again:\n\n\
+              --type-add 'src:include:cpp,py,md' --type-add 'src:*.foo'\n\n\
+              Note that type names must consist only of Unicode letters or \
+              numbers. Punctuation characters are not allowed.");
+        doc!(h, "type-clear",
+             "Clear globs for given file type.",
+             "Clear the file type globs previously defined for TYPE. This \
+              only clears the default type definitions that are found inside \
+              of ripgrep.\n\nNote that this MUST be passed to every \
+              invocation of ripgrep. Type settings are NOT persisted.");
+
+        h
+    };
+}
+
+fn validate_number(s: String) -> Result<(), String> {
+    s.parse::<usize>().map(|_| ()).map_err(|err| err.to_string())
+}
diff --git a/benches/06_rustup.rs b/benches/06_rustup.rs
new file mode 100644
index 00000000..b70996e8
--- /dev/null
+++ b/benches/06_rustup.rs
@@ -0,0 +1,458 @@
+// Used to simulate a fairly large number of subcommands
+//
+// CLI used is from rustup 408ed84f0e50511ed44a405dd91365e5da588790
+
+#![feature(test)]
+
+extern crate clap;
+extern crate test;
+
+use clap::{App, AppSettings, Arg, Shell, SubCommand, ArgGroup};
+
+use test::Bencher;
+
+#[bench]
+fn build_app(b: &mut Bencher) { b.iter(|| build_cli()); }
+
+#[bench]
+fn parse_clean(b: &mut Bencher) { b.iter(|| build_cli().get_matches_from(vec![""])); }
+
+#[bench]
+fn parse_subcommands(b: &mut Bencher) {
+    b.iter(|| build_cli().get_matches_from(vec!["rustup override add stable"]));
+}
+
+pub fn build_cli() -> App<'static, 'static> {
+    App::new("rustup")
+        .version("0.9.0") // Simulating
+        .about("The Rust toolchain installer")
+        .after_help(RUSTUP_HELP)
+        .setting(AppSettings::VersionlessSubcommands)
+        .setting(AppSettings::DeriveDisplayOrder)
+        // .setting(AppSettings::SubcommandRequiredElseHelp)
+        .arg(Arg::with_name("verbose")
+            .help("Enable verbose output")
+            .short("v")
+            .long("verbose"))
+        .subcommand(SubCommand::with_name("show")
+            .about("Show the active and installed toolchains")
+            .after_help(SHOW_HELP))
+        .subcommand(SubCommand::with_name("install")
+            .about("Update Rust toolchains")
+            .after_help(TOOLCHAIN_INSTALL_HELP)
+            .setting(AppSettings::Hidden) // synonym for 'toolchain install'
+            .arg(Arg::with_name("toolchain")
+                .required(true)))
+        .subcommand(SubCommand::with_name("update")
+            .about("Update Rust toolchains")
+            .after_help(UPDATE_HELP)
+            .arg(Arg::with_name("toolchain").required(false))
+            .arg(Arg::with_name("no-self-update")
+                .help("Don't perform self update when running the `rustup` command")
+                .long("no-self-update")
+                .takes_value(false)
+                .hidden(true)))
+        .subcommand(SubCommand::with_name("default")
+            .about("Set the default toolchain")
+            .after_help(DEFAULT_HELP)
+            .arg(Arg::with_name("toolchain").required(true)))
+        .subcommand(SubCommand::with_name("toolchain")
+            .about("Modify or query the installed toolchains")
+            .after_help(TOOLCHAIN_HELP)
+            .setting(AppSettings::VersionlessSubcommands)
+            .setting(AppSettings::DeriveDisplayOrder)
+            // .setting(AppSettings::SubcommandRequiredElseHelp)
+            .subcommand(SubCommand::with_name("list").about("List installed toolchains"))
+            .subcommand(SubCommand::with_name("install")
+                .about("Install or update a given toolchain")
+                .arg(Arg::with_name("toolchain").required(true)))
+            .subcommand(SubCommand::with_name("uninstall")
+                .about("Uninstall a toolchain")
+                .arg(Arg::with_name("toolchain").required(true)))
+            .subcommand(SubCommand::with_name("link")
+                .about("Create a custom toolchain by symlinking to a directory")
+                .arg(Arg::with_name("toolchain").required(true))
+                .arg(Arg::with_name("path").required(true)))
+            .subcommand(SubCommand::with_name("update")
+                .setting(AppSettings::Hidden) // synonym for 'install'
+                .arg(Arg::with_name("toolchain")
+                .required(true)))
+            .subcommand(SubCommand::with_name("add")
+                .setting(AppSettings::Hidden) // synonym for 'install'
+                .arg(Arg::with_name("toolchain")
+                     .required(true)))
+            .subcommand(SubCommand::with_name("remove")
+                .setting(AppSettings::Hidden) // synonym for 'uninstall'
+                .arg(Arg::with_name("toolchain")
+                     .required(true))))
+        .subcommand(SubCommand::with_name("target")
+            .about("Modify a toolchain's supported targets")
+            .setting(AppSettings::VersionlessSubcommands)
+            .setting(AppSettings::DeriveDisplayOrder)
+            // .setting(AppSettings::SubcommandRequiredElseHelp)
+            .subcommand(SubCommand::with_name("list")
+                .about("List installed and available targets")
+                .arg(Arg::with_name("toolchain")
+                    .long("toolchain")
+                    .takes_value(true)))
+            .subcommand(SubCommand::with_name("add")
+                .about("Add a target to a Rust toolchain")
+                .arg(Arg::with_name("target").required(true))
+                .arg(Arg::with_name("toolchain")
+                    .long("toolchain")
+                    .takes_value(true)))
+            .subcommand(SubCommand::with_name("remove")
+                .about("Remove a target  from a Rust toolchain")
+                .arg(Arg::with_name("target").required(true))
+                .arg(Arg::with_name("toolchain")
+                    .long("toolchain")
+                    .takes_value(true)))
+            .subcommand(SubCommand::with_name("install")
+                .setting(AppSettings::Hidden) // synonym for 'add'
+                .arg(Arg::with_name("target")
+                    .required(true))
+                .arg(Arg::with_name("toolchain")
+                    .long("toolchain")
+                    .takes_value(true)))
+            .subcommand(SubCommand::with_name("uninstall")
+                .setting(AppSettings::Hidden) // synonym for 'remove'
+                .arg(Arg::with_name("target")
+                    .required(true))
+                .arg(Arg::with_name("toolchain")
+                    .long("toolchain")
+                    .takes_value(true))))
+        .subcommand(SubCommand::with_name("component")
+            .about("Modify a toolchain's installed components")
+            .setting(AppSettings::VersionlessSubcommands)
+            .setting(AppSettings::DeriveDisplayOrder)
+            // .setting(AppSettings::SubcommandRequiredElseHelp)
+            .subcommand(SubCommand::with_name("list")
+                .about("List installed and available components")
+                .arg(Arg::with_name("toolchain")
+                    .long("toolchain")
+                    .takes_value(true)))
+            .subcommand(SubCommand::with_name("add")
+                .about("Add a component to a Rust toolchain")
+                .arg(Arg::with_name("component").required(true))
+                .arg(Arg::with_name("toolchain")
+                    .long("toolchain")
+                    .takes_value(true))
+                .arg(Arg::with_name("target")
+                    .long("target")
+                    .takes_value(true)))
+            .subcommand(SubCommand::with_name("remove")
+                .about("Remove a component from a Rust toolchain")
+                .arg(Arg::with_name("component").required(true))
+                .arg(Arg::with_name("toolchain")
+                    .long("toolchain")
+                    .takes_value(true))
+                .arg(Arg::with_name("target")
+                    .long("target")
+                    .takes_value(true))))
+        .subcommand(SubCommand::with_name("override")
+            .about("Modify directory toolchain overrides")
+            .after_help(OVERRIDE_HELP)
+            .setting(AppSettings::VersionlessSubcommands)
+            .setting(AppSettings::DeriveDisplayOrder)
+            // .setting(AppSettings::SubcommandRequiredElseHelp)
+            .subcommand(SubCommand::with_name("list").about("List directory toolchain overrides"))
+            .subcommand(SubCommand::with_name("set")
+                .about("Set the override toolchain for a directory")
+                .arg(Arg::with_name("toolchain").required(true)))
+            .subcommand(SubCommand::with_name("unset")
+                .about("Remove the override toolchain for a directory")
+                .after_help(OVERRIDE_UNSET_HELP)
+                .arg(Arg::with_name("path")
+                    .long("path")
+                    .takes_value(true)
+                    .help("Path to the directory"))
+                .arg(Arg::with_name("nonexistent")
+                    .long("nonexistent")
+                    .takes_value(false)
+                    .help("Remove override toolchain for all nonexistent directories")))
+            .subcommand(SubCommand::with_name("add")
+                .setting(AppSettings::Hidden) // synonym for 'set'
+                .arg(Arg::with_name("toolchain")
+                     .required(true)))
+            .subcommand(SubCommand::with_name("remove")
+                .setting(AppSettings::Hidden) // synonym for 'unset'
+                .about("Remove the override toolchain for a directory")
+                .arg(Arg::with_name("path")
+                    .long("path")
+                    .takes_value(true))
+                .arg(Arg::with_name("nonexistent")
+                    .long("nonexistent")
+                    .takes_value(false)
+                    .help("Remove override toolchain for all nonexistent directories"))))
+        .subcommand(SubCommand::with_name("run")
+            .about("Run a command with an environment configured for a given toolchain")
+            .after_help(RUN_HELP)
+            .setting(AppSettings::TrailingVarArg)
+            .arg(Arg::with_name("toolchain").required(true))
+            .arg(Arg::with_name("command")
+                .required(true)
+                .multiple(true)
+                .use_delimiter(false)))
+        .subcommand(SubCommand::with_name("which")
+            .about("Display which binary will be run for a given command")
+            .arg(Arg::with_name("command").required(true)))
+        .subcommand(SubCommand::with_name("doc")
+            .about("Open the documentation for the current toolchain")
+            .after_help(DOC_HELP)
+            .arg(Arg::with_name("book")
+                .long("book")
+                .help("The Rust Programming Language book"))
+            .arg(Arg::with_name("std")
+                .long("std")
+                .help("Standard library API documentation"))
+            .group(ArgGroup::with_name("page").args(&["book", "std"])))
+        .subcommand(SubCommand::with_name("man")
+            .about("View the man page for a given command")
+            .arg(Arg::with_name("command").required(true))
+            .arg(Arg::with_name("toolchain")
+                .long("toolchain")
+                .takes_value(true)))
+        .subcommand(SubCommand::with_name("self")
+            .about("Modify the rustup installation")
+            .setting(AppSettings::VersionlessSubcommands)
+            .setting(AppSettings::DeriveDisplayOrder)
+            // .setting(AppSettings::SubcommandRequiredElseHelp)
+            .subcommand(SubCommand::with_name("update")
+                .about("Download and install updates to rustup"))
+            .subcommand(SubCommand::with_name("uninstall")
+                .about("Uninstall rustup.")
+                .arg(Arg::with_name("no-prompt").short("y")))
+            .subcommand(SubCommand::with_name("upgrade-data")
+                .about("Upgrade the internal data format.")))
+        .subcommand(SubCommand::with_name("telemetry")
+            .about("rustup telemetry commands")
+            .setting(AppSettings::Hidden)
+            .setting(AppSettings::VersionlessSubcommands)
+            .setting(AppSettings::DeriveDisplayOrder)
+            // .setting(AppSettings::SubcommandRequiredElseHelp)
+            .subcommand(SubCommand::with_name("enable").about("Enable rustup telemetry"))
+            .subcommand(SubCommand::with_name("disable").about("Disable rustup telemetry"))
+            .subcommand(SubCommand::with_name("analyze").about("Analyze stored telemetry")))
+        .subcommand(SubCommand::with_name("set")
+            .about("Alter rustup settings")
+            // .setting(AppSettings::SubcommandRequiredElseHelp)
+            .subcommand(SubCommand::with_name("default-host")
+                .about("The triple used to identify toolchains when not specified")
+                .arg(Arg::with_name("host_triple").required(true))))
+        .subcommand(SubCommand::with_name("completions")
+            .about("Generate completion scripts for your shell")
+            .after_help(COMPLETIONS_HELP)
+            .setting(AppSettings::ArgRequiredElseHelp)
+            .arg(Arg::with_name("shell").possible_values(&Shell::variants())))
+}
+
+static RUSTUP_HELP: &'static str = r"
+rustup installs The Rust Programming Language from the official
+release channels, enabling you to easily switch between stable, beta,
+and nightly compilers and keep them updated. It makes cross-compiling
+simpler with binary builds of the standard library for common platforms.
+
+If you are new to Rust consider running `rustup doc --book`
+to learn Rust.";
+
+static SHOW_HELP: &'static str = r"
+Shows the name of the active toolchain and the version of `rustc`.
+
+If the active toolchain has installed support for additional
+compilation targets, then they are listed as well.
+
+If there are multiple toolchains installed then all installed
+toolchains are listed as well.";
+
+static UPDATE_HELP: &'static str = r"
+With no toolchain specified, the `update` command updates each of the
+installed toolchains from the official release channels, then updates
+rustup itself.
+
+If given a toolchain argument then `update` updates that toolchain,
+the same as `rustup toolchain install`.
+
+'toolchain' specifies a toolchain name, such as 'stable', 'nightly',
+or '1.8.0'. For more information see `rustup help toolchain`.";
+
+static TOOLCHAIN_INSTALL_HELP: &'static str = r"
+Installs a specific rust toolchain.
+
+The 'install' command is an alias for 'rustup update <toolchain>'.
+
+'toolchain' specifies a toolchain name, such as 'stable', 'nightly',
+or '1.8.0'. For more information see `rustup help toolchain`.";
+
+static DEFAULT_HELP: &'static str = r"
+Sets the default toolchain to the one specified. If the toolchain is
+not already installed then it is installed first.";
+
+static TOOLCHAIN_HELP: &'static str = r"
+Many `rustup` commands deal with *toolchains*, a single installation
+of the Rust compiler. `rustup` supports multiple types of
+toolchains. The most basic track the official release channels:
+'stable', 'beta' and 'nightly'; but `rustup` can also install
+toolchains from the official archives, for alternate host platforms,
+and from local builds.
+
+Standard release channel toolchain names have the following form:
+
+    <channel>[-<date>][-<host>]
+
+    <channel>       = stable|beta|nightly|<version>
+    <date>          = YYYY-MM-DD
+    <host>          = <target-triple>
+
+'channel' is either a named release channel or an explicit version
+number, such as '1.8.0'. Channel names can be optionally appended with
+an archive date, as in 'nightly-2014-12-18', in which case the
+toolchain is downloaded from the archive for that date.
+
+Finally, the host may be specified as a target triple. This is most
+useful for installing a 32-bit compiler on a 64-bit platform, or for
+installing the [MSVC-based toolchain] on Windows. For example:
+
+    rustup toolchain install stable-x86_64-pc-windows-msvc
+
+For convenience, elements of the target triple that are omitted will be
+inferred, so the above could be written:
+
+    $ rustup default stable-msvc
+
+Toolchain names that don't name a channel instead can be used to name
+custom toolchains with the `rustup toolchain link` command.";
+
+static OVERRIDE_HELP: &'static str = r"
+Overrides configure rustup to use a specific toolchain when
+running in a specific directory.
+
+Directories can be assigned their own Rust toolchain with
+`rustup override`. When a directory has an override then
+any time `rustc` or `cargo` is run inside that directory,
+or one of its child directories, the override toolchain
+will be invoked.
+
+To pin to a specific nightly:
+
+    rustup override set nightly-2014-12-18
+
+Or a specific stable release:
+
+    rustup override set 1.0.0
+
+To see the active toolchain use `rustup show`. To remove the override
+and use the default toolchain again, `rustup override unset`.";
+
+static OVERRIDE_UNSET_HELP: &'static str = r"
+If `--path` argument is present, removes the override toolchain for
+the specified directory. If `--nonexistent` argument is present, removes
+the override toolchain for all nonexistent directories. Otherwise,
+removes the override toolchain for the current directory.";
+
+static RUN_HELP: &'static str = r"
+Configures an environment to use the given toolchain and then runs
+the specified program. The command may be any program, not just
+rustc or cargo. This can be used for testing arbitrary toolchains
+without setting an override.
+
+Commands explicitly proxied by `rustup` (such as `rustc` and `cargo`)
+also have a shorthand for this available. The toolchain can be set by
+using `+toolchain` as the first argument. These are equivalent:
+
+    cargo +nightly build
+
+    rustup run nightly cargo build";
+
+static DOC_HELP: &'static str = r"
+Opens the documentation for the currently active toolchain with the
+default browser.
+
+By default, it opens the documentation index. Use the various flags to
+open specific pieces of documentation.";
+
+static COMPLETIONS_HELP: &'static str = r"
+One can generate a completion script for `rustup` that is compatible with
+a given shell. The script is output on `stdout` allowing one to re-direct
+the output to the file of their choosing. Where you place the file will
+depend on which shell, and which operating system you are using. Your
+particular configuration may also determine where these scripts need
+to be placed.
+
+Here are some common set ups for the three supported shells under
+Unix and similar operating systems (such as GNU/Linux).
+
+BASH:
+
+Completion files are commonly stored in `/etc/bash_completion.d/`
+
+Run the command:
+
+`rustup completions bash > /etc/bash_completion.d/rustup.bash-completion`
+
+This installs the completion script. You may have to log out and log
+back in to your shell session for the changes to take affect.
+
+FISH:
+
+Fish completion files are commonly stored in
+`$HOME/.config/fish/completions`
+
+Run the command:
+`rustup completions fish > ~/.config/fish/completions/rustup.fish`
+
+This installs the completion script. You may have to log out and log
+back in to your shell session for the changes to take affect.
+
+ZSH:
+
+ZSH completions are commonly stored in any directory listed in your
+`$fpath` variable. To use these completions, you must either add the
+generated script to one of those directories, or add your own
+to this list.
+
+Adding a custom directory is often the safest best if you're unsure
+of which directory to use. First create the directory, for this
+example we'll create a hidden directory inside our `$HOME` directory
+
+`mkdir ~/.zfunc`
+
+Then add the following lines to your `.zshrc` just before `compinit`
+
+`fpath+=~/.zfunc`
+
+Now you can install the completions script using the following command
+
+`rustup completions zsh > ~/.zfunc/_rustup`
+
+You must then either log out and log back in, or simply run
+
+`exec zsh`
+
+For the new completions to take affect.
+
+CUSTOM LOCATIONS:
+
+Alternatively, you could save these files to the place of your choosing,
+such as a custom directory inside your $HOME. Doing so will require you
+to add the proper directives, such as `source`ing inside your login
+script. Consult your shells documentation for how to add such directives.
+
+POWERSHELL:
+
+The powershell completion scripts require PowerShell v5.0+ (which comes
+Windows 10, but can be downloaded separately for windows 7 or 8.1).
+
+First, check if a profile has already been set
+
+`PS C:\> Test-Path $profile`
+
+If the above command returns `False` run the following
+
+`PS C:\> New-Item -path $profile -type file --force`
+
+Now open the file provided by `$profile` (if you used the `New-Item` command
+it will be `%USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`
+
+Next, we either save the completions file into our profile, or into a separate file
+and source it inside our profile. To save the completions into our profile simply
+use";
diff --git a/src/app/macros.rs b/src/app/macros.rs
index f589216f..7224fa42 100644
--- a/src/app/macros.rs
+++ b/src/app/macros.rs
@@ -19,11 +19,14 @@ macro_rules! remove_overriden {
     };
     ($_self:ident, $name:expr) => {
         debugln!("remove_overriden!;");
-        if let Some(ref o) = $_self.opts.iter().filter(|o| o.b.name == *$name).next() {
+        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);
         }
     };
@@ -56,7 +59,7 @@ macro_rules! arg_post_processing {
         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!("arg_post_processing!: Has '{}' already been matched...", c);
@@ -69,21 +72,20 @@ macro_rules! arg_post_processing {
                 }
             }
 
-            $me.blacklist.extend(bl);
+            $me.blacklist.extend_from_slice(bl);
             vec_remove_all!($me.overrides, bl.iter());
-            vec_remove_all!($me.required, 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!("arg_post_processing!: Does '{}' have requirements...", $arg.to_string());
         if let Some(reqs) = $arg.requires() {
-            for n in reqs.iter().filter(|&&(val, _)| val.is_none()).map(|&(_, name)| name) {
-                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"); }
@@ -96,9 +98,9 @@ macro_rules! _handle_group_reqs{
     ($me:ident, $arg:ident) => ({
         use args::AnyArg;
         debugln!("_handle_group_reqs!;");
-        for grp in $me.groups.values() {
+        for grp in $me.groups.iter() {
             let found = if grp.args.contains(&$arg.name()) {
-                vec_remove!($me.required, &$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);
@@ -126,18 +128,6 @@ macro_rules! _handle_group_reqs{
     })
 }
 
-macro_rules! validate_multiples {
-    ($_self:ident, $a:ident, $m:ident) => {
-        debugln!("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, None),
-                $_self.color()))
-        }
-    };
-}
-
 macro_rules! parse_positional {
     (
         $_self:ident,
@@ -147,12 +137,11 @@ macro_rules! parse_positional {
         $matcher:ident
     ) => {
         debugln!("parse_positional!;");
-        validate_multiples!($_self, $p, $matcher);
 
-        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));
 
@@ -166,89 +155,3 @@ macro_rules! parse_positional {
         }
     };
 }
-
-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))
-            })
-    }
-}
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 7135e9f7..67683f0e 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -6,7 +6,6 @@ mod meta;
 mod help;
 
 // Std
-use std::borrow::Borrow;
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::fmt;
@@ -639,8 +638,8 @@ impl<'a, 'b> App<'a, 'b> {
     /// # ;
     /// ```
     /// [argument]: ./struct.Arg.html
-    pub fn arg<A: Borrow<Arg<'a, 'b>> + 'a>(mut self, a: A) -> Self {
-        self.p.add_arg(a.borrow());
+    pub fn arg<A: Into<Arg<'a, 'b>>>(mut self, a: A) -> Self {
+        self.p.add_arg(a.into());
         self
     }
 
@@ -660,7 +659,7 @@ impl<'a, 'b> App<'a, 'b> {
     /// [arguments]: ./struct.Arg.html
     pub fn args(mut self, args: &[Arg<'a, 'b>]) -> Self {
         for arg in args {
-            self.p.add_arg(arg);
+            self.p.add_arg_ref(arg);
         }
         self
     }
@@ -683,7 +682,7 @@ impl<'a, 'b> App<'a, 'b> {
     /// [`Arg`]: ./struct.Arg.html
     /// [`Arg::from_usage`]: ./struct.Arg.html#method.from_usage
     pub fn arg_from_usage(mut self, usage: &'a str) -> Self {
-        self.p.add_arg(&Arg::from_usage(usage));
+        self.p.add_arg(Arg::from_usage(usage));
         self
     }
 
@@ -715,7 +714,7 @@ impl<'a, 'b> App<'a, 'b> {
             if l.is_empty() {
                 continue;
             }
-            self.p.add_arg(&Arg::from_usage(l));
+            self.p.add_arg(Arg::from_usage(l));
         }
         self
     }
@@ -1531,7 +1530,6 @@ impl<'n, 'e> AnyArg<'n, 'e> for App<'n, 'e> {
     fn name(&self) -> &'n str {
         unreachable!("App struct does not support AnyArg::name, this is a bug!")
     }
-    fn id(&self) -> usize { self.p.id }
     fn overrides(&self) -> Option<&[&'e str]> { None }
     fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> { None }
     fn blacklist(&self) -> Option<&[&'e str]> { None }
diff --git a/src/app/parser.rs b/src/app/parser.rs
index 4b5ec83c..9253b5df 100644
--- a/src/app/parser.rs
+++ b/src/app/parser.rs
@@ -1,5 +1,5 @@
 // Std
-use std::collections::{BTreeMap, HashMap, VecDeque};
+use std::collections::{BTreeMap, VecDeque};
 use std::ffi::{OsStr, OsString};
 use std::fmt::Display;
 use std::fs::File;
@@ -20,9 +20,9 @@ use SubCommand;
 use app::App;
 use app::help::Help;
 use app::meta::AppMeta;
-use app::settings::{AppFlags, AppSettings};
-use args::{AnyArg, ArgMatcher, Base, Switched, Arg, ArgGroup, FlagBuilder, OptBuilder, PosBuilder};
-use args::MatchedArg;
+use app::settings::AppFlags;
+use args::{AnyArg, ArgMatcher, Base, Switched, Arg, ArgGroup, FlagBuilder, OptBuilder, PosBuilder,
+           MatchedArg};
 use args::settings::ArgSettings;
 use completions::ComplGen;
 use errors::{Error, ErrorKind};
@@ -31,69 +31,29 @@ use fmt::{Colorizer, ColorWhen};
 use osstringext::OsStrExt2;
 use completions::Shell;
 use suggestions;
+use app::settings::AppSettings as AS;
 
 #[allow(missing_debug_implementations)]
 #[doc(hidden)]
+#[derive(Clone, Default)]
 pub struct Parser<'a, 'b>
     where 'a: 'b
 {
-    propogated: bool,
-    required: Vec<&'a str>,
-    r_ifs: Vec<(&'a str, &'b str, &'a str)>,
-    pub short_list: Vec<char>,
-    pub long_list: Vec<&'b str>,
-    blacklist: Vec<&'b str>,
-    // A list of possible flags
+    pub meta: AppMeta<'b>,
+    settings: AppFlags,
+    pub g_settings: AppFlags,
     pub flags: Vec<FlagBuilder<'a, 'b>>,
-    // A list of possible options
     pub opts: Vec<OptBuilder<'a, 'b>>,
-    // A list of positional arguments
     pub positionals: VecMap<PosBuilder<'a, 'b>>,
-    // A list of subcommands
-    #[doc(hidden)]
     pub subcommands: Vec<App<'a, 'b>>,
-    groups: HashMap<&'a str, ArgGroup<'a>>,
+    groups: Vec<ArgGroup<'a>>,
     pub global_args: Vec<Arg<'a, 'b>>,
+    required: Vec<&'a str>,
+    r_ifs: Vec<(&'a str, &'b str, &'a str)>,
+    blacklist: Vec<&'b str>,
     overrides: Vec<&'b str>,
     help_short: Option<char>,
     version_short: Option<char>,
-    settings: AppFlags,
-    pub g_settings: AppFlags,
-    pub meta: AppMeta<'b>,
-    pub id: usize,
-    trailing_vals: bool,
-    valid_neg_num: bool,
-    // have we found a valid arg yet
-    valid_arg: bool,
-}
-
-impl<'a, 'b> Default for Parser<'a, 'b> {
-    fn default() -> Self {
-        Parser {
-            propogated: false,
-            flags: vec![],
-            opts: vec![],
-            positionals: VecMap::new(),
-            subcommands: vec![],
-            help_short: None,
-            version_short: None,
-            required: vec![],
-            r_ifs: vec![],
-            short_list: vec![],
-            long_list: vec![],
-            blacklist: vec![],
-            groups: HashMap::new(),
-            global_args: vec![],
-            overrides: vec![],
-            g_settings: AppFlags::new(),
-            settings: AppFlags::new(),
-            meta: AppMeta::new(),
-            trailing_vals: false,
-            id: 0,
-            valid_neg_num: false,
-            valid_arg: false,
-        }
-    }
 }
 
 impl<'a, 'b> Parser<'a, 'b>
@@ -104,24 +64,28 @@ impl<'a, 'b> Parser<'a, 'b>
     }
 
     pub fn help_short(&mut self, s: &str) {
-        self.help_short = s.trim_left_matches(|c| c == '-')
+        let c = s.trim_left_matches(|c| c == '-')
             .chars()
-            .nth(0);
+            .nth(0)
+            .unwrap_or('h');
+        self.help_short = Some(c);
     }
 
     pub fn version_short(&mut self, s: &str) {
-        self.version_short = s.trim_left_matches(|c| c == '-')
+        let c = s.trim_left_matches(|c| c == '-')
             .chars()
-            .nth(0);
+            .nth(0)
+            .unwrap_or('V');
+        self.version_short = Some(c);
     }
 
     pub fn gen_completions_to<W: Write>(&mut self, for_shell: Shell, buf: &mut W) {
-        if !self.propogated {
+        if !self.is_set(AS::Propogated) {
             self.propogate_help_version();
             self.build_bin_names();
             self.propogate_globals();
             self.propogate_settings();
-            self.propogated = true;
+            self.set(AS::Propogated);
         }
 
         ComplGen::new(self).generate(for_shell, buf)
@@ -146,81 +110,134 @@ impl<'a, 'b> Parser<'a, 'b>
         self.gen_completions_to(for_shell, &mut file)
     }
 
-    // actually adds the arguments
-    pub fn add_arg(&mut self, a: &Arg<'a, 'b>) {
-        debug_assert!(!(self.flags.iter().any(|f| &f.b.name == &a.b.name) ||
-                        self.opts.iter().any(|o| o.b.name == a.b.name) ||
-                        self.positionals.values().any(|p| p.b.name == a.b.name)),
+    #[inline]
+    fn debug_asserts(&self, a: &Arg) {
+        debug_assert!(!arg_names!(self).any(|name| name == a.b.name),
                       format!("Non-unique argument name: {} is already in use", a.b.name));
+        if let Some(l) = a.s.long {
+            debug_assert!(!self.contains_long(l),
+                          format!("Argument long must be unique\n\n\t--{} is already in use",
+                                  l));
+        }
+        if let Some(s) = a.s.short {
+            debug_assert!(!self.contains_short(s),
+                          format!("Argument short must be unique\n\n\t-{} is already in use",
+                                  s));
+        }
+        let i = if a.index.is_none() {
+            (self.positionals.len() + 1)
+        } else {
+            a.index.unwrap() as usize
+        };
+        debug_assert!(!self.positionals.contains_key(i),
+                      format!("Argument \"{}\" has the same index as another positional \
+                    argument\n\n\tPerhaps try .multiple(true) to allow one positional argument \
+                    to take multiple values",
+                              a.b.name));
+        debug_assert!(!(a.is_set(ArgSettings::Required) && a.is_set(ArgSettings::Global)),
+                      format!("Global arguments cannot be required.\n\n\t'{}' is marked as \
+                          global and required",
+                              a.b.name));
+    }
+
+    #[inline]
+    fn add_conditional_reqs(&mut self, a: &Arg<'a, 'b>) {
         if let Some(ref r_ifs) = a.r_ifs {
             for &(arg, val) in r_ifs {
                 self.r_ifs.push((arg, val, a.b.name));
             }
         }
+    }
+
+    #[inline]
+    fn add_arg_groups(&mut self, a: &Arg<'a, 'b>) {
         if let Some(ref grps) = a.b.groups {
             for g in grps {
-                let ag = self.groups.entry(g).or_insert_with(|| ArgGroup::with_name(g));
-                ag.args.push(a.b.name);
-            }
-        }
-        if let Some(s) = a.s.short {
-            debug_assert!(!self.short_list.contains(&s),
-                          format!("Argument short must be unique\n\n\t-{} is already in use",
-                                  s));
-            self.short_list.push(s);
-        }
-        if let Some(l) = a.s.long {
-            debug_assert!(!self.long_list.contains(&l),
-                          format!("Argument long must be unique\n\n\t--{} is already in use",
-                                  l));
-            self.long_list.push(l);
-            if l == "help" {
-                self.unset(AppSettings::NeedsLongHelp);
-            } else if l == "version" {
-                self.unset(AppSettings::NeedsLongVersion);
+                let mut found = false;
+                if let Some(ref mut ag) = self.groups.iter_mut().find(|grp| &grp.name == g) {
+                    ag.args.push(a.b.name);
+                    found = true;
+                }
+                if !found {
+                    let mut ag = ArgGroup::with_name(g);
+                    ag.args.push(a.b.name);
+                    self.groups.push(ag);
+                }
             }
         }
+    }
+
+    #[inline]
+    fn add_reqs(&mut self, a: &Arg<'a, 'b>) {
         if a.is_set(ArgSettings::Required) {
+            // If the arg is required, add all it's requirements to master required list
+            if let Some(ref areqs) = a.b.requires {
+                for name in areqs.iter().filter(|&&(val, _)| val.is_none()).map(|&(_, name)| name) {
+                    self.required.push(name);
+                }
+            }
             self.required.push(a.b.name);
         }
+    }
+
+    // actually adds the arguments
+    pub fn add_arg(&mut self, a: Arg<'a, 'b>) {
+        // if it's global we have to clone anyways
+        if a.is_set(ArgSettings::Global) {
+            return self.add_arg_ref(&a);
+        }
+        self.debug_asserts(&a);
+        self.add_conditional_reqs(&a);
+        self.add_arg_groups(&a);
+        self.add_reqs(&a);
         if a.index.is_some() || (a.s.short.is_none() && a.s.long.is_none()) {
             let i = if a.index.is_none() {
                 (self.positionals.len() + 1)
             } else {
                 a.index.unwrap() as usize
             };
-            debug_assert!(!self.positionals.contains_key(i),
-                          format!("Argument \"{}\" has the same index as another positional \
-                    argument\n\n\tPerhaps try .multiple(true) to allow one positional argument \
-                    to take multiple values",
-                                  a.b.name));
-            let pb = PosBuilder::from_arg(a, i as u64, &mut self.required);
+            self.positionals.insert(i, PosBuilder::from_arg(a, i as u64));
+        } else if a.is_set(ArgSettings::TakesValue) {
+            let mut ob = OptBuilder::from(a);
+            ob.s.unified_ord = self.flags.len() + self.opts.len();
+            self.opts.push(ob);
+        } else {
+            let mut fb = FlagBuilder::from(a);
+            fb.s.unified_ord = self.flags.len() + self.opts.len();
+            self.flags.push(fb);
+        }
+    }
+    // actually adds the arguments but from a borrow (which means we have to do some clonine)
+    pub fn add_arg_ref(&mut self, a: &Arg<'a, 'b>) {
+        self.debug_asserts(&a);
+        self.add_conditional_reqs(&a);
+        self.add_arg_groups(&a);
+        self.add_reqs(&a);
+        if a.index.is_some() || (a.s.short.is_none() && a.s.long.is_none()) {
+            let i = if a.index.is_none() {
+                (self.positionals.len() + 1)
+            } else {
+                a.index.unwrap() as usize
+            };
+            let pb = PosBuilder::from_arg_ref(a, i as u64);
             self.positionals.insert(i, pb);
         } else if a.is_set(ArgSettings::TakesValue) {
-            let mut ob = OptBuilder::from_arg(a, &mut self.required);
-            let id = self.opts.len();
-            ob.b.id = id;
+            let mut ob = OptBuilder::from(a);
             ob.s.unified_ord = self.flags.len() + self.opts.len();
-            self.opts.insert(id, ob);
+            self.opts.push(ob);
         } else {
             let mut fb = FlagBuilder::from(a);
-            let id = self.flags.len();
-            fb.b.id = id;
             fb.s.unified_ord = self.flags.len() + self.opts.len();
-            self.flags.insert(id, fb);
+            self.flags.push(fb);
         }
         if a.is_set(ArgSettings::Global) {
-            debug_assert!(!a.is_set(ArgSettings::Required),
-                          format!("Global arguments cannot be required.\n\n\t'{}' is marked as \
-                          global and required",
-                                  a.b.name));
             self.global_args.push(a.into());
         }
     }
 
     pub fn add_group(&mut self, group: ArgGroup<'a>) {
         if group.required {
-            self.required.push(group.name.into());
+            self.required.push(group.name);
             if let Some(ref reqs) = group.requires {
                 self.required.extend_from_slice(reqs);
             }
@@ -228,16 +245,15 @@ impl<'a, 'b> Parser<'a, 'b>
                 self.blacklist.extend_from_slice(bl);
             }
         }
-        let mut found = false;
-        if let Some(ref mut grp) = self.groups.get_mut(&group.name) {
+        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);
             grp.args.extend_from_slice(&group.args);
             grp.requires = group.requires.clone();
             grp.conflicts = group.conflicts.clone();
             grp.required = group.required;
-            found = true;
-        }
-        if !found {
-            self.groups.insert(group.name.into(), group);
+        } else {
+            self.groups.push(group);
         }
     }
 
@@ -247,7 +263,7 @@ impl<'a, 'b> Parser<'a, 'b>
                  subcmd.p.meta.name);
         subcmd.p.meta.term_w = self.meta.term_w;
         if subcmd.p.meta.name == "help" {
-            self.settings.unset(AppSettings::NeedsSubcommandHelp);
+            self.unset(AS::NeedsSubcommandHelp);
         }
 
         self.subcommands.push(subcmd);
@@ -265,14 +281,14 @@ impl<'a, 'b> Parser<'a, 'b>
             // We have to create a new scope in order to tell rustc the borrow of `sc` is
             // done and to recursively call this method
             {
-                let vsc = self.settings.is_set(AppSettings::VersionlessSubcommands);
-                let gv = self.settings.is_set(AppSettings::GlobalVersion);
+                let vsc = self.settings.is_set(AS::VersionlessSubcommands);
+                let gv = self.settings.is_set(AS::GlobalVersion);
 
                 if vsc {
-                    sc.p.settings.set(AppSettings::DisableVersion);
+                    sc.p.set(AS::DisableVersion);
                 }
                 if gv && sc.p.meta.version.is_none() && self.meta.version.is_some() {
-                    sc.p.set(AppSettings::GlobalVersion);
+                    sc.p.set(AS::GlobalVersion);
                     sc.p.meta.version = Some(self.meta.version.unwrap());
                 }
                 sc.p.settings = sc.p.settings | self.g_settings;
@@ -284,8 +300,8 @@ impl<'a, 'b> Parser<'a, 'b>
 
     #[cfg_attr(feature = "lints", allow(needless_borrow))]
     pub fn derive_display_order(&mut self) {
-        if self.settings.is_set(AppSettings::DeriveDisplayOrder) {
-            let unified = self.settings.is_set(AppSettings::UnifiedHelpMessage);
+        if self.is_set(AS::DeriveDisplayOrder) {
+            let unified = self.is_set(AS::UnifiedHelpMessage);
             for (i, o) in self.opts
                 .iter_mut()
                 .enumerate()
@@ -321,120 +337,120 @@ impl<'a, 'b> Parser<'a, 'b>
         debugln!("Parser::get_required_from: reqs={:?}, extra={:?}",
                  reqs,
                  extra);
-        let mut c_flags: Vec<&str> = vec![];
-        let mut c_pos: Vec<&str> = vec![];
-        let mut c_opt: Vec<&str> = vec![];
-        let mut grps: Vec<&str> = vec![];
-        macro_rules! categorize {
-            ($_self:ident, $name:ident, $c_flags:ident, $c_pos:ident, $c_opt:ident, $grps:ident) => {
-                if $_self.flags.iter().any(|f| &f.b.name == $name) {
-                    $c_flags.push($name);
-                } else if self.opts.iter().any(|o| &o.b.name == $name) {
-                    $c_opt.push($name);
-                } else if self.groups.contains_key($name) {
-                    $grps.push($name);
-                } else {
-                    $c_pos.push($name);
+        let mut desc_reqs: Vec<&str> = vec![];
+        desc_reqs.extend(extra);
+        let mut new_reqs: Vec<&str> = vec![];
+        macro_rules! get_requires {
+            (@group $a: ident, $v:ident, $p:ident) => {{
+                if let Some(rl) = self.groups.iter().filter(|g| g.requires.is_some()).find(|g| &g.name == $a).map(|g| g.requires.as_ref().unwrap()) {
+                    for r in rl {
+                        if !$p.contains(&r) {
+                            debugln!("Parser::get_required_from:iter:{}: adding group req={:?}", $a, r);
+                            $v.push(r);
+                        }
+                    }
                 }
-            }
-        };
-        for name in reqs {
-            categorize!(self, name, c_flags, c_pos, c_opt, grps);
-        }
-        if let Some(ref name) = extra {
-            categorize!(self, name, c_flags, c_pos, c_opt, grps);
-        }
-        macro_rules! fill_vecs {
-            ($_self:ident {
-                $t1:ident => $v1:ident => $i1:ident,
-                $t2:ident => $v2:ident => $i2:ident,
-                $t3:ident => $v3:ident => $i3:ident,
-                $gv:ident, $tmp:ident
-            }) => {
-                for a in &$v1 {
-                    if let Some(a) = self.$t1.$i1().filter(|arg| &arg.b.name == a).next() {
-                        if let Some(ref rl) = a.b.requires {
-                            for &(_, r) in rl.iter() {
-                                if !reqs.contains(&r) {
-                                    if $_self.$t1.$i1().any(|t| &t.b.name == &r) {
-                                        $tmp.push(r);
-                                    } else if $_self.$t2.$i2().any(|t| &t.b.name == &r) {
-                                        $v2.push(r);
-                                    } else if $_self.$t3.$i3().any(|t| &t.b.name == &r) {
-                                        $v3.push(r);
-                                    } else if $_self.groups.contains_key(r) {
-                                        $gv.push(r);
-                                    }
-                                }
-                            }
+            }};
+            ($a:ident, $what:ident, $how:ident, $v:ident, $p:ident) => {{
+                if let Some(rl) = self.$what.$how().filter(|a| a.b.requires.is_some()).find(|arg| &arg.b.name == $a).map(|a| a.b.requires.as_ref().unwrap()) {
+                    for &(_, r) in rl.iter() {
+                        if !$p.contains(&r) {
+                            debugln!("Parser::get_required_from:iter:{}: adding arg req={:?}",$a, r);
+                            $v.push(r);
                         }
                     }
                 }
-                $v1.extend(&$tmp);
-            };
-        }
-
-        let mut tmp = vec![];
-        fill_vecs!(self {
-            flags       => c_flags => iter,
-            opts        => c_opt   => iter,
-            positionals => c_pos   => values,
-            grps, tmp
-        });
-        tmp.clear();
-        fill_vecs!(self {
-            opts        => c_opt   => iter,
-            flags       => c_flags => iter,
-            positionals => c_pos   => values,
-            grps, tmp
-        });
-        tmp.clear();
-        fill_vecs!(self {
-            positionals => c_pos   => values,
-            opts        => c_opt   => iter,
-            flags       => c_flags => iter,
-            grps, tmp
-        });
+            }};
+        }
+        // initialize new_reqs
+        for a in reqs {
+            get_requires!(a, flags, iter, new_reqs, reqs);
+            get_requires!(a, opts, iter, new_reqs, reqs);
+            get_requires!(a, positionals, values, new_reqs, reqs);
+            get_requires!(@group a, new_reqs, reqs);
+        }
+        desc_reqs.extend_from_slice(&*new_reqs);
+        debugln!("Parser::get_required_from: after init desc_reqs={:?}",
+                 desc_reqs);
+        loop {
+            let mut tmp = vec![];
+            for a in &new_reqs {
+                get_requires!(a, flags, iter, tmp, desc_reqs);
+                get_requires!(a, opts, iter, tmp, desc_reqs);
+                get_requires!(a, positionals, values, tmp, desc_reqs);
+                get_requires!(@group a, tmp, desc_reqs);
+            }
+            if tmp.is_empty() {
+                debugln!("Parser::get_required_from: no more children");
+                break;
+            } else {
+                debugln!("Parser::get_required_from: after iter tmp={:?}", tmp);
+                debugln!("Parser::get_required_from: after iter new_reqs={:?}",
+                         new_reqs);
+                desc_reqs.extend_from_slice(&*new_reqs);
+                new_reqs.clear();
+                new_reqs.extend_from_slice(&*tmp);
+                debugln!("Parser::get_required_from: after iter desc_reqs={:?}",
+                         desc_reqs);
+            }
+        }
+        desc_reqs.extend_from_slice(reqs);
+        desc_reqs.sort();
+        desc_reqs.dedup();
+        debugln!("Parser::get_required_from: final desc_reqs={:?}", desc_reqs);
         let mut ret_val = VecDeque::new();
-        c_pos.dedup();
-        c_flags.dedup();
-        c_opt.dedup();
-        grps.dedup();
-        let args_in_groups = grps.iter()
-            .flat_map(|g| self.arg_names_in_group(g))
+        let args_in_groups = self.groups
+            .iter()
+            .filter(|gn| desc_reqs.contains(&gn.name))
+            .flat_map(|g| self.arg_names_in_group(&g.name))
             .collect::<Vec<_>>();
 
-        let pmap = c_pos.into_iter()
-            .filter(|&p| matcher.is_none() || !matcher.as_ref().unwrap().contains(p))
-            .filter_map(|p| self.positionals.values().find(|x| x.b.name == p))
-            .filter(|p| !args_in_groups.contains(&p.b.name))
-            .map(|p| (p.index, p))
-            .collect::<BTreeMap<u64, &PosBuilder>>(); // sort by index
-        debugln!("Parser::get_required_from: args_in_groups={:?}", args_in_groups);
+        let pmap = if let Some(ref m) = matcher {
+            desc_reqs.iter()
+                .filter(|a| self.positionals.values().any(|p| &&p.b.name == a))
+                .filter(|&p| !m.contains(p))
+                .filter_map(|p| self.positionals.values().find(|x| &x.b.name == p))
+                .filter(|p| !args_in_groups.contains(&p.b.name))
+                .map(|p| (p.index, p))
+                .collect::<BTreeMap<u64, &PosBuilder>>() // sort by index
+        } else {
+            desc_reqs.iter()
+                .filter(|a| self.positionals.values().any(|p| &&p.b.name == a))
+                .filter_map(|p| self.positionals.values().find(|x| &x.b.name == p))
+                .filter(|p| !args_in_groups.contains(&p.b.name))
+                .map(|p| (p.index, p))
+                .collect::<BTreeMap<u64, &PosBuilder>>() // sort by index
+        };
+        debugln!("Parser::get_required_from: args_in_groups={:?}",
+                 args_in_groups);
         for &p in pmap.values() {
             let s = p.to_string();
             if args_in_groups.is_empty() || !args_in_groups.contains(&&*s) {
                 ret_val.push_back(s);
             }
         }
-        macro_rules! write_arg {
-            ($i:expr, $m:ident, $v:ident, $r:ident, $aig:ident) => {
-                for f in $v {
-                    if $m.is_some() && $m.as_ref().unwrap().contains(f) || $aig.contains(&f) {
-                        continue;
-                    }
-                    $r.push_back($i.filter(|flg| &flg.b.name == &f).next().unwrap().to_string());
-                }
-            }
+        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))) {
+            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)
+                });
+            ret_val.push_back(arg);
         }
-        write_arg!(self.flags.iter(), matcher, c_flags, ret_val, args_in_groups);
-        write_arg!(self.opts.iter(), matcher, c_opt, ret_val, args_in_groups);
         let mut g_vec = vec![];
-        for g in grps {
+        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("|");
             g_vec.push(format!("<{}>", &g_string[..g_string.len()]));
         }
+        g_vec.sort();
         g_vec.dedup();
         for g in g_vec {
             ret_val.push_back(g);
@@ -448,24 +464,20 @@ impl<'a, 'b> Parser<'a, 'b>
         debugln!("Parser::get_args_tag;");
         let mut count = 0;
         'outer: for p in self.positionals.values().filter(|p| !p.is_set(ArgSettings::Required)) {
-            debugln!("Parser::get_args_tag:iter:iter: p={};", p.b.name);
+            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 {
-                    debugln!("Parser::get_args_tag:iter:iter: grp_s={};", grp_s);
-                    if let Some(grp) = self.groups.get(grp_s) {
-                        debug!("Parser::get_args_tag:iter:iter: Is group required...{:?}", grp.required);
-                        if grp.required {
-                            // if it's part of a required group we don't want to count it
-                            continue 'outer;
-                        }
+                    debugln!("Parser::get_args_tag:iter:{}:iter:{};", p.b.name, grp_s);
+                    // if it's part of a required group we don't want to count it
+                    if self.groups.iter().any(|g| g.required && (&g.name == grp_s)) {
+                        continue 'outer;
                     }
                 }
             }
             count += 1;
             debugln!("Parser::get_args_tag:iter: {} Args not required", count);
         }
-        if !self.is_set(AppSettings::DontCollapseArgsInUsage) &&
-           (count > 1 || self.positionals.len() > 1) {
+        if !self.is_set(AS::DontCollapseArgsInUsage) && (count > 1 || self.positionals.len() > 1) {
             return None; // [ARGS]
         } else if count == 1 {
             let p = self.positionals
@@ -473,8 +485,7 @@ impl<'a, 'b> Parser<'a, 'b>
                 .find(|p| !p.is_set(ArgSettings::Required))
                 .expect(INTERNAL_ERROR_MSG);
             return Some(format!(" [{}]{}", p.name_no_brackets(), p.multiple_str()));
-        } else if self.is_set(AppSettings::DontCollapseArgsInUsage) &&
-                  !self.positionals.is_empty() {
+        } else if self.is_set(AS::DontCollapseArgsInUsage) && !self.positionals.is_empty() {
             return Some(self.positionals
                 .values()
                 .filter(|p| !p.is_set(ArgSettings::Required))
@@ -499,11 +510,9 @@ impl<'a, 'b> Parser<'a, 'b>
             if let Some(g_vec) = self.groups_for_arg(f.b.name) {
                 for grp_s in &g_vec {
                     debugln!("Parser::needs_flags_tag:iter:iter: grp_s={};", grp_s);
-                    if let Some(grp) = self.groups.get(grp_s) {
-                        debug!("Parser::needs_flags_tag:iter:iter: Is group required...{:?}", grp.required);
-                        if grp.required {
-                            continue 'outer;
-                        }
+                    if self.groups.iter().any(|g| &g.name == grp_s && g.required) {
+                        debug!("Parser::needs_flags_tag:iter:iter: Group is required");
+                        continue 'outer;
                     }
                 }
             }
@@ -528,13 +537,13 @@ impl<'a, 'b> Parser<'a, 'b>
     pub fn has_subcommands(&self) -> bool { !self.subcommands.is_empty() }
 
     #[inline]
-    pub fn is_set(&self, s: AppSettings) -> bool { self.settings.is_set(s) }
+    pub fn is_set(&self, s: AS) -> bool { self.settings.is_set(s) }
 
     #[inline]
-    pub fn set(&mut self, s: AppSettings) { self.settings.set(s) }
+    pub fn set(&mut self, s: AS) { self.settings.set(s) }
 
     #[inline]
-    pub fn unset(&mut self, s: AppSettings) { self.settings.unset(s) }
+    pub fn unset(&mut self, s: AS) { self.settings.unset(s) }
 
     #[cfg_attr(feature = "lints", allow(block_in_if_condition_stmt))]
     pub fn verify_positionals(&mut self) {
@@ -546,11 +555,11 @@ impl<'a, 'b> Parser<'a, 'b>
         // but no 2)
         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 \
+                          format!("Found positional argument \"{}\" who's index is {} but there are \
                     only {} positional arguments defined",
-                            p.b.name,
-                            idx,
-                            self.positionals.len()));
+                                  p.b.name,
+                                  idx,
+                                  self.positionals.len()));
         }
 
         // Next we verify that only the highest index has a .multiple(true) (if any)
@@ -562,36 +571,37 @@ impl<'a, 'b> Parser<'a, 'b>
                 }) {
 
             debug_assert!({
-                    let mut it = self.positionals.values().rev();
-                    // Either the final positional is required
-                    it.next().unwrap().is_set(ArgSettings::Required)
+                              let mut it = self.positionals.values().rev();
+                              // Either the final positional is required
+                              it.next().unwrap().is_set(ArgSettings::Required)
                     // Or the second to last has a terminator set
                     || it.next().unwrap().v.terminator.is_some()
-                },
-                "When using a positional argument with .multiple(true) that is *not the last* \
+                          },
+                          "When using a positional argument with .multiple(true) that is *not the last* \
                 positional argument, the last positional argument (i.e the one with the highest \
-                index) *must* have .required(true) set."
-            );
+                index) *must* have .required(true) set.");
 
             debug_assert!({
-                let num = self.positionals.len() - 1;
-                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)");
+                              let num = self.positionals.len() - 1;
+                              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)");
 
-            self.set(AppSettings::LowIndexMultiplePositional);
+            self.set(AS::LowIndexMultiplePositional);
         }
 
-        debug_assert!(self.positionals.values()
-            .filter(|p| 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 command");
+        debug_assert!(self.positionals
+                          .values()
+                          .filter(|p| {
+                              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 command");
 
         // If it's required we also need to ensure all previous positionals are
         // required too
-        if self.is_set(AppSettings::AllowMissingPositional) {
+        if self.is_set(AS::AllowMissingPositional) {
             let mut found = false;
             let mut foundx2 = false;
             for p in self.positionals.values().rev() {
@@ -599,10 +609,10 @@ impl<'a, 'b> Parser<'a, 'b>
                     // [arg1] <arg2> is Ok
                     // [arg1] <arg2> <arg3> Is not
                     debug_assert!(p.b.settings.is_set(ArgSettings::Required),
-                                "Found positional argument which is not required with a lower index \
+                                  "Found positional argument which is not required with a lower index \
                                 than a required positional argument by two or more: {:?} index {}",
-                                p.b.name,
-                                p.index);
+                                  p.b.name,
+                                  p.index);
                 } else if p.b.settings.is_set(ArgSettings::Required) {
                     if found {
                         foundx2 = true;
@@ -619,10 +629,10 @@ impl<'a, 'b> Parser<'a, 'b>
             for p in self.positionals.values().rev() {
                 if found {
                     debug_assert!(p.b.settings.is_set(ArgSettings::Required),
-                                "Found positional argument which is not required with a lower index \
+                                  "Found positional argument which is not required with a lower index \
                                 than a required positional argument: {:?} index {}",
-                                p.b.name,
-                                p.index);
+                                  p.b.name,
+                                  p.index);
                 } else if p.b.settings.is_set(ArgSettings::Required) {
                     found = true;
                     continue;
@@ -637,7 +647,7 @@ impl<'a, 'b> Parser<'a, 'b>
             // done and to recursively call this method
             {
                 for a in &self.global_args {
-                    sc.p.add_arg(a);
+                    sc.p.add_arg_ref(a);
                 }
             }
             sc.p.propogate_globals();
@@ -648,7 +658,7 @@ impl<'a, 'b> Parser<'a, 'b>
     #[inline]
     fn possible_subcommand(&self, arg_os: &OsStr) -> bool {
         debugln!("Parser::possible_subcommand: arg={:?}", arg_os);
-        if self.is_set(AppSettings::ArgsNegateSubcommands) && self.valid_arg {
+        if self.is_set(AS::ArgsNegateSubcommands) && self.is_set(AS::ValidArgFound) {
             return false;
         }
         self.subcommands
@@ -716,9 +726,7 @@ impl<'a, 'b> Parser<'a, 'b>
                                                                   .unwrap_or(&self.meta.name),
                                                               self.color()));
                 }
-                bin_name = format!("{} {}",
-                    bin_name,
-                    &*sc.meta.name);
+                bin_name = format!("{} {}", bin_name, &*sc.meta.name);
             }
             sc.clone()
         };
@@ -741,13 +749,15 @@ impl<'a, 'b> Parser<'a, 'b>
     #[cfg_attr(feature = "lints", allow(wrong_self_convention))]
     #[inline]
     fn is_new_arg(&mut self, arg_os: &OsStr, needs_val_of: Option<&'a str>) -> bool {
-        debugln!("Parser::is_new_arg: arg={:?}, Needs Val of={:?}", arg_os, needs_val_of);
-        let app_wide_settings = if self.is_set(AppSettings::AllowLeadingHyphen) {
+        debugln!("Parser::is_new_arg: arg={:?}, Needs Val of={:?}",
+                 arg_os,
+                 needs_val_of);
+        let app_wide_settings = if self.is_set(AS::AllowLeadingHyphen) {
             true
-        } else if self.is_set(AppSettings::AllowNegativeNumbers) {
+        } else if self.is_set(AS::AllowNegativeNumbers) {
             let a = arg_os.to_string_lossy();
             if a.parse::<i64>().is_ok() || a.parse::<f64>().is_ok() {
-                self.valid_neg_num = true;
+                self.set(AS::ValidNegNumFound);
                 true
             } else {
                 false
@@ -766,7 +776,8 @@ impl<'a, 'b> Parser<'a, 'b>
         } else {
             false
         };
-        debugln!("Parser::is_new_arg: Does arg allow leading hyphen...{:?}", arg_allows_tac);
+        debugln!("Parser::is_new_arg: Does arg allow leading hyphen...{:?}",
+                 arg_allows_tac);
 
         // Is this a new argument, or values from a previous option?
         debug!("Parser::is_new_arg: Starts new arg...");
@@ -813,17 +824,19 @@ impl<'a, 'b> Parser<'a, 'b>
         let mut pos_counter = 1;
         while let Some(arg) = it.next() {
             let arg_os = arg.into();
-            debugln!("Parser::get_matches_with: Begin parsing '{:?}' ({:?})", arg_os, &*arg_os.as_bytes());
+            debugln!("Parser::get_matches_with: Begin parsing '{:?}' ({:?})",
+                     arg_os,
+                     &*arg_os.as_bytes());
 
-            self.valid_neg_num = false;
+            self.unset(AS::ValidNegNumFound);
             // Is this a new argument, or values from a previous option?
             let starts_new_arg = self.is_new_arg(&arg_os, needs_val_of);
 
             // Has the user already passed '--'? Meaning only positional args follow
-            if !self.trailing_vals {
+            if !self.is_set(AS::TrailingValues) {
                 // Does the arg match a subcommand name, or any of it's aliases (if defined)
                 if self.possible_subcommand(&arg_os) {
-                    if &*arg_os == "help" && self.is_set(AppSettings::NeedsSubcommandHelp) {
+                    if &*arg_os == "help" && self.is_set(AS::NeedsSubcommandHelp) {
                         try!(self.parse_help_subcommand(it));
                     }
                     subcmd_name = Some(arg_os.to_str().expect(INVALID_UTF8).to_owned());
@@ -845,13 +858,12 @@ impl<'a, 'b> Parser<'a, 'b>
                         if arg_os.len_() == 2 {
                             // The user has passed '--' which means only positional args follow no
                             // matter what they start with
-                            self.trailing_vals = true;
+                            self.set(AS::TrailingValues);
                             continue;
                         }
 
                         needs_val_of = try!(self.parse_long_arg(matcher, &arg_os));
-                        if !(needs_val_of.is_none() &&
-                             self.is_set(AppSettings::AllowLeadingHyphen)) {
+                        if !(needs_val_of.is_none() && self.is_set(AS::AllowLeadingHyphen)) {
                             continue;
                         }
                     } else if arg_os.starts_with(b"-") && arg_os.len_() != 1 {
@@ -861,7 +873,7 @@ impl<'a, 'b> Parser<'a, 'b>
                         needs_val_of = try!(self.parse_short_arg(matcher, &arg_os));
                         // If it's None, we then check if one of those two AppSettings was set
                         if needs_val_of.is_none() {
-                            if self.is_set(AppSettings::AllowNegativeNumbers) {
+                            if self.is_set(AS::AllowNegativeNumbers) {
                                 if !(arg_os.to_string_lossy().parse::<i64>().is_ok() ||
                                      arg_os.to_string_lossy().parse::<f64>().is_ok()) {
                                     return Err(Error::unknown_argument(&*arg_os.to_string_lossy(),
@@ -869,7 +881,7 @@ impl<'a, 'b> Parser<'a, 'b>
                                                                 &*self.create_current_usage(matcher, None),
                                                                 self.color()));
                                 }
-                            } else if !self.is_set(AppSettings::AllowLeadingHyphen) {
+                            } else if !self.is_set(AS::AllowLeadingHyphen) {
                                 continue;
                             }
                         } else {
@@ -878,7 +890,7 @@ impl<'a, 'b> Parser<'a, 'b>
                     }
                 }
 
-                if !self.is_set(AppSettings::ArgsNegateSubcommands) {
+                if !self.is_set(AS::ArgsNegateSubcommands) {
                     if let Some(cdate) = suggestions::did_you_mean(&*arg_os.to_string_lossy(),
                                                                    self.subcommands
                                                                        .iter()
@@ -897,14 +909,16 @@ impl<'a, 'b> Parser<'a, 'b>
                 }
             }
 
-            let low_index_mults = self.is_set(AppSettings::LowIndexMultiplePositional) &&
+            let low_index_mults = self.is_set(AS::LowIndexMultiplePositional) &&
                                   !self.positionals.is_empty() &&
                                   pos_counter == (self.positionals.len() - 1);
-            let missing_pos = self.is_set(AppSettings::AllowMissingPositional) &&
+            let missing_pos = self.is_set(AS::AllowMissingPositional) &&
                               !self.positionals.is_empty() &&
                               pos_counter == (self.positionals.len() - 1);
-            debugln!("Parser::get_matches_with: Low index multiples...{:?}", low_index_mults);
-            debugln!("Parser::get_matches_with: Positional counter...{}", pos_counter);
+            debugln!("Parser::get_matches_with: Low index multiples...{:?}",
+                     low_index_mults);
+            debugln!("Parser::get_matches_with: Positional counter...{}",
+                     pos_counter);
             if low_index_mults || missing_pos {
                 if let Some(na) = it.peek() {
                     let n = (*na).clone().into();
@@ -933,13 +947,13 @@ impl<'a, 'b> Parser<'a, 'b>
             }
             if let Some(p) = self.positionals.get(pos_counter) {
                 parse_positional!(self, p, arg_os, pos_counter, matcher);
-                self.valid_arg = true;
-            } else if self.settings.is_set(AppSettings::AllowExternalSubcommands) {
+                self.settings.set(AS::ValidArgFound);
+            } else if self.is_set(AS::AllowExternalSubcommands) {
                 // Get external subcommand name
                 let sc_name = match arg_os.to_str() {
                     Some(s) => s.to_string(),
                     None => {
-                        if !self.settings.is_set(AppSettings::StrictUtf8) {
+                        if !self.is_set(AS::StrictUtf8) {
                             return Err(Error::invalid_utf8(&*self.create_current_usage(matcher,
                                                                                        None),
                                                            self.color()));
@@ -952,7 +966,7 @@ impl<'a, 'b> Parser<'a, 'b>
                 let mut sc_m = ArgMatcher::new();
                 while let Some(v) = it.next() {
                     let a = v.into();
-                    if a.to_str().is_none() && !self.settings.is_set(AppSettings::StrictUtf8) {
+                    if a.to_str().is_none() && !self.is_set(AS::StrictUtf8) {
                         return Err(Error::invalid_utf8(&*self.create_current_usage(matcher, None),
                                                        self.color()));
                     }
@@ -963,8 +977,8 @@ impl<'a, 'b> Parser<'a, 'b>
                     name: sc_name,
                     matches: sc_m.into(),
                 });
-            } else if !(self.is_set(AppSettings::AllowLeadingHyphen) ||
-                        self.is_set(AppSettings::AllowNegativeNumbers)) {
+            } else if !(self.is_set(AS::AllowLeadingHyphen) ||
+                        self.is_set(AS::AllowNegativeNumbers)) {
                 return Err(Error::unknown_argument(&*arg_os.to_string_lossy(),
                                                    "",
                                                    &*self.create_current_usage(matcher, None),
@@ -994,12 +1008,12 @@ impl<'a, 'b> Parser<'a, 'b>
                     .expect(INTERNAL_ERROR_MSG);
                 try!(self.parse_subcommand(sc_name, matcher, it));
             }
-        } else if self.is_set(AppSettings::SubcommandRequired) {
+        } else if self.is_set(AS::SubcommandRequired) {
             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),
                                                  self.color()));
-        } else if self.is_set(AppSettings::SubcommandRequiredElseHelp) {
+        } 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));
@@ -1040,15 +1054,14 @@ impl<'a, 'b> Parser<'a, 'b>
         }
 
         try!(self.validate_blacklist(matcher));
-        if !(self.settings.is_set(AppSettings::SubcommandsNegateReqs) &&
-             subcmd_name.is_some()) && !reqs_validated {
+        if !(self.is_set(AS::SubcommandsNegateReqs) && subcmd_name.is_some()) && !reqs_validated {
             try!(self.validate_required(matcher));
         }
         try!(self.validate_matched_args(matcher));
         matcher.usage(self.create_usage(&[]));
 
         if matcher.is_empty() && matcher.subcommand_name().is_none() &&
-           self.is_set(AppSettings::ArgRequiredElseHelp) {
+           self.is_set(AS::ArgRequiredElseHelp) {
             let mut out = vec![];
             try!(self.write_help_err(&mut out));
             return Err(Error {
@@ -1075,22 +1088,25 @@ impl<'a, 'b> Parser<'a, 'b>
             if sc.p.meta.bin_name.is_none() {
                 sdebugln!("No");
                 let bin_name = format!("{}{}{}",
-                                      self.meta
-                                          .bin_name
-                                          .as_ref()
-                                          .unwrap_or(&self.meta.name.clone()),
-                                      if self.meta.bin_name.is_some() {
-                                          " "
-                                      } else {
-                                          ""
-                                      },
-                                      &*sc.p.meta.name);
-                debugln!("Parser::build_bin_names:iter: Setting bin_name of {} to {}", self.meta.name, bin_name);
+                                       self.meta
+                                           .bin_name
+                                           .as_ref()
+                                           .unwrap_or(&self.meta.name.clone()),
+                                       if self.meta.bin_name.is_some() {
+                                           " "
+                                       } else {
+                                           ""
+                                       },
+                                       &*sc.p.meta.name);
+                debugln!("Parser::build_bin_names:iter: Setting bin_name of {} to {}",
+                         self.meta.name,
+                         bin_name);
                 sc.p.meta.bin_name = Some(bin_name);
             } else {
                 sdebugln!("yes ({:?})", sc.p.meta.bin_name);
             }
-            debugln!("Parser::build_bin_names:iter: Calling build_bin_names from...{}", sc.p.meta.name);
+            debugln!("Parser::build_bin_names:iter: Calling build_bin_names from...{}",
+                     sc.p.meta.name);
             sc.p.build_bin_names();
         }
     }
@@ -1106,7 +1122,7 @@ impl<'a, 'b> Parser<'a, 'b>
         use std::fmt::Write;
         debugln!("Parser::parse_subcommand;");
         let mut mid_string = String::new();
-        if !self.settings.is_set(AppSettings::SubcommandsNegateReqs) {
+        if !self.is_set(AS::SubcommandsNegateReqs) {
             let mut hs: Vec<&str> = self.required.iter().map(|n| &**n).collect();
             for k in matcher.arg_names() {
                 hs.push(k);
@@ -1143,7 +1159,8 @@ impl<'a, 'b> Parser<'a, 'b>
                                                   ""
                                               },
                                               &*sc.p.meta.name));
-            debugln!("Parser::parse_subcommand: About to parse sc={}", sc.p.meta.name);
+            debugln!("Parser::parse_subcommand: About to parse sc={}",
+                     sc.p.meta.name);
             debugln!("Parser::parse_subcommand: sc settings={:#?}", sc.p.settings);
             try!(sc.p.get_matches_with(&mut sc_matcher, it));
             matcher.subcommand(SubCommand {
@@ -1164,11 +1181,11 @@ impl<'a, 'b> Parser<'a, 'b>
         }
         let mut res = vec![];
         debugln!("Parser::groups_for_arg: Searching through groups...");
-        for (gn, grp) in &self.groups {
+        for grp in &self.groups {
             for a in &grp.args {
                 if a == &name {
-                    sdebugln!("\tFound '{}'", gn);
-                    res.push(*gn);
+                    sdebugln!("\tFound '{}'", grp.name);
+                    res.push(&*grp.name);
                 }
             }
         }
@@ -1183,17 +1200,17 @@ impl<'a, 'b> Parser<'a, 'b>
         let mut g_vec = vec![];
         let mut args = vec![];
 
-        for n in &self.groups[group].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 self.groups.contains_key(&**n) {
-                g_vec.push(*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);
             }
         }
 
@@ -1208,17 +1225,17 @@ impl<'a, 'b> Parser<'a, 'b>
         let mut g_vec = vec![];
         let mut args = vec![];
 
-        for n in &self.groups[group].args {
-            if self.groups.contains_key(&*n) {
+        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);
             } else {
                 args.push(*n);
             }
         }
 
-        for av in g_vec.iter().map(|g| self.arg_names_in_group(g)) {
-            args.extend(av);
-        }
+        // TODO: faster way to sort/dedup?
+        args.sort();
         args.dedup();
         args.iter().map(|s| *s).collect()
     }
@@ -1226,17 +1243,15 @@ impl<'a, 'b> Parser<'a, 'b>
     pub fn create_help_and_version(&mut self) {
         debugln!("Parser::create_help_and_version;");
         // name is "hclap_help" because flags are sorted by name
-        if self.is_set(AppSettings::NeedsLongHelp) {
+        if !self.contains_long("help") {
             debugln!("Parser::create_help_and_version: Building --help");
-            if self.help_short.is_none() && !self.short_list.contains(&'h') {
+            if self.help_short.is_none() && !self.contains_short('h') {
                 self.help_short = Some('h');
             }
-            let id = self.flags.len();
             let arg = FlagBuilder {
                 b: Base {
                     name: "hclap_help",
                     help: Some("Prints help information"),
-                    id: id,
                     ..Default::default()
                 },
                 s: Switched {
@@ -1245,25 +1260,18 @@ impl<'a, 'b> Parser<'a, 'b>
                     ..Default::default()
                 },
             };
-            if let Some(h) = self.help_short {
-                self.short_list.push(h);
-            }
-            self.long_list.push("help");
-            self.flags.insert(id, arg);
+            self.flags.push(arg);
         }
-        if !self.settings.is_set(AppSettings::DisableVersion) &&
-           self.is_set(AppSettings::NeedsLongVersion) {
+        if !self.is_set(AS::DisableVersion) && !self.contains_long("version") {
             debugln!("Parser::create_help_and_version: Building --version");
-            if self.version_short.is_none() && !self.short_list.contains(&'V') {
+            if self.version_short.is_none() && !self.contains_short('V') {
                 self.version_short = Some('V');
             }
-            let id = self.flags.len();
             // name is "vclap_version" because flags are sorted by name
             let arg = FlagBuilder {
                 b: Base {
                     name: "vclap_version",
                     help: Some("Prints version information"),
-                    id: id,
                     ..Default::default()
                 },
                 s: Switched {
@@ -1272,14 +1280,10 @@ impl<'a, 'b> Parser<'a, 'b>
                     ..Default::default()
                 },
             };
-            if let Some(v) = self.version_short {
-                self.short_list.push(v);
-            }
-            self.long_list.push("version");
-            self.flags.insert(id, arg);
+            self.flags.push(arg);
         }
-        if !self.subcommands.is_empty() && !self.is_set(AppSettings::DisableHelpSubcommand) &&
-           self.is_set(AppSettings::NeedsSubcommandHelp) {
+        if !self.subcommands.is_empty() && !self.is_set(AS::DisableHelpSubcommand) &&
+           self.is_set(AS::NeedsSubcommandHelp) {
             debugln!("Parser::create_help_and_version: Building help");
             self.subcommands
                 .push(App::new("help")
@@ -1313,11 +1317,11 @@ impl<'a, 'b> Parser<'a, 'b>
         debugln!("Parser::check_for_help_and_version_str;");
         debug!("Parser::check_for_help_and_version_str: Checking if --{} is help or version...",
                arg.to_str().unwrap());
-        if arg == "help" && self.settings.is_set(AppSettings::NeedsLongHelp) {
+        if arg == "help" && self.is_set(AS::NeedsLongHelp) {
             sdebugln!("Help");
             try!(self._help());
         }
-        if arg == "version" && self.settings.is_set(AppSettings::NeedsLongVersion) {
+        if arg == "version" && self.is_set(AS::NeedsLongVersion) {
             sdebugln!("Version");
             try!(self._version());
         }
@@ -1328,15 +1332,16 @@ impl<'a, 'b> Parser<'a, 'b>
 
     fn check_for_help_and_version_char(&self, arg: char) -> ClapResult<()> {
         debugln!("Parser::check_for_help_and_version_char;");
-        debug!("Parser::check_for_help_and_version_char: Checking if -{} is help or version...", arg);
+        debug!("Parser::check_for_help_and_version_char: Checking if -{} is help or version...",
+               arg);
         if let Some(h) = self.help_short {
-            if arg == h && self.settings.is_set(AppSettings::NeedsLongHelp) {
+            if arg == h && self.is_set(AS::NeedsLongHelp) {
                 sdebugln!("Help");
                 try!(self._help());
             }
         }
         if let Some(v) = self.version_short {
-            if arg == v && self.settings.is_set(AppSettings::NeedsLongVersion) {
+            if arg == v && self.is_set(AS::NeedsLongVersion) {
                 sdebugln!("Version");
                 try!(self._version());
             }
@@ -1384,16 +1389,18 @@ impl<'a, 'b> Parser<'a, 'b>
             full_arg.trim_left_matches(b'-')
         };
 
-        if let Some(opt) = find_by_long!(self, &arg, opts) {
-            debugln!("Parser::parse_long_arg: Found valid opt '{}'", opt.to_string());
-            self.valid_arg = true;
+        if let Some(opt) = find_opt_by_long!(@os self, &arg) {
+            debugln!("Parser::parse_long_arg: Found valid opt '{}'",
+                     opt.to_string());
+            self.settings.set(AS::ValidArgFound);
             let ret = try!(self.parse_opt(val, opt, val.is_some(), matcher));
             arg_post_processing!(self, opt, matcher);
 
             return Ok(ret);
-        } else if let Some(flag) = find_by_long!(self, &arg, flags) {
-            debugln!("Parser::parse_long_arg: Found valid flag '{}'", flag.to_string());
-            self.valid_arg = true;
+        } else if let Some(flag) = find_flag_by_long!(@os self, &arg) {
+            debugln!("Parser::parse_long_arg: Found valid flag '{}'",
+                     flag.to_string());
+            self.settings.set(AS::ValidArgFound);
             // Only flags could be help or version, and we need to check the raw long
             // so this is the first point to check
             try!(self.check_for_help_and_version_str(arg));
@@ -1404,9 +1411,9 @@ impl<'a, 'b> Parser<'a, 'b>
             arg_post_processing!(self, flag, matcher);
 
             return Ok(None);
-        } else if self.is_set(AppSettings::AllowLeadingHyphen) {
+        } else if self.is_set(AS::AllowLeadingHyphen) {
             return Ok(None);
-        } else if self.valid_neg_num {
+        } else if self.is_set(AS::ValidNegNumFound) {
             return Ok(None);
         }
 
@@ -1419,21 +1426,18 @@ impl<'a, 'b> Parser<'a, 'b>
                        full_arg: &OsStr)
                        -> ClapResult<Option<&'a str>> {
         debugln!("Parser::parse_short_arg;");
-        // let mut utf8 = true;
         let arg_os = full_arg.trim_left_matches(b'-');
         let arg = arg_os.to_string_lossy();
 
-        // If AllowLeadingHyphen is set, we want to ensure `-val` gets parsed as `-val` and not `-v` `-a` `-l` assuming
-        // `v` `a` and `l` are all, or mostly, valid shorts.
-        if self.is_set(AppSettings::AllowLeadingHyphen) {
-            let mut good = true;
-            for c in arg.chars() {
-                good = self.short_list.contains(&c);
-            }
-            if !good {
+        // If AllowLeadingHyphen is set, we want to ensure `-val` gets parsed as `-val` and not
+        // `-v` `-a` `-l` assuming `v` `a` and `l` are all, or mostly, valid shorts.
+        if self.is_set(AS::AllowLeadingHyphen) {
+            if arg.chars().any(|c| !self.contains_short(c)) {
+                debugln!("Parser::parse_short_arg: Leading Hyphen Allowed and -{} isn't a valid short",
+                         arg);
                 return Ok(None);
             }
-        } else if self.valid_neg_num {
+        } else if self.is_set(AS::ValidNegNumFound) {
             // TODO: Add docs about having AllowNegativeNumbers and `-2` as a valid short
             // May be better to move this to *after* not finding a valid flag/opt?
             debugln!("Parser::parse_short_arg: Valid negative num...");
@@ -1446,18 +1450,20 @@ impl<'a, 'b> Parser<'a, 'b>
             // concatenated value: -oval
             // Option: -o
             // Value: val
-            if let Some(opt) = self.opts
-                .iter()
-                .find(|&o| o.s.short.is_some() && o.s.short.unwrap() == c) {
-                debugln!("Parser::parse_short_arg:iter: Found valid short opt -{} in '{}'", c, arg);
-                self.valid_arg = true;
+            if let Some(opt) = find_opt_by_short!(self, c) {
+                debugln!("Parser::parse_short_arg:iter: Found valid short opt -{} in '{}'",
+                         c,
+                         arg);
+                self.settings.set(AS::ValidArgFound);
                 // Check for trailing concatenated value
                 let p: Vec<_> = arg.splitn(2, c).collect();
                 debugln!("Parser::parse_short_arg:iter: arg: {:?}, arg_os: {:?}, full_arg: {:?}",
                          arg,
                          arg_os,
                          full_arg);
-                debugln!("Parser::parse_short_arg:iter: p[0]: {:?}, p[1]: {:?}", p[0].as_bytes(), p[1].as_bytes());
+                debugln!("Parser::parse_short_arg:iter: p[0]: {:?}, p[1]: {:?}",
+                         p[0].as_bytes(),
+                         p[1].as_bytes());
                 let i = p[0].as_bytes().len() + 1;
                 let val = if p[1].as_bytes().len() > 0 {
                     debugln!("Parser::parse_short_arg:iter: setting val: {:?} (bytes), {:?} (ascii)",
@@ -1474,11 +1480,10 @@ impl<'a, 'b> Parser<'a, 'b>
                 arg_post_processing!(self, opt, matcher);
 
                 return Ok(ret);
-            } else if let Some(flag) = self.flags
-                .iter()
-                .find(|&f| f.s.short.is_some() && f.s.short.unwrap() == c) {
-                debugln!("Parser::parse_short_arg:iter: Found valid short flag -{}", c);
-                self.valid_arg = true;
+            } else if let Some(flag) = find_flag_by_short!(self, c) {
+                debugln!("Parser::parse_short_arg:iter: Found valid short flag -{}",
+                         c);
+                self.settings.set(AS::ValidArgFound);
                 // Only flags can be help or version
                 try!(self.check_for_help_and_version_char(c));
                 try!(self.parse_flag(flag, matcher));
@@ -1486,9 +1491,7 @@ impl<'a, 'b> Parser<'a, 'b>
                 // Must be called here due to mutablilty
                 arg_post_processing!(self, flag, matcher);
             } else {
-                let mut arg = String::new();
-                arg.push('-');
-                arg.push(c);
+                let arg = format!("-{}", c);
                 return Err(Error::unknown_argument(&*arg,
                                                    "",
                                                    &*self.create_current_usage(matcher, None),
@@ -1506,7 +1509,6 @@ impl<'a, 'b> Parser<'a, 'b>
                  -> ClapResult<Option<&'a str>> {
         debugln!("Parser::parse_opt; opt={}, val={:?}", opt.b.name, val);
         debugln!("Parser::parse_opt; opt.settings={:?}", opt.b.settings);
-        validate_multiples!(self, opt, matcher);
         let mut has_eq = false;
 
         debug!("Parser::parse_opt; Checking for val...");
@@ -1521,7 +1523,9 @@ impl<'a, 'b> Parser<'a, 'b>
                                               self.color()));
             }
             sdebugln!("Found - {:?}, len: {}", v, v.len_());
-            debugln!("Parser::parse_opt: {:?} contains '='...{:?}", fv, fv.starts_with(&[b'=']));
+            debugln!("Parser::parse_opt: {:?} contains '='...{:?}",
+                     fv,
+                     fv.starts_with(&[b'=']));
             try!(self.add_val_to_arg(opt, v, matcher));
         } else if opt.is_set(ArgSettings::RequireEquals) && !opt.is_set(ArgSettings::EmptyValues) {
             sdebugln!("None, but requires equals...Error");
@@ -1558,8 +1562,9 @@ impl<'a, 'b> Parser<'a, 'b>
         debugln!("Parser::add_val_to_arg; arg={}, val={:?}", arg.name(), val);
         let mut ret = None;
         debugln!("Parser::add_val_to_arg; trailing_vals={:?}, DontDelimTrailingVals={:?}",
-            self.trailing_vals, self.is_set(AppSettings::DontDelimitTrailingValues));
-        if !(self.trailing_vals && self.is_set(AppSettings::DontDelimitTrailingValues)) {
+                 self.is_set(AS::TrailingValues),
+                 self.is_set(AS::DontDelimitTrailingValues));
+        if !(self.is_set(AS::TrailingValues) && self.is_set(AS::DontDelimitTrailingValues)) {
             if let Some(delim) = arg.val_delim() {
                 if val.is_empty_() {
                     ret = try!(self.add_single_val_to_arg(arg, val, matcher));
@@ -1605,55 +1610,67 @@ impl<'a, 'b> Parser<'a, 'b>
             }
         }
 
-        // The validation must come AFTER inserting into 'matcher' or the usage string
-        // can't be built
-        self.validate_value(arg, v, matcher)
+        if matcher.needs_more_vals(arg) {
+            return Ok(Some(arg.name()));
+        }
+        Ok(None)
     }
 
-    fn validate_value<A>(&self,
-                         arg: &A,
-                         val: &OsStr,
-                         matcher: &ArgMatcher<'a>)
-                         -> ClapResult<Option<&'a str>>
+    fn validate_values<A>(&self,
+                          arg: &A,
+                          ma: &MatchedArg,
+                          matcher: &ArgMatcher<'a>)
+                          -> ClapResult<()>
         where A: AnyArg<'a, 'b> + Display
     {
-        debugln!("Parser::validate_value: val={:?}", val);
-        if self.is_set(AppSettings::StrictUtf8) && val.to_str().is_none() {
-            return Err(Error::invalid_utf8(&*self.create_current_usage(matcher, None),
-                                           self.color()));
-        }
-        if let Some(p_vals) = arg.possible_vals() {
-            let val_str = val.to_string_lossy();
-            if !p_vals.contains(&&*val_str) {
-                return Err(Error::invalid_value(val_str,
-                                                p_vals,
-                                                arg,
-                                                &*self.create_current_usage(matcher, None),
-                                                self.color()));
-            }
-        }
-        if !arg.is_set(ArgSettings::EmptyValues) && val.is_empty_() &&
-           matcher.contains(&*arg.name()) {
-            return Err(Error::empty_value(arg,
-                                          &*self.create_current_usage(matcher, None),
-                                          self.color()));
-        }
-        if let Some(vtor) = arg.validator() {
-            if let Err(e) = vtor(val.to_string_lossy().into_owned()) {
-                return Err(Error::value_validation(Some(arg), e, self.color()));
+        debugln!("Parser::validate_values: arg={:?}", arg.name());
+        for (_, val) in &ma.vals {
+            if self.is_set(AS::StrictUtf8) && val.to_str().is_none() {
+                debugln!("Parser::validate_values: invalid UTF-8 found in val {:?}",
+                         val);
+                return Err(Error::invalid_utf8(&*self.create_current_usage(matcher, None),
+                                               self.color()));
+            }
+            if let Some(p_vals) = arg.possible_vals() {
+                debugln!("Parser::validate_values: possible_vals={:?}", p_vals);
+                let val_str = val.to_string_lossy();
+                if !p_vals.contains(&&*val_str) {
+                    return Err(Error::invalid_value(val_str,
+                                                    p_vals,
+                                                    arg,
+                                                    &*self.create_current_usage(matcher, None),
+                                                    self.color()));
+                }
             }
-        }
-        if let Some(vtor) = arg.validator_os() {
-            if let Err(e) = vtor(val) {
-                return Err(Error::value_validation(Some(arg),
-                                                   (*e).to_string_lossy().to_string(),
-                                                   self.color()));
+            if !arg.is_set(ArgSettings::EmptyValues) && val.is_empty_() &&
+               matcher.contains(&*arg.name()) {
+                debugln!("Parser::validate_values: illegal empty val found");
+                return Err(Error::empty_value(arg,
+                                              &*self.create_current_usage(matcher, None),
+                                              self.color()));
+            }
+            if let Some(vtor) = arg.validator() {
+                debug!("Parser::validate_values: checking validator...");
+                if let Err(e) = vtor(val.to_string_lossy().into_owned()) {
+                    sdebugln!("error");
+                    return Err(Error::value_validation(Some(arg), e, self.color()));
+                } else {
+                    sdebugln!("good");
+                }
+            }
+            if let Some(vtor) = arg.validator_os() {
+                debug!("Parser::validate_values: checking validator_os...");
+                if let Err(e) = vtor(&val) {
+                    sdebugln!("error");
+                    return Err(Error::value_validation(Some(arg),
+                                                       (*e).to_string_lossy().to_string(),
+                                                       self.color()));
+                } else {
+                    sdebugln!("good");
+                }
             }
         }
-        if matcher.needs_more_vals(arg) {
-            return Ok(Some(arg.name()));
-        }
-        Ok(None)
+        Ok(())
     }
 
     fn parse_flag(&self,
@@ -1661,7 +1678,6 @@ impl<'a, 'b> Parser<'a, 'b>
                   matcher: &mut ArgMatcher<'a>)
                   -> ClapResult<()> {
         debugln!("Parser::parse_flag;");
-        validate_multiples!(self, flag, matcher);
 
         matcher.inc_occurrence_of(flag.b.name);
         // Increment or create the group "args"
@@ -1704,11 +1720,13 @@ impl<'a, 'b> Parser<'a, 'b>
         }
 
         for name in &self.blacklist {
-            debugln!("Parser::validate_blacklist:iter: Checking blacklisted name: {}", name);
-            if self.groups.contains_key(name) {
+            debugln!("Parser::validate_blacklist:iter: Checking blacklisted name: {}",
+                     name);
+            if self.groups.iter().any(|g| &g.name == name) {
                 debugln!("Parser::validate_blacklist:iter: groups contains it...");
                 for n in self.arg_names_in_group(name) {
-                    debugln!("Parser::validate_blacklist:iter:iter: Checking arg '{}' in group...", n);
+                    debugln!("Parser::validate_blacklist:iter:iter: Checking arg '{}' in group...",
+                             n);
                     if matcher.contains(n) {
                         debugln!("Parser::validate_blacklist:iter:iter: matcher contains it...");
                         return Err(build_err!(self, &n, matcher));
@@ -1725,17 +1743,24 @@ impl<'a, 'b> Parser<'a, 'b>
     fn validate_matched_args(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
         debugln!("Parser::validate_matched_args;");
         for (name, ma) in matcher.iter() {
-            debugln!("Parser::validate_matched_args:iter: name={}", name);
+            debugln!("Parser::validate_matched_args:iter:{}: vals={:#?}",
+                     name,
+                     ma.vals);
             if let Some(opt) = find_by_name!(self, name, opts, iter) {
                 try!(self.validate_arg_num_vals(opt, ma, matcher));
+                try!(self.validate_values(opt, ma, matcher));
                 try!(self.validate_arg_requires(opt, ma, matcher));
+                try!(self.validate_arg_num_occurs(opt, ma, matcher));
             } else if let Some(flag) = find_by_name!(self, name, flags, iter) {
-                // Only requires
                 try!(self.validate_arg_requires(flag, ma, matcher));
+                try!(self.validate_arg_num_occurs(flag, ma, matcher));
             } else if let Some(pos) = find_by_name!(self, name, positionals, values) {
                 try!(self.validate_arg_num_vals(pos, ma, matcher));
+                try!(self.validate_arg_num_occurs(pos, ma, matcher));
+                try!(self.validate_values(pos, ma, matcher));
                 try!(self.validate_arg_requires(pos, ma, matcher));
-            } else if let Some(grp) = self.groups.get(name) {
+            } else {
+                let grp = self.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);
@@ -1746,6 +1771,23 @@ impl<'a, 'b> Parser<'a, 'b>
         Ok(())
     }
 
+    fn validate_arg_num_occurs<A>(&self,
+                                  a: &A,
+                                  ma: &MatchedArg,
+                                  matcher: &ArgMatcher)
+                                  -> ClapResult<()>
+        where A: AnyArg<'a, 'b> + Display
+    {
+        debugln!("Parser::validate_arg_num_occurs: a={};", a.name());
+        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.create_current_usage(matcher, None),
+                                                        self.color()));
+        }
+        Ok(())
+    }
+
     fn validate_arg_num_vals<A>(&self,
                                 a: &A,
                                 ma: &MatchedArg,
@@ -1867,20 +1909,10 @@ impl<'a, 'b> Parser<'a, 'b>
     fn validate_required(&self, matcher: &ArgMatcher) -> ClapResult<()> {
         debugln!("Parser::validate_required: required={:?};", self.required);
         'outer: for name in &self.required {
-            debugln!("Parser::validate_required:iter: name={}", name);
+            debugln!("Parser::validate_required:iter:{}:", name);
             if matcher.contains(name) {
                 continue 'outer;
             }
-            if let Some(grp) = self.groups.get(name) {
-                for arg in &grp.args {
-                    if matcher.contains(arg) {
-                        continue 'outer;
-                    }
-                }
-            }
-            if self.groups.values().any(|g| g.args.contains(name)) {
-                continue 'outer;
-            }
             if let Some(a) = find_by_name!(self, name, flags, iter) {
                 if self.is_missing_required_ok(a, matcher) {
                     continue 'outer;
@@ -1910,61 +1942,70 @@ impl<'a, 'b> Parser<'a, 'b>
         Ok(())
     }
 
-    fn is_missing_required_ok<A>(&self, a: &A, matcher: &ArgMatcher) -> bool
+    fn check_conflicts<A>(&self, a: &A, matcher: &ArgMatcher) -> Option<bool>
         where A: AnyArg<'a, 'b>
     {
-        debugln!("Parser::is_missing_required_ok: a={}", a.name());
-        if let Some(bl) = a.blacklist() {
-            debugln!("Parser::is_missing_required_ok: Conflicts found...{:?}", bl);
-            for n in bl.iter() {
-                debugln!("Parser::is_missing_required_ok:iter: conflict={}", n);
-                if matcher.contains(n) ||
-                   self.groups
-                    .get(n)
-                    .map_or(false, |g| g.args.iter().any(|an| matcher.contains(an))) {
-                    return true;
-                }
-            }
+        debugln!("Parser::check_conflicts: a={:?};", a.name());
+        a.blacklist().map(|bl| {
+            bl.iter().any(|conf| {
+                matcher.contains(conf) ||
+                self.groups
+                    .iter()
+                    .find(|g| &g.name == conf)
+                    .map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg)))
+            })
+        })
+    }
+
+    fn check_required_unless<A>(&self, a: &A, matcher: &ArgMatcher) -> Option<bool>
+        where A: AnyArg<'a, 'b>
+    {
+        debugln!("Parser::check_required_unless: a={:?};", a.name());
+        macro_rules! check {
+            ($how:ident, $_self:ident, $a:ident, $m:ident) => {{
+                $a.required_unless().map(|ru| {
+                    ru.iter().$how(|n| {
+                        $m.contains(n) || {
+                            if let Some(grp) = $_self.groups.iter().find(|g| &g.name == n) {
+                                     grp.args.iter().any(|arg| $m.contains(arg))
+                            } else {
+                                false
+                            }
+                        }
+                    })
+                })
+            }}; 
         }
-        if let Some(ru) = a.required_unless() {
-            debugln!("Parser::is_missing_required_ok: Required unless found...{:?}", ru);
-            let mut found_any = false;
-            for n in ru.iter() {
-                debugln!("Parser::is_missing_required_ok:iter: ru={}", n);
-                if matcher.contains(n) ||
-                   self.groups
-                    .get(n)
-                    .map_or(false, |g| g.args.iter().any(|an| matcher.contains(an))) {
-                    if !a.is_set(ArgSettings::RequiredUnlessAll) {
-                        debugln!("Parser::is_missing_required_ok:iter: Doesn't require all...returning true");
-                        return true;
-                    }
-                    debugln!("Parser::is_missing_required_ok:iter: Requires all...next");
-                    found_any = true;
-                } else if a.is_set(ArgSettings::RequiredUnlessAll) {
-                    debugln!("Parser::is_missing_required_ok:iter: Not in matcher, or group and requires all...returning false");
-                    return false;
-                }
-            }
-            return found_any;
+        if a.is_set(ArgSettings::RequiredUnlessAll) {
+            check!(all, self, a, matcher)
+        } else {
+            check!(any, self, a, matcher)
         }
-        false
+    }
+
+    #[inline]
+    fn is_missing_required_ok<A>(&self, a: &A, matcher: &ArgMatcher) -> bool
+        where A: AnyArg<'a, 'b>
+    {
+        debugln!("Parser::is_missing_required_ok: a={}", a.name());
+        self.check_conflicts(a, matcher).unwrap_or(false) ||
+        self.check_required_unless(a, matcher).unwrap_or(false)
     }
 
     fn did_you_mean_error(&self, arg: &str, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
         // Didn't match a flag or option...maybe it was a typo and close to one
         let suffix =
             suggestions::did_you_mean_suffix(arg,
-                                             self.long_list.iter(),
+                                             longs!(self),
                                              suggestions::DidYouMeanMessageStyle::LongFlag);
 
         // Add the arg to the matches to build a proper usage string
         if let Some(name) = suffix.1 {
-            if let Some(opt) = find_by_long!(self, &name, opts) {
+            if let Some(opt) = find_opt_by_long!(self, &name) {
                 self.groups_for_arg(&*opt.b.name)
                     .and_then(|grps| Some(matcher.inc_occurrences_of(&*grps)));
                 matcher.insert(&*opt.b.name);
-            } else if let Some(flg) = find_by_long!(self, &name, flags) {
+            } else if let Some(flg) = find_flag_by_long!(self, &name) {
                 self.groups_for_arg(&*flg.b.name)
                     .and_then(|grps| Some(matcher.inc_occurrences_of(&*grps)));
                 matcher.insert(&*flg.b.name);
@@ -2015,12 +2056,12 @@ impl<'a, 'b> Parser<'a, 'b>
                 .fold(String::new(), |a, s| a + &format!(" {}", s)[..]);
 
             let flags = self.needs_flags_tag();
-            if flags && !self.is_set(AppSettings::UnifiedHelpMessage) {
+            if flags && !self.is_set(AS::UnifiedHelpMessage) {
                 usage.push_str(" [FLAGS]");
             } else if flags {
                 usage.push_str(" [OPTIONS]");
             }
-            if !self.is_set(AppSettings::UnifiedHelpMessage) && self.has_opts() &&
+            if !self.is_set(AS::UnifiedHelpMessage) && self.has_opts() &&
                self.opts.iter().any(|o| !o.b.settings.is_set(ArgSettings::Required)) {
                 usage.push_str(" [OPTIONS]");
             }
@@ -2045,9 +2086,9 @@ impl<'a, 'b> Parser<'a, 'b>
             }
 
 
-            if self.has_subcommands() && !self.is_set(AppSettings::SubcommandRequired) {
+            if self.has_subcommands() && !self.is_set(AS::SubcommandRequired) {
                 usage.push_str(" [SUBCOMMAND]");
-            } else if self.is_set(AppSettings::SubcommandRequired) && self.has_subcommands() {
+            } else if self.is_set(AS::SubcommandRequired) && self.has_subcommands() {
                 usage.push_str(" <SUBCOMMAND>");
             }
         } else {
@@ -2081,7 +2122,7 @@ impl<'a, 'b> Parser<'a, 'b>
             })
                             [..]);
         usage.push_str(&*r_string);
-        if self.is_set(AppSettings::SubcommandRequired) {
+        if self.is_set(AS::SubcommandRequired) {
             usage.push_str(" <SUBCOMMAND>");
         }
     }
@@ -2097,20 +2138,20 @@ impl<'a, 'b> Parser<'a, 'b>
             if bn.contains(' ') {
                 // Incase we're dealing with subcommands i.e. git mv is translated to git-mv
                 write!(w,
-                         "{} {}",
-                         bn.replace(" ", "-"),
-                         self.meta.version.unwrap_or("".into()))
+                       "{} {}",
+                       bn.replace(" ", "-"),
+                       self.meta.version.unwrap_or("".into()))
             } else {
                 write!(w,
-                         "{} {}",
-                         &self.meta.name[..],
-                         self.meta.version.unwrap_or("".into()))
+                       "{} {}",
+                       &self.meta.name[..],
+                       self.meta.version.unwrap_or("".into()))
             }
         } else {
             write!(w,
-                     "{} {}",
-                     &self.meta.name[..],
-                     self.meta.version.unwrap_or("".into()))
+                   "{} {}",
+                   &self.meta.name[..],
+                   self.meta.version.unwrap_or("".into()))
         }
     }
 
@@ -2191,10 +2232,10 @@ impl<'a, 'b> Parser<'a, 'b>
     pub fn color(&self) -> ColorWhen {
         debugln!("Parser::color;");
         debug!("Parser::color: Color setting...");
-        if self.is_set(AppSettings::ColorNever) {
+        if self.is_set(AS::ColorNever) {
             sdebugln!("Never");
             ColorWhen::Never
-        } else if self.is_set(AppSettings::ColorAlways) {
+        } else if self.is_set(AS::ColorAlways) {
             sdebugln!("Always");
             ColorWhen::Always
         } else {
@@ -2219,7 +2260,8 @@ impl<'a, 'b> Parser<'a, 'b>
     #[cfg_attr(feature = "lints", allow(explicit_iter_loop))]
     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());
+        debugln!("Parser::find_subcommand: Currently in Parser...{}",
+                 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() &&
@@ -2238,35 +2280,10 @@ impl<'a, 'b> Parser<'a, 'b>
         }
         None
     }
-}
 
-impl<'a, 'b> Clone for Parser<'a, 'b>
-    where 'a: 'b
-{
-    fn clone(&self) -> Self {
-        Parser {
-            propogated: self.propogated,
-            required: self.required.clone(),
-            short_list: self.short_list.clone(),
-            long_list: self.long_list.clone(),
-            blacklist: self.blacklist.clone(),
-            flags: self.flags.clone(),
-            opts: self.opts.clone(),
-            positionals: self.positionals.clone(),
-            subcommands: self.subcommands.clone(),
-            groups: self.groups.clone(),
-            global_args: self.global_args.clone(),
-            overrides: self.overrides.clone(),
-            help_short: self.help_short,
-            version_short: self.version_short,
-            settings: self.settings,
-            g_settings: self.g_settings,
-            meta: self.meta.clone(),
-            trailing_vals: self.trailing_vals,
-            id: self.id,
-            valid_neg_num: self.valid_neg_num,
-            r_ifs: self.r_ifs.clone(),
-            valid_arg: self.valid_arg,
-        }
-    }
+    #[inline]
+    fn contains_long(&self, l: &str) -> bool { longs!(self).any(|al| al == &l) }
+
+    #[inline]
+    fn contains_short(&self, s: char) -> bool { shorts!(self).any(|arg_s| arg_s == &s) }
 }
diff --git a/src/app/settings.rs b/src/app/settings.rs
index ae71a0c1..42edc610 100644
--- a/src/app/settings.rs
+++ b/src/app/settings.rs
@@ -5,40 +5,44 @@ use std::ops::BitOr;
 
 bitflags! {
     flags Flags: u64 {
-        const SC_NEGATE_REQS       = 0b0000000000000000000000000000000001,
-        const SC_REQUIRED          = 0b0000000000000000000000000000000010,
-        const A_REQUIRED_ELSE_HELP = 0b0000000000000000000000000000000100,
-        const GLOBAL_VERSION       = 0b0000000000000000000000000000001000,
-        const VERSIONLESS_SC       = 0b0000000000000000000000000000010000,
-        const UNIFIED_HELP         = 0b0000000000000000000000000000100000,
-        const WAIT_ON_ERROR        = 0b0000000000000000000000000001000000,
-        const SC_REQUIRED_ELSE_HELP= 0b0000000000000000000000000010000000,
-        const NEEDS_LONG_HELP      = 0b0000000000000000000000000100000000,
-        const NEEDS_LONG_VERSION   = 0b0000000000000000000000001000000000,
-        const NEEDS_SC_HELP        = 0b0000000000000000000000010000000000,
-        const DISABLE_VERSION      = 0b0000000000000000000000100000000000,
-        const HIDDEN               = 0b0000000000000000000001000000000000,
-        const TRAILING_VARARG      = 0b0000000000000000000010000000000000,
-        const NO_BIN_NAME          = 0b0000000000000000000100000000000000,
-        const ALLOW_UNK_SC         = 0b0000000000000000001000000000000000,
-        const UTF8_STRICT          = 0b0000000000000000010000000000000000,
-        const UTF8_NONE            = 0b0000000000000000100000000000000000,
-        const LEADING_HYPHEN       = 0b0000000000000001000000000000000000,
-        const NO_POS_VALUES        = 0b0000000000000010000000000000000000,
-        const NEXT_LINE_HELP       = 0b0000000000000100000000000000000000,
-        const DERIVE_DISP_ORDER    = 0b0000000000001000000000000000000000,
-        const COLORED_HELP         = 0b0000000000010000000000000000000000,
-        const COLOR_ALWAYS         = 0b0000000000100000000000000000000000,
-        const COLOR_AUTO           = 0b0000000001000000000000000000000000,
-        const COLOR_NEVER          = 0b0000000010000000000000000000000000,
-        const DONT_DELIM_TRAIL     = 0b0000000100000000000000000000000000,
-        const ALLOW_NEG_NUMS       = 0b0000001000000000000000000000000000,
-        const LOW_INDEX_MUL_POS    = 0b0000010000000000000000000000000000,
-        const DISABLE_HELP_SC      = 0b0000100000000000000000000000000000,
-        const DONT_COLLAPSE_ARGS   = 0b0001000000000000000000000000000000,
-        const ARGS_NEGATE_SCS      = 0b0010000000000000000000000000000000,
-        const PROPAGATE_VALS_DOWN  = 0b0100000000000000000000000000000000,
-        const ALLOW_MISSING_POS    = 0b1000000000000000000000000000000000,
+        const SC_NEGATE_REQS       = 0b00000000000000000000000000000000000001,
+        const SC_REQUIRED          = 0b00000000000000000000000000000000000010,
+        const A_REQUIRED_ELSE_HELP = 0b00000000000000000000000000000000000100,
+        const GLOBAL_VERSION       = 0b00000000000000000000000000000000001000,
+        const VERSIONLESS_SC       = 0b00000000000000000000000000000000010000,
+        const UNIFIED_HELP         = 0b00000000000000000000000000000000100000,
+        const WAIT_ON_ERROR        = 0b00000000000000000000000000000001000000,
+        const SC_REQUIRED_ELSE_HELP= 0b00000000000000000000000000000010000000,
+        const NEEDS_LONG_HELP      = 0b00000000000000000000000000000100000000,
+        const NEEDS_LONG_VERSION   = 0b00000000000000000000000000001000000000,
+        const NEEDS_SC_HELP        = 0b00000000000000000000000000010000000000,
+        const DISABLE_VERSION      = 0b00000000000000000000000000100000000000,
+        const HIDDEN               = 0b00000000000000000000000001000000000000,
+        const TRAILING_VARARG      = 0b00000000000000000000000010000000000000,
+        const NO_BIN_NAME          = 0b00000000000000000000000100000000000000,
+        const ALLOW_UNK_SC         = 0b00000000000000000000001000000000000000,
+        const UTF8_STRICT          = 0b00000000000000000000010000000000000000,
+        const UTF8_NONE            = 0b00000000000000000000100000000000000000,
+        const LEADING_HYPHEN       = 0b00000000000000000001000000000000000000,
+        const NO_POS_VALUES        = 0b00000000000000000010000000000000000000,
+        const NEXT_LINE_HELP       = 0b00000000000000000100000000000000000000,
+        const DERIVE_DISP_ORDER    = 0b00000000000000001000000000000000000000,
+        const COLORED_HELP         = 0b00000000000000010000000000000000000000,
+        const COLOR_ALWAYS         = 0b00000000000000100000000000000000000000,
+        const COLOR_AUTO           = 0b00000000000001000000000000000000000000,
+        const COLOR_NEVER          = 0b00000000000010000000000000000000000000,
+        const DONT_DELIM_TRAIL     = 0b00000000000100000000000000000000000000,
+        const ALLOW_NEG_NUMS       = 0b00000000001000000000000000000000000000,
+        const LOW_INDEX_MUL_POS    = 0b00000000010000000000000000000000000000,
+        const DISABLE_HELP_SC      = 0b00000000100000000000000000000000000000,
+        const DONT_COLLAPSE_ARGS   = 0b00000001000000000000000000000000000000,
+        const ARGS_NEGATE_SCS      = 0b00000010000000000000000000000000000000,
+        const PROPAGATE_VALS_DOWN  = 0b00000100000000000000000000000000000000,
+        const ALLOW_MISSING_POS    = 0b00001000000000000000000000000000000000,
+        const TRAILING_VALUES      = 0b00010000000000000000000000000000000000,
+        const VALID_NEG_NUM_FOUND  = 0b00100000000000000000000000000000000000,
+        const PROPOGATED           = 0b01000000000000000000000000000000000000,
+        const VALID_ARG_FOUND      = 0b10000000000000000000000000000000000000
     }
 }
 
@@ -94,7 +98,11 @@ impl AppFlags {
         UnifiedHelpMessage => UNIFIED_HELP,
         NextLineHelp => NEXT_LINE_HELP,
         VersionlessSubcommands => VERSIONLESS_SC,
-        WaitOnError => WAIT_ON_ERROR
+        WaitOnError => WAIT_ON_ERROR,
+        TrailingValues => TRAILING_VALUES,
+        ValidNegNumFound => VALID_NEG_NUM_FOUND,
+        Propogated => PROPOGATED,
+        ValidArgFound => VALID_ARG_FOUND
     }
 }
 
@@ -807,6 +815,18 @@ pub enum AppSettings {
 
     #[doc(hidden)]
     LowIndexMultiplePositional,
+
+    #[doc(hidden)]
+    TrailingValues,
+
+    #[doc(hidden)]
+    ValidNegNumFound,
+
+    #[doc(hidden)]
+    Propogated,
+
+    #[doc(hidden)]
+    ValidArgFound,
 }
 
 impl FromStr for AppSettings {
@@ -842,6 +862,10 @@ impl FromStr for AppSettings {
             "unifiedhelpmessage" => Ok(AppSettings::UnifiedHelpMessage),
             "versionlesssubcommands" => Ok(AppSettings::VersionlessSubcommands),
             "waitonerror" => Ok(AppSettings::WaitOnError),
+            "validnegnumfound" => Ok(AppSettings::ValidNegNumFound),
+            "validargfound" => Ok(AppSettings::ValidArgFound),
+            "propogated" => Ok(AppSettings::Propogated),
+            "trailingvalues" => Ok(AppSettings::TrailingValues),
             _ => Err("unknown AppSetting, cannot convert from str".to_owned()),
         }
     }
@@ -911,6 +935,14 @@ mod test {
                    AppSettings::VersionlessSubcommands);
         assert_eq!("waitonerror".parse::<AppSettings>().unwrap(),
                    AppSettings::WaitOnError);
+        assert_eq!("validnegnumfound".parse::<AppSettings>().unwrap(),
+                   AppSettings::ValidNegNumFound);
+        assert_eq!("validargfound".parse::<AppSettings>().unwrap(),
+                   AppSettings::ValidArgFound);
+        assert_eq!("propogated".parse::<AppSettings>().unwrap(),
+                   AppSettings::Propogated);
+        assert_eq!("trailingvalues".parse::<AppSettings>().unwrap(),
+                   AppSettings::TrailingValues);
         assert!("hahahaha".parse::<AppSettings>().is_err());
     }
 }
diff --git a/src/args/any_arg.rs b/src/args/any_arg.rs
index 6b20cca6..55245dba 100644
--- a/src/args/any_arg.rs
+++ b/src/args/any_arg.rs
@@ -12,7 +12,6 @@ use args::settings::ArgSettings;
 #[doc(hidden)]
 pub trait AnyArg<'n, 'e>: std_fmt::Display {
     fn name(&self) -> &'n str;
-    fn id(&self) -> usize;
     fn overrides(&self) -> Option<&[&'e str]>;
     fn aliases(&self) -> Option<Vec<&'e str>>;
     fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]>;
diff --git a/src/args/arg.rs b/src/args/arg.rs
index bb6bc50e..53cd262f 100644
--- a/src/args/arg.rs
+++ b/src/args/arg.rs
@@ -1335,7 +1335,7 @@ impl<'a, 'b> Arg<'a, 'b> {
     ///         .long("other")
     ///         .takes_value(true))
     ///     .get_matches_from_safe(vec![
-    ///         "prog", "--other", "not-special" 
+    ///         "prog", "--other", "not-special"
     ///     ]);
     ///
     /// assert!(res.is_ok()); // We didn't use --other=special, so "cfg" wasn't required
@@ -1355,7 +1355,7 @@ impl<'a, 'b> Arg<'a, 'b> {
     ///         .long("other")
     ///         .takes_value(true))
     ///     .get_matches_from_safe(vec![
-    ///         "prog", "--other", "special" 
+    ///         "prog", "--other", "special"
     ///     ]);
     ///
     /// assert!(res.is_err());
@@ -1721,7 +1721,7 @@ impl<'a, 'b> Arg<'a, 'b> {
     ///         .short("v"))
     ///     .get_matches_from(vec![
     ///         "prog", "-v", "-v", "-v"    // note, -vvv would have same result
-    ///     ]); 
+    ///     ]);
     ///
     /// assert!(m.is_present("verbose"));
     /// assert_eq!(m.occurrences_of("verbose"), 3);
@@ -1852,7 +1852,7 @@ impl<'a, 'b> Arg<'a, 'b> {
     /// [`number_of_values`]).
     ///
     /// **NOTE:** This setting only applies to [options] and [positional arguments]
-    /// 
+    ///
     /// **NOTE:** When the terminator is passed in on the command line, it is **not** stored as one
     /// of the vaues
     ///
@@ -2965,12 +2965,10 @@ impl<'a, 'b> Arg<'a, 'b> {
     /// ```
     /// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
     /// [`Arg::default_value`]: ./struct.Arg.html#method.default_value
-    pub fn default_value_if(self,
-                            arg: &'a str,
-                            val: Option<&'b str>,
-                            default: &'b str)
-                            -> Self {
-        self.default_value_if_os(arg, val.map(str::as_bytes).map(OsStr::from_bytes), OsStr::from_bytes(default.as_bytes()))
+    pub fn default_value_if(self, arg: &'a str, val: Option<&'b str>, default: &'b str) -> Self {
+        self.default_value_if_os(arg,
+                                 val.map(str::as_bytes).map(OsStr::from_bytes),
+                                 OsStr::from_bytes(default.as_bytes()))
     }
 
     /// Provides a conditional default value in the exact same manner as [`Arg::default_value_if`]
@@ -2978,10 +2976,10 @@ impl<'a, 'b> Arg<'a, 'b> {
     /// [`Arg::default_value_if`]: ./struct.Arg.html#method.default_value_if
     /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
     pub fn default_value_if_os(mut self,
-                            arg: &'a str,
-                            val: Option<&'b OsStr>,
-                            default: &'b OsStr)
-                            -> Self {
+                               arg: &'a str,
+                               val: Option<&'b OsStr>,
+                               default: &'b OsStr)
+                               -> Self {
         self.setb(ArgSettings::TakesValue);
         if let Some(ref mut vm) = self.v.default_vals_ifs {
             let l = vm.len();
@@ -3080,12 +3078,14 @@ impl<'a, 'b> Arg<'a, 'b> {
     /// [`Arg::default_value`]: ./struct.Arg.html#method.default_value
     pub fn default_value_ifs(mut self, ifs: &[(&'a str, Option<&'b str>, &'b str)]) -> Self {
         for &(arg, val, default) in ifs {
-            self = self.default_value_if_os(arg, val.map(str::as_bytes).map(OsStr::from_bytes), OsStr::from_bytes(default.as_bytes()));
+            self = self.default_value_if_os(arg,
+                                            val.map(str::as_bytes).map(OsStr::from_bytes),
+                                            OsStr::from_bytes(default.as_bytes()));
         }
         self
-    }   
+    }
 
-    /// Provides multiple conditional default values in the exact same manner as 
+    /// Provides multiple conditional default values in the exact same manner as
     /// [`Arg::default_value_ifs`] only using [`OsStr`]s instead.
     /// [`Arg::default_value_ifs`]: ./struct.Arg.html#method.default_value_ifs
     /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
diff --git a/src/args/arg_builder/base.rs b/src/args/arg_builder/base.rs
index fa52016f..1b5e534c 100644
--- a/src/args/arg_builder/base.rs
+++ b/src/args/arg_builder/base.rs
@@ -1,3 +1,4 @@
+
 use args::{ArgSettings, Arg, ArgFlags};
 
 #[derive(Debug, Clone, Default)]
@@ -5,7 +6,6 @@ pub struct Base<'a, 'b>
     where 'a: 'b
 {
     pub name: &'a str,
-    pub id: usize,
     pub help: Option<&'b str>,
     pub blacklist: Option<Vec<&'a str>>,
     pub settings: ArgFlags,
@@ -24,7 +24,5 @@ impl<'n, 'e> Base<'n, 'e> {
 }
 
 impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Base<'n, 'e> {
-    fn from(a: &'z Arg<'n, 'e>) -> Self {
-        a.b.clone()
-    }
+    fn from(a: &'z Arg<'n, 'e>) -> Self { a.b.clone() }
 }
diff --git a/src/args/arg_builder/flag.rs b/src/args/arg_builder/flag.rs
index ec3b5c35..6dc37243 100644
--- a/src/args/arg_builder/flag.rs
+++ b/src/args/arg_builder/flag.rs
@@ -4,6 +4,7 @@ use std::fmt::{Display, Formatter, Result};
 use std::rc::Rc;
 use std::result::Result as StdResult;
 use std::ffi::{OsStr, OsString};
+use std::mem;
 
 // Third Party
 use vec_map::{self, VecMap};
@@ -27,8 +28,6 @@ impl<'n, 'e> FlagBuilder<'n, 'e> {
 
 impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for FlagBuilder<'a, 'b> {
     fn from(a: &'z Arg<'a, 'b>) -> Self {
-        // No need to check for index() or takes_value() as that is handled above
-
         FlagBuilder {
             b: Base::from(a),
             s: Switched::from(a),
@@ -36,6 +35,15 @@ impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for FlagBuilder<'a, 'b> {
     }
 }
 
+impl<'a, 'b> From<Arg<'a, 'b>> for FlagBuilder<'a, 'b> {
+    fn from(mut a: Arg<'a, 'b>) -> Self {
+        FlagBuilder {
+            b: mem::replace(&mut a.b, Base::default()),
+            s: mem::replace(&mut a.s, Switched::default()),
+        }
+    }
+}
+
 impl<'n, 'e> Display for FlagBuilder<'n, 'e> {
     fn fmt(&self, f: &mut Formatter) -> Result {
         if let Some(l) = self.s.long {
@@ -50,9 +58,10 @@ impl<'n, 'e> Display for FlagBuilder<'n, 'e> {
 
 impl<'n, 'e> AnyArg<'n, 'e> for FlagBuilder<'n, 'e> {
     fn name(&self) -> &'n str { self.b.name }
-    fn id(&self) -> usize { self.b.id }
     fn overrides(&self) -> Option<&[&'e str]> { self.b.overrides.as_ref().map(|o| &o[..]) }
-    fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> { self.b.requires.as_ref().map(|o| &o[..]) }
+    fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
+        self.b.requires.as_ref().map(|o| &o[..])
+    }
     fn blacklist(&self) -> Option<&[&'e str]> { self.b.blacklist.as_ref().map(|o| &o[..]) }
     fn required_unless(&self) -> Option<&[&'e str]> { None }
     fn is_set(&self, s: ArgSettings) -> bool { self.b.settings.is_set(s) }
@@ -70,9 +79,11 @@ impl<'n, 'e> AnyArg<'n, 'e> for FlagBuilder<'n, 'e> {
     fn long(&self) -> Option<&'e str> { self.s.long }
     fn val_delim(&self) -> Option<char> { None }
     fn help(&self) -> Option<&'e str> { self.b.help }
-    fn val_terminator(&self) -> Option<&'e str> {None}
+    fn val_terminator(&self) -> Option<&'e str> { None }
     fn default_val(&self) -> Option<&'e OsStr> { None }
-    fn default_vals_ifs(&self) -> Option<vec_map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {None}
+    fn default_vals_ifs(&self) -> Option<vec_map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
+        None
+    }
     fn longest_filter(&self) -> bool { self.s.long.is_some() }
     fn aliases(&self) -> Option<Vec<&'e str>> {
         if let Some(ref aliases) = self.s.aliases {
diff --git a/src/args/arg_builder/option.rs b/src/args/arg_builder/option.rs
index 0bb784e4..75f14a73 100644
--- a/src/args/arg_builder/option.rs
+++ b/src/args/arg_builder/option.rs
@@ -3,6 +3,7 @@ use std::fmt::{Display, Formatter, Result};
 use std::rc::Rc;
 use std::result::Result as StdResult;
 use std::ffi::{OsStr, OsString};
+use std::mem;
 
 // Third Party
 use vec_map::{self, VecMap};
@@ -23,23 +24,26 @@ pub struct OptBuilder<'n, 'e>
 
 impl<'n, 'e> OptBuilder<'n, 'e> {
     pub fn new(name: &'n str) -> Self { OptBuilder { b: Base::new(name), ..Default::default() } }
+}
 
-    pub fn from_arg(a: &Arg<'n, 'e>, reqs: &mut Vec<&'n str>) -> Self {
-        // No need to check for .index() as that is handled above
-        let ob = OptBuilder {
+impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for OptBuilder<'n, 'e> {
+    fn from(a: &'z Arg<'n, 'e>) -> Self {
+        OptBuilder {
             b: Base::from(a),
             s: Switched::from(a),
             v: Valued::from(a),
-        };
-        // If the arg is required, add all it's requirements to master required list
-        if a.is_set(ArgSettings::Required) {
-            if let Some(ref areqs) = a.b.requires {
-                for r in areqs.iter().filter(|r| r.0.is_none()) {
-                    reqs.push(r.1);
-                }
-            }
         }
-        ob
+    }
+}
+
+impl<'n, 'e> From<Arg<'n, 'e>> for OptBuilder<'n, 'e> {
+    fn from(mut a: Arg<'n, 'e>) -> Self {
+        a.v.fill_in();
+        OptBuilder {
+            b: mem::replace(&mut a.b, Base::default()),
+            s: mem::replace(&mut a.s, Switched::default()),
+            v: mem::replace(&mut a.v, Valued::default()),
+        }
     }
 }
 
@@ -94,9 +98,10 @@ impl<'n, 'e> Display for OptBuilder<'n, 'e> {
 
 impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> {
     fn name(&self) -> &'n str { self.b.name }
-    fn id(&self) -> usize { self.b.id }
     fn overrides(&self) -> Option<&[&'e str]> { self.b.overrides.as_ref().map(|o| &o[..]) }
-    fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> { self.b.requires.as_ref().map(|o| &o[..]) }
+    fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
+        self.b.requires.as_ref().map(|o| &o[..])
+    }
     fn blacklist(&self) -> Option<&[&'e str]> { self.b.blacklist.as_ref().map(|o| &o[..]) }
     fn required_unless(&self) -> Option<&[&'e str]> { self.b.r_unless.as_ref().map(|o| &o[..]) }
     fn val_names(&self) -> Option<&VecMap<&'e str>> { self.v.val_names.as_ref() }
@@ -120,7 +125,9 @@ impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> {
     fn takes_value(&self) -> bool { true }
     fn help(&self) -> Option<&'e str> { self.b.help }
     fn default_val(&self) -> Option<&'e OsStr> { self.v.default_val }
-    fn default_vals_ifs(&self) -> Option<vec_map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> { self.v.default_vals_ifs.as_ref().map(|vm| vm.values()) }
+    fn default_vals_ifs(&self) -> Option<vec_map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
+        self.v.default_vals_ifs.as_ref().map(|vm| vm.values())
+    }
     fn longest_filter(&self) -> bool { true }
     fn aliases(&self) -> Option<Vec<&'e str>> {
         if let Some(ref aliases) = self.s.aliases {
diff --git a/src/args/arg_builder/positional.rs b/src/args/arg_builder/positional.rs
index 3d2da818..73fde4c1 100644
--- a/src/args/arg_builder/positional.rs
+++ b/src/args/arg_builder/positional.rs
@@ -4,6 +4,7 @@ use std::fmt::{Display, Formatter, Result};
 use std::rc::Rc;
 use std::result::Result as StdResult;
 use std::ffi::{OsStr, OsString};
+use std::mem;
 
 // Third Party
 use vec_map::{self, VecMap};
@@ -32,10 +33,7 @@ impl<'n, 'e> PosBuilder<'n, 'e> {
         }
     }
 
-    pub fn from_arg(a: &Arg<'n, 'e>, idx: u64, reqs: &mut Vec<&'n str>) -> Self {
-        // Create the Positional Argument Builder with each HashSet = None to only
-        // allocate
-        // those that require it
+    pub fn from_arg_ref(a: &Arg<'n, 'e>, idx: u64) -> Self {
         let mut pb = PosBuilder {
             b: Base::from(a),
             v: Valued::from(a),
@@ -45,17 +43,21 @@ impl<'n, 'e> PosBuilder<'n, 'e> {
            (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1) {
             pb.b.settings.set(ArgSettings::Multiple);
         }
-        // If the arg is required, add all it's requirements to master required list
-        if a.is_set(ArgSettings::Required) {
-            if let Some(ref areqs) = a.b.requires {
-                for name in areqs.iter().filter(|&&(val,_)|val.is_none()).map(|&(_, name)| name) {
-                    reqs.push(name);
-                }
-            }
-        }
         pb
     }
 
+    pub fn from_arg(mut a: Arg<'n, 'e>, idx: u64) -> Self {
+        if a.v.max_vals.is_some() || a.v.min_vals.is_some() ||
+           (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1) {
+            a.b.settings.set(ArgSettings::Multiple);
+        }
+        PosBuilder {
+            b: mem::replace(&mut a.b, Base::default()),
+            v: mem::replace(&mut a.v, Valued::default()),
+            index: idx,
+        }
+    }
+
     pub fn multiple_str(&self) -> &str {
         if self.b.settings.is_set(ArgSettings::Multiple) && self.v.val_names.is_none() {
             "..."
@@ -98,9 +100,10 @@ impl<'n, 'e> Display for PosBuilder<'n, 'e> {
 
 impl<'n, 'e> AnyArg<'n, 'e> for PosBuilder<'n, 'e> {
     fn name(&self) -> &'n str { self.b.name }
-    fn id(&self) -> usize { self.b.id }
     fn overrides(&self) -> Option<&[&'e str]> { self.b.overrides.as_ref().map(|o| &o[..]) }
-    fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> { self.b.requires.as_ref().map(|o| &o[..]) }
+    fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
+        self.b.requires.as_ref().map(|o| &o[..])
+    }
     fn blacklist(&self) -> Option<&[&'e str]> { self.b.blacklist.as_ref().map(|o| &o[..]) }
     fn required_unless(&self) -> Option<&[&'e str]> { self.b.r_unless.as_ref().map(|o| &o[..]) }
     fn val_names(&self) -> Option<&VecMap<&'e str>> { self.v.val_names.as_ref() }
@@ -123,7 +126,9 @@ impl<'n, 'e> AnyArg<'n, 'e> for PosBuilder<'n, 'e> {
     fn val_delim(&self) -> Option<char> { self.v.val_delim }
     fn takes_value(&self) -> bool { true }
     fn help(&self) -> Option<&'e str> { self.b.help }
-    fn default_vals_ifs(&self) -> Option<vec_map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> { self.v.default_vals_ifs.as_ref().map(|vm| vm.values()) }
+    fn default_vals_ifs(&self) -> Option<vec_map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
+        self.v.default_vals_ifs.as_ref().map(|vm| vm.values())
+    }
     fn default_val(&self) -> Option<&'e OsStr> { self.v.default_val }
     fn longest_filter(&self) -> bool { true }
     fn aliases(&self) -> Option<Vec<&'e str>> { None }
diff --git a/src/args/arg_builder/switched.rs b/src/args/arg_builder/switched.rs
index 777ff1d5..e42586c2 100644
--- a/src/args/arg_builder/switched.rs
+++ b/src/args/arg_builder/switched.rs
@@ -1,3 +1,4 @@
+
 use Arg;
 
 #[derive(Debug)]
@@ -22,9 +23,7 @@ impl<'e> Default for Switched<'e> {
 }
 
 impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Switched<'e> {
-    fn from(a: &'z Arg<'n, 'e>) -> Self {
-        a.s.clone()
-    }
+    fn from(a: &'z Arg<'n, 'e>) -> Self { a.s.clone() }
 }
 
 impl<'e> Clone for Switched<'e> {
diff --git a/src/args/arg_builder/valued.rs b/src/args/arg_builder/valued.rs
index d98e3c34..93d63cce 100644
--- a/src/args/arg_builder/valued.rs
+++ b/src/args/arg_builder/valued.rs
@@ -41,14 +41,19 @@ impl<'n, 'e> Default for Valued<'n, 'e> {
     }
 }
 
-impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Valued<'n, 'e> {
-    fn from(a: &'z Arg<'n, 'e>) -> Self {
-        let mut v = a.v.clone();
-        if let Some(ref vec) = a.v.val_names {
+impl<'n, 'e> Valued<'n, 'e> {
+    pub fn fill_in(&mut self) {
+        if let Some(ref vec) = self.val_names {
             if vec.len() > 1 {
-                v.num_vals = Some(vec.len() as u64);
+                self.num_vals = Some(vec.len() as u64);
             }
         }
+    }
+}
+
+impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Valued<'n, 'e> {
+    fn from(a: &'z Arg<'n, 'e>) -> Self {
+        let mut v = a.v.clone();
         if let Some(ref vec) = a.v.val_names {
             if vec.len() > 1 {
                 v.num_vals = Some(vec.len() as u64);
diff --git a/src/args/arg_matcher.rs b/src/args/arg_matcher.rs
index 27f57c6d..3052acd9 100644
--- a/src/args/arg_matcher.rs
+++ b/src/args/arg_matcher.rs
@@ -40,7 +40,7 @@ impl<'a> ArgMatcher<'a> {
                         gma.vals.insert(i, v.clone());
                     }
                     gma
-                }); 
+                });
                 if sma.vals.is_empty() {
                     for (i, v) in &vals {
                         sma.vals.insert(i, v.clone());
diff --git a/src/completions/bash.rs b/src/completions/bash.rs
index ab94865b..a5333828 100644
--- a/src/completions/bash.rs
+++ b/src/completions/bash.rs
@@ -125,21 +125,7 @@ complete -F _{name} -o bashdefault -o default {name}
         let mut p = self.p;
         for sc in path.split("__").skip(1) {
             debugln!("BashGen::option_details_for_path:iter: sc={}", sc);
-            p = &p.subcommands
-                .iter()
-                .find(|s| {
-                    s.p.meta.name == sc ||
-                    (s.p.meta.aliases.is_some() &&
-                     s.p
-                        .meta
-                        .aliases
-                        .as_ref()
-                        .unwrap()
-                        .iter()
-                        .any(|&(n, _)| n == sc))
-                })
-                .unwrap()
-                .p;
+            p = &find_subcmd!(p, sc).unwrap().p;
         }
         let mut opts = String::new();
         for o in p.opts() {
@@ -214,28 +200,12 @@ complete -F _{name} -o bashdefault -o default {name}
         let mut p = self.p;
         for sc in path.split("__").skip(1) {
             debugln!("BashGen::all_options_for_path:iter: sc={}", sc);
-            p = &p.subcommands
-                .iter()
-                .find(|s| {
-                    s.p.meta.name == sc ||
-                    (s.p.meta.aliases.is_some() &&
-                     s.p
-                        .meta
-                        .aliases
-                        .as_ref()
-                        .unwrap()
-                        .iter()
-                        .any(|&(n, _)| n == sc))
-                })
-                .unwrap()
-                .p;
+            p = &find_subcmd!(p, sc).unwrap().p;
         }
-        let mut opts = p.short_list.iter().fold(String::new(), |acc, s| format!("{} -{}", acc, s));
+        let mut opts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s));
         opts = format!("{} {}",
                        opts,
-                       p.long_list
-                           .iter()
-                           .fold(String::new(), |acc, l| format!("{} --{}", acc, l)));
+                       longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l)));
         opts = format!("{} {}",
                        opts,
                        p.positionals
diff --git a/src/completions/powershell.rs b/src/completions/powershell.rs
index 7c842b73..b70da452 100644
--- a/src/completions/powershell.rs
+++ b/src/completions/powershell.rs
@@ -19,10 +19,7 @@ impl<'a, 'b> PowerShellGen<'a, 'b> {
 
         let (subcommands_detection_cases, subcommands_cases) = generate_inner(self.p, "");
 
-        let mut bin_names = vec![
-            bin_name.to_string(),
-            format!("./{0}", bin_name),
-        ];
+        let mut bin_names = vec![bin_name.to_string(), format!("./{0}", bin_name)];
         if cfg!(windows) {
             bin_names.push(format!("{0}.exe", bin_name));
             bin_names.push(format!(r".\{0}", bin_name));
@@ -92,10 +89,10 @@ fn generate_inner<'a, 'b>(p: &Parser<'a, 'b>, previous_command_name: &str) -> (S
     for subcommand in &p.subcommands {
         completions.push_str(&format!("'{}', ", &subcommand.p.meta.name));
     }
-    for short in &p.short_list {
+    for short in shorts!(p) {
         completions.push_str(&format!("'-{}', ", short));
     }
-    for long in &p.long_list {
+    for long in longs!(p) {
         completions.push_str(&format!("'--{}', ", long));
     }
 
diff --git a/src/macros.rs b/src/macros.rs
index 277098e7..2ce6d679 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -498,11 +498,11 @@ macro_rules! crate_name {
 /// Provided separator is for the [`crate_authors!`](macro.crate_authors.html) macro,
 /// refer to the documentation therefor.
 ///
-/// **NOTE:** Changing the values in your `Cargo.toml` does not trigger a re-build automatically, 
+/// **NOTE:** Changing the values in your `Cargo.toml` does not trigger a re-build automatically,
 /// and therefore won't change the generated output until you recompile.
 ///
 /// **Pro Tip:** In some cases you can "trick" the compiler into triggering a rebuild when your
-/// `Cargo.toml` is changed by including this in your `src/main.rs` file 
+/// `Cargo.toml` is changed by including this in your `src/main.rs` file
 /// `include_str!("../Cargo.toml");`
 ///
 /// # Examples
@@ -542,47 +542,47 @@ macro_rules! app_from_crate {
 /// # #[macro_use]
 /// # extern crate clap;
 /// # fn main() {
-/// let matches = clap_app!(myapp =>                                       
-///     (version: "1.0")                                                   
-///     (author: "Kevin K. <kbknapp@gmail.com>")                           
-///     (about: "Does awesome things")                                     
+/// let matches = clap_app!(myapp =>
+///     (version: "1.0")
+///     (author: "Kevin K. <kbknapp@gmail.com>")
+///     (about: "Does awesome things")
 ///     (@arg CONFIG: -c --config +takes_value "Sets a custom config file")
-///     (@arg INPUT: +required "Sets the input file to use")               
-///     (@arg debug: -d ... "Sets the level of debugging information")     
-///     (@subcommand test =>                                               
-///         (about: "controls testing features")                           
-///         (version: "1.3")                                               
-///         (author: "Someone E. <someone_else@other.com>")                
+///     (@arg INPUT: +required "Sets the input file to use")
+///     (@arg debug: -d ... "Sets the level of debugging information")
+///     (@subcommand test =>
+///         (about: "controls testing features")
+///         (version: "1.3")
+///         (author: "Someone E. <someone_else@other.com>")
 ///         (@arg verbose: -v --verbose "Print test information verbosely")
-///     )                                                                  
+///     )
 /// );
-/// # }                                                                          
+/// # }
 /// ```
 /// # Shorthand Syntax for Args
-/// 
+///
 /// * A single hyphen followed by a character (such as `-c`) sets the [`Arg::short`]
 /// * A double hyphen followed by a character or word (such as `--config`) sets [`Arg::long`]
 /// * Three dots (`...`) sets [`Arg::multiple(true)`]
-/// * Angled brackets after either a short or long will set [`Arg::value_name`] and 
-/// `Arg::required(true)` such as `--config <FILE>` = `Arg::value_name("FILE")` and 
+/// * Angled brackets after either a short or long will set [`Arg::value_name`] and
+/// `Arg::required(true)` such as `--config <FILE>` = `Arg::value_name("FILE")` and
 /// `Arg::required(true)
-/// * Square brackets after either a short or long will set [`Arg::value_name`] and 
-/// `Arg::required(false)` such as `--config [FILE]` = `Arg::value_name("FILE")` and 
+/// * Square brackets after either a short or long will set [`Arg::value_name`] and
+/// `Arg::required(false)` such as `--config [FILE]` = `Arg::value_name("FILE")` and
 /// `Arg::required(false)
-/// * There are short hand syntaxes for Arg methods that accept booleans 
+/// * There are short hand syntaxes for Arg methods that accept booleans
 ///   * A plus sign will set that method to `true` such as `+required` = `Arg::required(true)`
 ///   * An exclamation will set that method to `false` such as `!required` = `Arg::required(false)`
 /// * A `#{min, max}` will set [`Arg::min_values(min)`] and [`Arg::max_values(max)`]
 /// * An asterisk (`*`) will set `Arg::required(true)`
 /// * Curly brackets around a `fn` will set [`Arg::validator`] as in `{fn}` = `Arg::validator(fn)`
-/// * An Arg method that accepts a string followed by square brackets will set that method such as 
-/// `conflicts_with[FOO]` will set `Arg::conflicts_with("FOO")` (note the lack of quotes around 
-/// `FOO` in the macro) 
-/// * An Arg method that takes a string and can be set multiple times (such as 
-/// [`Arg::conflicts_with`]) followed by square brackets and a list of values separated by spaces 
-/// will set that method such as `conflicts_with[FOO BAR BAZ]` will set 
+/// * An Arg method that accepts a string followed by square brackets will set that method such as
+/// `conflicts_with[FOO]` will set `Arg::conflicts_with("FOO")` (note the lack of quotes around
+/// `FOO` in the macro)
+/// * An Arg method that takes a string and can be set multiple times (such as
+/// [`Arg::conflicts_with`]) followed by square brackets and a list of values separated by spaces
+/// will set that method such as `conflicts_with[FOO BAR BAZ]` will set
 /// `Arg::conflicts_with("FOO")`, `Arg::conflicts_with("BAR")`, and `Arg::conflicts_with("BAZ")`
-/// (note the lack of quotes around the values in the macro) 
+/// (note the lack of quotes around the values in the macro)
 ///
 /// [`Arg::short`]: ./struct.Arg.html#method.short
 /// [`Arg::long`]: ./struct.Arg.html#method.long
@@ -846,3 +846,201 @@ macro_rules! vec_remove_all {
         }
     };
 }
+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_opt_by_long {
+    (@os $_self:ident, $long:expr) => {{
+        _find_by_long!($_self, $long, opts)
+    }};
+    ($_self:ident, $long:expr) => {{
+        _find_by_long!($_self, $long, opts)
+    }};
+}
+
+macro_rules! find_flag_by_long {
+    (@os $_self:ident, $long:expr) => {{
+        _find_by_long!($_self, $long, flags)
+    }};
+    ($_self:ident, $long:expr) => {{
+        _find_by_long!($_self, $long, flags)
+    }};
+}
+
+macro_rules! find_any_by_long {
+    ($_self:ident, $long:expr, $what:ident) => {
+        _find_flag_by_long!($_self, $long).or(_find_opt_by_long!($_self, $long))
+    }
+}
+
+macro_rules! _find_by_long {
+    ($_self:ident, $long:expr, $what:ident) => {{
+        $_self.$what
+            .iter()
+            .filter(|a| a.s.long.is_some())
+            .find(|a| {
+                &&a.s.long.unwrap() == &$long ||
+                (a.s.aliases.is_some() &&
+                 a.s
+                    .aliases
+                    .as_ref()
+                    .unwrap()
+                    .iter()
+                    .any(|&(alias, _)| &&alias == &$long))
+            })
+    }}
+}
+
+// Finds an option
+macro_rules! find_opt_by_short {
+    ($_self:ident, $short:expr) => {{
+        _find_by_short!($_self, $short, opts)
+    }}
+}
+
+macro_rules! find_flag_by_short {
+    ($_self:ident, $short:expr) => {{
+        _find_by_short!($_self, $short, flags)
+    }}
+}
+
+macro_rules! find_any_by_short {
+    ($_self:ident, $short:expr, $what:ident) => {
+        _find_flag_by_short!($_self, $short).or(_find_opt_by_short!($_self, $short))
+    }
+}
+
+macro_rules! _find_by_short {
+    ($_self:ident, $short:expr, $what:ident) => {{
+        $_self.$what
+            .iter()
+            .filter(|a| a.s.short.is_some())
+            .find(|a| a.s.short.unwrap() == $short)
+    }}
+}
+
+macro_rules! find_subcmd {
+    ($_self:expr, $sc:expr) => {{
+        $_self.subcommands
+            .iter()
+            .find(|s| {
+                s.p.meta.name == $sc ||
+                (s.p.meta.aliases.is_some() &&
+                 s.p
+                    .meta
+                    .aliases
+                    .as_ref()
+                    .unwrap()
+                    .iter()
+                    .any(|&(n, _)| n == $sc))
+            })
+    }};
+}
+
+macro_rules! shorts {
+    ($_self:ident) => {{
+        _shorts_longs!($_self, short)
+    }};
+}
+
+
+macro_rules! longs {
+    ($_self:ident) => {{
+        _shorts_longs!($_self, long)
+    }};
+}
+
+macro_rules! _shorts_longs {
+    ($_self:ident, $what:ident) => {{
+        $_self.flags
+                .iter()
+                .filter(|f| f.s.$what.is_some())
+                .map(|f| f.s.$what.as_ref().unwrap())
+                .chain($_self.opts.iter()
+                                  .filter(|o| o.s.$what.is_some())
+                                  .map(|o| o.s.$what.as_ref().unwrap()))
+    }};
+}
+
+macro_rules! arg_names {
+    ($_self:ident) => {{
+        _names!($_self)
+    }};
+}
+
+macro_rules! _names {
+    ($_self:ident) => {{
+        $_self.flags
+                .iter()
+                .map(|f| &*f.b.name)
+                .chain($_self.opts.iter()
+                                  .map(|o| &*o.b.name)
+                                  .chain($_self.positionals.values()
+                                                           .map(|p| &*p.b.name)))
+    }};
+}


Test patch:
diff --git a/clap-test.rs b/clap-test.rs
index ebbf9ea0..9b218172 100644
--- a/clap-test.rs
+++ b/clap-test.rs
@@ -9,11 +9,14 @@ mod test {
 
     fn compare<S, S2>(l: S, r: S2) -> bool
         where S: AsRef<str>,
-              S2: AsRef<str> {
+              S2: AsRef<str>
+    {
         let re = Regex::new("\x1b[^m]*m").unwrap();
         // Strip out any mismatching \r character on windows that might sneak in on either side
-        let left = re.replace_all(&l.as_ref().trim().replace("\r", "")[..], "").into_owned();
-        let right = re.replace_all(&r.as_ref().trim().replace("\r", "")[..], "").into_owned();
+        let ls = l.as_ref().trim().replace("\r", "");
+        let rs = r.as_ref().trim().replace("\r", "");
+        let left = re.replace_all(&*ls, "");
+        let right = re.replace_all(&*rs, "");
         let b = left == right;
         if !b {
             println!("");
diff --git a/tests/borrowed.rs b/tests/borrowed.rs
new file mode 100644
index 00000000..e7a184b5
--- /dev/null
+++ b/tests/borrowed.rs
@@ -0,0 +1,19 @@
+extern crate clap;
+extern crate regex;
+
+use clap::{App, Arg, SubCommand};
+
+include!("../clap-test.rs");
+
+#[test]
+fn borrowed_args() {
+    let arg = Arg::with_name("some").short("s").long("some").help("other help");
+    let arg2 = Arg::with_name("some2").short("S").long("some-thing").help("other help");
+    let result = App::new("sub_command_negate")
+        .arg(Arg::with_name("test").index(1))
+        .arg(&arg)
+        .arg(&arg2)
+        .subcommand(SubCommand::with_name("sub1").arg(&arg))
+        .get_matches_from_safe(vec!["prog"]);
+    assert!(result.is_ok());
+}
diff --git a/tests/completions.rs b/tests/completions.rs
index 8b4f843f..e41fc9d1 100644
--- a/tests/completions.rs
+++ b/tests/completions.rs
@@ -1,9 +1,9 @@
-extern crate regex;
-extern crate clap;
-
-use clap::{App, Arg, SubCommand, Shell};
-use regex::Regex;
-
+extern crate regex;
+extern crate clap;
+
+use clap::{App, Arg, SubCommand, Shell};
+use regex::Regex;
+
 static BASH: &'static str = r#"_myapp() {
     local i cur prev opts cmds
     COMPREPLY=()
@@ -63,7 +63,7 @@ static BASH: &'static str = r#"_myapp() {
             return 0
             ;;
         myapp__test)
-            opts=" -h -V  --case --help --version  "
+            opts=" -h -V  --help --version --case  "
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
                 return 0
@@ -85,8 +85,8 @@ static BASH: &'static str = r#"_myapp() {
 }
 
 complete -F _myapp -o bashdefault -o default myapp
-"#;
-
+"#;
+
 static ZSH: &'static str = r#"#compdef myapp
 
 _myapp() {
@@ -152,8 +152,8 @@ _myapp__test_commands() {
     _describe -t commands 'myapp test commands' commands "$@"
 }
 
-_myapp "$@""#;
-
+_myapp "$@""#;
+
 static FISH: &'static str = r#"function __fish_using_command
     set cmd (commandline -opc)
     if [ (count $cmd) -eq (count $argv) ]
@@ -176,9 +176,9 @@ complete -c myapp -n "__fish_using_command myapp test" -s h -l help -d "Prints h
 complete -c myapp -n "__fish_using_command myapp test" -s V -l version -d "Prints version information"
 complete -c myapp -n "__fish_using_command myapp help" -s h -l help -d "Prints help information"
 complete -c myapp -n "__fish_using_command myapp help" -s V -l version -d "Prints version information"
-"#;
-
-#[cfg(not(target_os="windows"))]
+"#;
+
+#[cfg(not(target_os="windows"))]
 static POWERSHELL: &'static str = r#"
 @('myapp', './myapp') | %{
     Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
@@ -227,9 +227,9 @@ static POWERSHELL: &'static str = r#"
             %{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
     }
 }
-"#;
-
-#[cfg(target_os="windows")]
+"#;
+
+#[cfg(target_os="windows")]
 static POWERSHELL: &'static str = r#"
 @('myapp', './myapp', 'myapp.exe', '.\myapp', '.\myapp.exe', './myapp.exe') | %{
     Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
@@ -267,9 +267,9 @@ static POWERSHELL: &'static str = r#"
             %{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
     }
 }
-"#;
-
-#[cfg(not(target_os="windows"))]
+"#;
+
+#[cfg(not(target_os="windows"))]
 static POWERSHELL_WUS: &'static str = r#"
 @('my_app', './my_app') | %{
     Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
@@ -327,9 +327,9 @@ static POWERSHELL_WUS: &'static str = r#"
             %{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
     }
 }
-"#;
-
-#[cfg(target_os="windows")]
+"#;
+
+#[cfg(target_os="windows")]
 static POWERSHELL_WUS: &'static str = r#"
 @('my_app', './my_app', 'my_app.exe', '.\my_app', '.\my_app.exe', './my_app.exe') | %{
     Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
@@ -374,8 +374,8 @@ static POWERSHELL_WUS: &'static str = r#"
             %{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
     }
 }
-"#;
-
+"#;
+
 static ZSH_WUS: &'static str = r#"#compdef my_app
 
 _my_app() {
@@ -458,8 +458,8 @@ _my_app__test_commands() {
     _describe -t commands 'my_app test commands' commands "$@"
 }
 
-_my_app "$@""#;
-
+_my_app "$@""#;
+
 static FISH_WUS: &'static str = r#"function __fish_using_command
     set cmd (commandline -opc)
     if [ (count $cmd) -eq (count $argv) ]
@@ -486,8 +486,8 @@ complete -c my_app -n "__fish_using_command my_app some_cmd" -s h -l help -d "Pr
 complete -c my_app -n "__fish_using_command my_app some_cmd" -s V -l version -d "Prints version information"
 complete -c my_app -n "__fish_using_command my_app help" -s h -l help -d "Prints help information"
 complete -c my_app -n "__fish_using_command my_app help" -s V -l version -d "Prints version information"
-"#;
-
+"#;
+
 static BASH_WUS: &'static str = r#"_my_app() {
     local i cur prev opts cmds
     COMPREPLY=()
@@ -550,7 +550,7 @@ static BASH_WUS: &'static str = r#"_my_app() {
             return 0
             ;;
         my_app__some_cmd)
-            opts=" -h -V  --config --help --version  "
+            opts=" -h -V  --help --version --config  "
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
                 return 0
@@ -569,7 +569,7 @@ static BASH_WUS: &'static str = r#"_my_app() {
             return 0
             ;;
         my_app__test)
-            opts=" -h -V  --case --help --version  "
+            opts=" -h -V  --help --version --case  "
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
                 return 0
@@ -591,129 +591,125 @@ static BASH_WUS: &'static str = r#"_my_app() {
 }
 
 complete -F _my_app -o bashdefault -o default my_app
-"#;
-
-fn compare(left: &str, right: &str) -> bool {
-    let b = left == right;
-    if !b {
-        let re = Regex::new(" ").unwrap();
-        println!("");
-        println!("--> left");
-        // println!("{}", left);
-        println!("{}", re.replace_all(left, "\u{2022}"));
-        println!("--> right");
-        println!("{}", re.replace_all(right, "\u{2022}"));
-        // println!("{}", right);
-        println!("--")
-    }
-    b
-}
-
-fn build_app() -> App<'static, 'static> {
-    build_app_with_name("myapp")
-}
-
-fn build_app_with_name(s: &'static str) -> App<'static, 'static> {
-   App::new(s)
-        .about("Tests completions")
-        .arg(Arg::with_name("file")
-            .help("some input file"))
-        .subcommand(SubCommand::with_name("test")
-            .about("tests things")
-            .arg(Arg::with_name("case")
-                .long("case")
-                .takes_value(true)
-                .help("the case to test")))
-}
-
-fn build_app_with_underscore() -> App<'static, 'static> {
-    build_app_with_name("my_app")
-        .subcommand(SubCommand::with_name("some_cmd")
-            .about("tests other things")
-            .arg(Arg::with_name("config")
-                .long("--config")
-                .takes_value(true)
-                .help("the other case to test")))
-}
-
-#[test]
-fn bash() {
-    let mut app = build_app();
-    let mut buf = vec![];
-    app.gen_completions_to("myapp", Shell::Bash, &mut buf);
-    let string = String::from_utf8(buf).unwrap();
-
-    assert!(compare(&*string, BASH));
-}
-
-#[test]
-fn zsh() {
-    let mut app = build_app();
-    let mut buf = vec![];
-    app.gen_completions_to("myapp", Shell::Zsh, &mut buf);
-    let string = String::from_utf8(buf).unwrap();
-
-    assert!(compare(&*string, ZSH));
-}
-
-#[test]
-fn fish() {
-    let mut app = build_app();
-    let mut buf = vec![];
-    app.gen_completions_to("myapp", Shell::Fish, &mut buf);
-    let string = String::from_utf8(buf).unwrap();
-
-    assert!(compare(&*string, FISH));
-}
-
-// Disabled until I figure out this windows line ending and AppVeyor issues
-//#[test]
-fn powershell() {
-    let mut app = build_app();
-    let mut buf = vec![];
-    app.gen_completions_to("myapp", Shell::PowerShell, &mut buf);
-    let string = String::from_utf8(buf).unwrap();
-
-    assert!(compare(&*string, POWERSHELL));
-}
-
-// Disabled until I figure out this windows line ending and AppVeyor issues
-//#[test]
-fn powershell_with_underscore() {
-    let mut app = build_app_with_underscore();
-    let mut buf = vec![];
-    app.gen_completions_to("my_app", Shell::PowerShell, &mut buf);
-    let string = String::from_utf8(buf).unwrap();
-
-    assert!(compare(&*string, POWERSHELL_WUS));
-}
-
-#[test]
-fn bash_with_underscore() {
-    let mut app = build_app_with_underscore();
-    let mut buf = vec![];
-    app.gen_completions_to("my_app", Shell::Bash, &mut buf);
-    let string = String::from_utf8(buf).unwrap();
-
-    assert!(compare(&*string, BASH_WUS));
-}
-
-#[test]
-fn fish_with_underscore() {
-    let mut app = build_app_with_underscore();
-    let mut buf = vec![];
-    app.gen_completions_to("my_app", Shell::Fish, &mut buf);
-    let string = String::from_utf8(buf).unwrap();
-
-    assert!(compare(&*string, FISH_WUS));
-}
-
-#[test]
-fn zsh_with_underscore() {
-    let mut app = build_app_with_underscore();
-    let mut buf = vec![];
-    app.gen_completions_to("my_app", Shell::Zsh, &mut buf);
-    let string = String::from_utf8(buf).unwrap();
-
-    assert!(compare(&*string, ZSH_WUS));
-}
\ No newline at end of file
+"#;
+
+fn compare(left: &str, right: &str) -> bool {
+    let b = left == right;
+    if !b {
+        let re = Regex::new(" ").unwrap();
+        println!("");
+        println!("--> left");
+        // println!("{}", left);
+        println!("{}", re.replace_all(left, "\u{2022}"));
+        println!("--> right");
+        println!("{}", re.replace_all(right, "\u{2022}"));
+        // println!("{}", right);
+        println!("--")
+    }
+    b
+}
+
+fn build_app() -> App<'static, 'static> { build_app_with_name("myapp") }
+
+fn build_app_with_name(s: &'static str) -> App<'static, 'static> {
+    App::new(s)
+        .about("Tests completions")
+        .arg(Arg::with_name("file").help("some input file"))
+        .subcommand(SubCommand::with_name("test")
+            .about("tests things")
+            .arg(Arg::with_name("case")
+                .long("case")
+                .takes_value(true)
+                .help("the case to test")))
+}
+
+fn build_app_with_underscore() -> App<'static, 'static> {
+    build_app_with_name("my_app").subcommand(SubCommand::with_name("some_cmd")
+        .about("tests other things")
+        .arg(Arg::with_name("config")
+            .long("--config")
+            .takes_value(true)
+            .help("the other case to test")))
+}
+
+#[test]
+fn bash() {
+    let mut app = build_app();
+    let mut buf = vec![];
+    app.gen_completions_to("myapp", Shell::Bash, &mut buf);
+    let string = String::from_utf8(buf).unwrap();
+
+    assert!(compare(&*string, BASH));
+}
+
+#[test]
+fn zsh() {
+    let mut app = build_app();
+    let mut buf = vec![];
+    app.gen_completions_to("myapp", Shell::Zsh, &mut buf);
+    let string = String::from_utf8(buf).unwrap();
+
+    assert!(compare(&*string, ZSH));
+}
+
+#[test]
+fn fish() {
+    let mut app = build_app();
+    let mut buf = vec![];
+    app.gen_completions_to("myapp", Shell::Fish, &mut buf);
+    let string = String::from_utf8(buf).unwrap();
+
+    assert!(compare(&*string, FISH));
+}
+
+// Disabled until I figure out this windows line ending and AppVeyor issues
+//#[test]
+// fn powershell() {
+//     let mut app = build_app();
+//     let mut buf = vec![];
+//     app.gen_completions_to("myapp", Shell::PowerShell, &mut buf);
+//     let string = String::from_utf8(buf).unwrap();
+//
+//     assert!(compare(&*string, POWERSHELL));
+// }
+
+// Disabled until I figure out this windows line ending and AppVeyor issues
+//#[test]
+// fn powershell_with_underscore() {
+//     let mut app = build_app_with_underscore();
+//     let mut buf = vec![];
+//     app.gen_completions_to("my_app", Shell::PowerShell, &mut buf);
+//     let string = String::from_utf8(buf).unwrap();
+//
+//     assert!(compare(&*string, POWERSHELL_WUS));
+// }
+
+#[test]
+fn bash_with_underscore() {
+    let mut app = build_app_with_underscore();
+    let mut buf = vec![];
+    app.gen_completions_to("my_app", Shell::Bash, &mut buf);
+    let string = String::from_utf8(buf).unwrap();
+
+    assert!(compare(&*string, BASH_WUS));
+}
+
+#[test]
+fn fish_with_underscore() {
+    let mut app = build_app_with_underscore();
+    let mut buf = vec![];
+    app.gen_completions_to("my_app", Shell::Fish, &mut buf);
+    let string = String::from_utf8(buf).unwrap();
+
+    assert!(compare(&*string, FISH_WUS));
+}
+
+#[test]
+fn zsh_with_underscore() {
+    let mut app = build_app_with_underscore();
+    let mut buf = vec![];
+    app.gen_completions_to("my_app", Shell::Zsh, &mut buf);
+    let string = String::from_utf8(buf).unwrap();
+
+    assert!(compare(&*string, ZSH_WUS));
+}
diff --git a/tests/help.rs b/tests/help.rs
index 0393f057..2390458e 100644
--- a/tests/help.rs
+++ b/tests/help.rs
@@ -278,8 +278,7 @@ fn help_subcommand() {
 
 #[test]
 fn subcommand_short_help() {
-    let m = test::complex_app()
-        .get_matches_from_safe(vec!["clap-test", "subcmd", "-h"]);
+    let m = test::complex_app().get_matches_from_safe(vec!["clap-test", "subcmd", "-h"]);
 
     assert!(m.is_err());
     assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
@@ -287,8 +286,7 @@ fn subcommand_short_help() {
 
 #[test]
 fn subcommand_long_help() {
-    let m = test::complex_app()
-        .get_matches_from_safe(vec!["clap-test", "subcmd", "--help"]);
+    let m = test::complex_app().get_matches_from_safe(vec!["clap-test", "subcmd", "--help"]);
 
     assert!(m.is_err());
     assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
@@ -296,8 +294,7 @@ fn subcommand_long_help() {
 
 #[test]
 fn subcommand_help_rev() {
-    let m = test::complex_app()
-        .get_matches_from_safe(vec!["clap-test", "help", "subcmd"]);
+    let m = test::complex_app().get_matches_from_safe(vec!["clap-test", "help", "subcmd"]);
 
     assert!(m.is_err());
     assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
@@ -321,12 +318,11 @@ fn after_and_before_help_output() {
 #[test]
 fn multi_level_sc_help() {
     let app = App::new("ctest")
-        .subcommand(SubCommand::with_name("subcmd")
-            .subcommand(SubCommand::with_name("multi")
-                .about("tests subcommands")
-                .author("Kevin K. <kbknapp@gmail.com>")
-                .version("0.1")
-                .args_from_usage("
+        .subcommand(SubCommand::with_name("subcmd").subcommand(SubCommand::with_name("multi")
+            .about("tests subcommands")
+            .author("Kevin K. <kbknapp@gmail.com>")
+            .version("0.1")
+            .args_from_usage("
                     -f, --flag                    'tests flags'
                     -o, --option [scoption]...    'tests options'
                 ")));
@@ -354,16 +350,16 @@ fn issue_626_unicode_cutoff() {
         .version("0.1")
         .set_term_width(70)
         .arg(Arg::with_name("cafe")
-           .short("c")
-           .long("cafe")
-           .value_name("FILE")
-           .help("A coffeehouse, coffee shop, or café is an establishment \
+            .short("c")
+            .long("cafe")
+            .value_name("FILE")
+            .help("A coffeehouse, coffee shop, or café is an establishment \
            which primarily serves hot coffee, related coffee beverages \
            (e.g., café latte, cappuccino, espresso), tea, and other hot \
            beverages. Some coffeehouses also serve cold beverages such as \
            iced coffee and iced tea. Many cafés also serve some type of \
            food, such as light snacks, muffins, or pastries.")
-           .takes_value(true));
+            .takes_value(true));
     assert!(test::compare_output(app, "ctest --help", ISSUE_626_CUTOFF, false));
 }
 
@@ -372,20 +368,20 @@ fn hide_possible_vals() {
     let app = App::new("ctest")
         .version("0.1")
         .arg(Arg::with_name("pos")
-           .short("p")
-           .long("pos")
-           .value_name("VAL")
-           .possible_values(&["fast", "slow"])
-           .help("Some vals")
-           .takes_value(true))
+            .short("p")
+            .long("pos")
+            .value_name("VAL")
+            .possible_values(&["fast", "slow"])
+            .help("Some vals")
+            .takes_value(true))
         .arg(Arg::with_name("cafe")
-           .short("c")
-           .long("cafe")
-           .value_name("FILE")
-           .hide_possible_values(true)
-           .possible_values(&["fast", "slow"])
-           .help("A coffeehouse, coffee shop, or café.")
-           .takes_value(true));
+            .short("c")
+            .long("cafe")
+            .value_name("FILE")
+            .hide_possible_values(true)
+            .possible_values(&["fast", "slow"])
+            .help("A coffeehouse, coffee shop, or café.")
+            .takes_value(true));
     assert!(test::compare_output(app, "ctest --help", HIDE_POS_VALS, false));
 }
 
@@ -441,9 +437,9 @@ fn old_newline_chars() {
 
 #[test]
 fn issue_688_hidden_pos_vals() {
-	let filter_values = ["Nearest", "Linear", "Cubic", "Gaussian", "Lanczos3"];
+    let filter_values = ["Nearest", "Linear", "Cubic", "Gaussian", "Lanczos3"];
 
-	let app1 = App::new("ctest")
+    let app1 = App::new("ctest")
             .version("0.1")
 			.set_term_width(120)
 			.setting(AppSettings::HidePossibleValuesInHelp)
@@ -455,7 +451,7 @@ fn issue_688_hidden_pos_vals() {
 				.takes_value(true));
     assert!(test::compare_output(app1, "ctest --help", ISSUE_688, false));
 
-	let app2 = App::new("ctest")
+    let app2 = App::new("ctest")
             .version("0.1")
 			.set_term_width(120)
 			.arg(Arg::with_name("filter")
@@ -466,7 +462,7 @@ fn issue_688_hidden_pos_vals() {
 				.takes_value(true));
     assert!(test::compare_output(app2, "ctest --help", ISSUE_688, false));
 
-	let app3 = App::new("ctest")
+    let app3 = App::new("ctest")
             .version("0.1")
 			.set_term_width(120)
 			.arg(Arg::with_name("filter")
@@ -483,27 +479,26 @@ fn issue_702_multiple_values() {
         .version("1.0")
         .author("foo")
         .about("bar")
-        .arg(Arg::with_name("arg1")
-             .help("some option"))
+        .arg(Arg::with_name("arg1").help("some option"))
         .arg(Arg::with_name("arg2")
-             .multiple(true)
-             .help("some option"))
+            .multiple(true)
+            .help("some option"))
         .arg(Arg::with_name("some")
-             .help("some option")
-             .short("s")
-             .long("some")
-             .takes_value(true))
+            .help("some option")
+            .short("s")
+            .long("some")
+            .takes_value(true))
         .arg(Arg::with_name("other")
-             .help("some other option")
-             .short("o")
-             .long("other")
-             .takes_value(true))
+            .help("some other option")
+            .short("o")
+            .long("other")
+            .takes_value(true))
         .arg(Arg::with_name("label")
-             .help("a label")
-             .short("l")
-             .long("label")
-             .multiple(true)
-             .takes_value(true));
+            .help("a label")
+            .short("l")
+            .long("label")
+            .multiple(true)
+            .takes_value(true));
     assert!(test::compare_output(app, "myapp --help", ISSUE_702, false));
 }
 
@@ -512,17 +507,17 @@ fn issue_760() {
     let app = App::new("ctest")
         .version("0.1")
         .arg(Arg::with_name("option")
-             .help("tests options")
-             .short("o")
-             .long("option")
-             .takes_value(true)
-             .multiple(true)
-             .number_of_values(1))
+            .help("tests options")
+            .short("o")
+            .long("option")
+            .takes_value(true)
+            .multiple(true)
+            .number_of_values(1))
         .arg(Arg::with_name("opt")
-             .help("tests options")
-             .short("O")
-             .long("opt")
-             .takes_value(true));
+            .help("tests options")
+            .short("O")
+            .long("opt")
+            .takes_value(true));
     assert!(test::compare_output(app, "ctest --help", ISSUE_760, false));
 }
 #[test]
diff --git a/tests/macros.rs b/tests/macros.rs
index b835f807..cc25e1bf 100644
--- a/tests/macros.rs
+++ b/tests/macros.rs
@@ -106,8 +106,7 @@ fn quoted_arg_long_name() {
             (@arg scpositional: index(1) "tests positionals"))
     );
 
-    assert_eq!(app.p.long_list[2], "long-option-2");
-
-    let matches = app.get_matches_from_safe(vec!["bin_name", "value1", "value2", "--long-option-2"]).expect("Expected to successfully match the given args.");
+    let matches = app.get_matches_from_safe(vec!["bin_name", "value1", "value2", "--long-option-2"])
+        .expect("Expected to successfully match the given args.");
     assert!(matches.is_present("option2"));
 }
diff --git a/tests/require.rs b/tests/require.rs
index f8eb4105..31033ef3 100644
--- a/tests/require.rs
+++ b/tests/require.rs
@@ -18,7 +18,7 @@ static COND_REQ_IN_USAGE: &'static str = "error: The following required argument
     --output <output>
 
 USAGE:
-    test --target <target> --input <input> --output <output>
+    test --input <input> --output <output> --target <target>
 
 For more information try --help";
 
@@ -46,7 +46,7 @@ fn flag_required_2() {
 #[test]
 fn option_required() {
     let result = App::new("option_required")
-        .arg(Arg::from_usage("-f [flag] 'some flag'").requires("color"))
+        .arg(Arg::from_usage("-f [flag] 'some flag'").requires("c"))
         .arg(Arg::from_usage("-c [color] 'third flag'"))
         .get_matches_from_safe(vec!["", "-f", "val"]);
     assert!(result.is_err());
@@ -560,4 +560,4 @@ fn required_ifs_wrong_val_mult_fail() {
 
     assert!(res.is_err());
     assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
-}
\ No newline at end of file
+}
diff --git a/tests/unique_args.rs b/tests/unique_args.rs
index b8e65df0..87102487 100644
--- a/tests/unique_args.rs
+++ b/tests/unique_args.rs
@@ -2,30 +2,21 @@ extern crate clap;
 
 use clap::{App, Arg};
 
-
 #[test]
 #[should_panic]
 fn unique_arg_names() {
-    App::new("some").args(&[
-        Arg::with_name("arg").short("a"),
-        Arg::with_name("arg").short("b")
-    ]);
+    App::new("some").args(&[Arg::with_name("arg").short("a"), Arg::with_name("arg").short("b")]);
 }
 
 #[test]
 #[should_panic]
 fn unique_arg_shorts() {
-    App::new("some").args(&[
-        Arg::with_name("arg1").short("a"),
-        Arg::with_name("arg2").short("a")
-    ]);
+    App::new("some").args(&[Arg::with_name("arg1").short("a"), Arg::with_name("arg2").short("a")]);
 }
 
 #[test]
 #[should_panic]
 fn unique_arg_longs() {
-    App::new("some").args(&[
-        Arg::with_name("arg1").long("long"),
-        Arg::with_name("arg2").long("long")
-    ]);
+    App::new("some")
+        .args(&[Arg::with_name("arg1").long("long"), Arg::with_name("arg2").long("long")]);
 }