mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 06:12:40 +00:00
commit
7b08a0a583
27 changed files with 2474 additions and 1218 deletions
|
@ -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"]
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
754
benches/05_ripgrep.rs
Normal file
754
benches/05_ripgrep.rs
Normal file
|
@ -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())
|
||||
}
|
458
benches/06_rustup.rs
Normal file
458
benches/06_rustup.rs
Normal file
|
@ -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";
|
|
@ -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!("");
|
||||
|
|
|
@ -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))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
|
|
1079
src/app/parser.rs
1079
src/app/parser.rs
File diff suppressed because it is too large
Load diff
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)]>;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() }
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -41,6 +41,16 @@ impl<'n, 'e> Default for Valued<'n, 'e> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> Valued<'n, 'e> {
|
||||
pub fn fill_in(&mut self) {
|
||||
if let Some(ref vec) = self.val_names {
|
||||
if vec.len() > 1 {
|
||||
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();
|
||||
|
@ -49,11 +59,6 @@ impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Valued<'n, 'e> {
|
|||
v.num_vals = Some(vec.len() as u64);
|
||||
}
|
||||
}
|
||||
if let Some(ref vec) = a.v.val_names {
|
||||
if vec.len() > 1 {
|
||||
v.num_vals = Some(vec.len() as u64);
|
||||
}
|
||||
}
|
||||
v
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
252
src/macros.rs
252
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)))
|
||||
}};
|
||||
}
|
||||
|
|
19
tests/borrowed.rs
Normal file
19
tests/borrowed.rs
Normal file
|
@ -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());
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
"#;
|
||||
|
||||
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));
|
||||
}
|
||||
|
|
117
tests/help.rs
117
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]
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")]);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue