1
0
mirror of https://github.com/BurntSushi/ripgrep.git synced 2024-12-12 19:18:24 +02:00
Commit Graph

1884 Commits

Author SHA1 Message Date
Andrew Gallant
c81caa673b core: fix file separator bug
I introduced a regression in the migration off of the clap by having
both the buffer writer and the printer be responsible for printing file
separators in multi-threaded search. The buffer writer owns that
responsibility in multi-threaded search.
2023-11-21 18:39:32 -05:00
Andrew Gallant
082245dadb cli: replace clap with lexopt and supporting code
ripgrep began it's life with docopt for argument parsing. Then it moved
to Clap and stayed there for a number of years. Clap has served ripgrep
well, and it probably could continue to serve ripgrep well, but I ended
up deciding to move off of it.

Why?

The first time I had the thought of moving off of Clap was during the
2->3->4 transition. I thought the 3.x and 4.x releases were great, but
for me, it ended up moving a little too quickly. Since the release of
4.x was telegraphed around when 3.x came out, I decided to just hold off
and wait to migrate to 4.x instead of doing a 3.x migration followed
shortly by another 4.x migration. Of course, I just never ended up doing
the migration at all. I never got around to it and there just wasn't a
compelling reason for me to upgrade. While I never investigated it, I
saw an upgrade as a non-trivial amount of work in part because I didn't
encapsulate the usage of Clap enough.

The above is just what got me started thinking about it. It wasn't
enough to get me to move off of it on its own. What ended up pushing me
over the edge was a combination of factors:

* As mentioned above, I didn't want to run on the migration treadmill.
This has proven to not be much of an issue, but at the time of the
2->3->4 releases, I didn't know how long Clap 4.x would be out before a
5.x would come out.
* The release of lexopt[1] caught my eye. IMO, that crate demonstrates
exactly how something new can arrive on the scene and just thoroughly
solve a problem minimalistically. It has the docs, the reasoning, the
simple API, the tests and good judgment. It gets all the weird corner
cases right that Clap also gets right (and is part of why I was
originally attracted to Clap).
* I have an overall desire to reduce the size of my dependency tree. In
part because a smaller dependency tree tends to correlate with better
compile times, but also in part because it reduces my reliance and trust
on others. It lets me be the "master" of ripgrep's destiny by reducing
the amount of behavior that is the result of someone else's decision
(whether good or bad).
* I perceived that Clap solves a more general problem than what I
actually need solved. Despite the vast number of flags that ripgrep has,
its requirements are actually pretty simple. We just need simple
switches and flags that support one value. No multi-value flags. No
sub-commands. And probably a lot of other functionality that Clap has
that makes it so flexible for so many different use cases. (I'm being
hand wavy on the last point.)

With all that said, perhaps most importantly, the future of ripgrep
possibly demands a more flexible CLI argument parser. In today's world,
I would really like, for example, flags like `--type` and `--type-not`
to be able to accumulate their repeated values into a single sequence
while respecting the order they appear on the CLI. For example, prior
to this migration, `rg regex-automata -Tlock -ttoml` would not return
results in `Cargo.lock` in this repository because the `-Tlock` always
took priority even though `-ttoml` appeared after it. But with this
migration, `-ttoml` now correctly overrides `-Tlock`. We would like to
do similar things for `-g/--glob` and `--iglob` and potentially even
now introduce a `-G/--glob-not` flag instead of requiring users to use
`!` to negate a glob. (Which I had done originally to work-around this
problem.) And some day, I'd like to add some kind of boolean matching to
ripgrep perhaps similar to how `git grep` does it. (Although I haven't
thought too carefully on a design yet.) In order to do that, I perceive
it would be difficult to implement correctly in Clap.

I believe that this last point is possible to implement correctly in
Clap 2.x, although it is awkward to do so. I have not looked closely
enough at the Clap 4.x API to know whether it's still possible there. In
any case, these were enough reasons to move off of Clap and own more of
the argument parsing process myself.

This did require a few things:

