1// Used to simulate a fairly large number of options/flags and parsing with thousands of positional
2// args
3//
4// CLI used is adapted from ripgrep 48a8a3a691220f9e5b2b08f4051abe8655ea7e8a
5
6use clap::{value_parser, Arg, ArgAction, Command};
7use criterion::{criterion_group, criterion_main, Criterion};
8use std::collections::HashMap;
9
10use lazy_static::lazy_static;
11
12pub fn build_rg_with_short_help(c: &mut Criterion) {
13    c.bench_function("build_rg_with_short_help", |b| b.iter(app_short));
14}
15
16pub fn build_rg_with_long_help(c: &mut Criterion) {
17    c.bench_function("build_rg_with_long_help", |b| b.iter(app_long));
18}
19
20pub fn write_rg_short_help(c: &mut Criterion) {
21    let mut cmd = app_short();
22    c.bench_function("write_rg_short_help", |b| b.iter(|| build_help(&mut cmd)));
23}
24
25pub fn write_rg_long_help(c: &mut Criterion) {
26    let mut cmd = app_long();
27    c.bench_function("write_rg_long_help", |b| b.iter(|| build_help(&mut cmd)));
28}
29
30pub fn parse_rg(c: &mut Criterion) {
31    c.bench_function("parse_rg", |b| {
32        b.iter(|| app_short().get_matches_from(vec!["rg", "pat"]))
33    });
34}
35
36pub fn parse_rg_with_complex(c: &mut Criterion) {
37    c.bench_function("parse_rg_with_complex", |b| {
38        b.iter(|| {
39            app_short().get_matches_from(vec![
40                "rg",
41                "pat",
42                "-cFlN",
43                "-pqr=some",
44                "--null",
45                "--no-filename",
46                "--no-messages",
47                "-SH",
48                "-C5",
49                "--follow",
50                "-e some",
51            ])
52        })
53    });
54}
55
56pub fn parse_rg_with_lots(c: &mut Criterion) {
57    c.bench_function("parse_rg_with_lots", |b| {
58        b.iter(|| {
59            app_short().get_matches_from(vec![
60                "rg", "pat", "some", "some", "some", "some", "some", "some", "some", "some",
61                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
62                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
63                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
64                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
65                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
66                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
67                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
68                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
69                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
70                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
71                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
72                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
73                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
74                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
75                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
76                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
77                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
78                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
79                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
80                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
81                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
82                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
83                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
84                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
85                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
86                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
87                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
88                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
89                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
90                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
91                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
92                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
93                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
94                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
95                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
96                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
97                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
98                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
99                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
100                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
101                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
102                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
103                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
104                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
105                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
106                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
107                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
108                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
109                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
110                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
111                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
112                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
113                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
114                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
115                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
116                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
117                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
118                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
119                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
120                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
121                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
122                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
123                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
124                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
125                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
126                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
127                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
128                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
129                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
130                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
131                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
132                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
133                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
134                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
135                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
136                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
137                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
138                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
139                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
140                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
141                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
142                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
143                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
144                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
145                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
146                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
147                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
148                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
149                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
150                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
151                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
152                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
153                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
154                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
155                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
156                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
157                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
158                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
159                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
160                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
161                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
162                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
163                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
164                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
165                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
166                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
167                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
168                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
169                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
170                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
171                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
172                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
173                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
174                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
175                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
176                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
177                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
178                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
179                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
180                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
181                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
182                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
183                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
184                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
185                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
186                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
187                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
188                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
189                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
190                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
191                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
192                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
193                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
194                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
195                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
196                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
197                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
198                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
199                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
200                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
201                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
202                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
203                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
204                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
205                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
206                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
207                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
208                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
209                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
210                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
211                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
212                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
213                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
214                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
215                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
216                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
217                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
218                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
219                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
220                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
221                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
222                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
223                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
224                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
225                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
226                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
227                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
228                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
229                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
230                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
231                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
232                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
233                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
234                "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
235                "some", "some", "some", "some", "some", "some",
236            ])
237        })
238    });
239}
240
241const ABOUT: &str = "
242ripgrep (rg) recursively searches your current directory for a regex pattern.
243
244ripgrep's regex engine uses finite automata and guarantees linear time
245searching. Because of this, features like backreferences and arbitrary
246lookaround are not supported.
247
248Project home page: https://github.com/BurntSushi/ripgrep
249
250Use -h for short descriptions and --help for more details.";
251
252const USAGE: &str = "
253    rg [OPTIONS] <pattern> [<path> ...]
254    rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
255    rg [OPTIONS] --files [<path> ...]
256    rg [OPTIONS] --type-list";
257
258const TEMPLATE: &str = "\
259{name} {version}
260{author}
261{about}
262
263USAGE:{usage}
264
265ARGS:
266{positionals}
267
268OPTIONS:
269{options}";
270
271/// Build a clap application with short help strings.
272fn app_short() -> Command {
273    cmd(false, |k| USAGES[k].short)
274}
275
276/// Build a clap application with long help strings.
277fn app_long() -> Command {
278    cmd(true, |k| USAGES[k].long)
279}
280
281/// Build the help text of an application.
282fn build_help(cmd: &mut Command) -> String {
283    let help = cmd.render_help();
284    help.to_string()
285}
286
287/// Build a clap application parameterized by usage strings.
288///
289/// The function given should take a clap argument name and return a help
290/// string. `cmd` will panic if a usage string is not defined.
291///
292/// This is an intentionally stand-alone module so that it can be used easily
293/// in a `build.rs` script to build shell completion files.
294fn cmd<F>(_next_line_help: bool, doc: F) -> Command
295where
296    F: Fn(&'static str) -> &'static str,
297{
298    let arg = |name| Arg::new(name).help(doc(name));
299    let flag = |name| arg(name).long(name).action(ArgAction::SetTrue);
300
301    Command::new("ripgrep")
302        .author("BurntSushi") // simulating since it's only a bench
303        .version("0.4.0") // Simulating
304        .about(ABOUT)
305        .max_term_width(100)
306        .override_usage(USAGE)
307        .help_template(TEMPLATE)
308        // Handle help/version manually to make their output formatting
309        // consistent with short/long views.
310        .disable_help_flag(true)
311        .disable_version_flag(true)
312        .arg(arg("help-short").short('h'))
313        .arg(flag("help"))
314        .arg(flag("version").short('V'))
315        // First, set up primary positional/flag arguments.
316        .arg(arg("pattern").required_unless_present_any([
317            "file",
318            "files",
319            "help-short",
320            "help",
321            "regexp",
322            "type-list",
323            "version",
324        ]))
325        .arg(arg("path").num_args(1..))
326        .arg(
327            flag("regexp")
328                .short('e')
329                .allow_hyphen_values(true)
330                .action(ArgAction::Append)
331                .value_name("pattern"),
332        )
333        .arg(
334            flag("files")
335                // This should also conflict with `pattern`, but the first file
336                // path will actually be in `pattern`.
337                .conflicts_with_all(["file", "regexp", "type-list"]),
338        )
339        .arg(flag("type-list").conflicts_with_all(["file", "files", "pattern", "regexp"]))
340        // Second, set up common flags.
341        .arg(flag("text").short('a'))
342        .arg(flag("count").short('c'))
343        .arg(
344            flag("color")
345                .value_name("WHEN")
346                .action(ArgAction::Set)
347                .hide_possible_values(true)
348                .value_parser(["never", "auto", "always", "ansi"]),
349        )
350        .arg(flag("colors").value_name("SPEC").action(ArgAction::Append))
351        .arg(flag("fixed-strings").short('F'))
352        .arg(
353            flag("glob")
354                .short('g')
355                .action(ArgAction::Append)
356                .value_name("GLOB"),
357        )
358        .arg(flag("ignore-case").short('i'))
359        .arg(flag("line-number").short('n'))
360        .arg(flag("no-line-number").short('N'))
361        .arg(flag("quiet").short('q'))
362        .arg(
363            flag("type")
364                .short('t')
365                .action(ArgAction::Append)
366                .value_name("TYPE"),
367        )
368        .arg(
369            flag("type-not")
370                .short('T')
371                .action(ArgAction::Append)
372                .value_name("TYPE"),
373        )
374        .arg(flag("unrestricted").short('u').action(ArgAction::Append))
375        .arg(flag("invert-match").short('v'))
376        .arg(flag("word-regexp").short('w'))
377        // Third, set up less common flags.
378        .arg(
379            flag("after-context")
380                .short('A')
381                .action(ArgAction::Set)
382                .value_name("NUM")
383                .value_parser(value_parser!(usize)),
384        )
385        .arg(
386            flag("before-context")
387                .short('B')
388                .action(ArgAction::Set)
389                .value_name("NUM")
390                .value_parser(value_parser!(usize)),
391        )
392        .arg(
393            flag("context")
394                .short('C')
395                .action(ArgAction::Set)
396                .value_name("NUM")
397                .value_parser(value_parser!(usize)),
398        )
399        .arg(flag("column"))
400        .arg(flag("context-separator").value_name("SEPARATOR"))
401        .arg(flag("debug"))
402        .arg(
403            flag("file")
404                .short('f')
405                .value_name("FILE")
406                .action(ArgAction::Append),
407        )
408        .arg(flag("files-with-matches").short('l'))
409        .arg(flag("files-without-match"))
410        .arg(flag("with-filename").short('H'))
411        .arg(flag("no-filename"))
412        .arg(flag("heading").overrides_with("no-heading"))
413        .arg(flag("no-heading").overrides_with("heading"))
414        .arg(flag("hidden"))
415        .arg(
416            flag("ignore-file")
417                .value_name("FILE")
418                .action(ArgAction::Append),
419        )
420        .arg(flag("follow").short('L'))
421        .arg(
422            flag("max-count")
423                .short('m')
424                .action(ArgAction::Set)
425                .value_name("NUM")
426                .value_parser(value_parser!(usize)),
427        )
428        .arg(
429            flag("maxdepth")
430                .action(ArgAction::Set)
431                .value_name("NUM")
432                .value_parser(value_parser!(usize)),
433        )
434        .arg(flag("mmap"))
435        .arg(flag("no-messages"))
436        .arg(flag("no-mmap"))
437        .arg(flag("no-ignore"))
438        .arg(flag("no-ignore-parent"))
439        .arg(flag("no-ignore-vcs"))
440        .arg(flag("null"))
441        .arg(flag("path-separator").value_name("SEPARATOR"))
442        .arg(flag("pretty").short('p'))
443        .arg(
444            flag("replace")
445                .short('r')
446                .action(ArgAction::Set)
447                .value_name("ARG"),
448        )
449        .arg(flag("case-sensitive").short('s'))
450        .arg(flag("smart-case").short('S'))
451        .arg(flag("sort-files"))
452        .arg(
453            flag("threads")
454                .short('j')
455                .action(ArgAction::Set)
456                .value_name("ARG")
457                .value_parser(value_parser!(usize)),
458        )
459        .arg(flag("vimgrep"))
460        .arg(
461            flag("type-add")
462                .value_name("TYPE")
463                .action(ArgAction::Append),
464        )
465        .arg(
466            flag("type-clear")
467                .value_name("TYPE")
468                .action(ArgAction::Append),
469        )
470}
471
472struct Usage {
473    short: &'static str,
474    long: &'static str,
475}
476
477macro_rules! doc {
478    ($map:expr, $name:expr, $short:expr) => {
479        doc!($map, $name, $short, $short)
480    };
481    ($map:expr, $name:expr, $short:expr, $long:expr) => {
482        $map.insert(
483            $name,
484            Usage {
485                short: $short,
486                long: concat!($long, "\n "),
487            },
488        );
489    };
490}
491
492lazy_static! {
493    static ref USAGES: HashMap<&'static str, Usage> = {
494        let mut h = HashMap::new();
495        doc!(
496            h,
497            "help-short",
498            "Show short help output.",
499            "Show short help output. Use --help to show more details."
500        );
501        doc!(
502            h,
503            "help",
504            "Show verbose help output.",
505            "When given, more details about flags are provided."
506        );
507        doc!(h, "version", "Print version information.");
508
509        doc!(
510            h,
511            "pattern",
512            "A regular expression used for searching.",
513            "A regular expression used for searching. Multiple patterns \
514             may be given. To match a pattern beginning with a -, use [-]."
515        );
516        doc!(
517            h,
518            "regexp",
519            "A regular expression used for searching.",
520            "A regular expression used for searching. Multiple patterns \
521             may be given. To match a pattern beginning with a -, use [-]."
522        );
523        doc!(
524            h,
525            "path",
526            "A file or directory to search.",
527            "A file or directory to search. Directories are searched \
528             recursively."
529        );
530        doc!(
531            h,
532            "files",
533            "Print each file that would be searched.",
534            "Print each file that would be searched without actually \
535             performing the search. This is useful to determine whether a \
536             particular file is being searched or not."
537        );
538        doc!(
539            h,
540            "type-list",
541            "Show all supported file types.",
542            "Show all supported file types and their corresponding globs."
543        );
544
545        doc!(h, "text", "Search binary files as if they were text.");
546        doc!(h, "count", "Only show count of matches for each file.");
547        doc!(
548            h,
549            "color",
550            "When to use color. [default: auto]",
551            "When to use color in the output. The possible values are \
552             never, auto, always or ansi. The default is auto. When always \
553             is used, coloring is attempted based on your environment. When \
554             ansi used, coloring is forcefully done using ANSI escape color \
555             codes."
556        );
557        doc!(
558            h,
559            "colors",
560            "Configure color settings and styles.",
561            "This flag specifies color settings for use in the output. \
562             This flag may be provided multiple times. Settings are applied \
563             iteratively. Colors are limited to one of eight choices: \
564             red, blue, green, cyan, magenta, yellow, white and black. \
565             Styles are limited to nobold, bold, nointense or intense.\n\n\
566             The format of the flag is {type}:{attribute}:{value}. {type} \
567             should be one of path, line or match. {attribute} can be fg, bg \
568             or style. {value} is either a color (for fg and bg) or a text \
569             style. A special format, {type}:none, will clear all color \
570             settings for {type}.\n\nFor example, the following command will \
571             change the match color to magenta and the background color for \
572             line numbers to yellow:\n\n\
573             rg --colors 'match:fg:magenta' --colors 'line:bg:yellow' foo."
574        );
575        doc!(
576            h,
577            "fixed-strings",
578            "Treat the pattern as a literal string.",
579            "Treat the pattern as a literal string instead of a regular \
580             expression. When this flag is used, special regular expression \
581             meta characters such as (){}*+. do not need to be escaped."
582        );
583        doc!(
584            h,
585            "glob",
586            "Include or exclude files/directories.",
587            "Include or exclude files/directories for searching that \
588             match the given glob. This always overrides any other \
589             ignore logic. Multiple glob flags may be used. Globbing \
590             rules match .gitignore globs. Precede a glob with a ! \
591             to exclude it."
592        );
593        doc!(
594            h,
595            "ignore-case",
596            "Case insensitive search.",
597            "Case insensitive search. This is overridden by \
598             --case-sensitive."
599        );
600        doc!(
601            h,
602            "line-number",
603            "Show line numbers.",
604            "Show line numbers (1-based). This is enabled by default when \
605             searching in a tty."
606        );
607        doc!(
608            h,
609            "no-line-number",
610            "Suppress line numbers.",
611            "Suppress line numbers. This is enabled by default when NOT \
612             searching in a tty."
613        );
614        doc!(
615            h,
616            "quiet",
617            "Do not print anything to stdout.",
618            "Do not print anything to stdout. If a match is found in a file, \
619             stop searching. This is useful when ripgrep is used only for \
620             its exit code."
621        );
622        doc!(
623            h,
624            "type",
625            "Only search files matching TYPE.",
626            "Only search files matching TYPE. Multiple type flags may be \
627             provided. Use the --type-list flag to list all available \
628             types."
629        );
630        doc!(
631            h,
632            "type-not",
633            "Do not search files matching TYPE.",
634            "Do not search files matching TYPE. Multiple type-not flags may \
635             be provided. Use the --type-list flag to list all available \
636             types."
637        );
638        doc!(
639            h,
640            "unrestricted",
641            "Reduce the level of \"smart\" searching.",
642            "Reduce the level of \"smart\" searching. A single -u \
643             won't respect .gitignore (etc.) files. Two -u flags will \
644             additionally search hidden files and directories. Three \
645             -u flags will additionally search binary files. -uu is \
646             roughly equivalent to grep -r and -uuu is roughly \
647             equivalent to grep -a -r."
648        );
649        doc!(
650            h,
651            "invert-match",
652            "Invert matching.",
653            "Invert matching. Show lines that don't match given patterns."
654        );
655        doc!(
656            h,
657            "word-regexp",
658            "Only show matches surrounded by word boundaries.",
659            "Only show matches surrounded by word boundaries. This is \
660             equivalent to putting \\b before and after all of the search \
661             patterns."
662        );
663
664        doc!(h, "after-context", "Show NUM lines after each match.");
665        doc!(h, "before-context", "Show NUM lines before each match.");
666        doc!(h, "context", "Show NUM lines before and after each match.");
667        doc!(
668            h,
669            "column",
670            "Show column numbers",
671            "Show column numbers (1-based). This only shows the column \
672             numbers for the first match on each line. This does not try \
673             to account for Unicode. One byte is equal to one column. This \
674             implies --line-number."
675        );
676        doc!(
677            h,
678            "context-separator",
679            "Set the context separator string. [default: --]",
680            "The string used to separate non-contiguous context lines in the \
681             output. Escape sequences like \\x7F or \\t may be used. The \
682             default value is --."
683        );
684        doc!(
685            h,
686            "debug",
687            "Show debug messages.",
688            "Show debug messages. Please use this when filing a bug report."
689        );
690        doc!(
691            h,
692            "file",
693            "Search for patterns from the given file.",
694            "Search for patterns from the given file, with one pattern per \
695             line. When this flag is used or multiple times or in \
696             combination with the -e/--regexp flag, then all patterns \
697             provided are searched. Empty pattern lines will match all input \
698             lines, and the newline is not counted as part of the pattern."
699        );
700        doc!(
701            h,
702            "files-with-matches",
703            "Only show the path of each file with at least one match."
704        );
705        doc!(
706            h,
707            "files-without-match",
708            "Only show the path of each file that contains zero matches."
709        );
710        doc!(
711            h,
712            "with-filename",
713            "Show file name for each match.",
714            "Prefix each match with the file name that contains it. This is \
715             the default when more than one file is searched."
716        );
717        doc!(
718            h,
719            "no-filename",
720            "Never show the file name for a match.",
721            "Never show the file name for a match. This is the default when \
722             one file is searched."
723        );
724        doc!(
725            h,
726            "heading",
727            "Show matches grouped by each file.",
728            "This shows the file name above clusters of matches from each \
729             file instead of showing the file name for every match. This is \
730             the default mode at a tty."
731        );
732        doc!(
733            h,
734            "no-heading",
735            "Don't group matches by each file.",
736            "Don't group matches by each file. If -H/--with-filename is \
737             enabled, then file names will be shown for every line matched. \
738             This is the default mode when not at a tty."
739        );
740        doc!(
741            h,
742            "hidden",
743            "Search hidden files and directories.",
744            "Search hidden files and directories. By default, hidden files \
745             and directories are skipped."
746        );
747        doc!(
748            h,
749            "ignore-file",
750            "Specify additional ignore files.",
751            "Specify additional ignore files for filtering file paths. \
752             Ignore files should be in the gitignore format and are matched \
753             relative to the current working directory. These ignore files \
754             have lower precedence than all other ignore files. When \
755             specifying multiple ignore files, earlier files have lower \
756             precedence than later files."
757        );
758        doc!(h, "follow", "Follow symbolic links.");
759        doc!(
760            h,
761            "max-count",
762            "Limit the number of matches.",
763            "Limit the number of matching lines per file searched to NUM."
764        );
765        doc!(
766            h,
767            "maxdepth",
768            "Descend at most NUM directories.",
769            "Limit the depth of directory traversal to NUM levels beyond \
770             the paths given. A value of zero only searches the \
771             starting-points themselves.\n\nFor example, \
772             'rg --maxdepth 0 dir/' is a no-op because dir/ will not be \
773             descended into. 'rg --maxdepth 1 dir/' will search only the \
774             direct children of dir/."
775        );
776        doc!(
777            h,
778            "mmap",
779            "Searching using memory maps when possible.",
780            "Search using memory maps when possible. This is enabled by \
781             default when ripgrep thinks it will be faster. Note that memory \
782             map searching doesn't currently support all options, so if an \
783             incompatible option (e.g., --context) is given with --mmap, \
784             then memory maps will not be used."
785        );
786        doc!(
787            h,
788            "no-messages",
789            "Suppress all error messages.",
790            "Suppress all error messages. This is equivalent to redirecting \
791             stderr to /dev/null."
792        );
793        doc!(
794            h,
795            "no-mmap",
796            "Never use memory maps.",
797            "Never use memory maps, even when they might be faster."
798        );
799        doc!(
800            h,
801            "no-ignore",
802            "Don't respect ignore files.",
803            "Don't respect ignore files (.gitignore, .ignore, etc.). This \
804             implies --no-ignore-parent and --no-ignore-vcs."
805        );
806        doc!(
807            h,
808            "no-ignore-parent",
809            "Don't respect ignore files in parent directories.",
810            "Don't respect ignore files (.gitignore, .ignore, etc.) in \
811             parent directories."
812        );
813        doc!(
814            h,
815            "no-ignore-vcs",
816            "Don't respect VCS ignore files",
817            "Don't respect version control ignore files (.gitignore, etc.). \
818             This implies --no-ignore-parent. Note that .ignore files will \
819             continue to be respected."
820        );
821        doc!(
822            h,
823            "null",
824            "Print NUL byte after file names",
825            "Whenever a file name is printed, follow it with a NUL byte. \
826             This includes printing file names before matches, and when \
827             printing a list of matching files such as with --count, \
828             --files-with-matches and --files. This option is useful for use \
829             with xargs."
830        );
831        doc!(
832            h,
833            "path-separator",
834            "Path separator to use when printing file paths.",
835            "The path separator to use when printing file paths. This \
836             defaults to your platform's path separator, which is / on Unix \
837             and \\ on Windows. This flag is intended for overriding the \
838             default when the environment demands it (e.g., cygwin). A path \
839             separator is limited to a single byte."
840        );
841        doc!(h, "pretty", "Alias for --color always --heading -n.");
842        doc!(
843            h,
844            "replace",
845            "Replace matches with string given.",
846            "Replace every match with the string given when printing \
847             results. Neither this flag nor any other flag will modify your \
848             files.\n\nCapture group indices (e.g., $5) and names \
849             (e.g., $foo) are supported in the replacement string.\n\n\
850             Note that the replacement by default replaces each match, and \
851             NOT the entire line. To replace the entire line, you should \
852             match the entire line."
853        );
854        doc!(
855            h,
856            "case-sensitive",
857            "Search case sensitively.",
858            "Search case sensitively. This overrides -i/--ignore-case and \
859             -S/--smart-case."
860        );
861        doc!(
862            h,
863            "smart-case",
864            "Smart case search.",
865            "Searches case insensitively if the pattern is all lowercase. \
866             Search case sensitively otherwise. This is overridden by \
867             either -s/--case-sensitive or -i/--ignore-case."
868        );
869        doc!(
870            h,
871            "sort-files",
872            "Sort results by file path. Implies --threads=1.",
873            "Sort results by file path. Note that this currently \
874             disables all parallelism and runs search in a single thread."
875        );
876        doc!(
877            h,
878            "threads",
879            "The approximate number of threads to use.",
880            "The approximate number of threads to use. A value of 0 (which \
881             is the default) causes ripgrep to choose the thread count \
882             using heuristics."
883        );
884        doc!(
885            h,
886            "vimgrep",
887            "Show results in vim compatible format.",
888            "Show results with every match on its own line, including \
889             line numbers and column numbers. With this option, a line with \
890             more than one match will be printed more than once."
891        );
892
893        doc!(
894            h,
895            "type-add",
896            "Add a new glob for a file type.",
897            "Add a new glob for a particular file type. Only one glob can be \
898             added at a time. Multiple --type-add flags can be provided. \
899             Unless --type-clear is used, globs are added to any existing \
900             globs defined inside of ripgrep.\n\nNote that this MUST be \
901             passed to every invocation of ripgrep. Type settings are NOT \
902             persisted.\n\nExample: \
903             rg --type-add 'foo:*.foo' -tfoo PATTERN.\n\n\
904             --type-add can also be used to include rules from other types \
905             with the special include directive. The include directive \
906             permits specifying one or more other type names (separated by a \
907             comma) that have been defined and its rules will automatically \
908             be imported into the type specified. For example, to create a \
909             type called src that matches C++, Python and Markdown files, one \
910             can use:\n\n\
911             --type-add 'src:include:cpp,py,md'\n\n\
912             Additional glob rules can still be added to the src type by \
913             using the --type-add flag again:\n\n\
914             --type-add 'src:include:cpp,py,md' --type-add 'src:*.foo'\n\n\
915             Note that type names must consist only of Unicode letters or \
916             numbers. Punctuation characters are not allowed."
917        );
918        doc!(
919            h,
920            "type-clear",
921            "Clear globs for given file type.",
922            "Clear the file type globs previously defined for TYPE. This \
923             only clears the default type definitions that are found inside \
924             of ripgrep.\n\nNote that this MUST be passed to every \
925             invocation of ripgrep. Type settings are NOT persisted."
926        );
927
928        h
929    };
930}
931
932criterion_group!(
933    benches,
934    build_rg_with_short_help,
935    build_rg_with_long_help,
936    write_rg_short_help,
937    write_rg_long_help,
938    parse_rg,
939    parse_rg_with_complex,
940    parse_rg_with_lots
941);
942criterion_main!(benches);
943