mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 06:12:40 +00:00
tests(Benches): adds real world benchmarks
This commit is contained in:
parent
0efa411963
commit
85a636d539
4 changed files with 1021 additions and 155 deletions
|
@ -29,7 +29,8 @@ clippy = { version = "~0.0.112", optional = true }
|
|||
atty = { version = "0.2.2", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
regex = "0.2"
|
||||
regex = "~0.1.80"
|
||||
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));
|
||||
}
|
||||
|
|
511
benches/05_ripgrep.rs
Normal file
511
benches/05_ripgrep.rs
Normal file
|
@ -0,0 +1,511 @@
|
|||
// 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"])); }
|
||||
|
||||
|
||||
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())
|
||||
}
|
453
benches/06_rustup.rs
Normal file
453
benches/06_rustup.rs
Normal file
|
@ -0,0 +1,453 @@
|
|||
// 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![""])); }
|
||||
|
||||
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";
|
Loading…
Reference in a new issue