* I had to write my own logic for how arguments are combined into one
single state object. Of course, I wanted this. This was part of the
upside. But it's still code I didn't have to write for Clap.
* I had to write my own shell completion generator.
* I had to write my own `-h/--help` output generator.
* I also had to write my own man page generator. Well, I had to do this
with Clap 2.x too, although my understanding is that Clap 4.x supports
this. With that said, without having tried it, my guess is that I
probably wouldn't have liked the output it generated because I
ultimately had to write most of the roff by hand myself to get the man
page I wanted. (This also had the benefit of dropping the build
dependency on asciidoc/asciidoctor.)

While this is definitely a fair bit of extra work, it overall only cost
me a couple days. IMO, that's a good trade off given that this code is
unlikely to change again in any substantial way. And it should also
allow for more flexible semantics going forward.

Fixes #884, Fixes #1648, Fixes #1701, Fixes #1814, Fixes #1966

[1]: https://docs.rs/lexopt/0.3.0/lexopt/index.html
2023-11-20 23:51:53 -05:00
Andrew Gallant
c33f623719 cargo: explicitly configure musl to be statically linked
It looks like the musl target will, at some point, default to be
dynamically linked. This config knob should make it so that it's always
statically linked.

Ref https://github.com/rust-lang/compiler-team/issues/422
Ref https://github.com/rust-lang/compiler-team/issues/422#issuecomment-812135847
2023-11-20 23:51:53 -05:00
Jonas Platte
824778c009 globset: add GlobSet::builder
This avoids needing to import and call GlobSetBuilder::new explicitly.

Closes #2635
2023-11-20 23:51:53 -05:00
Kento Okamoto
922bad2b92 ignore: improve 'excludesFile' parsing
This permits the value to be surrounded in double quotes. It's still not
perfect, but probably better than it was. Getting this to be more
correct will likely require writing (or using) a real parser, which I'm
not particularly incliend to do at present.

Fixes #2392, Closes #2629
2023-11-20 23:51:53 -05:00
Andrew Gallant
538ba956dc deps: bump regex and regex-automata 2023-11-20 23:51:53 -05:00
Andrew Gallant
443c057042 deps: bump regex, regex-automata and regex-syntax 2023-11-20 23:51:53 -05:00
Andrew Gallant
5b88515faf build: a bit of clean-up
This does just a smidge of polishing in the build script source code.
2023-11-20 23:51:53 -05:00
Andrew Gallant
92c81b1225 core: switch to anyhow
This commit adds `anyhow` as a dependency and switches over to it from
Box<dyn Error>.

It actually looks like I've kept all of my errors rather shallow, such
that we don't get a huge benefit from anyhow at present. But now that
anyhow is in use, I expect to use its "context" feature more going
forward.
2023-11-20 23:51:53 -05:00
Tavian Barnes
53679e4c43 ignore: simplify the work-stealing strategy
There's no particular reason for this change. I happened to be looking
at the code again and realized that stealing from your left neighbour
or your right neighbour shouldn't make a difference (and indeed perf is
the same in my benchmarks).

Closes #2624
2023-11-20 23:51:53 -05:00
Andrew Gallant
8b766a2522 ripgrep: disable hyperlinks by default
As a result of discussion in #2611, it seems prudent to disable
hyperlinks by default. Ideally they would be enabled, but it looks like
some environments may barf on them. Since this is the first release with
hyperlink support, it makes sense to me at least to make users opt into
them. This does not preclude enabling them by default in future
releases.
2023-11-20 23:51:53 -05:00
Andrew Gallant
c21302b409 regex: tweak inner literal heuristic
Previously, we had logic to skip our own inner literal optimization if
the regex itself was already (likely) accelerated. It turns out that the
presence of a Unicode word boundary can defeat acceleration to a point.
It's likely enough that even if the underlying regex is accelerated, it
would be prudent to do our own inner literal optimization if the pattern
has a Unicode word boundary.

