summaryrefslogtreecommitdiffstats
path: root/third_party/rust/clap/benches
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/clap/benches')
-rw-r--r--third_party/rust/clap/benches/01_default.rs15
-rw-r--r--third_party/rust/clap/benches/02_simple.rs104
-rw-r--r--third_party/rust/clap/benches/03_complex.rs307
-rw-r--r--third_party/rust/clap/benches/04_new_help.rs223
-rw-r--r--third_party/rust/clap/benches/05_ripgrep.rs952
-rw-r--r--third_party/rust/clap/benches/06_rustup.rs412
6 files changed, 2013 insertions, 0 deletions
diff --git a/third_party/rust/clap/benches/01_default.rs b/third_party/rust/clap/benches/01_default.rs
new file mode 100644
index 0000000000..620b32b818
--- /dev/null
+++ b/third_party/rust/clap/benches/01_default.rs
@@ -0,0 +1,15 @@
+use clap::Command;
+use criterion::{criterion_group, criterion_main, Criterion};
+
+pub fn build_empty(c: &mut Criterion) {
+ c.bench_function("build_empty", |b| b.iter(|| Command::new("claptests")));
+}
+
+pub fn parse_empty(c: &mut Criterion) {
+ c.bench_function("parse_empty", |b| {
+ b.iter(|| Command::new("claptests").get_matches_from(vec![""]))
+ });
+}
+
+criterion_group!(benches, build_empty, parse_empty);
+criterion_main!(benches);
diff --git a/third_party/rust/clap/benches/02_simple.rs b/third_party/rust/clap/benches/02_simple.rs
new file mode 100644
index 0000000000..667d02f873
--- /dev/null
+++ b/third_party/rust/clap/benches/02_simple.rs
@@ -0,0 +1,104 @@
+use clap::{arg, Arg, Command};
+use criterion::{criterion_group, criterion_main, Criterion};
+
+macro_rules! create_app {
+ () => {{
+ Command::new("claptests")
+ .version("0.1")
+ .about("tests clap library")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .arg(arg!(-f --flag "tests flags"))
+ .arg(arg!(-o --option <opt> "tests options").required(false))
+ .arg(arg!([positional] "tests positional"))
+ }};
+}
+
+pub fn build_simple(c: &mut Criterion) {
+ c.bench_function("build_simple", |b| b.iter(|| create_app!()));
+}
+
+pub fn build_with_flag(c: &mut Criterion) {
+ c.bench_function("build_with_flag", |b| {
+ b.iter(|| Command::new("claptests").arg(arg!(-s --some "something")))
+ });
+}
+
+pub fn build_with_flag_ref(c: &mut Criterion) {
+ c.bench_function("build_with_flag_ref", |b| {
+ b.iter(|| {
+ let arg = arg!(-s --some "something");
+ Command::new("claptests").arg(&arg)
+ })
+ });
+}
+
+pub fn build_with_opt(c: &mut Criterion) {
+ c.bench_function("build_with_opt", |b| {
+ b.iter(|| Command::new("claptests").arg(arg!(-s --some <FILE> "something")))
+ });
+}
+
+pub fn build_with_opt_ref(c: &mut Criterion) {
+ c.bench_function("build_with_opt_ref", |b| {
+ b.iter(|| {
+ let arg = arg!(-s --some <FILE> "something");
+ Command::new("claptests").arg(&arg)
+ })
+ });
+}
+
+pub fn build_with_pos(c: &mut Criterion) {
+ c.bench_function("build_with_pos", |b| {
+ b.iter(|| Command::new("claptests").arg(Arg::new("some")))
+ });
+}
+
+pub fn build_with_pos_ref(c: &mut Criterion) {
+ c.bench_function("build_with_pos_ref", |b| {
+ b.iter(|| {
+ let arg = Arg::new("some");
+ Command::new("claptests").arg(&arg)
+ })
+ });
+}
+
+pub fn parse_simple_with_flag(c: &mut Criterion) {
+ c.bench_function("parse_simple_with_flag", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "-f"]))
+ });
+}
+
+pub fn parse_simple_with_opt(c: &mut Criterion) {
+ c.bench_function("parse_simple_with_opt", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "-o", "option1"]))
+ });
+}
+
+pub fn parse_simple_with_pos(c: &mut Criterion) {
+ c.bench_function("parse_simple_with_pos", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "arg1"]))
+ });
+}
+
+pub fn parse_simple_with_complex(c: &mut Criterion) {
+ c.bench_function("parse_simple_with_complex", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "-o", "option1", "-f", "arg1"]))
+ });
+}
+
+criterion_group!(
+ benches,
+ parse_simple_with_complex,
+ parse_simple_with_pos,
+ parse_simple_with_opt,
+ parse_simple_with_flag,
+ build_with_pos_ref,
+ build_with_pos,
+ build_with_opt_ref,
+ build_with_opt,
+ build_with_flag_ref,
+ build_with_flag,
+ build_simple
+);
+
+criterion_main!(benches);
diff --git a/third_party/rust/clap/benches/03_complex.rs b/third_party/rust/clap/benches/03_complex.rs
new file mode 100644
index 0000000000..3ac81bb15d
--- /dev/null
+++ b/third_party/rust/clap/benches/03_complex.rs
@@ -0,0 +1,307 @@
+use clap::{arg, Arg, Command};
+use criterion::{criterion_group, criterion_main, Criterion};
+
+static OPT3_VALS: [&str; 2] = ["fast", "slow"];
+static POS3_VALS: [&str; 2] = ["vi", "emacs"];
+
+macro_rules! create_app {
+ () => {{
+ Command::new("claptests")
+ .version("0.1")
+ .about("tests clap library")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .arg(arg!(-o --option <opt> ... "tests options").required(false))
+ .arg(arg!([positional] "tests positionals"))
+ .arg(arg!(-f --flag ... "tests flags").global(true))
+ .args(&[
+ arg!(flag2: -F "tests flags with exclusions")
+ .conflicts_with("flag")
+ .requires("option2"),
+ arg!(option2: --"long-option-2" <option2> "tests long options with exclusions")
+ .required(false)
+ .conflicts_with("option")
+ .requires("positional2"),
+ arg!([positional2] "tests positionals with exclusions"),
+ arg!(-O --Option <option3> "tests options with specific value sets")
+ .required(false)
+ .possible_values(OPT3_VALS),
+ arg!([positional3] ... "tests positionals with specific values")
+ .possible_values(POS3_VALS),
+ arg!(--multvals "Tests multiple values not mult occs").required(false).value_names(&["one", "two"]),
+ arg!(
+ --multvalsmo "Tests multiple values, not mult occs"
+ ).multiple_values(true).required(false).value_names(&["one", "two"]),
+ arg!(--minvals2 <minvals> ... "Tests 2 min vals").min_values(2).multiple_values(true).required(false),
+ arg!(--maxvals3 <maxvals> ... "Tests 3 max vals").max_values(3).multiple_values(true).required(false),
+ ])
+ .subcommand(
+ Command::new("subcmd")
+ .about("tests subcommands")
+ .version("0.1")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .arg(arg!(-o --option <scoption> ... "tests options").required(false))
+ .arg(arg!([scpositional] "tests positionals"))
+ )
+ }};
+}
+
+pub fn build_from_builder(c: &mut Criterion) {
+ c.bench_function("build_from_builder", |b| {
+ b.iter(|| {
+ Command::new("claptests")
+ .version("0.1")
+ .about("tests clap library")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .arg(
+ Arg::new("opt")
+ .help("tests options")
+ .short('o')
+ .long("option")
+ .takes_value(true)
+ .multiple_values(true)
+ .multiple_occurrences(true),
+ )
+ .arg(Arg::new("positional").help("tests positionals").index(1))
+ .arg(
+ Arg::new("flag")
+ .short('f')
+ .help("tests flags")
+ .long("flag")
+ .global(true)
+ .multiple_occurrences(true),
+ )
+ .arg(
+ Arg::new("flag2")
+ .short('F')
+ .help("tests flags with exclusions")
+ .conflicts_with("flag")
+ .requires("option2"),
+ )
+ .arg(
+ Arg::new("option2")
+ .help("tests long options with exclusions")
+ .conflicts_with("option")
+ .requires("positional2")
+ .takes_value(true)
+ .long("long-option-2"),
+ )
+ .arg(
+ Arg::new("positional2")
+ .index(3)
+ .help("tests positionals with exclusions"),
+ )
+ .arg(
+ Arg::new("option3")
+ .short('O')
+ .long("Option")
+ .takes_value(true)
+ .help("tests options with specific value sets")
+ .possible_values(OPT3_VALS),
+ )
+ .arg(
+ Arg::new("positional3")
+ .takes_value(true)
+ .multiple_values(true)
+ .multiple_occurrences(true)
+ .help("tests positionals with specific values")
+ .index(4)
+ .possible_values(POS3_VALS),
+ )
+ .arg(
+ Arg::new("multvals")
+ .long("multvals")
+ .help("Tests multiple values, not mult occs")
+ .value_names(&["one", "two"]),
+ )
+ .arg(
+ Arg::new("multvalsmo")
+ .long("multvalsmo")
+ .takes_value(true)
+ .multiple_values(true)
+ .multiple_occurrences(true)
+ .help("Tests multiple values, not mult occs")
+ .value_names(&["one", "two"]),
+ )
+ .arg(
+ Arg::new("minvals")
+ .long("minvals2")
+ .takes_value(true)
+ .multiple_values(true)
+ .multiple_occurrences(true)
+ .help("Tests 2 min vals")
+ .min_values(2),
+ )
+ .arg(
+ Arg::new("maxvals")
+ .long("maxvals3")
+ .takes_value(true)
+ .multiple_values(true)
+ .multiple_occurrences(true)
+ .help("Tests 3 max vals")
+ .max_values(3),
+ )
+ .subcommand(
+ Command::new("subcmd")
+ .about("tests subcommands")
+ .version("0.1")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .arg(
+ Arg::new("scoption")
+ .short('o')
+ .long("option")
+ .takes_value(true)
+ .multiple_values(true)
+ .multiple_occurrences(true)
+ .help("tests options"),
+ )
+ .arg(Arg::new("scpositional").index(1).help("tests positionals")),
+ )
+ })
+ });
+}
+
+pub fn parse_complex(c: &mut Criterion) {
+ c.bench_function("parse_complex", |b| {
+ b.iter(|| create_app!().get_matches_from(vec![""]))
+ });
+}
+
+pub fn parse_complex_with_flag(c: &mut Criterion) {
+ c.bench_function("parse_complex_with_flag", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "-f"]))
+ });
+}
+
+pub fn parse_complex_with_opt(c: &mut Criterion) {
+ c.bench_function("parse_complex_with_opt", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "-o", "option1"]))
+ });
+}
+
+pub fn parse_complex_with_pos(c: &mut Criterion) {
+ c.bench_function("parse_complex_with_pos", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "arg1"]))
+ });
+}
+
+pub fn parse_complex_with_sc(c: &mut Criterion) {
+ c.bench_function("parse_complex_with_sc", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "subcmd"]))
+ });
+}
+
+pub fn parse_complex_with_sc_flag(c: &mut Criterion) {
+ c.bench_function("parse_complex_with_sc_flag", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "subcmd", "-f"]))
+ });
+}
+
+pub fn parse_complex_with_sc_opt(c: &mut Criterion) {
+ c.bench_function("parse_complex_with_sc_opt", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "subcmd", "-o", "option1"]))
+ });
+}
+
+pub fn parse_complex_with_sc_pos(c: &mut Criterion) {
+ c.bench_function("parse_complex_with_sc_pos", |b| {
+ b.iter(|| create_app!().get_matches_from(vec!["myprog", "subcmd", "arg1"]))
+ });
+}
+
+pub fn parse_complex1(c: &mut Criterion) {
+ c.bench_function("parse_complex1", |b| {
+ b.iter(|| {
+ create_app!().get_matches_from(vec![
+ "myprog",
+ "-ff",
+ "-o",
+ "option1",
+ "arg1",
+ "-O",
+ "fast",
+ "arg2",
+ "--multvals",
+ "one",
+ "two",
+ "emacs",
+ ])
+ })
+ });
+}
+
+pub fn parse_complex2(c: &mut Criterion) {
+ c.bench_function("parse_complex2", |b| {
+ b.iter(|| {
+ create_app!().get_matches_from(vec![
+ "myprog",
+ "arg1",
+ "-f",
+ "arg2",
+ "--long-option-2",
+ "some",
+ "-O",
+ "slow",
+ "--multvalsmo",
+ "one",
+ "two",
+ "--minvals2",
+ "3",
+ "2",
+ "1",
+ ])
+ })
+ });
+}
+
+pub fn parse_args_negate_scs(c: &mut Criterion) {
+ c.bench_function("parse_args_negate_scs", |b| {
+ b.iter(|| {
+ create_app!()
+ .args_conflicts_with_subcommands(true)
+ .get_matches_from(vec![
+ "myprog",
+ "arg1",
+ "-f",
+ "arg2",
+ "--long-option-2",
+ "some",
+ "-O",
+ "slow",
+ "--multvalsmo",
+ "one",
+ "two",
+ "--minvals2",
+ "3",
+ "2",
+ "1",
+ ])
+ })
+ });
+}
+
+pub fn parse_complex_with_sc_complex(c: &mut Criterion) {
+ c.bench_function("parse_complex_with_sc_complex", |b| {
+ b.iter(|| {
+ create_app!().get_matches_from(vec!["myprog", "subcmd", "-f", "-o", "option1", "arg1"])
+ })
+ });
+}
+
+criterion_group!(
+ benches,
+ build_from_builder,
+ parse_complex,
+ parse_complex_with_flag,
+ parse_complex_with_opt,
+ parse_complex_with_pos,
+ parse_complex_with_sc,
+ parse_complex_with_sc_flag,
+ parse_complex_with_sc_opt,
+ parse_complex_with_sc_pos,
+ parse_complex1,
+ parse_complex2,
+ parse_args_negate_scs,
+ parse_complex_with_sc_complex
+);
+
+criterion_main!(benches);
diff --git a/third_party/rust/clap/benches/04_new_help.rs b/third_party/rust/clap/benches/04_new_help.rs
new file mode 100644
index 0000000000..83b14fb706
--- /dev/null
+++ b/third_party/rust/clap/benches/04_new_help.rs
@@ -0,0 +1,223 @@
+use clap::Command;
+use clap::{arg, Arg};
+use criterion::{criterion_group, criterion_main, Criterion};
+use std::io::Cursor;
+
+fn build_help(cmd: &mut Command) -> String {
+ let mut buf = Cursor::new(Vec::with_capacity(50));
+ cmd.write_help(&mut buf).unwrap();
+ let content = buf.into_inner();
+ String::from_utf8(content).unwrap()
+}
+
+fn app_example1<'c>() -> Command<'c> {
+ Command::new("MyApp")
+ .version("1.0")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .about("Does awesome things")
+ .arg(
+ arg!(
+ -c --config <FILE> "Sets a custom config file"
+ )
+ .required(false),
+ )
+ .arg(arg!(<output> "Sets an optional output file"))
+ .arg(arg!(d: -d ... "Turn debugging information on"))
+ .subcommand(
+ Command::new("test")
+ .about("does testing things")
+ .arg(arg!(-l --list "lists test values")),
+ )
+}
+
+fn app_example2<'c>() -> Command<'c> {
+ Command::new("MyApp")
+ .version("1.0")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .about("Does awesome things")
+}
+
+fn app_example3<'c>() -> Command<'c> {
+ Command::new("MyApp")
+ .arg(
+ Arg::new("debug")
+ .help("turn on debugging information")
+ .short('d'),
+ )
+ .args(&[
+ Arg::new("config")
+ .help("sets the config file to use")
+ .takes_value(true)
+ .short('c')
+ .long("config"),
+ Arg::new("input")
+ .help("the input file to use")
+ .required(true),
+ ])
+ .arg(arg!(--license "display the license file"))
+ .arg(arg!([output] "Supply an output file to use"))
+ .arg(
+ arg!(
+ -i --int <IFACE> "Set an interface to use"
+ )
+ .required(false),
+ )
+}
+
+fn app_example4<'c>() -> Command<'c> {
+ Command::new("MyApp")
+ .about("Parses an input file to do awesome things")
+ .version("1.0")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .arg(
+ Arg::new("debug")
+ .help("turn on debugging information")
+ .short('d')
+ .long("debug"),
+ )
+ .arg(
+ Arg::new("config")
+ .help("sets the config file to use")
+ .short('c')
+ .long("config"),
+ )
+ .arg(
+ Arg::new("input")
+ .help("the input file to use")
+ .index(1)
+ .required(true),
+ )
+}
+
+fn app_example5<'c>() -> Command<'c> {
+ Command::new("MyApp").arg(
+ Arg::new("awesome")
+ .help("turns up the awesome")
+ .short('a')
+ .long("awesome")
+ .multiple_occurrences(true),
+ )
+}
+
+fn app_example6<'c>() -> Command<'c> {
+ Command::new("MyApp")
+ .arg(
+ Arg::new("input")
+ .help("the input file to use")
+ .index(1)
+ .requires("config")
+ .required(true),
+ )
+ .arg(Arg::new("config").help("the config file to use").index(2))
+}
+
+fn app_example7<'c>() -> Command<'c> {
+ Command::new("MyApp")
+ .arg(Arg::new("config"))
+ .arg(Arg::new("output"))
+ .arg(
+ Arg::new("input")
+ .help("the input file to use")
+ .takes_value(true)
+ .multiple_values(true)
+ .multiple_occurrences(true)
+ .required(true)
+ .short('i')
+ .long("input")
+ .requires("config")
+ .conflicts_with("output"),
+ )
+}
+
+fn app_example8<'c>() -> Command<'c> {
+ Command::new("MyApp")
+ .arg(Arg::new("config"))
+ .arg(Arg::new("output"))
+ .arg(
+ Arg::new("input")
+ .help("the input file to use")
+ .takes_value(true)
+ .multiple_values(true)
+ .multiple_occurrences(true)
+ .required(true)
+ .short('i')
+ .long("input")
+ .requires("config")
+ .conflicts_with("output"),
+ )
+}
+
+fn app_example10<'c>() -> Command<'c> {
+ Command::new("myapp").about("does awesome things").arg(
+ Arg::new("CONFIG")
+ .help("The config file to use (default is \"config.json\")")
+ .short('c')
+ .takes_value(true),
+ )
+}
+
+pub fn example1(c: &mut Criterion) {
+ let mut cmd = app_example1();
+ c.bench_function("example1", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn example2(c: &mut Criterion) {
+ let mut cmd = app_example2();
+ c.bench_function("example2", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn example3(c: &mut Criterion) {
+ let mut cmd = app_example3();
+ c.bench_function("example3", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn example4(c: &mut Criterion) {
+ let mut cmd = app_example4();
+ c.bench_function("example4", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn example5(c: &mut Criterion) {
+ let mut cmd = app_example5();
+ c.bench_function("example5", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn example6(c: &mut Criterion) {
+ let mut cmd = app_example6();
+ c.bench_function("example6", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn example7(c: &mut Criterion) {
+ let mut cmd = app_example7();
+ c.bench_function("example7", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn example8(c: &mut Criterion) {
+ let mut cmd = app_example8();
+ c.bench_function("example8", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn example10(c: &mut Criterion) {
+ let mut cmd = app_example10();
+ c.bench_function("example10", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn example4_template(c: &mut Criterion) {
+ let mut cmd = app_example4().help_template("{bin} {version}\n{author}\n{about}\n\nUSAGE:\n {usage}\n\nOPTIONS:\n{options}\n\nARGS:\n{args}\n");
+ c.bench_function("example4_template", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+criterion_group!(
+ benches,
+ example1,
+ example2,
+ example3,
+ example4,
+ example5,
+ example6,
+ example7,
+ example8,
+ example10,
+ example4_template
+);
+
+criterion_main!(benches);
diff --git a/third_party/rust/clap/benches/05_ripgrep.rs b/third_party/rust/clap/benches/05_ripgrep.rs
new file mode 100644
index 0000000000..7d5cab6964
--- /dev/null
+++ b/third_party/rust/clap/benches/05_ripgrep.rs
@@ -0,0 +1,952 @@
+// Used to simulate a fairly large number of options/flags and parsing with thousands of positional
+// args
+//
+// CLI used is adapted from ripgrep 48a8a3a691220f9e5b2b08f4051abe8655ea7e8a
+
+use clap::{Arg, Command};
+use criterion::{criterion_group, criterion_main, Criterion};
+use std::collections::HashMap;
+use std::io::Cursor;
+
+use lazy_static::lazy_static;
+
+pub fn build_rg_with_short_help(c: &mut Criterion) {
+ c.bench_function("build_rg_with_short_help", |b| b.iter(app_short));
+}
+
+pub fn build_rg_with_long_help(c: &mut Criterion) {
+ c.bench_function("build_rg_with_long_help", |b| b.iter(app_long));
+}
+
+pub fn write_rg_short_help(c: &mut Criterion) {
+ let mut cmd = app_short();
+ c.bench_function("write_rg_short_help", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn write_rg_long_help(c: &mut Criterion) {
+ let mut cmd = app_long();
+ c.bench_function("write_rg_long_help", |b| b.iter(|| build_help(&mut cmd)));
+}
+
+pub fn parse_rg(c: &mut Criterion) {
+ c.bench_function("parse_rg", |b| {
+ b.iter(|| app_short().get_matches_from(vec!["rg", "pat"]))
+ });
+}
+
+pub fn parse_rg_with_complex(c: &mut Criterion) {
+ c.bench_function("parse_rg_with_complex", |b| {
+ b.iter(|| {
+ app_short().get_matches_from(vec![
+ "rg",
+ "pat",
+ "-cFlN",
+ "-pqr=some",
+ "--null",
+ "--no-filename",
+ "--no-messages",
+ "-SH",
+ "-C5",
+ "--follow",
+ "-e some",
+ ])
+ })
+ });
+}
+
+pub fn parse_rg_with_lots(c: &mut Criterion) {
+ c.bench_function("parse_rg_with_lots", |b| {
+ b.iter(|| {
+ app_short().get_matches_from(vec![
+ "rg", "pat", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
+ "some", "some", "some", "some", "some", "some",
+ ])
+ })
+ });
+}
+
+const ABOUT: &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: &str = "
+ rg [OPTIONS] <pattern> [<path> ...]
+ rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
+ rg [OPTIONS] --files [<path> ...]
+ rg [OPTIONS] --type-list";
+
+const TEMPLATE: &str = "\
+{bin} {version}
+{author}
+{about}
+
+USAGE:{usage}
+
+ARGS:
+{positionals}
+
+OPTIONS:
+{options}";
+
+/// Build a clap application with short help strings.
+fn app_short() -> Command<'static> {
+ cmd(false, |k| USAGES[k].short)
+}
+
+/// Build a clap application with long help strings.
+fn app_long() -> Command<'static> {
+ cmd(true, |k| USAGES[k].long)
+}
+
+/// Build the help text of an application.
+fn build_help(cmd: &mut Command) -> String {
+ let mut buf = Cursor::new(Vec::with_capacity(50));
+ cmd.write_help(&mut buf).unwrap();
+ let content = buf.into_inner();
+ String::from_utf8(content).unwrap()
+}
+
+/// Build a clap application parameterized by usage strings.
+///
+/// The function given should take a clap argument name and return a help
+/// string. `cmd` 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 cmd<F>(_next_line_help: bool, doc: F) -> Command<'static>
+where
+ F: Fn(&'static str) -> &'static str,
+{
+ let arg = |name| Arg::new(name).help(doc(name));
+ let flag = |name| arg(name).long(name);
+
+ Command::new("ripgrep")
+ .author("BurntSushi") // simulating since it's only a bench
+ .version("0.4.0") // Simulating
+ .about(ABOUT)
+ .max_term_width(100)
+ .override_usage(USAGE)
+ .help_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_present_any(&[
+ "file",
+ "files",
+ "help-short",
+ "help",
+ "regexp",
+ "type-list",
+ "version",
+ ]))
+ .arg(
+ arg("path")
+ .takes_value(true)
+ .multiple_values(true)
+ .multiple_occurrences(true),
+ )
+ .arg(
+ flag("regexp")
+ .short('e')
+ .allow_hyphen_values(true)
+ .multiple_occurrences(true)
+ .takes_value(true)
+ .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")
+ .multiple_occurrences(true)
+ .takes_value(true),
+ )
+ .arg(flag("fixed-strings").short('F'))
+ .arg(
+ flag("glob")
+ .short('g')
+ .multiple_occurrences(true)
+ .takes_value(true)
+ .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')
+ .multiple_occurrences(true)
+ .takes_value(true)
+ .value_name("TYPE"),
+ )
+ .arg(
+ flag("type-not")
+ .short('T')
+ .multiple_occurrences(true)
+ .takes_value(true)
+ .value_name("TYPE"),
+ )
+ .arg(flag("unrestricted").short('u').multiple_occurrences(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")
+ .validator(validate_number),
+ )
+ .arg(
+ flag("before-context")
+ .short('B')
+ .value_name("NUM")
+ .validator(validate_number),
+ )
+ .arg(
+ flag("context")
+ .short('C')
+ .value_name("NUM")
+ .validator(validate_number),
+ )
+ .arg(flag("column"))
+ .arg(flag("context-separator").value_name("SEPARATOR"))
+ .arg(flag("debug"))
+ .arg(
+ flag("file")
+ .short('f')
+ .value_name("FILE")
+ .multiple_occurrences(true),
+ )
+ .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")
+ .multiple_occurrences(true),
+ )
+ .arg(flag("follow").short('L'))
+ .arg(
+ flag("max-count")
+ .short('m')
+ .value_name("NUM")
+ .validator(validate_number),
+ )
+ .arg(
+ flag("maxdepth")
+ .value_name("NUM")
+ .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"))
+ .arg(flag("pretty").short('p'))
+ .arg(flag("replace").short('r').value_name("ARG"))
+ .arg(flag("case-sensitive").short('s'))
+ .arg(flag("smart-case").short('S'))
+ .arg(flag("sort-files"))
+ .arg(
+ flag("threads")
+ .short('j')
+ .value_name("ARG")
+ .validator(validate_number),
+ )
+ .arg(flag("vimgrep"))
+ .arg(
+ flag("type-add")
+ .value_name("TYPE")
+ .multiple_occurrences(true),
+ )
+ .arg(
+ flag("type-clear")
+ .value_name("TYPE")
+ .multiple_occurrences(true),
+ )
+}
+
+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", "Print 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: &str) -> Result<(), String> {
+ s.parse::<usize>()
+ .map(|_| ())
+ .map_err(|err| err.to_string())
+}
+
+criterion_group!(
+ benches,
+ build_rg_with_short_help,
+ build_rg_with_long_help,
+ write_rg_short_help,
+ write_rg_long_help,
+ parse_rg,
+ parse_rg_with_complex,
+ parse_rg_with_lots
+);
+criterion_main!(benches);
diff --git a/third_party/rust/clap/benches/06_rustup.rs b/third_party/rust/clap/benches/06_rustup.rs
new file mode 100644
index 0000000000..8d9c406e40
--- /dev/null
+++ b/third_party/rust/clap/benches/06_rustup.rs
@@ -0,0 +1,412 @@
+// Used to simulate a fairly large number of subcommands
+//
+// CLI used is from rustup 408ed84f0e50511ed44a405dd91365e5da588790
+
+use clap::{AppSettings, Arg, ArgGroup, Command};
+use criterion::{criterion_group, criterion_main, Criterion};
+
+pub fn build_rustup(c: &mut Criterion) {
+ c.bench_function("build_rustup", |b| b.iter(build_cli));
+}
+
+pub fn parse_rustup(c: &mut Criterion) {
+ c.bench_function("parse_rustup", |b| {
+ b.iter(|| build_cli().get_matches_from(vec![""]))
+ });
+}
+
+pub fn parse_rustup_with_sc(c: &mut Criterion) {
+ c.bench_function("parse_rustup_with_sc", |b| {
+ b.iter(|| build_cli().get_matches_from(vec!["rustup override add stable"]))
+ });
+}
+
+fn build_cli() -> Command<'static> {
+ Command::new("rustup")
+ .version("0.9.0") // Simulating
+ .about("The Rust toolchain installer")
+ .after_help(RUSTUP_HELP)
+ .setting(AppSettings::DeriveDisplayOrder)
+ // .setting(AppSettings::SubcommandRequiredElseHelp)
+ .arg(
+ Arg::new("verbose")
+ .help("Enable verbose output")
+ .short('v')
+ .long("verbose"),
+ )
+ .subcommand(
+ Command::new("show")
+ .about("Show the active and installed toolchains")
+ .after_help(SHOW_HELP),
+ )
+ .subcommand(
+ Command::new("install")
+ .about("Update Rust toolchains")
+ .after_help(TOOLCHAIN_INSTALL_HELP)
+ .hide(true) // synonym for 'toolchain install'
+ .arg(Arg::new("toolchain").required(true)),
+ )
+ .subcommand(
+ Command::new("update")
+ .about("Update Rust toolchains")
+ .after_help(UPDATE_HELP)
+ .arg(Arg::new("toolchain").required(true))
+ .arg(
+ Arg::new("no-self-update")
+ .help("Don't perform self update when running the `rustup` command")
+ .long("no-self-update")
+ .hide(true),
+ ),
+ )
+ .subcommand(
+ Command::new("default")
+ .about("Set the default toolchain")
+ .after_help(DEFAULT_HELP)
+ .arg(Arg::new("toolchain").required(true)),
+ )
+ .subcommand(
+ Command::new("toolchain")
+ .about("Modify or query the installed toolchains")
+ .after_help(TOOLCHAIN_HELP)
+ .setting(AppSettings::DeriveDisplayOrder)
+ // .setting(AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(Command::new("list").about("List installed toolchains"))
+ .subcommand(
+ Command::new("install")
+ .about("Install or update a given toolchain")
+ .arg(Arg::new("toolchain").required(true)),
+ )
+ .subcommand(
+ Command::new("uninstall")
+ .about("Uninstall a toolchain")
+ .arg(Arg::new("toolchain").required(true)),
+ )
+ .subcommand(
+ Command::new("link")
+ .about("Create a custom toolchain by symlinking to a directory")
+ .arg(Arg::new("toolchain").required(true))
+ .arg(Arg::new("path").required(true)),
+ )
+ .subcommand(
+ Command::new("update")
+ .hide(true) // synonym for 'install'
+ .arg(Arg::new("toolchain").required(true)),
+ )
+ .subcommand(
+ Command::new("add")
+ .hide(true) // synonym for 'install'
+ .arg(Arg::new("toolchain").required(true)),
+ )
+ .subcommand(
+ Command::new("remove")
+ .hide(true) // synonym for 'uninstall'
+ .arg(Arg::new("toolchain").required(true)),
+ ),
+ )
+ .subcommand(
+ Command::new("target")
+ .about("Modify a toolchain's supported targets")
+ .setting(AppSettings::DeriveDisplayOrder)
+ // .setting(AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(
+ Command::new("list")
+ .about("List installed and available targets")
+ .arg(Arg::new("toolchain").long("toolchain").takes_value(true)),
+ )
+ .subcommand(
+ Command::new("add")
+ .about("Add a target to a Rust toolchain")
+ .arg(Arg::new("target").required(true))
+ .arg(Arg::new("toolchain").long("toolchain").takes_value(true)),
+ )
+ .subcommand(
+ Command::new("remove")
+ .about("Remove a target from a Rust toolchain")
+ .arg(Arg::new("target").required(true))
+ .arg(Arg::new("toolchain").long("toolchain").takes_value(true)),
+ )
+ .subcommand(
+ Command::new("install")
+ .hide(true) // synonym for 'add'
+ .arg(Arg::new("target").required(true))
+ .arg(Arg::new("toolchain").long("toolchain").takes_value(true)),
+ )
+ .subcommand(
+ Command::new("uninstall")
+ .hide(true) // synonym for 'remove'
+ .arg(Arg::new("target").required(true))
+ .arg(Arg::new("toolchain").long("toolchain").takes_value(true)),
+ ),
+ )
+ .subcommand(
+ Command::new("component")
+ .about("Modify a toolchain's installed components")
+ .setting(AppSettings::DeriveDisplayOrder)
+ // .setting(AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(
+ Command::new("list")
+ .about("List installed and available components")
+ .arg(Arg::new("toolchain").long("toolchain").takes_value(true)),
+ )
+ .subcommand(
+ Command::new("add")
+ .about("Add a component to a Rust toolchain")
+ .arg(Arg::new("component").required(true))
+ .arg(Arg::new("toolchain").long("toolchain").takes_value(true))
+ .arg(Arg::new("target").long("target").takes_value(true)),
+ )
+ .subcommand(
+ Command::new("remove")
+ .about("Remove a component from a Rust toolchain")
+ .arg(Arg::new("component").required(true))
+ .arg(Arg::new("toolchain").long("toolchain").takes_value(true))
+ .arg(Arg::new("target").long("target").takes_value(true)),
+ ),
+ )
+ .subcommand(
+ Command::new("override")
+ .about("Modify directory toolchain overrides")
+ .after_help(OVERRIDE_HELP)
+ .setting(AppSettings::DeriveDisplayOrder)
+ // .setting(AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(Command::new("list").about("List directory toolchain overrides"))
+ .subcommand(
+ Command::new("set")
+ .about("Set the override toolchain for a directory")
+ .arg(Arg::new("toolchain").required(true)),
+ )
+ .subcommand(
+ Command::new("unset")
+ .about("Remove the override toolchain for a directory")
+ .after_help(OVERRIDE_UNSET_HELP)
+ .arg(
+ Arg::new("path")
+ .long("path")
+ .takes_value(true)
+ .help("Path to the directory"),
+ )
+ .arg(
+ Arg::new("nonexistent")
+ .long("nonexistent")
+ .help("Remove override toolchain for all nonexistent directories"),
+ ),
+ )
+ .subcommand(
+ Command::new("add")
+ .hide(true) // synonym for 'set'
+ .arg(Arg::new("toolchain").required(true)),
+ )
+ .subcommand(
+ Command::new("remove")
+ .hide(true) // synonym for 'unset'
+ .about("Remove the override toolchain for a directory")
+ .arg(Arg::new("path").long("path").takes_value(true))
+ .arg(
+ Arg::new("nonexistent")
+ .long("nonexistent")
+ .help("Remove override toolchain for all nonexistent directories"),
+ ),
+ ),
+ )
+ .subcommand(
+ Command::new("run")
+ .about("Run a command with an environment configured for a given toolchain")
+ .after_help(RUN_HELP)
+ .trailing_var_arg(true)
+ .arg(Arg::new("toolchain").required(true))
+ .arg(
+ Arg::new("command")
+ .required(true)
+ .takes_value(true)
+ .multiple_values(true)
+ .multiple_occurrences(true),
+ ),
+ )
+ .subcommand(
+ Command::new("which")
+ .about("Display which binary will be run for a given command")
+ .arg(Arg::new("command").required(true)),
+ )
+ .subcommand(
+ Command::new("doc")
+ .about("Open the documentation for the current toolchain")
+ .after_help(DOC_HELP)
+ .arg(
+ Arg::new("book")
+ .long("book")
+ .help("The Rust Programming Language book"),
+ )
+ .arg(
+ Arg::new("std")
+ .long("std")
+ .help("Standard library API documentation"),
+ )
+ .group(ArgGroup::new("page").args(&["book", "std"])),
+ )
+ .subcommand(
+ Command::new("man")
+ .about("View the man page for a given command")
+ .arg(Arg::new("command").required(true))
+ .arg(Arg::new("toolchain").long("toolchain").takes_value(true)),
+ )
+ .subcommand(
+ Command::new("self")
+ .about("Modify the rustup installation")
+ .setting(AppSettings::DeriveDisplayOrder)
+ .subcommand(Command::new("update").about("Download and install updates to rustup"))
+ .subcommand(
+ Command::new("uninstall")
+ .about("Uninstall rustup.")
+ .arg(Arg::new("no-prompt").short('y')),
+ )
+ .subcommand(
+ Command::new("upgrade-data").about("Upgrade the internal data format."),
+ ),
+ )
+ .subcommand(
+ Command::new("telemetry")
+ .about("rustup telemetry commands")
+ .hide(true)
+ .setting(AppSettings::DeriveDisplayOrder)
+ .subcommand(Command::new("enable").about("Enable rustup telemetry"))
+ .subcommand(Command::new("disable").about("Disable rustup telemetry"))
+ .subcommand(Command::new("analyze").about("Analyze stored telemetry")),
+ )
+ .subcommand(
+ Command::new("set")
+ .about("Alter rustup settings")
+ .subcommand(
+ Command::new("default-host")
+ .about("The triple used to identify toolchains when not specified")
+ .arg(Arg::new("host_triple").required(true)),
+ ),
+ )
+}
+
+static RUSTUP_HELP: &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: &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: &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: &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: &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: &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: &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: &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: &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: &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.";
+
+criterion_group!(benches, build_rustup, parse_rustup, parse_rustup_with_sc);
+
+criterion_main!(benches);