mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +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 }
|
atty = { version = "0.2.2", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
regex = "0.2"
|
regex = "~0.1.80"
|
||||||
|
lazy_static = "~0.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["suggestions", "color", "wrap_help"]
|
default = ["suggestions", "color", "wrap_help"]
|
||||||
|
|
|
@ -39,17 +39,10 @@ fn app_example2<'b, 'c>() -> App<'b, 'c> {
|
||||||
|
|
||||||
fn app_example3<'b, 'c>() -> App<'b, 'c> {
|
fn app_example3<'b, 'c>() -> App<'b, 'c> {
|
||||||
App::new("MyApp")
|
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")
|
.arg(Arg::with_name("debug")
|
||||||
.help("turn on debugging information")
|
.help("turn on debugging information")
|
||||||
.short("d"))
|
.short("d"))
|
||||||
|
.args(&[Arg::with_name("config")
|
||||||
// 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("sets the config file to use")
|
.help("sets the config file to use")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.short("c")
|
.short("c")
|
||||||
|
@ -57,19 +50,8 @@ fn app_example3<'b, 'c>() -> App<'b, 'c> {
|
||||||
Arg::with_name("input")
|
Arg::with_name("input")
|
||||||
.help("the input file to use")
|
.help("the input file to use")
|
||||||
.index(1)
|
.index(1)
|
||||||
.required(true)
|
.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
|
|
||||||
.arg_from_usage("--license 'display the license file'")
|
.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'
|
.args_from_usage("[output] 'Supply an output file to use'
|
||||||
-i, --int=[IFACE] 'Set an interface to use'")
|
-i, --int=[IFACE] 'Set an interface to use'")
|
||||||
}
|
}
|
||||||
|
@ -94,119 +76,56 @@ fn app_example4<'b, 'c>() -> App<'b, 'c> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app_example5<'b, 'c>() -> App<'b, 'c> {
|
fn app_example5<'b, 'c>() -> App<'b, 'c> {
|
||||||
App::new("MyApp")
|
App::new("MyApp").arg(Arg::with_name("awesome")
|
||||||
// Regular App configuration goes here...
|
.help("turns up the awesome")
|
||||||
|
.short("a")
|
||||||
// We'll add a flag that represents an awesome meter...
|
.long("awesome")
|
||||||
//
|
.multiple(true)
|
||||||
// I'll explain each possible setting that "flags" accept. Keep in mind
|
.requires("config")
|
||||||
// that you DO NOT need to set each of these for every flag, only the ones
|
.conflicts_with("output"))
|
||||||
// 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>)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app_example6<'b, 'c>() -> App<'b, 'c> {
|
fn app_example6<'b, 'c>() -> App<'b, 'c> {
|
||||||
App::new("MyApp")
|
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")
|
.arg(Arg::with_name("input")
|
||||||
.help("the input file to use") // Displayed when showing help info
|
.help("the input file to use")
|
||||||
.index(1) // Set the order in which the user must
|
.index(1)
|
||||||
// specify this argument (Starts at 1)
|
.requires("config")
|
||||||
.requires("config") // Says, "If the user uses "input", they MUST
|
.conflicts_with("output")
|
||||||
// also use this other 'config' arg too"
|
.required(true))
|
||||||
// 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
|
|
||||||
)
|
|
||||||
.arg(Arg::with_name("config")
|
.arg(Arg::with_name("config")
|
||||||
.help("the config file to use")
|
.help("the config file to use")
|
||||||
.index(2)) // Note, we do not need to specify required(true)
|
.index(2))
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app_example7<'b, 'c>() -> App<'b, 'c> {
|
fn app_example7<'b, 'c>() -> App<'b, 'c> {
|
||||||
App::new("MyApp")
|
App::new("MyApp")
|
||||||
// Regular App configuration goes here...
|
.arg(Arg::with_name("config"))
|
||||||
|
.arg(Arg::with_name("output"))
|
||||||
// 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("input")
|
.arg(Arg::with_name("input")
|
||||||
.help("the input file to use") // Displayed when showing help info
|
.help("the input file to use")
|
||||||
.takes_value(true) // MUST be set to true in order to be an "option" argument
|
.takes_value(true)
|
||||||
.short("i") // This argument is triggered with "-i"
|
.short("i")
|
||||||
.long("input") // This argument is triggered with "--input"
|
.long("input")
|
||||||
.multiple(true) // Set to true if you wish to allow multiple occurrences
|
.multiple(true)
|
||||||
// such as "-i file -i other_file -i third_file"
|
.required(true)
|
||||||
.required(true) // By default this argument MUST be present
|
.requires("config")
|
||||||
// NOTE: mutual exclusions take precedence over
|
.conflicts_with("output"))
|
||||||
// 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>)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app_example8<'b, 'c>() -> App<'b, 'c> {
|
fn app_example8<'b, 'c>() -> App<'b, 'c> {
|
||||||
App::new("MyApp")
|
App::new("MyApp")
|
||||||
// Regular App configuration goes here...
|
.arg(Arg::with_name("config"))
|
||||||
|
.arg(Arg::with_name("output"))
|
||||||
// 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("input")
|
.arg(Arg::with_name("input")
|
||||||
.help("the input file to use") // Displayed when showing help info
|
.help("the input file to use")
|
||||||
.takes_value(true) // MUST be set to true in order to be an "option" argument
|
.takes_value(true)
|
||||||
.short("i") // This argument is triggered with "-i"
|
.short("i")
|
||||||
.long("input") // This argument is triggered with "--input"
|
.long("input")
|
||||||
.multiple(true) // Set to true if you wish to allow multiple occurrences
|
.multiple(true)
|
||||||
// such as "-i file -i other_file -i third_file"
|
.required(true)
|
||||||
.required(true) // By default this argument MUST be present
|
.requires("config")
|
||||||
// NOTE: mutual exclusions take precedence over
|
.conflicts_with("output"))
|
||||||
// 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>)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app_example10<'b, 'c>() -> App<'b, 'c> {
|
fn app_example10<'b, 'c>() -> App<'b, 'c> {
|
||||||
|
@ -274,24 +193,6 @@ fn example10(b: &mut Bencher) {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn example4_template(b: &mut Bencher) {
|
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");
|
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));
|
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