Normally a Unicode word boundary doesn't defeat literal optimizations,
since even the slower engines can make use of *prefix* literal
optimizations. But a regex can be accelerated via its own inner or
suffix literal optimizations, and those require the use of a DFA (or
lazy DFA). Since DFAs crap out on haystacks that contain a non-ASCII
Unicode scalar value when the regex contains a Unicode word boundary, it
follows that an "accelerated" can still wind up being quite slow.

(An "accelerated" regex can also slow down because of restrictions on
avoiding quadratic behavior, but I believe this happens less frequently
and is not as severe as the slow down as a result of Unicode word
boundaries. Namely, avoiding quadratic behavior just means giving up on
the inner literal optimization for a single search. In which case, the
regex engine can still fall back to a normal forward DFA. That will
definitely be slower than an inner literal optimization done by ripgrep,
but not quite as dramatic as it would be when DFAs can't be used at
all.)
2023-11-20 23:51:53 -05:00
Andrew Gallant
8a5b81716a deps: update dependencies
Specifically, regex-syntax 0.8.1 has this fix:
f082244720
2023-11-20 23:51:53 -05:00
Andrew Gallant
7099e174ac cargo: remove dependency patches
I'm too lazy to fixup old commits.
2023-10-09 20:29:52 -04:00
Andrew Gallant
dd810779d4 changelog: add another note about -w/--word-regexp bugs
This was fixed a few commits ago when we updated to regex-automata 0.4
(regex 1.10).

Fixes #2623
2023-10-09 20:29:52 -04:00
Andrew Gallant
5011f6e9f1 changelog: add perf bug fix for \b
Like the previous CHANGELOG entry, this marks a bug that was fixed
likely with the introduction of regex 1.9:

    $ hyperfine "rg-13.0.0 -ic '\bfoo\b \bbar\b' git-3a06386e.txt" "rg -ic '\bfoo\b \bbar\b' git-3a06386e.txt"
    Benchmark 1: rg-13.0.0 -ic '\bfoo\b \bbar\b' git-3a06386e.txt
      Time (mean ± σ):      1.034 s ±  0.011 s    [User: 1.030 s, System: 0.004 s]
      Range (min … max):    1.021 s …  1.053 s    10 runs

    Benchmark 2: rg -ic '\bfoo\b \bbar\b' git-3a06386e.txt
      Time (mean ± σ):       6.3 ms ±   0.3 ms    [User: 4.6 ms, System: 1.6 ms]
      Range (min … max):     5.6 ms …   7.3 ms    343 runs

    Summary
      'rg -ic '\bfoo\b \bbar\b' git-3a06386e.txt' ran
      164.95 ± 7.70 times faster than 'rg-13.0.0 -ic '\bfoo\b \bbar\b' git-3a06386e.txt'

This was not fixed by making \b itself faster, but rather, by improving
inner literal extraction. In particular, if the regex doesn't have any
literals extracted, then search time can still be quite slow:

    $ time rg-13.0.0 -ic '\b[a-z]{3}\b\s\b[a-z]{3}\b' git-3a06386e.txt
    57538

    real    0.427
    user    0.423
    sys     0.003
    maxmem  46 MB
    faults  0
    $ time rg -ic '\b[a-z]{3}\b\s\b[a-z]{3}\b' git-3a06386e.txt
    57538

    real    0.337
    user    0.333
    sys     0.003
    maxmem  46 MB
    faults  0

But then again, so is grep, because grep doesn't benefit from any
literal optimizations either:

    $ time grep -E -ic '\b[a-z]{3}\b\s\b[a-z]{3}\b' git-3a06386e.txt
    62396

    real    1.316
    user    1.292
    sys     0.007
    maxmem  13 MB
    faults  7

The count mismatch should probably be investigated.

Fixes #1760
2023-10-09 20:29:52 -04:00
Andrew Gallant
a2799ccb41 changelog: add bug fix for \b
This was probably fixed in a past commit where I bumped the regex engine
to 1.9 (or perhaps more precisely, regex-automata 0.3). But I didn't
track it as fixed at the time.

