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