Fixes #1275
2023-10-09 20:29:52 -04:00
Andrew Gallant
a13b5e0196 deps: update various crates 2023-10-09 20:29:52 -04:00
Andrew Gallant
9626f16757 progress 2023-10-09 20:29:52 -04:00
Andrew Gallant
f7ff34fdf9 searcher: simplify 'replace_bytes' routine
I did this in the course of trying to optimize it. I don't believe I
made it any faster, but the refactoring led to code that I think is
more readable.
2023-10-09 20:29:52 -04:00
Andrew Gallant
b9de003f81 matcher: add a bunch of inline annotations
Many of these functions should be inlineable, but I'm not 100% sure
that they can be inlined without these annotations. We don't want to
force things, but we do try and nudge the compiler in the right
direction.
2023-10-09 20:29:52 -04:00
Andrew Gallant
1659fb9b43 printer: hand-roll decimal formatting
It seems like a trifle, but if the match frequency is high enough, the
allocation+formatting of line numbers (and columns and byte offsets)
starts to matter. We squash that part of the profile in this commit by
doing our own decimal formatting. I speculate that we get a speed-up
from this by avoiding the formatting machinery and also a possible
allocation.

An alternative would be to use the `itoa` crate, and it is indeed
marginally faster in ad hoc benchmarks, but I'm satisfied enough with
this solution.
2023-10-09 20:29:52 -04:00
Andrew Gallant
dd1bc5b898 printer: sprinkle in a few #[inline] annotations
These seem to help when ripgrep emits a lot of output, especially when
the --column flag is used.
2023-10-09 20:29:52 -04:00
Andrew Gallant
c9bfbe1e3d deps: bump regex and regex-automata
This brings in a fix for a bug I found during ad hoc benchmarking:
aa4e4c7120
2023-10-09 20:29:52 -04:00
Andrew Gallant
88524a2b52 core: dedup patterns
ripgrep does not, and likely never will, report which pattern matched.
Because of that, we can dedup the patterns via just their concrete
syntax without any fuss.

This is somewhat of a pathological case because you don't expect the end
user to pass duplicate patterns in general. But if the end user
generated a list of, say, names and did not dedup them, then ripgrep
could end up spending a lot of extra time on those duplicates if there
are many of them. By deduping them explicitly in the application, we
essentially remove their extra cost completely.
2023-10-09 20:29:52 -04:00
Andrew Gallant
9c6732bd26 printer: remove 'subl' alias
It was apparently using a format specific to a particular plugin. I did
know that, but apparently the plugin is not ubiquitous or de facto
standard[1]. Thus, including it I think just leads to more confusion. We
definitely do not want to be in the business of bundling aliases for
every conceivable plugin to different editors, so just drop it. We
expose the ability to write your own format for exactly this sort of
reason.

[1]: https://github.com/BurntSushi/ripgrep/discussions/2611#discussioncomment-7138302
2023-10-09 20:29:52 -04:00
Andrew Gallant
392bb0944a core: polish the core of ripgrep
This I believe finishes are quest to do mechanical updates to ripgrep's
style, bringing it in line with my current practice (loosely speaking).
2023-10-09 20:29:52 -04:00
Andrew Gallant
90b849912f deps: bump what we can 2023-10-09 20:29:52 -04:00
Andrew Gallant
6d17b3ed68 deps: drop thread_local, lazy_static and once_cell
This is largely made possible by the addition of std::sync::OnceLock to
the standard library, and the memory pool available in regex-automata.
2023-10-09 20:29:52 -04:00
Andrew Gallant
f16ea0812d ignore: polish
Like previous commits, we do a bit of polishing and bring the style up
to my current practice.
2023-10-09 20:29:52 -04:00
Andrew Gallant
be9e308999 globset: use a Pool from regex-automata
In the time before, we just used a RegexSet from the regex crate. That
allocated unconditionally, so there was nothing we could do and it
didn't expose any APIs to reuse that memory. But now that we're using
the lower level regex-automata, we can reuse a PatternSet.

Ideally we would just provide a way for the caller to build a PatternSet
(perhaps via an opaque type) so that we don't have to shuffle data into
a PatternSet and then back into the caller's `Vec<usize>`. But this at
least avoids allocating for every search.
2023-10-09 20:29:52 -04:00
Andrew Gallant
d53b7310ee searcher: polish
This updates some dependencies and brings code style in line with my
current practice.
2023-10-09 20:29:52 -04:00
Andrew Gallant
e30bbb8cff grep: update to the 2021 edition 2023-10-09 20:29:52 -04:00
Andrew Gallant
7f45640401 globset: polishing
This brings the code in line with my current style. It also inlines the
dozen or so lines of code for FNV hashing instead of bringing in a
micro-crate for it. Finally, it drops the dependency on regex in favor
of using regex-syntax and regex-automata directly.
2023-10-09 20:29:52 -04:00
Andrew Gallant
0951820f63 core: doc and logging touchups 2023-10-09 20:29:52 -04:00
Lucas Trzesniewski
c3e85f2b44 printer: fix a few issues in the hyperlink docs
Closes #2612
2023-10-09 20:29:52 -04:00
Andrew Gallant
3ad7a0d95e crates: remove hard-coded links
And use rustdoc's native intra-crate links. So much nicer.
2023-10-09 20:29:52 -04:00
Andrew Gallant
82d3183a04 regex: some minor polish
I think I already did a clean-up of this crate when I moved it to regex
1.9, so the polish here is very minor.
2023-10-09 20:29:52 -04:00
Andrew Gallant
798f8981eb pcre2: small polishing 2023-10-09 20:29:52 -04:00
Andrew Gallant
96f01b92a0 matcher: polish the grep-matcher crate
Not much here. Just updating to reflect my current style and bringing
the crate to the 2021 edition.
2023-10-09 20:29:52 -04:00
Linda_pp
abfa65c2c1
ignore/types: add *.sarif for SARIF format files
[SARIF] is a format for reporting static analysis results. It is [used
by GitHub CodeQL][GH] for example.

Here are some samples from Microsoft's VSCode extension:

https://github.com/microsoft/sarif-vscode-extension/tree/main/samples

The SARIF format is built on top of JSON.

[SARIF]: https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html
[GH]: https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning

PR #2620
2023-10-05 13:23:29 -04:00
Andrew Gallant
f608d4d9b3 hyperlink: rejigger how hyperlinks work
This essentially takes the work done in #2483 and does a bit of a
facelift. A brief summary:

* We reduce the hyperlink API we expose to just the format, a
  configuration and an environment.
* We move buffer management into a hyperlink-specific interpolator.
* We expand the documentation on --hyperlink-format.
* We rewrite the hyperlink format parser to be a simple state machine
  with support for escaping '{{' and '}}'.
* We remove the 'gethostname' dependency and instead insist on the
  caller to provide the hostname. (So grep-printer doesn't get it
  itself, but the application will.) Similarly for the WSL prefix.
* Probably some other things.

Overall, the general structure of #2483 was kept. The biggest change is
probably requiring the caller to pass in things like a hostname instead
of having the crate do it. I did this for a couple reasons:

1. I feel uncomfortable with code deep inside the printing logic
   reaching out into the environment to assume responsibility for
   retrieving the hostname. This feels more like an application-level
   responsibility. Arguably, path canonicalization falls into this same
   bucket, but it is more difficult to rip that out. (And we can do it
   in the future in a backwards compatible fashion I think.)
2. I wanted to permit end users to tell ripgrep about their system's
   hostname in their own way, e.g., by running a custom executable. I
   want this because I know at least for my own use cases, I sometimes
   log into systems using an SSH hostname that is distinct from the
   system's actual hostname (usually because the system is shared in
   some way or changing its hostname is not allowed/practical).

I think that's about it.

Closes #665, Closes #2483
2023-09-25 14:39:54 -04:00
Andrew Gallant
23e21133ba printer: move PathPrinter into grep-printer
I originally did not put PathPrinter into grep-printer because I
considered it somewhat extraneous to what a "grep" program does, and
also that its implementation was rather simple. But now with hyperlink
support, its implementation has grown a smidge more complicated. And
more importantly, its existence required exposing a lot more of the
hyperlink guts. Without it, we can keep things like HyperlinkPath and
HyperlinkSpan completely private.

We can now also keep `PrinterPath` completely private as well. And this
is a breaking change.
2023-09-25 14:39:54 -04:00
Andrew Gallant
09905560ff printer: clean-up
Like a previous commit did for the grep-cli crate, this does some
polishing to the grep-printer crate. We aren't able to achieve as much
as we did with grep-cli, but we at least eliminate all rust-analyzer
lints and group imports in the way I've been doing recently.

Next we'll start doing some more invasive changes.
2023-09-25 14:39:54 -04:00
Andrew Gallant
25a7145c79 cli: add new 'hostname' function
This will enable us to query for the current system's hostname in both
Unix and Windows environments.

We could have pulled in the 'gethostname' crate for this, but:

1. I'm not a huge fan of micro-crates.
2. The 'gethostname' crate panics if an error occurs. (Which, to be
fair, an error should never occur, but it seems plausible on borked
systems? ripgrep runs in a lot of places, so I'd rather not take the
chance of a panic bringing down ripgrep for an optional convenience
feature.)
3. The 'gethostname' crate uses the 'windows-targets' crate from
Microsoft. This is arguably the "right" thing to do, but ripgrep
doesn't use them yet and they appear high-churn.

So I just added a safe wrapper to do this to winapi-util[1] and then
inlined the Unix version here. This brings in no extra dependencies and
the routine is fallible so that callers can recover from potentially
strange failures.

[1]: https://github.com/BurntSushi/winapi-util/pull/14
2023-09-25 14:39:54 -04:00
Andrew Gallant
19a08bee8a cli: clean-up crate
This does a variety of polishing.

1. Deprecate the tty methods in favor of std's IsTerminal trait.
2. Trim down un-needed dependencies.
3. Use bstr to implement escaping.
4. Various aesthetic polishing.

I'm doing this as prep work before adding more to this crate. And as
part of a general effort toward reducing ripgrep's dependencies.
2023-09-25 14:39:54 -04:00
Lucas Trzesniewski
1a50324013 printer: add hyperlinks
This commit represents the initial work to get hyperlinks working and
was submitted as part of PR #2483. Subsequent commits largely retain the
functionality and structure of the hyperlink support added here, but
rejigger some things around.
2023-09-25 14:39:54 -04:00
Andrew Gallant
86ef683308 deps: update everything
Notably, this includes termcolor 1.3, which comes with hyperlink
support.
2023-09-20 11:52:42 -04:00
Tavian Barnes
d938e955af ignore: use work-stealing stack instead of Arc<Mutex<Vec<_>>>
This represents yet another iteration on how `ignore` enqueues and
distributes work in parallel. The original implementation used a
multi-producer/multi-consumer thread safe queue from crossbeam. At some
point, I migrated to a simple `Arc<Mutex<Vec<_>>>` and treated it as a
stack so that we did depth first traversal. This helped with memory
usage in very wide directories.

But it turns out that a naive stack-behind-a-mutex can be quite a bit
slower than something that's a little smarter, such as a work-stealing
stack used in this commit. My hypothesis for why this helps is that
without the stealing component, work distribution can get stuck in
sub-optimal configurations that depend on which directory entries get
assigned to a particular worker. It's likely that this can result in
some workers getting "more" work than others, just by chance, and thus
remain idle. But the work-stealing approach heads that off.

This does re-introduce a dependency on parts of crossbeam which is kind
of a bummer, but it's carrying its weight for now.

Closes #1823, Closes #2591
Ref https://github.com/sharkdp/fd/issues/28
2023-09-20 11:52:42 -04:00
Thilo Uttendorfer
cad1f5fae2 ignore: fix filtering when searching subdirectories
When searching subdirectories the path was not correctly built and
included duplicate parts. This fix will remove the duplicate part if
possible.

Fixes #1757, Closes #2295
2023-09-20 11:52:42 -04:00