mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-08-19 14:13:49 -07:00
Compare commits
302 Commits
globset-0.
...
ignore-0.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0e8dbe9df | ||
|
|
e95254a86f | ||
|
|
2f484d8ce5 | ||
|
|
364772ddd2 | ||
|
|
2e207833bc | ||
|
|
92b35a65f8 | ||
|
|
ac8fecbbf2 | ||
|
|
8596817374 | ||
|
|
28bff84a0a | ||
|
|
61101289fa | ||
|
|
13faa39b66 | ||
|
|
6b61271bbb | ||
|
|
1be86392e0 | ||
|
|
63058453fa | ||
|
|
7f23cd63a5 | ||
|
|
8905d54a9f | ||
|
|
25a4eaf5ae | ||
|
|
0000157917 | ||
|
|
65b1b0e38a | ||
|
|
c032cda4b7 | ||
|
|
eab044d829 | ||
|
|
55e62a4411 | ||
|
|
5b2f614aad | ||
|
|
4386b8e805 | ||
|
|
6b012d8129 | ||
|
|
a928ca4221 | ||
|
|
d1570defbf | ||
|
|
b732c23e36 | ||
|
|
49965703fa | ||
|
|
609838aebd | ||
|
|
515f120b5c | ||
|
|
a66315d232 | ||
|
|
bdf10ab7c0 | ||
|
|
a02678800b | ||
|
|
387df97d85 | ||
|
|
a9d97a1dda | ||
|
|
3bb71b0cb8 | ||
|
|
87b33c96c0 | ||
|
|
5e975c43f8 | ||
|
|
7efa2e46d3 | ||
|
|
db0b92b62d | ||
|
|
33b81cac48 | ||
|
|
6a13a4f64d | ||
|
|
b13d835d95 | ||
|
|
d53506b7f7 | ||
|
|
78a35d4d43 | ||
|
|
a933d0bc90 | ||
|
|
2cae30e399 | ||
|
|
8e57989cd2 | ||
|
|
b9f5835534 | ||
|
|
e70778e89d | ||
|
|
87c4a2b4b1 | ||
|
|
0aa31676e3 | ||
|
|
9f0e88bcb1 | ||
|
|
eb4b389846 | ||
|
|
dc337bab0a | ||
|
|
2cfb338530 | ||
|
|
48646e3451 | ||
|
|
985394a19e | ||
|
|
ec36f8c3ff | ||
|
|
a726d03641 | ||
|
|
91afd4214a | ||
|
|
4dc6c73c5a | ||
|
|
36d03b4101 | ||
|
|
d161acb0a3 | ||
|
|
30ee6f08ee | ||
|
|
ced5b92aa9 | ||
|
|
191315a2ea | ||
|
|
5370064f00 | ||
|
|
b6189c659e | ||
|
|
0b36942f68 | ||
|
|
7e05cde008 | ||
|
|
418d048b27 | ||
|
|
009dda1488 | ||
|
|
ba535fb5a3 | ||
|
|
427aaeeb2e | ||
|
|
f5cff746bc | ||
|
|
457f53b7ee | ||
|
|
eb35f7978e | ||
|
|
fc69bd366c | ||
|
|
9b01a8f9ae | ||
|
|
0ff5dd2360 | ||
|
|
3c7819301b | ||
|
|
699e651db2 | ||
|
|
9eddb71b8e | ||
|
|
abf115228e | ||
|
|
fdfc418be5 | ||
|
|
5bf74362b9 | ||
|
|
431ea38620 | ||
|
|
caba5c4348 | ||
|
|
07f97d42cf | ||
|
|
e33d6e73f5 | ||
|
|
478da4f271 | ||
|
|
7ce66f73cf | ||
|
|
bc76a30c23 | ||
|
|
5e81c60b35 | ||
|
|
b3e5ae9d28 | ||
|
|
a024f14fdd | ||
|
|
8c30c8294a | ||
|
|
c44d263419 | ||
|
|
af6b6c543b | ||
|
|
1a4fec8b4a | ||
|
|
c8d8ab8ded | ||
|
|
1d53ed2744 | ||
|
|
29696d1455 | ||
|
|
57ce623a57 | ||
|
|
f1c656de40 | ||
|
|
dd47582619 | ||
|
|
9b88cf8b72 | ||
|
|
6668d7ba8a | ||
|
|
008da5dca4 | ||
|
|
a34df1f690 | ||
|
|
7f3fd6f7ce | ||
|
|
6331a7ac18 | ||
|
|
cd4386bd9b | ||
|
|
cdc20c5685 | ||
|
|
0cf2b98df2 | ||
|
|
9efdbf74a1 | ||
|
|
53cb9a779e | ||
|
|
14860b0f16 | ||
|
|
0eb1a1e7c9 | ||
|
|
5631e5c7a0 | ||
|
|
21644408f2 | ||
|
|
0ee85a89f5 | ||
|
|
ed9d37959f | ||
|
|
9f924ee187 | ||
|
|
35c5db6d1a | ||
|
|
e824531e38 | ||
|
|
af54069c51 | ||
|
|
77a9e99964 | ||
|
|
459a9c5637 | ||
|
|
e4c4540f6a | ||
|
|
5d0f2b0fc0 | ||
|
|
079a23b515 | ||
|
|
6e27649af1 | ||
|
|
df83b8b444 | ||
|
|
e48a17e189 | ||
|
|
fbb2cfed28 | ||
|
|
af8b27ffae | ||
|
|
8a4071eea9 | ||
|
|
ee23ab5173 | ||
|
|
efd9cfb2fc | ||
|
|
656aa12649 | ||
|
|
fc31aedcf3 | ||
|
|
578e1992fa | ||
|
|
46d0130597 | ||
|
|
7534d5144f | ||
|
|
a28e664abd | ||
|
|
0ca96e004c | ||
|
|
2295061e80 | ||
|
|
53c4855517 | ||
|
|
121e0135c1 | ||
|
|
c53c4c0ade | ||
|
|
4566882521 | ||
|
|
12dd455ee9 | ||
|
|
e6cac8b119 | ||
|
|
0f502a9439 | ||
|
|
51d2db7f19 | ||
|
|
b3a6a69f9d | ||
|
|
26a29c750e | ||
|
|
beda5f70dc | ||
|
|
5af7707a35 | ||
|
|
3f33a83a5f | ||
|
|
35b52d33b9 | ||
|
|
a77b914e7a | ||
|
|
2e2af50a4d | ||
|
|
229d1a8d41 | ||
|
|
8ec6ef373f | ||
|
|
581a35e568 | ||
|
|
ba965962fe | ||
|
|
94e4b8e301 | ||
|
|
2af77242c5 | ||
|
|
3f4c4188c1 | ||
|
|
ce4b587055 | ||
|
|
be63122508 | ||
|
|
92286ad4d2 | ||
|
|
4ebe8375ec | ||
|
|
7923d25228 | ||
|
|
1c3eebefec | ||
|
|
64ac2ebe0f | ||
|
|
46fb77c20c | ||
|
|
6a1c3253e0 | ||
|
|
c7730d1f3a | ||
|
|
c5ea5a13df | ||
|
|
9c8d873a75 | ||
|
|
7899a4b931 | ||
|
|
ae55a4e872 | ||
|
|
3a1780d841 | ||
|
|
a6d05475fb | ||
|
|
020c5453a5 | ||
|
|
873abecbf1 | ||
|
|
8c73833efc | ||
|
|
44e69ba627 | ||
|
|
13d77ab646 | ||
|
|
d97fb72d84 | ||
|
|
d6365117e2 | ||
|
|
f32e906012 | ||
|
|
59644d4592 | ||
|
|
3ca324fda7 | ||
|
|
8782f8200c | ||
|
|
2819212f89 | ||
|
|
810be0b348 | ||
|
|
a28bb1e953 | ||
|
|
3ef63dacbe | ||
|
|
e1ac18ef06 | ||
|
|
ba3f9673ad | ||
|
|
c777e2cd57 | ||
|
|
e5639cf22d | ||
|
|
86c843a44b | ||
|
|
2b1637d1db | ||
|
|
6301e20ee4 | ||
|
|
145cef2eff | ||
|
|
20534fad04 | ||
|
|
de0c24f31c | ||
|
|
c55e7af675 | ||
|
|
5ebb3ad039 | ||
|
|
b0066274cb | ||
|
|
def993bad1 | ||
|
|
f511849c81 | ||
|
|
e6e50054b0 | ||
|
|
11c7b2ae17 | ||
|
|
ac7d4c99b9 | ||
|
|
b5681e3694 | ||
|
|
fc2a99bb1f | ||
|
|
ffd4c9ccba | ||
|
|
a16bfcb3d6 | ||
|
|
1b2c1dc675 | ||
|
|
b1e3de246c | ||
|
|
bb36fc1bf8 | ||
|
|
7cb211378a | ||
|
|
a73c0a21d9 | ||
|
|
0b965f900c | ||
|
|
a2f90747c9 | ||
|
|
f97cc623f7 | ||
|
|
f35de5c523 | ||
|
|
c9bb78ceba | ||
|
|
72bdde6771 | ||
|
|
d66712a452 | ||
|
|
e8822ce97a | ||
|
|
a700b75843 | ||
|
|
b72ad8f8aa | ||
|
|
1980630f17 | ||
|
|
1e9a481a66 | ||
|
|
bacfca174e | ||
|
|
6162b000a3 | ||
|
|
2658bd4e46 | ||
|
|
4b8e1f030e | ||
|
|
72807462e8 | ||
|
|
08dee094dd | ||
|
|
caa53b7b09 | ||
|
|
c5d6141562 | ||
|
|
c0f0492b98 | ||
|
|
568018386b | ||
|
|
6219d29c24 | ||
|
|
b458cf39f2 | ||
|
|
3fd2694fbc | ||
|
|
b56315ea84 | ||
|
|
fac47906e6 | ||
|
|
e02bb6b99a | ||
|
|
16a1221fc7 | ||
|
|
793c1179cc | ||
|
|
df7a3bfc7f | ||
|
|
28f2a93cae | ||
|
|
0eb2501b6e | ||
|
|
184c15882e | ||
|
|
64a4dee495 | ||
|
|
50840ea43b | ||
|
|
17dcc2bf51 | ||
|
|
9a858e4909 | ||
|
|
cbfbe9312f | ||
|
|
7ed9a31819 | ||
|
|
a2e6aec7a4 | ||
|
|
73103df6d9 | ||
|
|
139f186e57 | ||
|
|
afb325f733 | ||
|
|
40af352d74 | ||
|
|
3f1d4b397d | ||
|
|
a75b4d122a | ||
|
|
f51b762c6d | ||
|
|
49de7b119c | ||
|
|
1c4b5adb7b | ||
|
|
3d6a58faff | ||
|
|
5b6ca04e39 | ||
|
|
47f20c2661 | ||
|
|
1d5b1011e5 | ||
|
|
1bb30b72fc | ||
|
|
09a4b75baf | ||
|
|
58c428827d | ||
|
|
b9bb04b793 | ||
|
|
4dfea016b9 | ||
|
|
3193d57ac1 | ||
|
|
67c0f576b6 | ||
|
|
543f99dbf1 | ||
|
|
0ea65efd6d | ||
|
|
20deae6497 | ||
|
|
655e33219a | ||
|
|
8ba6ccd159 | ||
|
|
34edb8123a | ||
|
|
5b30c2aed6 | ||
|
|
bf1027a83e | ||
|
|
031264e5fb | ||
|
|
b9cd95faf1 |
8
.cargo/config.toml
Normal file
8
.cargo/config.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# On Windows MSVC, statically link the C runtime so that the resulting EXE does
|
||||||
|
# not depend on the vcruntime DLL.
|
||||||
|
#
|
||||||
|
# See: https://github.com/BurntSushi/ripgrep/pull/1613
|
||||||
|
[target.x86_64-pc-windows-msvc]
|
||||||
|
rustflags = ["-C", "target-feature=+crt-static"]
|
||||||
|
[target.i686-pc-windows-msvc]
|
||||||
|
rustflags = ["-C", "target-feature=+crt-static"]
|
||||||
@@ -1,3 +1,12 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: An issue with ripgrep or any of its crates (ignore, globset, etc.)
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
#### What version of ripgrep are you using?
|
#### What version of ripgrep are you using?
|
||||||
|
|
||||||
Replace this text with the output of `rg --version`.
|
Replace this text with the output of `rg --version`.
|
||||||
@@ -12,18 +21,11 @@ Github binary releases.
|
|||||||
|
|
||||||
Replace this text with your operating system and version.
|
Replace this text with your operating system and version.
|
||||||
|
|
||||||
#### Describe your question, feature request, or bug.
|
#### Describe your bug.
|
||||||
|
|
||||||
If a question, please describe the problem you're trying to solve and give
|
Give a high level description of the bug.
|
||||||
as much context as possible.
|
|
||||||
|
|
||||||
If a feature request, please describe the behavior you want and the motivation.
|
#### What are the steps to reproduce the behavior?
|
||||||
Please also provide an example of how ripgrep would be used if your feature
|
|
||||||
request were added.
|
|
||||||
|
|
||||||
If a bug, please see below.
|
|
||||||
|
|
||||||
#### If this is a bug, what are the steps to reproduce the behavior?
|
|
||||||
|
|
||||||
If possible, please include both your search patterns and the corpus on which
|
If possible, please include both your search patterns and the corpus on which
|
||||||
you are searching. Unless the bug is very obvious, then it is unlikely that it
|
you are searching. Unless the bug is very obvious, then it is unlikely that it
|
||||||
@@ -32,7 +34,7 @@ will be fixed if the ripgrep maintainers cannot reproduce it.
|
|||||||
If the corpus is too big and you cannot decrease its size, file the bug anyway
|
If the corpus is too big and you cannot decrease its size, file the bug anyway
|
||||||
and the ripgrep maintainers will help figure out next steps.
|
and the ripgrep maintainers will help figure out next steps.
|
||||||
|
|
||||||
#### If this is a bug, what is the actual behavior?
|
#### What is the actual behavior?
|
||||||
|
|
||||||
Show the command you ran and the actual output. Include the `--debug` flag in
|
Show the command you ran and the actual output. Include the `--debug` flag in
|
||||||
your invocation of ripgrep.
|
your invocation of ripgrep.
|
||||||
@@ -48,6 +50,6 @@ goes
|
|||||||
here
|
here
|
||||||
```
|
```
|
||||||
|
|
||||||
#### If this is a bug, what is the expected behavior?
|
#### What is the expected behavior?
|
||||||
|
|
||||||
What do you think ripgrep should have done?
|
What do you think ripgrep should have done?
|
||||||
6
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
6
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
blank_issues_enabled: true
|
||||||
|
contact_links:
|
||||||
|
- name: Ask a question
|
||||||
|
about: |
|
||||||
|
You've come to seek help or want to discuss something related to ripgrep.
|
||||||
|
url: https://github.com/BurntSushi/ripgrep/discussions/new
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest a new feature for ripgrep
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
#### Describe your feature request
|
||||||
|
|
||||||
|
Please describe the behavior you want and the motivation. Please also provide
|
||||||
|
examples of how ripgrep would be used if your feature request were added.
|
||||||
|
|
||||||
|
If you're not sure what to write here, then try imagining what the ideal
|
||||||
|
documentation of your new feature would look like in ripgrep's man page. Then
|
||||||
|
try to write it.
|
||||||
|
|
||||||
|
If you're requesting the addition or change of default file types, please open
|
||||||
|
a PR. We can discuss it there if necessary.
|
||||||
6
.github/dependabot.yml
vendored
Normal file
6
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
89
.github/workflows/ci.yml
vendored
89
.github/workflows/ci.yml
vendored
@@ -42,31 +42,31 @@ jobs:
|
|||||||
- win-gnu
|
- win-gnu
|
||||||
include:
|
include:
|
||||||
- build: pinned
|
- build: pinned
|
||||||
os: ubuntu-18.04
|
os: ubuntu-22.04
|
||||||
rust: 1.41.0
|
rust: 1.65.0
|
||||||
- build: stable
|
- build: stable
|
||||||
os: ubuntu-18.04
|
os: ubuntu-22.04
|
||||||
rust: stable
|
rust: stable
|
||||||
- build: beta
|
- build: beta
|
||||||
os: ubuntu-18.04
|
os: ubuntu-22.04
|
||||||
rust: beta
|
rust: beta
|
||||||
- build: nightly
|
- build: nightly
|
||||||
os: ubuntu-18.04
|
os: ubuntu-22.04
|
||||||
rust: nightly
|
rust: nightly
|
||||||
- build: nightly-musl
|
- build: nightly-musl
|
||||||
os: ubuntu-18.04
|
os: ubuntu-22.04
|
||||||
rust: nightly
|
rust: nightly
|
||||||
target: x86_64-unknown-linux-musl
|
target: x86_64-unknown-linux-musl
|
||||||
- build: nightly-32
|
- build: nightly-32
|
||||||
os: ubuntu-18.04
|
os: ubuntu-22.04
|
||||||
rust: nightly
|
rust: nightly
|
||||||
target: i686-unknown-linux-gnu
|
target: i686-unknown-linux-gnu
|
||||||
- build: nightly-mips
|
- build: nightly-mips
|
||||||
os: ubuntu-18.04
|
os: ubuntu-22.04
|
||||||
rust: nightly
|
rust: nightly
|
||||||
target: mips64-unknown-linux-gnuabi64
|
target: mips64-unknown-linux-gnuabi64
|
||||||
- build: nightly-arm
|
- build: nightly-arm
|
||||||
os: ubuntu-18.04
|
os: ubuntu-22.04
|
||||||
rust: nightly
|
rust: nightly
|
||||||
# For stripping release binaries:
|
# For stripping release binaries:
|
||||||
# docker run --rm -v $PWD/target:/target:Z \
|
# docker run --rm -v $PWD/target:/target:Z \
|
||||||
@@ -75,44 +75,40 @@ jobs:
|
|||||||
# /target/arm-unknown-linux-gnueabihf/debug/rg
|
# /target/arm-unknown-linux-gnueabihf/debug/rg
|
||||||
target: arm-unknown-linux-gnueabihf
|
target: arm-unknown-linux-gnueabihf
|
||||||
- build: macos
|
- build: macos
|
||||||
os: macos-latest
|
os: macos-12
|
||||||
rust: nightly
|
rust: nightly
|
||||||
- build: win-msvc
|
- build: win-msvc
|
||||||
os: windows-2019
|
os: windows-2022
|
||||||
rust: nightly
|
rust: nightly
|
||||||
- build: win-gnu
|
- build: win-gnu
|
||||||
os: windows-2019
|
os: windows-2022
|
||||||
rust: nightly-x86_64-gnu
|
rust: nightly-x86_64-gnu
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install packages (Ubuntu)
|
- name: Install packages (Ubuntu)
|
||||||
if: matrix.os == 'ubuntu-18.04'
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
run: |
|
run: |
|
||||||
ci/ubuntu-install-packages
|
ci/ubuntu-install-packages
|
||||||
|
|
||||||
- name: Install packages (macOS)
|
- name: Install packages (macOS)
|
||||||
if: matrix.os == 'macos-latest'
|
if: matrix.os == 'macos-12'
|
||||||
run: |
|
run: |
|
||||||
ci/macos-install-packages
|
ci/macos-install-packages
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ matrix.rust }}
|
toolchain: ${{ matrix.rust }}
|
||||||
profile: minimal
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Use Cross
|
- name: Use Cross
|
||||||
if: matrix.target != ''
|
if: matrix.target != ''
|
||||||
run: |
|
run: |
|
||||||
# FIXME: to work around bugs in latest cross release, install master.
|
cargo install cross
|
||||||
# See: https://github.com/rust-embedded/cross/issues/357
|
echo "CARGO=cross" >> $GITHUB_ENV
|
||||||
cargo install --git https://github.com/rust-embedded/cross
|
echo "TARGET_FLAGS=--target ${{ matrix.target }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CARGO::cross"
|
echo "TARGET_DIR=./target/${{ matrix.target }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=TARGET_FLAGS::--target ${{ matrix.target }}"
|
|
||||||
echo "::set-env name=TARGET_DIR::./target/${{ matrix.target }}"
|
|
||||||
|
|
||||||
- name: Show command used for Cargo
|
- name: Show command used for Cargo
|
||||||
run: |
|
run: |
|
||||||
@@ -120,10 +116,10 @@ jobs:
|
|||||||
echo "target flag is: ${{ env.TARGET_FLAGS }}"
|
echo "target flag is: ${{ env.TARGET_FLAGS }}"
|
||||||
|
|
||||||
- name: Build ripgrep and all crates
|
- name: Build ripgrep and all crates
|
||||||
run: ${{ env.CARGO }} build --verbose --all ${{ env.TARGET_FLAGS }}
|
run: ${{ env.CARGO }} build --verbose --workspace ${{ env.TARGET_FLAGS }}
|
||||||
|
|
||||||
- name: Build ripgrep with PCRE2
|
- name: Build ripgrep with PCRE2
|
||||||
run: ${{ env.CARGO }} build --verbose --all --features pcre2 ${{ env.TARGET_FLAGS }}
|
run: ${{ env.CARGO }} build --verbose --workspace --features pcre2 ${{ env.TARGET_FLAGS }}
|
||||||
|
|
||||||
# This is useful for debugging problems when the expected build artifacts
|
# This is useful for debugging problems when the expected build artifacts
|
||||||
# (like shell completions and man pages) aren't generated.
|
# (like shell completions and man pages) aren't generated.
|
||||||
@@ -141,7 +137,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Run tests with PCRE2 (sans cross)
|
- name: Run tests with PCRE2 (sans cross)
|
||||||
if: matrix.target == ''
|
if: matrix.target == ''
|
||||||
run: ${{ env.CARGO }} test --verbose --all --features pcre2 ${{ env.TARGET_FLAGS }}
|
run: ${{ env.CARGO }} test --verbose --workspace --features pcre2 ${{ env.TARGET_FLAGS }}
|
||||||
|
|
||||||
- name: Run tests without PCRE2 (with cross)
|
- name: Run tests without PCRE2 (with cross)
|
||||||
# These tests should actually work, but they almost double the runtime.
|
# These tests should actually work, but they almost double the runtime.
|
||||||
@@ -149,21 +145,24 @@ jobs:
|
|||||||
# enabled, every integration test is run twice: one with the default
|
# enabled, every integration test is run twice: one with the default
|
||||||
# regex engine and once with PCRE2.
|
# regex engine and once with PCRE2.
|
||||||
if: matrix.target != ''
|
if: matrix.target != ''
|
||||||
run: ${{ env.CARGO }} test --verbose --all ${{ env.TARGET_FLAGS }}
|
run: ${{ env.CARGO }} test --verbose --workspace ${{ env.TARGET_FLAGS }}
|
||||||
|
|
||||||
- name: Test for existence of build artifacts (Windows)
|
- name: Test for existence of build artifacts (Windows)
|
||||||
if: matrix.os == 'windows-2019'
|
if: matrix.os == 'windows-2022'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
outdir="$(ci/cargo-out-dir "${{ env.TARGET_DIR }}")"
|
outdir="$(ci/cargo-out-dir "${{ env.TARGET_DIR }}")"
|
||||||
ls "$outdir/_rg.ps1" && file "$outdir/_rg.ps1"
|
ls "$outdir/_rg.ps1" && file "$outdir/_rg.ps1"
|
||||||
|
|
||||||
- name: Test for existence of build artifacts (Unix)
|
- name: Test for existence of build artifacts (Unix)
|
||||||
if: matrix.os != 'windows-2019'
|
if: matrix.os != 'windows-2022'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
outdir="$(ci/cargo-out-dir "${{ env.TARGET_DIR }}")"
|
outdir="$(ci/cargo-out-dir "${{ env.TARGET_DIR }}")"
|
||||||
for f in rg.bash rg.fish rg.1; do
|
# TODO: Check for the man page generation here. For whatever reason,
|
||||||
|
# it seems to be intermittently failing in CI. No idea why.
|
||||||
|
# for f in rg.bash rg.fish rg.1; do
|
||||||
|
for f in rg.bash rg.fish; do
|
||||||
# We could use file -E here, but it isn't supported on macOS.
|
# We could use file -E here, but it isn't supported on macOS.
|
||||||
ls "$outdir/$f" && file "$outdir/$f"
|
ls "$outdir/$f" && file "$outdir/$f"
|
||||||
done
|
done
|
||||||
@@ -173,23 +172,35 @@ jobs:
|
|||||||
# 'rg' binary (done in test-complete) with qemu, which is a pain and
|
# 'rg' binary (done in test-complete) with qemu, which is a pain and
|
||||||
# doesn't really gain us much. If shell completion works in one place,
|
# doesn't really gain us much. If shell completion works in one place,
|
||||||
# it probably works everywhere.
|
# it probably works everywhere.
|
||||||
if: matrix.target == '' && matrix.os != 'windows-2019'
|
if: matrix.target == '' && matrix.os != 'windows-2022'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ci/test-complete
|
run: ci/test-complete
|
||||||
|
|
||||||
rustfmt:
|
rustfmt:
|
||||||
name: rustfmt
|
name: rustfmt
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v3
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
override: true
|
|
||||||
profile: minimal
|
|
||||||
components: rustfmt
|
components: rustfmt
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
run: |
|
run: cargo fmt --all --check
|
||||||
cargo fmt --all -- --check
|
|
||||||
|
docs:
|
||||||
|
name: Docs
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Install Rust
|
||||||
|
uses: dtolnay/rust-toolchain@master
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
- name: Check documentation
|
||||||
|
env:
|
||||||
|
RUSTDOCFLAGS: -D warnings
|
||||||
|
run: cargo doc --no-deps --document-private-items --workspace
|
||||||
|
|||||||
117
.github/workflows/release.yml
vendored
117
.github/workflows/release.yml
vendored
@@ -1,43 +1,46 @@
|
|||||||
# The way this works is a little weird. But basically, the create-release job
|
# The way this works is the following:
|
||||||
# runs purely to initialize the GitHub release itself. Once done, the upload
|
|
||||||
# URL of the release is saved as an artifact.
|
|
||||||
#
|
#
|
||||||
# The build-release job runs only once create-release is finished. It gets
|
# The create-release job runs purely to initialize the GitHub release itself
|
||||||
# the release upload URL by downloading the corresponding artifact (which was
|
# and to output upload_url for the following job.
|
||||||
# uploaded by create-release). It then builds the release executables for each
|
#
|
||||||
# supported platform and attaches them as release assets to the previously
|
# The build-release job runs only once create-release is finished. It gets the
|
||||||
# created release.
|
# release upload URL from create-release job outputs, then builds the release
|
||||||
|
# executables for each supported platform and attaches them as release assets
|
||||||
|
# to the previously created release.
|
||||||
#
|
#
|
||||||
# The key here is that we create the release only once.
|
# The key here is that we create the release only once.
|
||||||
|
#
|
||||||
|
# Reference:
|
||||||
|
# https://eugene-babichenko.github.io/blog/2020/05/09/github-actions-cross-platform-auto-releases/
|
||||||
|
|
||||||
name: release
|
name: release
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
# Enable when testing release infrastructure on a branch.
|
# Enable when testing release infrastructure on a branch.
|
||||||
# branches:
|
# branches:
|
||||||
# - ag/release
|
# - ag/work
|
||||||
tags:
|
tags:
|
||||||
- '[0-9]+.[0-9]+.[0-9]+'
|
- "[0-9]+.[0-9]+.[0-9]+"
|
||||||
jobs:
|
jobs:
|
||||||
create-release:
|
create-release:
|
||||||
name: create-release
|
name: create-release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
env:
|
# env:
|
||||||
# Set to force version number, e.g., when no tag exists.
|
# Set to force version number, e.g., when no tag exists.
|
||||||
# RG_VERSION: TEST-0.0.0
|
# RG_VERSION: TEST-0.0.0
|
||||||
|
outputs:
|
||||||
|
upload_url: ${{ steps.release.outputs.upload_url }}
|
||||||
|
rg_version: ${{ env.RG_VERSION }}
|
||||||
steps:
|
steps:
|
||||||
- name: Create artifacts directory
|
|
||||||
run: mkdir artifacts
|
|
||||||
|
|
||||||
- name: Get the release version from the tag
|
- name: Get the release version from the tag
|
||||||
|
shell: bash
|
||||||
if: env.RG_VERSION == ''
|
if: env.RG_VERSION == ''
|
||||||
run: |
|
run: |
|
||||||
# Apparently, this is the right way to get a tag name. Really?
|
# Apparently, this is the right way to get a tag name. Really?
|
||||||
#
|
#
|
||||||
# See: https://github.community/t5/GitHub-Actions/How-to-get-just-the-tag-name/m-p/32167/highlight/true#M1027
|
# See: https://github.community/t5/GitHub-Actions/How-to-get-just-the-tag-name/m-p/32167/highlight/true#M1027
|
||||||
echo "::set-env name=RG_VERSION::${GITHUB_REF#refs/tags/}"
|
echo "RG_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||||
echo "version is: ${{ env.RG_VERSION }}"
|
echo "version is: ${{ env.RG_VERSION }}"
|
||||||
|
|
||||||
- name: Create GitHub release
|
- name: Create GitHub release
|
||||||
id: release
|
id: release
|
||||||
uses: actions/create-release@v1
|
uses: actions/create-release@v1
|
||||||
@@ -45,19 +48,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ env.RG_VERSION }}
|
tag_name: ${{ env.RG_VERSION }}
|
||||||
release_name: ripgrep ${{ env.RG_VERSION }}
|
release_name: ${{ env.RG_VERSION }}
|
||||||
|
|
||||||
- name: Save release upload URL to artifact
|
|
||||||
run: echo "${{ steps.release.outputs.upload_url }}" > artifacts/release-upload-url
|
|
||||||
|
|
||||||
- name: Save version number to artifact
|
|
||||||
run: echo "${{ env.RG_VERSION }}" > artifacts/release-version
|
|
||||||
|
|
||||||
- name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v1
|
|
||||||
with:
|
|
||||||
name: artifacts
|
|
||||||
path: artifacts
|
|
||||||
|
|
||||||
build-release:
|
build-release:
|
||||||
name: build-release
|
name: build-release
|
||||||
@@ -68,7 +59,7 @@ jobs:
|
|||||||
# systems.
|
# systems.
|
||||||
CARGO: cargo
|
CARGO: cargo
|
||||||
# When CARGO is set to CROSS, this is set to `--target matrix.target`.
|
# When CARGO is set to CROSS, this is set to `--target matrix.target`.
|
||||||
TARGET_FLAGS:
|
TARGET_FLAGS: ""
|
||||||
# When CARGO is set to CROSS, TARGET_DIR includes matrix.target.
|
# When CARGO is set to CROSS, TARGET_DIR includes matrix.target.
|
||||||
TARGET_DIR: ./target
|
TARGET_DIR: ./target
|
||||||
# Emit backtraces on panics.
|
# Emit backtraces on panics.
|
||||||
@@ -80,63 +71,57 @@ jobs:
|
|||||||
build: [linux, linux-arm, macos, win-msvc, win-gnu, win32-msvc]
|
build: [linux, linux-arm, macos, win-msvc, win-gnu, win32-msvc]
|
||||||
include:
|
include:
|
||||||
- build: linux
|
- build: linux
|
||||||
os: ubuntu-18.04
|
os: ubuntu-22.04
|
||||||
rust: nightly
|
rust: nightly
|
||||||
target: x86_64-unknown-linux-musl
|
target: x86_64-unknown-linux-musl
|
||||||
- build: linux-arm
|
- build: linux-arm
|
||||||
os: ubuntu-18.04
|
os: ubuntu-22.04
|
||||||
rust: nightly
|
rust: nightly
|
||||||
target: arm-unknown-linux-gnueabihf
|
target: arm-unknown-linux-gnueabihf
|
||||||
- build: macos
|
- build: macos
|
||||||
os: macos-latest
|
os: macos-12
|
||||||
rust: nightly
|
rust: nightly
|
||||||
target: x86_64-apple-darwin
|
target: x86_64-apple-darwin
|
||||||
- build: win-msvc
|
- build: win-msvc
|
||||||
os: windows-2019
|
os: windows-2022
|
||||||
rust: nightly
|
rust: nightly
|
||||||
target: x86_64-pc-windows-msvc
|
target: x86_64-pc-windows-msvc
|
||||||
- build: win-gnu
|
- build: win-gnu
|
||||||
os: windows-2019
|
os: windows-2022
|
||||||
rust: nightly-x86_64-gnu
|
rust: nightly-x86_64-gnu
|
||||||
target: x86_64-pc-windows-gnu
|
target: x86_64-pc-windows-gnu
|
||||||
- build: win32-msvc
|
- build: win32-msvc
|
||||||
os: windows-2019
|
os: windows-2022
|
||||||
rust: nightly
|
rust: nightly
|
||||||
target: i686-pc-windows-msvc
|
target: i686-pc-windows-msvc
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v3
|
||||||
with:
|
|
||||||
fetch-depth: 1
|
|
||||||
|
|
||||||
- name: Install packages (Ubuntu)
|
- name: Install packages (Ubuntu)
|
||||||
if: matrix.os == 'ubuntu-18.04'
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
run: |
|
run: |
|
||||||
ci/ubuntu-install-packages
|
ci/ubuntu-install-packages
|
||||||
|
|
||||||
- name: Install packages (macOS)
|
- name: Install packages (macOS)
|
||||||
if: matrix.os == 'macos-latest'
|
if: matrix.os == 'macos-12'
|
||||||
run: |
|
run: |
|
||||||
ci/macos-install-packages
|
ci/macos-install-packages
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ matrix.rust }}
|
toolchain: ${{ matrix.rust }}
|
||||||
profile: minimal
|
|
||||||
override: true
|
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Use Cross
|
- name: Use Cross
|
||||||
# if: matrix.os != 'windows-2019'
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
# FIXME: to work around bugs in latest cross release, install master.
|
cargo install cross
|
||||||
# See: https://github.com/rust-embedded/cross/issues/357
|
echo "CARGO=cross" >> $GITHUB_ENV
|
||||||
cargo install --git https://github.com/rust-embedded/cross
|
echo "TARGET_FLAGS=--target ${{ matrix.target }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=CARGO::cross"
|
echo "TARGET_DIR=./target/${{ matrix.target }}" >> $GITHUB_ENV
|
||||||
echo "::set-env name=TARGET_FLAGS::--target ${{ matrix.target }}"
|
|
||||||
echo "::set-env name=TARGET_DIR::./target/${{ matrix.target }}"
|
|
||||||
|
|
||||||
- name: Show command used for Cargo
|
- name: Show command used for Cargo
|
||||||
run: |
|
run: |
|
||||||
@@ -144,22 +129,6 @@ jobs:
|
|||||||
echo "target flag is: ${{ env.TARGET_FLAGS }}"
|
echo "target flag is: ${{ env.TARGET_FLAGS }}"
|
||||||
echo "target dir is: ${{ env.TARGET_DIR }}"
|
echo "target dir is: ${{ env.TARGET_DIR }}"
|
||||||
|
|
||||||
- name: Get release download URL
|
|
||||||
uses: actions/download-artifact@v1
|
|
||||||
with:
|
|
||||||
name: artifacts
|
|
||||||
path: artifacts
|
|
||||||
|
|
||||||
- name: Set release upload URL and release version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
release_upload_url="$(cat artifacts/release-upload-url)"
|
|
||||||
echo "::set-env name=RELEASE_UPLOAD_URL::$release_upload_url"
|
|
||||||
echo "release upload url: $RELEASE_UPLOAD_URL"
|
|
||||||
release_version="$(cat artifacts/release-version)"
|
|
||||||
echo "::set-env name=RELEASE_VERSION::$release_version"
|
|
||||||
echo "release version: $RELEASE_VERSION"
|
|
||||||
|
|
||||||
- name: Build release binary
|
- name: Build release binary
|
||||||
run: ${{ env.CARGO }} build --verbose --release --features pcre2 ${{ env.TARGET_FLAGS }}
|
run: ${{ env.CARGO }} build --verbose --release --features pcre2 ${{ env.TARGET_FLAGS }}
|
||||||
|
|
||||||
@@ -180,7 +149,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
outdir="$(ci/cargo-out-dir "${{ env.TARGET_DIR }}")"
|
outdir="$(ci/cargo-out-dir "${{ env.TARGET_DIR }}")"
|
||||||
staging="ripgrep-${{ env.RELEASE_VERSION }}-${{ matrix.target }}"
|
staging="ripgrep-${{ needs.create-release.outputs.rg_version }}-${{ matrix.target }}"
|
||||||
mkdir -p "$staging"/{complete,doc}
|
mkdir -p "$staging"/{complete,doc}
|
||||||
|
|
||||||
cp {README.md,COPYING,UNLICENSE,LICENSE-MIT} "$staging/"
|
cp {README.md,COPYING,UNLICENSE,LICENSE-MIT} "$staging/"
|
||||||
@@ -188,24 +157,24 @@ jobs:
|
|||||||
cp "$outdir"/{rg.bash,rg.fish,_rg.ps1} "$staging/complete/"
|
cp "$outdir"/{rg.bash,rg.fish,_rg.ps1} "$staging/complete/"
|
||||||
cp complete/_rg "$staging/complete/"
|
cp complete/_rg "$staging/complete/"
|
||||||
|
|
||||||
if [ "${{ matrix.os }}" = "windows-2019" ]; then
|
if [ "${{ matrix.os }}" = "windows-2022" ]; then
|
||||||
cp "target/${{ matrix.target }}/release/rg.exe" "$staging/"
|
cp "target/${{ matrix.target }}/release/rg.exe" "$staging/"
|
||||||
7z a "$staging.zip" "$staging"
|
7z a "$staging.zip" "$staging"
|
||||||
echo "::set-env name=ASSET::$staging.zip"
|
echo "ASSET=$staging.zip" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
# The man page is only generated on Unix systems. ¯\_(ツ)_/¯
|
# The man page is only generated on Unix systems. ¯\_(ツ)_/¯
|
||||||
cp "$outdir"/rg.1 "$staging/doc/"
|
cp "$outdir"/rg.1 "$staging/doc/"
|
||||||
cp "target/${{ matrix.target }}/release/rg" "$staging/"
|
cp "target/${{ matrix.target }}/release/rg" "$staging/"
|
||||||
tar czf "$staging.tar.gz" "$staging"
|
tar czf "$staging.tar.gz" "$staging"
|
||||||
echo "::set-env name=ASSET::$staging.tar.gz"
|
echo "ASSET=$staging.tar.gz" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upload release archive
|
- name: Upload release archive
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
uses: actions/upload-release-asset@v1.0.2
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ env.RELEASE_UPLOAD_URL }}
|
upload_url: ${{ needs.create-release.outputs.upload_url }}
|
||||||
asset_path: ${{ env.ASSET }}
|
asset_path: ${{ env.ASSET }}
|
||||||
asset_name: ${{ env.ASSET }}
|
asset_name: ${{ env.ASSET }}
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -15,3 +15,7 @@ parts
|
|||||||
*.snap
|
*.snap
|
||||||
*.pyc
|
*.pyc
|
||||||
ripgrep*_source.tar.bz2
|
ripgrep*_source.tar.bz2
|
||||||
|
|
||||||
|
# Cargo timings
|
||||||
|
cargo-timing-*.html
|
||||||
|
cargo-timing.html
|
||||||
|
|||||||
225
CHANGELOG.md
225
CHANGELOG.md
@@ -1,3 +1,224 @@
|
|||||||
|
TBD
|
||||||
|
===
|
||||||
|
Unreleased changes. Release notes have not yet been written.
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* [BUG #1891](https://github.com/BurntSushi/ripgrep/issues/1891):
|
||||||
|
Fix bug when using `-w` with a regex that can match the empty string.
|
||||||
|
* [BUG #1911](https://github.com/BurntSushi/ripgrep/issues/1911):
|
||||||
|
Disable mmap searching in all non-64-bit environments.
|
||||||
|
* [BUG #2236](https://github.com/BurntSushi/ripgrep/issues/2236):
|
||||||
|
Fix gitignore parsing bug where a trailing `\/` resulted in an error.
|
||||||
|
|
||||||
|
|
||||||
|
13.0.0 (2021-06-12)
|
||||||
|
===================
|
||||||
|
ripgrep 13 is a new major version release of ripgrep that primarily contains
|
||||||
|
bug fixes, some performance improvements and a few minor breaking changes.
|
||||||
|
There is also a fix for a security vulnerability on Windows
|
||||||
|
([CVE-2021-3013](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3013)).
|
||||||
|
|
||||||
|
Some highlights:
|
||||||
|
|
||||||
|
A new short flag, `-.`, has been added. It is an alias for the `--hidden` flag,
|
||||||
|
which instructs ripgrep to search hidden files and directories.
|
||||||
|
|
||||||
|
ripgrep is now using a new
|
||||||
|
[vectorized implementation of `memmem`](https://github.com/BurntSushi/memchr/pull/82),
|
||||||
|
which accelerates many common searches. If you notice any performance
|
||||||
|
regressions (or major improvements), I'd love to hear about them through an
|
||||||
|
issue report!
|
||||||
|
|
||||||
|
Also, for Windows users targeting MSVC, Cargo will now build fully static
|
||||||
|
executables of ripgrep. The release binaries for ripgrep 13 have been compiled
|
||||||
|
using this configuration.
|
||||||
|
|
||||||
|
**BREAKING CHANGES**:
|
||||||
|
|
||||||
|
**Binary detection output has changed slightly.**
|
||||||
|
|
||||||
|
In this release, a small tweak has been made to the output format when a binary
|
||||||
|
file is detected. Previously, it looked like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
Binary file FOO matches (found "\0" byte around offset XXX)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now it looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
FOO: binary file matches (found "\0" byte around offset XXX)
|
||||||
|
```
|
||||||
|
|
||||||
|
**vimgrep output in multi-line now only prints the first line for each match.**
|
||||||
|
|
||||||
|
See [issue 1866](https://github.com/BurntSushi/ripgrep/issues/1866) for more
|
||||||
|
discussion on this. Previously, every line in a match was duplicated, even
|
||||||
|
when it spanned multiple lines. There are no changes to vimgrep output when
|
||||||
|
multi-line mode is disabled.
|
||||||
|
|
||||||
|
**In multi-line mode, --count is now equivalent to --count-matches.**
|
||||||
|
|
||||||
|
This appears to match how `pcre2grep` implements `--count`. Previously, ripgrep
|
||||||
|
would produce outright incorrect counts. Another alternative would be to simply
|
||||||
|
count the number of lines---even if it's more than the number of matches---but
|
||||||
|
that seems highly unintuitive.
|
||||||
|
|
||||||
|
**FULL LIST OF FIXES AND IMPROVEMENTS:**
|
||||||
|
|
||||||
|
Security fixes:
|
||||||
|
|
||||||
|
* [CVE-2021-3013](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3013):
|
||||||
|
Fixes a security hole on Windows where running ripgrep with either the
|
||||||
|
`-z/--search-zip` or `--pre` flags can result in running arbitrary
|
||||||
|
executables from the current directory.
|
||||||
|
* [VULN #1773](https://github.com/BurntSushi/ripgrep/issues/1773):
|
||||||
|
This is the public facing issue tracking CVE-2021-3013. ripgrep's README
|
||||||
|
now contains a section describing how to report a vulnerability.
|
||||||
|
|
||||||
|
Performance improvements:
|
||||||
|
|
||||||
|
* [PERF #1657](https://github.com/BurntSushi/ripgrep/discussions/1657):
|
||||||
|
Check if a file should be ignored first before issuing stat calls.
|
||||||
|
* [PERF memchr#82](https://github.com/BurntSushi/memchr/pull/82):
|
||||||
|
ripgrep now uses a new vectorized implementation of `memmem`.
|
||||||
|
|
||||||
|
Feature enhancements:
|
||||||
|
|
||||||
|
* Added or improved file type filtering for ASP, Bazel, dvc, FlatBuffers,
|
||||||
|
Futhark, minified files, Mint, pofiles (from GNU gettext) Racket, Red, Ruby,
|
||||||
|
VCL, Yang.
|
||||||
|
* [FEATURE #1404](https://github.com/BurntSushi/ripgrep/pull/1404):
|
||||||
|
ripgrep now prints a warning if nothing is searched.
|
||||||
|
* [FEATURE #1613](https://github.com/BurntSushi/ripgrep/pull/1613):
|
||||||
|
Cargo will now produce static executables on Windows when using MSVC.
|
||||||
|
* [FEATURE #1680](https://github.com/BurntSushi/ripgrep/pull/1680):
|
||||||
|
Add `-.` as a short flag alias for `--hidden`.
|
||||||
|
* [FEATURE #1842](https://github.com/BurntSushi/ripgrep/issues/1842):
|
||||||
|
Add `--field-{context,match}-separator` for customizing field delimiters.
|
||||||
|
* [FEATURE #1856](https://github.com/BurntSushi/ripgrep/pull/1856):
|
||||||
|
The README now links to a
|
||||||
|
[Spanish translation](https://github.com/UltiRequiem/traducciones/tree/master/ripgrep).
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* [BUG #1277](https://github.com/BurntSushi/ripgrep/issues/1277):
|
||||||
|
Document cygwin path translation behavior in the FAQ.
|
||||||
|
* [BUG #1739](https://github.com/BurntSushi/ripgrep/issues/1739):
|
||||||
|
Fix bug where replacements were buggy if the regex matched a line terminator.
|
||||||
|
* [BUG #1311](https://github.com/BurntSushi/ripgrep/issues/1311):
|
||||||
|
Fix multi-line bug where a search & replace for `\n` didn't work as expected.
|
||||||
|
* [BUG #1401](https://github.com/BurntSushi/ripgrep/issues/1401):
|
||||||
|
Fix buggy interaction between PCRE2 look-around and `-o/--only-matching`.
|
||||||
|
* [BUG #1412](https://github.com/BurntSushi/ripgrep/issues/1412):
|
||||||
|
Fix multi-line bug with searches using look-around past matching lines.
|
||||||
|
* [BUG #1577](https://github.com/BurntSushi/ripgrep/issues/1577):
|
||||||
|
Fish shell completions will continue to be auto-generated.
|
||||||
|
* [BUG #1642](https://github.com/BurntSushi/ripgrep/issues/1642):
|
||||||
|
Fixes a bug where using `-m` and `-A` printed more matches than the limit.
|
||||||
|
* [BUG #1703](https://github.com/BurntSushi/ripgrep/issues/1703):
|
||||||
|
Clarify the function of `-u/--unrestricted`.
|
||||||
|
* [BUG #1708](https://github.com/BurntSushi/ripgrep/issues/1708):
|
||||||
|
Clarify how `-S/--smart-case` works.
|
||||||
|
* [BUG #1730](https://github.com/BurntSushi/ripgrep/issues/1730):
|
||||||
|
Clarify that CLI invocation must always be valid, regardless of config file.
|
||||||
|
* [BUG #1741](https://github.com/BurntSushi/ripgrep/issues/1741):
|
||||||
|
Fix stdin detection when using PowerShell in UNIX environments.
|
||||||
|
* [BUG #1756](https://github.com/BurntSushi/ripgrep/pull/1756):
|
||||||
|
Fix bug where `foo/**` would match `foo`, but it shouldn't.
|
||||||
|
* [BUG #1765](https://github.com/BurntSushi/ripgrep/issues/1765):
|
||||||
|
Fix panic when `--crlf` is used in some cases.
|
||||||
|
* [BUG #1638](https://github.com/BurntSushi/ripgrep/issues/1638):
|
||||||
|
Correctly sniff UTF-8 and do transcoding, like we do for UTF-16.
|
||||||
|
* [BUG #1816](https://github.com/BurntSushi/ripgrep/issues/1816):
|
||||||
|
Add documentation for glob alternate syntax, e.g., `{a,b,..}`.
|
||||||
|
* [BUG #1847](https://github.com/BurntSushi/ripgrep/issues/1847):
|
||||||
|
Clarify how the `--hidden` flag works.
|
||||||
|
* [BUG #1866](https://github.com/BurntSushi/ripgrep/issues/1866#issuecomment-841635553):
|
||||||
|
Fix bug when computing column numbers in `--vimgrep` mode.
|
||||||
|
* [BUG #1868](https://github.com/BurntSushi/ripgrep/issues/1868):
|
||||||
|
Fix bug where `--passthru` and `-A/-B/-C` did not override each other.
|
||||||
|
* [BUG #1869](https://github.com/BurntSushi/ripgrep/pull/1869):
|
||||||
|
Clarify docs for `--files-with-matches` and `--files-without-match`.
|
||||||
|
* [BUG #1878](https://github.com/BurntSushi/ripgrep/issues/1878):
|
||||||
|
Fix bug where `\A` could produce unanchored matches in multiline search.
|
||||||
|
* [BUG 94e4b8e3](https://github.com/BurntSushi/ripgrep/commit/94e4b8e3):
|
||||||
|
Fix column numbers with `--vimgrep` is used with `-U/--multiline`.
|
||||||
|
|
||||||
|
|
||||||
|
12.1.1 (2020-05-29)
|
||||||
|
===================
|
||||||
|
ripgrep 12.1.1 is a patch release that fixes a couple small bugs. In
|
||||||
|
particular, the ripgrep 12.1.0 release did not tag new releases for all of its
|
||||||
|
in-tree dependencies. As a result, ripgrep built dependencies from crates.io
|
||||||
|
would produce a different build than compiling ripgrep from source on the
|
||||||
|
`12.1.0` tag. Namely, some crates like `grep-cli` had unreleased changes.
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* [BUG #1581](https://github.com/BurntSushi/ripgrep/issues/1581):
|
||||||
|
Corrects some egregious markup output in `--help`.
|
||||||
|
* [BUG #1591](https://github.com/BurntSushi/ripgrep/issues/1591):
|
||||||
|
Mention the special `$0` capture group in docs for the `-r/--replace` flag.
|
||||||
|
* [BUG #1602](https://github.com/BurntSushi/ripgrep/issues/1602):
|
||||||
|
Fix failing test resulting from out-of-sync dependencies.
|
||||||
|
|
||||||
|
|
||||||
|
12.1.0 (2020-05-09)
|
||||||
|
===================
|
||||||
|
ripgrep 12.1.0 is a small minor version release that mostly includes bug fixes
|
||||||
|
and documentation improvements. This release also contains some important
|
||||||
|
notices for downstream packagers.
|
||||||
|
|
||||||
|
**Notices for downstream ripgrep package maintainers:**
|
||||||
|
|
||||||
|
* Fish shell completions will be removed in the ripgrep 13 release.
|
||||||
|
See [#1577](https://github.com/BurntSushi/ripgrep/issues/1577)
|
||||||
|
for more details.
|
||||||
|
* ripgrep has switched from `a2x` to `asciidoctor` to generate the man page.
|
||||||
|
If `asciidoctor` is not present, then ripgrep will currently fall back to
|
||||||
|
`a2x`. Support for `a2x` will be dropped in the ripgrep 13 release.
|
||||||
|
See [#1544](https://github.com/BurntSushi/ripgrep/issues/1544)
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
Feature enhancements:
|
||||||
|
|
||||||
|
* [FEATURE #1547](https://github.com/BurntSushi/ripgrep/pull/1547):
|
||||||
|
Support decompressing `.Z` files via `uncompress`.
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* [BUG #1252](https://github.com/BurntSushi/ripgrep/issues/1252):
|
||||||
|
Add a section on the `--pre` flag to the GUIDE.
|
||||||
|
* [BUG #1339](https://github.com/BurntSushi/ripgrep/issues/1339):
|
||||||
|
Improve error message when a pattern with invalid UTF-8 is provided.
|
||||||
|
* [BUG #1524](https://github.com/BurntSushi/ripgrep/issues/1524):
|
||||||
|
Note how to escape a `$` when using `--replace`.
|
||||||
|
* [BUG #1537](https://github.com/BurntSushi/ripgrep/issues/1537):
|
||||||
|
Fix match bug caused by inner literal optimization.
|
||||||
|
* [BUG #1544](https://github.com/BurntSushi/ripgrep/issues/1544):
|
||||||
|
ripgrep now uses `asciidoctor` instead of `a2x` to generate its man page.
|
||||||
|
* [BUG #1550](https://github.com/BurntSushi/ripgrep/issues/1550):
|
||||||
|
Substantially reduce peak memory usage when searching wide directories.
|
||||||
|
* [BUG #1571](https://github.com/BurntSushi/ripgrep/issues/1571):
|
||||||
|
Add note about configuration files in `--type-{add,clear}` docs.
|
||||||
|
* [BUG #1573](https://github.com/BurntSushi/ripgrep/issues/1573):
|
||||||
|
Fix incorrect `--count-matches` output when using look-around.
|
||||||
|
|
||||||
|
|
||||||
|
12.0.1 (2020-03-29)
|
||||||
|
===================
|
||||||
|
ripgrep 12.0.1 is a small patch release that includes a minor bug fix relating
|
||||||
|
to superfluous error messages when searching git repositories with sub-modules.
|
||||||
|
This was a regression introduced in the 12.0.0 release.
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* [BUG #1520](https://github.com/BurntSushi/ripgrep/issues/1520):
|
||||||
|
Don't emit spurious error messages in git repositories with submodules.
|
||||||
|
|
||||||
|
|
||||||
12.0.0 (2020-03-15)
|
12.0.0 (2020-03-15)
|
||||||
===================
|
===================
|
||||||
ripgrep 12 is a new major version release of ripgrep that contains many bug
|
ripgrep 12 is a new major version release of ripgrep that contains many bug
|
||||||
@@ -495,7 +716,7 @@ Bug fixes:
|
|||||||
|
|
||||||
0.8.0 (2018-02-11)
|
0.8.0 (2018-02-11)
|
||||||
==================
|
==================
|
||||||
This is a new minor version releae of ripgrep that satisfies several popular
|
This is a new minor version release of ripgrep that satisfies several popular
|
||||||
feature requests (config files, search compressed files, true colors), fixes
|
feature requests (config files, search compressed files, true colors), fixes
|
||||||
many bugs and improves the quality of life for ripgrep maintainers. This
|
many bugs and improves the quality of life for ripgrep maintainers. This
|
||||||
release also includes greatly improved documentation in the form of a
|
release also includes greatly improved documentation in the form of a
|
||||||
@@ -1193,7 +1414,7 @@ Bug fixes:
|
|||||||
=====
|
=====
|
||||||
Feature enhancements:
|
Feature enhancements:
|
||||||
|
|
||||||
* Added or improved file type filtering for VB, R, F#, Swift, Nim, Javascript,
|
* Added or improved file type filtering for VB, R, F#, Swift, Nim, JavaScript,
|
||||||
TypeScript
|
TypeScript
|
||||||
* [FEATURE #20](https://github.com/BurntSushi/ripgrep/issues/20):
|
* [FEATURE #20](https://github.com/BurntSushi/ripgrep/issues/20):
|
||||||
Adds a --no-filename flag.
|
Adds a --no-filename flag.
|
||||||
|
|||||||
545
Cargo.lock
generated
545
Cargo.lock
generated
@@ -1,599 +1,590 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "0.7.10"
|
version = "0.7.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hermit-abi",
|
||||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc",
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.11.0"
|
version = "0.20.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "0.2.12"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memchr",
|
||||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"once_cell",
|
||||||
"regex-automata 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex-automata",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytecount"
|
name = "bytecount"
|
||||||
version = "0.6.0"
|
version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byteorder"
|
|
||||||
version = "1.3.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.50"
|
version = "1.0.78"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
||||||
|
dependencies = [
|
||||||
|
"jobserver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.10"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.33.0"
|
version = "2.34.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags",
|
||||||
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"strsim",
|
||||||
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"textwrap",
|
||||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.4.2"
|
version = "0.5.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if",
|
||||||
"maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.7.2"
|
version = "0.8.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if",
|
||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.22"
|
version = "0.8.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if",
|
||||||
"packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"packed_simd_2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs_io"
|
name = "encoding_rs_io"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cc3c5651fb62ab8aa3103998dade57efdd028544bd300516baa31840c252a83"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
"encoding_rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.6"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fs_extra"
|
name = "fs_extra"
|
||||||
version = "1.1.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.5"
|
version = "0.4.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"aho-corasick",
|
||||||
"bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bstr",
|
||||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv",
|
||||||
"glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"glob",
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
"regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex",
|
||||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde",
|
||||||
"serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep"
|
name = "grep"
|
||||||
version = "0.2.5"
|
version = "0.2.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"grep-cli 0.1.4",
|
"grep-cli",
|
||||||
"grep-matcher 0.1.4",
|
"grep-matcher",
|
||||||
"grep-pcre2 0.1.4",
|
"grep-pcre2",
|
||||||
"grep-printer 0.1.4",
|
"grep-printer",
|
||||||
"grep-regex 0.1.6",
|
"grep-regex",
|
||||||
"grep-searcher 0.1.7",
|
"grep-searcher",
|
||||||
"termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termcolor",
|
||||||
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-cli"
|
name = "grep-cli"
|
||||||
version = "0.1.4"
|
version = "0.1.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"atty",
|
||||||
"bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bstr",
|
||||||
"globset 0.4.5",
|
"globset",
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
"regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex",
|
||||||
"same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"same-file",
|
||||||
"termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termcolor",
|
||||||
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-matcher"
|
name = "grep-matcher"
|
||||||
version = "0.1.4"
|
version = "0.1.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memchr",
|
||||||
"regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-pcre2"
|
name = "grep-pcre2"
|
||||||
version = "0.1.4"
|
version = "0.1.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"grep-matcher 0.1.4",
|
"grep-matcher",
|
||||||
"pcre2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pcre2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-printer"
|
name = "grep-printer"
|
||||||
version = "0.1.4"
|
version = "0.1.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"base64",
|
||||||
"bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bstr",
|
||||||
"grep-matcher 0.1.4",
|
"grep-matcher",
|
||||||
"grep-regex 0.1.6",
|
"grep-regex",
|
||||||
"grep-searcher 0.1.7",
|
"grep-searcher",
|
||||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde",
|
||||||
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json",
|
||||||
"serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termcolor",
|
||||||
"termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-regex"
|
name = "grep-regex"
|
||||||
version = "0.1.6"
|
version = "0.1.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"aho-corasick",
|
||||||
"bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bstr",
|
||||||
"grep-matcher 0.1.4",
|
"grep-matcher",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
"regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex",
|
||||||
"regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex-syntax",
|
||||||
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"thread_local",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-searcher"
|
name = "grep-searcher"
|
||||||
version = "0.1.7"
|
version = "0.1.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bstr",
|
||||||
"bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytecount",
|
||||||
"encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
"encoding_rs",
|
||||||
"encoding_rs_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"encoding_rs_io",
|
||||||
"grep-matcher 0.1.4",
|
"grep-matcher",
|
||||||
"grep-regex 0.1.6",
|
"grep-regex",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memmap2",
|
||||||
"regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.8"
|
version = "0.1.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.4.12"
|
version = "0.4.19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-channel",
|
||||||
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"globset",
|
||||||
"globset 0.4.5",
|
"lazy_static",
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memchr",
|
||||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex",
|
||||||
"regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"same-file",
|
||||||
"same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"thread_local",
|
||||||
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"walkdir",
|
||||||
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-util",
|
||||||
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.5"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jemalloc-sys"
|
name = "jemalloc-sys"
|
||||||
version = "0.3.2"
|
version = "0.5.2+5.3.0-patched"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "134163979b6eed9564c98637b710b40979939ba351f59952708234ea11b5f3f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc",
|
||||||
"fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fs_extra",
|
||||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jemallocator"
|
name = "jemallocator"
|
||||||
version = "0.3.2"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16c2514137880c52b0b4822b563fadd38257c1f380858addb74a400889696ea6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jemalloc-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jemalloc-sys",
|
||||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.67"
|
version = "0.2.139"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.8"
|
version = "0.4.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "maybe-uninit"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.3.3"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memmap"
|
name = "memmap2"
|
||||||
version = "0.7.0"
|
version = "0.5.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc",
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_cpus"
|
name = "once_cell"
|
||||||
version = "1.12.0"
|
version = "1.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||||
"hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packed_simd"
|
name = "packed_simd_2"
|
||||||
version = "0.3.3"
|
version = "0.3.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if",
|
||||||
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pcre2"
|
name = "pcre2"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85b30f2f69903b439dd9dc9e824119b82a55bf113b29af8d70948a03c1b11ab1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
"pcre2-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pcre2-sys",
|
||||||
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"thread_local",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pcre2-sys"
|
name = "pcre2-sys"
|
||||||
version = "0.2.2"
|
version = "0.2.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dec30e5e9ec37eb8fbf1dea5989bc957fd3df56fbee5061aa7b7a99dbb37b722"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc",
|
||||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc",
|
||||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.17"
|
version = "0.3.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.9"
|
version = "1.0.49"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.3"
|
version = "1.0.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.3.5"
|
version = "1.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"aho-corasick",
|
||||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memchr",
|
||||||
"regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex-syntax",
|
||||||
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.1.9"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.17"
|
version = "0.6.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ripgrep"
|
name = "ripgrep"
|
||||||
version = "12.0.0"
|
version = "13.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bstr",
|
||||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap",
|
||||||
"grep 0.2.5",
|
"grep",
|
||||||
"ignore 0.4.12",
|
"ignore",
|
||||||
"jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jemallocator",
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log",
|
||||||
"num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex",
|
||||||
"regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde",
|
||||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive",
|
||||||
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json",
|
||||||
"serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termcolor",
|
||||||
"termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"walkdir",
|
||||||
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.3"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.104"
|
version = "1.0.152"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.104"
|
version = "1.0.152"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2",
|
||||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote",
|
||||||
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.48"
|
version = "1.0.91"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itoa",
|
||||||
"ryu 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ryu",
|
||||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.16"
|
version = "1.0.107"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2",
|
||||||
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote",
|
||||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.1.0"
|
version = "1.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.0.1"
|
version = "1.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-ident"
|
||||||
version = "0.1.7"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-width"
|
||||||
version = "0.2.0"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.3.1"
|
version = "2.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"same-file",
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi",
|
||||||
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.8"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-i686-pc-windows-gnu",
|
||||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.3"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
[metadata]
|
|
||||||
"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
|
|
||||||
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
|
||||||
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
|
||||||
"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
|
||||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
|
||||||
"checksum bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41"
|
|
||||||
"checksum bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e"
|
|
||||||
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
|
||||||
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
|
||||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
|
||||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
|
||||||
"checksum crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061"
|
|
||||||
"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
|
||||||
"checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28"
|
|
||||||
"checksum encoding_rs_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1cc3c5651fb62ab8aa3103998dade57efdd028544bd300516baa31840c252a83"
|
|
||||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
|
||||||
"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
|
|
||||||
"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
|
||||||
"checksum hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8"
|
|
||||||
"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
|
|
||||||
"checksum jemalloc-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45"
|
|
||||||
"checksum jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "43ae63fcfc45e99ab3d1b29a46782ad679e98436c3169d15a167a1108a724b69"
|
|
||||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
||||||
"checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
|
|
||||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
|
||||||
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
|
||||||
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
|
||||||
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
|
||||||
"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6"
|
|
||||||
"checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220"
|
|
||||||
"checksum pcre2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "85b30f2f69903b439dd9dc9e824119b82a55bf113b29af8d70948a03c1b11ab1"
|
|
||||||
"checksum pcre2-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "876c72d05059d23a84bd9fcdc3b1d31c50ea7fe00fe1522b4e68cd3608db8d5b"
|
|
||||||
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
|
||||||
"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
|
|
||||||
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
|
|
||||||
"checksum regex 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8900ebc1363efa7ea1c399ccc32daed870b4002651e0bed86e72d501ebbe0048"
|
|
||||||
"checksum regex-automata 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
|
|
||||||
"checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
|
|
||||||
"checksum ryu 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
|
|
||||||
"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
|
||||||
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
|
|
||||||
"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
|
|
||||||
"checksum serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25"
|
|
||||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
|
||||||
"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
|
|
||||||
"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
|
|
||||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
|
||||||
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
|
||||||
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
|
||||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
|
||||||
"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
|
|
||||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
|
||||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
"checksum winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
|
|
||||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
||||||
|
|||||||
25
Cargo.toml
25
Cargo.toml
@@ -1,16 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ripgrep"
|
name = "ripgrep"
|
||||||
version = "12.0.0" #:version
|
version = "13.0.0" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
ripgrep is a line-oriented search tool that recursively searches your current
|
ripgrep is a line-oriented search tool that recursively searches the current
|
||||||
directory for a regex pattern while respecting your gitignore rules. ripgrep
|
directory for a regex pattern while respecting gitignore rules. ripgrep has
|
||||||
has first class support on Windows, macOS and Linux.
|
first class support on Windows, macOS and Linux.
|
||||||
"""
|
"""
|
||||||
documentation = "https://github.com/BurntSushi/ripgrep"
|
documentation = "https://github.com/BurntSushi/ripgrep"
|
||||||
homepage = "https://github.com/BurntSushi/ripgrep"
|
homepage = "https://github.com/BurntSushi/ripgrep"
|
||||||
repository = "https://github.com/BurntSushi/ripgrep"
|
repository = "https://github.com/BurntSushi/ripgrep"
|
||||||
readme = "README.md"
|
|
||||||
keywords = ["regex", "grep", "egrep", "search", "pattern"]
|
keywords = ["regex", "grep", "egrep", "search", "pattern"]
|
||||||
categories = ["command-line-utilities", "text-processing"]
|
categories = ["command-line-utilities", "text-processing"]
|
||||||
license = "Unlicense OR MIT"
|
license = "Unlicense OR MIT"
|
||||||
@@ -18,10 +17,7 @@ exclude = ["HomebrewFormula"]
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
autotests = false
|
autotests = false
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
rust-version = "1.65"
|
||||||
[badges]
|
|
||||||
travis-ci = { repository = "BurntSushi/ripgrep" }
|
|
||||||
appveyor = { repository = "BurntSushi/ripgrep" }
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
bench = false
|
bench = false
|
||||||
@@ -46,12 +42,11 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bstr = "0.2.12"
|
bstr = "1.1.0"
|
||||||
grep = { version = "0.2.5", path = "crates/grep" }
|
grep = { version = "0.2.8", path = "crates/grep" }
|
||||||
ignore = { version = "0.4.12", path = "crates/ignore" }
|
ignore = { version = "0.4.18", path = "crates/ignore" }
|
||||||
lazy_static = "1.1.0"
|
lazy_static = "1.1.0"
|
||||||
log = "0.4.5"
|
log = "0.4.5"
|
||||||
num_cpus = "1.8.0"
|
|
||||||
regex = "1.3.5"
|
regex = "1.3.5"
|
||||||
serde_json = "1.0.23"
|
serde_json = "1.0.23"
|
||||||
termcolor = "1.1.0"
|
termcolor = "1.1.0"
|
||||||
@@ -62,7 +57,7 @@ default-features = false
|
|||||||
features = ["suggestions"]
|
features = ["suggestions"]
|
||||||
|
|
||||||
[target.'cfg(all(target_env = "musl", target_pointer_width = "64"))'.dependencies.jemallocator]
|
[target.'cfg(all(target_env = "musl", target_pointer_width = "64"))'.dependencies.jemallocator]
|
||||||
version = "0.3.0"
|
version = "0.5.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
lazy_static = "1.1.0"
|
lazy_static = "1.1.0"
|
||||||
@@ -96,7 +91,7 @@ assets = [
|
|||||||
["README.md", "usr/share/doc/ripgrep/README", "644"],
|
["README.md", "usr/share/doc/ripgrep/README", "644"],
|
||||||
["FAQ.md", "usr/share/doc/ripgrep/FAQ", "644"],
|
["FAQ.md", "usr/share/doc/ripgrep/FAQ", "644"],
|
||||||
# The man page is automatically generated by ripgrep's build process, so
|
# The man page is automatically generated by ripgrep's build process, so
|
||||||
# this file isn't actually commited. Instead, to create a dpkg, either
|
# this file isn't actually committed. Instead, to create a dpkg, either
|
||||||
# create a deployment/deb directory and copy the man page to it, or use the
|
# create a deployment/deb directory and copy the man page to it, or use the
|
||||||
# 'ci/build-deb' script.
|
# 'ci/build-deb' script.
|
||||||
["deployment/deb/rg.1", "usr/share/man/man1/rg.1", "644"],
|
["deployment/deb/rg.1", "usr/share/man/man1/rg.1", "644"],
|
||||||
|
|||||||
44
FAQ.md
44
FAQ.md
@@ -5,14 +5,15 @@
|
|||||||
* [When is the next release?](#release)
|
* [When is the next release?](#release)
|
||||||
* [Does ripgrep have a man page?](#manpage)
|
* [Does ripgrep have a man page?](#manpage)
|
||||||
* [Does ripgrep have support for shell auto-completion?](#complete)
|
* [Does ripgrep have support for shell auto-completion?](#complete)
|
||||||
* [How do I use lookaround and/or backreferences?](#fancy)
|
|
||||||
* [How do I configure ripgrep's colors?](#colors)
|
|
||||||
* [How do I enable true colors on Windows?](#truecolors-windows)
|
|
||||||
* [How do I stop ripgrep from messing up colors when I kill it?](#stop-ripgrep)
|
|
||||||
* [How can I get results in a consistent order?](#order)
|
* [How can I get results in a consistent order?](#order)
|
||||||
* [How do I search files that aren't UTF-8?](#encoding)
|
* [How do I search files that aren't UTF-8?](#encoding)
|
||||||
* [How do I search compressed files?](#compressed)
|
* [How do I search compressed files?](#compressed)
|
||||||
* [How do I search over multiple lines?](#multiline)
|
* [How do I search over multiple lines?](#multiline)
|
||||||
|
* [How do I use lookaround and/or backreferences?](#fancy)
|
||||||
|
* [How do I configure ripgrep's colors?](#colors)
|
||||||
|
* [How do I enable true colors on Windows?](#truecolors-windows)
|
||||||
|
* [How do I stop ripgrep from messing up colors when I kill it?](#stop-ripgrep)
|
||||||
|
* [Why does using a leading `/` on Windows fail?](#because-cygwin)
|
||||||
* [How do I get around the regex size limit?](#size-limit)
|
* [How do I get around the regex size limit?](#size-limit)
|
||||||
* [How do I make the `-f/--file` flag faster?](#dfa-size)
|
* [How do I make the `-f/--file` flag faster?](#dfa-size)
|
||||||
* [How do I make the output look like The Silver Searcher's output?](#silver-searcher-output)
|
* [How do I make the output look like The Silver Searcher's output?](#silver-searcher-output)
|
||||||
@@ -60,9 +61,10 @@ patch release out with a fix. However, no promises are made.
|
|||||||
Does ripgrep have a man page?
|
Does ripgrep have a man page?
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
Yes! Whenever ripgrep is compiled on a system with `asciidoc` present, then a
|
Yes! Whenever ripgrep is compiled on a system with `asciidoctor` or `asciidoc`
|
||||||
man page is generated from ripgrep's argv parser. After compiling ripgrep, you
|
present, then a man page is generated from ripgrep's argv parser. After
|
||||||
can find the man page like so from the root of the repository:
|
compiling ripgrep, you can find the man page like so from the root of the
|
||||||
|
repository:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ find ./target -name rg.1 -print0 | xargs -0 ls -t | head -n1
|
$ find ./target -name rg.1 -print0 | xargs -0 ls -t | head -n1
|
||||||
@@ -138,7 +140,7 @@ How do I search compressed files?
|
|||||||
|
|
||||||
ripgrep's `-z/--search-zip` flag will cause it to search compressed files
|
ripgrep's `-z/--search-zip` flag will cause it to search compressed files
|
||||||
automatically. Currently, this supports gzip, bzip2, xz, lzma, lz4, Brotli and
|
automatically. Currently, this supports gzip, bzip2, xz, lzma, lz4, Brotli and
|
||||||
Zstd. Each of these requires requires the corresponding `gzip`, `bzip2`, `xz`,
|
Zstd. Each of these requires the corresponding `gzip`, `bzip2`, `xz`,
|
||||||
`lz4`, `brotli` and `zstd` binaries to be installed on your system. (That is,
|
`lz4`, `brotli` and `zstd` binaries to be installed on your system. (That is,
|
||||||
ripgrep does decompression by shelling out to another process.)
|
ripgrep does decompression by shelling out to another process.)
|
||||||
|
|
||||||
@@ -206,7 +208,7 @@ The `--color` flag accepts one of the following possible values: `never`,
|
|||||||
ripgrep to only enable colors when it is printing to a terminal. But if you
|
ripgrep to only enable colors when it is printing to a terminal. But if you
|
||||||
pipe ripgrep to a file or some other process, then it will suppress colors.
|
pipe ripgrep to a file or some other process, then it will suppress colors.
|
||||||
|
|
||||||
The --colors` flag is a bit more complicated. The general format is:
|
The `--colors` flag is a bit more complicated. The general format is:
|
||||||
|
|
||||||
```
|
```
|
||||||
--colors '{type}:{attribute}:{value}'
|
--colors '{type}:{attribute}:{value}'
|
||||||
@@ -314,6 +316,26 @@ available
|
|||||||
[here](https://github.com/BurntSushi/ripgrep/issues/281#issuecomment-269093893).
|
[here](https://github.com/BurntSushi/ripgrep/issues/281#issuecomment-269093893).
|
||||||
|
|
||||||
|
|
||||||
|
<h3 name="because-cygwin">
|
||||||
|
Why does using a leading `/` on Windows fail?
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
If you're using cygwin on Windows and try to search for a pattern beginning
|
||||||
|
with a `/`, then it's possible that cygwin is mangling that pattern without
|
||||||
|
your knowledge. For example, if you tried running `rg /foo` in a cygwin shell
|
||||||
|
on Windows, then cygwin might mistakenly perform path translation on `/foo`,
|
||||||
|
which would result in `rg C:/msys64/foo` being searched instead.
|
||||||
|
|
||||||
|
You can fix this in one of three ways:
|
||||||
|
|
||||||
|
1. Stop using cygwin.
|
||||||
|
2. Escape the leading slash with an additional slash. e.g., `rg //foo`.
|
||||||
|
3. Temporarily disable path translation by setting `MSYS_NO_PATHCONV=1`. e.g.,
|
||||||
|
`MSYS_NO_PATHCONV=1 rg /foo`.
|
||||||
|
|
||||||
|
For more details, see https://github.com/BurntSushi/ripgrep/issues/1277
|
||||||
|
|
||||||
|
|
||||||
<h3 name="size-limit">
|
<h3 name="size-limit">
|
||||||
How do I get around the regex size limit?
|
How do I get around the regex size limit?
|
||||||
</h3>
|
</h3>
|
||||||
@@ -823,7 +845,7 @@ rg foo --files-with-matches | xargs sed -i 's/foo/bar/g'
|
|||||||
will replace all instances of 'foo' with 'bar' in the files in which
|
will replace all instances of 'foo' with 'bar' in the files in which
|
||||||
ripgrep finds the foo pattern. The `-i` flag to sed indicates that you are
|
ripgrep finds the foo pattern. The `-i` flag to sed indicates that you are
|
||||||
editing files in place, and `s/foo/bar/g` says that you are performing a
|
editing files in place, and `s/foo/bar/g` says that you are performing a
|
||||||
**s**ubstitution of the pattren `foo` for `bar`, and that you are doing this
|
**s**ubstitution of the pattern `foo` for `bar`, and that you are doing this
|
||||||
substitution **g**lobally (all occurrences of the pattern in each file).
|
substitution **g**lobally (all occurrences of the pattern in each file).
|
||||||
|
|
||||||
Note: the above command assumes that you are using GNU sed. If you are using
|
Note: the above command assumes that you are using GNU sed. If you are using
|
||||||
@@ -870,7 +892,7 @@ The reason why ripgrep is dual licensed this way is two-fold:
|
|||||||
1. I, as ripgrep's author, would like to participate in a small bit of
|
1. I, as ripgrep's author, would like to participate in a small bit of
|
||||||
ideological activism by promoting the Unlicense's goal: to disclaim
|
ideological activism by promoting the Unlicense's goal: to disclaim
|
||||||
copyright monopoly interest.
|
copyright monopoly interest.
|
||||||
2. I, as ripgrep's author, would like as many people to use rigprep as
|
2. I, as ripgrep's author, would like as many people to use ripgrep as
|
||||||
possible. Since the Unlicense is not a proven or well known license, ripgrep
|
possible. Since the Unlicense is not a proven or well known license, ripgrep
|
||||||
is also offered under the MIT license, which is ubiquitous and accepted by
|
is also offered under the MIT license, which is ubiquitous and accepted by
|
||||||
almost everyone.
|
almost everyone.
|
||||||
|
|||||||
231
GUIDE.md
231
GUIDE.md
@@ -19,6 +19,7 @@ translatable to any command line shell environment.
|
|||||||
* [Configuration file](#configuration-file)
|
* [Configuration file](#configuration-file)
|
||||||
* [File encoding](#file-encoding)
|
* [File encoding](#file-encoding)
|
||||||
* [Binary data](#binary-data)
|
* [Binary data](#binary-data)
|
||||||
|
* [Preprocessor](#preprocessor)
|
||||||
* [Common options](#common-options)
|
* [Common options](#common-options)
|
||||||
|
|
||||||
|
|
||||||
@@ -176,16 +177,21 @@ After recursive search, ripgrep's most important feature is what it *doesn't*
|
|||||||
search. By default, when you search a directory, ripgrep will ignore all of
|
search. By default, when you search a directory, ripgrep will ignore all of
|
||||||
the following:
|
the following:
|
||||||
|
|
||||||
1. Files and directories that match the rules in your `.gitignore` glob
|
1. Files and directories that match glob patterns in these three categories:
|
||||||
pattern.
|
1. gitignore globs (including global and repo-specific globs).
|
||||||
|
2. `.ignore` globs, which take precedence over all gitignore globs
|
||||||
|
when there's a conflict.
|
||||||
|
3. `.rgignore` globs, which take precedence over all `.ignore` globs
|
||||||
|
when there's a conflict.
|
||||||
2. Hidden files and directories.
|
2. Hidden files and directories.
|
||||||
3. Binary files. (ripgrep considers any file with a `NUL` byte to be binary.)
|
3. Binary files. (ripgrep considers any file with a `NUL` byte to be binary.)
|
||||||
4. Symbolic links aren't followed.
|
4. Symbolic links aren't followed.
|
||||||
|
|
||||||
All of these things can be toggled using various flags provided by ripgrep:
|
All of these things can be toggled using various flags provided by ripgrep:
|
||||||
|
|
||||||
1. You can disable `.gitignore` handling with the `--no-ignore` flag.
|
1. You can disable all ignore-related filtering with the `--no-ignore` flag.
|
||||||
2. Hidden files and directories can be searched with the `--hidden` flag.
|
2. Hidden files and directories can be searched with the `--hidden` (`-.` for
|
||||||
|
short) flag.
|
||||||
3. Binary files can be searched via the `--text` (`-a` for short) flag.
|
3. Binary files can be searched via the `--text` (`-a` for short) flag.
|
||||||
Be careful with this flag! Binary files may emit control characters to your
|
Be careful with this flag! Binary files may emit control characters to your
|
||||||
terminal, which might cause strange behavior.
|
terminal, which might cause strange behavior.
|
||||||
@@ -376,7 +382,7 @@ make: *.mak, *.mk, GNUmakefile, Gnumakefile, Makefile, gnumakefile, makefile
|
|||||||
By default, ripgrep comes with a bunch of pre-defined types. Generally, these
|
By default, ripgrep comes with a bunch of pre-defined types. Generally, these
|
||||||
types correspond to well known public formats. But you can define your own
|
types correspond to well known public formats. But you can define your own
|
||||||
types as well. For example, perhaps you frequently search "web" files, which
|
types as well. For example, perhaps you frequently search "web" files, which
|
||||||
consist of Javascript, HTML and CSS:
|
consist of JavaScript, HTML and CSS:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rg --type-add 'web:*.html' --type-add 'web:*.css' --type-add 'web:*.js' -tweb title
|
$ rg --type-add 'web:*.html' --type-add 'web:*.css' --type-add 'web:*.js' -tweb title
|
||||||
@@ -643,9 +649,9 @@ given, which is the default:
|
|||||||
they correspond to a UTF-16 BOM, then ripgrep will transcode the contents of
|
they correspond to a UTF-16 BOM, then ripgrep will transcode the contents of
|
||||||
the file from UTF-16 to UTF-8, and then execute the search on the transcoded
|
the file from UTF-16 to UTF-8, and then execute the search on the transcoded
|
||||||
version of the file. (This incurs a performance penalty since transcoding
|
version of the file. (This incurs a performance penalty since transcoding
|
||||||
is slower than regex searching.) If the file contains invalid UTF-16, then
|
is needed in addition to regex searching.) If the file contains invalid
|
||||||
the Unicode replacement codepoint is substituted in place of invalid code
|
UTF-16, then the Unicode replacement codepoint is substituted in place of
|
||||||
units.
|
invalid code units.
|
||||||
* To handle other cases, ripgrep provides a `-E/--encoding` flag, which permits
|
* To handle other cases, ripgrep provides a `-E/--encoding` flag, which permits
|
||||||
you to specify an encoding from the
|
you to specify an encoding from the
|
||||||
[Encoding Standard](https://encoding.spec.whatwg.org/#concept-encoding-get).
|
[Encoding Standard](https://encoding.spec.whatwg.org/#concept-encoding-get).
|
||||||
@@ -767,6 +773,212 @@ via the `--no-mmap` flag. (The cost will be a small performance regression when
|
|||||||
searching very large files on some platforms.)
|
searching very large files on some platforms.)
|
||||||
|
|
||||||
|
|
||||||
|
### Preprocessor
|
||||||
|
|
||||||
|
In ripgrep, a preprocessor is any type of command that can be run to transform
|
||||||
|
the input of every file before ripgrep searches it. This makes it possible to
|
||||||
|
search virtually any kind of content that can be automatically converted to
|
||||||
|
text without having to teach ripgrep how to read said content.
|
||||||
|
|
||||||
|
One common example is searching PDFs. PDFs are first and foremost meant to be
|
||||||
|
displayed to users. But PDFs often have text streams in them that can be useful
|
||||||
|
to search. In our case, we want to search Bruce Watson's excellent
|
||||||
|
dissertation,
|
||||||
|
[Taxonomies and Toolkits of Regular Language Algorithms](https://burntsushi.net/stuff/1995-watson.pdf).
|
||||||
|
After downloading it, let's try searching it:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ rg 'The Commentz-Walter algorithm' 1995-watson.pdf
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
Surely, a dissertation on regular language algorithms would mention
|
||||||
|
Commentz-Walter. Indeed it does, but our search isn't picking it up because
|
||||||
|
PDFs are a binary format, and the text shown in the PDF may not be encoded as
|
||||||
|
simple contiguous UTF-8. Namely, even passing the `-a/--text` flag to ripgrep
|
||||||
|
will not make our search work.
|
||||||
|
|
||||||
|
One way to fix this is to convert the PDF to plain text first. This won't work
|
||||||
|
well for all PDFs, but does great in a lot of cases. (Note that the tool we
|
||||||
|
use, `pdftotext`, is part of the [poppler](https://poppler.freedesktop.org)
|
||||||
|
PDF rendering library.)
|
||||||
|
|
||||||
|
```
|
||||||
|
$ pdftotext 1995-watson.pdf > 1995-watson.txt
|
||||||
|
$ rg 'The Commentz-Walter algorithm' 1995-watson.txt
|
||||||
|
316:The Commentz-Walter algorithms : : : : : : : : : : : : : : :
|
||||||
|
7165:4.4 The Commentz-Walter algorithms
|
||||||
|
10062:in input string S , we obtain the Boyer-Moore algorithm. The Commentz-Walter algorithm
|
||||||
|
17218:The Commentz-Walter algorithm (and its variants) displayed more interesting behaviour,
|
||||||
|
17249:Aho-Corasick algorithms are used extensively. The Commentz-Walter algorithms are used
|
||||||
|
17297: The Commentz-Walter algorithms (CW). In all versions of the CW algorithms, a common program skeleton is used with di erent shift functions. The CW algorithms are
|
||||||
|
```
|
||||||
|
|
||||||
|
But having to explicitly convert every file can be a pain, especially when you
|
||||||
|
have a directory full of PDF files. Instead, we can use ripgrep's preprocessor
|
||||||
|
feature to search the PDF. ripgrep's `--pre` flag works by taking a single
|
||||||
|
command name and then executing that command for every file that it searches.
|
||||||
|
ripgrep passes the file path as the first and only argument to the command and
|
||||||
|
also sends the contents of the file to stdin. So let's write a simple shell
|
||||||
|
script that wraps `pdftotext` in a way that conforms to this interface:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cat preprocess
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec pdftotext - -
|
||||||
|
```
|
||||||
|
|
||||||
|
With `preprocess` in the same directory as `1995-watson.pdf`, we can now use it
|
||||||
|
to search the PDF:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ rg --pre ./preprocess 'The Commentz-Walter algorithm' 1995-watson.pdf
|
||||||
|
316:The Commentz-Walter algorithms : : : : : : : : : : : : : : :
|
||||||
|
7165:4.4 The Commentz-Walter algorithms
|
||||||
|
10062:in input string S , we obtain the Boyer-Moore algorithm. The Commentz-Walter algorithm
|
||||||
|
17218:The Commentz-Walter algorithm (and its variants) displayed more interesting behaviour,
|
||||||
|
17249:Aho-Corasick algorithms are used extensively. The Commentz-Walter algorithms are used
|
||||||
|
17297: The Commentz-Walter algorithms (CW). In all versions of the CW algorithms, a common program skeleton is used with di erent shift functions. The CW algorithms are
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that `preprocess` must be resolvable to a command that ripgrep can read.
|
||||||
|
The simplest way to do this is to put your preprocessor command in a directory
|
||||||
|
that is in your `PATH` (or equivalent), or otherwise use an absolute path.
|
||||||
|
|
||||||
|
As a bonus, this turns out to be quite a bit faster than other specialized PDF
|
||||||
|
grepping tools:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ time rg --pre ./preprocess 'The Commentz-Walter algorithm' 1995-watson.pdf -c
|
||||||
|
6
|
||||||
|
|
||||||
|
real 0.697
|
||||||
|
user 0.684
|
||||||
|
sys 0.007
|
||||||
|
maxmem 16 MB
|
||||||
|
faults 0
|
||||||
|
|
||||||
|
$ time pdfgrep 'The Commentz-Walter algorithm' 1995-watson.pdf -c
|
||||||
|
6
|
||||||
|
|
||||||
|
real 1.336
|
||||||
|
user 1.310
|
||||||
|
sys 0.023
|
||||||
|
maxmem 16 MB
|
||||||
|
faults 0
|
||||||
|
```
|
||||||
|
|
||||||
|
If you wind up needing to search a lot of PDFs, then ripgrep's parallelism can
|
||||||
|
make the speed difference even greater.
|
||||||
|
|
||||||
|
#### A more robust preprocessor
|
||||||
|
|
||||||
|
One of the problems with the aforementioned preprocessor is that it will fail
|
||||||
|
if you try to search a file that isn't a PDF:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ echo foo > not-a-pdf
|
||||||
|
$ rg --pre ./preprocess 'The Commentz-Walter algorithm' not-a-pdf
|
||||||
|
not-a-pdf: preprocessor command failed: '"./preprocess" "not-a-pdf"':
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Syntax Warning: May not be a PDF file (continuing anyway)
|
||||||
|
Syntax Error: Couldn't find trailer dictionary
|
||||||
|
Syntax Error: Couldn't find trailer dictionary
|
||||||
|
Syntax Error: Couldn't read xref table
|
||||||
|
```
|
||||||
|
|
||||||
|
To fix this, we can make our preprocessor script a bit more robust by only
|
||||||
|
running `pdftotext` when we think the input is a non-empty PDF:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cat preprocessor
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
*.pdf)
|
||||||
|
# The -s flag ensures that the file is non-empty.
|
||||||
|
if [ -s "$1" ]; then
|
||||||
|
exec pdftotext - -
|
||||||
|
else
|
||||||
|
exec cat
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exec cat
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
```
|
||||||
|
|
||||||
|
We can even extend our preprocessor to search other kinds of files. Sometimes
|
||||||
|
we don't always know the file type from the file name, so we can use the `file`
|
||||||
|
utility to "sniff" the type of the file based on its contents:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cat processor
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
*.pdf)
|
||||||
|
# The -s flag ensures that the file is non-empty.
|
||||||
|
if [ -s "$1" ]; then
|
||||||
|
exec pdftotext - -
|
||||||
|
else
|
||||||
|
exec cat
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
case $(file "$1") in
|
||||||
|
*Zstandard*)
|
||||||
|
exec pzstd -cdq
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exec cat
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Reducing preprocessor overhead
|
||||||
|
|
||||||
|
There is one more problem with the above approach: it requires running a
|
||||||
|
preprocessor for every single file that ripgrep searches. If every file needs
|
||||||
|
a preprocessor, then this is OK. But if most don't, then this can substantially
|
||||||
|
slow down searches because of the overhead of launching new processors. You
|
||||||
|
can avoid this by telling ripgrep to only invoke the preprocessor when the file
|
||||||
|
path matches a glob. For example, consider the performance difference even when
|
||||||
|
searching a repository as small as ripgrep's:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ time rg --pre pre-rg 'fn is_empty' -c
|
||||||
|
crates/globset/src/lib.rs:1
|
||||||
|
crates/matcher/src/lib.rs:2
|
||||||
|
crates/ignore/src/overrides.rs:1
|
||||||
|
crates/ignore/src/gitignore.rs:1
|
||||||
|
crates/ignore/src/types.rs:1
|
||||||
|
|
||||||
|
real 0.138
|
||||||
|
user 0.485
|
||||||
|
sys 0.209
|
||||||
|
maxmem 7 MB
|
||||||
|
faults 0
|
||||||
|
|
||||||
|
$ time rg --pre pre-rg --pre-glob '*.pdf' 'fn is_empty' -c
|
||||||
|
crates/globset/src/lib.rs:1
|
||||||
|
crates/ignore/src/types.rs:1
|
||||||
|
crates/ignore/src/gitignore.rs:1
|
||||||
|
crates/ignore/src/overrides.rs:1
|
||||||
|
crates/matcher/src/lib.rs:2
|
||||||
|
|
||||||
|
real 0.008
|
||||||
|
user 0.010
|
||||||
|
sys 0.002
|
||||||
|
maxmem 7 MB
|
||||||
|
faults 0
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Common options
|
### Common options
|
||||||
|
|
||||||
ripgrep has a lot of flags. Too many to keep in your head at once. This section
|
ripgrep has a lot of flags. Too many to keep in your head at once. This section
|
||||||
@@ -781,6 +993,8 @@ used options that will likely impact how you use ripgrep on a regular basis.
|
|||||||
* `-S/--smart-case`: This is similar to `--ignore-case`, but disables itself
|
* `-S/--smart-case`: This is similar to `--ignore-case`, but disables itself
|
||||||
if the pattern contains any uppercase letters. Usually this flag is put into
|
if the pattern contains any uppercase letters. Usually this flag is put into
|
||||||
alias or a config file.
|
alias or a config file.
|
||||||
|
* `-F/--fixed-strings`: Disable regular expression matching and treat the pattern
|
||||||
|
as a literal string.
|
||||||
* `-w/--word-regexp`: Require that all matches of the pattern be surrounded
|
* `-w/--word-regexp`: Require that all matches of the pattern be surrounded
|
||||||
by word boundaries. That is, given `pattern`, the `--word-regexp` flag will
|
by word boundaries. That is, given `pattern`, the `--word-regexp` flag will
|
||||||
cause ripgrep to behave as if `pattern` were actually `\b(?:pattern)\b`.
|
cause ripgrep to behave as if `pattern` were actually `\b(?:pattern)\b`.
|
||||||
@@ -788,6 +1002,7 @@ used options that will likely impact how you use ripgrep on a regular basis.
|
|||||||
* `--files`: Print the files that ripgrep *would* search, but don't actually
|
* `--files`: Print the files that ripgrep *would* search, but don't actually
|
||||||
search them.
|
search them.
|
||||||
* `-a/--text`: Search binary files as if they were plain text.
|
* `-a/--text`: Search binary files as if they were plain text.
|
||||||
|
* `-U/--multiline`: Permit matches to span multiple lines.
|
||||||
* `-z/--search-zip`: Search compressed files (gzip, bzip2, lzma, xz, lz4,
|
* `-z/--search-zip`: Search compressed files (gzip, bzip2, lzma, xz, lz4,
|
||||||
brotli, zstd). This is disabled by default.
|
brotli, zstd). This is disabled by default.
|
||||||
* `-C/--context`: Show the lines surrounding a match.
|
* `-C/--context`: Show the lines surrounding a match.
|
||||||
|
|||||||
93
README.md
93
README.md
@@ -1,12 +1,12 @@
|
|||||||
ripgrep (rg)
|
ripgrep (rg)
|
||||||
------------
|
------------
|
||||||
ripgrep is a line-oriented search tool that recursively searches your current
|
ripgrep is a line-oriented search tool that recursively searches the current
|
||||||
directory for a regex pattern. By default, ripgrep will respect your .gitignore
|
directory for a regex pattern. By default, ripgrep will respect gitignore rules
|
||||||
and automatically skip hidden files/directories and binary files. ripgrep
|
and automatically skip hidden files/directories and binary files. (To disable
|
||||||
has first class support on Windows, macOS and Linux, with binary downloads
|
all automatic filtering by default, use `rg -uuu`.) ripgrep has first class
|
||||||
available for [every release](https://github.com/BurntSushi/ripgrep/releases).
|
support on Windows, macOS and Linux, with binary downloads available for [every
|
||||||
ripgrep is similar to other popular search tools like The Silver Searcher, ack
|
release](https://github.com/BurntSushi/ripgrep/releases). ripgrep is similar to
|
||||||
and grep.
|
other popular search tools like The Silver Searcher, ack and grep.
|
||||||
|
|
||||||
[](https://github.com/BurntSushi/ripgrep/actions)
|
[](https://github.com/BurntSushi/ripgrep/actions)
|
||||||
[](https://crates.io/crates/ripgrep)
|
[](https://crates.io/crates/ripgrep)
|
||||||
@@ -53,8 +53,8 @@ for a very detailed comparison with more benchmarks and analysis.
|
|||||||
| ripgrep (Unicode) | `rg -n -w '[A-Z]+_SUSPEND'` | 452 | **0.136s** |
|
| ripgrep (Unicode) | `rg -n -w '[A-Z]+_SUSPEND'` | 452 | **0.136s** |
|
||||||
| [git grep](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `git grep -P -n -w '[A-Z]+_SUSPEND'` | 452 | 0.348s |
|
| [git grep](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `git grep -P -n -w '[A-Z]+_SUSPEND'` | 452 | 0.348s |
|
||||||
| [ugrep (Unicode)](https://github.com/Genivia/ugrep) | `ugrep -r --ignore-files --no-hidden -I -w '[A-Z]+_SUSPEND'` | 452 | 0.506s |
|
| [ugrep (Unicode)](https://github.com/Genivia/ugrep) | `ugrep -r --ignore-files --no-hidden -I -w '[A-Z]+_SUSPEND'` | 452 | 0.506s |
|
||||||
| [git grep](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `LC_ALL=C git grep -E -n -w '[A-Z]+_SUSPEND'` | 452 | 1.150s |
|
|
||||||
| [The Silver Searcher](https://github.com/ggreer/the_silver_searcher) | `ag -w '[A-Z]+_SUSPEND'` | 452 | 0.654s |
|
| [The Silver Searcher](https://github.com/ggreer/the_silver_searcher) | `ag -w '[A-Z]+_SUSPEND'` | 452 | 0.654s |
|
||||||
|
| [git grep](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `LC_ALL=C git grep -E -n -w '[A-Z]+_SUSPEND'` | 452 | 1.150s |
|
||||||
| [ack](https://github.com/beyondgrep/ack3) | `ack -w '[A-Z]+_SUSPEND'` | 452 | 4.054s |
|
| [ack](https://github.com/beyondgrep/ack3) | `ack -w '[A-Z]+_SUSPEND'` | 452 | 4.054s |
|
||||||
| [git grep (Unicode)](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `LC_ALL=en_US.UTF-8 git grep -E -n -w '[A-Z]+_SUSPEND'` | 452 | 4.205s |
|
| [git grep (Unicode)](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `LC_ALL=en_US.UTF-8 git grep -E -n -w '[A-Z]+_SUSPEND'` | 452 | 4.205s |
|
||||||
|
|
||||||
@@ -90,16 +90,16 @@ times are unaffected by the presence or absence of `-n`.
|
|||||||
because it contains most of their features and is generally faster. (See
|
because it contains most of their features and is generally faster. (See
|
||||||
[the FAQ](FAQ.md#posix4ever) for more details on whether ripgrep can truly
|
[the FAQ](FAQ.md#posix4ever) for more details on whether ripgrep can truly
|
||||||
replace grep.)
|
replace grep.)
|
||||||
* Like other tools specialized to code search, ripgrep defaults to recursive
|
* Like other tools specialized to code search, ripgrep defaults to
|
||||||
directory search and won't search files ignored by your
|
[recursive search](GUIDE.md#recursive-search) and does [automatic
|
||||||
`.gitignore`/`.ignore`/`.rgignore` files. It also ignores hidden and binary
|
filtering](GUIDE.md#automatic-filtering). Namely, ripgrep won't search files
|
||||||
files by default. ripgrep also implements full support for `.gitignore`,
|
ignored by your `.gitignore`/`.ignore`/`.rgignore` files, it won't search
|
||||||
whereas there are many bugs related to that functionality in other code
|
hidden files and it won't search binary files. Automatic filtering can be
|
||||||
search tools claiming to provide the same functionality.
|
disabled with `rg -uuu`.
|
||||||
* ripgrep can search specific types of files. For example, `rg -tpy foo`
|
* ripgrep can [search specific types of files](GUIDE.md#manual-filtering-file-types).
|
||||||
limits your search to Python files and `rg -Tjs foo` excludes Javascript
|
For example, `rg -tpy foo` limits your search to Python files and `rg -Tjs
|
||||||
files from your search. ripgrep can be taught about new file types with
|
foo` excludes JavaScript files from your search. ripgrep can be taught about
|
||||||
custom matching rules.
|
new file types with custom matching rules.
|
||||||
* ripgrep supports many features found in `grep`, such as showing the context
|
* ripgrep supports many features found in `grep`, such as showing the context
|
||||||
of search results, searching multiple patterns, highlighting matches with
|
of search results, searching multiple patterns, highlighting matches with
|
||||||
color and full Unicode support. Unlike GNU grep, ripgrep stays fast while
|
color and full Unicode support. Unlike GNU grep, ripgrep stays fast while
|
||||||
@@ -110,15 +110,20 @@ times are unaffected by the presence or absence of `-n`.
|
|||||||
regex engine. PCRE2 support can be enabled with `-P/--pcre2` (use PCRE2
|
regex engine. PCRE2 support can be enabled with `-P/--pcre2` (use PCRE2
|
||||||
always) or `--auto-hybrid-regex` (use PCRE2 only if needed). An alternative
|
always) or `--auto-hybrid-regex` (use PCRE2 only if needed). An alternative
|
||||||
syntax is provided via the `--engine (default|pcre2|auto-hybrid)` option.
|
syntax is provided via the `--engine (default|pcre2|auto-hybrid)` option.
|
||||||
* ripgrep supports searching files in text encodings other than UTF-8, such
|
* ripgrep has [rudimentary support for replacements](GUIDE.md#replacements),
|
||||||
as UTF-16, latin-1, GBK, EUC-JP, Shift_JIS and more. (Some support for
|
which permit rewriting output based on what was matched.
|
||||||
automatically detecting UTF-16 is provided. Other text encodings must be
|
* ripgrep supports [searching files in text encodings](GUIDE.md#file-encoding)
|
||||||
specifically specified with the `-E/--encoding` flag.)
|
other than UTF-8, such as UTF-16, latin-1, GBK, EUC-JP, Shift_JIS and more.
|
||||||
|
(Some support for automatically detecting UTF-16 is provided. Other text
|
||||||
|
encodings must be specifically specified with the `-E/--encoding` flag.)
|
||||||
* ripgrep supports searching files compressed in a common format (brotli,
|
* ripgrep supports searching files compressed in a common format (brotli,
|
||||||
bzip2, gzip, lz4, lzma, xz, or zstandard) with the `-z/--search-zip` flag.
|
bzip2, gzip, lz4, lzma, xz, or zstandard) with the `-z/--search-zip` flag.
|
||||||
* ripgrep supports arbitrary input preprocessing filters which could be PDF
|
* ripgrep supports
|
||||||
text extraction, less supported decompression, decrypting, automatic encoding
|
[arbitrary input preprocessing filters](GUIDE.md#preprocessor)
|
||||||
detection and so on.
|
which could be PDF text extraction, less supported decompression, decrypting,
|
||||||
|
automatic encoding detection and so on.
|
||||||
|
* ripgrep can be configured via a
|
||||||
|
[configuration file](GUIDE.md#configuration-file).
|
||||||
|
|
||||||
In other words, use ripgrep if you like speed, filtering by default, fewer
|
In other words, use ripgrep if you like speed, filtering by default, fewer
|
||||||
bugs and Unicode support.
|
bugs and Unicode support.
|
||||||
@@ -191,15 +196,9 @@ multiline search and opt-in fancy regex support via PCRE2.
|
|||||||
The binary name for ripgrep is `rg`.
|
The binary name for ripgrep is `rg`.
|
||||||
|
|
||||||
**[Archives of precompiled binaries for ripgrep are available for Windows,
|
**[Archives of precompiled binaries for ripgrep are available for Windows,
|
||||||
macOS and Linux.](https://github.com/BurntSushi/ripgrep/releases)** Users of
|
macOS and Linux.](https://github.com/BurntSushi/ripgrep/releases)** Linux and
|
||||||
platforms not explicitly mentioned below are advised to download one of these
|
Windows binaries are static executables. Users of platforms not explicitly
|
||||||
archives.
|
mentioned below are advised to download one of these archives.
|
||||||
|
|
||||||
Linux binaries are static executables. Windows binaries are available either as
|
|
||||||
built with MinGW (GNU) or with Microsoft Visual C++ (MSVC). When possible,
|
|
||||||
prefer MSVC over GNU, but you'll need to have the [Microsoft VC++ 2015
|
|
||||||
redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=48145)
|
|
||||||
installed.
|
|
||||||
|
|
||||||
If you're a **macOS Homebrew** or a **Linuxbrew** user, then you can install
|
If you're a **macOS Homebrew** or a **Linuxbrew** user, then you can install
|
||||||
ripgrep from homebrew-core:
|
ripgrep from homebrew-core:
|
||||||
@@ -272,13 +271,20 @@ $ nix-env --install ripgrep
|
|||||||
$ # (Or using the attribute name, which is also ripgrep.)
|
$ # (Or using the attribute name, which is also ripgrep.)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you're a **Guix** user, you can install ripgrep from the official
|
||||||
|
package collection:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ guix install ripgrep
|
||||||
|
```
|
||||||
|
|
||||||
If you're a **Debian** user (or a user of a Debian derivative like **Ubuntu**),
|
If you're a **Debian** user (or a user of a Debian derivative like **Ubuntu**),
|
||||||
then ripgrep can be installed using a binary `.deb` file provided in each
|
then ripgrep can be installed using a binary `.deb` file provided in each
|
||||||
[ripgrep release](https://github.com/BurntSushi/ripgrep/releases).
|
[ripgrep release](https://github.com/BurntSushi/ripgrep/releases).
|
||||||
|
|
||||||
```
|
```
|
||||||
$ curl -LO https://github.com/BurntSushi/ripgrep/releases/download/11.0.2/ripgrep_11.0.2_amd64.deb
|
$ curl -LO https://github.com/BurntSushi/ripgrep/releases/download/13.0.0/ripgrep_13.0.0_amd64.deb
|
||||||
$ sudo dpkg -i ripgrep_11.0.2_amd64.deb
|
$ sudo dpkg -i ripgrep_13.0.0_amd64.deb
|
||||||
```
|
```
|
||||||
|
|
||||||
If you run Debian Buster (currently Debian stable) or Debian sid, ripgrep is
|
If you run Debian Buster (currently Debian stable) or Debian sid, ripgrep is
|
||||||
@@ -308,14 +314,14 @@ If you're a **FreeBSD** user, then you can install ripgrep from the
|
|||||||
```
|
```
|
||||||
|
|
||||||
If you're an **OpenBSD** user, then you can install ripgrep from the
|
If you're an **OpenBSD** user, then you can install ripgrep from the
|
||||||
[official ports](http://openports.se/textproc/ripgrep):
|
[official ports](https://openports.se/textproc/ripgrep):
|
||||||
|
|
||||||
```
|
```
|
||||||
$ doas pkg_add ripgrep
|
$ doas pkg_add ripgrep
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're a **NetBSD** user, then you can install ripgrep from
|
If you're a **NetBSD** user, then you can install ripgrep from
|
||||||
[pkgsrc](http://pkgsrc.se/textproc/ripgrep):
|
[pkgsrc](https://pkgsrc.se/textproc/ripgrep):
|
||||||
|
|
||||||
```
|
```
|
||||||
# pkgin install ripgrep
|
# pkgin install ripgrep
|
||||||
@@ -352,7 +358,7 @@ $ cargo install ripgrep
|
|||||||
|
|
||||||
ripgrep is written in Rust, so you'll need to grab a
|
ripgrep is written in Rust, so you'll need to grab a
|
||||||
[Rust installation](https://www.rust-lang.org/) in order to compile it.
|
[Rust installation](https://www.rust-lang.org/) in order to compile it.
|
||||||
ripgrep compiles with Rust 1.34.0 (stable) or newer. In general, ripgrep tracks
|
ripgrep compiles with Rust 1.65.0 (stable) or newer. In general, ripgrep tracks
|
||||||
the latest stable release of the Rust compiler.
|
the latest stable release of the Rust compiler.
|
||||||
|
|
||||||
To build ripgrep:
|
To build ripgrep:
|
||||||
@@ -424,9 +430,18 @@ $ cargo test --all
|
|||||||
from the repository root.
|
from the repository root.
|
||||||
|
|
||||||
|
|
||||||
|
### Vulnerability reporting
|
||||||
|
|
||||||
|
For reporting a security vulnerability, please
|
||||||
|
[contact Andrew Gallant](https://blog.burntsushi.net/about/),
|
||||||
|
which has my email address and PGP public key if you wish to send an encrypted
|
||||||
|
message.
|
||||||
|
|
||||||
|
|
||||||
### Translations
|
### Translations
|
||||||
|
|
||||||
The following is a list of known translations of ripgrep's documentation. These
|
The following is a list of known translations of ripgrep's documentation. These
|
||||||
are unofficially maintained and may not be up to date.
|
are unofficially maintained and may not be up to date.
|
||||||
|
|
||||||
* [Chinese](https://github.com/chinanf-boy/ripgrep-zh#%E6%9B%B4%E6%96%B0-)
|
* [Chinese](https://github.com/chinanf-boy/ripgrep-zh#%E6%9B%B4%E6%96%B0-)
|
||||||
|
* [Spanish](https://github.com/UltiRequiem/traducciones/tree/master/ripgrep)
|
||||||
|
|||||||
56
RELEASE-CHECKLIST.md
Normal file
56
RELEASE-CHECKLIST.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
Release Checklist
|
||||||
|
-----------------
|
||||||
|
* Ensure local `master` is up to date with respect to `origin/master`.
|
||||||
|
* Run `cargo update` and review dependency updates. Commit updated
|
||||||
|
`Cargo.lock`.
|
||||||
|
* Run `cargo outdated` and review semver incompatible updates. Unless there is
|
||||||
|
a strong motivation otherwise, review and update every dependency. Also
|
||||||
|
run `--aggressive`, but don't update to crates that are still in beta.
|
||||||
|
* Review changes for every crate in `crates` since the last ripgrep release.
|
||||||
|
If the set of changes is non-empty, issue a new release for that crate. Check
|
||||||
|
crates in the following order. After updating a crate, ensure minimal
|
||||||
|
versions are updated as appropriate in dependents. If an update is required,
|
||||||
|
run `cargo-up --no-push crates/{CRATE}/Cargo.toml`.
|
||||||
|
* crates/globset
|
||||||
|
* crates/ignore
|
||||||
|
* crates/cli
|
||||||
|
* crates/matcher
|
||||||
|
* crates/regex
|
||||||
|
* crates/pcre2
|
||||||
|
* crates/searcher
|
||||||
|
* crates/printer
|
||||||
|
* crates/grep (bump minimal versions as necessary)
|
||||||
|
* crates/core (do **not** bump version, but update dependencies as needed)
|
||||||
|
* Update the CHANGELOG as appropriate.
|
||||||
|
* Edit the `Cargo.toml` to set the new ripgrep version. Run
|
||||||
|
`cargo update -p ripgrep` so that the `Cargo.lock` is updated. Commit the
|
||||||
|
changes and create a new signed tag. Alternatively, use
|
||||||
|
`cargo-up --no-push --no-release Cargo.toml {VERSION}` to automate this.
|
||||||
|
* Push changes to GitHub, NOT including the tag. (But do not publish new
|
||||||
|
version of ripgrep to crates.io yet.)
|
||||||
|
* Once CI for `master` finishes successfully, push the version tag. (Trying to
|
||||||
|
do this in one step seems to result in GitHub Actions not seeing the tag
|
||||||
|
push and thus not running the release workflow.)
|
||||||
|
* Wait for CI to finish creating the release. If the release build fails, then
|
||||||
|
delete the tag from GitHub, make fixes, re-tag, delete the release and push.
|
||||||
|
* Copy the relevant section of the CHANGELOG to the tagged release notes.
|
||||||
|
Include this blurb describing what ripgrep is:
|
||||||
|
> In case you haven't heard of it before, ripgrep is a line-oriented search
|
||||||
|
> tool that recursively searches the current directory for a regex pattern.
|
||||||
|
> By default, ripgrep will respect gitignore rules and automatically skip
|
||||||
|
> hidden files/directories and binary files.
|
||||||
|
* Run `ci/build-deb` locally and manually upload the deb package to the
|
||||||
|
release.
|
||||||
|
* Run `cargo publish`.
|
||||||
|
* Run `ci/sha256-releases {VERSION} >> pkg/brew/ripgrep-bin.rb`. Then edit
|
||||||
|
`pkg/brew/ripgrep-bin.rb` to update the version number and sha256 hashes.
|
||||||
|
Remove extraneous stuff added by `ci/sha256-releases`. Commit changes.
|
||||||
|
* Add TBD section to the top of the CHANGELOG:
|
||||||
|
```
|
||||||
|
TBD
|
||||||
|
===
|
||||||
|
Unreleased changes. Release notes have not yet been written.
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that
|
||||||
|
[`cargo-up` can be found in BurntSushi's dotfiles](https://github.com/BurntSushi/dotfiles/blob/master/bin/cargo-up).
|
||||||
@@ -23,16 +23,16 @@ import time
|
|||||||
# strategies used to increase the relevance of results returned.
|
# strategies used to increase the relevance of results returned.
|
||||||
|
|
||||||
SUBTITLES_DIR = 'subtitles'
|
SUBTITLES_DIR = 'subtitles'
|
||||||
SUBTITLES_EN_NAME = 'OpenSubtitles2016.raw.en'
|
SUBTITLES_EN_NAME = 'en.txt'
|
||||||
SUBTITLES_EN_NAME_SAMPLE = 'OpenSubtitles2016.raw.sample.en'
|
SUBTITLES_EN_NAME_SAMPLE = 'en.sample.txt'
|
||||||
SUBTITLES_EN_NAME_GZ = '%s.gz' % SUBTITLES_EN_NAME
|
SUBTITLES_EN_NAME_GZ = '%s.gz' % SUBTITLES_EN_NAME
|
||||||
SUBTITLES_EN_URL = 'http://opus.lingfil.uu.se/OpenSubtitles2016/mono/OpenSubtitles2016.raw.en.gz' # noqa
|
SUBTITLES_EN_URL = 'https://object.pouta.csc.fi/OPUS-OpenSubtitles/v2016/mono/en.txt.gz' # noqa
|
||||||
SUBTITLES_RU_NAME = 'OpenSubtitles2016.raw.ru'
|
SUBTITLES_RU_NAME = 'ru.txt'
|
||||||
SUBTITLES_RU_NAME_GZ = '%s.gz' % SUBTITLES_RU_NAME
|
SUBTITLES_RU_NAME_GZ = '%s.gz' % SUBTITLES_RU_NAME
|
||||||
SUBTITLES_RU_URL = 'http://opus.lingfil.uu.se/OpenSubtitles2016/mono/OpenSubtitles2016.raw.ru.gz' # noqa
|
SUBTITLES_RU_URL = 'https://object.pouta.csc.fi/OPUS-OpenSubtitles/v2016/mono/ru.txt.gz' # noqa
|
||||||
|
|
||||||
LINUX_DIR = 'linux'
|
LINUX_DIR = 'linux'
|
||||||
LINUX_CLONE = 'git://github.com/BurntSushi/linux'
|
LINUX_CLONE = 'https://github.com/BurntSushi/linux'
|
||||||
|
|
||||||
# Grep takes locale settings from the environment. There is a *substantial*
|
# Grep takes locale settings from the environment. There is a *substantial*
|
||||||
# performance impact for enabling Unicode, so we need to handle this explicitly
|
# performance impact for enabling Unicode, so we need to handle this explicitly
|
||||||
@@ -55,8 +55,10 @@ def bench_linux_literal_default(suite_dir):
|
|||||||
Benchmark the speed of a literal using *default* settings.
|
Benchmark the speed of a literal using *default* settings.
|
||||||
|
|
||||||
This is a purposefully unfair benchmark for use in performance
|
This is a purposefully unfair benchmark for use in performance
|
||||||
analysis, but it is pedagogically useful to demonstrate how
|
analysis, but it is pedagogically useful to demonstrate how default
|
||||||
default behaviors differ.
|
behaviors differ. For example, ugrep and grep don't do any smart
|
||||||
|
filtering by default, so they will invariably search more files
|
||||||
|
than ripgrep, ag or git grep.
|
||||||
'''
|
'''
|
||||||
require(suite_dir, 'linux')
|
require(suite_dir, 'linux')
|
||||||
cwd = path.join(suite_dir, LINUX_DIR)
|
cwd = path.join(suite_dir, LINUX_DIR)
|
||||||
@@ -69,16 +71,11 @@ def bench_linux_literal_default(suite_dir):
|
|||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg', ['rg', pat]),
|
mkcmd('rg', ['rg', pat]),
|
||||||
mkcmd('ag', ['ag', pat]),
|
mkcmd('ag', ['ag', pat]),
|
||||||
# ucg reports the exact same matches as ag and rg even though it
|
|
||||||
# doesn't read gitignore files. Instead, it has a file whitelist
|
|
||||||
# that happens to match up exactly with the gitignores for this search.
|
|
||||||
mkcmd('ucg', ['ucg', pat]),
|
|
||||||
# I guess setting LC_ALL=en_US.UTF-8 probably isn't necessarily the
|
# I guess setting LC_ALL=en_US.UTF-8 probably isn't necessarily the
|
||||||
# default, but I'd guess it to be on most desktop systems.
|
# default, but I'd guess it to be on most desktop systems.
|
||||||
mkcmd('pt', ['pt', pat]),
|
mkcmd('git grep', ['git', 'grep', pat], env=GREP_UNICODE),
|
||||||
# sift reports an extra line here for a binary file matched.
|
mkcmd('ugrep', ['ugrep', '-r', pat, './']),
|
||||||
mkcmd('sift', ['sift', pat]),
|
mkcmd('grep', ['grep', '-r', pat, './'], env=GREP_UNICODE),
|
||||||
mkcmd('git grep', ['git', 'grep', pat], env={'LC_ALL': 'en_US.UTF-8'}),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -100,16 +97,16 @@ def bench_linux_literal(suite_dir):
|
|||||||
return Command(*args, **kwargs)
|
return Command(*args, **kwargs)
|
||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg (ignore)', ['rg', '-n', pat]),
|
mkcmd('rg', ['rg', '-n', pat]),
|
||||||
mkcmd('rg (ignore) (mmap)', ['rg', '-n', '--mmap', pat]),
|
mkcmd('rg (mmap)', ['rg', '-n', '--mmap', pat]),
|
||||||
mkcmd('ag (ignore) (mmap)', ['ag', '-s', pat]),
|
mkcmd('ag (mmap)', ['ag', '-s', pat]),
|
||||||
mkcmd('pt (ignore)', ['pt', pat]),
|
mkcmd('git grep', [
|
||||||
mkcmd('sift (ignore)', SIFT + ['-n', '--git', pat]),
|
|
||||||
mkcmd('git grep (ignore)', [
|
|
||||||
'git', 'grep', '-I', '-n', pat,
|
'git', 'grep', '-I', '-n', pat,
|
||||||
], env={'LC_ALL': 'C'}),
|
], env={'LC_ALL': 'C'}),
|
||||||
mkcmd('rg (whitelist)', ['rg', '-n', '--no-ignore', '-tall', pat]),
|
mkcmd('ugrep', [
|
||||||
mkcmd('ucg (whitelist)', ['ucg', '--nosmart-case', pat]),
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
|
'-n', pat, './',
|
||||||
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -129,31 +126,26 @@ def bench_linux_literal_casei(suite_dir):
|
|||||||
return Command(*args, **kwargs)
|
return Command(*args, **kwargs)
|
||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg (ignore)', ['rg', '-n', '-i', pat]),
|
mkcmd('rg', ['rg', '-n', '-i', pat]),
|
||||||
mkcmd('rg (ignore) (mmap)', ['rg', '-n', '-i', '--mmap', pat]),
|
mkcmd('rg (mmap)', ['rg', '-n', '-i', '--mmap', pat]),
|
||||||
mkcmd('ag (ignore) (mmap)', ['ag', '-i', pat]),
|
mkcmd('ag (mmap)', ['ag', '-i', pat]),
|
||||||
mkcmd('pt (ignore)', ['pt', '-i', pat]),
|
|
||||||
mkcmd('sift (ignore)', SIFT + ['-n', '-i', '--git', pat]),
|
|
||||||
# It'd technically be more appropriate to set LC_ALL=en_US.UTF-8 here,
|
# It'd technically be more appropriate to set LC_ALL=en_US.UTF-8 here,
|
||||||
# since that is certainly what ripgrep is doing, but this is for an
|
# since that is certainly what ripgrep is doing, but this is for an
|
||||||
# ASCII literal, so we should give `git grep` all the opportunity to
|
# ASCII literal, so we should give `git grep` all the opportunity to
|
||||||
# do its best.
|
# do its best.
|
||||||
mkcmd('git grep (ignore)', [
|
mkcmd('git grep', [
|
||||||
'git', 'grep', '-I', '-n', '-i', pat,
|
'git', 'grep', '-I', '-n', '-i', pat,
|
||||||
], env={'LC_ALL': 'C'}),
|
], env={'LC_ALL': 'C'}),
|
||||||
mkcmd('rg (whitelist)', [
|
mkcmd('ugrep', [
|
||||||
'rg', '-n', '-i', '--no-ignore', '-tall', pat,
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
]),
|
'-n', '-i', pat, './',
|
||||||
mkcmd('ucg (whitelist)', ['ucg', '-i', pat]),
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
def bench_linux_re_literal_suffix(suite_dir):
|
def bench_linux_re_literal_suffix(suite_dir):
|
||||||
'''
|
'''
|
||||||
Benchmark the speed of a literal inside a regex.
|
Benchmark the speed of a literal inside a regex.
|
||||||
|
|
||||||
This, for example, inhibits a prefix byte optimization used
|
|
||||||
inside of Go's regex engine (relevant for sift and pt).
|
|
||||||
'''
|
'''
|
||||||
require(suite_dir, 'linux')
|
require(suite_dir, 'linux')
|
||||||
cwd = path.join(suite_dir, LINUX_DIR)
|
cwd = path.join(suite_dir, LINUX_DIR)
|
||||||
@@ -164,26 +156,23 @@ def bench_linux_re_literal_suffix(suite_dir):
|
|||||||
return Command(*args, **kwargs)
|
return Command(*args, **kwargs)
|
||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg (ignore)', ['rg', '-n', pat]),
|
mkcmd('rg', ['rg', '-n', pat]),
|
||||||
mkcmd('ag (ignore)', ['ag', '-s', pat]),
|
mkcmd('ag', ['ag', '-s', pat]),
|
||||||
mkcmd('pt (ignore)', ['pt', '-e', pat]),
|
|
||||||
mkcmd('sift (ignore)', SIFT + ['-n', '--git', pat]),
|
|
||||||
mkcmd(
|
mkcmd(
|
||||||
'git grep (ignore)',
|
'git grep',
|
||||||
['git', 'grep', '-E', '-I', '-n', pat],
|
['git', 'grep', '-E', '-I', '-n', pat],
|
||||||
env={'LC_ALL': 'C'},
|
env={'LC_ALL': 'C'},
|
||||||
),
|
),
|
||||||
mkcmd('rg (whitelist)', ['rg', '-n', '--no-ignore', '-tall', pat]),
|
mkcmd('ugrep', [
|
||||||
mkcmd('ucg (whitelist)', ['ucg', '--nosmart-case', pat]),
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
|
'-n', pat, './',
|
||||||
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
def bench_linux_word(suite_dir):
|
def bench_linux_word(suite_dir):
|
||||||
'''
|
'''
|
||||||
Benchmark use of the -w ("match word") flag in each tool.
|
Benchmark use of the -w ("match word") flag in each tool.
|
||||||
|
|
||||||
sift has a lot of trouble with this because it forces it into Go's
|
|
||||||
regex engine by surrounding the pattern with \b assertions.
|
|
||||||
'''
|
'''
|
||||||
require(suite_dir, 'linux')
|
require(suite_dir, 'linux')
|
||||||
cwd = path.join(suite_dir, LINUX_DIR)
|
cwd = path.join(suite_dir, LINUX_DIR)
|
||||||
@@ -194,28 +183,23 @@ def bench_linux_word(suite_dir):
|
|||||||
return Command(*args, **kwargs)
|
return Command(*args, **kwargs)
|
||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg (ignore)', ['rg', '-n', '-w', pat]),
|
mkcmd('rg', ['rg', '-n', '-w', pat]),
|
||||||
mkcmd('ag (ignore)', ['ag', '-s', '-w', pat]),
|
mkcmd('ag', ['ag', '-s', '-w', pat]),
|
||||||
mkcmd('pt (ignore)', ['pt', '-w', pat]),
|
|
||||||
mkcmd('sift (ignore)', SIFT + ['-n', '-w', '--git', pat]),
|
|
||||||
mkcmd(
|
mkcmd(
|
||||||
'git grep (ignore)',
|
'git grep',
|
||||||
['git', 'grep', '-E', '-I', '-n', '-w', pat],
|
['git', 'grep', '-E', '-I', '-n', '-w', pat],
|
||||||
env={'LC_ALL': 'C'},
|
env={'LC_ALL': 'C'},
|
||||||
),
|
),
|
||||||
mkcmd('rg (whitelist)', [
|
mkcmd('ugrep', [
|
||||||
'rg', '-n', '-w', '--no-ignore', '-tall', pat,
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
]),
|
'-n', '-w', pat, './',
|
||||||
mkcmd('ucg (whitelist)', ['ucg', '--nosmart-case', '-w', pat]),
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
def bench_linux_unicode_greek(suite_dir):
|
def bench_linux_unicode_greek(suite_dir):
|
||||||
'''
|
'''
|
||||||
Benchmark matching of a Unicode category.
|
Benchmark matching of a Unicode category.
|
||||||
|
|
||||||
Only three tools (ripgrep, sift and pt) support this. We omit
|
|
||||||
pt because it is too slow.
|
|
||||||
'''
|
'''
|
||||||
require(suite_dir, 'linux')
|
require(suite_dir, 'linux')
|
||||||
cwd = path.join(suite_dir, LINUX_DIR)
|
cwd = path.join(suite_dir, LINUX_DIR)
|
||||||
@@ -227,8 +211,10 @@ def bench_linux_unicode_greek(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg', ['rg', '-n', pat]),
|
mkcmd('rg', ['rg', '-n', pat]),
|
||||||
mkcmd('pt', ['pt', '-e', pat]),
|
mkcmd('ugrep', [
|
||||||
mkcmd('sift', SIFT + ['-n', '--git', pat]),
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
|
'-n', pat, './',
|
||||||
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -248,18 +234,20 @@ def bench_linux_unicode_greek_casei(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg', ['rg', '-n', '-i', pat]),
|
mkcmd('rg', ['rg', '-n', '-i', pat]),
|
||||||
mkcmd('pt', ['pt', '-i', '-e', pat]),
|
mkcmd('ugrep', [
|
||||||
mkcmd('sift', SIFT + ['-n', '-i', '--git', pat]),
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
|
'-n', '-i', pat, './',
|
||||||
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
def bench_linux_unicode_word(suite_dir):
|
def bench_linux_unicode_word(suite_dir):
|
||||||
'''
|
'''
|
||||||
Benchmark Unicode aware \w character class.
|
Benchmark Unicode aware \\w character class.
|
||||||
|
|
||||||
Only ripgrep and git-grep (with LC_ALL=en_US.UTF-8) actually get
|
Only ripgrep and git-grep (with LC_ALL=en_US.UTF-8) actually get
|
||||||
this right. Everything else uses the standard ASCII interpretation
|
this right. Everything else uses the standard ASCII interpretation
|
||||||
of \w.
|
of \\w.
|
||||||
'''
|
'''
|
||||||
require(suite_dir, 'linux')
|
require(suite_dir, 'linux')
|
||||||
cwd = path.join(suite_dir, LINUX_DIR)
|
cwd = path.join(suite_dir, LINUX_DIR)
|
||||||
@@ -270,26 +258,27 @@ def bench_linux_unicode_word(suite_dir):
|
|||||||
return Command(*args, **kwargs)
|
return Command(*args, **kwargs)
|
||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg (ignore)', ['rg', '-n', pat]),
|
mkcmd('rg', ['rg', '-n', pat]),
|
||||||
mkcmd('rg (ignore) (ASCII)', ['rg', '-n', '(?-u)' + pat]),
|
mkcmd('rg (ASCII)', ['rg', '-n', '(?-u)' + pat]),
|
||||||
mkcmd('ag (ignore) (ASCII)', ['ag', '-s', pat]),
|
mkcmd('ag (ASCII)', ['ag', '-s', pat]),
|
||||||
mkcmd('pt (ignore) (ASCII)', ['pt', '-e', pat]),
|
|
||||||
mkcmd('sift (ignore) (ASCII)', SIFT + ['-n', '--git', pat]),
|
|
||||||
mkcmd(
|
mkcmd(
|
||||||
'git grep (ignore)',
|
'git grep',
|
||||||
['git', 'grep', '-E', '-I', '-n', pat],
|
['git', 'grep', '-E', '-I', '-n', pat],
|
||||||
env={'LC_ALL': 'en_US.UTF-8'},
|
env={'LC_ALL': 'en_US.UTF-8'},
|
||||||
),
|
),
|
||||||
mkcmd(
|
mkcmd(
|
||||||
'git grep (ignore) (ASCII)',
|
'git grep (ASCII)',
|
||||||
['git', 'grep', '-E', '-I', '-n', pat],
|
['git', 'grep', '-E', '-I', '-n', pat],
|
||||||
env={'LC_ALL': 'C'},
|
env={'LC_ALL': 'C'},
|
||||||
),
|
),
|
||||||
mkcmd('rg (whitelist)', ['rg', '-n', '--no-ignore', '-tall', pat]),
|
mkcmd('ugrep', [
|
||||||
mkcmd('rg (whitelist) (ASCII)', [
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
'rg', '-n', '--no-ignore', '-tall', '(?-u)' + pat,
|
'-n', pat, './',
|
||||||
|
]),
|
||||||
|
mkcmd('ugrep (ASCII)', [
|
||||||
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
|
'-n', '-U', pat, './',
|
||||||
]),
|
]),
|
||||||
mkcmd('ucg (ASCII)', ['ucg', '--nosmart-case', pat]),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -311,26 +300,27 @@ def bench_linux_no_literal(suite_dir):
|
|||||||
return Command(*args, **kwargs)
|
return Command(*args, **kwargs)
|
||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg (ignore)', ['rg', '-n', pat]),
|
mkcmd('rg', ['rg', '-n', pat]),
|
||||||
mkcmd('rg (ignore) (ASCII)', ['rg', '-n', '(?-u)' + pat]),
|
mkcmd('rg (ASCII)', ['rg', '-n', '(?-u)' + pat]),
|
||||||
mkcmd('ag (ignore) (ASCII)', ['ag', '-s', pat]),
|
mkcmd('ag (ASCII)', ['ag', '-s', pat]),
|
||||||
mkcmd('pt (ignore) (ASCII)', ['pt', '-e', pat]),
|
|
||||||
mkcmd('sift (ignore) (ASCII)', SIFT + ['-n', '--git', pat]),
|
|
||||||
mkcmd(
|
mkcmd(
|
||||||
'git grep (ignore)',
|
'git grep',
|
||||||
['git', 'grep', '-E', '-I', '-n', pat],
|
['git', 'grep', '-E', '-I', '-n', pat],
|
||||||
env={'LC_ALL': 'en_US.UTF-8'},
|
env={'LC_ALL': 'en_US.UTF-8'},
|
||||||
),
|
),
|
||||||
mkcmd(
|
mkcmd(
|
||||||
'git grep (ignore) (ASCII)',
|
'git grep (ASCII)',
|
||||||
['git', 'grep', '-E', '-I', '-n', pat],
|
['git', 'grep', '-E', '-I', '-n', pat],
|
||||||
env={'LC_ALL': 'C'},
|
env={'LC_ALL': 'C'},
|
||||||
),
|
),
|
||||||
mkcmd('rg (whitelist)', ['rg', '-n', '--no-ignore', '-tall', pat]),
|
mkcmd('ugrep', [
|
||||||
mkcmd('rg (whitelist) (ASCII)', [
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
'rg', '-n', '--no-ignore', '-tall', '(?-u)' + pat,
|
'-n', pat, './',
|
||||||
|
]),
|
||||||
|
mkcmd('ugrep (ASCII)', [
|
||||||
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
|
'-n', '-U', pat, './',
|
||||||
]),
|
]),
|
||||||
mkcmd('ucg (whitelist) (ASCII)', ['ucg', '--nosmart-case', pat]),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -352,15 +342,17 @@ def bench_linux_alternates(suite_dir):
|
|||||||
return Command(*args, **kwargs)
|
return Command(*args, **kwargs)
|
||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg (ignore)', ['rg', '-n', pat]),
|
mkcmd('rg', ['rg', '-n', pat]),
|
||||||
mkcmd('ag (ignore)', ['ag', '-s', pat]),
|
mkcmd('ag', ['ag', '-s', pat]),
|
||||||
mkcmd(
|
mkcmd(
|
||||||
'git grep (ignore)',
|
'git grep',
|
||||||
['git', 'grep', '-E', '-I', '-n', pat],
|
['git', 'grep', '-E', '-I', '-n', pat],
|
||||||
env={'LC_ALL': 'C'},
|
env={'LC_ALL': 'C'},
|
||||||
),
|
),
|
||||||
mkcmd('rg (whitelist)', ['rg', '--no-ignore', '-n', pat]),
|
mkcmd('ugrep', [
|
||||||
mkcmd('ucg (whitelist)', ['ucg', '--nosmart-case', pat]),
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
|
'-n', pat, './',
|
||||||
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -375,15 +367,17 @@ def bench_linux_alternates_casei(suite_dir):
|
|||||||
return Command(*args, **kwargs)
|
return Command(*args, **kwargs)
|
||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
mkcmd('rg (ignore)', ['rg', '-n', '-i', pat]),
|
mkcmd('rg', ['rg', '-n', '-i', pat]),
|
||||||
mkcmd('ag (ignore)', ['ag', '-i', pat]),
|
mkcmd('ag', ['ag', '-i', pat]),
|
||||||
mkcmd(
|
mkcmd(
|
||||||
'git grep (ignore)',
|
'git grep',
|
||||||
['git', 'grep', '-E', '-I', '-n', '-i', pat],
|
['git', 'grep', '-E', '-I', '-n', '-i', pat],
|
||||||
env={'LC_ALL': 'C'},
|
env={'LC_ALL': 'C'},
|
||||||
),
|
),
|
||||||
mkcmd('rg (whitelist)', ['rg', '--no-ignore', '-n', '-i', pat]),
|
mkcmd('ugrep', [
|
||||||
mkcmd('ucg (whitelist)', ['ucg', '-i', pat]),
|
'ugrep', '-r', '--ignore-files', '--no-hidden', '-I',
|
||||||
|
'-n', '-i', pat, './',
|
||||||
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -398,15 +392,11 @@ def bench_subtitles_en_literal(suite_dir):
|
|||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg', ['rg', pat, en]),
|
Command('rg', ['rg', pat, en]),
|
||||||
Command('rg (no mmap)', ['rg', '--no-mmap', pat, en]),
|
Command('rg (no mmap)', ['rg', '--no-mmap', pat, en]),
|
||||||
Command('pt', ['pt', '-N', pat, en]),
|
Command('grep', ['grep', pat, en], env=GREP_ASCII),
|
||||||
Command('sift', ['sift', pat, en]),
|
|
||||||
Command('grep', ['grep', '-a', pat, en], env=GREP_ASCII),
|
|
||||||
Command('rg (lines)', ['rg', '-n', pat, en]),
|
Command('rg (lines)', ['rg', '-n', pat, en]),
|
||||||
Command('ag (lines)', ['ag', '-s', pat, en]),
|
Command('ag (lines)', ['ag', '-s', pat, en]),
|
||||||
Command('ucg (lines)', ['ucg', '--nosmart-case', pat, en]),
|
Command('grep (lines)', ['grep', '-n', pat, en], env=GREP_ASCII),
|
||||||
Command('pt (lines)', ['pt', pat, en]),
|
Command('ugrep (lines)', ['ugrep', '-n', pat, en])
|
||||||
Command('sift (lines)', ['sift', '-n', pat, en]),
|
|
||||||
Command('grep (lines)', ['grep', '-an', pat, en], env=GREP_ASCII),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -420,13 +410,11 @@ def bench_subtitles_en_literal_casei(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg', ['rg', '-i', pat, en]),
|
Command('rg', ['rg', '-i', pat, en]),
|
||||||
Command('grep', ['grep', '-ai', pat, en], env=GREP_UNICODE),
|
Command('grep', ['grep', '-i', pat, en], env=GREP_UNICODE),
|
||||||
Command('grep (ASCII)', [
|
Command('grep (ASCII)', ['grep', '-E', '-i', pat, en], env=GREP_ASCII),
|
||||||
'grep', '-E', '-ai', pat, en,
|
|
||||||
], env=GREP_ASCII),
|
|
||||||
Command('rg (lines)', ['rg', '-n', '-i', pat, en]),
|
Command('rg (lines)', ['rg', '-n', '-i', pat, en]),
|
||||||
Command('ag (lines) (ASCII)', ['ag', '-i', pat, en]),
|
Command('ag (lines) (ASCII)', ['ag', '-i', pat, en]),
|
||||||
Command('ucg (lines) (ASCII)', ['ucg', '-i', pat, en]),
|
Command('ugrep (lines)', ['ugrep', '-n', '-i', pat, en])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -443,12 +431,10 @@ def bench_subtitles_en_literal_word(suite_dir):
|
|||||||
'rg', '-n', r'(?-u:\b)' + pat + r'(?-u:\b)', en,
|
'rg', '-n', r'(?-u:\b)' + pat + r'(?-u:\b)', en,
|
||||||
]),
|
]),
|
||||||
Command('ag (ASCII)', ['ag', '-sw', pat, en]),
|
Command('ag (ASCII)', ['ag', '-sw', pat, en]),
|
||||||
Command('ucg (ASCII)', ['ucg', '--nosmart-case', pat, en]),
|
Command('grep (ASCII)', ['grep', '-nw', pat, en], env=GREP_ASCII),
|
||||||
Command('grep (ASCII)', [
|
Command('ugrep (ASCII)', ['ugrep', '-nw', pat, en]),
|
||||||
'grep', '-anw', pat, en,
|
|
||||||
], env=GREP_ASCII),
|
|
||||||
Command('rg', ['rg', '-nw', pat, en]),
|
Command('rg', ['rg', '-nw', pat, en]),
|
||||||
Command('grep', ['grep', '-anw', pat, en], env=GREP_UNICODE),
|
Command('grep', ['grep', '-nw', pat, en], env=GREP_UNICODE),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -469,14 +455,10 @@ def bench_subtitles_en_alternate(suite_dir):
|
|||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg (lines)', ['rg', '-n', pat, en]),
|
Command('rg (lines)', ['rg', '-n', pat, en]),
|
||||||
Command('ag (lines)', ['ag', '-s', pat, en]),
|
Command('ag (lines)', ['ag', '-s', pat, en]),
|
||||||
Command('ucg (lines)', ['ucg', '--nosmart-case', pat, en]),
|
Command('grep (lines)', ['grep', '-E', '-n', pat, en], env=GREP_ASCII),
|
||||||
Command('grep (lines)', [
|
Command('ugrep (lines)', ['ugrep', '-n', pat, en]),
|
||||||
'grep', '-E', '-an', pat, en,
|
|
||||||
], env=GREP_ASCII),
|
|
||||||
Command('rg', ['rg', pat, en]),
|
Command('rg', ['rg', pat, en]),
|
||||||
Command('grep', [
|
Command('grep', ['grep', '-E', pat, en], env=GREP_ASCII),
|
||||||
'grep', '-E', '-a', pat, en,
|
|
||||||
], env=GREP_ASCII),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -496,12 +478,12 @@ def bench_subtitles_en_alternate_casei(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('ag (ASCII)', ['ag', '-s', '-i', pat, en]),
|
Command('ag (ASCII)', ['ag', '-s', '-i', pat, en]),
|
||||||
Command('ucg (ASCII)', ['ucg', '-i', pat, en]),
|
|
||||||
Command('grep (ASCII)', [
|
Command('grep (ASCII)', [
|
||||||
'grep', '-E', '-ani', pat, en,
|
'grep', '-E', '-ni', pat, en,
|
||||||
], env=GREP_ASCII),
|
], env=GREP_ASCII),
|
||||||
|
Command('ugrep (ASCII)', ['ugrep', '-n', '-i', pat, en]),
|
||||||
Command('rg', ['rg', '-n', '-i', pat, en]),
|
Command('rg', ['rg', '-n', '-i', pat, en]),
|
||||||
Command('grep', ['grep', '-E', '-ani', pat, en], env=GREP_UNICODE),
|
Command('grep', ['grep', '-E', '-ni', pat, en], env=GREP_UNICODE),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -515,13 +497,12 @@ def bench_subtitles_en_surrounding_words(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg', ['rg', '-n', pat, en]),
|
Command('rg', ['rg', '-n', pat, en]),
|
||||||
Command('grep', ['grep', '-E', '-an', pat, en], env=GREP_UNICODE),
|
Command('grep', ['grep', '-E', '-n', pat, en], env=GREP_UNICODE),
|
||||||
|
Command('ugrep', ['ugrep', '-n', pat, en]),
|
||||||
Command('rg (ASCII)', ['rg', '-n', '(?-u)' + pat, en]),
|
Command('rg (ASCII)', ['rg', '-n', '(?-u)' + pat, en]),
|
||||||
Command('ag (ASCII)', ['ag', '-s', pat, en]),
|
Command('ag (ASCII)', ['ag', '-s', pat, en]),
|
||||||
Command('ucg (ASCII)', ['ucg', '--nosmart-case', pat, en]),
|
Command('grep (ASCII)', ['grep', '-E', '-n', pat, en], env=GREP_ASCII),
|
||||||
Command('grep (ASCII)', [
|
Command('ugrep (ASCII)', ['ugrep', '-n', '-U', pat, en])
|
||||||
'grep', '-E', '-an', pat, en,
|
|
||||||
], env=GREP_ASCII),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -540,12 +521,11 @@ def bench_subtitles_en_no_literal(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg', ['rg', '-n', pat, en]),
|
Command('rg', ['rg', '-n', pat, en]),
|
||||||
|
Command('ugrep', ['ugrep', '-n', pat, en]),
|
||||||
Command('rg (ASCII)', ['rg', '-n', '(?-u)' + pat, en]),
|
Command('rg (ASCII)', ['rg', '-n', '(?-u)' + pat, en]),
|
||||||
Command('ag (ASCII)', ['ag', '-s', pat, en]),
|
Command('ag (ASCII)', ['ag', '-s', pat, en]),
|
||||||
Command('ucg (ASCII)', ['ucg', '--nosmart-case', pat, en]),
|
Command('grep (ASCII)', ['grep', '-E', '-n', pat, en], env=GREP_ASCII),
|
||||||
Command('grep (ASCII)', [
|
Command('ugrep (ASCII)', ['ugrep', '-n', '-U', pat, en])
|
||||||
'grep', '-E', '-an', pat, en,
|
|
||||||
], env=GREP_ASCII),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -560,15 +540,15 @@ def bench_subtitles_ru_literal(suite_dir):
|
|||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg', ['rg', pat, ru]),
|
Command('rg', ['rg', pat, ru]),
|
||||||
Command('rg (no mmap)', ['rg', '--no-mmap', pat, ru]),
|
Command('rg (no mmap)', ['rg', '--no-mmap', pat, ru]),
|
||||||
Command('pt', ['pt', '-N', pat, ru]),
|
Command('grep', ['grep', pat, ru], env=GREP_ASCII),
|
||||||
Command('sift', ['sift', pat, ru]),
|
|
||||||
Command('grep', ['grep', '-a', pat, ru], env=GREP_ASCII),
|
|
||||||
Command('rg (lines)', ['rg', '-n', pat, ru]),
|
Command('rg (lines)', ['rg', '-n', pat, ru]),
|
||||||
Command('ag (lines)', ['ag', '-s', pat, ru]),
|
Command('ag (lines)', ['ag', '-s', pat, ru]),
|
||||||
Command('ucg (lines)', ['ucg', '--nosmart-case', pat, ru]),
|
Command('grep (lines)', ['grep', '-n', pat, ru], env=GREP_ASCII),
|
||||||
Command('pt (lines)', ['pt', pat, ru]),
|
# ugrep incorrectly identifies this corpus as binary, but it is
|
||||||
Command('sift (lines)', ['sift', '-n', pat, ru]),
|
# entirely valid UTF-8. So we tell ugrep to always treat the corpus
|
||||||
Command('grep (lines)', ['grep', '-an', pat, ru], env=GREP_ASCII),
|
# as text even though this technically gives it an edge over other
|
||||||
|
# tools. (It no longer needs to check for binary data.)
|
||||||
|
Command('ugrep (lines)', ['ugrep', '-a', '-n', pat, ru])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -582,13 +562,12 @@ def bench_subtitles_ru_literal_casei(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg', ['rg', '-i', pat, ru]),
|
Command('rg', ['rg', '-i', pat, ru]),
|
||||||
Command('grep', ['grep', '-ai', pat, ru], env=GREP_UNICODE),
|
Command('grep', ['grep', '-i', pat, ru], env=GREP_UNICODE),
|
||||||
Command('grep (ASCII)', [
|
Command('grep (ASCII)', ['grep', '-E', '-i', pat, ru], env=GREP_ASCII),
|
||||||
'grep', '-E', '-ai', pat, ru,
|
|
||||||
], env=GREP_ASCII),
|
|
||||||
Command('rg (lines)', ['rg', '-n', '-i', pat, ru]),
|
Command('rg (lines)', ['rg', '-n', '-i', pat, ru]),
|
||||||
Command('ag (lines) (ASCII)', ['ag', '-i', pat, ru]),
|
Command('ag (lines) (ASCII)', ['ag', '-i', pat, ru]),
|
||||||
Command('ucg (lines) (ASCII)', ['ucg', '-i', pat, ru]),
|
# See bench_subtitles_ru_literal for why we use '-a' here.
|
||||||
|
Command('ugrep (lines) (ASCII)', ['ugrep', '-a', '-n', '-i', pat, ru])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -602,15 +581,20 @@ def bench_subtitles_ru_literal_word(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg (ASCII)', [
|
Command('rg (ASCII)', [
|
||||||
'rg', '-n', r'(?-u:\b)' + pat + r'(?-u:\b)', ru,
|
# You might think we'd use \b here for word boundaries, but both
|
||||||
|
# GNU grep and ripgrep implement -w with the formulation below.
|
||||||
|
# Since we can't use Unicode in a pattern and disable Unicode word
|
||||||
|
# boundaries, we just hand-jam this ourselves.
|
||||||
|
'rg', '-n', r'(?-u:^|\W)' + pat + r'(?-u:$|\W)', ru,
|
||||||
]),
|
]),
|
||||||
Command('ag (ASCII)', ['ag', '-sw', pat, ru]),
|
Command('ag (ASCII)', ['ag', '-sw', pat, ru]),
|
||||||
Command('ucg (ASCII)', ['ucg', '--nosmart-case', pat, ru]),
|
|
||||||
Command('grep (ASCII)', [
|
Command('grep (ASCII)', [
|
||||||
'grep', '-anw', pat, ru,
|
'grep', '-nw', pat, ru,
|
||||||
], env=GREP_ASCII),
|
], env=GREP_ASCII),
|
||||||
|
# See bench_subtitles_ru_literal for why we use '-a' here.
|
||||||
|
Command('ugrep (ASCII)', ['ugrep', '-anw', pat, ru]),
|
||||||
Command('rg', ['rg', '-nw', pat, ru]),
|
Command('rg', ['rg', '-nw', pat, ru]),
|
||||||
Command('grep', ['grep', '-anw', pat, ru], env=GREP_UNICODE),
|
Command('grep', ['grep', '-nw', pat, ru], env=GREP_UNICODE),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -631,14 +615,11 @@ def bench_subtitles_ru_alternate(suite_dir):
|
|||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg (lines)', ['rg', '-n', pat, ru]),
|
Command('rg (lines)', ['rg', '-n', pat, ru]),
|
||||||
Command('ag (lines)', ['ag', '-s', pat, ru]),
|
Command('ag (lines)', ['ag', '-s', pat, ru]),
|
||||||
Command('ucg (lines)', ['ucg', '--nosmart-case', pat, ru]),
|
Command('grep (lines)', ['grep', '-E', '-n', pat, ru], env=GREP_ASCII),
|
||||||
Command('grep (lines)', [
|
# See bench_subtitles_ru_literal for why we use '-a' here.
|
||||||
'grep', '-E', '-an', pat, ru,
|
Command('ugrep (lines)', ['ugrep', '-an', pat, ru]),
|
||||||
], env=GREP_ASCII),
|
|
||||||
Command('rg', ['rg', pat, ru]),
|
Command('rg', ['rg', pat, ru]),
|
||||||
Command('grep', [
|
Command('grep', ['grep', '-E', pat, ru], env=GREP_ASCII),
|
||||||
'grep', '-E', '-a', pat, ru,
|
|
||||||
], env=GREP_ASCII),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -658,12 +639,13 @@ def bench_subtitles_ru_alternate_casei(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('ag (ASCII)', ['ag', '-s', '-i', pat, ru]),
|
Command('ag (ASCII)', ['ag', '-s', '-i', pat, ru]),
|
||||||
Command('ucg (ASCII)', ['ucg', '-i', pat, ru]),
|
|
||||||
Command('grep (ASCII)', [
|
Command('grep (ASCII)', [
|
||||||
'grep', '-E', '-ani', pat, ru,
|
'grep', '-E', '-ni', pat, ru,
|
||||||
], env=GREP_ASCII),
|
], env=GREP_ASCII),
|
||||||
|
# See bench_subtitles_ru_literal for why we use '-a' here.
|
||||||
|
Command('ugrep (ASCII)', ['ugrep', '-ani', pat, ru]),
|
||||||
Command('rg', ['rg', '-n', '-i', pat, ru]),
|
Command('rg', ['rg', '-n', '-i', pat, ru]),
|
||||||
Command('grep', ['grep', '-E', '-ani', pat, ru], env=GREP_UNICODE),
|
Command('grep', ['grep', '-E', '-ni', pat, ru], env=GREP_UNICODE),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -677,12 +659,12 @@ def bench_subtitles_ru_surrounding_words(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg', ['rg', '-n', pat, ru]),
|
Command('rg', ['rg', '-n', pat, ru]),
|
||||||
Command('grep', ['grep', '-E', '-an', pat, ru], env=GREP_UNICODE),
|
Command('grep', ['grep', '-E', '-n', pat, ru], env=GREP_UNICODE),
|
||||||
|
Command('ugrep', ['ugrep', '-an', pat, ru]),
|
||||||
Command('ag (ASCII)', ['ag', '-s', pat, ru]),
|
Command('ag (ASCII)', ['ag', '-s', pat, ru]),
|
||||||
Command('ucg (ASCII)', ['ucg', '--nosmart-case', pat, ru]),
|
Command('grep (ASCII)', ['grep', '-E', '-n', pat, ru], env=GREP_ASCII),
|
||||||
Command('grep (ASCII)', [
|
# See bench_subtitles_ru_literal for why we use '-a' here.
|
||||||
'grep', '-E', '-an', pat, ru,
|
Command('ugrep (ASCII)', ['ugrep', '-a', '-n', '-U', pat, ru]),
|
||||||
], env=GREP_ASCII),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -701,12 +683,13 @@ def bench_subtitles_ru_no_literal(suite_dir):
|
|||||||
|
|
||||||
return Benchmark(pattern=pat, commands=[
|
return Benchmark(pattern=pat, commands=[
|
||||||
Command('rg', ['rg', '-n', pat, ru]),
|
Command('rg', ['rg', '-n', pat, ru]),
|
||||||
|
# See bench_subtitles_ru_literal for why we use '-a' here.
|
||||||
|
Command('ugrep', ['ugrep', '-an', pat, ru]),
|
||||||
Command('rg (ASCII)', ['rg', '-n', '(?-u)' + pat, ru]),
|
Command('rg (ASCII)', ['rg', '-n', '(?-u)' + pat, ru]),
|
||||||
Command('ag (ASCII)', ['ag', '-s', pat, ru]),
|
Command('ag (ASCII)', ['ag', '-s', pat, ru]),
|
||||||
Command('ucg (ASCII)', ['ucg', '--nosmart-case', pat, ru]),
|
Command('grep (ASCII)', ['grep', '-E', '-n', pat, ru], env=GREP_ASCII),
|
||||||
Command('grep (ASCII)', [
|
# See bench_subtitles_ru_literal for why we use '-a' here.
|
||||||
'grep', '-E', '-an', pat, ru,
|
Command('ugrep (ASCII)', ['ugrep', '-anU', pat, ru])
|
||||||
], env=GREP_ASCII),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -756,7 +739,7 @@ class Benchmark(object):
|
|||||||
def __init__(self, name=None, pattern=None, commands=None,
|
def __init__(self, name=None, pattern=None, commands=None,
|
||||||
warmup_count=1, count=3, line_count=True,
|
warmup_count=1, count=3, line_count=True,
|
||||||
allow_missing_commands=False,
|
allow_missing_commands=False,
|
||||||
disabled_cmds=None):
|
disabled_cmds=None, order=0):
|
||||||
'''
|
'''
|
||||||
Create a single benchmark.
|
Create a single benchmark.
|
||||||
|
|
||||||
@@ -792,6 +775,8 @@ class Benchmark(object):
|
|||||||
will simply skip it.
|
will simply skip it.
|
||||||
:param list(str) disabled_cmds:
|
:param list(str) disabled_cmds:
|
||||||
A list of commands to skip.
|
A list of commands to skip.
|
||||||
|
:param int order:
|
||||||
|
An integer indicating the sequence number of this benchmark.
|
||||||
'''
|
'''
|
||||||
self.name = name
|
self.name = name
|
||||||
self.pattern = pattern
|
self.pattern = pattern
|
||||||
@@ -801,6 +786,7 @@ class Benchmark(object):
|
|||||||
self.line_count = line_count
|
self.line_count = line_count
|
||||||
self.allow_missing_commands = allow_missing_commands
|
self.allow_missing_commands = allow_missing_commands
|
||||||
self.disabled_cmds = set(disabled_cmds or [])
|
self.disabled_cmds = set(disabled_cmds or [])
|
||||||
|
self.order = order
|
||||||
|
|
||||||
def raise_if_missing(self):
|
def raise_if_missing(self):
|
||||||
'''
|
'''
|
||||||
@@ -894,7 +880,7 @@ class Result(object):
|
|||||||
'''
|
'''
|
||||||
Create a new set of results, initially empty.
|
Create a new set of results, initially empty.
|
||||||
|
|
||||||
:param Benchmarl benchmark:
|
:param Benchmark benchmark:
|
||||||
The benchmark that produced these results.
|
The benchmark that produced these results.
|
||||||
'''
|
'''
|
||||||
self.benchmark = benchmark
|
self.benchmark = benchmark
|
||||||
@@ -1088,7 +1074,7 @@ def download_subtitles_en(suite_dir):
|
|||||||
# benchmarks finish in a reasonable time.
|
# benchmarks finish in a reasonable time.
|
||||||
with open(path.join(subtitle_dir, en_path_sample), 'wb+') as f:
|
with open(path.join(subtitle_dir, en_path_sample), 'wb+') as f:
|
||||||
run_cmd(
|
run_cmd(
|
||||||
['head', '-n', '32722372', en_path],
|
['head', '-n', '55000000', en_path],
|
||||||
cwd=subtitle_dir, stdout=f)
|
cwd=subtitle_dir, stdout=f)
|
||||||
|
|
||||||
|
|
||||||
@@ -1163,19 +1149,22 @@ def collect_benchmarks(suite_dir, filter_pat=None,
|
|||||||
requires corpora that are missing, then a log message is
|
requires corpora that are missing, then a log message is
|
||||||
emitted to stderr and it is not yielded.
|
emitted to stderr and it is not yielded.
|
||||||
'''
|
'''
|
||||||
for fun in sorted(globals()):
|
benchmarks = []
|
||||||
if not fun.startswith('bench_'):
|
for global_name in globals():
|
||||||
|
if not global_name.startswith('bench_'):
|
||||||
continue
|
continue
|
||||||
name = re.sub('^bench_', '', fun)
|
name = re.sub('^bench_', '', global_name)
|
||||||
if filter_pat is not None and not re.search(filter_pat, name):
|
if filter_pat is not None and not re.search(filter_pat, name):
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
benchmark = globals()[fun](suite_dir)
|
fun = globals()[global_name]
|
||||||
|
benchmark = fun(suite_dir)
|
||||||
benchmark.name = name
|
benchmark.name = name
|
||||||
benchmark.warmup_count = warmup_iter
|
benchmark.warmup_count = warmup_iter
|
||||||
benchmark.count = bench_iter
|
benchmark.count = bench_iter
|
||||||
benchmark.allow_missing_commands = allow_missing_commands
|
benchmark.allow_missing_commands = allow_missing_commands
|
||||||
benchmark.disabled_cmds = disabled_cmds
|
benchmark.disabled_cmds = disabled_cmds
|
||||||
|
benchmark.order = fun.__code__.co_firstlineno
|
||||||
benchmark.raise_if_missing()
|
benchmark.raise_if_missing()
|
||||||
except MissingDependencies as e:
|
except MissingDependencies as e:
|
||||||
eprint(
|
eprint(
|
||||||
@@ -1190,7 +1179,8 @@ def collect_benchmarks(suite_dir, filter_pat=None,
|
|||||||
'(run with --allow-missing to run incomplete benchmarks)'
|
'(run with --allow-missing to run incomplete benchmarks)'
|
||||||
eprint(fmt % (', '.join(e.missing_names), name))
|
eprint(fmt % (', '.join(e.missing_names), name))
|
||||||
continue
|
continue
|
||||||
yield benchmark
|
benchmarks.append(benchmark)
|
||||||
|
return sorted(benchmarks, key=lambda b: b.order)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
37
benchsuite/runs/2020-10-14-archlinux-frink/README.md
Normal file
37
benchsuite/runs/2020-10-14-archlinux-frink/README.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
This directory contains updated benchmarks as of 2020-10-14. They were captured
|
||||||
|
via the benchsuite script at `benchsuite/benchsuite` from the root of this
|
||||||
|
repository. The command that was run:
|
||||||
|
|
||||||
|
$ ./benchsuite \
|
||||||
|
--dir /tmp/benchsuite \
|
||||||
|
--raw runs/2020-10-14-archlinux-frink/raw.csv \
|
||||||
|
--warmup-iter 1 \
|
||||||
|
--bench-iter 5
|
||||||
|
|
||||||
|
The versions of each tool are as follows:
|
||||||
|
|
||||||
|
$ rg --version
|
||||||
|
ripgrep 12.1.1 (rev def993bad1)
|
||||||
|
-SIMD -AVX (compiled)
|
||||||
|
+SIMD +AVX (runtime)
|
||||||
|
|
||||||
|
$ grep -V
|
||||||
|
grep (GNU grep) 3.4
|
||||||
|
|
||||||
|
$ ag -V
|
||||||
|
ag version 2.2.0
|
||||||
|
|
||||||
|
Features:
|
||||||
|
+jit +lzma +zlib
|
||||||
|
|
||||||
|
$ git --version
|
||||||
|
git version 2.28.0
|
||||||
|
|
||||||
|
$ ugrep --version
|
||||||
|
ugrep 3.0.2 x86_64-pc-linux-gnu +avx2 +pcre2_jit +zlib +bzip2 +lzma +lz4
|
||||||
|
License BSD-3-Clause: <https://opensource.org/licenses/BSD-3-Clause>
|
||||||
|
Written by Robert van Engelen and others: <https://github.com/Genivia/ugrep>
|
||||||
|
|
||||||
|
The version of ripgrep used was compiled from source on commit def993bad1:
|
||||||
|
|
||||||
|
$ cargo build --release --features 'pcre2'
|
||||||
671
benchsuite/runs/2020-10-14-archlinux-frink/raw.csv
Normal file
671
benchsuite/runs/2020-10-14-archlinux-frink/raw.csv
Normal file
@@ -0,0 +1,671 @@
|
|||||||
|
benchmark,warmup_iter,iter,name,command,duration,lines,env
|
||||||
|
linux_literal_default,1,5,rg,rg PM_RESUME,0.12675833702087402,19,
|
||||||
|
linux_literal_default,1,5,rg,rg PM_RESUME,0.1196434497833252,19,
|
||||||
|
linux_literal_default,1,5,rg,rg PM_RESUME,0.12096214294433594,19,
|
||||||
|
linux_literal_default,1,5,rg,rg PM_RESUME,0.1257617473602295,19,
|
||||||
|
linux_literal_default,1,5,rg,rg PM_RESUME,0.12903356552124023,19,
|
||||||
|
linux_literal_default,1,5,ag,ag PM_RESUME,0.8575565814971924,19,
|
||||||
|
linux_literal_default,1,5,ag,ag PM_RESUME,0.9113664627075195,19,
|
||||||
|
linux_literal_default,1,5,ag,ag PM_RESUME,0.944256067276001,19,
|
||||||
|
linux_literal_default,1,5,ag,ag PM_RESUME,0.5309450626373291,19,
|
||||||
|
linux_literal_default,1,5,ag,ag PM_RESUME,0.6105470657348633,19,
|
||||||
|
linux_literal_default,1,5,git grep,git grep PM_RESUME,0.49039149284362793,19,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,5,git grep,git grep PM_RESUME,0.48095154762268066,19,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,5,git grep,git grep PM_RESUME,0.48927950859069824,19,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,5,git grep,git grep PM_RESUME,0.47182321548461914,19,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,5,git grep,git grep PM_RESUME,0.46923041343688965,19,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,5,ugrep,ugrep -r PM_RESUME ./,0.13612771034240723,19,
|
||||||
|
linux_literal_default,1,5,ugrep,ugrep -r PM_RESUME ./,0.13677191734313965,19,
|
||||||
|
linux_literal_default,1,5,ugrep,ugrep -r PM_RESUME ./,0.13688087463378906,19,
|
||||||
|
linux_literal_default,1,5,ugrep,ugrep -r PM_RESUME ./,0.13218474388122559,19,
|
||||||
|
linux_literal_default,1,5,ugrep,ugrep -r PM_RESUME ./,0.13851046562194824,19,
|
||||||
|
linux_literal_default,1,5,grep,grep -r PM_RESUME ./,1.1436240673065186,19,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,5,grep,grep -r PM_RESUME ./,1.1436970233917236,19,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,5,grep,grep -r PM_RESUME ./,1.1542651653289795,19,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,5,grep,grep -r PM_RESUME ./,1.14790940284729,19,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,5,grep,grep -r PM_RESUME ./,1.1441664695739746,19,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal,1,5,rg,rg -n PM_RESUME,0.134232759475708,19,
|
||||||
|
linux_literal,1,5,rg,rg -n PM_RESUME,0.12477993965148926,19,
|
||||||
|
linux_literal,1,5,rg,rg -n PM_RESUME,0.11790871620178223,19,
|
||||||
|
linux_literal,1,5,rg,rg -n PM_RESUME,0.13471150398254395,19,
|
||||||
|
linux_literal,1,5,rg,rg -n PM_RESUME,0.13730239868164062,19,
|
||||||
|
linux_literal,1,5,rg (mmap),rg -n --mmap PM_RESUME,1.2953157424926758,19,
|
||||||
|
linux_literal,1,5,rg (mmap),rg -n --mmap PM_RESUME,1.3263885974884033,19,
|
||||||
|
linux_literal,1,5,rg (mmap),rg -n --mmap PM_RESUME,1.320932388305664,19,
|
||||||
|
linux_literal,1,5,rg (mmap),rg -n --mmap PM_RESUME,1.3446438312530518,19,
|
||||||
|
linux_literal,1,5,rg (mmap),rg -n --mmap PM_RESUME,1.3919141292572021,19,
|
||||||
|
linux_literal,1,5,ag (mmap),ag -s PM_RESUME,0.7901346683502197,19,
|
||||||
|
linux_literal,1,5,ag (mmap),ag -s PM_RESUME,0.9647164344787598,19,
|
||||||
|
linux_literal,1,5,ag (mmap),ag -s PM_RESUME,0.8800022602081299,19,
|
||||||
|
linux_literal,1,5,ag (mmap),ag -s PM_RESUME,0.9307558536529541,19,
|
||||||
|
linux_literal,1,5,ag (mmap),ag -s PM_RESUME,0.8346366882324219,19,
|
||||||
|
linux_literal,1,5,git grep,git grep -I -n PM_RESUME,0.4694955348968506,19,LC_ALL=C
|
||||||
|
linux_literal,1,5,git grep,git grep -I -n PM_RESUME,0.4620368480682373,19,LC_ALL=C
|
||||||
|
linux_literal,1,5,git grep,git grep -I -n PM_RESUME,0.4673285484313965,19,LC_ALL=C
|
||||||
|
linux_literal,1,5,git grep,git grep -I -n PM_RESUME,0.4570960998535156,19,LC_ALL=C
|
||||||
|
linux_literal,1,5,git grep,git grep -I -n PM_RESUME,0.4648761749267578,19,LC_ALL=C
|
||||||
|
linux_literal,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n PM_RESUME ./,0.3233473300933838,19,
|
||||||
|
linux_literal,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n PM_RESUME ./,0.3199331760406494,19,
|
||||||
|
linux_literal,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n PM_RESUME ./,0.29825615882873535,19,
|
||||||
|
linux_literal,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n PM_RESUME ./,0.3003232479095459,19,
|
||||||
|
linux_literal,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n PM_RESUME ./,0.30283141136169434,19,
|
||||||
|
linux_literal_casei,1,5,rg,rg -n -i PM_RESUME,0.1349015235900879,456,
|
||||||
|
linux_literal_casei,1,5,rg,rg -n -i PM_RESUME,0.1277780532836914,456,
|
||||||
|
linux_literal_casei,1,5,rg,rg -n -i PM_RESUME,0.1251516342163086,456,
|
||||||
|
linux_literal_casei,1,5,rg,rg -n -i PM_RESUME,0.12959671020507812,456,
|
||||||
|
linux_literal_casei,1,5,rg,rg -n -i PM_RESUME,0.1374528408050537,456,
|
||||||
|
linux_literal_casei,1,5,rg (mmap),rg -n -i --mmap PM_RESUME,1.3468265533447266,456,
|
||||||
|
linux_literal_casei,1,5,rg (mmap),rg -n -i --mmap PM_RESUME,1.3552894592285156,456,
|
||||||
|
linux_literal_casei,1,5,rg (mmap),rg -n -i --mmap PM_RESUME,1.3028552532196045,456,
|
||||||
|
linux_literal_casei,1,5,rg (mmap),rg -n -i --mmap PM_RESUME,1.336735725402832,456,
|
||||||
|
linux_literal_casei,1,5,rg (mmap),rg -n -i --mmap PM_RESUME,1.338634729385376,456,
|
||||||
|
linux_literal_casei,1,5,ag (mmap),ag -i PM_RESUME,0.5562450885772705,456,
|
||||||
|
linux_literal_casei,1,5,ag (mmap),ag -i PM_RESUME,0.7324790954589844,456,
|
||||||
|
linux_literal_casei,1,5,ag (mmap),ag -i PM_RESUME,0.8382794857025146,456,
|
||||||
|
linux_literal_casei,1,5,ag (mmap),ag -i PM_RESUME,0.5817627906799316,456,
|
||||||
|
linux_literal_casei,1,5,ag (mmap),ag -i PM_RESUME,0.5771033763885498,456,
|
||||||
|
linux_literal_casei,1,5,git grep,git grep -I -n -i PM_RESUME,0.48885059356689453,456,LC_ALL=C
|
||||||
|
linux_literal_casei,1,5,git grep,git grep -I -n -i PM_RESUME,0.4838893413543701,456,LC_ALL=C
|
||||||
|
linux_literal_casei,1,5,git grep,git grep -I -n -i PM_RESUME,0.48733997344970703,456,LC_ALL=C
|
||||||
|
linux_literal_casei,1,5,git grep,git grep -I -n -i PM_RESUME,0.4765594005584717,456,LC_ALL=C
|
||||||
|
linux_literal_casei,1,5,git grep,git grep -I -n -i PM_RESUME,0.47402334213256836,456,LC_ALL=C
|
||||||
|
linux_literal_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i PM_RESUME ./,0.3075406551361084,456,
|
||||||
|
linux_literal_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i PM_RESUME ./,0.2922379970550537,456,
|
||||||
|
linux_literal_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i PM_RESUME ./,0.2901036739349365,456,
|
||||||
|
linux_literal_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i PM_RESUME ./,0.2723674774169922,456,
|
||||||
|
linux_literal_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i PM_RESUME ./,0.2762429714202881,456,
|
||||||
|
linux_re_literal_suffix,1,5,rg,rg -n [A-Z]+_RESUME,0.12853646278381348,1944,
|
||||||
|
linux_re_literal_suffix,1,5,rg,rg -n [A-Z]+_RESUME,0.1190040111541748,1944,
|
||||||
|
linux_re_literal_suffix,1,5,rg,rg -n [A-Z]+_RESUME,0.14054393768310547,1944,
|
||||||
|
linux_re_literal_suffix,1,5,rg,rg -n [A-Z]+_RESUME,0.12263894081115723,1944,
|
||||||
|
linux_re_literal_suffix,1,5,rg,rg -n [A-Z]+_RESUME,0.12101268768310547,1944,
|
||||||
|
linux_re_literal_suffix,1,5,ag,ag -s [A-Z]+_RESUME,0.9220716953277588,1944,
|
||||||
|
linux_re_literal_suffix,1,5,ag,ag -s [A-Z]+_RESUME,1.009810209274292,1944,
|
||||||
|
linux_re_literal_suffix,1,5,ag,ag -s [A-Z]+_RESUME,0.9654982089996338,1944,
|
||||||
|
linux_re_literal_suffix,1,5,ag,ag -s [A-Z]+_RESUME,1.2758586406707764,1944,
|
||||||
|
linux_re_literal_suffix,1,5,ag,ag -s [A-Z]+_RESUME,1.0480666160583496,1944,
|
||||||
|
linux_re_literal_suffix,1,5,git grep,git grep -E -I -n [A-Z]+_RESUME,1.1811027526855469,1944,LC_ALL=C
|
||||||
|
linux_re_literal_suffix,1,5,git grep,git grep -E -I -n [A-Z]+_RESUME,1.1824719905853271,1944,LC_ALL=C
|
||||||
|
linux_re_literal_suffix,1,5,git grep,git grep -E -I -n [A-Z]+_RESUME,1.2052066326141357,1944,LC_ALL=C
|
||||||
|
linux_re_literal_suffix,1,5,git grep,git grep -E -I -n [A-Z]+_RESUME,1.224193811416626,1944,LC_ALL=C
|
||||||
|
linux_re_literal_suffix,1,5,git grep,git grep -E -I -n [A-Z]+_RESUME,1.2896029949188232,1944,LC_ALL=C
|
||||||
|
linux_re_literal_suffix,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n [A-Z]+_RESUME ./,0.5580098628997803,1944,
|
||||||
|
linux_re_literal_suffix,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n [A-Z]+_RESUME ./,0.5409820079803467,1944,
|
||||||
|
linux_re_literal_suffix,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n [A-Z]+_RESUME ./,0.5436761379241943,1944,
|
||||||
|
linux_re_literal_suffix,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n [A-Z]+_RESUME ./,0.5317332744598389,1944,
|
||||||
|
linux_re_literal_suffix,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n [A-Z]+_RESUME ./,0.5662341117858887,1944,
|
||||||
|
linux_word,1,5,rg,rg -n -w PM_RESUME,0.13112211227416992,6,
|
||||||
|
linux_word,1,5,rg,rg -n -w PM_RESUME,0.13633346557617188,6,
|
||||||
|
linux_word,1,5,rg,rg -n -w PM_RESUME,0.1308743953704834,6,
|
||||||
|
linux_word,1,5,rg,rg -n -w PM_RESUME,0.13691973686218262,6,
|
||||||
|
linux_word,1,5,rg,rg -n -w PM_RESUME,0.1369326114654541,6,
|
||||||
|
linux_word,1,5,ag,ag -s -w PM_RESUME,0.5965347290039062,6,
|
||||||
|
linux_word,1,5,ag,ag -s -w PM_RESUME,0.8891518115997314,6,
|
||||||
|
linux_word,1,5,ag,ag -s -w PM_RESUME,0.5207972526550293,6,
|
||||||
|
linux_word,1,5,ag,ag -s -w PM_RESUME,0.5551142692565918,6,
|
||||||
|
linux_word,1,5,ag,ag -s -w PM_RESUME,0.5308854579925537,6,
|
||||||
|
linux_word,1,5,git grep,git grep -E -I -n -w PM_RESUME,0.45984363555908203,6,LC_ALL=C
|
||||||
|
linux_word,1,5,git grep,git grep -E -I -n -w PM_RESUME,0.47351694107055664,6,LC_ALL=C
|
||||||
|
linux_word,1,5,git grep,git grep -E -I -n -w PM_RESUME,0.5011758804321289,6,LC_ALL=C
|
||||||
|
linux_word,1,5,git grep,git grep -E -I -n -w PM_RESUME,0.45740509033203125,6,LC_ALL=C
|
||||||
|
linux_word,1,5,git grep,git grep -E -I -n -w PM_RESUME,0.46122002601623535,6,LC_ALL=C
|
||||||
|
linux_word,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -w PM_RESUME ./,0.3174629211425781,6,
|
||||||
|
linux_word,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -w PM_RESUME ./,0.32368993759155273,6,
|
||||||
|
linux_word,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -w PM_RESUME ./,0.3131399154663086,6,
|
||||||
|
linux_word,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -w PM_RESUME ./,0.2834908962249756,6,
|
||||||
|
linux_word,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -w PM_RESUME ./,0.2899782657623291,6,
|
||||||
|
linux_unicode_greek,1,5,rg,rg -n \p{Greek},0.2624638080596924,105,
|
||||||
|
linux_unicode_greek,1,5,rg,rg -n \p{Greek},0.26248669624328613,105,
|
||||||
|
linux_unicode_greek,1,5,rg,rg -n \p{Greek},0.26514244079589844,105,
|
||||||
|
linux_unicode_greek,1,5,rg,rg -n \p{Greek},0.26303768157958984,105,
|
||||||
|
linux_unicode_greek,1,5,rg,rg -n \p{Greek},0.2612752914428711,105,
|
||||||
|
linux_unicode_greek,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \p{Greek} ./,0.2842683792114258,105,
|
||||||
|
linux_unicode_greek,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \p{Greek} ./,0.2718374729156494,105,
|
||||||
|
linux_unicode_greek,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \p{Greek} ./,0.26900339126586914,105,
|
||||||
|
linux_unicode_greek,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \p{Greek} ./,0.267728328704834,105,
|
||||||
|
linux_unicode_greek,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \p{Greek} ./,0.27019381523132324,105,
|
||||||
|
linux_unicode_greek_casei,1,5,rg,rg -n -i \p{Greek},0.24460315704345703,225,
|
||||||
|
linux_unicode_greek_casei,1,5,rg,rg -n -i \p{Greek},0.2752077579498291,225,
|
||||||
|
linux_unicode_greek_casei,1,5,rg,rg -n -i \p{Greek},0.25118350982666016,225,
|
||||||
|
linux_unicode_greek_casei,1,5,rg,rg -n -i \p{Greek},0.2610158920288086,225,
|
||||||
|
linux_unicode_greek_casei,1,5,rg,rg -n -i \p{Greek},0.24675774574279785,225,
|
||||||
|
linux_unicode_greek_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i \p{Greek} ./,0.26882410049438477,105,
|
||||||
|
linux_unicode_greek_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i \p{Greek} ./,0.2770118713378906,105,
|
||||||
|
linux_unicode_greek_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i \p{Greek} ./,0.2694118022918701,105,
|
||||||
|
linux_unicode_greek_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i \p{Greek} ./,0.2690916061401367,105,
|
||||||
|
linux_unicode_greek_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i \p{Greek} ./,0.2686276435852051,105,
|
||||||
|
linux_unicode_word,1,5,rg,rg -n \wAh,0.13727664947509766,229,
|
||||||
|
linux_unicode_word,1,5,rg,rg -n \wAh,0.1450798511505127,229,
|
||||||
|
linux_unicode_word,1,5,rg,rg -n \wAh,0.13819336891174316,229,
|
||||||
|
linux_unicode_word,1,5,rg,rg -n \wAh,0.1422877311706543,229,
|
||||||
|
linux_unicode_word,1,5,rg,rg -n \wAh,0.13657712936401367,229,
|
||||||
|
linux_unicode_word,1,5,rg (ASCII),rg -n (?-u)\wAh,0.1487271785736084,216,
|
||||||
|
linux_unicode_word,1,5,rg (ASCII),rg -n (?-u)\wAh,0.1459641456604004,216,
|
||||||
|
linux_unicode_word,1,5,rg (ASCII),rg -n (?-u)\wAh,0.13515281677246094,216,
|
||||||
|
linux_unicode_word,1,5,rg (ASCII),rg -n (?-u)\wAh,0.12724566459655762,216,
|
||||||
|
linux_unicode_word,1,5,rg (ASCII),rg -n (?-u)\wAh,0.13360023498535156,216,
|
||||||
|
linux_unicode_word,1,5,ag (ASCII),ag -s \wAh,1.2160453796386719,216,
|
||||||
|
linux_unicode_word,1,5,ag (ASCII),ag -s \wAh,1.230163335800171,216,
|
||||||
|
linux_unicode_word,1,5,ag (ASCII),ag -s \wAh,1.2649273872375488,216,
|
||||||
|
linux_unicode_word,1,5,ag (ASCII),ag -s \wAh,1.224984884262085,216,
|
||||||
|
linux_unicode_word,1,5,ag (ASCII),ag -s \wAh,1.4559555053710938,216,
|
||||||
|
linux_unicode_word,1,5,git grep,git grep -E -I -n \wAh,8.233768224716187,229,LC_ALL=en_US.UTF-8
|
||||||
|
linux_unicode_word,1,5,git grep,git grep -E -I -n \wAh,8.191053867340088,229,LC_ALL=en_US.UTF-8
|
||||||
|
linux_unicode_word,1,5,git grep,git grep -E -I -n \wAh,8.175920724868774,229,LC_ALL=en_US.UTF-8
|
||||||
|
linux_unicode_word,1,5,git grep,git grep -E -I -n \wAh,8.167959451675415,229,LC_ALL=en_US.UTF-8
|
||||||
|
linux_unicode_word,1,5,git grep,git grep -E -I -n \wAh,8.1710205078125,229,LC_ALL=en_US.UTF-8
|
||||||
|
linux_unicode_word,1,5,git grep (ASCII),git grep -E -I -n \wAh,2.3747494220733643,216,LC_ALL=C
|
||||||
|
linux_unicode_word,1,5,git grep (ASCII),git grep -E -I -n \wAh,2.3170926570892334,216,LC_ALL=C
|
||||||
|
linux_unicode_word,1,5,git grep (ASCII),git grep -E -I -n \wAh,2.3430888652801514,216,LC_ALL=C
|
||||||
|
linux_unicode_word,1,5,git grep (ASCII),git grep -E -I -n \wAh,2.3219168186187744,216,LC_ALL=C
|
||||||
|
linux_unicode_word,1,5,git grep (ASCII),git grep -E -I -n \wAh,2.3155832290649414,216,LC_ALL=C
|
||||||
|
linux_unicode_word,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \wAh ./,0.2722008228302002,229,
|
||||||
|
linux_unicode_word,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \wAh ./,0.27547430992126465,229,
|
||||||
|
linux_unicode_word,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \wAh ./,0.2771613597869873,229,
|
||||||
|
linux_unicode_word,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \wAh ./,0.27692317962646484,229,
|
||||||
|
linux_unicode_word,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \wAh ./,0.27749085426330566,229,
|
||||||
|
linux_unicode_word,1,5,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \wAh ./,0.2744929790496826,216,
|
||||||
|
linux_unicode_word,1,5,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \wAh ./,0.2725999355316162,216,
|
||||||
|
linux_unicode_word,1,5,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \wAh ./,0.27443718910217285,216,
|
||||||
|
linux_unicode_word,1,5,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \wAh ./,0.2668039798736572,216,
|
||||||
|
linux_unicode_word,1,5,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \wAh ./,0.27918338775634766,216,
|
||||||
|
linux_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.38802123069763184,611,
|
||||||
|
linux_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.40351152420043945,611,
|
||||||
|
linux_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.40592288970947266,611,
|
||||||
|
linux_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.40622901916503906,611,
|
||||||
|
linux_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.40683722496032715,611,
|
||||||
|
linux_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2553420066833496,610,
|
||||||
|
linux_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2511327266693115,610,
|
||||||
|
linux_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2530384063720703,610,
|
||||||
|
linux_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2420644760131836,610,
|
||||||
|
linux_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2691671848297119,610,
|
||||||
|
linux_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.9446702003479004,971,
|
||||||
|
linux_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.9380638599395752,971,
|
||||||
|
linux_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.9273786544799805,971,
|
||||||
|
linux_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.9271430969238281,971,
|
||||||
|
linux_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.9307007789611816,971,
|
||||||
|
linux_no_literal,1,5,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},14.531656265258789,611,LC_ALL=en_US.UTF-8
|
||||||
|
linux_no_literal,1,5,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},14.570266008377075,611,LC_ALL=en_US.UTF-8
|
||||||
|
linux_no_literal,1,5,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},14.51328158378601,611,LC_ALL=en_US.UTF-8
|
||||||
|
linux_no_literal,1,5,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},14.644389629364014,611,LC_ALL=en_US.UTF-8
|
||||||
|
linux_no_literal,1,5,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},14.694648027420044,611,LC_ALL=en_US.UTF-8
|
||||||
|
linux_no_literal,1,5,git grep (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},3.164829730987549,610,LC_ALL=C
|
||||||
|
linux_no_literal,1,5,git grep (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},3.2377045154571533,610,LC_ALL=C
|
||||||
|
linux_no_literal,1,5,git grep (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},3.1798932552337646,610,LC_ALL=C
|
||||||
|
linux_no_literal,1,5,git grep (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},3.142343044281006,610,LC_ALL=C
|
||||||
|
linux_no_literal,1,5,git grep (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},3.185952663421631,610,LC_ALL=C
|
||||||
|
linux_no_literal,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,6.241358041763306,973,
|
||||||
|
linux_no_literal,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,6.213250637054443,973,
|
||||||
|
linux_no_literal,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,6.242088079452515,973,
|
||||||
|
linux_no_literal,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,6.126717567443848,973,
|
||||||
|
linux_no_literal,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,6.15744948387146,973,
|
||||||
|
linux_no_literal,1,5,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,0.3647449016571045,972,
|
||||||
|
linux_no_literal,1,5,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,0.36277341842651367,972,
|
||||||
|
linux_no_literal,1,5,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,0.3670034408569336,972,
|
||||||
|
linux_no_literal,1,5,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,0.3563535213470459,972,
|
||||||
|
linux_no_literal,1,5,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,0.36490702629089355,972,
|
||||||
|
linux_alternates,1,5,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.14299488067626953,112,
|
||||||
|
linux_alternates,1,5,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.15548348426818848,112,
|
||||||
|
linux_alternates,1,5,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.14477276802062988,112,
|
||||||
|
linux_alternates,1,5,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.12926578521728516,112,
|
||||||
|
linux_alternates,1,5,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.13896560668945312,112,
|
||||||
|
linux_alternates,1,5,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.9893472194671631,112,
|
||||||
|
linux_alternates,1,5,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.016686201095581,112,
|
||||||
|
linux_alternates,1,5,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.9755496978759766,112,
|
||||||
|
linux_alternates,1,5,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.9718713760375977,112,
|
||||||
|
linux_alternates,1,5,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.0030465126037598,112,
|
||||||
|
linux_alternates,1,5,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5737886428833008,112,LC_ALL=C
|
||||||
|
linux_alternates,1,5,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.562185525894165,112,LC_ALL=C
|
||||||
|
linux_alternates,1,5,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5762710571289062,112,LC_ALL=C
|
||||||
|
linux_alternates,1,5,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5561251640319824,112,LC_ALL=C
|
||||||
|
linux_alternates,1,5,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5849525928497314,112,LC_ALL=C
|
||||||
|
linux_alternates,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.3186032772064209,112,
|
||||||
|
linux_alternates,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.2896738052368164,112,
|
||||||
|
linux_alternates,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.28582000732421875,112,
|
||||||
|
linux_alternates,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.2837677001953125,112,
|
||||||
|
linux_alternates,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.27143406867980957,112,
|
||||||
|
linux_alternates_casei,1,5,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.21955585479736328,203,
|
||||||
|
linux_alternates_casei,1,5,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.22631502151489258,203,
|
||||||
|
linux_alternates_casei,1,5,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.23458337783813477,203,
|
||||||
|
linux_alternates_casei,1,5,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.21781086921691895,203,
|
||||||
|
linux_alternates_casei,1,5,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.231217622756958,203,
|
||||||
|
linux_alternates_casei,1,5,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.7170076370239258,203,
|
||||||
|
linux_alternates_casei,1,5,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.7032256126403809,203,
|
||||||
|
linux_alternates_casei,1,5,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.6868026256561279,203,
|
||||||
|
linux_alternates_casei,1,5,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.6965539455413818,203,
|
||||||
|
linux_alternates_casei,1,5,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.6966633796691895,203,
|
||||||
|
linux_alternates_casei,1,5,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.9774580001831055,203,LC_ALL=C
|
||||||
|
linux_alternates_casei,1,5,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.9654648303985596,203,LC_ALL=C
|
||||||
|
linux_alternates_casei,1,5,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.967714786529541,203,LC_ALL=C
|
||||||
|
linux_alternates_casei,1,5,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.9789888858795166,203,LC_ALL=C
|
||||||
|
linux_alternates_casei,1,5,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.9938976764678955,203,LC_ALL=C
|
||||||
|
linux_alternates_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.2825000286102295,203,
|
||||||
|
linux_alternates_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.27024054527282715,203,
|
||||||
|
linux_alternates_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.27353668212890625,203,
|
||||||
|
linux_alternates_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.27333736419677734,203,
|
||||||
|
linux_alternates_casei,1,5,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.2730555534362793,203,
|
||||||
|
subtitles_en_literal,1,5,rg,rg Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.2259538173675537,830,
|
||||||
|
subtitles_en_literal,1,5,rg,rg Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.22034168243408203,830,
|
||||||
|
subtitles_en_literal,1,5,rg,rg Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.22986674308776855,830,
|
||||||
|
subtitles_en_literal,1,5,rg,rg Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.22815775871276855,830,
|
||||||
|
subtitles_en_literal,1,5,rg,rg Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.2238922119140625,830,
|
||||||
|
subtitles_en_literal,1,5,rg (no mmap),rg --no-mmap Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.36427783966064453,830,
|
||||||
|
subtitles_en_literal,1,5,rg (no mmap),rg --no-mmap Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.37499117851257324,830,
|
||||||
|
subtitles_en_literal,1,5,rg (no mmap),rg --no-mmap Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.36223769187927246,830,
|
||||||
|
subtitles_en_literal,1,5,rg (no mmap),rg --no-mmap Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.3646128177642822,830,
|
||||||
|
subtitles_en_literal,1,5,rg (no mmap),rg --no-mmap Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.36281347274780273,830,
|
||||||
|
subtitles_en_literal,1,5,grep,grep Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.8064453601837158,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,5,grep,grep Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.8001935482025146,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,5,grep,grep Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.8018591403961182,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,5,grep,grep Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.7978458404541016,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,5,grep,grep Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.7912843227386475,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,5,rg (lines),rg -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.31099891662597656,830,
|
||||||
|
subtitles_en_literal,1,5,rg (lines),rg -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.3145768642425537,830,
|
||||||
|
subtitles_en_literal,1,5,rg (lines),rg -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.30507469177246094,830,
|
||||||
|
subtitles_en_literal,1,5,rg (lines),rg -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.3450126647949219,830,
|
||||||
|
subtitles_en_literal,1,5,rg (lines),rg -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.31091880798339844,830,
|
||||||
|
subtitles_en_literal,1,5,ag (lines),ag -s Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.5518174171447754,830,
|
||||||
|
subtitles_en_literal,1,5,ag (lines),ag -s Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.551568031311035,830,
|
||||||
|
subtitles_en_literal,1,5,ag (lines),ag -s Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.5306365489959717,830,
|
||||||
|
subtitles_en_literal,1,5,ag (lines),ag -s Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.537529468536377,830,
|
||||||
|
subtitles_en_literal,1,5,ag (lines),ag -s Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.5627124309539795,830,
|
||||||
|
subtitles_en_literal,1,5,grep (lines),grep -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.2934913635253906,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,5,grep (lines),grep -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.2990975379943848,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,5,grep (lines),grep -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.2942156791687012,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,5,grep (lines),grep -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.2887969017028809,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,5,grep (lines),grep -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.2922444343566895,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,5,ugrep (lines),ugrep -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.3939177989959717,830,
|
||||||
|
subtitles_en_literal,1,5,ugrep (lines),ugrep -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.3916018009185791,830,
|
||||||
|
subtitles_en_literal,1,5,ugrep (lines),ugrep -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.40460968017578125,830,
|
||||||
|
subtitles_en_literal,1,5,ugrep (lines),ugrep -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.41738367080688477,830,
|
||||||
|
subtitles_en_literal,1,5,ugrep (lines),ugrep -n Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.41339826583862305,830,
|
||||||
|
subtitles_en_literal_casei,1,5,rg,rg -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.37847900390625,871,
|
||||||
|
subtitles_en_literal_casei,1,5,rg,rg -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.3692331314086914,871,
|
||||||
|
subtitles_en_literal_casei,1,5,rg,rg -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.40493106842041016,871,
|
||||||
|
subtitles_en_literal_casei,1,5,rg,rg -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.4074361324310303,871,
|
||||||
|
subtitles_en_literal_casei,1,5,rg,rg -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.4297189712524414,871,
|
||||||
|
subtitles_en_literal_casei,1,5,grep,grep -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,3.63842511177063,871,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_casei,1,5,grep,grep -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,3.6366350650787354,871,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_casei,1,5,grep,grep -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,3.6044440269470215,871,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_casei,1,5,grep,grep -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,3.6123127937316895,871,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_casei,1,5,grep,grep -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,3.6119742393493652,871,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_casei,1,5,grep (ASCII),grep -E -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.917151689529419,871,LC_ALL=C
|
||||||
|
subtitles_en_literal_casei,1,5,grep (ASCII),grep -E -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.9379458427429199,871,LC_ALL=C
|
||||||
|
subtitles_en_literal_casei,1,5,grep (ASCII),grep -E -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.9703550338745117,871,LC_ALL=C
|
||||||
|
subtitles_en_literal_casei,1,5,grep (ASCII),grep -E -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.9309988021850586,871,LC_ALL=C
|
||||||
|
subtitles_en_literal_casei,1,5,grep (ASCII),grep -E -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.9328129291534424,871,LC_ALL=C
|
||||||
|
subtitles_en_literal_casei,1,5,rg (lines),rg -n -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.5196061134338379,871,
|
||||||
|
subtitles_en_literal_casei,1,5,rg (lines),rg -n -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.5225450992584229,871,
|
||||||
|
subtitles_en_literal_casei,1,5,rg (lines),rg -n -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.4856400489807129,871,
|
||||||
|
subtitles_en_literal_casei,1,5,rg (lines),rg -n -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.5204241275787354,871,
|
||||||
|
subtitles_en_literal_casei,1,5,rg (lines),rg -n -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.5224106311798096,871,
|
||||||
|
subtitles_en_literal_casei,1,5,ag (lines) (ASCII),ag -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.5935003757476807,871,
|
||||||
|
subtitles_en_literal_casei,1,5,ag (lines) (ASCII),ag -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.640918016433716,871,
|
||||||
|
subtitles_en_literal_casei,1,5,ag (lines) (ASCII),ag -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.602182626724243,871,
|
||||||
|
subtitles_en_literal_casei,1,5,ag (lines) (ASCII),ag -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.575654983520508,871,
|
||||||
|
subtitles_en_literal_casei,1,5,ag (lines) (ASCII),ag -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.5606820583343506,871,
|
||||||
|
subtitles_en_literal_casei,1,5,ugrep (lines),ugrep -n -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.0980546474456787,871,
|
||||||
|
subtitles_en_literal_casei,1,5,ugrep (lines),ugrep -n -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.095038652420044,871,
|
||||||
|
subtitles_en_literal_casei,1,5,ugrep (lines),ugrep -n -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.0974702835083008,871,
|
||||||
|
subtitles_en_literal_casei,1,5,ugrep (lines),ugrep -n -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.113879919052124,871,
|
||||||
|
subtitles_en_literal_casei,1,5,ugrep (lines),ugrep -n -i Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.1096961498260498,871,
|
||||||
|
subtitles_en_literal_word,1,5,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /tmp/benchsuite/subtitles/en.sample.txt,0.3175060749053955,830,
|
||||||
|
subtitles_en_literal_word,1,5,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /tmp/benchsuite/subtitles/en.sample.txt,0.321685791015625,830,
|
||||||
|
subtitles_en_literal_word,1,5,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /tmp/benchsuite/subtitles/en.sample.txt,0.30799293518066406,830,
|
||||||
|
subtitles_en_literal_word,1,5,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /tmp/benchsuite/subtitles/en.sample.txt,0.31140613555908203,830,
|
||||||
|
subtitles_en_literal_word,1,5,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /tmp/benchsuite/subtitles/en.sample.txt,0.32439208030700684,830,
|
||||||
|
subtitles_en_literal_word,1,5,ag (ASCII),ag -sw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.5530965328216553,830,
|
||||||
|
subtitles_en_literal_word,1,5,ag (ASCII),ag -sw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.5833561420440674,830,
|
||||||
|
subtitles_en_literal_word,1,5,ag (ASCII),ag -sw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.5765762329101562,830,
|
||||||
|
subtitles_en_literal_word,1,5,ag (ASCII),ag -sw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.610975742340088,830,
|
||||||
|
subtitles_en_literal_word,1,5,ag (ASCII),ag -sw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,2.5965471267700195,830,
|
||||||
|
subtitles_en_literal_word,1,5,grep (ASCII),grep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.3212966918945312,830,LC_ALL=C
|
||||||
|
subtitles_en_literal_word,1,5,grep (ASCII),grep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.311401128768921,830,LC_ALL=C
|
||||||
|
subtitles_en_literal_word,1,5,grep (ASCII),grep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.298889398574829,830,LC_ALL=C
|
||||||
|
subtitles_en_literal_word,1,5,grep (ASCII),grep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.316542148590088,830,LC_ALL=C
|
||||||
|
subtitles_en_literal_word,1,5,grep (ASCII),grep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.3483500480651855,830,LC_ALL=C
|
||||||
|
subtitles_en_literal_word,1,5,ugrep (ASCII),ugrep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.4127326011657715,830,
|
||||||
|
subtitles_en_literal_word,1,5,ugrep (ASCII),ugrep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.4138009548187256,830,
|
||||||
|
subtitles_en_literal_word,1,5,ugrep (ASCII),ugrep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.4203319549560547,830,
|
||||||
|
subtitles_en_literal_word,1,5,ugrep (ASCII),ugrep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.4127979278564453,830,
|
||||||
|
subtitles_en_literal_word,1,5,ugrep (ASCII),ugrep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.41126537322998047,830,
|
||||||
|
subtitles_en_literal_word,1,5,rg,rg -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.3251321315765381,830,
|
||||||
|
subtitles_en_literal_word,1,5,rg,rg -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.31773900985717773,830,
|
||||||
|
subtitles_en_literal_word,1,5,rg,rg -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.32987523078918457,830,
|
||||||
|
subtitles_en_literal_word,1,5,rg,rg -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.32228970527648926,830,
|
||||||
|
subtitles_en_literal_word,1,5,rg,rg -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,0.3207516670227051,830,
|
||||||
|
subtitles_en_literal_word,1,5,grep,grep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.2946159839630127,830,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_word,1,5,grep,grep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.333972454071045,830,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_word,1,5,grep,grep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.3002500534057617,830,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_word,1,5,grep,grep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.347550630569458,830,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_word,1,5,grep,grep -nw Sherlock Holmes /tmp/benchsuite/subtitles/en.sample.txt,1.306572675704956,830,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_alternate,1,5,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.4178187847137451,1094,
|
||||||
|
subtitles_en_alternate,1,5,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.44626832008361816,1094,
|
||||||
|
subtitles_en_alternate,1,5,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.44959425926208496,1094,
|
||||||
|
subtitles_en_alternate,1,5,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.38634324073791504,1094,
|
||||||
|
subtitles_en_alternate,1,5,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.4460463523864746,1094,
|
||||||
|
subtitles_en_alternate,1,5,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,3.6045682430267334,1094,
|
||||||
|
subtitles_en_alternate,1,5,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,3.6191344261169434,1094,
|
||||||
|
subtitles_en_alternate,1,5,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,3.579859972000122,1094,
|
||||||
|
subtitles_en_alternate,1,5,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,3.6637580394744873,1094,
|
||||||
|
subtitles_en_alternate,1,5,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,3.5728182792663574,1094,
|
||||||
|
subtitles_en_alternate,1,5,grep (lines),grep -E -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,3.323948621749878,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,5,grep (lines),grep -E -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,3.3338429927825928,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,5,grep (lines),grep -E -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,3.34714937210083,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,5,grep (lines),grep -E -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,3.314117908477783,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,5,grep (lines),grep -E -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,3.303710699081421,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,5,ugrep (lines),ugrep -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,1.147033452987671,1094,
|
||||||
|
subtitles_en_alternate,1,5,ugrep (lines),ugrep -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,1.2054970264434814,1094,
|
||||||
|
subtitles_en_alternate,1,5,ugrep (lines),ugrep -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,1.0998892784118652,1094,
|
||||||
|
subtitles_en_alternate,1,5,ugrep (lines),ugrep -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,1.101989984512329,1094,
|
||||||
|
subtitles_en_alternate,1,5,ugrep (lines),ugrep -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,1.110612154006958,1094,
|
||||||
|
subtitles_en_alternate,1,5,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.29009222984313965,1094,
|
||||||
|
subtitles_en_alternate,1,5,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.29300451278686523,1094,
|
||||||
|
subtitles_en_alternate,1,5,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.3199915885925293,1094,
|
||||||
|
subtitles_en_alternate,1,5,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.3187263011932373,1094,
|
||||||
|
subtitles_en_alternate,1,5,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.30321288108825684,1094,
|
||||||
|
subtitles_en_alternate,1,5,grep,grep -E Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,2.813009738922119,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,5,grep,grep -E Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,2.80930757522583,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,5,grep,grep -E Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,2.814509153366089,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,5,grep,grep -E Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,2.8390560150146484,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,5,grep,grep -E Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,2.830871105194092,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate_casei,1,5,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,6.166510343551636,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,6.192304849624634,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,6.185140132904053,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,6.20132040977478,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,6.159040451049805,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,grep (ASCII),grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,5.523138999938965,1136,LC_ALL=C
|
||||||
|
subtitles_en_alternate_casei,1,5,grep (ASCII),grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,5.512346267700195,1136,LC_ALL=C
|
||||||
|
subtitles_en_alternate_casei,1,5,grep (ASCII),grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,5.562563896179199,1136,LC_ALL=C
|
||||||
|
subtitles_en_alternate_casei,1,5,grep (ASCII),grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,5.533160448074341,1136,LC_ALL=C
|
||||||
|
subtitles_en_alternate_casei,1,5,grep (ASCII),grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,5.504830837249756,1136,LC_ALL=C
|
||||||
|
subtitles_en_alternate_casei,1,5,ugrep (ASCII),ugrep -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,1.1120033264160156,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,ugrep (ASCII),ugrep -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,1.1150739192962646,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,ugrep (ASCII),ugrep -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,1.1018304824829102,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,ugrep (ASCII),ugrep -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,1.1106996536254883,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,ugrep (ASCII),ugrep -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,1.0994808673858643,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.8494291305541992,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.7878148555755615,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.8290884494781494,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.7409803867340088,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,0.7880558967590332,1136,
|
||||||
|
subtitles_en_alternate_casei,1,5,grep,grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,5.5523765087127686,1136,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_alternate_casei,1,5,grep,grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,5.527086019515991,1136,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_alternate_casei,1,5,grep,grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,5.740911483764648,1136,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_alternate_casei,1,5,grep,grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,5.520638465881348,1136,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_alternate_casei,1,5,grep,grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /tmp/benchsuite/subtitles/en.sample.txt,5.52523398399353,1136,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_surrounding_words,1,5,rg,rg -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,0.3353078365325928,483,
|
||||||
|
subtitles_en_surrounding_words,1,5,rg,rg -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,0.3248591423034668,483,
|
||||||
|
subtitles_en_surrounding_words,1,5,rg,rg -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,0.33918261528015137,483,
|
||||||
|
subtitles_en_surrounding_words,1,5,rg,rg -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,0.33177971839904785,483,
|
||||||
|
subtitles_en_surrounding_words,1,5,rg,rg -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,0.34472131729125977,483,
|
||||||
|
subtitles_en_surrounding_words,1,5,grep,grep -E -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,1.7516274452209473,483,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_surrounding_words,1,5,grep,grep -E -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,1.7489221096038818,483,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_surrounding_words,1,5,grep,grep -E -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,1.7574889659881592,483,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_surrounding_words,1,5,grep,grep -E -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,1.813244342803955,483,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_surrounding_words,1,5,grep,grep -E -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,1.750051498413086,483,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_surrounding_words,1,5,ugrep,ugrep -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,70.12419986724854,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ugrep,ugrep -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,70.26925611495972,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ugrep,ugrep -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,70.56865787506104,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ugrep,ugrep -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,70.12933135032654,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ugrep,ugrep -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,70.07925295829773,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,0.3309454917907715,483,
|
||||||
|
subtitles_en_surrounding_words,1,5,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,0.33062124252319336,483,
|
||||||
|
subtitles_en_surrounding_words,1,5,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,0.3292708396911621,483,
|
||||||
|
subtitles_en_surrounding_words,1,5,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,0.3300509452819824,483,
|
||||||
|
subtitles_en_surrounding_words,1,5,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,0.3252389430999756,483,
|
||||||
|
subtitles_en_surrounding_words,1,5,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,7.372813701629639,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,7.338848114013672,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,7.739792108535767,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,7.302056074142456,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,7.334207057952881,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,grep (ASCII),grep -E -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,1.7617950439453125,483,LC_ALL=C
|
||||||
|
subtitles_en_surrounding_words,1,5,grep (ASCII),grep -E -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,1.7765378952026367,483,LC_ALL=C
|
||||||
|
subtitles_en_surrounding_words,1,5,grep (ASCII),grep -E -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,1.7456245422363281,483,LC_ALL=C
|
||||||
|
subtitles_en_surrounding_words,1,5,grep (ASCII),grep -E -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,1.748713731765747,483,LC_ALL=C
|
||||||
|
subtitles_en_surrounding_words,1,5,grep (ASCII),grep -E -n \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,1.7846882343292236,483,LC_ALL=C
|
||||||
|
subtitles_en_surrounding_words,1,5,ugrep (ASCII),ugrep -n -U \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,31.14370322227478,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ugrep (ASCII),ugrep -n -U \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,31.543628454208374,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ugrep (ASCII),ugrep -n -U \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,31.133421182632446,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ugrep (ASCII),ugrep -n -U \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,31.149214506149292,489,
|
||||||
|
subtitles_en_surrounding_words,1,5,ugrep (ASCII),ugrep -n -U \w+\s+Holmes\s+\w+ /tmp/benchsuite/subtitles/en.sample.txt,31.180144548416138,489,
|
||||||
|
subtitles_en_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,2.9173591136932373,22,
|
||||||
|
subtitles_en_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,2.867539644241333,22,
|
||||||
|
subtitles_en_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,2.9047088623046875,22,
|
||||||
|
subtitles_en_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,2.9265778064727783,22,
|
||||||
|
subtitles_en_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,2.874317169189453,22,
|
||||||
|
subtitles_en_no_literal,1,5,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,24.619744777679443,309,
|
||||||
|
subtitles_en_no_literal,1,5,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,24.622087240219116,309,
|
||||||
|
subtitles_en_no_literal,1,5,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,24.770710468292236,309,
|
||||||
|
subtitles_en_no_literal,1,5,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,24.60181713104248,309,
|
||||||
|
subtitles_en_no_literal,1,5,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,24.678969383239746,309,
|
||||||
|
subtitles_en_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,2.676262140274048,22,
|
||||||
|
subtitles_en_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,2.673837184906006,22,
|
||||||
|
subtitles_en_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,2.667243003845215,22,
|
||||||
|
subtitles_en_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,2.667970657348633,22,
|
||||||
|
subtitles_en_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,2.6588196754455566,22,
|
||||||
|
subtitles_en_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,10.786212682723999,302,
|
||||||
|
subtitles_en_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,10.744041204452515,302,
|
||||||
|
subtitles_en_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,10.74718165397644,302,
|
||||||
|
subtitles_en_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,10.768681287765503,302,
|
||||||
|
subtitles_en_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,10.772834777832031,302,
|
||||||
|
subtitles_en_no_literal,1,5,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,6.287469148635864,22,LC_ALL=C
|
||||||
|
subtitles_en_no_literal,1,5,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,6.243509769439697,22,LC_ALL=C
|
||||||
|
subtitles_en_no_literal,1,5,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,6.242478370666504,22,LC_ALL=C
|
||||||
|
subtitles_en_no_literal,1,5,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,6.2600791454315186,22,LC_ALL=C
|
||||||
|
subtitles_en_no_literal,1,5,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,6.2560741901397705,22,LC_ALL=C
|
||||||
|
subtitles_en_no_literal,1,5,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,4.670856237411499,302,
|
||||||
|
subtitles_en_no_literal,1,5,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,4.703561544418335,302,
|
||||||
|
subtitles_en_no_literal,1,5,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,4.675989627838135,302,
|
||||||
|
subtitles_en_no_literal,1,5,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,4.6688103675842285,302,
|
||||||
|
subtitles_en_no_literal,1,5,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/en.sample.txt,4.715432167053223,302,
|
||||||
|
subtitles_ru_literal,1,5,rg,rg Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.20440673828125,583,
|
||||||
|
subtitles_ru_literal,1,5,rg,rg Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.20561552047729492,583,
|
||||||
|
subtitles_ru_literal,1,5,rg,rg Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.2381761074066162,583,
|
||||||
|
subtitles_ru_literal,1,5,rg,rg Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.23102140426635742,583,
|
||||||
|
subtitles_ru_literal,1,5,rg,rg Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.19649791717529297,583,
|
||||||
|
subtitles_ru_literal,1,5,rg (no mmap),rg --no-mmap Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.3158297538757324,583,
|
||||||
|
subtitles_ru_literal,1,5,rg (no mmap),rg --no-mmap Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.3136112689971924,583,
|
||||||
|
subtitles_ru_literal,1,5,rg (no mmap),rg --no-mmap Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.32402992248535156,583,
|
||||||
|
subtitles_ru_literal,1,5,rg (no mmap),rg --no-mmap Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.3248250484466553,583,
|
||||||
|
subtitles_ru_literal,1,5,rg (no mmap),rg --no-mmap Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.3201103210449219,583,
|
||||||
|
subtitles_ru_literal,1,5,grep,grep Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.7790360450744629,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,5,grep,grep Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.7977695465087891,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,5,grep,grep Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.7397308349609375,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,5,grep,grep Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.7123947143554688,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,5,grep,grep Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.711977481842041,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,5,rg (lines),rg -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.27593088150024414,583,
|
||||||
|
subtitles_ru_literal,1,5,rg (lines),rg -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.2842848300933838,583,
|
||||||
|
subtitles_ru_literal,1,5,rg (lines),rg -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.28340864181518555,583,
|
||||||
|
subtitles_ru_literal,1,5,rg (lines),rg -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.28469133377075195,583,
|
||||||
|
subtitles_ru_literal,1,5,rg (lines),rg -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.27951884269714355,583,
|
||||||
|
subtitles_ru_literal,1,5,ag (lines),ag -s Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,2.7401182651519775,583,
|
||||||
|
subtitles_ru_literal,1,5,ag (lines),ag -s Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,2.658051013946533,583,
|
||||||
|
subtitles_ru_literal,1,5,ag (lines),ag -s Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,2.666799306869507,583,
|
||||||
|
subtitles_ru_literal,1,5,ag (lines),ag -s Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,2.7145025730133057,583,
|
||||||
|
subtitles_ru_literal,1,5,ag (lines),ag -s Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,2.7412168979644775,583,
|
||||||
|
subtitles_ru_literal,1,5,grep (lines),grep -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.0886235237121582,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,5,grep (lines),grep -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.0896506309509277,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,5,grep (lines),grep -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.1100494861602783,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,5,grep (lines),grep -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.088308334350586,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,5,grep (lines),grep -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.0891127586364746,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,5,ugrep (lines),ugrep -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.8426175117492676,583,
|
||||||
|
subtitles_ru_literal,1,5,ugrep (lines),ugrep -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.85064697265625,583,
|
||||||
|
subtitles_ru_literal,1,5,ugrep (lines),ugrep -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.8356082439422607,583,
|
||||||
|
subtitles_ru_literal,1,5,ugrep (lines),ugrep -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.8405826091766357,583,
|
||||||
|
subtitles_ru_literal,1,5,ugrep (lines),ugrep -n Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.83730149269104,583,
|
||||||
|
subtitles_ru_literal_casei,1,5,rg,rg -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.48739099502563477,604,
|
||||||
|
subtitles_ru_literal_casei,1,5,rg,rg -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.4823324680328369,604,
|
||||||
|
subtitles_ru_literal_casei,1,5,rg,rg -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.4832422733306885,604,
|
||||||
|
subtitles_ru_literal_casei,1,5,rg,rg -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.4812777042388916,604,
|
||||||
|
subtitles_ru_literal_casei,1,5,rg,rg -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.4854264259338379,604,
|
||||||
|
subtitles_ru_literal_casei,1,5,grep,grep -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,6.694453477859497,604,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_casei,1,5,grep,grep -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,6.759232044219971,604,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_casei,1,5,grep,grep -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,6.686243534088135,604,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_casei,1,5,grep,grep -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,6.7029454708099365,604,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_casei,1,5,grep,grep -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,6.699738264083862,604,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_casei,1,5,grep (ASCII),grep -E -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.7290260791778564,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_casei,1,5,grep (ASCII),grep -E -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.7400493621826172,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_casei,1,5,grep (ASCII),grep -E -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.7299001216888428,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_casei,1,5,grep (ASCII),grep -E -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.7308380603790283,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_casei,1,5,grep (ASCII),grep -E -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.7283904552459717,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_casei,1,5,rg (lines),rg -n -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.5711629390716553,604,
|
||||||
|
subtitles_ru_literal_casei,1,5,rg (lines),rg -n -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.574974536895752,604,
|
||||||
|
subtitles_ru_literal_casei,1,5,rg (lines),rg -n -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.5820963382720947,604,
|
||||||
|
subtitles_ru_literal_casei,1,5,rg (lines),rg -n -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.5438523292541504,604,
|
||||||
|
subtitles_ru_literal_casei,1,5,rg (lines),rg -n -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.5054161548614502,604,
|
||||||
|
subtitles_ru_literal_casei,1,5,ag (lines) (ASCII),ag -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.6135058403015137,,
|
||||||
|
subtitles_ru_literal_casei,1,5,ag (lines) (ASCII),ag -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.6051545143127441,,
|
||||||
|
subtitles_ru_literal_casei,1,5,ag (lines) (ASCII),ag -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.6032793521881104,,
|
||||||
|
subtitles_ru_literal_casei,1,5,ag (lines) (ASCII),ag -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.6097028255462646,,
|
||||||
|
subtitles_ru_literal_casei,1,5,ag (lines) (ASCII),ag -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.6850666999816895,,
|
||||||
|
subtitles_ru_literal_casei,1,5,ugrep (lines) (ASCII),ugrep -n -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.833592176437378,583,
|
||||||
|
subtitles_ru_literal_casei,1,5,ugrep (lines) (ASCII),ugrep -n -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.8357219696044922,583,
|
||||||
|
subtitles_ru_literal_casei,1,5,ugrep (lines) (ASCII),ugrep -n -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.8394358158111572,583,
|
||||||
|
subtitles_ru_literal_casei,1,5,ugrep (lines) (ASCII),ugrep -n -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.8334264755249023,583,
|
||||||
|
subtitles_ru_literal_casei,1,5,ugrep (lines) (ASCII),ugrep -n -i Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.8304622173309326,583,
|
||||||
|
subtitles_ru_literal_word,1,5,rg (ASCII),rg -n (?-u:^|\W)Шерлок Холмс(?-u:$|\W) /tmp/benchsuite/subtitles/ru.txt,0.2904787063598633,583,
|
||||||
|
subtitles_ru_literal_word,1,5,rg (ASCII),rg -n (?-u:^|\W)Шерлок Холмс(?-u:$|\W) /tmp/benchsuite/subtitles/ru.txt,0.2831101417541504,583,
|
||||||
|
subtitles_ru_literal_word,1,5,rg (ASCII),rg -n (?-u:^|\W)Шерлок Холмс(?-u:$|\W) /tmp/benchsuite/subtitles/ru.txt,0.2786984443664551,583,
|
||||||
|
subtitles_ru_literal_word,1,5,rg (ASCII),rg -n (?-u:^|\W)Шерлок Холмс(?-u:$|\W) /tmp/benchsuite/subtitles/ru.txt,0.28719663619995117,583,
|
||||||
|
subtitles_ru_literal_word,1,5,rg (ASCII),rg -n (?-u:^|\W)Шерлок Холмс(?-u:$|\W) /tmp/benchsuite/subtitles/ru.txt,0.27600622177124023,583,
|
||||||
|
subtitles_ru_literal_word,1,5,ag (ASCII),ag -sw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.6810102462768555,,
|
||||||
|
subtitles_ru_literal_word,1,5,ag (ASCII),ag -sw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.6855161190032959,,
|
||||||
|
subtitles_ru_literal_word,1,5,ag (ASCII),ag -sw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.6827929019927979,,
|
||||||
|
subtitles_ru_literal_word,1,5,ag (ASCII),ag -sw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.6587810516357422,,
|
||||||
|
subtitles_ru_literal_word,1,5,ag (ASCII),ag -sw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.6551673412322998,,
|
||||||
|
subtitles_ru_literal_word,1,5,grep (ASCII),grep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.0948495864868164,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_word,1,5,grep (ASCII),grep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.097151756286621,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_word,1,5,grep (ASCII),grep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.1051688194274902,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_word,1,5,grep (ASCII),grep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.1151607036590576,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_word,1,5,grep (ASCII),grep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.1100919246673584,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_word,1,5,ugrep (ASCII),ugrep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.84104585647583,,
|
||||||
|
subtitles_ru_literal_word,1,5,ugrep (ASCII),ugrep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.9092209339141846,,
|
||||||
|
subtitles_ru_literal_word,1,5,ugrep (ASCII),ugrep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.836583137512207,,
|
||||||
|
subtitles_ru_literal_word,1,5,ugrep (ASCII),ugrep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.8941335678100586,,
|
||||||
|
subtitles_ru_literal_word,1,5,ugrep (ASCII),ugrep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.8811957836151123,,
|
||||||
|
subtitles_ru_literal_word,1,5,rg,rg -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.2956504821777344,579,
|
||||||
|
subtitles_ru_literal_word,1,5,rg,rg -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.29023194313049316,579,
|
||||||
|
subtitles_ru_literal_word,1,5,rg,rg -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.3374972343444824,579,
|
||||||
|
subtitles_ru_literal_word,1,5,rg,rg -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.29686713218688965,579,
|
||||||
|
subtitles_ru_literal_word,1,5,rg,rg -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,0.29778003692626953,579,
|
||||||
|
subtitles_ru_literal_word,1,5,grep,grep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.1042869091033936,579,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_word,1,5,grep,grep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.1068925857543945,579,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_word,1,5,grep,grep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.0973529815673828,579,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_word,1,5,grep,grep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.0917479991912842,579,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_word,1,5,grep,grep -nw Шерлок Холмс /tmp/benchsuite/subtitles/ru.txt,1.0987188816070557,579,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_alternate,1,5,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,0.8945937156677246,691,
|
||||||
|
subtitles_ru_alternate,1,5,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,0.8919808864593506,691,
|
||||||
|
subtitles_ru_alternate,1,5,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,0.9041986465454102,691,
|
||||||
|
subtitles_ru_alternate,1,5,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,0.8838107585906982,691,
|
||||||
|
subtitles_ru_alternate,1,5,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,0.903540849685669,691,
|
||||||
|
subtitles_ru_alternate,1,5,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,3.715298652648926,691,
|
||||||
|
subtitles_ru_alternate,1,5,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,3.676830530166626,691,
|
||||||
|
subtitles_ru_alternate,1,5,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,3.721431016921997,691,
|
||||||
|
subtitles_ru_alternate,1,5,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,3.6990325450897217,691,
|
||||||
|
subtitles_ru_alternate,1,5,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,3.764216184616089,691,
|
||||||
|
subtitles_ru_alternate,1,5,grep (lines),grep -E -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.519805669784546,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,5,grep (lines),grep -E -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.40212869644165,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,5,grep (lines),grep -E -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.381818294525146,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,5,grep (lines),grep -E -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.386401176452637,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,5,grep (lines),grep -E -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.425997257232666,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,5,ugrep (lines),ugrep -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,13.259684801101685,691,
|
||||||
|
subtitles_ru_alternate,1,5,ugrep (lines),ugrep -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,13.236181735992432,691,
|
||||||
|
subtitles_ru_alternate,1,5,ugrep (lines),ugrep -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,13.340983629226685,691,
|
||||||
|
subtitles_ru_alternate,1,5,ugrep (lines),ugrep -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,13.21895980834961,691,
|
||||||
|
subtitles_ru_alternate,1,5,ugrep (lines),ugrep -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,13.194425106048584,691,
|
||||||
|
subtitles_ru_alternate,1,5,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,0.8262777328491211,691,
|
||||||
|
subtitles_ru_alternate,1,5,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,0.8343832492828369,691,
|
||||||
|
subtitles_ru_alternate,1,5,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,0.8675012588500977,691,
|
||||||
|
subtitles_ru_alternate,1,5,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,0.8584244251251221,691,
|
||||||
|
subtitles_ru_alternate,1,5,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,0.8777158260345459,691,
|
||||||
|
subtitles_ru_alternate,1,5,grep,grep -E Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.25586986541748,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,5,grep,grep -E Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.007173538208008,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,5,grep,grep -E Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.068726301193237,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,5,grep,grep -E Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.010542631149292,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,5,grep,grep -E Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.021028280258179,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate_casei,1,5,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,3.7179486751556396,691,
|
||||||
|
subtitles_ru_alternate_casei,1,5,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,3.682896375656128,691,
|
||||||
|
subtitles_ru_alternate_casei,1,5,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,3.699859142303467,691,
|
||||||
|
subtitles_ru_alternate_casei,1,5,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,3.662733316421509,691,
|
||||||
|
subtitles_ru_alternate_casei,1,5,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,3.661060094833374,691,
|
||||||
|
subtitles_ru_alternate_casei,1,5,grep (ASCII),grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.434819221496582,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate_casei,1,5,grep (ASCII),grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.436205625534058,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate_casei,1,5,grep (ASCII),grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.388120412826538,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate_casei,1,5,grep (ASCII),grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.407799243927002,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate_casei,1,5,grep (ASCII),grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,8.44464373588562,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate_casei,1,5,ugrep (ASCII),ugrep -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,13.216991662979126,691,
|
||||||
|
subtitles_ru_alternate_casei,1,5,ugrep (ASCII),ugrep -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,13.470320701599121,691,
|
||||||
|
subtitles_ru_alternate_casei,1,5,ugrep (ASCII),ugrep -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,13.21274471282959,691,
|
||||||
|
subtitles_ru_alternate_casei,1,5,ugrep (ASCII),ugrep -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,13.38324522972107,691,
|
||||||
|
subtitles_ru_alternate_casei,1,5,ugrep (ASCII),ugrep -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,13.3148832321167,691,
|
||||||
|
subtitles_ru_alternate_casei,1,5,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,6.205031156539917,735,
|
||||||
|
subtitles_ru_alternate_casei,1,5,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,6.1502509117126465,735,
|
||||||
|
subtitles_ru_alternate_casei,1,5,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,6.150696516036987,735,
|
||||||
|
subtitles_ru_alternate_casei,1,5,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,6.150148630142212,735,
|
||||||
|
subtitles_ru_alternate_casei,1,5,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,6.153124809265137,735,
|
||||||
|
subtitles_ru_alternate_casei,1,5,grep,grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,7.477111339569092,735,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_alternate_casei,1,5,grep,grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,7.483617782592773,735,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_alternate_casei,1,5,grep,grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,7.502292156219482,735,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_alternate_casei,1,5,grep,grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,7.528963327407837,735,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_alternate_casei,1,5,grep,grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /tmp/benchsuite/subtitles/ru.txt,7.482379198074341,735,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,5,rg,rg -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,0.3461883068084717,278,
|
||||||
|
subtitles_ru_surrounding_words,1,5,rg,rg -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,0.30211687088012695,278,
|
||||||
|
subtitles_ru_surrounding_words,1,5,rg,rg -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,0.30521416664123535,278,
|
||||||
|
subtitles_ru_surrounding_words,1,5,rg,rg -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,0.2969543933868408,278,
|
||||||
|
subtitles_ru_surrounding_words,1,5,rg,rg -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,0.3003671169281006,278,
|
||||||
|
subtitles_ru_surrounding_words,1,5,grep,grep -E -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.4209251403808594,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,5,grep,grep -E -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.4190807342529297,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,5,grep,grep -E -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.4178283214569092,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,5,grep,grep -E -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.4173235893249512,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,5,grep,grep -E -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.4221296310424805,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,5,ugrep,ugrep -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,70.6701226234436,326,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ugrep,ugrep -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,71.15788650512695,326,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ugrep,ugrep -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,71.07276272773743,326,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ugrep,ugrep -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,70.5626060962677,326,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ugrep,ugrep -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,70.54449439048767,326,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.868441104888916,,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.886382818222046,,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.8685986995697021,,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.8727426528930664,,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.8667800426483154,,
|
||||||
|
subtitles_ru_surrounding_words,1,5,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.3818490505218506,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,5,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.3709721565246582,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,5,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.3819043636322021,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,5,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.460402488708496,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,5,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.4097135066986084,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,5,ugrep (ASCII),ugrep -n -U \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.286102294921875,,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ugrep (ASCII),ugrep -n -U \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.2712647914886475,,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ugrep (ASCII),ugrep -n -U \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.2950100898742676,,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ugrep (ASCII),ugrep -n -U \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.264500617980957,,
|
||||||
|
subtitles_ru_surrounding_words,1,5,ugrep (ASCII),ugrep -n -U \w+\s+Холмс\s+\w+ /tmp/benchsuite/subtitles/ru.txt,1.2877566814422607,,
|
||||||
|
subtitles_ru_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,3.1152236461639404,41,
|
||||||
|
subtitles_ru_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,3.1311423778533936,41,
|
||||||
|
subtitles_ru_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,3.0800061225891113,41,
|
||||||
|
subtitles_ru_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,3.070636510848999,41,
|
||||||
|
subtitles_ru_no_literal,1,5,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,3.0940587520599365,41,
|
||||||
|
subtitles_ru_no_literal,1,5,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,50.85447072982788,86,
|
||||||
|
subtitles_ru_no_literal,1,5,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,50.832582235336304,86,
|
||||||
|
subtitles_ru_no_literal,1,5,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,50.8755087852478,86,
|
||||||
|
subtitles_ru_no_literal,1,5,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,50.79056358337402,86,
|
||||||
|
subtitles_ru_no_literal,1,5,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,50.84795618057251,86,
|
||||||
|
subtitles_ru_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,2.716826915740967,,
|
||||||
|
subtitles_ru_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,2.7381114959716797,,
|
||||||
|
subtitles_ru_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,2.7545180320739746,,
|
||||||
|
subtitles_ru_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,2.7215416431427,,
|
||||||
|
subtitles_ru_no_literal,1,5,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,2.707784414291382,,
|
||||||
|
subtitles_ru_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.9250116348266602,,
|
||||||
|
subtitles_ru_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.8956947326660156,,
|
||||||
|
subtitles_ru_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.8904175758361816,,
|
||||||
|
subtitles_ru_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.8968868255615234,,
|
||||||
|
subtitles_ru_no_literal,1,5,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.900888204574585,,
|
||||||
|
subtitles_ru_no_literal,1,5,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.755054235458374,,LC_ALL=C
|
||||||
|
subtitles_ru_no_literal,1,5,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.7681376934051514,,LC_ALL=C
|
||||||
|
subtitles_ru_no_literal,1,5,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.7654614448547363,,LC_ALL=C
|
||||||
|
subtitles_ru_no_literal,1,5,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.75648832321167,,LC_ALL=C
|
||||||
|
subtitles_ru_no_literal,1,5,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.7456772327423096,,LC_ALL=C
|
||||||
|
subtitles_ru_no_literal,1,5,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.2170698642730713,,
|
||||||
|
subtitles_ru_no_literal,1,5,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.1907124519348145,,
|
||||||
|
subtitles_ru_no_literal,1,5,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.1722266674041748,,
|
||||||
|
subtitles_ru_no_literal,1,5,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.191617727279663,,
|
||||||
|
subtitles_ru_no_literal,1,5,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /tmp/benchsuite/subtitles/ru.txt,1.1909863948822021,,
|
||||||
|
208
benchsuite/runs/2020-10-14-archlinux-frink/summary
Normal file
208
benchsuite/runs/2020-10-14-archlinux-frink/summary
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
linux_literal_default (pattern: PM_RESUME)
|
||||||
|
------------------------------------------
|
||||||
|
rg* 0.124 +/- 0.004 (lines: 19)*
|
||||||
|
ag 0.771 +/- 0.187 (lines: 19)
|
||||||
|
git grep 0.480 +/- 0.010 (lines: 19)
|
||||||
|
ugrep 0.136 +/- 0.002 (lines: 19)
|
||||||
|
grep 1.147 +/- 0.005 (lines: 19)
|
||||||
|
|
||||||
|
linux_literal (pattern: PM_RESUME)
|
||||||
|
----------------------------------
|
||||||
|
rg* 0.130 +/- 0.008 (lines: 19)*
|
||||||
|
rg (mmap) 1.336 +/- 0.036 (lines: 19)
|
||||||
|
ag (mmap) 0.880 +/- 0.071 (lines: 19)
|
||||||
|
git grep 0.464 +/- 0.005 (lines: 19)
|
||||||
|
ugrep 0.309 +/- 0.012 (lines: 19)
|
||||||
|
|
||||||
|
linux_literal_casei (pattern: PM_RESUME)
|
||||||
|
----------------------------------------
|
||||||
|
rg* 0.131 +/- 0.005 (lines: 456)*
|
||||||
|
rg (mmap) 1.336 +/- 0.020 (lines: 456)
|
||||||
|
ag (mmap) 0.657 +/- 0.123 (lines: 456)
|
||||||
|
git grep 0.482 +/- 0.007 (lines: 456)
|
||||||
|
ugrep 0.288 +/- 0.014 (lines: 456)
|
||||||
|
|
||||||
|
linux_re_literal_suffix (pattern: [A-Z]+_RESUME)
|
||||||
|
------------------------------------------------
|
||||||
|
rg* 0.126 +/- 0.009 (lines: 1944)*
|
||||||
|
ag 1.044 +/- 0.138 (lines: 1944)
|
||||||
|
git grep 1.217 +/- 0.045 (lines: 1944)
|
||||||
|
ugrep 0.548 +/- 0.014 (lines: 1944)
|
||||||
|
|
||||||
|
linux_word (pattern: PM_RESUME)
|
||||||
|
-------------------------------
|
||||||
|
rg* 0.134 +/- 0.003 (lines: 6)*
|
||||||
|
ag 0.618 +/- 0.154 (lines: 6)
|
||||||
|
git grep 0.471 +/- 0.018 (lines: 6)
|
||||||
|
ugrep 0.306 +/- 0.018 (lines: 6)
|
||||||
|
|
||||||
|
linux_unicode_greek (pattern: \p{Greek})
|
||||||
|
----------------------------------------
|
||||||
|
rg* 0.263 +/- 0.001 (lines: 105)*
|
||||||
|
ugrep 0.273 +/- 0.007 (lines: 105)
|
||||||
|
|
||||||
|
linux_unicode_greek_casei (pattern: \p{Greek})
|
||||||
|
----------------------------------------------
|
||||||
|
rg* 0.256 +/- 0.013 (lines: 225)*
|
||||||
|
ugrep 0.271 +/- 0.004 (lines: 105)
|
||||||
|
|
||||||
|
linux_unicode_word (pattern: \wAh)
|
||||||
|
----------------------------------
|
||||||
|
rg 0.140 +/- 0.004 (lines: 229)
|
||||||
|
rg (ASCII)* 0.138 +/- 0.009 (lines: 216)*
|
||||||
|
ag (ASCII) 1.278 +/- 0.101 (lines: 216)
|
||||||
|
git grep 8.188 +/- 0.027 (lines: 229)
|
||||||
|
git grep (ASCII) 2.334 +/- 0.025 (lines: 216)
|
||||||
|
ugrep 0.276 +/- 0.002 (lines: 229)
|
||||||
|
ugrep (ASCII) 0.274 +/- 0.004 (lines: 216)
|
||||||
|
|
||||||
|
linux_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
rg 0.402 +/- 0.008 (lines: 611)
|
||||||
|
rg (ASCII)* 0.254 +/- 0.010 (lines: 610)*
|
||||||
|
ag (ASCII) 0.934 +/- 0.008 (lines: 971)
|
||||||
|
git grep 14.591 +/- 0.077 (lines: 611)
|
||||||
|
git grep (ASCII) 3.182 +/- 0.035 (lines: 610)
|
||||||
|
ugrep 6.196 +/- 0.052 (lines: 973)
|
||||||
|
ugrep (ASCII) 0.363 +/- 0.004 (lines: 972)
|
||||||
|
|
||||||
|
linux_alternates (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
rg* 0.142 +/- 0.010 (lines: 112)*
|
||||||
|
ag 0.991 +/- 0.019 (lines: 112)
|
||||||
|
git grep 0.571 +/- 0.011 (lines: 112)
|
||||||
|
ugrep 0.290 +/- 0.017 (lines: 112)
|
||||||
|
|
||||||
|
linux_alternates_casei (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
rg* 0.226 +/- 0.007 (lines: 203)*
|
||||||
|
ag 0.700 +/- 0.011 (lines: 203)
|
||||||
|
git grep 0.977 +/- 0.011 (lines: 203)
|
||||||
|
ugrep 0.275 +/- 0.005 (lines: 203)
|
||||||
|
|
||||||
|
subtitles_en_literal (pattern: Sherlock Holmes)
|
||||||
|
-----------------------------------------------
|
||||||
|
rg* 0.226 +/- 0.004 (lines: 830)*
|
||||||
|
rg (no mmap) 0.366 +/- 0.005 (lines: 830)
|
||||||
|
grep 0.800 +/- 0.006 (lines: 830)
|
||||||
|
rg (lines) 0.317 +/- 0.016 (lines: 830)
|
||||||
|
ag (lines) 2.547 +/- 0.013 (lines: 830)
|
||||||
|
grep (lines) 1.294 +/- 0.004 (lines: 830)
|
||||||
|
ugrep (lines) 0.404 +/- 0.011 (lines: 830)
|
||||||
|
|
||||||
|
subtitles_en_literal_casei (pattern: Sherlock Holmes)
|
||||||
|
-----------------------------------------------------
|
||||||
|
rg* 0.398 +/- 0.024 (lines: 871)*
|
||||||
|
grep 3.621 +/- 0.016 (lines: 871)
|
||||||
|
grep (ASCII) 0.938 +/- 0.020 (lines: 871)
|
||||||
|
rg (lines) 0.514 +/- 0.016 (lines: 871)
|
||||||
|
ag (lines) (ASCII) 2.595 +/- 0.030 (lines: 871)
|
||||||
|
ugrep (lines) 1.103 +/- 0.008 (lines: 871)
|
||||||
|
|
||||||
|
subtitles_en_literal_word (pattern: Sherlock Holmes)
|
||||||
|
----------------------------------------------------
|
||||||
|
rg (ASCII)* 0.317 +/- 0.007 (lines: 830)*
|
||||||
|
ag (ASCII) 2.584 +/- 0.022 (lines: 830)
|
||||||
|
grep (ASCII) 1.319 +/- 0.018 (lines: 830)
|
||||||
|
ugrep (ASCII) 0.414 +/- 0.004 (lines: 830)
|
||||||
|
rg 0.323 +/- 0.005 (lines: 830)
|
||||||
|
grep 1.317 +/- 0.023 (lines: 830)
|
||||||
|
|
||||||
|
subtitles_en_alternate (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
|
||||||
|
---------------------------------------------------------------------------------------------------------------
|
||||||
|
rg (lines) 0.429 +/- 0.027 (lines: 1094)
|
||||||
|
ag (lines) 3.608 +/- 0.036 (lines: 1094)
|
||||||
|
grep (lines) 3.325 +/- 0.017 (lines: 1094)
|
||||||
|
ugrep (lines) 1.133 +/- 0.045 (lines: 1094)
|
||||||
|
rg* 0.305 +/- 0.014 (lines: 1094)*
|
||||||
|
grep 2.821 +/- 0.013 (lines: 1094)
|
||||||
|
|
||||||
|
subtitles_en_alternate_casei (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
|
||||||
|
---------------------------------------------------------------------------------------------------------------------
|
||||||
|
ag (ASCII) 6.181 +/- 0.018 (lines: 1136)
|
||||||
|
grep (ASCII) 5.527 +/- 0.022 (lines: 1136)
|
||||||
|
ugrep (ASCII) 1.108 +/- 0.007 (lines: 1136)
|
||||||
|
rg* 0.799 +/- 0.042 (lines: 1136)*
|
||||||
|
grep 5.573 +/- 0.095 (lines: 1136)
|
||||||
|
|
||||||
|
subtitles_en_surrounding_words (pattern: \w+\s+Holmes\s+\w+)
|
||||||
|
------------------------------------------------------------
|
||||||
|
rg* 0.335 +/- 0.008 (lines: 483)
|
||||||
|
grep 1.764 +/- 0.028 (lines: 483)
|
||||||
|
ugrep 70.234 +/- 0.200 (lines: 489)
|
||||||
|
rg (ASCII) 0.329 +/- 0.002 (lines: 483)*
|
||||||
|
ag (ASCII) 7.418 +/- 0.182 (lines: 489)
|
||||||
|
grep (ASCII) 1.763 +/- 0.017 (lines: 483)
|
||||||
|
ugrep (ASCII) 31.230 +/- 0.176 (lines: 489)
|
||||||
|
|
||||||
|
subtitles_en_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||||
|
----------------------------------------------------------------------------------------
|
||||||
|
rg 2.898 +/- 0.026 (lines: 22)
|
||||||
|
ugrep 24.659 +/- 0.069 (lines: 309)
|
||||||
|
rg (ASCII)* 2.669 +/- 0.007 (lines: 22)*
|
||||||
|
ag (ASCII) 10.764 +/- 0.018 (lines: 302)
|
||||||
|
grep (ASCII) 6.258 +/- 0.018 (lines: 22)
|
||||||
|
ugrep (ASCII) 4.687 +/- 0.021 (lines: 302)
|
||||||
|
|
||||||
|
subtitles_ru_literal (pattern: Шерлок Холмс)
|
||||||
|
--------------------------------------------
|
||||||
|
rg* 0.215 +/- 0.018 (lines: 583)*
|
||||||
|
rg (no mmap) 0.320 +/- 0.005 (lines: 583)
|
||||||
|
grep 0.748 +/- 0.039 (lines: 583)
|
||||||
|
rg (lines) 0.282 +/- 0.004 (lines: 583)
|
||||||
|
ag (lines) 2.704 +/- 0.040 (lines: 583)
|
||||||
|
grep (lines) 1.093 +/- 0.009 (lines: 583)
|
||||||
|
ugrep (lines) 1.841 +/- 0.006 (lines: 583)
|
||||||
|
|
||||||
|
subtitles_ru_literal_casei (pattern: Шерлок Холмс)
|
||||||
|
--------------------------------------------------
|
||||||
|
rg* 0.484 +/- 0.002 (lines: 604)*
|
||||||
|
grep 6.709 +/- 0.029 (lines: 604)
|
||||||
|
grep (ASCII) 0.732 +/- 0.005 (lines: 583)
|
||||||
|
rg (lines) 0.556 +/- 0.032 (lines: 604)
|
||||||
|
ag (lines) (ASCII) 0.623 +/- 0.035 (lines: 0)
|
||||||
|
ugrep (lines) (ASCII) 1.835 +/- 0.003 (lines: 583)
|
||||||
|
|
||||||
|
subtitles_ru_literal_word (pattern: Шерлок Холмс)
|
||||||
|
-------------------------------------------------
|
||||||
|
rg (ASCII)* 0.283 +/- 0.006 (lines: 583)*
|
||||||
|
ag (ASCII) 0.673 +/- 0.014 (lines: 0)
|
||||||
|
grep (ASCII) 1.104 +/- 0.009 (lines: 583)
|
||||||
|
ugrep (ASCII) 1.872 +/- 0.032 (lines: 0)
|
||||||
|
rg 0.304 +/- 0.019 (lines: 579)
|
||||||
|
grep 1.100 +/- 0.006 (lines: 579)
|
||||||
|
|
||||||
|
subtitles_ru_alternate (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
|
||||||
|
-----------------------------------------------------------------------------------------------------------
|
||||||
|
rg (lines) 0.896 +/- 0.009 (lines: 691)
|
||||||
|
ag (lines) 3.715 +/- 0.032 (lines: 691)
|
||||||
|
grep (lines) 8.423 +/- 0.057 (lines: 691)
|
||||||
|
ugrep (lines) 13.250 +/- 0.056 (lines: 691)
|
||||||
|
rg* 0.853 +/- 0.022 (lines: 691)*
|
||||||
|
grep 8.073 +/- 0.105 (lines: 691)
|
||||||
|
|
||||||
|
subtitles_ru_alternate_casei (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
|
||||||
|
-----------------------------------------------------------------------------------------------------------------
|
||||||
|
ag (ASCII)* 3.685 +/- 0.024 (lines: 691)*
|
||||||
|
grep (ASCII) 8.422 +/- 0.024 (lines: 691)
|
||||||
|
ugrep (ASCII) 13.320 +/- 0.110 (lines: 691)
|
||||||
|
rg 6.162 +/- 0.024 (lines: 735)
|
||||||
|
grep 7.495 +/- 0.021 (lines: 735)
|
||||||
|
|
||||||
|
subtitles_ru_surrounding_words (pattern: \w+\s+Холмс\s+\w+)
|
||||||
|
-----------------------------------------------------------
|
||||||
|
rg* 0.310 +/- 0.020 (lines: 278)*
|
||||||
|
grep 1.419 +/- 0.002 (lines: 278)
|
||||||
|
ugrep 70.802 +/- 0.292 (lines: 326)
|
||||||
|
ag (ASCII) 1.873 +/- 0.008 (lines: 0)
|
||||||
|
grep (ASCII) 1.401 +/- 0.036 (lines: 0)
|
||||||
|
ugrep (ASCII) 1.281 +/- 0.013 (lines: 0)
|
||||||
|
|
||||||
|
subtitles_ru_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||||
|
----------------------------------------------------------------------------------------
|
||||||
|
rg 3.098 +/- 0.025 (lines: 41)
|
||||||
|
ugrep 50.840 +/- 0.032 (lines: 86)
|
||||||
|
rg (ASCII) 2.728 +/- 0.019 (lines: 0)
|
||||||
|
ag (ASCII) 1.902 +/- 0.014 (lines: 0)
|
||||||
|
grep (ASCII) 1.758 +/- 0.009 (lines: 0)
|
||||||
|
ugrep (ASCII)* 1.193 +/- 0.016 (lines: 0)*
|
||||||
38
benchsuite/runs/2022-12-16-archlinux-duff/README.md
Normal file
38
benchsuite/runs/2022-12-16-archlinux-duff/README.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
This directory contains updated benchmarks as of 2022-12-16. They were captured
|
||||||
|
via the benchsuite script at `benchsuite/benchsuite` from the root of this
|
||||||
|
repository. The command that was run:
|
||||||
|
|
||||||
|
$ ./benchsuite \
|
||||||
|
--dir /dev/shm/benchsuite \
|
||||||
|
--raw runs/2022-12-16-archlinux-duff/raw.csv \
|
||||||
|
| tee runs/2022-12-16-archlinux-duff/summary
|
||||||
|
|
||||||
|
The versions of each tool are as follows:
|
||||||
|
|
||||||
|
$ rg --version
|
||||||
|
ripgrep 13.0.0 (rev 87c4a2b4b1)
|
||||||
|
-SIMD -AVX (compiled)
|
||||||
|
+SIMD +AVX (runtime)
|
||||||
|
|
||||||
|
$ grep -V
|
||||||
|
grep (GNU grep) 3.8
|
||||||
|
|
||||||
|
$ ag -V
|
||||||
|
ag version 2.2.0
|
||||||
|
|
||||||
|
Features:
|
||||||
|
+jit +lzma +zlib
|
||||||
|
|
||||||
|
$ git --version
|
||||||
|
git version 2.39.0
|
||||||
|
|
||||||
|
$ ugrep --version
|
||||||
|
ugrep 3.9.2 x86_64-pc-linux-gnu +avx2 +pcre2jit +zlib +bzip2 +lzma +lz4 +zstd
|
||||||
|
License BSD-3-Clause: <https://opensource.org/licenses/BSD-3-Clause>
|
||||||
|
Written by Robert van Engelen and others: <https://github.com/Genivia/ugrep>
|
||||||
|
|
||||||
|
The version of ripgrep used was compiled from source on commit 7f23cd63:
|
||||||
|
|
||||||
|
$ cargo build --release --features 'pcre2'
|
||||||
|
|
||||||
|
This was run on a machine with an Intel i9-12900K with 128GB of memory.
|
||||||
400
benchsuite/runs/2022-12-16-archlinux-duff/raw.csv
Normal file
400
benchsuite/runs/2022-12-16-archlinux-duff/raw.csv
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
benchmark,warmup_iter,iter,name,command,duration,lines,env
|
||||||
|
linux_literal_default,1,3,rg,rg PM_RESUME,0.08678817749023438,39,
|
||||||
|
linux_literal_default,1,3,rg,rg PM_RESUME,0.08307123184204102,39,
|
||||||
|
linux_literal_default,1,3,rg,rg PM_RESUME,0.08347964286804199,39,
|
||||||
|
linux_literal_default,1,3,ag,ag PM_RESUME,0.2955434322357178,39,
|
||||||
|
linux_literal_default,1,3,ag,ag PM_RESUME,0.2954287528991699,39,
|
||||||
|
linux_literal_default,1,3,ag,ag PM_RESUME,0.2938194274902344,39,
|
||||||
|
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.23198556900024414,39,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.22356963157653809,39,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.2189793586730957,39,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,3,ugrep,ugrep -r PM_RESUME ./,0.10710000991821289,39,
|
||||||
|
linux_literal_default,1,3,ugrep,ugrep -r PM_RESUME ./,0.10364222526550293,39,
|
||||||
|
linux_literal_default,1,3,ugrep,ugrep -r PM_RESUME ./,0.1052248477935791,39,
|
||||||
|
linux_literal_default,1,3,grep,grep -r PM_RESUME ./,0.9994468688964844,39,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,3,grep,grep -r PM_RESUME ./,0.9939279556274414,39,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal_default,1,3,grep,grep -r PM_RESUME ./,0.9957931041717529,39,LC_ALL=en_US.UTF-8
|
||||||
|
linux_literal,1,3,rg,rg -n PM_RESUME,0.08603358268737793,39,
|
||||||
|
linux_literal,1,3,rg,rg -n PM_RESUME,0.0837090015411377,39,
|
||||||
|
linux_literal,1,3,rg,rg -n PM_RESUME,0.08435535430908203,39,
|
||||||
|
linux_literal,1,3,rg (mmap),rg -n --mmap PM_RESUME,0.3215503692626953,39,
|
||||||
|
linux_literal,1,3,rg (mmap),rg -n --mmap PM_RESUME,0.32426929473876953,39,
|
||||||
|
linux_literal,1,3,rg (mmap),rg -n --mmap PM_RESUME,0.3215982913970947,39,
|
||||||
|
linux_literal,1,3,ag (mmap),ag -s PM_RESUME,0.2894856929779053,39,
|
||||||
|
linux_literal,1,3,ag (mmap),ag -s PM_RESUME,0.2892603874206543,39,
|
||||||
|
linux_literal,1,3,ag (mmap),ag -s PM_RESUME,0.29217028617858887,39,
|
||||||
|
linux_literal,1,3,git grep,git grep -I -n PM_RESUME,0.206068754196167,39,LC_ALL=C
|
||||||
|
linux_literal,1,3,git grep,git grep -I -n PM_RESUME,0.2218036651611328,39,LC_ALL=C
|
||||||
|
linux_literal,1,3,git grep,git grep -I -n PM_RESUME,0.20590710639953613,39,LC_ALL=C
|
||||||
|
linux_literal,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n PM_RESUME ./,0.18692874908447266,39,
|
||||||
|
linux_literal,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n PM_RESUME ./,0.19518327713012695,39,
|
||||||
|
linux_literal,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n PM_RESUME ./,0.18577361106872559,39,
|
||||||
|
linux_literal_casei,1,3,rg,rg -n -i PM_RESUME,0.08709383010864258,536,
|
||||||
|
linux_literal_casei,1,3,rg,rg -n -i PM_RESUME,0.08861064910888672,536,
|
||||||
|
linux_literal_casei,1,3,rg,rg -n -i PM_RESUME,0.08769798278808594,536,
|
||||||
|
linux_literal_casei,1,3,rg (mmap),rg -n -i --mmap PM_RESUME,0.3218965530395508,536,
|
||||||
|
linux_literal_casei,1,3,rg (mmap),rg -n -i --mmap PM_RESUME,0.30869364738464355,536,
|
||||||
|
linux_literal_casei,1,3,rg (mmap),rg -n -i --mmap PM_RESUME,0.31044936180114746,536,
|
||||||
|
linux_literal_casei,1,3,ag (mmap),ag -i PM_RESUME,0.2989068031311035,536,
|
||||||
|
linux_literal_casei,1,3,ag (mmap),ag -i PM_RESUME,0.2996039390563965,536,
|
||||||
|
linux_literal_casei,1,3,ag (mmap),ag -i PM_RESUME,0.29817700386047363,536,
|
||||||
|
linux_literal_casei,1,3,git grep,git grep -I -n -i PM_RESUME,0.2122786045074463,536,LC_ALL=C
|
||||||
|
linux_literal_casei,1,3,git grep,git grep -I -n -i PM_RESUME,0.20763754844665527,536,LC_ALL=C
|
||||||
|
linux_literal_casei,1,3,git grep,git grep -I -n -i PM_RESUME,0.220794677734375,536,LC_ALL=C
|
||||||
|
linux_literal_casei,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i PM_RESUME ./,0.17305850982666016,536,
|
||||||
|
linux_literal_casei,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i PM_RESUME ./,0.1745915412902832,536,
|
||||||
|
linux_literal_casei,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i PM_RESUME ./,0.17526865005493164,536,
|
||||||
|
linux_re_literal_suffix,1,3,rg,rg -n [A-Z]+_RESUME,0.08527851104736328,2160,
|
||||||
|
linux_re_literal_suffix,1,3,rg,rg -n [A-Z]+_RESUME,0.08487534523010254,2160,
|
||||||
|
linux_re_literal_suffix,1,3,rg,rg -n [A-Z]+_RESUME,0.0848684310913086,2160,
|
||||||
|
linux_re_literal_suffix,1,3,ag,ag -s [A-Z]+_RESUME,0.37945985794067383,2160,
|
||||||
|
linux_re_literal_suffix,1,3,ag,ag -s [A-Z]+_RESUME,0.36303210258483887,2160,
|
||||||
|
linux_re_literal_suffix,1,3,ag,ag -s [A-Z]+_RESUME,0.36359691619873047,2160,
|
||||||
|
linux_re_literal_suffix,1,3,git grep,git grep -E -I -n [A-Z]+_RESUME,0.9589834213256836,2160,LC_ALL=C
|
||||||
|
linux_re_literal_suffix,1,3,git grep,git grep -E -I -n [A-Z]+_RESUME,0.9206984043121338,2160,LC_ALL=C
|
||||||
|
linux_re_literal_suffix,1,3,git grep,git grep -E -I -n [A-Z]+_RESUME,0.8642933368682861,2160,LC_ALL=C
|
||||||
|
linux_re_literal_suffix,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n [A-Z]+_RESUME ./,0.40503501892089844,2160,
|
||||||
|
linux_re_literal_suffix,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n [A-Z]+_RESUME ./,0.4531714916229248,2160,
|
||||||
|
linux_re_literal_suffix,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n [A-Z]+_RESUME ./,0.4397866725921631,2160,
|
||||||
|
linux_word,1,3,rg,rg -n -w PM_RESUME,0.08639907836914062,9,
|
||||||
|
linux_word,1,3,rg,rg -n -w PM_RESUME,0.08583569526672363,9,
|
||||||
|
linux_word,1,3,rg,rg -n -w PM_RESUME,0.08414363861083984,9,
|
||||||
|
linux_word,1,3,ag,ag -s -w PM_RESUME,0.2853865623474121,9,
|
||||||
|
linux_word,1,3,ag,ag -s -w PM_RESUME,0.2871377468109131,9,
|
||||||
|
linux_word,1,3,ag,ag -s -w PM_RESUME,0.28753662109375,9,
|
||||||
|
linux_word,1,3,git grep,git grep -E -I -n -w PM_RESUME,0.20428204536437988,9,LC_ALL=C
|
||||||
|
linux_word,1,3,git grep,git grep -E -I -n -w PM_RESUME,0.20490717887878418,9,LC_ALL=C
|
||||||
|
linux_word,1,3,git grep,git grep -E -I -n -w PM_RESUME,0.20840072631835938,9,LC_ALL=C
|
||||||
|
linux_word,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -w PM_RESUME ./,0.18790841102600098,9,
|
||||||
|
linux_word,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -w PM_RESUME ./,0.18659543991088867,9,
|
||||||
|
linux_word,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -w PM_RESUME ./,0.19104933738708496,9,
|
||||||
|
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.19976496696472168,105,
|
||||||
|
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.20618367195129395,105,
|
||||||
|
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.19702935218811035,105,
|
||||||
|
linux_unicode_greek,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n \p{Greek} ./,0.17758727073669434,105,
|
||||||
|
linux_unicode_greek,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n \p{Greek} ./,0.17793798446655273,105,
|
||||||
|
linux_unicode_greek,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n \p{Greek} ./,0.1872577667236328,105,
|
||||||
|
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.19808244705200195,245,
|
||||||
|
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.1979837417602539,245,
|
||||||
|
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.1984400749206543,245,
|
||||||
|
linux_unicode_greek_casei,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i \p{Greek} ./,0.1819148063659668,105,
|
||||||
|
linux_unicode_greek_casei,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i \p{Greek} ./,0.17530512809753418,105,
|
||||||
|
linux_unicode_greek_casei,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i \p{Greek} ./,0.17999005317687988,105,
|
||||||
|
linux_unicode_word,1,3,rg,rg -n \wAh,0.08527827262878418,247,
|
||||||
|
linux_unicode_word,1,3,rg,rg -n \wAh,0.08541679382324219,247,
|
||||||
|
linux_unicode_word,1,3,rg,rg -n \wAh,0.08553218841552734,247,
|
||||||
|
linux_unicode_word,1,3,rg (ASCII),rg -n (?-u)\wAh,0.08484745025634766,233,
|
||||||
|
linux_unicode_word,1,3,rg (ASCII),rg -n (?-u)\wAh,0.08466482162475586,233,
|
||||||
|
linux_unicode_word,1,3,rg (ASCII),rg -n (?-u)\wAh,0.08487439155578613,233,
|
||||||
|
linux_unicode_word,1,3,ag (ASCII),ag -s \wAh,0.3061795234680176,233,
|
||||||
|
linux_unicode_word,1,3,ag (ASCII),ag -s \wAh,0.2993617057800293,233,
|
||||||
|
linux_unicode_word,1,3,ag (ASCII),ag -s \wAh,0.29722046852111816,233,
|
||||||
|
linux_unicode_word,1,3,git grep,git grep -E -I -n \wAh,4.257144451141357,247,LC_ALL=en_US.UTF-8
|
||||||
|
linux_unicode_word,1,3,git grep,git grep -E -I -n \wAh,3.852163076400757,247,LC_ALL=en_US.UTF-8
|
||||||
|
linux_unicode_word,1,3,git grep,git grep -E -I -n \wAh,3.8293941020965576,247,LC_ALL=en_US.UTF-8
|
||||||
|
linux_unicode_word,1,3,git grep (ASCII),git grep -E -I -n \wAh,1.647632122039795,233,LC_ALL=C
|
||||||
|
linux_unicode_word,1,3,git grep (ASCII),git grep -E -I -n \wAh,1.6269629001617432,233,LC_ALL=C
|
||||||
|
linux_unicode_word,1,3,git grep (ASCII),git grep -E -I -n \wAh,1.5847914218902588,233,LC_ALL=C
|
||||||
|
linux_unicode_word,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n \wAh ./,0.1802208423614502,247,
|
||||||
|
linux_unicode_word,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n \wAh ./,0.17564702033996582,247,
|
||||||
|
linux_unicode_word,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n \wAh ./,0.1746981143951416,247,
|
||||||
|
linux_unicode_word,1,3,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \wAh ./,0.1799161434173584,233,
|
||||||
|
linux_unicode_word,1,3,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \wAh ./,0.18733000755310059,233,
|
||||||
|
linux_unicode_word,1,3,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \wAh ./,0.18859529495239258,233,
|
||||||
|
linux_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.26203155517578125,721,
|
||||||
|
linux_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2615540027618408,721,
|
||||||
|
linux_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2730247974395752,721,
|
||||||
|
linux_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.19902300834655762,720,
|
||||||
|
linux_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.20034146308898926,720,
|
||||||
|
linux_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.20192813873291016,720,
|
||||||
|
linux_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.8269081115722656,1134,
|
||||||
|
linux_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.8393104076385498,1134,
|
||||||
|
linux_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.8293666839599609,1134,
|
||||||
|
linux_no_literal,1,3,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},7.334395408630371,721,LC_ALL=en_US.UTF-8
|
||||||
|
linux_no_literal,1,3,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},7.338796854019165,721,LC_ALL=en_US.UTF-8
|
||||||
|
linux_no_literal,1,3,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},7.36545991897583,721,LC_ALL=en_US.UTF-8
|
||||||
|
linux_no_literal,1,3,git grep (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},2.1588926315307617,720,LC_ALL=C
|
||||||
|
linux_no_literal,1,3,git grep (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},2.132209062576294,720,LC_ALL=C
|
||||||
|
linux_no_literal,1,3,git grep (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},2.1407439708709717,720,LC_ALL=C
|
||||||
|
linux_no_literal,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,3.410162925720215,723,
|
||||||
|
linux_no_literal,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,3.405057668685913,723,
|
||||||
|
linux_no_literal,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,3.3945884704589844,723,
|
||||||
|
linux_no_literal,1,3,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,0.23865604400634766,722,
|
||||||
|
linux_no_literal,1,3,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,0.23371148109436035,722,
|
||||||
|
linux_no_literal,1,3,ugrep (ASCII),ugrep -r --ignore-files --no-hidden -I -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} ./,0.2343149185180664,722,
|
||||||
|
linux_alternates,1,3,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.08691263198852539,140,
|
||||||
|
linux_alternates,1,3,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.08707070350646973,140,
|
||||||
|
linux_alternates,1,3,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.08713960647583008,140,
|
||||||
|
linux_alternates,1,3,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.32947278022766113,140,
|
||||||
|
linux_alternates,1,3,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.33203840255737305,140,
|
||||||
|
linux_alternates,1,3,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.3292670249938965,140,
|
||||||
|
linux_alternates,1,3,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.4576725959777832,140,LC_ALL=C
|
||||||
|
linux_alternates,1,3,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.41936421394348145,140,LC_ALL=C
|
||||||
|
linux_alternates,1,3,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.3639688491821289,140,LC_ALL=C
|
||||||
|
linux_alternates,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.17806458473205566,140,
|
||||||
|
linux_alternates,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.18224716186523438,140,
|
||||||
|
linux_alternates,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.17795038223266602,140,
|
||||||
|
linux_alternates_casei,1,3,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.12421393394470215,241,
|
||||||
|
linux_alternates_casei,1,3,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.12235784530639648,241,
|
||||||
|
linux_alternates_casei,1,3,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.12151455879211426,241,
|
||||||
|
linux_alternates_casei,1,3,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.529585599899292,241,
|
||||||
|
linux_alternates_casei,1,3,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5305526256561279,241,
|
||||||
|
linux_alternates_casei,1,3,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5311264991760254,241,
|
||||||
|
linux_alternates_casei,1,3,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.7589735984802246,241,LC_ALL=C
|
||||||
|
linux_alternates_casei,1,3,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.7852108478546143,241,LC_ALL=C
|
||||||
|
linux_alternates_casei,1,3,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.8308050632476807,241,LC_ALL=C
|
||||||
|
linux_alternates_casei,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.17955923080444336,241,
|
||||||
|
linux_alternates_casei,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.1745290756225586,241,
|
||||||
|
linux_alternates_casei,1,3,ugrep,ugrep -r --ignore-files --no-hidden -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT ./,0.1773686408996582,241,
|
||||||
|
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.1213979721069336,830,
|
||||||
|
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.1213991641998291,830,
|
||||||
|
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.12620782852172852,830,
|
||||||
|
subtitles_en_literal,1,3,rg (no mmap),rg --no-mmap Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.18207263946533203,830,
|
||||||
|
subtitles_en_literal,1,3,rg (no mmap),rg --no-mmap Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.17281484603881836,830,
|
||||||
|
subtitles_en_literal,1,3,rg (no mmap),rg --no-mmap Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.17368507385253906,830,
|
||||||
|
subtitles_en_literal,1,3,grep,grep Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.560560941696167,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,3,grep,grep Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.563499927520752,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,3,grep,grep Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.5916609764099121,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.19600844383239746,830,
|
||||||
|
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.18436980247497559,830,
|
||||||
|
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.18594050407409668,830,
|
||||||
|
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.871025562286377,830,
|
||||||
|
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.8636960983276367,830,
|
||||||
|
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.8680994510650635,830,
|
||||||
|
subtitles_en_literal,1,3,grep (lines),grep -n Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.9978001117706299,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,3,grep (lines),grep -n Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.9385361671447754,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,3,grep (lines),grep -n Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.0036489963531494,830,LC_ALL=C
|
||||||
|
subtitles_en_literal,1,3,ugrep (lines),ugrep -n Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.18918490409851074,830,
|
||||||
|
subtitles_en_literal,1,3,ugrep (lines),ugrep -n Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.1769108772277832,830,
|
||||||
|
subtitles_en_literal,1,3,ugrep (lines),ugrep -n Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.18808293342590332,830,
|
||||||
|
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.21876287460327148,871,
|
||||||
|
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.2044692039489746,871,
|
||||||
|
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.2184743881225586,871,
|
||||||
|
subtitles_en_literal_casei,1,3,grep,grep -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,2.224027156829834,871,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_casei,1,3,grep,grep -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,2.223188877105713,871,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_casei,1,3,grep,grep -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,2.223966598510742,871,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.671149492263794,871,LC_ALL=C
|
||||||
|
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.6705749034881592,871,LC_ALL=C
|
||||||
|
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.6700258255004883,871,LC_ALL=C
|
||||||
|
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.2624058723449707,871,
|
||||||
|
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.25513339042663574,871,
|
||||||
|
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.26088857650756836,871,
|
||||||
|
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.9144322872161865,871,
|
||||||
|
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.866628885269165,871,
|
||||||
|
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.9098389148712158,871,
|
||||||
|
subtitles_en_literal_casei,1,3,ugrep (lines),ugrep -n -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.7860472202301025,871,
|
||||||
|
subtitles_en_literal_casei,1,3,ugrep (lines),ugrep -n -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.7858343124389648,871,
|
||||||
|
subtitles_en_literal_casei,1,3,ugrep (lines),ugrep -n -i Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.782252311706543,871,
|
||||||
|
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /dev/shm/benchsuite/subtitles/en.sample.txt,0.18424677848815918,830,
|
||||||
|
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /dev/shm/benchsuite/subtitles/en.sample.txt,0.19610810279846191,830,
|
||||||
|
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /dev/shm/benchsuite/subtitles/en.sample.txt,0.18711471557617188,830,
|
||||||
|
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.8301315307617188,830,
|
||||||
|
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.8689801692962646,830,
|
||||||
|
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.8279321193695068,830,
|
||||||
|
subtitles_en_literal_word,1,3,grep (ASCII),grep -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.0036842823028564,830,LC_ALL=C
|
||||||
|
subtitles_en_literal_word,1,3,grep (ASCII),grep -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.002833604812622,830,LC_ALL=C
|
||||||
|
subtitles_en_literal_word,1,3,grep (ASCII),grep -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.9236147403717041,830,LC_ALL=C
|
||||||
|
subtitles_en_literal_word,1,3,ugrep (ASCII),ugrep -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.17717313766479492,830,
|
||||||
|
subtitles_en_literal_word,1,3,ugrep (ASCII),ugrep -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.18994617462158203,830,
|
||||||
|
subtitles_en_literal_word,1,3,ugrep (ASCII),ugrep -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.17972850799560547,830,
|
||||||
|
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.18804550170898438,830,
|
||||||
|
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.18867778778076172,830,
|
||||||
|
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.19913530349731445,830,
|
||||||
|
subtitles_en_literal_word,1,3,grep,grep -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.0044364929199219,830,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_word,1,3,grep,grep -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,1.0040032863616943,830,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_literal_word,1,3,grep,grep -nw Sherlock Holmes /dev/shm/benchsuite/subtitles/en.sample.txt,0.9627983570098877,830,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.24848055839538574,1094,
|
||||||
|
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.24738383293151855,1094,
|
||||||
|
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.24789118766784668,1094,
|
||||||
|
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,2.668708562850952,1094,
|
||||||
|
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,2.57511305809021,1094,
|
||||||
|
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,2.6714110374450684,1094,
|
||||||
|
subtitles_en_alternate,1,3,grep (lines),grep -E -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,2.0586187839508057,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,3,grep (lines),grep -E -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,2.0227150917053223,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,3,grep (lines),grep -E -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,2.075378179550171,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,3,ugrep (lines),ugrep -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.7863781452178955,1094,
|
||||||
|
subtitles_en_alternate,1,3,ugrep (lines),ugrep -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.7874250411987305,1094,
|
||||||
|
subtitles_en_alternate,1,3,ugrep (lines),ugrep -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.7867889404296875,1094,
|
||||||
|
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.18195557594299316,1094,
|
||||||
|
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.18239641189575195,1094,
|
||||||
|
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.1625690460205078,1094,
|
||||||
|
subtitles_en_alternate,1,3,grep,grep -E Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,1.6601614952087402,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,3,grep,grep -E Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,1.6617567539215088,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate,1,3,grep,grep -E Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,1.6584677696228027,1094,LC_ALL=C
|
||||||
|
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,4.0028722286224365,1136,
|
||||||
|
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,3.991217851638794,1136,
|
||||||
|
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,4.00272274017334,1136,
|
||||||
|
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,3.549154758453369,1136,LC_ALL=C
|
||||||
|
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,3.5468921661376953,1136,LC_ALL=C
|
||||||
|
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,3.5873491764068604,1136,LC_ALL=C
|
||||||
|
subtitles_en_alternate_casei,1,3,ugrep (ASCII),ugrep -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.7872169017791748,1136,
|
||||||
|
subtitles_en_alternate_casei,1,3,ugrep (ASCII),ugrep -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.784674882888794,1136,
|
||||||
|
subtitles_en_alternate_casei,1,3,ugrep (ASCII),ugrep -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.7882401943206787,1136,
|
||||||
|
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.4785435199737549,1136,
|
||||||
|
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.4940922260284424,1136,
|
||||||
|
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,0.4774627685546875,1136,
|
||||||
|
subtitles_en_alternate_casei,1,3,grep,grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,3.5677175521850586,1136,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_alternate_casei,1,3,grep,grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,3.603273391723633,1136,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_en_alternate_casei,1,3,grep,grep -E -ni Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /dev/shm/benchsuite/subtitles/en.sample.txt,3.5834741592407227,1136,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.20238041877746582,278,
|
||||||
|
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.2031264305114746,278,
|
||||||
|
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.20475172996520996,278,
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep,grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0288453102111816,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep,grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.044802188873291,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep,grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0432109832763672,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep,ugrep -an \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,43.00765633583069,278,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep,ugrep -an \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,42.832849740982056,278,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep,ugrep -an \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,42.915205240249634,278,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.083683967590332,,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0841526985168457,,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0850934982299805,,
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0116353034973145,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.9868073463439941,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0224814414978027,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep (ASCII),ugrep -a -n -U \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.8892502784729004,,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep (ASCII),ugrep -a -n -U \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.8910088539123535,,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep (ASCII),ugrep -a -n -U \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.8897674083709717,,
|
||||||
|
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,2.11850643157959,22,
|
||||||
|
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,2.1359670162200928,22,
|
||||||
|
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,2.103114128112793,22,
|
||||||
|
subtitles_en_no_literal,1,3,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,13.050881385803223,22,
|
||||||
|
subtitles_en_no_literal,1,3,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,13.050772190093994,22,
|
||||||
|
subtitles_en_no_literal,1,3,ugrep,ugrep -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,13.05719804763794,22,
|
||||||
|
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,1.9961926937103271,22,
|
||||||
|
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,2.019721508026123,22,
|
||||||
|
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,1.9965126514434814,22,
|
||||||
|
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,6.849602222442627,302,
|
||||||
|
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,6.813834190368652,302,
|
||||||
|
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,6.8263633251190186,302,
|
||||||
|
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,4.42924165725708,22,LC_ALL=C
|
||||||
|
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,4.378557205200195,22,LC_ALL=C
|
||||||
|
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,4.376646518707275,22,LC_ALL=C
|
||||||
|
subtitles_en_no_literal,1,3,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,3.5110037326812744,22,
|
||||||
|
subtitles_en_no_literal,1,3,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,3.5137360095977783,22,
|
||||||
|
subtitles_en_no_literal,1,3,ugrep (ASCII),ugrep -n -U \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/en.sample.txt,3.5051844120025635,22,
|
||||||
|
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.13207745552062988,583,
|
||||||
|
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.13084721565246582,583,
|
||||||
|
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.13469862937927246,583,
|
||||||
|
subtitles_ru_literal,1,3,rg (no mmap),rg --no-mmap Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.18022370338439941,583,
|
||||||
|
subtitles_ru_literal,1,3,rg (no mmap),rg --no-mmap Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.1801767349243164,583,
|
||||||
|
subtitles_ru_literal,1,3,rg (no mmap),rg --no-mmap Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.17995166778564453,583,
|
||||||
|
subtitles_ru_literal,1,3,grep,grep Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.5151040554046631,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,3,grep,grep Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.5154542922973633,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,3,grep,grep Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.49927639961242676,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.19464492797851562,583,
|
||||||
|
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.18920588493347168,583,
|
||||||
|
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.19465351104736328,583,
|
||||||
|
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,1.9595966339111328,583,
|
||||||
|
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,2.0014493465423584,583,
|
||||||
|
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,1.9567768573760986,583,
|
||||||
|
subtitles_ru_literal,1,3,grep (lines),grep -n Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.8119180202484131,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,3,grep (lines),grep -n Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.8111097812652588,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,3,grep (lines),grep -n Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.8006868362426758,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal,1,3,ugrep (lines),ugrep -a -n Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.70003342628479,583,
|
||||||
|
subtitles_ru_literal,1,3,ugrep (lines),ugrep -a -n Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.650275468826294,583,
|
||||||
|
subtitles_ru_literal,1,3,ugrep (lines),ugrep -a -n Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.689772367477417,583,
|
||||||
|
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.267578125,604,
|
||||||
|
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.2665982246398926,604,
|
||||||
|
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.26861572265625,604,
|
||||||
|
subtitles_ru_literal_casei,1,3,grep,grep -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,4.764627456665039,604,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_casei,1,3,grep,grep -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,4.767015695571899,604,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_casei,1,3,grep,grep -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,4.7688889503479,604,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.5046737194061279,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.5139875411987305,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.4993159770965576,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.33438658714294434,604,
|
||||||
|
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.3398289680480957,604,
|
||||||
|
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.3298227787017822,604,
|
||||||
|
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.4468214511871338,,
|
||||||
|
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.44559574127197266,,
|
||||||
|
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.47882938385009766,,
|
||||||
|
subtitles_ru_literal_casei,1,3,ugrep (lines) (ASCII),ugrep -a -n -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.7039575576782227,583,
|
||||||
|
subtitles_ru_literal_casei,1,3,ugrep (lines) (ASCII),ugrep -a -n -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.6490752696990967,583,
|
||||||
|
subtitles_ru_literal_casei,1,3,ugrep (lines) (ASCII),ugrep -a -n -i Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.8081104755401611,583,
|
||||||
|
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:^|\W)Шерлок Холмс(?-u:$|\W) /dev/shm/benchsuite/subtitles/ru.txt,0.20162224769592285,583,
|
||||||
|
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:^|\W)Шерлок Холмс(?-u:$|\W) /dev/shm/benchsuite/subtitles/ru.txt,0.18215250968933105,583,
|
||||||
|
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:^|\W)Шерлок Холмс(?-u:$|\W) /dev/shm/benchsuite/subtitles/ru.txt,0.20087671279907227,583,
|
||||||
|
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.48624587059020996,,
|
||||||
|
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.5212516784667969,,
|
||||||
|
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.520557165145874,,
|
||||||
|
subtitles_ru_literal_word,1,3,grep (ASCII),grep -nw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.8108196258544922,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_word,1,3,grep (ASCII),grep -nw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.8121066093444824,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_word,1,3,grep (ASCII),grep -nw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.7784581184387207,583,LC_ALL=C
|
||||||
|
subtitles_ru_literal_word,1,3,ugrep (ASCII),ugrep -anw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.7469344139099121,583,
|
||||||
|
subtitles_ru_literal_word,1,3,ugrep (ASCII),ugrep -anw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.6838233470916748,583,
|
||||||
|
subtitles_ru_literal_word,1,3,ugrep (ASCII),ugrep -anw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.6921679973602295,583,
|
||||||
|
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.19918251037597656,579,
|
||||||
|
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.2046656608581543,579,
|
||||||
|
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.1984848976135254,579,
|
||||||
|
subtitles_ru_literal_word,1,3,grep,grep -nw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.794173002243042,579,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_word,1,3,grep,grep -nw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.7715346813201904,579,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_literal_word,1,3,grep,grep -nw Шерлок Холмс /dev/shm/benchsuite/subtitles/ru.txt,0.8116705417633057,579,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,0.6730976104736328,691,
|
||||||
|
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,0.7020411491394043,691,
|
||||||
|
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,0.6693949699401855,691,
|
||||||
|
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,2.7100515365600586,691,
|
||||||
|
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,2.7458419799804688,691,
|
||||||
|
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,2.7115116119384766,691,
|
||||||
|
subtitles_ru_alternate,1,3,grep (lines),grep -E -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.703738451004028,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,3,grep (lines),grep -E -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.715883731842041,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,3,grep (lines),grep -E -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.712724924087524,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,3,ugrep (lines),ugrep -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,8.276995420455933,691,
|
||||||
|
subtitles_ru_alternate,1,3,ugrep (lines),ugrep -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,8.304608345031738,691,
|
||||||
|
subtitles_ru_alternate,1,3,ugrep (lines),ugrep -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,8.322760820388794,691,
|
||||||
|
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,0.6119842529296875,691,
|
||||||
|
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,0.6368775367736816,691,
|
||||||
|
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,0.6258070468902588,691,
|
||||||
|
subtitles_ru_alternate,1,3,grep,grep -E Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.4300291538238525,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,3,grep,grep -E Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.418199300765991,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate,1,3,grep,grep -E Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.425868511199951,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,2.7216460704803467,691,
|
||||||
|
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,2.7108607292175293,691,
|
||||||
|
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,2.747138500213623,691,
|
||||||
|
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.711230039596558,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.709407329559326,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.714034557342529,691,LC_ALL=C
|
||||||
|
subtitles_ru_alternate_casei,1,3,ugrep (ASCII),ugrep -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,8.305904626846313,691,
|
||||||
|
subtitles_ru_alternate_casei,1,3,ugrep (ASCII),ugrep -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,8.307406187057495,691,
|
||||||
|
subtitles_ru_alternate_casei,1,3,ugrep (ASCII),ugrep -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,8.288233995437622,691,
|
||||||
|
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,3.673624277114868,735,
|
||||||
|
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,3.6759188175201416,735,
|
||||||
|
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,3.66877818107605,735,
|
||||||
|
subtitles_ru_alternate_casei,1,3,grep,grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.366282224655151,735,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_alternate_casei,1,3,grep,grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.370524883270264,735,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_alternate_casei,1,3,grep,grep -E -ni Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /dev/shm/benchsuite/subtitles/ru.txt,5.342163324356079,735,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.20331382751464844,278,
|
||||||
|
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.2034592628479004,278,
|
||||||
|
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.20407724380493164,278,
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep,grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0436389446258545,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep,grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0388383865356445,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep,grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0446207523345947,278,LC_ALL=en_US.UTF-8
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep,ugrep -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.29245424270629883,1,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep,ugrep -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.29168128967285156,1,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep,ugrep -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.29593825340270996,1,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.085604190826416,,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.083526372909546,,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.1223819255828857,,
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.9905192852020264,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0222513675689697,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -n \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,1.0216262340545654,,LC_ALL=C
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep (ASCII),ugrep -a -n -U \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.8875806331634521,,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep (ASCII),ugrep -a -n -U \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.8861405849456787,,
|
||||||
|
subtitles_ru_surrounding_words,1,3,ugrep (ASCII),ugrep -a -n -U \w+\s+Холмс\s+\w+ /dev/shm/benchsuite/subtitles/ru.txt,0.8898241519927979,,
|
||||||
|
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,2.237398147583008,41,
|
||||||
|
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,2.253706693649292,41,
|
||||||
|
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,2.2161178588867188,41,
|
||||||
|
subtitles_ru_no_literal,1,3,ugrep,ugrep -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,28.85959553718567,41,
|
||||||
|
subtitles_ru_no_literal,1,3,ugrep,ugrep -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,28.666419982910156,41,
|
||||||
|
subtitles_ru_no_literal,1,3,ugrep,ugrep -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,28.90555214881897,41,
|
||||||
|
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,2.051813840866089,,
|
||||||
|
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,2.026675224304199,,
|
||||||
|
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,2.027498245239258,,
|
||||||
|
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,1.0998010635375977,,
|
||||||
|
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,1.0900018215179443,,
|
||||||
|
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,1.0901548862457275,,
|
||||||
|
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,1.0691263675689697,,LC_ALL=C
|
||||||
|
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,1.0875153541564941,,LC_ALL=C
|
||||||
|
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,1.0997354984283447,,LC_ALL=C
|
||||||
|
subtitles_ru_no_literal,1,3,ugrep (ASCII),ugrep -anU \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,0.8329172134399414,,
|
||||||
|
subtitles_ru_no_literal,1,3,ugrep (ASCII),ugrep -anU \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,0.8292679786682129,,
|
||||||
|
subtitles_ru_no_literal,1,3,ugrep (ASCII),ugrep -anU \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /dev/shm/benchsuite/subtitles/ru.txt,0.8326950073242188,,
|
||||||
|
208
benchsuite/runs/2022-12-16-archlinux-duff/summary
Normal file
208
benchsuite/runs/2022-12-16-archlinux-duff/summary
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
linux_literal_default (pattern: PM_RESUME)
|
||||||
|
------------------------------------------
|
||||||
|
rg* 0.084 +/- 0.002 (lines: 39)*
|
||||||
|
ag 0.295 +/- 0.001 (lines: 39)
|
||||||
|
git grep 0.225 +/- 0.007 (lines: 39)
|
||||||
|
ugrep 0.105 +/- 0.002 (lines: 39)
|
||||||
|
grep 0.996 +/- 0.003 (lines: 39)
|
||||||
|
|
||||||
|
linux_literal (pattern: PM_RESUME)
|
||||||
|
----------------------------------
|
||||||
|
rg* 0.085 +/- 0.001 (lines: 39)*
|
||||||
|
rg (mmap) 0.322 +/- 0.002 (lines: 39)
|
||||||
|
ag (mmap) 0.290 +/- 0.002 (lines: 39)
|
||||||
|
git grep 0.211 +/- 0.009 (lines: 39)
|
||||||
|
ugrep 0.189 +/- 0.005 (lines: 39)
|
||||||
|
|
||||||
|
linux_literal_casei (pattern: PM_RESUME)
|
||||||
|
----------------------------------------
|
||||||
|
rg* 0.088 +/- 0.001 (lines: 536)*
|
||||||
|
rg (mmap) 0.314 +/- 0.007 (lines: 536)
|
||||||
|
ag (mmap) 0.299 +/- 0.001 (lines: 536)
|
||||||
|
git grep 0.214 +/- 0.007 (lines: 536)
|
||||||
|
ugrep 0.174 +/- 0.001 (lines: 536)
|
||||||
|
|
||||||
|
linux_re_literal_suffix (pattern: [A-Z]+_RESUME)
|
||||||
|
------------------------------------------------
|
||||||
|
rg* 0.085 +/- 0.000 (lines: 2160)*
|
||||||
|
ag 0.369 +/- 0.009 (lines: 2160)
|
||||||
|
git grep 0.915 +/- 0.048 (lines: 2160)
|
||||||
|
ugrep 0.433 +/- 0.025 (lines: 2160)
|
||||||
|
|
||||||
|
linux_word (pattern: PM_RESUME)
|
||||||
|
-------------------------------
|
||||||
|
rg* 0.085 +/- 0.001 (lines: 9)*
|
||||||
|
ag 0.287 +/- 0.001 (lines: 9)
|
||||||
|
git grep 0.206 +/- 0.002 (lines: 9)
|
||||||
|
ugrep 0.189 +/- 0.002 (lines: 9)
|
||||||
|
|
||||||
|
linux_unicode_greek (pattern: \p{Greek})
|
||||||
|
----------------------------------------
|
||||||
|
rg 0.201 +/- 0.005 (lines: 105)
|
||||||
|
ugrep* 0.181 +/- 0.005 (lines: 105)*
|
||||||
|
|
||||||
|
linux_unicode_greek_casei (pattern: \p{Greek})
|
||||||
|
----------------------------------------------
|
||||||
|
rg 0.198 +/- 0.000 (lines: 245)
|
||||||
|
ugrep* 0.179 +/- 0.003 (lines: 105)*
|
||||||
|
|
||||||
|
linux_unicode_word (pattern: \wAh)
|
||||||
|
----------------------------------
|
||||||
|
rg 0.085 +/- 0.000 (lines: 247)
|
||||||
|
rg (ASCII)* 0.085 +/- 0.000 (lines: 233)*
|
||||||
|
ag (ASCII) 0.301 +/- 0.005 (lines: 233)
|
||||||
|
git grep 3.980 +/- 0.241 (lines: 247)
|
||||||
|
git grep (ASCII) 1.620 +/- 0.032 (lines: 233)
|
||||||
|
ugrep 0.177 +/- 0.003 (lines: 247)
|
||||||
|
ugrep (ASCII) 0.185 +/- 0.005 (lines: 233)
|
||||||
|
|
||||||
|
linux_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
rg 0.266 +/- 0.006 (lines: 721)
|
||||||
|
rg (ASCII)* 0.200 +/- 0.001 (lines: 720)*
|
||||||
|
ag (ASCII) 0.832 +/- 0.007 (lines: 1134)
|
||||||
|
git grep 7.346 +/- 0.017 (lines: 721)
|
||||||
|
git grep (ASCII) 2.144 +/- 0.014 (lines: 720)
|
||||||
|
ugrep 3.403 +/- 0.008 (lines: 723)
|
||||||
|
ugrep (ASCII) 0.236 +/- 0.003 (lines: 722)
|
||||||
|
|
||||||
|
linux_alternates (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
rg* 0.087 +/- 0.000 (lines: 140)*
|
||||||
|
ag 0.330 +/- 0.002 (lines: 140)
|
||||||
|
git grep 0.414 +/- 0.047 (lines: 140)
|
||||||
|
ugrep 0.179 +/- 0.002 (lines: 140)
|
||||||
|
|
||||||
|
linux_alternates_casei (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
rg* 0.123 +/- 0.001 (lines: 241)*
|
||||||
|
ag 0.530 +/- 0.001 (lines: 241)
|
||||||
|
git grep 0.792 +/- 0.036 (lines: 241)
|
||||||
|
ugrep 0.177 +/- 0.003 (lines: 241)
|
||||||
|
|
||||||
|
subtitles_en_literal (pattern: Sherlock Holmes)
|
||||||
|
-----------------------------------------------
|
||||||
|
rg* 0.123 +/- 0.003 (lines: 830)*
|
||||||
|
rg (no mmap) 0.176 +/- 0.005 (lines: 830)
|
||||||
|
grep 0.572 +/- 0.017 (lines: 830)
|
||||||
|
rg (lines) 0.189 +/- 0.006 (lines: 830)
|
||||||
|
ag (lines) 1.868 +/- 0.004 (lines: 830)
|
||||||
|
grep (lines) 0.980 +/- 0.036 (lines: 830)
|
||||||
|
ugrep (lines) 0.185 +/- 0.007 (lines: 830)
|
||||||
|
|
||||||
|
subtitles_en_literal_casei (pattern: Sherlock Holmes)
|
||||||
|
-----------------------------------------------------
|
||||||
|
rg* 0.214 +/- 0.008 (lines: 871)*
|
||||||
|
grep 2.224 +/- 0.000 (lines: 871)
|
||||||
|
grep (ASCII) 0.671 +/- 0.001 (lines: 871)
|
||||||
|
rg (lines) 0.259 +/- 0.004 (lines: 871)
|
||||||
|
ag (lines) (ASCII) 1.897 +/- 0.026 (lines: 871)
|
||||||
|
ugrep (lines) 0.785 +/- 0.002 (lines: 871)
|
||||||
|
|
||||||
|
subtitles_en_literal_word (pattern: Sherlock Holmes)
|
||||||
|
----------------------------------------------------
|
||||||
|
rg (ASCII) 0.189 +/- 0.006 (lines: 830)
|
||||||
|
ag (ASCII) 1.842 +/- 0.023 (lines: 830)
|
||||||
|
grep (ASCII) 0.977 +/- 0.046 (lines: 830)
|
||||||
|
ugrep (ASCII)* 0.182 +/- 0.007 (lines: 830)*
|
||||||
|
rg 0.192 +/- 0.006 (lines: 830)
|
||||||
|
grep 0.990 +/- 0.024 (lines: 830)
|
||||||
|
|
||||||
|
subtitles_en_alternate (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
|
||||||
|
---------------------------------------------------------------------------------------------------------------
|
||||||
|
rg (lines) 0.248 +/- 0.001 (lines: 1094)
|
||||||
|
ag (lines) 2.638 +/- 0.055 (lines: 1094)
|
||||||
|
grep (lines) 2.052 +/- 0.027 (lines: 1094)
|
||||||
|
ugrep (lines) 0.787 +/- 0.001 (lines: 1094)
|
||||||
|
rg* 0.176 +/- 0.011 (lines: 1094)*
|
||||||
|
grep 1.660 +/- 0.002 (lines: 1094)
|
||||||
|
|
||||||
|
subtitles_en_alternate_casei (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
|
||||||
|
---------------------------------------------------------------------------------------------------------------------
|
||||||
|
ag (ASCII) 3.999 +/- 0.007 (lines: 1136)
|
||||||
|
grep (ASCII) 3.561 +/- 0.023 (lines: 1136)
|
||||||
|
ugrep (ASCII) 0.787 +/- 0.002 (lines: 1136)
|
||||||
|
rg* 0.483 +/- 0.009 (lines: 1136)*
|
||||||
|
grep 3.585 +/- 0.018 (lines: 1136)
|
||||||
|
|
||||||
|
subtitles_en_surrounding_words (pattern: \w+\s+Holmes\s+\w+)
|
||||||
|
------------------------------------------------------------
|
||||||
|
rg 0.200 +/- 0.001 (lines: 483)
|
||||||
|
grep 1.303 +/- 0.040 (lines: 483)
|
||||||
|
ugrep 43.220 +/- 0.047 (lines: 483)
|
||||||
|
rg (ASCII)* 0.197 +/- 0.000 (lines: 483)*
|
||||||
|
ag (ASCII) 5.223 +/- 0.056 (lines: 489)
|
||||||
|
grep (ASCII) 1.316 +/- 0.043 (lines: 483)
|
||||||
|
ugrep (ASCII) 17.647 +/- 0.219 (lines: 483)
|
||||||
|
|
||||||
|
subtitles_en_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||||
|
----------------------------------------------------------------------------------------
|
||||||
|
rg 2.119 +/- 0.016 (lines: 22)
|
||||||
|
ugrep 13.053 +/- 0.004 (lines: 22)
|
||||||
|
rg (ASCII)* 2.004 +/- 0.013 (lines: 22)*
|
||||||
|
ag (ASCII) 6.830 +/- 0.018 (lines: 302)
|
||||||
|
grep (ASCII) 4.395 +/- 0.030 (lines: 22)
|
||||||
|
ugrep (ASCII) 3.510 +/- 0.004 (lines: 22)
|
||||||
|
|
||||||
|
subtitles_ru_literal (pattern: Шерлок Холмс)
|
||||||
|
--------------------------------------------
|
||||||
|
rg* 0.133 +/- 0.002 (lines: 583)*
|
||||||
|
rg (no mmap) 0.180 +/- 0.000 (lines: 583)
|
||||||
|
grep 0.510 +/- 0.009 (lines: 583)
|
||||||
|
rg (lines) 0.193 +/- 0.003 (lines: 583)
|
||||||
|
ag (lines) 1.973 +/- 0.025 (lines: 583)
|
||||||
|
grep (lines) 0.808 +/- 0.006 (lines: 583)
|
||||||
|
ugrep (lines) 0.680 +/- 0.026 (lines: 583)
|
||||||
|
|
||||||
|
subtitles_ru_literal_casei (pattern: Шерлок Холмс)
|
||||||
|
--------------------------------------------------
|
||||||
|
rg* 0.268 +/- 0.001 (lines: 604)*
|
||||||
|
grep 4.767 +/- 0.002 (lines: 604)
|
||||||
|
grep (ASCII) 0.506 +/- 0.007 (lines: 583)
|
||||||
|
rg (lines) 0.335 +/- 0.005 (lines: 604)
|
||||||
|
ag (lines) (ASCII) 0.457 +/- 0.019 (lines: 0)
|
||||||
|
ugrep (lines) (ASCII) 0.720 +/- 0.081 (lines: 583)
|
||||||
|
|
||||||
|
subtitles_ru_literal_word (pattern: Шерлок Холмс)
|
||||||
|
-------------------------------------------------
|
||||||
|
rg (ASCII)* 0.195 +/- 0.011 (lines: 583)*
|
||||||
|
ag (ASCII) 0.509 +/- 0.020 (lines: 0)
|
||||||
|
grep (ASCII) 0.800 +/- 0.019 (lines: 583)
|
||||||
|
ugrep (ASCII) 0.708 +/- 0.034 (lines: 583)
|
||||||
|
rg 0.201 +/- 0.003 (lines: 579)
|
||||||
|
grep 0.792 +/- 0.020 (lines: 579)
|
||||||
|
|
||||||
|
subtitles_ru_alternate (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
|
||||||
|
-----------------------------------------------------------------------------------------------------------
|
||||||
|
rg (lines) 0.682 +/- 0.018 (lines: 691)
|
||||||
|
ag (lines) 2.722 +/- 0.020 (lines: 691)
|
||||||
|
grep (lines) 5.711 +/- 0.006 (lines: 691)
|
||||||
|
ugrep (lines) 8.301 +/- 0.023 (lines: 691)
|
||||||
|
rg* 0.625 +/- 0.012 (lines: 691)*
|
||||||
|
grep 5.425 +/- 0.006 (lines: 691)
|
||||||
|
|
||||||
|
subtitles_ru_alternate_casei (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
|
||||||
|
-----------------------------------------------------------------------------------------------------------------
|
||||||
|
ag (ASCII)* 2.727 +/- 0.019 (lines: 691)*
|
||||||
|
grep (ASCII) 5.712 +/- 0.002 (lines: 691)
|
||||||
|
ugrep (ASCII) 8.301 +/- 0.011 (lines: 691)
|
||||||
|
rg 3.673 +/- 0.004 (lines: 735)
|
||||||
|
grep 5.360 +/- 0.015 (lines: 735)
|
||||||
|
|
||||||
|
subtitles_ru_surrounding_words (pattern: \w+\s+Холмс\s+\w+)
|
||||||
|
-----------------------------------------------------------
|
||||||
|
rg* 0.203 +/- 0.001 (lines: 278)*
|
||||||
|
grep 1.039 +/- 0.009 (lines: 278)
|
||||||
|
ugrep 42.919 +/- 0.087 (lines: 278)
|
||||||
|
ag (ASCII) 1.084 +/- 0.001 (lines: 0)
|
||||||
|
grep (ASCII) 1.007 +/- 0.018 (lines: 0)
|
||||||
|
ugrep (ASCII) 0.890 +/- 0.001 (lines: 0)
|
||||||
|
|
||||||
|
subtitles_ru_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||||
|
----------------------------------------------------------------------------------------
|
||||||
|
rg 2.236 +/- 0.019 (lines: 41)
|
||||||
|
ugrep 28.811 +/- 0.127 (lines: 41)
|
||||||
|
rg (ASCII) 2.035 +/- 0.014 (lines: 0)
|
||||||
|
ag (ASCII) 1.093 +/- 0.006 (lines: 0)
|
||||||
|
grep (ASCII) 1.085 +/- 0.015 (lines: 0)
|
||||||
|
ugrep (ASCII)* 0.832 +/- 0.002 (lines: 0)*
|
||||||
49
build.rs
49
build.rs
@@ -65,6 +65,51 @@ fn git_revision_hash() -> Option<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generate_man_page<P: AsRef<Path>>(outdir: P) -> io::Result<()> {
|
fn generate_man_page<P: AsRef<Path>>(outdir: P) -> io::Result<()> {
|
||||||
|
// If asciidoctor isn't installed, fallback to asciidoc.
|
||||||
|
if let Err(err) = process::Command::new("asciidoctor").output() {
|
||||||
|
eprintln!(
|
||||||
|
"Could not run 'asciidoctor' binary, falling back to 'a2x'."
|
||||||
|
);
|
||||||
|
eprintln!("Error from running 'asciidoctor': {}", err);
|
||||||
|
return legacy_generate_man_page::<P>(outdir);
|
||||||
|
}
|
||||||
|
// 1. Read asciidoctor template.
|
||||||
|
// 2. Interpolate template with auto-generated docs.
|
||||||
|
// 3. Save interpolation to disk.
|
||||||
|
// 4. Use asciidoctor to convert to man page.
|
||||||
|
let outdir = outdir.as_ref();
|
||||||
|
let cwd = env::current_dir()?;
|
||||||
|
let tpl_path = cwd.join("doc").join("rg.1.txt.tpl");
|
||||||
|
let txt_path = outdir.join("rg.1.txt");
|
||||||
|
|
||||||
|
let mut tpl = String::new();
|
||||||
|
File::open(&tpl_path)?.read_to_string(&mut tpl)?;
|
||||||
|
let options =
|
||||||
|
formatted_options()?.replace("{", "{").replace("}", "}");
|
||||||
|
tpl = tpl.replace("{OPTIONS}", &options);
|
||||||
|
|
||||||
|
let githash = git_revision_hash();
|
||||||
|
let githash = githash.as_ref().map(|x| &**x);
|
||||||
|
tpl = tpl.replace("{VERSION}", &app::long_version(githash, false));
|
||||||
|
|
||||||
|
File::create(&txt_path)?.write_all(tpl.as_bytes())?;
|
||||||
|
let result = process::Command::new("asciidoctor")
|
||||||
|
.arg("--doctype")
|
||||||
|
.arg("manpage")
|
||||||
|
.arg("--backend")
|
||||||
|
.arg("manpage")
|
||||||
|
.arg(&txt_path)
|
||||||
|
.spawn()?
|
||||||
|
.wait()?;
|
||||||
|
if !result.success() {
|
||||||
|
let msg =
|
||||||
|
format!("'asciidoctor' failed with exit code {:?}", result.code());
|
||||||
|
return Err(ioerr(msg));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn legacy_generate_man_page<P: AsRef<Path>>(outdir: P) -> io::Result<()> {
|
||||||
// If asciidoc isn't installed, then don't do anything.
|
// If asciidoc isn't installed, then don't do anything.
|
||||||
if let Err(err) = process::Command::new("a2x").output() {
|
if let Err(err) = process::Command::new("a2x").output() {
|
||||||
eprintln!("Could not run 'a2x' binary, skipping man page generation.");
|
eprintln!("Could not run 'a2x' binary, skipping man page generation.");
|
||||||
@@ -172,6 +217,10 @@ fn formatted_doc_txt(arg: &RGArg) -> io::Result<String> {
|
|||||||
.doc_long
|
.doc_long
|
||||||
.replace("{", "{")
|
.replace("{", "{")
|
||||||
.replace("}", r"}")
|
.replace("}", r"}")
|
||||||
|
// Hack to render ** literally in man page correctly. We can't put
|
||||||
|
// these crazy +++ in the help text directly, since that shows
|
||||||
|
// literally in --help output.
|
||||||
|
.replace("*-g 'foo/**'*", "*-g +++'foo/**'+++*")
|
||||||
.split("\n\n")
|
.split("\n\n")
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
|
|||||||
12
ci/build-deb
12
ci/build-deb
@@ -17,20 +17,26 @@ if ! command -V cargo-deb > /dev/null 2>&1; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! command -V asciidoctor > /dev/null 2>&1; then
|
||||||
|
echo "asciidoctor command missing" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# 'cargo deb' does not seem to provide a way to specify an asset that is
|
# 'cargo deb' does not seem to provide a way to specify an asset that is
|
||||||
# created at build time, such as ripgrep's man page. To work around this,
|
# created at build time, such as ripgrep's man page. To work around this,
|
||||||
# we force a debug build, copy out the man page (and shell completions)
|
# we force a debug build, copy out the man page (and shell completions)
|
||||||
# produced from that build, put it into a predictable location and then build
|
# produced from that build, put it into a predictable location and then build
|
||||||
# the deb, which knows where to look.
|
# the deb, which knows where to look.
|
||||||
|
cargo build
|
||||||
|
|
||||||
DEPLOY_DIR=deployment/deb
|
DEPLOY_DIR=deployment/deb
|
||||||
OUT_DIR="$("$D"/cargo-out-dir target/debug/)"
|
OUT_DIR="$("$D"/cargo-out-dir target/debug/)"
|
||||||
mkdir -p "$DEPLOY_DIR"
|
mkdir -p "$DEPLOY_DIR"
|
||||||
cargo build
|
|
||||||
|
|
||||||
# Copy man page and shell completions.
|
# Copy man page and shell completions.
|
||||||
cp "$OUT_DIR"/{rg.1,rg.bash,rg.fish,_rg} "$DEPLOY_DIR/"
|
cp "$OUT_DIR"/{rg.1,rg.bash,rg.fish} "$DEPLOY_DIR/"
|
||||||
|
cp complete/_rg "$DEPLOY_DIR/"
|
||||||
|
|
||||||
# Since we're distributing the dpkg, we don't know whether the user will have
|
# Since we're distributing the dpkg, we don't know whether the user will have
|
||||||
# PCRE2 installed, so just do a static build.
|
# PCRE2 installed, so just do a static build.
|
||||||
PCRE2_SYS_STATIC=1 cargo deb
|
PCRE2_SYS_STATIC=1 cargo deb --target x86_64-unknown-linux-musl
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ via the [Cross](https://github.com/rust-embedded/cross) tool.
|
|||||||
The Cross tool actually provides its own Docker images, and all Docker images
|
The Cross tool actually provides its own Docker images, and all Docker images
|
||||||
in this directory are derived from one of them. We provide our own in order
|
in this directory are derived from one of them. We provide our own in order
|
||||||
to customize the environment. For example, we need to install some things like
|
to customize the environment. For example, we need to install some things like
|
||||||
`asciidoc` in order to generate man pages. We also install compression tools
|
`asciidoctor` in order to generate man pages. We also install compression tools
|
||||||
like `xz` so that tests for the `-z/--search-zip` flag are run.
|
like `xz` so that tests for the `-z/--search-zip` flag are run.
|
||||||
|
|
||||||
If you make a change to a Docker image, then you can re-build it. `cd` into the
|
If you make a change to a Docker image, then you can re-build it. `cd` into the
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
brew install asciidoc docbook-xsl
|
brew install asciidoctor
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ main() {
|
|||||||
# Occasionally we may have to handle some manually, however
|
# Occasionally we may have to handle some manually, however
|
||||||
help_args=( ${(f)"$(
|
help_args=( ${(f)"$(
|
||||||
$rg --help |
|
$rg --help |
|
||||||
$rg -i -- '^\s+--?[a-z0-9]|--[a-z]' |
|
$rg -i -- '^\s+--?[a-z0-9.]|--[a-z]' |
|
||||||
$rg -ior '$1' -- $'[\t /\"\'`.,](-[a-z0-9]|--[a-z0-9-]+)\\b' |
|
$rg -ior '$1' -- $'[\t /\"\'`.,](-[a-z0-9.]|--[a-z0-9-]+)(,|\\b)' |
|
||||||
$rg -v -- --print0 | # False positives
|
$rg -v -- --print0 | # False positives
|
||||||
sort -u
|
sort -u
|
||||||
)"} )
|
)"} )
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
# This script gets run in weird environments that have been stripped of just
|
||||||
|
# about every inessential thing. In order to keep this script versatile, we
|
||||||
|
# just install 'sudo' and use it like normal if it doesn't exist. If it doesn't
|
||||||
|
# exist, we assume we're root. (Otherwise we ain't doing much of anything
|
||||||
|
# anyway.)
|
||||||
|
if ! command -V sudo; then
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y --no-install-recommends sudo
|
||||||
|
fi
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y --no-install-recommends \
|
sudo apt-get install -y --no-install-recommends \
|
||||||
libxslt1-dev asciidoc docbook-xsl xsltproc libxml2-utils \
|
asciidoctor \
|
||||||
zsh xz-utils liblz4-tool musl-tools
|
zsh xz-utils liblz4-tool musl-tools \
|
||||||
|
brotli zstd
|
||||||
|
|||||||
@@ -99,9 +99,7 @@ is_osx() {
|
|||||||
|
|
||||||
builder() {
|
builder() {
|
||||||
if is_musl && is_x86_64; then
|
if is_musl && is_x86_64; then
|
||||||
# cargo install cross
|
cargo install cross
|
||||||
# To work around https://github.com/rust-embedded/cross/issues/357
|
|
||||||
cargo install --git https://github.com/rust-embedded/cross --force
|
|
||||||
echo "cross"
|
echo "cross"
|
||||||
else
|
else
|
||||||
echo "cargo"
|
echo "cargo"
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ _rg() {
|
|||||||
"(pretty-vimgrep)--no-heading[don't show matches grouped by file name]"
|
"(pretty-vimgrep)--no-heading[don't show matches grouped by file name]"
|
||||||
|
|
||||||
+ '(hidden)' # Hidden-file options
|
+ '(hidden)' # Hidden-file options
|
||||||
'--hidden[search hidden files and directories]'
|
{-.,--hidden}'[search hidden files and directories]'
|
||||||
$no"--no-hidden[don't search hidden files and directories]"
|
$no"--no-hidden[don't search hidden files and directories]"
|
||||||
|
|
||||||
+ '(hybrid)' # hybrid regex options
|
+ '(hybrid)' # hybrid regex options
|
||||||
@@ -303,6 +303,8 @@ _rg() {
|
|||||||
'--context-separator=[specify string used to separate non-continuous context lines in output]:separator'
|
'--context-separator=[specify string used to separate non-continuous context lines in output]:separator'
|
||||||
$no"--no-context-separator[don't print context separators]"
|
$no"--no-context-separator[don't print context separators]"
|
||||||
'--debug[show debug messages]'
|
'--debug[show debug messages]'
|
||||||
|
'--field-context-separator[set string to delimit fields in context lines]'
|
||||||
|
'--field-match-separator[set string to delimit fields in matching lines]'
|
||||||
'--trace[show more verbose debug messages]'
|
'--trace[show more verbose debug messages]'
|
||||||
'--dfa-size-limit=[specify upper size limit of generated DFA]:DFA size (bytes)'
|
'--dfa-size-limit=[specify upper size limit of generated DFA]:DFA size (bytes)'
|
||||||
"(1 stats)--files[show each file that would be searched (but don't search)]"
|
"(1 stats)--files[show each file that would be searched (but don't search)]"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-cli"
|
name = "grep-cli"
|
||||||
version = "0.1.4" #:version
|
version = "0.1.6" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Utilities for search oriented command line applications.
|
Utilities for search oriented command line applications.
|
||||||
@@ -10,12 +10,13 @@ homepage = "https://github.com/BurntSushi/ripgrep/tree/master/crates/cli"
|
|||||||
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/cli"
|
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/cli"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["regex", "grep", "cli", "utility", "util"]
|
keywords = ["regex", "grep", "cli", "utility", "util"]
|
||||||
license = "Unlicense/MIT"
|
license = "Unlicense OR MIT"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
atty = "0.2.11"
|
atty = "0.2.11"
|
||||||
bstr = "0.2.0"
|
bstr = "1.1.0"
|
||||||
globset = { version = "0.4.3", path = "../globset" }
|
globset = { version = "0.4.10", path = "../globset" }
|
||||||
lazy_static = "1.1.0"
|
lazy_static = "1.1.0"
|
||||||
log = "0.4.5"
|
log = "0.4.5"
|
||||||
regex = "1.1"
|
regex = "1.1"
|
||||||
|
|||||||
@@ -5,11 +5,10 @@ command line applications. This includes, but is not limited to, parsing hex
|
|||||||
escapes, detecting whether stdin is readable and more. To the extent possible,
|
escapes, detecting whether stdin is readable and more. To the extent possible,
|
||||||
this crate strives for compatibility across Windows, macOS and Linux.
|
this crate strives for compatibility across Windows, macOS and Linux.
|
||||||
|
|
||||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
[](https://github.com/BurntSushi/ripgrep/actions)
|
||||||
[](https://ci.appveyor.com/project/BurntSushi/ripgrep)
|
|
||||||
[](https://crates.io/crates/grep-cli)
|
[](https://crates.io/crates/grep-cli)
|
||||||
|
|
||||||
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
|
||||||
|
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
@@ -30,9 +29,3 @@ Add this to your `Cargo.toml`:
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
grep-cli = "0.1"
|
grep-cli = "0.1"
|
||||||
```
|
```
|
||||||
|
|
||||||
and this to your crate root:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
extern crate grep_cli;
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use std::ffi::{OsStr, OsString};
|
use std::ffi::{OsStr, OsString};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use globset::{Glob, GlobSet, GlobSetBuilder};
|
use globset::{Glob, GlobSet, GlobSetBuilder};
|
||||||
|
|
||||||
use process::{CommandError, CommandReader, CommandReaderBuilder};
|
use crate::process::{CommandError, CommandReader, CommandReaderBuilder};
|
||||||
|
|
||||||
/// A builder for a matcher that determines which files get decompressed.
|
/// A builder for a matcher that determines which files get decompressed.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -24,7 +24,7 @@ struct DecompressionCommand {
|
|||||||
/// The glob that matches this command.
|
/// The glob that matches this command.
|
||||||
glob: String,
|
glob: String,
|
||||||
/// The command or binary name.
|
/// The command or binary name.
|
||||||
bin: OsString,
|
bin: PathBuf,
|
||||||
/// The arguments to invoke with the command.
|
/// The arguments to invoke with the command.
|
||||||
args: Vec<OsString>,
|
args: Vec<OsString>,
|
||||||
}
|
}
|
||||||
@@ -83,23 +83,60 @@ impl DecompressionMatcherBuilder {
|
|||||||
///
|
///
|
||||||
/// The syntax for the glob is documented in the
|
/// The syntax for the glob is documented in the
|
||||||
/// [`globset` crate](https://docs.rs/globset/#syntax).
|
/// [`globset` crate](https://docs.rs/globset/#syntax).
|
||||||
|
///
|
||||||
|
/// The `program` given is resolved with respect to `PATH` and turned
|
||||||
|
/// into an absolute path internally before being executed by the current
|
||||||
|
/// platform. Notably, on Windows, this avoids a security problem where
|
||||||
|
/// passing a relative path to `CreateProcess` will automatically search
|
||||||
|
/// the current directory for a matching program. If the program could
|
||||||
|
/// not be resolved, then it is silently ignored and the association is
|
||||||
|
/// dropped. For this reason, callers should prefer `try_associate`.
|
||||||
pub fn associate<P, I, A>(
|
pub fn associate<P, I, A>(
|
||||||
&mut self,
|
&mut self,
|
||||||
glob: &str,
|
glob: &str,
|
||||||
program: P,
|
program: P,
|
||||||
args: I,
|
args: I,
|
||||||
) -> &mut DecompressionMatcherBuilder
|
) -> &mut DecompressionMatcherBuilder
|
||||||
|
where
|
||||||
|
P: AsRef<OsStr>,
|
||||||
|
I: IntoIterator<Item = A>,
|
||||||
|
A: AsRef<OsStr>,
|
||||||
|
{
|
||||||
|
let _ = self.try_associate(glob, program, args);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Associates a glob with a command to decompress files matching the glob.
|
||||||
|
///
|
||||||
|
/// If multiple globs match the same file, then the most recently added
|
||||||
|
/// glob takes precedence.
|
||||||
|
///
|
||||||
|
/// The syntax for the glob is documented in the
|
||||||
|
/// [`globset` crate](https://docs.rs/globset/#syntax).
|
||||||
|
///
|
||||||
|
/// The `program` given is resolved with respect to `PATH` and turned
|
||||||
|
/// into an absolute path internally before being executed by the current
|
||||||
|
/// platform. Notably, on Windows, this avoids a security problem where
|
||||||
|
/// passing a relative path to `CreateProcess` will automatically search
|
||||||
|
/// the current directory for a matching program. If the program could not
|
||||||
|
/// be resolved, then an error is returned.
|
||||||
|
pub fn try_associate<P, I, A>(
|
||||||
|
&mut self,
|
||||||
|
glob: &str,
|
||||||
|
program: P,
|
||||||
|
args: I,
|
||||||
|
) -> Result<&mut DecompressionMatcherBuilder, CommandError>
|
||||||
where
|
where
|
||||||
P: AsRef<OsStr>,
|
P: AsRef<OsStr>,
|
||||||
I: IntoIterator<Item = A>,
|
I: IntoIterator<Item = A>,
|
||||||
A: AsRef<OsStr>,
|
A: AsRef<OsStr>,
|
||||||
{
|
{
|
||||||
let glob = glob.to_string();
|
let glob = glob.to_string();
|
||||||
let bin = program.as_ref().to_os_string();
|
let bin = resolve_binary(Path::new(program.as_ref()))?;
|
||||||
let args =
|
let args =
|
||||||
args.into_iter().map(|a| a.as_ref().to_os_string()).collect();
|
args.into_iter().map(|a| a.as_ref().to_os_string()).collect();
|
||||||
self.commands.push(DecompressionCommand { glob, bin, args });
|
self.commands.push(DecompressionCommand { glob, bin, args });
|
||||||
self
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,7 +230,7 @@ impl DecompressionReaderBuilder {
|
|||||||
match self.command_builder.build(&mut cmd) {
|
match self.command_builder.build(&mut cmd) {
|
||||||
Ok(cmd_reader) => Ok(DecompressionReader { rdr: Ok(cmd_reader) }),
|
Ok(cmd_reader) => Ok(DecompressionReader { rdr: Ok(cmd_reader) }),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
debug!(
|
log::debug!(
|
||||||
"{}: error spawning command '{:?}': {} \
|
"{}: error spawning command '{:?}': {} \
|
||||||
(falling back to uncompressed reader)",
|
(falling back to uncompressed reader)",
|
||||||
path.display(),
|
path.display(),
|
||||||
@@ -329,6 +366,30 @@ impl DecompressionReader {
|
|||||||
let file = File::open(path)?;
|
let file = File::open(path)?;
|
||||||
Ok(DecompressionReader { rdr: Err(file) })
|
Ok(DecompressionReader { rdr: Err(file) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Closes this reader, freeing any resources used by its underlying child
|
||||||
|
/// process, if one was used. If the child process exits with a nonzero
|
||||||
|
/// exit code, the returned Err value will include its stderr.
|
||||||
|
///
|
||||||
|
/// `close` is idempotent, meaning it can be safely called multiple times.
|
||||||
|
/// The first call closes the CommandReader and any subsequent calls do
|
||||||
|
/// nothing.
|
||||||
|
///
|
||||||
|
/// This method should be called after partially reading a file to prevent
|
||||||
|
/// resource leakage. However there is no need to call `close` explicitly
|
||||||
|
/// if your code always calls `read` to EOF, as `read` takes care of
|
||||||
|
/// calling `close` in this case.
|
||||||
|
///
|
||||||
|
/// `close` is also called in `drop` as a last line of defense against
|
||||||
|
/// resource leakage. Any error from the child process is then printed as a
|
||||||
|
/// warning to stderr. This can be avoided by explicitly calling `close`
|
||||||
|
/// before the CommandReader is dropped.
|
||||||
|
pub fn close(&mut self) -> io::Result<()> {
|
||||||
|
match self.rdr {
|
||||||
|
Ok(ref mut rdr) => rdr.close(),
|
||||||
|
Err(_) => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl io::Read for DecompressionReader {
|
impl io::Read for DecompressionReader {
|
||||||
@@ -340,6 +401,70 @@ impl io::Read for DecompressionReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolves a path to a program to a path by searching for the program in
|
||||||
|
/// `PATH`.
|
||||||
|
///
|
||||||
|
/// If the program could not be resolved, then an error is returned.
|
||||||
|
///
|
||||||
|
/// The purpose of doing this instead of passing the path to the program
|
||||||
|
/// directly to Command::new is that Command::new will hand relative paths
|
||||||
|
/// to CreateProcess on Windows, which will implicitly search the current
|
||||||
|
/// working directory for the executable. This could be undesirable for
|
||||||
|
/// security reasons. e.g., running ripgrep with the -z/--search-zip flag on an
|
||||||
|
/// untrusted directory tree could result in arbitrary programs executing on
|
||||||
|
/// Windows.
|
||||||
|
///
|
||||||
|
/// Note that this could still return a relative path if PATH contains a
|
||||||
|
/// relative path. We permit this since it is assumed that the user has set
|
||||||
|
/// this explicitly, and thus, desires this behavior.
|
||||||
|
///
|
||||||
|
/// On non-Windows, this is a no-op.
|
||||||
|
pub fn resolve_binary<P: AsRef<Path>>(
|
||||||
|
prog: P,
|
||||||
|
) -> Result<PathBuf, CommandError> {
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn is_exe(path: &Path) -> bool {
|
||||||
|
let md = match path.metadata() {
|
||||||
|
Err(_) => return false,
|
||||||
|
Ok(md) => md,
|
||||||
|
};
|
||||||
|
!md.is_dir()
|
||||||
|
}
|
||||||
|
|
||||||
|
let prog = prog.as_ref();
|
||||||
|
if !cfg!(windows) || prog.is_absolute() {
|
||||||
|
return Ok(prog.to_path_buf());
|
||||||
|
}
|
||||||
|
let syspaths = match env::var_os("PATH") {
|
||||||
|
Some(syspaths) => syspaths,
|
||||||
|
None => {
|
||||||
|
let msg = "system PATH environment variable not found";
|
||||||
|
return Err(CommandError::io(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
msg,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for syspath in env::split_paths(&syspaths) {
|
||||||
|
if syspath.as_os_str().is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let abs_prog = syspath.join(prog);
|
||||||
|
if is_exe(&abs_prog) {
|
||||||
|
return Ok(abs_prog.to_path_buf());
|
||||||
|
}
|
||||||
|
if abs_prog.extension().is_none() {
|
||||||
|
let abs_prog = abs_prog.with_extension("exe");
|
||||||
|
if is_exe(&abs_prog) {
|
||||||
|
return Ok(abs_prog.to_path_buf());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let msg = format!("{}: could not find executable in PATH", prog.display());
|
||||||
|
return Err(CommandError::io(io::Error::new(io::ErrorKind::Other, msg)));
|
||||||
|
}
|
||||||
|
|
||||||
fn default_decompression_commands() -> Vec<DecompressionCommand> {
|
fn default_decompression_commands() -> Vec<DecompressionCommand> {
|
||||||
const ARGS_GZIP: &[&str] = &["gzip", "-d", "-c"];
|
const ARGS_GZIP: &[&str] = &["gzip", "-d", "-c"];
|
||||||
const ARGS_BZIP: &[&str] = &["bzip2", "-d", "-c"];
|
const ARGS_BZIP: &[&str] = &["bzip2", "-d", "-c"];
|
||||||
@@ -348,29 +473,38 @@ fn default_decompression_commands() -> Vec<DecompressionCommand> {
|
|||||||
const ARGS_LZMA: &[&str] = &["xz", "--format=lzma", "-d", "-c"];
|
const ARGS_LZMA: &[&str] = &["xz", "--format=lzma", "-d", "-c"];
|
||||||
const ARGS_BROTLI: &[&str] = &["brotli", "-d", "-c"];
|
const ARGS_BROTLI: &[&str] = &["brotli", "-d", "-c"];
|
||||||
const ARGS_ZSTD: &[&str] = &["zstd", "-q", "-d", "-c"];
|
const ARGS_ZSTD: &[&str] = &["zstd", "-q", "-d", "-c"];
|
||||||
|
const ARGS_UNCOMPRESS: &[&str] = &["uncompress", "-c"];
|
||||||
|
|
||||||
fn cmd(glob: &str, args: &[&str]) -> DecompressionCommand {
|
fn add(glob: &str, args: &[&str], cmds: &mut Vec<DecompressionCommand>) {
|
||||||
DecompressionCommand {
|
let bin = match resolve_binary(Path::new(args[0])) {
|
||||||
|
Ok(bin) => bin,
|
||||||
|
Err(err) => {
|
||||||
|
log::debug!("{}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cmds.push(DecompressionCommand {
|
||||||
glob: glob.to_string(),
|
glob: glob.to_string(),
|
||||||
bin: OsStr::new(&args[0]).to_os_string(),
|
bin,
|
||||||
args: args
|
args: args
|
||||||
.iter()
|
.iter()
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.map(|s| OsStr::new(s).to_os_string())
|
.map(|s| OsStr::new(s).to_os_string())
|
||||||
.collect(),
|
.collect(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
let mut cmds = vec![];
|
||||||
vec![
|
add("*.gz", ARGS_GZIP, &mut cmds);
|
||||||
cmd("*.gz", ARGS_GZIP),
|
add("*.tgz", ARGS_GZIP, &mut cmds);
|
||||||
cmd("*.tgz", ARGS_GZIP),
|
add("*.bz2", ARGS_BZIP, &mut cmds);
|
||||||
cmd("*.bz2", ARGS_BZIP),
|
add("*.tbz2", ARGS_BZIP, &mut cmds);
|
||||||
cmd("*.tbz2", ARGS_BZIP),
|
add("*.xz", ARGS_XZ, &mut cmds);
|
||||||
cmd("*.xz", ARGS_XZ),
|
add("*.txz", ARGS_XZ, &mut cmds);
|
||||||
cmd("*.txz", ARGS_XZ),
|
add("*.lz4", ARGS_LZ4, &mut cmds);
|
||||||
cmd("*.lz4", ARGS_LZ4),
|
add("*.lzma", ARGS_LZMA, &mut cmds);
|
||||||
cmd("*.lzma", ARGS_LZMA),
|
add("*.br", ARGS_BROTLI, &mut cmds);
|
||||||
cmd("*.br", ARGS_BROTLI),
|
add("*.zst", ARGS_ZSTD, &mut cmds);
|
||||||
cmd("*.zst", ARGS_ZSTD),
|
add("*.zstd", ARGS_ZSTD, &mut cmds);
|
||||||
cmd("*.zstd", ARGS_ZSTD),
|
add("*.Z", ARGS_UNCOMPRESS, &mut cmds);
|
||||||
]
|
cmds
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use regex::Regex;
|
|||||||
|
|
||||||
/// An error that occurs when parsing a human readable size description.
|
/// An error that occurs when parsing a human readable size description.
|
||||||
///
|
///
|
||||||
/// This error provides a end user friendly message describing why the
|
/// This error provides an end user friendly message describing why the
|
||||||
/// description coudln't be parsed and what the expected format is.
|
/// description couldn't be parsed and what the expected format is.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct ParseSizeError {
|
pub struct ParseSizeError {
|
||||||
original: String,
|
original: String,
|
||||||
@@ -52,7 +52,7 @@ impl error::Error for ParseSizeError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ParseSizeError {
|
impl fmt::Display for ParseSizeError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
use self::ParseSizeErrorKind::*;
|
use self::ParseSizeErrorKind::*;
|
||||||
|
|
||||||
match self.kind {
|
match self.kind {
|
||||||
@@ -88,7 +88,7 @@ impl From<ParseSizeError> for io::Error {
|
|||||||
///
|
///
|
||||||
/// Additional suffixes may be added over time.
|
/// Additional suffixes may be added over time.
|
||||||
pub fn parse_human_readable_size(size: &str) -> Result<u64, ParseSizeError> {
|
pub fn parse_human_readable_size(size: &str) -> Result<u64, ParseSizeError> {
|
||||||
lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
// Normally I'd just parse something this simple by hand to avoid the
|
// Normally I'd just parse something this simple by hand to avoid the
|
||||||
// regex dep, but we bring regex in any way for glob matching, so might
|
// regex dep, but we bring regex in any way for glob matching, so might
|
||||||
// as well use it.
|
// as well use it.
|
||||||
|
|||||||
@@ -158,19 +158,6 @@ error message is crafted that typically tells the user how to fix the problem.
|
|||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
extern crate atty;
|
|
||||||
extern crate bstr;
|
|
||||||
extern crate globset;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate lazy_static;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
|
||||||
extern crate regex;
|
|
||||||
extern crate same_file;
|
|
||||||
extern crate termcolor;
|
|
||||||
#[cfg(windows)]
|
|
||||||
extern crate winapi_util;
|
|
||||||
|
|
||||||
mod decompress;
|
mod decompress;
|
||||||
mod escape;
|
mod escape;
|
||||||
mod human;
|
mod human;
|
||||||
@@ -178,18 +165,18 @@ mod pattern;
|
|||||||
mod process;
|
mod process;
|
||||||
mod wtr;
|
mod wtr;
|
||||||
|
|
||||||
pub use decompress::{
|
pub use crate::decompress::{
|
||||||
DecompressionMatcher, DecompressionMatcherBuilder, DecompressionReader,
|
resolve_binary, DecompressionMatcher, DecompressionMatcherBuilder,
|
||||||
DecompressionReaderBuilder,
|
DecompressionReader, DecompressionReaderBuilder,
|
||||||
};
|
};
|
||||||
pub use escape::{escape, escape_os, unescape, unescape_os};
|
pub use crate::escape::{escape, escape_os, unescape, unescape_os};
|
||||||
pub use human::{parse_human_readable_size, ParseSizeError};
|
pub use crate::human::{parse_human_readable_size, ParseSizeError};
|
||||||
pub use pattern::{
|
pub use crate::pattern::{
|
||||||
pattern_from_bytes, pattern_from_os, patterns_from_path,
|
pattern_from_bytes, pattern_from_os, patterns_from_path,
|
||||||
patterns_from_reader, patterns_from_stdin, InvalidPatternError,
|
patterns_from_reader, patterns_from_stdin, InvalidPatternError,
|
||||||
};
|
};
|
||||||
pub use process::{CommandError, CommandReader, CommandReaderBuilder};
|
pub use crate::process::{CommandError, CommandReader, CommandReaderBuilder};
|
||||||
pub use wtr::{
|
pub use crate::wtr::{
|
||||||
stdout, stdout_buffered_block, stdout_buffered_line, StandardStream,
|
stdout, stdout_buffered_block, stdout_buffered_line, StandardStream,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -210,7 +197,7 @@ pub fn is_readable_stdin() -> bool {
|
|||||||
Err(_) => return false,
|
Err(_) => return false,
|
||||||
Ok(md) => md.file_type(),
|
Ok(md) => md.file_type(),
|
||||||
};
|
};
|
||||||
ft.is_file() || ft.is_fifo()
|
ft.is_file() || ft.is_fifo() || ft.is_socket()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@@ -225,13 +212,13 @@ pub fn is_readable_stdin() -> bool {
|
|||||||
!is_tty_stdin() && imp()
|
!is_tty_stdin() && imp()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if and only if stdin is believed to be connectted to a tty
|
/// Returns true if and only if stdin is believed to be connected to a tty
|
||||||
/// or a console.
|
/// or a console.
|
||||||
pub fn is_tty_stdin() -> bool {
|
pub fn is_tty_stdin() -> bool {
|
||||||
atty::is(atty::Stream::Stdin)
|
atty::is(atty::Stream::Stdin)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if and only if stdout is believed to be connectted to a tty
|
/// Returns true if and only if stdout is believed to be connected to a tty
|
||||||
/// or a console.
|
/// or a console.
|
||||||
///
|
///
|
||||||
/// This is useful for when you want your command line program to produce
|
/// This is useful for when you want your command line program to produce
|
||||||
@@ -243,7 +230,7 @@ pub fn is_tty_stdout() -> bool {
|
|||||||
atty::is(atty::Stream::Stdout)
|
atty::is(atty::Stream::Stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if and only if stderr is believed to be connectted to a tty
|
/// Returns true if and only if stderr is believed to be connected to a tty
|
||||||
/// or a console.
|
/// or a console.
|
||||||
pub fn is_tty_stderr() -> bool {
|
pub fn is_tty_stderr() -> bool {
|
||||||
atty::is(atty::Stream::Stderr)
|
atty::is(atty::Stream::Stderr)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::str;
|
|||||||
|
|
||||||
use bstr::io::BufReadExt;
|
use bstr::io::BufReadExt;
|
||||||
|
|
||||||
use escape::{escape, escape_os};
|
use crate::escape::{escape, escape_os};
|
||||||
|
|
||||||
/// An error that occurs when a pattern could not be converted to valid UTF-8.
|
/// An error that occurs when a pattern could not be converted to valid UTF-8.
|
||||||
///
|
///
|
||||||
@@ -35,12 +35,12 @@ impl error::Error for InvalidPatternError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for InvalidPatternError {
|
impl fmt::Display for InvalidPatternError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"found invalid UTF-8 in pattern at byte offset {} \
|
"found invalid UTF-8 in pattern at byte offset {}: {} \
|
||||||
(use hex escape sequences to match arbitrary bytes \
|
(disable Unicode mode and use hex escape sequences to match \
|
||||||
in a pattern, e.g., \\xFF): '{}'",
|
arbitrary bytes in a pattern, e.g., '(?-u)\\xFF')",
|
||||||
self.valid_up_to, self.original,
|
self.valid_up_to, self.original,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -64,10 +64,7 @@ pub fn pattern_from_os(pattern: &OsStr) -> Result<&str, InvalidPatternError> {
|
|||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.find('\u{FFFD}')
|
.find('\u{FFFD}')
|
||||||
.expect("a Unicode replacement codepoint for invalid UTF-8");
|
.expect("a Unicode replacement codepoint for invalid UTF-8");
|
||||||
InvalidPatternError {
|
InvalidPatternError { original: escape_os(pattern), valid_up_to }
|
||||||
original: escape_os(pattern),
|
|
||||||
valid_up_to: valid_up_to,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,14 @@ impl CommandError {
|
|||||||
pub(crate) fn stderr(bytes: Vec<u8>) -> CommandError {
|
pub(crate) fn stderr(bytes: Vec<u8>) -> CommandError {
|
||||||
CommandError { kind: CommandErrorKind::Stderr(bytes) }
|
CommandError { kind: CommandErrorKind::Stderr(bytes) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if and only if this error has empty data from stderr.
|
||||||
|
pub(crate) fn is_empty(&self) -> bool {
|
||||||
|
match self.kind {
|
||||||
|
CommandErrorKind::Stderr(ref bytes) => bytes.is_empty(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for CommandError {
|
impl error::Error for CommandError {
|
||||||
@@ -39,7 +47,7 @@ impl error::Error for CommandError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for CommandError {
|
impl fmt::Display for CommandError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
CommandErrorKind::Io(ref e) => e.fmt(f),
|
CommandErrorKind::Io(ref e) => e.fmt(f),
|
||||||
CommandErrorKind::Stderr(ref bytes) => {
|
CommandErrorKind::Stderr(ref bytes) => {
|
||||||
@@ -107,18 +115,12 @@ impl CommandReaderBuilder {
|
|||||||
.stdout(process::Stdio::piped())
|
.stdout(process::Stdio::piped())
|
||||||
.stderr(process::Stdio::piped())
|
.stderr(process::Stdio::piped())
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
let stdout = child.stdout.take().unwrap();
|
|
||||||
let stderr = if self.async_stderr {
|
let stderr = if self.async_stderr {
|
||||||
StderrReader::async(child.stderr.take().unwrap())
|
StderrReader::r#async(child.stderr.take().unwrap())
|
||||||
} else {
|
} else {
|
||||||
StderrReader::sync(child.stderr.take().unwrap())
|
StderrReader::sync(child.stderr.take().unwrap())
|
||||||
};
|
};
|
||||||
Ok(CommandReader {
|
Ok(CommandReader { child, stderr, eof: false })
|
||||||
child: child,
|
|
||||||
stdout: stdout,
|
|
||||||
stderr: stderr,
|
|
||||||
done: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When enabled, the reader will asynchronously read the contents of the
|
/// When enabled, the reader will asynchronously read the contents of the
|
||||||
@@ -175,9 +177,11 @@ impl CommandReaderBuilder {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CommandReader {
|
pub struct CommandReader {
|
||||||
child: process::Child,
|
child: process::Child,
|
||||||
stdout: process::ChildStdout,
|
|
||||||
stderr: StderrReader,
|
stderr: StderrReader,
|
||||||
done: bool,
|
/// This is set to true once 'read' returns zero bytes. When this isn't
|
||||||
|
/// set and we close the reader, then we anticipate a pipe error when
|
||||||
|
/// reaping the child process and silence it.
|
||||||
|
eof: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandReader {
|
impl CommandReader {
|
||||||
@@ -201,24 +205,74 @@ impl CommandReader {
|
|||||||
) -> Result<CommandReader, CommandError> {
|
) -> Result<CommandReader, CommandError> {
|
||||||
CommandReaderBuilder::new().build(cmd)
|
CommandReaderBuilder::new().build(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Closes the CommandReader, freeing any resources used by its underlying
|
||||||
|
/// child process. If the child process exits with a nonzero exit code, the
|
||||||
|
/// returned Err value will include its stderr.
|
||||||
|
///
|
||||||
|
/// `close` is idempotent, meaning it can be safely called multiple times.
|
||||||
|
/// The first call closes the CommandReader and any subsequent calls do
|
||||||
|
/// nothing.
|
||||||
|
///
|
||||||
|
/// This method should be called after partially reading a file to prevent
|
||||||
|
/// resource leakage. However there is no need to call `close` explicitly
|
||||||
|
/// if your code always calls `read` to EOF, as `read` takes care of
|
||||||
|
/// calling `close` in this case.
|
||||||
|
///
|
||||||
|
/// `close` is also called in `drop` as a last line of defense against
|
||||||
|
/// resource leakage. Any error from the child process is then printed as a
|
||||||
|
/// warning to stderr. This can be avoided by explicitly calling `close`
|
||||||
|
/// before the CommandReader is dropped.
|
||||||
|
pub fn close(&mut self) -> io::Result<()> {
|
||||||
|
// Dropping stdout closes the underlying file descriptor, which should
|
||||||
|
// cause a well-behaved child process to exit. If child.stdout is None
|
||||||
|
// we assume that close() has already been called and do nothing.
|
||||||
|
let stdout = match self.child.stdout.take() {
|
||||||
|
None => return Ok(()),
|
||||||
|
Some(stdout) => stdout,
|
||||||
|
};
|
||||||
|
drop(stdout);
|
||||||
|
if self.child.wait()?.success() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let err = self.stderr.read_to_end();
|
||||||
|
// In the specific case where we haven't consumed the full data
|
||||||
|
// from the child process, then closing stdout above results in
|
||||||
|
// a pipe signal being thrown in most cases. But I don't think
|
||||||
|
// there is any reliable and portable way of detecting it. Instead,
|
||||||
|
// if we know we haven't hit EOF (so we anticipate a broken pipe
|
||||||
|
// error) and if stderr otherwise doesn't have anything on it, then
|
||||||
|
// we assume total success.
|
||||||
|
if !self.eof && err.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Err(io::Error::from(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for CommandReader {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Err(error) = self.close() {
|
||||||
|
log::warn!("{}", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl io::Read for CommandReader {
|
impl io::Read for CommandReader {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
if self.done {
|
let stdout = match self.child.stdout {
|
||||||
return Ok(0);
|
None => return Ok(0),
|
||||||
}
|
Some(ref mut stdout) => stdout,
|
||||||
let nread = self.stdout.read(buf)?;
|
};
|
||||||
|
let nread = stdout.read(buf)?;
|
||||||
if nread == 0 {
|
if nread == 0 {
|
||||||
self.done = true;
|
self.eof = true;
|
||||||
// Reap the child now that we're done reading. If the command
|
self.close().map(|_| 0)
|
||||||
// failed, report stderr as an error.
|
} else {
|
||||||
if !self.child.wait()?.success() {
|
|
||||||
return Err(io::Error::from(self.stderr.read_to_end()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(nread)
|
Ok(nread)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A reader that encapsulates the asynchronous or synchronous reading of
|
/// A reader that encapsulates the asynchronous or synchronous reading of
|
||||||
@@ -231,7 +285,7 @@ enum StderrReader {
|
|||||||
|
|
||||||
impl StderrReader {
|
impl StderrReader {
|
||||||
/// Create a reader for stderr that reads contents asynchronously.
|
/// Create a reader for stderr that reads contents asynchronously.
|
||||||
fn async(mut stderr: process::ChildStderr) -> StderrReader {
|
fn r#async(mut stderr: process::ChildStderr) -> StderrReader {
|
||||||
let handle =
|
let handle =
|
||||||
thread::spawn(move || stderr_to_command_error(&mut stderr));
|
thread::spawn(move || stderr_to_command_error(&mut stderr));
|
||||||
StderrReader::Async(Some(handle))
|
StderrReader::Async(Some(handle))
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::io;
|
|||||||
|
|
||||||
use termcolor;
|
use termcolor;
|
||||||
|
|
||||||
use is_tty_stdout;
|
use crate::is_tty_stdout;
|
||||||
|
|
||||||
/// A writer that supports coloring with either line or block buffering.
|
/// A writer that supports coloring with either line or block buffering.
|
||||||
pub struct StandardStream(StandardStreamKind);
|
pub struct StandardStream(StandardStreamKind);
|
||||||
|
|||||||
@@ -13,38 +13,24 @@ use clap::{self, crate_authors, crate_version, App, AppSettings};
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
const ABOUT: &str = "
|
const ABOUT: &str = "
|
||||||
ripgrep (rg) recursively searches your current directory for a regex pattern.
|
ripgrep (rg) recursively searches the current directory for a regex pattern.
|
||||||
By default, ripgrep will respect your .gitignore and automatically skip hidden
|
By default, ripgrep will respect gitignore rules and automatically skip hidden
|
||||||
files/directories and binary files.
|
files/directories and binary files.
|
||||||
|
|
||||||
ripgrep's default regex engine uses finite automata and guarantees linear
|
Use -h for short descriptions and --help for more details.
|
||||||
time searching. Because of this, features like backreferences and arbitrary
|
|
||||||
look-around are not supported. However, if ripgrep is built with PCRE2, then
|
|
||||||
the --pcre2 flag can be used to enable backreferences and look-around.
|
|
||||||
|
|
||||||
ripgrep supports configuration files. Set RIPGREP_CONFIG_PATH to a
|
|
||||||
configuration file. The file can specify one shell argument per line. Lines
|
|
||||||
starting with '#' are ignored. For more details, see the man page or the
|
|
||||||
README.
|
|
||||||
|
|
||||||
ripgrep will automatically detect if stdin exists and search stdin for a regex
|
|
||||||
pattern, e.g. 'ls | rg foo'. In some environments, stdin may exist when it
|
|
||||||
shouldn't. To turn off stdin detection explicitly specify the directory to
|
|
||||||
search, e.g. 'rg foo ./'.
|
|
||||||
|
|
||||||
Tip: to disable all smart filtering and make ripgrep behave a bit more like
|
|
||||||
classical grep, use 'rg -uuu'.
|
|
||||||
|
|
||||||
Project home page: https://github.com/BurntSushi/ripgrep
|
Project home page: https://github.com/BurntSushi/ripgrep
|
||||||
|
";
|
||||||
Use -h for short descriptions and --help for more details.";
|
|
||||||
|
|
||||||
const USAGE: &str = "
|
const USAGE: &str = "
|
||||||
rg [OPTIONS] PATTERN [PATH ...]
|
rg [OPTIONS] PATTERN [PATH ...]
|
||||||
rg [OPTIONS] [-e PATTERN ...] [-f PATTERNFILE ...] [PATH ...]
|
rg [OPTIONS] -e PATTERN ... [PATH ...]
|
||||||
|
rg [OPTIONS] -f PATTERNFILE ... [PATH ...]
|
||||||
rg [OPTIONS] --files [PATH ...]
|
rg [OPTIONS] --files [PATH ...]
|
||||||
rg [OPTIONS] --type-list
|
rg [OPTIONS] --type-list
|
||||||
command | rg [OPTIONS] PATTERN";
|
command | rg [OPTIONS] PATTERN
|
||||||
|
rg [OPTIONS] --help
|
||||||
|
rg [OPTIONS] --version";
|
||||||
|
|
||||||
const TEMPLATE: &str = "\
|
const TEMPLATE: &str = "\
|
||||||
{bin} {version}
|
{bin} {version}
|
||||||
@@ -478,7 +464,7 @@ impl RGArg {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Permit this flag to have values that begin with a hypen.
|
/// Permit this flag to have values that begin with a hyphen.
|
||||||
///
|
///
|
||||||
/// This panics if this arg is not a flag.
|
/// This panics if this arg is not a flag.
|
||||||
fn allow_leading_hyphen(mut self) -> RGArg {
|
fn allow_leading_hyphen(mut self) -> RGArg {
|
||||||
@@ -582,6 +568,8 @@ pub fn all_args_and_flags() -> Vec<RGArg> {
|
|||||||
flag_dfa_size_limit(&mut args);
|
flag_dfa_size_limit(&mut args);
|
||||||
flag_encoding(&mut args);
|
flag_encoding(&mut args);
|
||||||
flag_engine(&mut args);
|
flag_engine(&mut args);
|
||||||
|
flag_field_context_separator(&mut args);
|
||||||
|
flag_field_match_separator(&mut args);
|
||||||
flag_file(&mut args);
|
flag_file(&mut args);
|
||||||
flag_files(&mut args);
|
flag_files(&mut args);
|
||||||
flag_files_with_matches(&mut args);
|
flag_files_with_matches(&mut args);
|
||||||
@@ -693,8 +681,8 @@ fn arg_path(args: &mut Vec<RGArg>) {
|
|||||||
const SHORT: &str = "A file or directory to search.";
|
const SHORT: &str = "A file or directory to search.";
|
||||||
const LONG: &str = long!(
|
const LONG: &str = long!(
|
||||||
"\
|
"\
|
||||||
A file or directory to search. Directories are searched recursively. Paths \
|
A file or directory to search. Directories are searched recursively. File \
|
||||||
specified on the command line override glob and ignore rules. \
|
paths specified on the command line override glob and ignore rules. \
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
let arg = RGArg::positional("path", "PATH")
|
let arg = RGArg::positional("path", "PATH")
|
||||||
@@ -710,7 +698,7 @@ fn flag_after_context(args: &mut Vec<RGArg>) {
|
|||||||
"\
|
"\
|
||||||
Show NUM lines after each match.
|
Show NUM lines after each match.
|
||||||
|
|
||||||
This overrides the --context flag.
|
This overrides the --context and --passthru flags.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
let arg = RGArg::flag("after-context", "NUM")
|
let arg = RGArg::flag("after-context", "NUM")
|
||||||
@@ -718,6 +706,7 @@ This overrides the --context flag.
|
|||||||
.help(SHORT)
|
.help(SHORT)
|
||||||
.long_help(LONG)
|
.long_help(LONG)
|
||||||
.number()
|
.number()
|
||||||
|
.overrides("passthru")
|
||||||
.overrides("context");
|
.overrides("context");
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
@@ -779,7 +768,7 @@ fn flag_before_context(args: &mut Vec<RGArg>) {
|
|||||||
"\
|
"\
|
||||||
Show NUM lines before each match.
|
Show NUM lines before each match.
|
||||||
|
|
||||||
This overrides the --context flag.
|
This overrides the --context and --passthru flags.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
let arg = RGArg::flag("before-context", "NUM")
|
let arg = RGArg::flag("before-context", "NUM")
|
||||||
@@ -787,6 +776,7 @@ This overrides the --context flag.
|
|||||||
.help(SHORT)
|
.help(SHORT)
|
||||||
.long_help(LONG)
|
.long_help(LONG)
|
||||||
.number()
|
.number()
|
||||||
|
.overrides("passthru")
|
||||||
.overrides("context");
|
.overrides("context");
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
@@ -885,8 +875,8 @@ Print the 0-based byte offset within the input file before each line of output.
|
|||||||
If -o (--only-matching) is specified, print the offset of the matching part
|
If -o (--only-matching) is specified, print the offset of the matching part
|
||||||
itself.
|
itself.
|
||||||
|
|
||||||
If ripgrep does transcoding, then the byte offset is in terms of the the result
|
If ripgrep does transcoding, then the byte offset is in terms of the result of
|
||||||
of transcoding and not the original data. This applies similarly to another
|
transcoding and not the original data. This applies similarly to another
|
||||||
transformation on the source, such as decompression or a --pre filter. Note
|
transformation on the source, such as decompression or a --pre filter. Note
|
||||||
that when the PCRE2 regex engine is used, then UTF-8 transcoding is done by
|
that when the PCRE2 regex engine is used, then UTF-8 transcoding is done by
|
||||||
default.
|
default.
|
||||||
@@ -980,7 +970,7 @@ or, equivalently,
|
|||||||
|
|
||||||
rg --colors 'match:bg:0x0,0x80,0xFF'
|
rg --colors 'match:bg:0x0,0x80,0xFF'
|
||||||
|
|
||||||
Note that the the intense and nointense style flags will have no effect when
|
Note that the intense and nointense style flags will have no effect when
|
||||||
used alongside these extended color codes.
|
used alongside these extended color codes.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
@@ -1019,7 +1009,8 @@ fn flag_context(args: &mut Vec<RGArg>) {
|
|||||||
Show NUM lines before and after each match. This is equivalent to providing
|
Show NUM lines before and after each match. This is equivalent to providing
|
||||||
both the -B/--before-context and -A/--after-context flags with the same value.
|
both the -B/--before-context and -A/--after-context flags with the same value.
|
||||||
|
|
||||||
This overrides both the -B/--before-context and -A/--after-context flags.
|
This overrides both the -B/--before-context and -A/--after-context flags,
|
||||||
|
in addition to the --passthru flag.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
let arg = RGArg::flag("context", "NUM")
|
let arg = RGArg::flag("context", "NUM")
|
||||||
@@ -1027,6 +1018,7 @@ This overrides both the -B/--before-context and -A/--after-context flags.
|
|||||||
.help(SHORT)
|
.help(SHORT)
|
||||||
.long_help(LONG)
|
.long_help(LONG)
|
||||||
.number()
|
.number()
|
||||||
|
.overrides("passthru")
|
||||||
.overrides("before-context")
|
.overrides("before-context")
|
||||||
.overrides("after-context");
|
.overrides("after-context");
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
@@ -1065,11 +1057,13 @@ fn flag_count(args: &mut Vec<RGArg>) {
|
|||||||
This flag suppresses normal output and shows the number of lines that match
|
This flag suppresses normal output and shows the number of lines that match
|
||||||
the given patterns for each file searched. Each file containing a match has its
|
the given patterns for each file searched. Each file containing a match has its
|
||||||
path and count printed on each line. Note that this reports the number of lines
|
path and count printed on each line. Note that this reports the number of lines
|
||||||
that match and not the total number of matches.
|
that match and not the total number of matches, unless -U/--multiline is
|
||||||
|
enabled. In multiline mode, --count is equivalent to --count-matches.
|
||||||
|
|
||||||
If only one file is given to ripgrep, then only the count is printed if there
|
If only one file is given to ripgrep, then only the count is printed if there
|
||||||
is a match. The --with-filename flag can be used to force printing the file
|
is a match. The --with-filename flag can be used to force printing the file
|
||||||
path in this case.
|
path in this case. If you need a count to be printed regardless of whether
|
||||||
|
there is a match, then use --include-zero.
|
||||||
|
|
||||||
This overrides the --count-matches flag. Note that when --count is combined
|
This overrides the --count-matches flag. Note that when --count is combined
|
||||||
with --only-matching, then ripgrep behaves as if --count-matches was given.
|
with --only-matching, then ripgrep behaves as if --count-matches was given.
|
||||||
@@ -1223,7 +1217,7 @@ between supported regex engines depending on the features used in a pattern on
|
|||||||
a best effort basis.
|
a best effort basis.
|
||||||
|
|
||||||
Note that the 'pcre2' engine is an optional ripgrep feature. If PCRE2 wasn't
|
Note that the 'pcre2' engine is an optional ripgrep feature. If PCRE2 wasn't
|
||||||
including in your build of ripgrep, then using this flag will result in ripgrep
|
included in your build of ripgrep, then using this flag will result in ripgrep
|
||||||
printing an error message and exiting.
|
printing an error message and exiting.
|
||||||
|
|
||||||
This overrides previous uses of --pcre2 and --auto-hybrid-regex flags.
|
This overrides previous uses of --pcre2 and --auto-hybrid-regex flags.
|
||||||
@@ -1241,6 +1235,38 @@ This overrides previous uses of --pcre2 and --auto-hybrid-regex flags.
|
|||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flag_field_context_separator(args: &mut Vec<RGArg>) {
|
||||||
|
const SHORT: &str = "Set the field context separator.";
|
||||||
|
const LONG: &str = long!(
|
||||||
|
"\
|
||||||
|
Set the field context separator, which is used to delimit file paths, line
|
||||||
|
numbers, columns and the context itself, when printing contextual lines. The
|
||||||
|
separator may be any number of bytes, including zero. Escape sequences like
|
||||||
|
\\x7F or \\t may be used. The '-' character is the default value.
|
||||||
|
"
|
||||||
|
);
|
||||||
|
let arg = RGArg::flag("field-context-separator", "SEPARATOR")
|
||||||
|
.help(SHORT)
|
||||||
|
.long_help(LONG);
|
||||||
|
args.push(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flag_field_match_separator(args: &mut Vec<RGArg>) {
|
||||||
|
const SHORT: &str = "Set the match separator.";
|
||||||
|
const LONG: &str = long!(
|
||||||
|
"\
|
||||||
|
Set the field match separator, which is used to delimit file paths, line
|
||||||
|
numbers, columns and the match itself. The separator may be any number of
|
||||||
|
bytes, including zero. Escape sequences like \\x7F or \\t may be used. The ':'
|
||||||
|
character is the default value.
|
||||||
|
"
|
||||||
|
);
|
||||||
|
let arg = RGArg::flag("field-match-separator", "SEPARATOR")
|
||||||
|
.help(SHORT)
|
||||||
|
.long_help(LONG);
|
||||||
|
args.push(arg);
|
||||||
|
}
|
||||||
|
|
||||||
fn flag_file(args: &mut Vec<RGArg>) {
|
fn flag_file(args: &mut Vec<RGArg>) {
|
||||||
const SHORT: &str = "Search for patterns from the given file.";
|
const SHORT: &str = "Search for patterns from the given file.";
|
||||||
const LONG: &str = long!(
|
const LONG: &str = long!(
|
||||||
@@ -1280,10 +1306,10 @@ This is useful to determine whether a particular file is being searched or not.
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn flag_files_with_matches(args: &mut Vec<RGArg>) {
|
fn flag_files_with_matches(args: &mut Vec<RGArg>) {
|
||||||
const SHORT: &str = "Only print the paths with at least one match.";
|
const SHORT: &str = "Print the paths with at least one match.";
|
||||||
const LONG: &str = long!(
|
const LONG: &str = long!(
|
||||||
"\
|
"\
|
||||||
Only print the paths with at least one match.
|
Print the paths with at least one match and suppress match contents.
|
||||||
|
|
||||||
This overrides --files-without-match.
|
This overrides --files-without-match.
|
||||||
"
|
"
|
||||||
@@ -1297,11 +1323,11 @@ This overrides --files-without-match.
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn flag_files_without_match(args: &mut Vec<RGArg>) {
|
fn flag_files_without_match(args: &mut Vec<RGArg>) {
|
||||||
const SHORT: &str = "Only print the paths that contain zero matches.";
|
const SHORT: &str = "Print the paths that contain zero matches.";
|
||||||
const LONG: &str = long!(
|
const LONG: &str = long!(
|
||||||
"\
|
"\
|
||||||
Only print the paths that contain zero matches. This inverts/negates the
|
Print the paths that contain zero matches and suppress match contents. This
|
||||||
--files-with-matches flag.
|
inverts/negates the --files-with-matches flag.
|
||||||
|
|
||||||
This overrides --files-with-matches.
|
This overrides --files-with-matches.
|
||||||
"
|
"
|
||||||
@@ -1368,10 +1394,17 @@ used. Globbing rules match .gitignore globs. Precede a glob with a ! to exclude
|
|||||||
it. If multiple globs match a file or directory, the glob given later in the
|
it. If multiple globs match a file or directory, the glob given later in the
|
||||||
command line takes precedence.
|
command line takes precedence.
|
||||||
|
|
||||||
|
As an extension, globs support specifying alternatives: *-g ab{c,d}* is
|
||||||
|
equivalent to *-g abc -g abd*. Empty alternatives like *-g ab{,c}* are not
|
||||||
|
currently supported. Note that this syntax extension is also currently enabled
|
||||||
|
in gitignore files, even though this syntax isn't supported by git itself.
|
||||||
|
ripgrep may disable this syntax extension in gitignore files, but it will
|
||||||
|
always remain available via the -g/--glob flag.
|
||||||
|
|
||||||
When this flag is set, every file and directory is applied to it to test for
|
When this flag is set, every file and directory is applied to it to test for
|
||||||
a match. So for example, if you only want to search in a particular directory
|
a match. So for example, if you only want to search in a particular directory
|
||||||
'foo', then *-g foo* is incorrect because 'foo/bar' does not match the glob
|
'foo', then *-g foo* is incorrect because 'foo/bar' does not match the glob
|
||||||
'foo'. Instead, you should use *-g +++'foo/**'+++*.
|
'foo'. Instead, you should use *-g 'foo/**'*.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
let arg = RGArg::flag("glob", "GLOB")
|
let arg = RGArg::flag("glob", "GLOB")
|
||||||
@@ -1447,10 +1480,15 @@ Search hidden files and directories. By default, hidden files and directories
|
|||||||
are skipped. Note that if a hidden file or a directory is whitelisted in an
|
are skipped. Note that if a hidden file or a directory is whitelisted in an
|
||||||
ignore file, then it will be searched even if this flag isn't provided.
|
ignore file, then it will be searched even if this flag isn't provided.
|
||||||
|
|
||||||
|
A file or directory is considered hidden if its base name starts with a dot
|
||||||
|
character ('.'). On operating systems which support a `hidden` file attribute,
|
||||||
|
like Windows, files with this attribute are also considered hidden.
|
||||||
|
|
||||||
This flag can be disabled with --no-hidden.
|
This flag can be disabled with --no-hidden.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
let arg = RGArg::switch("hidden")
|
let arg = RGArg::switch("hidden")
|
||||||
|
.short(".")
|
||||||
.help(SHORT)
|
.help(SHORT)
|
||||||
.long_help(LONG)
|
.long_help(LONG)
|
||||||
.overrides("no-hidden");
|
.overrides("no-hidden");
|
||||||
@@ -1510,7 +1548,7 @@ When specifying multiple ignore files, earlier files have lower precedence
|
|||||||
than later files.
|
than later files.
|
||||||
|
|
||||||
If you are looking for a way to include or exclude files and directories
|
If you are looking for a way to include or exclude files and directories
|
||||||
directly on the command line, then used -g instead.
|
directly on the command line, then use -g instead.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
let arg = RGArg::flag("ignore-file", "PATH")
|
let arg = RGArg::flag("ignore-file", "PATH")
|
||||||
@@ -1962,6 +2000,10 @@ Don't respect ignore files (.gitignore, .ignore, etc.). This implies
|
|||||||
This does *not* imply --no-ignore-files, since --ignore-file is specified
|
This does *not* imply --no-ignore-files, since --ignore-file is specified
|
||||||
explicitly as a command line argument.
|
explicitly as a command line argument.
|
||||||
|
|
||||||
|
When given only once, the -u flag is identical in behavior to --no-ignore and
|
||||||
|
can be considered an alias. However, subsequent -u flags have additional
|
||||||
|
effects; see --unrestricted.
|
||||||
|
|
||||||
This flag can be disabled with the --ignore flag.
|
This flag can be disabled with the --ignore flag.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
@@ -1981,6 +2023,9 @@ fn flag_no_ignore_dot(args: &mut Vec<RGArg>) {
|
|||||||
"\
|
"\
|
||||||
Don't respect .ignore files.
|
Don't respect .ignore files.
|
||||||
|
|
||||||
|
This does *not* affect whether ripgrep will ignore files and directories
|
||||||
|
whose names begin with a dot. For that, see the -./--hidden flag.
|
||||||
|
|
||||||
This flag can be disabled with the --ignore-dot flag.
|
This flag can be disabled with the --ignore-dot flag.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
@@ -2313,7 +2358,7 @@ This flag can be disabled with --no-one-file-system.
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn flag_only_matching(args: &mut Vec<RGArg>) {
|
fn flag_only_matching(args: &mut Vec<RGArg>) {
|
||||||
const SHORT: &str = "Print only matches parts of a line.";
|
const SHORT: &str = "Print only matched parts of a line.";
|
||||||
const LONG: &str = long!(
|
const LONG: &str = long!(
|
||||||
"\
|
"\
|
||||||
Print only the matched (non-empty) parts of a matching line, with each such
|
Print only the matched (non-empty) parts of a matching line, with each such
|
||||||
@@ -2351,12 +2396,17 @@ the empty string. For example, if you are searching using 'rg foo' then using
|
|||||||
'rg \"^|foo\"' instead will emit every line in every file searched, but only
|
'rg \"^|foo\"' instead will emit every line in every file searched, but only
|
||||||
occurrences of 'foo' will be highlighted. This flag enables the same behavior
|
occurrences of 'foo' will be highlighted. This flag enables the same behavior
|
||||||
without needing to modify the pattern.
|
without needing to modify the pattern.
|
||||||
|
|
||||||
|
This overrides the --context, --after-context and --before-context flags.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
let arg = RGArg::switch("passthru")
|
let arg = RGArg::switch("passthru")
|
||||||
.help(SHORT)
|
.help(SHORT)
|
||||||
.long_help(LONG)
|
.long_help(LONG)
|
||||||
.alias("passthrough");
|
.alias("passthrough")
|
||||||
|
.overrides("after-context")
|
||||||
|
.overrides("before-context")
|
||||||
|
.overrides("context");
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2374,7 +2424,7 @@ Note that PCRE2 is an optional ripgrep feature. If PCRE2 wasn't included in
|
|||||||
your build of ripgrep, then using this flag will result in ripgrep printing
|
your build of ripgrep, then using this flag will result in ripgrep printing
|
||||||
an error message and exiting. PCRE2 may also have worse user experience in
|
an error message and exiting. PCRE2 may also have worse user experience in
|
||||||
some cases, since it has fewer introspection APIs than ripgrep's default regex
|
some cases, since it has fewer introspection APIs than ripgrep's default regex
|
||||||
engine. For example, if you use a '\n' in a PCRE2 regex without the
|
engine. For example, if you use a '\\n' in a PCRE2 regex without the
|
||||||
'-U/--multiline' flag, then ripgrep will silently fail to match anything
|
'-U/--multiline' flag, then ripgrep will silently fail to match anything
|
||||||
instead of reporting an error immediately (like it does with the default
|
instead of reporting an error immediately (like it does with the default
|
||||||
regex engine).
|
regex engine).
|
||||||
@@ -2593,10 +2643,15 @@ Replace every match with the text given when printing results. Neither this
|
|||||||
flag nor any other ripgrep flag will modify your files.
|
flag nor any other ripgrep flag will modify your files.
|
||||||
|
|
||||||
Capture group indices (e.g., $5) and names (e.g., $foo) are supported in the
|
Capture group indices (e.g., $5) and names (e.g., $foo) are supported in the
|
||||||
replacement string. In shells such as Bash and zsh, you should wrap the
|
replacement string. Capture group indices are numbered based on the position of
|
||||||
pattern in single quotes instead of double quotes. Otherwise, capture group
|
the opening parenthesis of the group, where the leftmost such group is $1. The
|
||||||
indices will be replaced by expanded shell variables which will most likely
|
special $0 group corresponds to the entire match.
|
||||||
be empty.
|
|
||||||
|
In shells such as Bash and zsh, you should wrap the pattern in single quotes
|
||||||
|
instead of double quotes. Otherwise, capture group indices will be replaced by
|
||||||
|
expanded shell variables which will most likely be empty.
|
||||||
|
|
||||||
|
To write a literal '$', use '$$'.
|
||||||
|
|
||||||
Note that the replacement by default replaces each match, and NOT the entire
|
Note that the replacement by default replaces each match, and NOT the entire
|
||||||
line. To replace the entire line, you should match the entire line.
|
line. To replace the entire line, you should match the entire line.
|
||||||
@@ -2642,6 +2697,15 @@ fn flag_smart_case(args: &mut Vec<RGArg>) {
|
|||||||
Searches case insensitively if the pattern is all lowercase. Search case
|
Searches case insensitively if the pattern is all lowercase. Search case
|
||||||
sensitively otherwise.
|
sensitively otherwise.
|
||||||
|
|
||||||
|
A pattern is considered all lowercase if both of the following rules hold:
|
||||||
|
|
||||||
|
First, the pattern contains at least one literal character. For example, 'a\\w'
|
||||||
|
contains a literal ('a') but just '\\w' does not.
|
||||||
|
|
||||||
|
Second, of the literals in the pattern, none of them are considered to be
|
||||||
|
uppercase according to Unicode. For example, 'foo\\pL' has no uppercase
|
||||||
|
literals but 'Foo\\pL' does.
|
||||||
|
|
||||||
This overrides the -s/--case-sensitive and -i/--ignore-case flags.
|
This overrides the -s/--case-sensitive and -i/--ignore-case flags.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
@@ -2877,7 +2941,7 @@ time. Multiple --type-add flags can be provided. Unless --type-clear is used,
|
|||||||
globs are added to any existing globs defined inside of ripgrep.
|
globs are added to any existing globs defined inside of ripgrep.
|
||||||
|
|
||||||
Note that this MUST be passed to every invocation of ripgrep. Type settings are
|
Note that this MUST be passed to every invocation of ripgrep. Type settings are
|
||||||
NOT persisted.
|
NOT persisted. See CONFIGURATION FILES for a workaround.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@@ -2915,7 +2979,7 @@ Clear the file type globs previously defined for TYPE. This only clears the
|
|||||||
default type definitions that are found inside of ripgrep.
|
default type definitions that are found inside of ripgrep.
|
||||||
|
|
||||||
Note that this MUST be passed to every invocation of ripgrep. Type settings are
|
Note that this MUST be passed to every invocation of ripgrep. Type settings are
|
||||||
NOT persisted.
|
NOT persisted. See CONFIGURATION FILES for a workaround.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
let arg = RGArg::flag("type-clear", "TYPE")
|
let arg = RGArg::flag("type-clear", "TYPE")
|
||||||
@@ -2962,8 +3026,9 @@ fn flag_unrestricted(args: &mut Vec<RGArg>) {
|
|||||||
const LONG: &str = long!(
|
const LONG: &str = long!(
|
||||||
"\
|
"\
|
||||||
Reduce the level of \"smart\" searching. A single -u won't respect .gitignore
|
Reduce the level of \"smart\" searching. A single -u won't respect .gitignore
|
||||||
(etc.) files. Two -u flags will additionally search hidden files and
|
(etc.) files (--no-ignore). Two -u flags will additionally search hidden files
|
||||||
directories. Three -u flags will additionally search binary files.
|
and directories (-./--hidden). Three -u flags will additionally search binary
|
||||||
|
files (--binary).
|
||||||
|
|
||||||
'rg -uuu' is roughly equivalent to 'grep -r'.
|
'rg -uuu' is roughly equivalent to 'grep -r'.
|
||||||
"
|
"
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ use ignore::overrides::{Override, OverrideBuilder};
|
|||||||
use ignore::types::{FileTypeDef, Types, TypesBuilder};
|
use ignore::types::{FileTypeDef, Types, TypesBuilder};
|
||||||
use ignore::{Walk, WalkBuilder, WalkParallel};
|
use ignore::{Walk, WalkBuilder, WalkParallel};
|
||||||
use log;
|
use log;
|
||||||
use num_cpus;
|
|
||||||
use regex;
|
use regex;
|
||||||
use termcolor::{BufferWriter, ColorChoice, WriteColor};
|
use termcolor::{BufferWriter, ColorChoice, WriteColor};
|
||||||
|
|
||||||
@@ -97,14 +96,17 @@ pub struct Args(Arc<ArgsImp>);
|
|||||||
struct ArgsImp {
|
struct ArgsImp {
|
||||||
/// Mid-to-low level routines for extracting CLI arguments.
|
/// Mid-to-low level routines for extracting CLI arguments.
|
||||||
matches: ArgMatches,
|
matches: ArgMatches,
|
||||||
/// The patterns provided at the command line and/or via the -f/--file
|
/// The command we want to execute.
|
||||||
/// flag. This may be empty.
|
command: Command,
|
||||||
patterns: Vec<String>,
|
/// The number of threads to use. This is based in part on available
|
||||||
|
/// threads, in part on the number of threads requested and in part on the
|
||||||
|
/// command we're running.
|
||||||
|
threads: usize,
|
||||||
/// A matcher built from the patterns.
|
/// A matcher built from the patterns.
|
||||||
///
|
///
|
||||||
/// It's important that this is only built once, since building this goes
|
/// It's important that this is only built once, since building this goes
|
||||||
/// through regex compilation and various types of analyses. That is, if
|
/// through regex compilation and various types of analyses. That is, if
|
||||||
/// you need many of theses (one per thread, for example), it is better to
|
/// you need many of these (one per thread, for example), it is better to
|
||||||
/// build it once and then clone it.
|
/// build it once and then clone it.
|
||||||
matcher: PatternMatcher,
|
matcher: PatternMatcher,
|
||||||
/// The paths provided at the command line. This is guaranteed to be
|
/// The paths provided at the command line. This is guaranteed to be
|
||||||
@@ -165,12 +167,6 @@ impl Args {
|
|||||||
&self.0.matches
|
&self.0.matches
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the patterns found in the command line arguments. This includes
|
|
||||||
/// patterns read via the -f/--file flags.
|
|
||||||
fn patterns(&self) -> &[String] {
|
|
||||||
&self.0.patterns
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the matcher builder from the patterns.
|
/// Return the matcher builder from the patterns.
|
||||||
fn matcher(&self) -> &PatternMatcher {
|
fn matcher(&self) -> &PatternMatcher {
|
||||||
&self.0.matcher
|
&self.0.matcher
|
||||||
@@ -186,7 +182,7 @@ impl Args {
|
|||||||
/// Returns true if and only if `paths` had to be populated with a default
|
/// Returns true if and only if `paths` had to be populated with a default
|
||||||
/// path, which occurs only when no paths were given as command line
|
/// path, which occurs only when no paths were given as command line
|
||||||
/// arguments.
|
/// arguments.
|
||||||
fn using_default_path(&self) -> bool {
|
pub fn using_default_path(&self) -> bool {
|
||||||
self.0.using_default_path
|
self.0.using_default_path
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +193,7 @@ impl Args {
|
|||||||
fn printer<W: WriteColor>(&self, wtr: W) -> Result<Printer<W>> {
|
fn printer<W: WriteColor>(&self, wtr: W) -> Result<Printer<W>> {
|
||||||
match self.matches().output_kind() {
|
match self.matches().output_kind() {
|
||||||
OutputKind::Standard => {
|
OutputKind::Standard => {
|
||||||
let separator_search = self.command()? == Command::Search;
|
let separator_search = self.command() == Command::Search;
|
||||||
self.matches()
|
self.matches()
|
||||||
.printer_standard(self.paths(), wtr, separator_search)
|
.printer_standard(self.paths(), wtr, separator_search)
|
||||||
.map(Printer::Standard)
|
.map(Printer::Standard)
|
||||||
@@ -225,28 +221,8 @@ impl Args {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the high-level command that ripgrep should run.
|
/// Return the high-level command that ripgrep should run.
|
||||||
pub fn command(&self) -> Result<Command> {
|
pub fn command(&self) -> Command {
|
||||||
let is_one_search = self.matches().is_one_search(self.paths());
|
self.0.command
|
||||||
let threads = self.matches().threads()?;
|
|
||||||
let one_thread = is_one_search || threads == 1;
|
|
||||||
|
|
||||||
Ok(if self.matches().is_present("pcre2-version") {
|
|
||||||
Command::PCRE2Version
|
|
||||||
} else if self.matches().is_present("type-list") {
|
|
||||||
Command::Types
|
|
||||||
} else if self.matches().is_present("files") {
|
|
||||||
if one_thread {
|
|
||||||
Command::Files
|
|
||||||
} else {
|
|
||||||
Command::FilesParallel
|
|
||||||
}
|
|
||||||
} else if self.matches().can_never_match(self.patterns()) {
|
|
||||||
Command::SearchNever
|
|
||||||
} else if one_thread {
|
|
||||||
Command::Search
|
|
||||||
} else {
|
|
||||||
Command::SearchParallel
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder a path printer that can be used for printing just file paths,
|
/// Builder a path printer that can be used for printing just file paths,
|
||||||
@@ -290,7 +266,7 @@ impl Args {
|
|||||||
let mut builder = SearchWorkerBuilder::new();
|
let mut builder = SearchWorkerBuilder::new();
|
||||||
builder
|
builder
|
||||||
.json_stats(matches.is_present("json"))
|
.json_stats(matches.is_present("json"))
|
||||||
.preprocessor(matches.preprocessor())
|
.preprocessor(matches.preprocessor())?
|
||||||
.preprocessor_globs(matches.preprocessor_globs()?)
|
.preprocessor_globs(matches.preprocessor_globs()?)
|
||||||
.search_zip(matches.is_present("search-zip"))
|
.search_zip(matches.is_present("search-zip"))
|
||||||
.binary_detection_implicit(matches.binary_detection_implicit())
|
.binary_detection_implicit(matches.binary_detection_implicit())
|
||||||
@@ -304,7 +280,7 @@ impl Args {
|
|||||||
/// When this returns a `Stats` value, then it is guaranteed that the
|
/// When this returns a `Stats` value, then it is guaranteed that the
|
||||||
/// search worker will be configured to track statistics as well.
|
/// search worker will be configured to track statistics as well.
|
||||||
pub fn stats(&self) -> Result<Option<Stats>> {
|
pub fn stats(&self) -> Result<Option<Stats>> {
|
||||||
Ok(if self.command()?.is_search() && self.matches().stats() {
|
Ok(if self.command().is_search() && self.matches().stats() {
|
||||||
Some(Stats::new())
|
Some(Stats::new())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -343,12 +319,18 @@ impl Args {
|
|||||||
|
|
||||||
/// Return a walker that never uses additional threads.
|
/// Return a walker that never uses additional threads.
|
||||||
pub fn walker(&self) -> Result<Walk> {
|
pub fn walker(&self) -> Result<Walk> {
|
||||||
Ok(self.matches().walker_builder(self.paths())?.build())
|
Ok(self
|
||||||
|
.matches()
|
||||||
|
.walker_builder(self.paths(), self.0.threads)?
|
||||||
|
.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a walker that never uses additional threads.
|
/// Return a parallel walker that may use additional threads.
|
||||||
pub fn walker_parallel(&self) -> Result<WalkParallel> {
|
pub fn walker_parallel(&self) -> Result<WalkParallel> {
|
||||||
Ok(self.matches().walker_builder(self.paths())?.build_parallel())
|
Ok(self
|
||||||
|
.matches()
|
||||||
|
.walker_builder(self.paths(), self.0.threads)?
|
||||||
|
.build_parallel())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,9 +539,36 @@ impl ArgMatches {
|
|||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
// Now figure out the number of threads we'll use and which
|
||||||
|
// command will run.
|
||||||
|
let is_one_search = self.is_one_search(&paths);
|
||||||
|
let threads = if is_one_search { 1 } else { self.threads()? };
|
||||||
|
if threads == 1 {
|
||||||
|
log::debug!("running in single threaded mode");
|
||||||
|
} else {
|
||||||
|
log::debug!("running with {threads} threads for parallelism");
|
||||||
|
}
|
||||||
|
let command = if self.is_present("pcre2-version") {
|
||||||
|
Command::PCRE2Version
|
||||||
|
} else if self.is_present("type-list") {
|
||||||
|
Command::Types
|
||||||
|
} else if self.is_present("files") {
|
||||||
|
if threads == 1 {
|
||||||
|
Command::Files
|
||||||
|
} else {
|
||||||
|
Command::FilesParallel
|
||||||
|
}
|
||||||
|
} else if self.can_never_match(&patterns) {
|
||||||
|
Command::SearchNever
|
||||||
|
} else if threads == 1 {
|
||||||
|
Command::Search
|
||||||
|
} else {
|
||||||
|
Command::SearchParallel
|
||||||
|
};
|
||||||
Ok(Args(Arc::new(ArgsImp {
|
Ok(Args(Arc::new(ArgsImp {
|
||||||
matches: self,
|
matches: self,
|
||||||
patterns,
|
command,
|
||||||
|
threads,
|
||||||
matcher,
|
matcher,
|
||||||
paths,
|
paths,
|
||||||
using_default_path,
|
using_default_path,
|
||||||
@@ -777,6 +786,7 @@ impl ArgMatches {
|
|||||||
.path(self.with_filename(paths))
|
.path(self.with_filename(paths))
|
||||||
.only_matching(self.is_present("only-matching"))
|
.only_matching(self.is_present("only-matching"))
|
||||||
.per_match(self.is_present("vimgrep"))
|
.per_match(self.is_present("vimgrep"))
|
||||||
|
.per_match_one_line(true)
|
||||||
.replacement(self.replacement())
|
.replacement(self.replacement())
|
||||||
.max_columns(self.max_columns()?)
|
.max_columns(self.max_columns()?)
|
||||||
.max_columns_preview(self.max_columns_preview())
|
.max_columns_preview(self.max_columns_preview())
|
||||||
@@ -786,8 +796,8 @@ impl ArgMatches {
|
|||||||
.trim_ascii(self.is_present("trim"))
|
.trim_ascii(self.is_present("trim"))
|
||||||
.separator_search(None)
|
.separator_search(None)
|
||||||
.separator_context(self.context_separator())
|
.separator_context(self.context_separator())
|
||||||
.separator_field_match(b":".to_vec())
|
.separator_field_match(self.field_match_separator())
|
||||||
.separator_field_context(b"-".to_vec())
|
.separator_field_context(self.field_context_separator())
|
||||||
.separator_path(self.path_separator()?)
|
.separator_path(self.path_separator()?)
|
||||||
.path_terminator(self.path_terminator());
|
.path_terminator(self.path_terminator());
|
||||||
if separator_search {
|
if separator_search {
|
||||||
@@ -857,7 +867,11 @@ impl ArgMatches {
|
|||||||
///
|
///
|
||||||
/// If there was a problem parsing the CLI arguments necessary for
|
/// If there was a problem parsing the CLI arguments necessary for
|
||||||
/// constructing the builder, then this returns an error.
|
/// constructing the builder, then this returns an error.
|
||||||
fn walker_builder(&self, paths: &[PathBuf]) -> Result<WalkBuilder> {
|
fn walker_builder(
|
||||||
|
&self,
|
||||||
|
paths: &[PathBuf],
|
||||||
|
threads: usize,
|
||||||
|
) -> Result<WalkBuilder> {
|
||||||
let mut builder = WalkBuilder::new(&paths[0]);
|
let mut builder = WalkBuilder::new(&paths[0]);
|
||||||
for path in &paths[1..] {
|
for path in &paths[1..] {
|
||||||
builder.add(path);
|
builder.add(path);
|
||||||
@@ -873,7 +887,7 @@ impl ArgMatches {
|
|||||||
.max_depth(self.usize_of("max-depth")?)
|
.max_depth(self.usize_of("max-depth")?)
|
||||||
.follow_links(self.is_present("follow"))
|
.follow_links(self.is_present("follow"))
|
||||||
.max_filesize(self.max_file_size()?)
|
.max_filesize(self.max_file_size()?)
|
||||||
.threads(self.threads()?)
|
.threads(threads)
|
||||||
.same_file_system(self.is_present("one-file-system"))
|
.same_file_system(self.is_present("one-file-system"))
|
||||||
.skip_stdout(!self.is_present("files"))
|
.skip_stdout(!self.is_present("files"))
|
||||||
.overrides(self.overrides()?)
|
.overrides(self.overrides()?)
|
||||||
@@ -1377,6 +1391,24 @@ impl ArgMatches {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the unescaped field context separator. If one wasn't specified,
|
||||||
|
/// then '-' is used as the default.
|
||||||
|
fn field_context_separator(&self) -> Vec<u8> {
|
||||||
|
match self.value_of_os("field-context-separator") {
|
||||||
|
None => b"-".to_vec(),
|
||||||
|
Some(sep) => cli::unescape_os(&sep),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the unescaped field match separator. If one wasn't specified,
|
||||||
|
/// then ':' is used as the default.
|
||||||
|
fn field_match_separator(&self) -> Vec<u8> {
|
||||||
|
match self.value_of_os("field-match-separator") {
|
||||||
|
None => b":".to_vec(),
|
||||||
|
Some(sep) => cli::unescape_os(&sep),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a sequence of all available patterns from the command line.
|
/// Get a sequence of all available patterns from the command line.
|
||||||
/// This includes reading the -e/--regexp and -f/--file flags.
|
/// This includes reading the -e/--regexp and -f/--file flags.
|
||||||
///
|
///
|
||||||
@@ -1541,7 +1573,7 @@ impl ArgMatches {
|
|||||||
///
|
///
|
||||||
/// Generally, this is only enabled when explicitly requested by in the
|
/// Generally, this is only enabled when explicitly requested by in the
|
||||||
/// command line arguments via the --stats flag, but this can also be
|
/// command line arguments via the --stats flag, but this can also be
|
||||||
/// enabled implicity via the output format, e.g., for JSON Lines.
|
/// enabled implicitly via the output format, e.g., for JSON Lines.
|
||||||
fn stats(&self) -> bool {
|
fn stats(&self) -> bool {
|
||||||
self.output_kind() == OutputKind::JSON || self.is_present("stats")
|
self.output_kind() == OutputKind::JSON || self.is_present("stats")
|
||||||
}
|
}
|
||||||
@@ -1573,7 +1605,9 @@ impl ArgMatches {
|
|||||||
return Ok(1);
|
return Ok(1);
|
||||||
}
|
}
|
||||||
let threads = self.usize_of("threads")?.unwrap_or(0);
|
let threads = self.usize_of("threads")?.unwrap_or(0);
|
||||||
Ok(if threads == 0 { cmp::min(12, num_cpus::get()) } else { threads })
|
let available =
|
||||||
|
std::thread::available_parallelism().map_or(1, |n| n.get());
|
||||||
|
Ok(if threads == 0 { cmp::min(12, available) } else { threads })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a file type matcher from the command line flags.
|
/// Builds a file type matcher from the command line flags.
|
||||||
@@ -1701,7 +1735,7 @@ impl ArgMatches {
|
|||||||
self.0.value_of_os(name)
|
self.0.value_of_os(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn values_of_os(&self, name: &str) -> Option<clap::OsValues> {
|
fn values_of_os(&self, name: &str) -> Option<clap::OsValues<'_>> {
|
||||||
self.0.values_of_os(name)
|
self.0.values_of_os(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ pub fn args() -> Vec<OsString> {
|
|||||||
let (args, errs) = match parse(&config_path) {
|
let (args, errs) = match parse(&config_path) {
|
||||||
Ok((args, errs)) => (args, errs),
|
Ok((args, errs)) => (args, errs),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
message!("{}", err);
|
message!(
|
||||||
|
"failed to read the file specified in RIPGREP_CONFIG_PATH: {}",
|
||||||
|
err
|
||||||
|
);
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -77,7 +80,7 @@ fn parse<P: AsRef<Path>>(
|
|||||||
fn parse_reader<R: io::Read>(
|
fn parse_reader<R: io::Read>(
|
||||||
rdr: R,
|
rdr: R,
|
||||||
) -> Result<(Vec<OsString>, Vec<Box<dyn Error>>)> {
|
) -> Result<(Vec<OsString>, Vec<Box<dyn Error>>)> {
|
||||||
let bufrdr = io::BufReader::new(rdr);
|
let mut bufrdr = io::BufReader::new(rdr);
|
||||||
let (mut args, mut errs) = (vec![], vec![]);
|
let (mut args, mut errs) = (vec![], vec![]);
|
||||||
let mut line_number = 0;
|
let mut line_number = 0;
|
||||||
bufrdr.for_byte_line_with_terminator(|line| {
|
bufrdr.for_byte_line_with_terminator(|line| {
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ impl Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Log for Logger {
|
impl Log for Logger {
|
||||||
fn enabled(&self, _: &log::Metadata) -> bool {
|
fn enabled(&self, _: &log::Metadata<'_>) -> bool {
|
||||||
// We set the log level via log::set_max_level, so we don't need to
|
// We set the log level via log::set_max_level, so we don't need to
|
||||||
// implement filtering here.
|
// implement filtering here.
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log(&self, record: &log::Record) {
|
fn log(&self, record: &log::Record<'_>) {
|
||||||
match (record.file(), record.line()) {
|
match (record.file(), record.line()) {
|
||||||
(Some(file), Some(line)) => {
|
(Some(file), Some(line)) => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ fn main() {
|
|||||||
fn try_main(args: Args) -> Result<()> {
|
fn try_main(args: Args) -> Result<()> {
|
||||||
use args::Command::*;
|
use args::Command::*;
|
||||||
|
|
||||||
let matched = match args.command()? {
|
let matched = match args.command() {
|
||||||
Search => search(&args),
|
Search => search(&args),
|
||||||
SearchParallel => search_parallel(&args),
|
SearchParallel => search_parallel(&args),
|
||||||
SearchNever => Ok(false),
|
SearchNever => Ok(false),
|
||||||
@@ -83,12 +83,14 @@ fn search(args: &Args) -> Result<bool> {
|
|||||||
let mut stats = args.stats()?;
|
let mut stats = args.stats()?;
|
||||||
let mut searcher = args.search_worker(args.stdout())?;
|
let mut searcher = args.search_worker(args.stdout())?;
|
||||||
let mut matched = false;
|
let mut matched = false;
|
||||||
|
let mut searched = false;
|
||||||
|
|
||||||
for result in args.walker()? {
|
for result in args.walker()? {
|
||||||
let subject = match subject_builder.build_from_result(result) {
|
let subject = match subject_builder.build_from_result(result) {
|
||||||
Some(subject) => subject,
|
Some(subject) => subject,
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
searched = true;
|
||||||
let search_result = match searcher.search(&subject) {
|
let search_result = match searcher.search(&subject) {
|
||||||
Ok(search_result) => search_result,
|
Ok(search_result) => search_result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -108,6 +110,9 @@ fn search(args: &Args) -> Result<bool> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if args.using_default_path() && !searched {
|
||||||
|
eprint_nothing_searched();
|
||||||
|
}
|
||||||
if let Some(ref stats) = stats {
|
if let Some(ref stats) = stats {
|
||||||
let elapsed = Instant::now().duration_since(started_at);
|
let elapsed = Instant::now().duration_since(started_at);
|
||||||
// We don't care if we couldn't print this successfully.
|
// We don't care if we couldn't print this successfully.
|
||||||
@@ -129,11 +134,13 @@ fn search_parallel(args: &Args) -> Result<bool> {
|
|||||||
let bufwtr = args.buffer_writer()?;
|
let bufwtr = args.buffer_writer()?;
|
||||||
let stats = args.stats()?.map(Mutex::new);
|
let stats = args.stats()?.map(Mutex::new);
|
||||||
let matched = AtomicBool::new(false);
|
let matched = AtomicBool::new(false);
|
||||||
|
let searched = AtomicBool::new(false);
|
||||||
let mut searcher_err = None;
|
let mut searcher_err = None;
|
||||||
args.walker_parallel()?.run(|| {
|
args.walker_parallel()?.run(|| {
|
||||||
let bufwtr = &bufwtr;
|
let bufwtr = &bufwtr;
|
||||||
let stats = &stats;
|
let stats = &stats;
|
||||||
let matched = &matched;
|
let matched = &matched;
|
||||||
|
let searched = &searched;
|
||||||
let subject_builder = &subject_builder;
|
let subject_builder = &subject_builder;
|
||||||
let mut searcher = match args.search_worker(bufwtr.buffer()) {
|
let mut searcher = match args.search_worker(bufwtr.buffer()) {
|
||||||
Ok(searcher) => searcher,
|
Ok(searcher) => searcher,
|
||||||
@@ -148,6 +155,7 @@ fn search_parallel(args: &Args) -> Result<bool> {
|
|||||||
Some(subject) => subject,
|
Some(subject) => subject,
|
||||||
None => return WalkState::Continue,
|
None => return WalkState::Continue,
|
||||||
};
|
};
|
||||||
|
searched.store(true, SeqCst);
|
||||||
searcher.printer().get_mut().clear();
|
searcher.printer().get_mut().clear();
|
||||||
let search_result = match searcher.search(&subject) {
|
let search_result = match searcher.search(&subject) {
|
||||||
Ok(search_result) => search_result,
|
Ok(search_result) => search_result,
|
||||||
@@ -181,6 +189,9 @@ fn search_parallel(args: &Args) -> Result<bool> {
|
|||||||
if let Some(err) = searcher_err.take() {
|
if let Some(err) = searcher_err.take() {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
if args.using_default_path() && !searched.load(SeqCst) {
|
||||||
|
eprint_nothing_searched();
|
||||||
|
}
|
||||||
if let Some(ref locked_stats) = stats {
|
if let Some(ref locked_stats) = stats {
|
||||||
let elapsed = Instant::now().duration_since(started_at);
|
let elapsed = Instant::now().duration_since(started_at);
|
||||||
let stats = locked_stats.lock().unwrap();
|
let stats = locked_stats.lock().unwrap();
|
||||||
@@ -191,6 +202,14 @@ fn search_parallel(args: &Args) -> Result<bool> {
|
|||||||
Ok(matched.load(SeqCst))
|
Ok(matched.load(SeqCst))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eprint_nothing_searched() {
|
||||||
|
err_message!(
|
||||||
|
"No files were searched, which means ripgrep probably \
|
||||||
|
applied a filter you didn't expect.\n\
|
||||||
|
Running with --debug will show why files are being skipped."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// The top-level entry point for listing files without searching them. This
|
/// The top-level entry point for listing files without searching them. This
|
||||||
/// recursively steps through the file list (current directory by default) and
|
/// recursively steps through the file list (current directory by default) and
|
||||||
/// prints each path sequentially using a single thread.
|
/// prints each path sequentially using a single thread.
|
||||||
|
|||||||
@@ -115,9 +115,14 @@ impl SearchWorkerBuilder {
|
|||||||
pub fn preprocessor(
|
pub fn preprocessor(
|
||||||
&mut self,
|
&mut self,
|
||||||
cmd: Option<PathBuf>,
|
cmd: Option<PathBuf>,
|
||||||
) -> &mut SearchWorkerBuilder {
|
) -> crate::Result<&mut SearchWorkerBuilder> {
|
||||||
self.config.preprocessor = cmd;
|
if let Some(ref prog) = cmd {
|
||||||
self
|
let bin = cli::resolve_binary(prog)?;
|
||||||
|
self.config.preprocessor = Some(bin);
|
||||||
|
} else {
|
||||||
|
self.config.preprocessor = None;
|
||||||
|
}
|
||||||
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the globs for determining which files should be run through the
|
/// Set the globs for determining which files should be run through the
|
||||||
@@ -325,11 +330,12 @@ impl<W: WriteColor> SearchWorker<W> {
|
|||||||
} else {
|
} else {
|
||||||
self.config.binary_implicit.clone()
|
self.config.binary_implicit.clone()
|
||||||
};
|
};
|
||||||
self.searcher.set_binary_detection(bin);
|
|
||||||
|
|
||||||
let path = subject.path();
|
let path = subject.path();
|
||||||
|
log::trace!("{}: binary detection: {:?}", path.display(), bin);
|
||||||
|
|
||||||
|
self.searcher.set_binary_detection(bin);
|
||||||
if subject.is_stdin() {
|
if subject.is_stdin() {
|
||||||
self.search_reader(path, io::stdin().lock())
|
self.search_reader(path, &mut io::stdin().lock())
|
||||||
} else if self.should_preprocess(path) {
|
} else if self.should_preprocess(path) {
|
||||||
self.search_preprocessor(path)
|
self.search_preprocessor(path)
|
||||||
} else if self.should_decompress(path) {
|
} else if self.should_decompress(path) {
|
||||||
@@ -393,7 +399,7 @@ impl<W: WriteColor> SearchWorker<W> {
|
|||||||
let mut cmd = Command::new(bin);
|
let mut cmd = Command::new(bin);
|
||||||
cmd.arg(path).stdin(Stdio::from(File::open(path)?));
|
cmd.arg(path).stdin(Stdio::from(File::open(path)?));
|
||||||
|
|
||||||
let rdr = self.command_builder.build(&mut cmd).map_err(|err| {
|
let mut rdr = self.command_builder.build(&mut cmd).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!(
|
format!(
|
||||||
@@ -402,20 +408,28 @@ impl<W: WriteColor> SearchWorker<W> {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
self.search_reader(path, rdr).map_err(|err| {
|
let result = self.search_reader(path, &mut rdr).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("preprocessor command failed: '{:?}': {}", cmd, err),
|
format!("preprocessor command failed: '{:?}': {}", cmd, err),
|
||||||
)
|
)
|
||||||
})
|
});
|
||||||
|
let close_result = rdr.close();
|
||||||
|
let search_result = result?;
|
||||||
|
close_result?;
|
||||||
|
Ok(search_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to decompress the data at the given file path and search the
|
/// Attempt to decompress the data at the given file path and search the
|
||||||
/// result. If the given file path isn't recognized as a compressed file,
|
/// result. If the given file path isn't recognized as a compressed file,
|
||||||
/// then search it without doing any decompression.
|
/// then search it without doing any decompression.
|
||||||
fn search_decompress(&mut self, path: &Path) -> io::Result<SearchResult> {
|
fn search_decompress(&mut self, path: &Path) -> io::Result<SearchResult> {
|
||||||
let rdr = self.decomp_builder.build(path)?;
|
let mut rdr = self.decomp_builder.build(path)?;
|
||||||
self.search_reader(path, rdr)
|
let result = self.search_reader(path, &mut rdr);
|
||||||
|
let close_result = rdr.close();
|
||||||
|
let search_result = result?;
|
||||||
|
close_result?;
|
||||||
|
Ok(search_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search the contents of the given file path.
|
/// Search the contents of the given file path.
|
||||||
@@ -442,7 +456,7 @@ impl<W: WriteColor> SearchWorker<W> {
|
|||||||
fn search_reader<R: io::Read>(
|
fn search_reader<R: io::Read>(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
rdr: R,
|
rdr: &mut R,
|
||||||
) -> io::Result<SearchResult> {
|
) -> io::Result<SearchResult> {
|
||||||
use self::PatternMatcher::*;
|
use self::PatternMatcher::*;
|
||||||
|
|
||||||
@@ -498,12 +512,12 @@ fn search_reader<M: Matcher, R: io::Read, W: WriteColor>(
|
|||||||
searcher: &mut Searcher,
|
searcher: &mut Searcher,
|
||||||
printer: &mut Printer<W>,
|
printer: &mut Printer<W>,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
rdr: R,
|
mut rdr: R,
|
||||||
) -> io::Result<SearchResult> {
|
) -> io::Result<SearchResult> {
|
||||||
match *printer {
|
match *printer {
|
||||||
Printer::Standard(ref mut p) => {
|
Printer::Standard(ref mut p) => {
|
||||||
let mut sink = p.sink_with_path(&matcher, path);
|
let mut sink = p.sink_with_path(&matcher, path);
|
||||||
searcher.search_reader(&matcher, rdr, &mut sink)?;
|
searcher.search_reader(&matcher, &mut rdr, &mut sink)?;
|
||||||
Ok(SearchResult {
|
Ok(SearchResult {
|
||||||
has_match: sink.has_match(),
|
has_match: sink.has_match(),
|
||||||
stats: sink.stats().map(|s| s.clone()),
|
stats: sink.stats().map(|s| s.clone()),
|
||||||
@@ -511,7 +525,7 @@ fn search_reader<M: Matcher, R: io::Read, W: WriteColor>(
|
|||||||
}
|
}
|
||||||
Printer::Summary(ref mut p) => {
|
Printer::Summary(ref mut p) => {
|
||||||
let mut sink = p.sink_with_path(&matcher, path);
|
let mut sink = p.sink_with_path(&matcher, path);
|
||||||
searcher.search_reader(&matcher, rdr, &mut sink)?;
|
searcher.search_reader(&matcher, &mut rdr, &mut sink)?;
|
||||||
Ok(SearchResult {
|
Ok(SearchResult {
|
||||||
has_match: sink.has_match(),
|
has_match: sink.has_match(),
|
||||||
stats: sink.stats().map(|s| s.clone()),
|
stats: sink.stats().map(|s| s.clone()),
|
||||||
@@ -519,7 +533,7 @@ fn search_reader<M: Matcher, R: io::Read, W: WriteColor>(
|
|||||||
}
|
}
|
||||||
Printer::JSON(ref mut p) => {
|
Printer::JSON(ref mut p) => {
|
||||||
let mut sink = p.sink_with_path(&matcher, path);
|
let mut sink = p.sink_with_path(&matcher, path);
|
||||||
searcher.search_reader(&matcher, rdr, &mut sink)?;
|
searcher.search_reader(&matcher, &mut rdr, &mut sink)?;
|
||||||
Ok(SearchResult {
|
Ok(SearchResult {
|
||||||
has_match: sink.has_match(),
|
has_match: sink.has_match(),
|
||||||
stats: Some(sink.stats().clone()),
|
stats: Some(sink.stats().clone()),
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ impl SubjectBuilder {
|
|||||||
if subj.is_file() {
|
if subj.is_file() {
|
||||||
return Some(subj);
|
return Some(subj);
|
||||||
}
|
}
|
||||||
// We got nothin. Emit a debug message, but only if this isn't a
|
// We got nothing. Emit a debug message, but only if this isn't a
|
||||||
// directory. Otherwise, emitting messages for directories is just
|
// directory. Otherwise, emitting messages for directories is just
|
||||||
// noisy.
|
// noisy.
|
||||||
if !subj.is_dir() {
|
if !subj.is_dir() {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.5" #:version
|
version = "0.4.10" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Cross platform single glob and glob set matching. Glob set matching is the
|
Cross platform single glob and glob set matching. Glob set matching is the
|
||||||
@@ -12,7 +12,8 @@ homepage = "https://github.com/BurntSushi/ripgrep/tree/master/crates/globset"
|
|||||||
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/globset"
|
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/globset"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["regex", "glob", "multiple", "set", "pattern"]
|
keywords = ["regex", "glob", "multiple", "set", "pattern"]
|
||||||
license = "Unlicense/MIT"
|
license = "Unlicense OR MIT"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
@@ -20,10 +21,10 @@ bench = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aho-corasick = "0.7.3"
|
aho-corasick = "0.7.3"
|
||||||
bstr = { version = "0.2.0", default-features = false, features = ["std"] }
|
bstr = { version = "1.1.0", default-features = false, features = ["std"] }
|
||||||
fnv = "1.0.6"
|
fnv = "1.0.6"
|
||||||
log = "0.4.5"
|
log = { version = "0.4.5", optional = true }
|
||||||
regex = "1.1.5"
|
regex = { version = "1.1.5", default-features = false, features = ["perf", "std"] }
|
||||||
serde = { version = "1.0.104", optional = true }
|
serde = { version = "1.0.104", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
@@ -32,5 +33,6 @@ lazy_static = "1"
|
|||||||
serde_json = "1.0.45"
|
serde_json = "1.0.45"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = ["log"]
|
||||||
simd-accel = []
|
simd-accel = []
|
||||||
serde1 = ["serde"]
|
serde1 = ["serde"]
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ Cross platform single glob and glob set matching. Glob set matching is the
|
|||||||
process of matching one or more glob patterns against a single candidate path
|
process of matching one or more glob patterns against a single candidate path
|
||||||
simultaneously, and returning all of the globs that matched.
|
simultaneously, and returning all of the globs that matched.
|
||||||
|
|
||||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
[](https://github.com/BurntSushi/ripgrep/actions)
|
||||||
[](https://ci.appveyor.com/project/BurntSushi/ripgrep)
|
|
||||||
[](https://crates.io/crates/globset)
|
[](https://crates.io/crates/globset)
|
||||||
|
|
||||||
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
@@ -20,13 +19,7 @@ Add this to your `Cargo.toml`:
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
globset = "0.3"
|
globset = "0.4"
|
||||||
```
|
|
||||||
|
|
||||||
and this to your crate root:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
extern crate globset;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
@@ -85,12 +78,12 @@ assert_eq!(set.matches("src/bar/baz/foo.rs"), vec![0, 2]);
|
|||||||
|
|
||||||
This crate implements globs by converting them to regular expressions, and
|
This crate implements globs by converting them to regular expressions, and
|
||||||
executing them with the
|
executing them with the
|
||||||
[`regex`](https://github.com/rust-lang-nursery/regex)
|
[`regex`](https://github.com/rust-lang/regex)
|
||||||
crate.
|
crate.
|
||||||
|
|
||||||
For single glob matching, performance of this crate should be roughly on par
|
For single glob matching, performance of this crate should be roughly on par
|
||||||
with the performance of the
|
with the performance of the
|
||||||
[`glob`](https://github.com/rust-lang-nursery/glob)
|
[`glob`](https://github.com/rust-lang/glob)
|
||||||
crate. (`*_regex` correspond to benchmarks for this library while `*_glob`
|
crate. (`*_regex` correspond to benchmarks for this library while `*_glob`
|
||||||
correspond to benchmarks for the `glob` library.)
|
correspond to benchmarks for the `glob` library.)
|
||||||
Optimizations in the `regex` crate may propel this library past `glob`,
|
Optimizations in the `regex` crate may propel this library past `glob`,
|
||||||
@@ -115,7 +108,7 @@ test many_short_glob ... bench: 1,063 ns/iter (+/- 47)
|
|||||||
test many_short_regex_set ... bench: 186 ns/iter (+/- 11)
|
test many_short_regex_set ... bench: 186 ns/iter (+/- 11)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Comparison with the [`glob`](https://github.com/rust-lang-nursery/glob) crate
|
### Comparison with the [`glob`](https://github.com/rust-lang/glob) crate
|
||||||
|
|
||||||
* Supports alternate "or" globs, e.g., `*.{foo,bar}`.
|
* Supports alternate "or" globs, e.g., `*.{foo,bar}`.
|
||||||
* Can match non-UTF-8 file paths correctly.
|
* Can match non-UTF-8 file paths correctly.
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ tool itself, see the benchsuite directory.
|
|||||||
*/
|
*/
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
|
|
||||||
extern crate glob;
|
|
||||||
extern crate globset;
|
|
||||||
extern crate regex;
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
use globset::{Candidate, Glob, GlobMatcher, GlobSet, GlobSetBuilder};
|
use globset::{Candidate, Glob, GlobMatcher, GlobSet, GlobSetBuilder};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::str;
|
|||||||
use regex;
|
use regex;
|
||||||
use regex::bytes::Regex;
|
use regex::bytes::Regex;
|
||||||
|
|
||||||
use {new_regex, Candidate, Error, ErrorKind};
|
use crate::{new_regex, Candidate, Error, ErrorKind};
|
||||||
|
|
||||||
/// Describes a matching strategy for a particular pattern.
|
/// Describes a matching strategy for a particular pattern.
|
||||||
///
|
///
|
||||||
@@ -98,7 +98,7 @@ impl hash::Hash for Glob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Glob {
|
impl fmt::Display for Glob {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
self.glob.fmt(f)
|
self.glob.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ impl GlobMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Tests whether the given path matches this pattern or not.
|
/// Tests whether the given path matches this pattern or not.
|
||||||
pub fn is_match_candidate(&self, path: &Candidate) -> bool {
|
pub fn is_match_candidate(&self, path: &Candidate<'_>) -> bool {
|
||||||
self.re.is_match(&path.path)
|
self.re.is_match(&path.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,8 +143,6 @@ impl GlobMatcher {
|
|||||||
struct GlobStrategic {
|
struct GlobStrategic {
|
||||||
/// The match strategy to use.
|
/// The match strategy to use.
|
||||||
strategy: MatchStrategy,
|
strategy: MatchStrategy,
|
||||||
/// The underlying pattern.
|
|
||||||
pat: Glob,
|
|
||||||
/// The pattern, as a compiled regex.
|
/// The pattern, as a compiled regex.
|
||||||
re: Regex,
|
re: Regex,
|
||||||
}
|
}
|
||||||
@@ -157,7 +155,7 @@ impl GlobStrategic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Tests whether the given path matches this pattern or not.
|
/// Tests whether the given path matches this pattern or not.
|
||||||
fn is_match_candidate(&self, candidate: &Candidate) -> bool {
|
fn is_match_candidate(&self, candidate: &Candidate<'_>) -> bool {
|
||||||
let byte_path = &*candidate.path;
|
let byte_path = &*candidate.path;
|
||||||
|
|
||||||
match self.strategy {
|
match self.strategy {
|
||||||
@@ -273,7 +271,7 @@ impl Glob {
|
|||||||
let strategy = MatchStrategy::new(self);
|
let strategy = MatchStrategy::new(self);
|
||||||
let re =
|
let re =
|
||||||
new_regex(&self.re).expect("regex compilation shouldn't fail");
|
new_regex(&self.re).expect("regex compilation shouldn't fail");
|
||||||
GlobStrategic { strategy: strategy, pat: self.clone(), re: re }
|
GlobStrategic { strategy: strategy, re: re }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the original glob pattern used to build this pattern.
|
/// Returns the original glob pattern used to build this pattern.
|
||||||
@@ -367,7 +365,7 @@ impl Glob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is like `ext`, but returns an extension even if it isn't sufficent
|
/// This is like `ext`, but returns an extension even if it isn't sufficient
|
||||||
/// to imply a match. Namely, if an extension is returned, then it is
|
/// to imply a match. Namely, if an extension is returned, then it is
|
||||||
/// necessary but not sufficient for a match.
|
/// necessary but not sufficient for a match.
|
||||||
fn required_ext(&self) -> Option<String> {
|
fn required_ext(&self) -> Option<String> {
|
||||||
@@ -403,7 +401,7 @@ impl Glob {
|
|||||||
if self.opts.case_insensitive {
|
if self.opts.case_insensitive {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let end = match self.tokens.last() {
|
let (end, need_sep) = match self.tokens.last() {
|
||||||
Some(&Token::ZeroOrMore) => {
|
Some(&Token::ZeroOrMore) => {
|
||||||
if self.opts.literal_separator {
|
if self.opts.literal_separator {
|
||||||
// If a trailing `*` can't match a `/`, then we can't
|
// If a trailing `*` can't match a `/`, then we can't
|
||||||
@@ -414,9 +412,10 @@ impl Glob {
|
|||||||
// literal prefix.
|
// literal prefix.
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
self.tokens.len() - 1
|
(self.tokens.len() - 1, false)
|
||||||
}
|
}
|
||||||
_ => self.tokens.len(),
|
Some(&Token::RecursiveSuffix) => (self.tokens.len() - 1, true),
|
||||||
|
_ => (self.tokens.len(), false),
|
||||||
};
|
};
|
||||||
let mut lit = String::new();
|
let mut lit = String::new();
|
||||||
for t in &self.tokens[0..end] {
|
for t in &self.tokens[0..end] {
|
||||||
@@ -425,6 +424,9 @@ impl Glob {
|
|||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if need_sep {
|
||||||
|
lit.push('/');
|
||||||
|
}
|
||||||
if lit.is_empty() {
|
if lit.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@@ -612,6 +614,8 @@ impl<'a> GlobBuilder<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Toggle whether a literal `/` is required to match a path separator.
|
/// Toggle whether a literal `/` is required to match a path separator.
|
||||||
|
///
|
||||||
|
/// By default this is false: `*` and `?` will match `/`.
|
||||||
pub fn literal_separator(&mut self, yes: bool) -> &mut GlobBuilder<'a> {
|
pub fn literal_separator(&mut self, yes: bool) -> &mut GlobBuilder<'a> {
|
||||||
self.opts.literal_separator = yes;
|
self.opts.literal_separator = yes;
|
||||||
self
|
self
|
||||||
@@ -683,7 +687,7 @@ impl Tokens {
|
|||||||
re.push_str("(?:/?|.*/)");
|
re.push_str("(?:/?|.*/)");
|
||||||
}
|
}
|
||||||
Token::RecursiveSuffix => {
|
Token::RecursiveSuffix => {
|
||||||
re.push_str("(?:/?|/.*)");
|
re.push_str("/.*");
|
||||||
}
|
}
|
||||||
Token::RecursiveZeroOrMore => {
|
Token::RecursiveZeroOrMore => {
|
||||||
re.push_str("(?:/|/.*/)");
|
re.push_str("(?:/|/.*/)");
|
||||||
@@ -1009,7 +1013,7 @@ fn ends_with(needle: &[u8], haystack: &[u8]) -> bool {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::Token::*;
|
use super::Token::*;
|
||||||
use super::{Glob, GlobBuilder, Token};
|
use super::{Glob, GlobBuilder, Token};
|
||||||
use {ErrorKind, GlobSetBuilder};
|
use crate::{ErrorKind, GlobSetBuilder};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
struct Options {
|
struct Options {
|
||||||
@@ -1222,9 +1226,9 @@ mod tests {
|
|||||||
toregex!(re16, "**/**/*", r"^(?:/?|.*/).*$");
|
toregex!(re16, "**/**/*", r"^(?:/?|.*/).*$");
|
||||||
toregex!(re17, "**/**/**", r"^.*$");
|
toregex!(re17, "**/**/**", r"^.*$");
|
||||||
toregex!(re18, "**/**/**/*", r"^(?:/?|.*/).*$");
|
toregex!(re18, "**/**/**/*", r"^(?:/?|.*/).*$");
|
||||||
toregex!(re19, "a/**", r"^a(?:/?|/.*)$");
|
toregex!(re19, "a/**", r"^a/.*$");
|
||||||
toregex!(re20, "a/**/**", r"^a(?:/?|/.*)$");
|
toregex!(re20, "a/**/**", r"^a/.*$");
|
||||||
toregex!(re21, "a/**/**/**", r"^a(?:/?|/.*)$");
|
toregex!(re21, "a/**/**/**", r"^a/.*$");
|
||||||
toregex!(re22, "a/**/b", r"^a(?:/|/.*/)b$");
|
toregex!(re22, "a/**/b", r"^a(?:/|/.*/)b$");
|
||||||
toregex!(re23, "a/**/**/b", r"^a(?:/|/.*/)b$");
|
toregex!(re23, "a/**/**/b", r"^a(?:/|/.*/)b$");
|
||||||
toregex!(re24, "a/**/**/**/b", r"^a(?:/|/.*/)b$");
|
toregex!(re24, "a/**/**/**/b", r"^a(?:/|/.*/)b$");
|
||||||
@@ -1270,11 +1274,12 @@ mod tests {
|
|||||||
matches!(matchrec18, "/**/test", "/test");
|
matches!(matchrec18, "/**/test", "/test");
|
||||||
matches!(matchrec19, "**/.*", ".abc");
|
matches!(matchrec19, "**/.*", ".abc");
|
||||||
matches!(matchrec20, "**/.*", "abc/.abc");
|
matches!(matchrec20, "**/.*", "abc/.abc");
|
||||||
matches!(matchrec21, ".*/**", ".abc");
|
matches!(matchrec21, "**/foo/bar", "foo/bar");
|
||||||
matches!(matchrec22, ".*/**", ".abc/abc");
|
matches!(matchrec22, ".*/**", ".abc/abc");
|
||||||
matches!(matchrec23, "foo/**", "foo");
|
matches!(matchrec23, "test/**", "test/");
|
||||||
matches!(matchrec24, "**/foo/bar", "foo/bar");
|
matches!(matchrec24, "test/**", "test/one");
|
||||||
matches!(matchrec25, "some/*/needle.txt", "some/one/needle.txt");
|
matches!(matchrec25, "test/**", "test/one/two");
|
||||||
|
matches!(matchrec26, "some/*/needle.txt", "some/one/needle.txt");
|
||||||
|
|
||||||
matches!(matchrange1, "a[0-9]b", "a0b");
|
matches!(matchrange1, "a[0-9]b", "a0b");
|
||||||
matches!(matchrange2, "a[0-9]b", "a9b");
|
matches!(matchrange2, "a[0-9]b", "a9b");
|
||||||
@@ -1400,6 +1405,8 @@ mod tests {
|
|||||||
"some/one/two/three/needle.txt",
|
"some/one/two/three/needle.txt",
|
||||||
SLASHLIT
|
SLASHLIT
|
||||||
);
|
);
|
||||||
|
nmatches!(matchrec33, ".*/**", ".abc");
|
||||||
|
nmatches!(matchrec34, "foo/**", "foo");
|
||||||
|
|
||||||
macro_rules! extract {
|
macro_rules! extract {
|
||||||
($which:ident, $name:ident, $pat:expr, $expect:expr) => {
|
($which:ident, $name:ident, $pat:expr, $expect:expr) => {
|
||||||
@@ -1504,7 +1511,7 @@ mod tests {
|
|||||||
prefix!(extract_prefix1, "/foo", Some(s("/foo")));
|
prefix!(extract_prefix1, "/foo", Some(s("/foo")));
|
||||||
prefix!(extract_prefix2, "/foo/*", Some(s("/foo/")));
|
prefix!(extract_prefix2, "/foo/*", Some(s("/foo/")));
|
||||||
prefix!(extract_prefix3, "**/foo", None);
|
prefix!(extract_prefix3, "**/foo", None);
|
||||||
prefix!(extract_prefix4, "foo/**", None);
|
prefix!(extract_prefix4, "foo/**", Some(s("foo/")));
|
||||||
|
|
||||||
suffix!(extract_suffix1, "**/foo/bar", Some((s("/foo/bar"), true)));
|
suffix!(extract_suffix1, "**/foo/bar", Some((s("/foo/bar"), true)));
|
||||||
suffix!(extract_suffix2, "*/foo/bar", Some((s("/foo/bar"), false)));
|
suffix!(extract_suffix2, "*/foo/bar", Some((s("/foo/bar"), false)));
|
||||||
|
|||||||
@@ -103,16 +103,6 @@ or to enable case insensitive matching.
|
|||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
extern crate aho_corasick;
|
|
||||||
extern crate bstr;
|
|
||||||
extern crate fnv;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
|
||||||
extern crate regex;
|
|
||||||
|
|
||||||
#[cfg(feature = "serde1")]
|
|
||||||
extern crate serde;
|
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
@@ -125,9 +115,9 @@ use aho_corasick::AhoCorasick;
|
|||||||
use bstr::{ByteSlice, ByteVec, B};
|
use bstr::{ByteSlice, ByteVec, B};
|
||||||
use regex::bytes::{Regex, RegexBuilder, RegexSet};
|
use regex::bytes::{Regex, RegexBuilder, RegexSet};
|
||||||
|
|
||||||
use glob::MatchStrategy;
|
use crate::glob::MatchStrategy;
|
||||||
pub use glob::{Glob, GlobBuilder, GlobMatcher};
|
pub use crate::glob::{Glob, GlobBuilder, GlobMatcher};
|
||||||
use pathutil::{file_name, file_name_ext, normalize_path};
|
use crate::pathutil::{file_name, file_name_ext, normalize_path};
|
||||||
|
|
||||||
mod glob;
|
mod glob;
|
||||||
mod pathutil;
|
mod pathutil;
|
||||||
@@ -135,6 +125,16 @@ mod pathutil;
|
|||||||
#[cfg(feature = "serde1")]
|
#[cfg(feature = "serde1")]
|
||||||
mod serde_impl;
|
mod serde_impl;
|
||||||
|
|
||||||
|
#[cfg(feature = "log")]
|
||||||
|
macro_rules! debug {
|
||||||
|
($($token:tt)*) => (::log::debug!($($token)*);)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "log"))]
|
||||||
|
macro_rules! debug {
|
||||||
|
($($token:tt)*) => {};
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents an error that can occur when parsing a glob pattern.
|
/// Represents an error that can occur when parsing a glob pattern.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
@@ -228,7 +228,7 @@ impl ErrorKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self.glob {
|
match self.glob {
|
||||||
None => self.kind.fmt(f),
|
None => self.kind.fmt(f),
|
||||||
Some(ref glob) => {
|
Some(ref glob) => {
|
||||||
@@ -239,7 +239,7 @@ impl fmt::Display for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ErrorKind {
|
impl fmt::Display for ErrorKind {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
ErrorKind::InvalidRecursive
|
ErrorKind::InvalidRecursive
|
||||||
| ErrorKind::UnclosedClass
|
| ErrorKind::UnclosedClass
|
||||||
@@ -317,7 +317,7 @@ impl GlobSet {
|
|||||||
///
|
///
|
||||||
/// This takes a Candidate as input, which can be used to amortize the
|
/// This takes a Candidate as input, which can be used to amortize the
|
||||||
/// cost of preparing a path for matching.
|
/// cost of preparing a path for matching.
|
||||||
pub fn is_match_candidate(&self, path: &Candidate) -> bool {
|
pub fn is_match_candidate(&self, path: &Candidate<'_>) -> bool {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -340,7 +340,7 @@ impl GlobSet {
|
|||||||
///
|
///
|
||||||
/// This takes a Candidate as input, which can be used to amortize the
|
/// This takes a Candidate as input, which can be used to amortize the
|
||||||
/// cost of preparing a path for matching.
|
/// cost of preparing a path for matching.
|
||||||
pub fn matches_candidate(&self, path: &Candidate) -> Vec<usize> {
|
pub fn matches_candidate(&self, path: &Candidate<'_>) -> Vec<usize> {
|
||||||
let mut into = vec![];
|
let mut into = vec![];
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
return into;
|
return into;
|
||||||
@@ -352,7 +352,7 @@ impl GlobSet {
|
|||||||
/// Adds the sequence number of every glob pattern that matches the given
|
/// Adds the sequence number of every glob pattern that matches the given
|
||||||
/// path to the vec given.
|
/// path to the vec given.
|
||||||
///
|
///
|
||||||
/// `into` is is cleared before matching begins, and contains the set of
|
/// `into` is cleared before matching begins, and contains the set of
|
||||||
/// sequence numbers (in ascending order) after matching ends. If no globs
|
/// sequence numbers (in ascending order) after matching ends. If no globs
|
||||||
/// were matched, then `into` will be empty.
|
/// were matched, then `into` will be empty.
|
||||||
pub fn matches_into<P: AsRef<Path>>(
|
pub fn matches_into<P: AsRef<Path>>(
|
||||||
@@ -366,7 +366,7 @@ impl GlobSet {
|
|||||||
/// Adds the sequence number of every glob pattern that matches the given
|
/// Adds the sequence number of every glob pattern that matches the given
|
||||||
/// path to the vec given.
|
/// path to the vec given.
|
||||||
///
|
///
|
||||||
/// `into` is is cleared before matching begins, and contains the set of
|
/// `into` is cleared before matching begins, and contains the set of
|
||||||
/// sequence numbers (in ascending order) after matching ends. If no globs
|
/// sequence numbers (in ascending order) after matching ends. If no globs
|
||||||
/// were matched, then `into` will be empty.
|
/// were matched, then `into` will be empty.
|
||||||
///
|
///
|
||||||
@@ -374,7 +374,7 @@ impl GlobSet {
|
|||||||
/// cost of preparing a path for matching.
|
/// cost of preparing a path for matching.
|
||||||
pub fn matches_candidate_into(
|
pub fn matches_candidate_into(
|
||||||
&self,
|
&self,
|
||||||
path: &Candidate,
|
path: &Candidate<'_>,
|
||||||
into: &mut Vec<usize>,
|
into: &mut Vec<usize>,
|
||||||
) {
|
) {
|
||||||
into.clear();
|
into.clear();
|
||||||
@@ -456,6 +456,13 @@ impl GlobSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for GlobSet {
|
||||||
|
/// Create a default empty GlobSet.
|
||||||
|
fn default() -> Self {
|
||||||
|
GlobSet::empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// GlobSetBuilder builds a group of patterns that can be used to
|
/// GlobSetBuilder builds a group of patterns that can be used to
|
||||||
/// simultaneously match a file path.
|
/// simultaneously match a file path.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -536,7 +543,7 @@ enum GlobSetMatchStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GlobSetMatchStrategy {
|
impl GlobSetMatchStrategy {
|
||||||
fn is_match(&self, candidate: &Candidate) -> bool {
|
fn is_match(&self, candidate: &Candidate<'_>) -> bool {
|
||||||
use self::GlobSetMatchStrategy::*;
|
use self::GlobSetMatchStrategy::*;
|
||||||
match *self {
|
match *self {
|
||||||
Literal(ref s) => s.is_match(candidate),
|
Literal(ref s) => s.is_match(candidate),
|
||||||
@@ -549,7 +556,11 @@ impl GlobSetMatchStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
|
fn matches_into(
|
||||||
|
&self,
|
||||||
|
candidate: &Candidate<'_>,
|
||||||
|
matches: &mut Vec<usize>,
|
||||||
|
) {
|
||||||
use self::GlobSetMatchStrategy::*;
|
use self::GlobSetMatchStrategy::*;
|
||||||
match *self {
|
match *self {
|
||||||
Literal(ref s) => s.matches_into(candidate, matches),
|
Literal(ref s) => s.matches_into(candidate, matches),
|
||||||
@@ -575,12 +586,16 @@ impl LiteralStrategy {
|
|||||||
self.0.entry(lit.into_bytes()).or_insert(vec![]).push(global_index);
|
self.0.entry(lit.into_bytes()).or_insert(vec![]).push(global_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_match(&self, candidate: &Candidate) -> bool {
|
fn is_match(&self, candidate: &Candidate<'_>) -> bool {
|
||||||
self.0.contains_key(candidate.path.as_bytes())
|
self.0.contains_key(candidate.path.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
|
fn matches_into(
|
||||||
|
&self,
|
||||||
|
candidate: &Candidate<'_>,
|
||||||
|
matches: &mut Vec<usize>,
|
||||||
|
) {
|
||||||
if let Some(hits) = self.0.get(candidate.path.as_bytes()) {
|
if let Some(hits) = self.0.get(candidate.path.as_bytes()) {
|
||||||
matches.extend(hits);
|
matches.extend(hits);
|
||||||
}
|
}
|
||||||
@@ -599,7 +614,7 @@ impl BasenameLiteralStrategy {
|
|||||||
self.0.entry(lit.into_bytes()).or_insert(vec![]).push(global_index);
|
self.0.entry(lit.into_bytes()).or_insert(vec![]).push(global_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_match(&self, candidate: &Candidate) -> bool {
|
fn is_match(&self, candidate: &Candidate<'_>) -> bool {
|
||||||
if candidate.basename.is_empty() {
|
if candidate.basename.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -607,7 +622,11 @@ impl BasenameLiteralStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
|
fn matches_into(
|
||||||
|
&self,
|
||||||
|
candidate: &Candidate<'_>,
|
||||||
|
matches: &mut Vec<usize>,
|
||||||
|
) {
|
||||||
if candidate.basename.is_empty() {
|
if candidate.basename.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -629,7 +648,7 @@ impl ExtensionStrategy {
|
|||||||
self.0.entry(ext.into_bytes()).or_insert(vec![]).push(global_index);
|
self.0.entry(ext.into_bytes()).or_insert(vec![]).push(global_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_match(&self, candidate: &Candidate) -> bool {
|
fn is_match(&self, candidate: &Candidate<'_>) -> bool {
|
||||||
if candidate.ext.is_empty() {
|
if candidate.ext.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -637,7 +656,11 @@ impl ExtensionStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
|
fn matches_into(
|
||||||
|
&self,
|
||||||
|
candidate: &Candidate<'_>,
|
||||||
|
matches: &mut Vec<usize>,
|
||||||
|
) {
|
||||||
if candidate.ext.is_empty() {
|
if candidate.ext.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -655,7 +678,7 @@ struct PrefixStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PrefixStrategy {
|
impl PrefixStrategy {
|
||||||
fn is_match(&self, candidate: &Candidate) -> bool {
|
fn is_match(&self, candidate: &Candidate<'_>) -> bool {
|
||||||
let path = candidate.path_prefix(self.longest);
|
let path = candidate.path_prefix(self.longest);
|
||||||
for m in self.matcher.find_overlapping_iter(path) {
|
for m in self.matcher.find_overlapping_iter(path) {
|
||||||
if m.start() == 0 {
|
if m.start() == 0 {
|
||||||
@@ -665,7 +688,11 @@ impl PrefixStrategy {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
|
fn matches_into(
|
||||||
|
&self,
|
||||||
|
candidate: &Candidate<'_>,
|
||||||
|
matches: &mut Vec<usize>,
|
||||||
|
) {
|
||||||
let path = candidate.path_prefix(self.longest);
|
let path = candidate.path_prefix(self.longest);
|
||||||
for m in self.matcher.find_overlapping_iter(path) {
|
for m in self.matcher.find_overlapping_iter(path) {
|
||||||
if m.start() == 0 {
|
if m.start() == 0 {
|
||||||
@@ -683,7 +710,7 @@ struct SuffixStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SuffixStrategy {
|
impl SuffixStrategy {
|
||||||
fn is_match(&self, candidate: &Candidate) -> bool {
|
fn is_match(&self, candidate: &Candidate<'_>) -> bool {
|
||||||
let path = candidate.path_suffix(self.longest);
|
let path = candidate.path_suffix(self.longest);
|
||||||
for m in self.matcher.find_overlapping_iter(path) {
|
for m in self.matcher.find_overlapping_iter(path) {
|
||||||
if m.end() == path.len() {
|
if m.end() == path.len() {
|
||||||
@@ -693,7 +720,11 @@ impl SuffixStrategy {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
|
fn matches_into(
|
||||||
|
&self,
|
||||||
|
candidate: &Candidate<'_>,
|
||||||
|
matches: &mut Vec<usize>,
|
||||||
|
) {
|
||||||
let path = candidate.path_suffix(self.longest);
|
let path = candidate.path_suffix(self.longest);
|
||||||
for m in self.matcher.find_overlapping_iter(path) {
|
for m in self.matcher.find_overlapping_iter(path) {
|
||||||
if m.end() == path.len() {
|
if m.end() == path.len() {
|
||||||
@@ -707,7 +738,7 @@ impl SuffixStrategy {
|
|||||||
struct RequiredExtensionStrategy(HashMap<Vec<u8>, Vec<(usize, Regex)>, Fnv>);
|
struct RequiredExtensionStrategy(HashMap<Vec<u8>, Vec<(usize, Regex)>, Fnv>);
|
||||||
|
|
||||||
impl RequiredExtensionStrategy {
|
impl RequiredExtensionStrategy {
|
||||||
fn is_match(&self, candidate: &Candidate) -> bool {
|
fn is_match(&self, candidate: &Candidate<'_>) -> bool {
|
||||||
if candidate.ext.is_empty() {
|
if candidate.ext.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -725,7 +756,11 @@ impl RequiredExtensionStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
|
fn matches_into(
|
||||||
|
&self,
|
||||||
|
candidate: &Candidate<'_>,
|
||||||
|
matches: &mut Vec<usize>,
|
||||||
|
) {
|
||||||
if candidate.ext.is_empty() {
|
if candidate.ext.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -746,11 +781,15 @@ struct RegexSetStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RegexSetStrategy {
|
impl RegexSetStrategy {
|
||||||
fn is_match(&self, candidate: &Candidate) -> bool {
|
fn is_match(&self, candidate: &Candidate<'_>) -> bool {
|
||||||
self.matcher.is_match(candidate.path.as_bytes())
|
self.matcher.is_match(candidate.path.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_into(&self, candidate: &Candidate, matches: &mut Vec<usize>) {
|
fn matches_into(
|
||||||
|
&self,
|
||||||
|
candidate: &Candidate<'_>,
|
||||||
|
matches: &mut Vec<usize>,
|
||||||
|
) {
|
||||||
for i in self.matcher.matches(candidate.path.as_bytes()) {
|
for i in self.matcher.matches(candidate.path.as_bytes()) {
|
||||||
matches.push(self.map[i]);
|
matches.push(self.map[i]);
|
||||||
}
|
}
|
||||||
@@ -833,8 +872,8 @@ impl RequiredExtensionStrategyBuilder {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::GlobSetBuilder;
|
use super::{GlobSet, GlobSetBuilder};
|
||||||
use glob::Glob;
|
use crate::glob::Glob;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_works() {
|
fn set_works() {
|
||||||
@@ -863,4 +902,11 @@ mod tests {
|
|||||||
assert!(!set.is_match(""));
|
assert!(!set.is_match(""));
|
||||||
assert!(!set.is_match("a"));
|
assert!(!set.is_match("a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_set_is_empty_works() {
|
||||||
|
let set: GlobSet = Default::default();
|
||||||
|
assert!(!set.is_match(""));
|
||||||
|
assert!(!set.is_match("a"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ pub fn file_name_ext<'a>(name: &Cow<'a, [u8]>) -> Option<Cow<'a, [u8]>> {
|
|||||||
/// Normalizes a path to use `/` as a separator everywhere, even on platforms
|
/// Normalizes a path to use `/` as a separator everywhere, even on platforms
|
||||||
/// that recognize other characters as separators.
|
/// that recognize other characters as separators.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn normalize_path(path: Cow<[u8]>) -> Cow<[u8]> {
|
pub fn normalize_path(path: Cow<'_, [u8]>) -> Cow<'_, [u8]> {
|
||||||
// UNIX only uses /, so we're good.
|
// UNIX only uses /, so we're good.
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use serde::de::Error;
|
use serde::de::Error;
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
use Glob;
|
use crate::Glob;
|
||||||
|
|
||||||
impl Serialize for Glob {
|
impl Serialize for Glob {
|
||||||
fn serialize<S: Serializer>(
|
fn serialize<S: Serializer>(
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep"
|
name = "grep"
|
||||||
version = "0.2.5" #:version
|
version = "0.2.10" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Fast line oriented regex searching as a library.
|
Fast line oriented regex searching as a library.
|
||||||
"""
|
"""
|
||||||
documentation = "http://burntsushi.net/rustdoc/grep/"
|
documentation = "https://docs.rs/grep"
|
||||||
homepage = "https://github.com/BurntSushi/ripgrep/tree/master/crates/grep"
|
homepage = "https://github.com/BurntSushi/ripgrep/tree/master/crates/grep"
|
||||||
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/grep"
|
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/grep"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["regex", "grep", "egrep", "search", "pattern"]
|
keywords = ["regex", "grep", "egrep", "search", "pattern"]
|
||||||
license = "Unlicense/MIT"
|
license = "Unlicense OR MIT"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
grep-cli = { version = "0.1.4", path = "../cli" }
|
grep-cli = { version = "0.1.6", path = "../cli" }
|
||||||
grep-matcher = { version = "0.1.4", path = "../matcher" }
|
grep-matcher = { version = "0.1.5", path = "../matcher" }
|
||||||
grep-pcre2 = { version = "0.1.4", path = "../pcre2", optional = true }
|
grep-pcre2 = { version = "0.1.5", path = "../pcre2", optional = true }
|
||||||
grep-printer = { version = "0.1.4", path = "../printer" }
|
grep-printer = { version = "0.1.6", path = "../printer" }
|
||||||
grep-regex = { version = "0.1.6", path = "../regex" }
|
grep-regex = { version = "0.1.10", path = "../regex" }
|
||||||
grep-searcher = { version = "0.1.7", path = "../searcher" }
|
grep-searcher = { version = "0.1.10", path = "../searcher" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
termcolor = "1.0.4"
|
termcolor = "1.0.4"
|
||||||
|
|||||||
@@ -2,11 +2,10 @@ grep
|
|||||||
----
|
----
|
||||||
ripgrep, as a library.
|
ripgrep, as a library.
|
||||||
|
|
||||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
[](https://github.com/BurntSushi/ripgrep/actions)
|
||||||
[](https://ci.appveyor.com/project/BurntSushi/ripgrep)
|
|
||||||
[](https://crates.io/crates/grep)
|
[](https://crates.io/crates/grep)
|
||||||
|
|
||||||
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
|
||||||
|
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
@@ -27,12 +26,6 @@ Add this to your `Cargo.toml`:
|
|||||||
grep = "0.2"
|
grep = "0.2"
|
||||||
```
|
```
|
||||||
|
|
||||||
and this to your crate root:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
extern crate grep;
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
extern crate grep;
|
|
||||||
extern crate termcolor;
|
|
||||||
extern crate walkdir;
|
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.4.12" #:version
|
version = "0.4.19" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
A fast library for efficiently matching ignore files such as `.gitignore`
|
A fast library for efficiently matching ignore files such as `.gitignore`
|
||||||
@@ -11,16 +11,15 @@ homepage = "https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore"
|
|||||||
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore"
|
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["glob", "ignore", "gitignore", "pattern", "file"]
|
keywords = ["glob", "ignore", "gitignore", "pattern", "file"]
|
||||||
license = "Unlicense/MIT"
|
license = "Unlicense OR MIT"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
bench = false
|
bench = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
crossbeam-channel = "0.4.0"
|
globset = { version = "0.4.10", path = "../globset" }
|
||||||
crossbeam-utils = "0.7.0"
|
|
||||||
globset = { version = "0.4.3", path = "../globset" }
|
|
||||||
lazy_static = "1.1"
|
lazy_static = "1.1"
|
||||||
log = "0.4.5"
|
log = "0.4.5"
|
||||||
memchr = "2.1"
|
memchr = "2.1"
|
||||||
@@ -32,5 +31,8 @@ walkdir = "2.2.7"
|
|||||||
[target.'cfg(windows)'.dependencies.winapi-util]
|
[target.'cfg(windows)'.dependencies.winapi-util]
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
crossbeam-channel = "0.5.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
simd-accel = ["globset/simd-accel"]
|
simd-accel = ["globset/simd-accel"]
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ The ignore crate provides a fast recursive directory iterator that respects
|
|||||||
various filters such as globs, file types and `.gitignore` files. This crate
|
various filters such as globs, file types and `.gitignore` files. This crate
|
||||||
also provides lower level direct access to gitignore and file type matchers.
|
also provides lower level direct access to gitignore and file type matchers.
|
||||||
|
|
||||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
[](https://github.com/BurntSushi/ripgrep/actions)
|
||||||
[](https://ci.appveyor.com/project/BurntSushi/ripgrep)
|
|
||||||
[](https://crates.io/crates/ignore)
|
[](https://crates.io/crates/ignore)
|
||||||
|
|
||||||
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
@@ -23,12 +22,6 @@ Add this to your `Cargo.toml`:
|
|||||||
ignore = "0.4"
|
ignore = "0.4"
|
||||||
```
|
```
|
||||||
|
|
||||||
and this to your crate root:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
extern crate ignore;
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
This example shows the most basic usage of this crate. This code will
|
This example shows the most basic usage of this crate. This code will
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
extern crate crossbeam_channel as channel;
|
|
||||||
extern crate ignore;
|
|
||||||
extern crate walkdir;
|
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@@ -14,7 +10,7 @@ fn main() {
|
|||||||
let mut path = env::args().nth(1).unwrap();
|
let mut path = env::args().nth(1).unwrap();
|
||||||
let mut parallel = false;
|
let mut parallel = false;
|
||||||
let mut simple = false;
|
let mut simple = false;
|
||||||
let (tx, rx) = channel::bounded::<DirEntry>(100);
|
let (tx, rx) = crossbeam_channel::bounded::<DirEntry>(100);
|
||||||
if path == "parallel" {
|
if path == "parallel" {
|
||||||
path = env::args().nth(2).unwrap();
|
path = env::args().nth(2).unwrap();
|
||||||
parallel = true;
|
parallel = true;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
/// types to each invocation of ripgrep with the '--type-add' flag.
|
/// types to each invocation of ripgrep with the '--type-add' flag.
|
||||||
///
|
///
|
||||||
/// If you would like to add or improve this list, please file a PR:
|
/// If you would like to add or improve this list, please file a PR:
|
||||||
/// https://github.com/BurntSushi/ripgrep
|
/// <https://github.com/BurntSushi/ripgrep>.
|
||||||
///
|
///
|
||||||
/// Please try to keep this list sorted lexicographically and wrapped to 79
|
/// Please try to keep this list sorted lexicographically and wrapped to 79
|
||||||
/// columns (inclusive).
|
/// columns (inclusive).
|
||||||
@@ -16,18 +16,24 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
|
|||||||
("asciidoc", &["*.adoc", "*.asc", "*.asciidoc"]),
|
("asciidoc", &["*.adoc", "*.asc", "*.asciidoc"]),
|
||||||
("asm", &["*.asm", "*.s", "*.S"]),
|
("asm", &["*.asm", "*.s", "*.S"]),
|
||||||
("asp", &[
|
("asp", &[
|
||||||
"*.aspx", "*.aspx.cs", "*.aspx.cs", "*.ascx", "*.ascx.cs", "*.ascx.vb",
|
"*.aspx", "*.aspx.cs", "*.aspx.vb", "*.ascx", "*.ascx.cs",
|
||||||
|
"*.ascx.vb", "*.asp"
|
||||||
]),
|
]),
|
||||||
("ats", &["*.ats", "*.dats", "*.sats", "*.hats"]),
|
("ats", &["*.ats", "*.dats", "*.sats", "*.hats"]),
|
||||||
("avro", &["*.avdl", "*.avpr", "*.avsc"]),
|
("avro", &["*.avdl", "*.avpr", "*.avsc"]),
|
||||||
("awk", &["*.awk"]),
|
("awk", &["*.awk"]),
|
||||||
("bazel", &["*.bzl", "WORKSPACE", "BUILD", "BUILD.bazel"]),
|
("bazel", &[
|
||||||
|
"*.bazel", "*.bzl", "*.BUILD", "*.bazelrc", "BUILD", "MODULE.bazel",
|
||||||
|
"WORKSPACE", "WORKSPACE.bazel",
|
||||||
|
]),
|
||||||
("bitbake", &["*.bb", "*.bbappend", "*.bbclass", "*.conf", "*.inc"]),
|
("bitbake", &["*.bb", "*.bbappend", "*.bbclass", "*.conf", "*.inc"]),
|
||||||
("brotli", &["*.br"]),
|
("brotli", &["*.br"]),
|
||||||
("buildstream", &["*.bst"]),
|
("buildstream", &["*.bst"]),
|
||||||
("bzip2", &["*.bz2", "*.tbz2"]),
|
("bzip2", &["*.bz2", "*.tbz2"]),
|
||||||
("c", &["*.[chH]", "*.[chH].in", "*.cats"]),
|
("c", &["*.[chH]", "*.[chH].in", "*.cats"]),
|
||||||
("cabal", &["*.cabal"]),
|
("cabal", &["*.cabal"]),
|
||||||
|
("candid", &["*.did"]),
|
||||||
|
("carp", &["*.carp"]),
|
||||||
("cbor", &["*.cbor"]),
|
("cbor", &["*.cbor"]),
|
||||||
("ceylon", &["*.ceylon"]),
|
("ceylon", &["*.ceylon"]),
|
||||||
("clojure", &["*.clj", "*.cljc", "*.cljs", "*.cljx"]),
|
("clojure", &["*.clj", "*.cljc", "*.cljs", "*.cljx"]),
|
||||||
@@ -40,48 +46,59 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
|
|||||||
"*.[ChH].in", "*.cc.in", "*.[ch]pp.in", "*.[ch]xx.in", "*.hh.in",
|
"*.[ChH].in", "*.cc.in", "*.[ch]pp.in", "*.[ch]xx.in", "*.hh.in",
|
||||||
]),
|
]),
|
||||||
("creole", &["*.creole"]),
|
("creole", &["*.creole"]),
|
||||||
("crystal", &["Projectfile", "*.cr"]),
|
("crystal", &["Projectfile", "*.cr", "*.ecr", "shard.yml"]),
|
||||||
("cs", &["*.cs"]),
|
("cs", &["*.cs"]),
|
||||||
("csharp", &["*.cs"]),
|
("csharp", &["*.cs"]),
|
||||||
("cshtml", &["*.cshtml"]),
|
("cshtml", &["*.cshtml"]),
|
||||||
("css", &["*.css", "*.scss"]),
|
("css", &["*.css", "*.scss"]),
|
||||||
("csv", &["*.csv"]),
|
("csv", &["*.csv"]),
|
||||||
|
("cuda", &["*.cu", "*.cuh"]),
|
||||||
("cython", &["*.pyx", "*.pxi", "*.pxd"]),
|
("cython", &["*.pyx", "*.pxi", "*.pxd"]),
|
||||||
("d", &["*.d"]),
|
("d", &["*.d"]),
|
||||||
("dart", &["*.dart"]),
|
("dart", &["*.dart"]),
|
||||||
|
("devicetree", &["*.dts", "*.dtsi"]),
|
||||||
("dhall", &["*.dhall"]),
|
("dhall", &["*.dhall"]),
|
||||||
("diff", &["*.patch", "*.diff"]),
|
("diff", &["*.patch", "*.diff"]),
|
||||||
("docker", &["*Dockerfile*"]),
|
("docker", &["*Dockerfile*"]),
|
||||||
|
("dts", &["*.dts", "*.dtsi"]),
|
||||||
|
("dvc", &["Dvcfile", "*.dvc"]),
|
||||||
|
("ebuild", &["*.ebuild"]),
|
||||||
("edn", &["*.edn"]),
|
("edn", &["*.edn"]),
|
||||||
("elisp", &["*.el"]),
|
("elisp", &["*.el"]),
|
||||||
("elixir", &["*.ex", "*.eex", "*.exs"]),
|
("elixir", &["*.ex", "*.eex", "*.exs"]),
|
||||||
("elm", &["*.elm"]),
|
("elm", &["*.elm"]),
|
||||||
("erb", &["*.erb"]),
|
("erb", &["*.erb"]),
|
||||||
("erlang", &["*.erl", "*.hrl"]),
|
("erlang", &["*.erl", "*.hrl"]),
|
||||||
|
("fennel", &["*.fnl"]),
|
||||||
("fidl", &["*.fidl"]),
|
("fidl", &["*.fidl"]),
|
||||||
("fish", &["*.fish"]),
|
("fish", &["*.fish"]),
|
||||||
|
("flatbuffers", &["*.fbs"]),
|
||||||
("fortran", &[
|
("fortran", &[
|
||||||
"*.f", "*.F", "*.f77", "*.F77", "*.pfo",
|
"*.f", "*.F", "*.f77", "*.F77", "*.pfo",
|
||||||
"*.f90", "*.F90", "*.f95", "*.F95",
|
"*.f90", "*.F90", "*.f95", "*.F95",
|
||||||
]),
|
]),
|
||||||
("fsharp", &["*.fs", "*.fsx", "*.fsi"]),
|
("fsharp", &["*.fs", "*.fsx", "*.fsi"]),
|
||||||
|
("fut", &["*.fut"]),
|
||||||
("gap", &["*.g", "*.gap", "*.gi", "*.gd", "*.tst"]),
|
("gap", &["*.g", "*.gap", "*.gi", "*.gd", "*.tst"]),
|
||||||
("gn", &["*.gn", "*.gni"]),
|
("gn", &["*.gn", "*.gni"]),
|
||||||
("go", &["*.go"]),
|
("go", &["*.go"]),
|
||||||
("gradle", &["*.gradle"]),
|
("gradle", &["*.gradle"]),
|
||||||
("groovy", &["*.groovy", "*.gradle"]),
|
("groovy", &["*.groovy", "*.gradle"]),
|
||||||
("gzip", &["*.gz", "*.tgz"]),
|
("gzip", &["*.gz", "*.tgz"]),
|
||||||
("h", &["*.h", "*.hpp"]),
|
("h", &["*.h", "*.hh", "*.hpp"]),
|
||||||
("haml", &["*.haml"]),
|
("haml", &["*.haml"]),
|
||||||
|
("hare", &["*.ha"]),
|
||||||
("haskell", &["*.hs", "*.lhs", "*.cpphs", "*.c2hs", "*.hsc"]),
|
("haskell", &["*.hs", "*.lhs", "*.cpphs", "*.c2hs", "*.hsc"]),
|
||||||
("hbs", &["*.hbs"]),
|
("hbs", &["*.hbs"]),
|
||||||
("hs", &["*.hs", "*.lhs"]),
|
("hs", &["*.hs", "*.lhs"]),
|
||||||
("html", &["*.htm", "*.html", "*.ejs"]),
|
("html", &["*.htm", "*.html", "*.ejs"]),
|
||||||
|
("hy", &["*.hy"]),
|
||||||
("idris", &["*.idr", "*.lidr"]),
|
("idris", &["*.idr", "*.lidr"]),
|
||||||
|
("janet", &["*.janet"]),
|
||||||
("java", &["*.java", "*.jsp", "*.jspx", "*.properties"]),
|
("java", &["*.java", "*.jsp", "*.jspx", "*.properties"]),
|
||||||
("jinja", &["*.j2", "*.jinja", "*.jinja2"]),
|
("jinja", &["*.j2", "*.jinja", "*.jinja2"]),
|
||||||
("jl", &["*.jl"]),
|
("jl", &["*.jl"]),
|
||||||
("js", &["*.js", "*.jsx", "*.vue"]),
|
("js", &["*.js", "*.jsx", "*.vue", "*.cjs", "*.mjs"]),
|
||||||
("json", &["*.json", "composer.lock"]),
|
("json", &["*.json", "composer.lock"]),
|
||||||
("jsonl", &["*.jsonl"]),
|
("jsonl", &["*.jsonl"]),
|
||||||
("julia", &["*.jl"]),
|
("julia", &["*.jl"]),
|
||||||
@@ -116,6 +133,7 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
|
|||||||
"MPL-*[0-9]*",
|
"MPL-*[0-9]*",
|
||||||
"OFL-*[0-9]*",
|
"OFL-*[0-9]*",
|
||||||
]),
|
]),
|
||||||
|
("lilypond", &["*.ly", "*.ily"]),
|
||||||
("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]),
|
("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]),
|
||||||
("lock", &["*.lock", "package-lock.json"]),
|
("lock", &["*.lock", "package-lock.json"]),
|
||||||
("log", &["*.log"]),
|
("log", &["*.log"]),
|
||||||
@@ -131,11 +149,15 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
|
|||||||
]),
|
]),
|
||||||
("mako", &["*.mako", "*.mao"]),
|
("mako", &["*.mako", "*.mao"]),
|
||||||
("man", &["*.[0-9lnpx]", "*.[0-9][cEFMmpSx]"]),
|
("man", &["*.[0-9lnpx]", "*.[0-9][cEFMmpSx]"]),
|
||||||
("markdown", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
|
("markdown", &["*.markdown", "*.md", "*.mdown", "*.mkd", "*.mkdn"]),
|
||||||
("matlab", &["*.m"]),
|
("matlab", &["*.m"]),
|
||||||
("md", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
|
("md", &["*.markdown", "*.md", "*.mdown", "*.mkd", "*.mkdn"]),
|
||||||
|
("meson", &["meson.build", "meson_options.txt"]),
|
||||||
|
("minified", &["*.min.html", "*.min.css", "*.min.js"]),
|
||||||
|
("mint", &["*.mint"]),
|
||||||
("mk", &["mkfile"]),
|
("mk", &["mkfile"]),
|
||||||
("ml", &["*.ml"]),
|
("ml", &["*.ml"]),
|
||||||
|
("motoko", &["*.mo"]),
|
||||||
("msbuild", &[
|
("msbuild", &[
|
||||||
"*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets",
|
"*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets",
|
||||||
]),
|
]),
|
||||||
@@ -145,25 +167,41 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
|
|||||||
("objcpp", &["*.h", "*.mm"]),
|
("objcpp", &["*.h", "*.mm"]),
|
||||||
("ocaml", &["*.ml", "*.mli", "*.mll", "*.mly"]),
|
("ocaml", &["*.ml", "*.mli", "*.mll", "*.mly"]),
|
||||||
("org", &["*.org", "*.org_archive"]),
|
("org", &["*.org", "*.org_archive"]),
|
||||||
|
("pants", &["BUILD"]),
|
||||||
("pascal", &["*.pas", "*.dpr", "*.lpr", "*.pp", "*.inc"]),
|
("pascal", &["*.pas", "*.dpr", "*.lpr", "*.pp", "*.inc"]),
|
||||||
("pdf", &["*.pdf"]),
|
("pdf", &["*.pdf"]),
|
||||||
("perl", &["*.perl", "*.pl", "*.PL", "*.plh", "*.plx", "*.pm", "*.t"]),
|
("perl", &["*.perl", "*.pl", "*.PL", "*.plh", "*.plx", "*.pm", "*.t"]),
|
||||||
("php", &["*.php", "*.php3", "*.php4", "*.php5", "*.phtml"]),
|
("php", &[
|
||||||
|
// note that PHP 6 doesn't exist
|
||||||
|
// See: https://wiki.php.net/rfc/php6
|
||||||
|
"*.php", "*.php3", "*.php4", "*.php5", "*.php7", "*.php8",
|
||||||
|
"*.pht", "*.phtml"
|
||||||
|
]),
|
||||||
|
("po", &["*.po"]),
|
||||||
("pod", &["*.pod"]),
|
("pod", &["*.pod"]),
|
||||||
("postscript", &["*.eps", "*.ps"]),
|
("postscript", &["*.eps", "*.ps"]),
|
||||||
("protobuf", &["*.proto"]),
|
("protobuf", &["*.proto"]),
|
||||||
("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]),
|
("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]),
|
||||||
("puppet", &["*.erb", "*.pp", "*.rb"]),
|
("puppet", &["*.epp", "*.erb", "*.pp", "*.rb"]),
|
||||||
("purs", &["*.purs"]),
|
("purs", &["*.purs"]),
|
||||||
("py", &["*.py"]),
|
("py", &["*.py"]),
|
||||||
("qmake", &["*.pro", "*.pri", "*.prf"]),
|
("qmake", &["*.pro", "*.pri", "*.prf"]),
|
||||||
("qml", &["*.qml"]),
|
("qml", &["*.qml"]),
|
||||||
("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
|
("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
|
||||||
|
("racket", &["*.rkt"]),
|
||||||
("rdoc", &["*.rdoc"]),
|
("rdoc", &["*.rdoc"]),
|
||||||
("readme", &["README*", "*README"]),
|
("readme", &["README*", "*README"]),
|
||||||
|
("reasonml", &["*.re", "*.rei"]),
|
||||||
|
("red", &["*.r", "*.red", "*.reds"]),
|
||||||
|
("rescript", &["*.res", "*.resi"]),
|
||||||
("robot", &["*.robot"]),
|
("robot", &["*.robot"]),
|
||||||
("rst", &["*.rst"]),
|
("rst", &["*.rst"]),
|
||||||
("ruby", &["Gemfile", "*.gemspec", ".irbrc", "Rakefile", "*.rb"]),
|
("ruby", &[
|
||||||
|
// Idiomatic files
|
||||||
|
"config.ru", "Gemfile", ".irbrc", "Rakefile",
|
||||||
|
// Extensions
|
||||||
|
"*.gemspec", "*.rb", "*.rbw"
|
||||||
|
]),
|
||||||
("rust", &["*.rs"]),
|
("rust", &["*.rs"]),
|
||||||
("sass", &["*.sass", "*.scss"]),
|
("sass", &["*.sass", "*.scss"]),
|
||||||
("scala", &["*.scala", "*.sbt"]),
|
("scala", &["*.scala", "*.sbt"]),
|
||||||
@@ -193,6 +231,7 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
|
|||||||
("slim", &["*.skim", "*.slim", "*.slime"]),
|
("slim", &["*.skim", "*.slim", "*.slime"]),
|
||||||
("smarty", &["*.tpl"]),
|
("smarty", &["*.tpl"]),
|
||||||
("sml", &["*.sml", "*.sig"]),
|
("sml", &["*.sml", "*.sig"]),
|
||||||
|
("solidity", &["*.sol"]),
|
||||||
("soy", &["*.soy"]),
|
("soy", &["*.soy"]),
|
||||||
("spark", &["*.spark"]),
|
("spark", &["*.spark"]),
|
||||||
("spec", &["*.spec"]),
|
("spec", &["*.spec"]),
|
||||||
@@ -210,20 +249,26 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
|
|||||||
("taskpaper", &["*.taskpaper"]),
|
("taskpaper", &["*.taskpaper"]),
|
||||||
("tcl", &["*.tcl"]),
|
("tcl", &["*.tcl"]),
|
||||||
("tex", &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib", "*.dtx", "*.ins"]),
|
("tex", &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib", "*.dtx", "*.ins"]),
|
||||||
|
("texinfo", &["*.texi"]),
|
||||||
("textile", &["*.textile"]),
|
("textile", &["*.textile"]),
|
||||||
("tf", &["*.tf"]),
|
("tf", &["*.tf"]),
|
||||||
("thrift", &["*.thrift"]),
|
("thrift", &["*.thrift"]),
|
||||||
("toml", &["*.toml", "Cargo.lock"]),
|
("toml", &["*.toml", "Cargo.lock"]),
|
||||||
("ts", &["*.ts", "*.tsx"]),
|
("ts", &["*.ts", "*.tsx", "*.cts", "*.mts"]),
|
||||||
("twig", &["*.twig"]),
|
("twig", &["*.twig"]),
|
||||||
("txt", &["*.txt"]),
|
("txt", &["*.txt"]),
|
||||||
("typoscript", &["*.typoscript", "*.ts"]),
|
("typoscript", &["*.typoscript", "*.ts"]),
|
||||||
("vala", &["*.vala"]),
|
("vala", &["*.vala"]),
|
||||||
("vb", &["*.vb"]),
|
("vb", &["*.vb"]),
|
||||||
|
("vcl", &["*.vcl"]),
|
||||||
("verilog", &["*.v", "*.vh", "*.sv", "*.svh"]),
|
("verilog", &["*.v", "*.vh", "*.sv", "*.svh"]),
|
||||||
("vhdl", &["*.vhd", "*.vhdl"]),
|
("vhdl", &["*.vhd", "*.vhdl"]),
|
||||||
("vim", &["*.vim"]),
|
("vim", &[
|
||||||
("vimscript", &["*.vim"]),
|
"*.vim", ".vimrc", ".gvimrc", "vimrc", "gvimrc", "_vimrc", "_gvimrc",
|
||||||
|
]),
|
||||||
|
("vimscript", &[
|
||||||
|
"*.vim", ".vimrc", ".gvimrc", "vimrc", "gvimrc", "_vimrc", "_gvimrc",
|
||||||
|
]),
|
||||||
("webidl", &["*.idl", "*.webidl", "*.widl"]),
|
("webidl", &["*.idl", "*.webidl", "*.widl"]),
|
||||||
("wiki", &["*.mediawiki", "*.wiki"]),
|
("wiki", &["*.mediawiki", "*.wiki"]),
|
||||||
("xml", &[
|
("xml", &[
|
||||||
@@ -233,6 +278,8 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
|
|||||||
("xz", &["*.xz", "*.txz"]),
|
("xz", &["*.xz", "*.txz"]),
|
||||||
("yacc", &["*.y"]),
|
("yacc", &["*.y"]),
|
||||||
("yaml", &["*.yaml", "*.yml"]),
|
("yaml", &["*.yaml", "*.yml"]),
|
||||||
|
("yang", &["*.yang"]),
|
||||||
|
("z", &["*.Z"]),
|
||||||
("zig", &["*.zig"]),
|
("zig", &["*.zig"]),
|
||||||
("zsh", &[
|
("zsh", &[
|
||||||
".zshenv", "zshenv",
|
".zshenv", "zshenv",
|
||||||
@@ -244,3 +291,26 @@ pub const DEFAULT_TYPES: &[(&str, &[&str])] = &[
|
|||||||
]),
|
]),
|
||||||
("zstd", &["*.zst", "*.zstd"]),
|
("zstd", &["*.zst", "*.zstd"]),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::DEFAULT_TYPES;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_types_are_sorted() {
|
||||||
|
let mut names = DEFAULT_TYPES.iter().map(|(name, _exts)| name);
|
||||||
|
|
||||||
|
let Some(mut previous_name) = names.next() else { return; };
|
||||||
|
|
||||||
|
for name in names {
|
||||||
|
assert!(
|
||||||
|
name > previous_name,
|
||||||
|
r#""{}" should be sorted before "{}" in `DEFAULT_TYPES`"#,
|
||||||
|
name,
|
||||||
|
previous_name
|
||||||
|
);
|
||||||
|
|
||||||
|
previous_name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ use std::io::{self, BufRead};
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use gitignore::{self, Gitignore, GitignoreBuilder};
|
use crate::gitignore::{self, Gitignore, GitignoreBuilder};
|
||||||
use overrides::{self, Override};
|
use crate::overrides::{self, Override};
|
||||||
use pathutil::{is_hidden, strip_prefix};
|
use crate::pathutil::{is_hidden, strip_prefix};
|
||||||
use types::{self, Types};
|
use crate::types::{self, Types};
|
||||||
use walk::DirEntry;
|
use crate::walk::DirEntry;
|
||||||
use {Error, Match, PartialErrorBuilder};
|
use crate::{Error, Match, PartialErrorBuilder};
|
||||||
|
|
||||||
/// IgnoreMatch represents information about where a match came from when using
|
/// IgnoreMatch represents information about where a match came from when using
|
||||||
/// the `Ignore` matcher.
|
/// the `Ignore` matcher.
|
||||||
@@ -202,7 +202,8 @@ impl Ignore {
|
|||||||
errs.maybe_push(err);
|
errs.maybe_push(err);
|
||||||
igtmp.is_absolute_parent = true;
|
igtmp.is_absolute_parent = true;
|
||||||
igtmp.absolute_base = Some(absolute_base.clone());
|
igtmp.absolute_base = Some(absolute_base.clone());
|
||||||
igtmp.has_git = if self.0.opts.git_ignore {
|
igtmp.has_git =
|
||||||
|
if self.0.opts.require_git && self.0.opts.git_ignore {
|
||||||
parent.join(".git").exists()
|
parent.join(".git").exists()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -231,7 +232,9 @@ impl Ignore {
|
|||||||
|
|
||||||
/// Like add_child, but takes a full path and returns an IgnoreInner.
|
/// Like add_child, but takes a full path and returns an IgnoreInner.
|
||||||
fn add_child_path(&self, dir: &Path) -> (IgnoreInner, Option<Error>) {
|
fn add_child_path(&self, dir: &Path) -> (IgnoreInner, Option<Error>) {
|
||||||
let git_type = if self.0.opts.git_ignore || self.0.opts.git_exclude {
|
let git_type = if self.0.opts.require_git
|
||||||
|
&& (self.0.opts.git_ignore || self.0.opts.git_exclude)
|
||||||
|
{
|
||||||
dir.join(".git").metadata().ok().map(|md| md.file_type())
|
dir.join(".git").metadata().ok().map(|md| md.file_type())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -310,7 +313,7 @@ impl Ignore {
|
|||||||
git_global_matcher: self.0.git_global_matcher.clone(),
|
git_global_matcher: self.0.git_global_matcher.clone(),
|
||||||
git_ignore_matcher: gi_matcher,
|
git_ignore_matcher: gi_matcher,
|
||||||
git_exclude_matcher: gi_exclude_matcher,
|
git_exclude_matcher: gi_exclude_matcher,
|
||||||
has_git: has_git,
|
has_git,
|
||||||
opts: self.0.opts,
|
opts: self.0.opts,
|
||||||
};
|
};
|
||||||
(ig, errs.into_error_option())
|
(ig, errs.into_error_option())
|
||||||
@@ -495,7 +498,7 @@ impl Ignore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over parent ignore matchers, including this one.
|
/// Returns an iterator over parent ignore matchers, including this one.
|
||||||
pub fn parents(&self) -> Parents {
|
pub fn parents(&self) -> Parents<'_> {
|
||||||
Parents(Some(self))
|
Parents(Some(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -581,7 +584,7 @@ impl IgnoreBuilder {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let (gi, err) = builder.build_global();
|
let (gi, err) = builder.build_global();
|
||||||
if let Some(err) = err {
|
if let Some(err) = err {
|
||||||
debug!("{}", err);
|
log::debug!("{}", err);
|
||||||
}
|
}
|
||||||
gi
|
gi
|
||||||
};
|
};
|
||||||
@@ -817,9 +820,7 @@ fn resolve_git_commondir(
|
|||||||
let git_commondir_file = || real_git_dir.join("commondir");
|
let git_commondir_file = || real_git_dir.join("commondir");
|
||||||
let file = match File::open(git_commondir_file()) {
|
let file = match File::open(git_commondir_file()) {
|
||||||
Ok(file) => io::BufReader::new(file),
|
Ok(file) => io::BufReader::new(file),
|
||||||
Err(err) => {
|
Err(_) => return Err(None),
|
||||||
return Err(Some(Error::Io(err).with_path(git_commondir_file())));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let commondir_line = match file.lines().next() {
|
let commondir_line = match file.lines().next() {
|
||||||
Some(Ok(line)) => line,
|
Some(Ok(line)) => line,
|
||||||
@@ -839,13 +840,13 @@ fn resolve_git_commondir(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::{self, Write};
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use dir::IgnoreBuilder;
|
use crate::dir::IgnoreBuilder;
|
||||||
use gitignore::Gitignore;
|
use crate::gitignore::Gitignore;
|
||||||
use tests::TempDir;
|
use crate::tests::TempDir;
|
||||||
use Error;
|
use crate::Error;
|
||||||
|
|
||||||
fn wfile<P: AsRef<Path>>(path: P, contents: &str) {
|
fn wfile<P: AsRef<Path>>(path: P, contents: &str) {
|
||||||
let mut file = File::create(path).unwrap();
|
let mut file = File::create(path).unwrap();
|
||||||
@@ -1172,22 +1173,9 @@ mod tests {
|
|||||||
// missing commondir file
|
// missing commondir file
|
||||||
assert!(fs::remove_file(commondir_path()).is_ok());
|
assert!(fs::remove_file(commondir_path()).is_ok());
|
||||||
let (_, err) = ib.add_child(td.path().join("linked-worktree"));
|
let (_, err) = ib.add_child(td.path().join("linked-worktree"));
|
||||||
assert!(err.is_some());
|
// We squash the error in this case, because it occurs in repositories
|
||||||
assert!(match err {
|
// that are not linked worktrees but have submodules.
|
||||||
Some(Error::WithPath { path, err }) => {
|
assert!(err.is_none());
|
||||||
if path != commondir_path() {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
match *err {
|
|
||||||
Error::Io(ioerr) => {
|
|
||||||
ioerr.kind() == io::ErrorKind::NotFound
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
});
|
|
||||||
|
|
||||||
wfile(td.path().join("linked-worktree/.git"), "garbage");
|
wfile(td.path().join("linked-worktree/.git"), "garbage");
|
||||||
let (_, err) = ib.add_child(td.path().join("linked-worktree"));
|
let (_, err) = ib.add_child(td.path().join("linked-worktree"));
|
||||||
@@ -1195,6 +1183,6 @@ mod tests {
|
|||||||
|
|
||||||
wfile(td.path().join("linked-worktree/.git"), "gitdir: garbage");
|
wfile(td.path().join("linked-worktree/.git"), "gitdir: garbage");
|
||||||
let (_, err) = ib.add_child(td.path().join("linked-worktree"));
|
let (_, err) = ib.add_child(td.path().join("linked-worktree"));
|
||||||
assert!(err.is_some());
|
assert!(err.is_none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ use globset::{Candidate, GlobBuilder, GlobSet, GlobSetBuilder};
|
|||||||
use regex::bytes::Regex;
|
use regex::bytes::Regex;
|
||||||
use thread_local::ThreadLocal;
|
use thread_local::ThreadLocal;
|
||||||
|
|
||||||
use pathutil::{is_file_name, strip_prefix};
|
use crate::pathutil::{is_file_name, strip_prefix};
|
||||||
use {Error, Match, PartialErrorBuilder};
|
use crate::{Error, Match, PartialErrorBuilder};
|
||||||
|
|
||||||
/// Glob represents a single glob in a gitignore file.
|
/// Glob represents a single glob in a gitignore file.
|
||||||
///
|
///
|
||||||
@@ -474,10 +474,13 @@ impl GitignoreBuilder {
|
|||||||
}
|
}
|
||||||
// If it ends with a slash, then this should only match directories,
|
// If it ends with a slash, then this should only match directories,
|
||||||
// but the slash should otherwise not be used while globbing.
|
// but the slash should otherwise not be used while globbing.
|
||||||
if let Some((i, c)) = line.char_indices().rev().nth(0) {
|
if line.as_bytes().last() == Some(&b'/') {
|
||||||
if c == '/' {
|
|
||||||
glob.is_only_dir = true;
|
glob.is_only_dir = true;
|
||||||
line = &line[..i];
|
line = &line[..line.len() - 1];
|
||||||
|
// If the slash was escaped, then remove the escape.
|
||||||
|
// See: https://github.com/BurntSushi/ripgrep/issues/2236
|
||||||
|
if line.as_bytes().last() == Some(&b'\\') {
|
||||||
|
line = &line[..line.len() - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glob.actual = line.to_string();
|
glob.actual = line.to_string();
|
||||||
@@ -592,7 +595,7 @@ fn parse_excludes_file(data: &[u8]) -> Option<PathBuf> {
|
|||||||
// N.B. This is the lazy approach, and isn't technically correct, but
|
// N.B. This is the lazy approach, and isn't technically correct, but
|
||||||
// probably works in more circumstances. I guess we would ideally have
|
// probably works in more circumstances. I guess we would ideally have
|
||||||
// a full INI parser. Yuck.
|
// a full INI parser. Yuck.
|
||||||
lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref RE: Regex =
|
static ref RE: Regex =
|
||||||
Regex::new(r"(?im)^\s*excludesfile\s*=\s*(.+)\s*$").unwrap();
|
Regex::new(r"(?im)^\s*excludesfile\s*=\s*(.+)\s*$").unwrap();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,26 +46,12 @@ See the documentation for `WalkBuilder` for many other options.
|
|||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
extern crate crossbeam_channel as channel;
|
|
||||||
extern crate globset;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate lazy_static;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
|
||||||
extern crate memchr;
|
|
||||||
extern crate regex;
|
|
||||||
extern crate same_file;
|
|
||||||
extern crate thread_local;
|
|
||||||
extern crate walkdir;
|
|
||||||
#[cfg(windows)]
|
|
||||||
extern crate winapi_util;
|
|
||||||
|
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub use walk::{
|
pub use crate::walk::{
|
||||||
DirEntry, ParallelVisitor, ParallelVisitorBuilder, Walk, WalkBuilder,
|
DirEntry, ParallelVisitor, ParallelVisitorBuilder, Walk, WalkBuilder,
|
||||||
WalkParallel, WalkState,
|
WalkParallel, WalkState,
|
||||||
};
|
};
|
||||||
@@ -197,6 +183,71 @@ impl Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inspect the original [`io::Error`] if there is one.
|
||||||
|
///
|
||||||
|
/// [`None`] is returned if the [`Error`] doesn't correspond to an
|
||||||
|
/// [`io::Error`]. This might happen, for example, when the error was
|
||||||
|
/// produced because a cycle was found in the directory tree while
|
||||||
|
/// following symbolic links.
|
||||||
|
///
|
||||||
|
/// This method returns a borrowed value that is bound to the lifetime of the [`Error`]. To
|
||||||
|
/// obtain an owned value, the [`into_io_error`] can be used instead.
|
||||||
|
///
|
||||||
|
/// > This is the original [`io::Error`] and is _not_ the same as
|
||||||
|
/// > [`impl From<Error> for std::io::Error`][impl] which contains additional context about the
|
||||||
|
/// error.
|
||||||
|
///
|
||||||
|
/// [`None`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#variant.None
|
||||||
|
/// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html
|
||||||
|
/// [`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html
|
||||||
|
/// [`Error`]: struct.Error.html
|
||||||
|
/// [`into_io_error`]: struct.Error.html#method.into_io_error
|
||||||
|
/// [impl]: struct.Error.html#impl-From%3CError%3E
|
||||||
|
pub fn io_error(&self) -> Option<&std::io::Error> {
|
||||||
|
match *self {
|
||||||
|
Error::Partial(ref errs) => {
|
||||||
|
if errs.len() == 1 {
|
||||||
|
errs[0].io_error()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Error::WithLineNumber { ref err, .. } => err.io_error(),
|
||||||
|
Error::WithPath { ref err, .. } => err.io_error(),
|
||||||
|
Error::WithDepth { ref err, .. } => err.io_error(),
|
||||||
|
Error::Loop { .. } => None,
|
||||||
|
Error::Io(ref err) => Some(err),
|
||||||
|
Error::Glob { .. } => None,
|
||||||
|
Error::UnrecognizedFileType(_) => None,
|
||||||
|
Error::InvalidDefinition => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Similar to [`io_error`] except consumes self to convert to the original
|
||||||
|
/// [`io::Error`] if one exists.
|
||||||
|
///
|
||||||
|
/// [`io_error`]: struct.Error.html#method.io_error
|
||||||
|
/// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html
|
||||||
|
pub fn into_io_error(self) -> Option<std::io::Error> {
|
||||||
|
match self {
|
||||||
|
Error::Partial(mut errs) => {
|
||||||
|
if errs.len() == 1 {
|
||||||
|
errs.remove(0).into_io_error()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Error::WithLineNumber { err, .. } => err.into_io_error(),
|
||||||
|
Error::WithPath { err, .. } => err.into_io_error(),
|
||||||
|
Error::WithDepth { err, .. } => err.into_io_error(),
|
||||||
|
Error::Loop { .. } => None,
|
||||||
|
Error::Io(err) => Some(err),
|
||||||
|
Error::Glob { .. } => None,
|
||||||
|
Error::UnrecognizedFileType(_) => None,
|
||||||
|
Error::InvalidDefinition => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a depth associated with recursively walking a directory (if
|
/// Returns a depth associated with recursively walking a directory (if
|
||||||
/// this error was generated from a recursive directory iterator).
|
/// this error was generated from a recursive directory iterator).
|
||||||
pub fn depth(&self) -> Option<usize> {
|
pub fn depth(&self) -> Option<usize> {
|
||||||
@@ -270,7 +321,7 @@ impl error::Error for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Error::Partial(ref errs) => {
|
Error::Partial(ref errs) => {
|
||||||
let msgs: Vec<String> =
|
let msgs: Vec<String> =
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ line tools.
|
|||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use gitignore::{self, Gitignore, GitignoreBuilder};
|
use crate::gitignore::{self, Gitignore, GitignoreBuilder};
|
||||||
use {Error, Match};
|
use crate::{Error, Match};
|
||||||
|
|
||||||
/// Glob represents a single glob in an override matcher.
|
/// Glob represents a single glob in an override matcher.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use walk::DirEntry;
|
use crate::walk::DirEntry;
|
||||||
|
|
||||||
/// Returns true if and only if this entry is considered to be hidden.
|
/// Returns true if and only if this entry is considered to be hidden.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -93,9 +93,9 @@ use globset::{GlobBuilder, GlobSet, GlobSetBuilder};
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use thread_local::ThreadLocal;
|
use thread_local::ThreadLocal;
|
||||||
|
|
||||||
use default_types::DEFAULT_TYPES;
|
use crate::default_types::DEFAULT_TYPES;
|
||||||
use pathutil::file_name;
|
use crate::pathutil::file_name;
|
||||||
use {Error, Match};
|
use crate::{Error, Match};
|
||||||
|
|
||||||
/// Glob represents a single glob in a set of file type definitions.
|
/// Glob represents a single glob in a set of file type definitions.
|
||||||
///
|
///
|
||||||
@@ -122,10 +122,6 @@ enum GlobInner<'a> {
|
|||||||
Matched {
|
Matched {
|
||||||
/// The file type definition which provided the glob.
|
/// The file type definition which provided the glob.
|
||||||
def: &'a FileTypeDef,
|
def: &'a FileTypeDef,
|
||||||
/// The index of the glob that matched inside the file type definition.
|
|
||||||
which: usize,
|
|
||||||
/// Whether the selection was negated or not.
|
|
||||||
negated: bool,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +130,7 @@ impl<'a> Glob<'a> {
|
|||||||
Glob(GlobInner::UnmatchedIgnore)
|
Glob(GlobInner::UnmatchedIgnore)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the file type defintion that matched, if one exists. A file type
|
/// Return the file type definition that matched, if one exists. A file type
|
||||||
/// definition always exists when a specific definition matches a file
|
/// definition always exists when a specific definition matches a file
|
||||||
/// path.
|
/// path.
|
||||||
pub fn file_type_def(&self) -> Option<&FileTypeDef> {
|
pub fn file_type_def(&self) -> Option<&FileTypeDef> {
|
||||||
@@ -291,13 +287,9 @@ impl Types {
|
|||||||
self.set.matches_into(name, &mut *matches);
|
self.set.matches_into(name, &mut *matches);
|
||||||
// The highest precedent match is the last one.
|
// The highest precedent match is the last one.
|
||||||
if let Some(&i) = matches.last() {
|
if let Some(&i) = matches.last() {
|
||||||
let (isel, iglob) = self.glob_to_selection[i];
|
let (isel, _) = self.glob_to_selection[i];
|
||||||
let sel = &self.selections[isel];
|
let sel = &self.selections[isel];
|
||||||
let glob = Glob(GlobInner::Matched {
|
let glob = Glob(GlobInner::Matched { def: sel.inner() });
|
||||||
def: sel.inner(),
|
|
||||||
which: iglob,
|
|
||||||
negated: sel.is_negated(),
|
|
||||||
});
|
|
||||||
return if sel.is_negated() {
|
return if sel.is_negated() {
|
||||||
Match::Ignore(glob)
|
Match::Ignore(glob)
|
||||||
} else {
|
} else {
|
||||||
@@ -427,7 +419,7 @@ impl TypesBuilder {
|
|||||||
/// If `name` is `all` or otherwise contains any character that is not a
|
/// If `name` is `all` or otherwise contains any character that is not a
|
||||||
/// Unicode letter or number, then an error is returned.
|
/// Unicode letter or number, then an error is returned.
|
||||||
pub fn add(&mut self, name: &str, glob: &str) -> Result<(), Error> {
|
pub fn add(&mut self, name: &str, glob: &str) -> Result<(), Error> {
|
||||||
lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref RE: Regex = Regex::new(r"^[\pL\pN]+$").unwrap();
|
static ref RE: Regex = Regex::new(r"^[\pL\pN]+$").unwrap();
|
||||||
};
|
};
|
||||||
if name == "all" || !RE.is_match(name) {
|
if name == "all" || !RE.is_match(name) {
|
||||||
|
|||||||
@@ -5,18 +5,19 @@ use std::fs::{self, FileType, Metadata};
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
use channel::{self, TryRecvError};
|
|
||||||
use same_file::Handle;
|
use same_file::Handle;
|
||||||
use walkdir::{self, WalkDir};
|
use walkdir::{self, WalkDir};
|
||||||
|
|
||||||
use dir::{Ignore, IgnoreBuilder};
|
use crate::dir::{Ignore, IgnoreBuilder};
|
||||||
use gitignore::GitignoreBuilder;
|
use crate::gitignore::GitignoreBuilder;
|
||||||
use overrides::Override;
|
use crate::overrides::Override;
|
||||||
use types::Types;
|
use crate::types::Types;
|
||||||
use {Error, PartialErrorBuilder};
|
use crate::{Error, PartialErrorBuilder};
|
||||||
|
|
||||||
/// A directory entry with a possible error attached.
|
/// A directory entry with a possible error attached.
|
||||||
///
|
///
|
||||||
@@ -251,7 +252,7 @@ struct DirEntryRaw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for DirEntryRaw {
|
impl fmt::Debug for DirEntryRaw {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
// Leaving out FileType because it doesn't have a debug impl
|
// Leaving out FileType because it doesn't have a debug impl
|
||||||
// in Rust 1.9. We could add it if we really wanted to by manually
|
// in Rust 1.9. We could add it if we really wanted to by manually
|
||||||
// querying each possibly file type. Meh. ---AG
|
// querying each possibly file type. Meh. ---AG
|
||||||
@@ -364,7 +365,8 @@ impl DirEntryRaw {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Placeholder implementation to allow compiling on non-standard platforms (e.g. wasm32).
|
// Placeholder implementation to allow compiling on non-standard platforms
|
||||||
|
// (e.g. wasm32).
|
||||||
#[cfg(not(any(windows, unix)))]
|
#[cfg(not(any(windows, unix)))]
|
||||||
fn from_entry_os(
|
fn from_entry_os(
|
||||||
depth: usize,
|
depth: usize,
|
||||||
@@ -413,7 +415,8 @@ impl DirEntryRaw {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Placeholder implementation to allow compiling on non-standard platforms (e.g. wasm32).
|
// Placeholder implementation to allow compiling on non-standard platforms
|
||||||
|
// (e.g. wasm32).
|
||||||
#[cfg(not(any(windows, unix)))]
|
#[cfg(not(any(windows, unix)))]
|
||||||
fn from_path(
|
fn from_path(
|
||||||
depth: usize,
|
depth: usize,
|
||||||
@@ -486,6 +489,7 @@ pub struct WalkBuilder {
|
|||||||
sorter: Option<Sorter>,
|
sorter: Option<Sorter>,
|
||||||
threads: usize,
|
threads: usize,
|
||||||
skip: Option<Arc<Handle>>,
|
skip: Option<Arc<Handle>>,
|
||||||
|
filter: Option<Filter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -496,8 +500,11 @@ enum Sorter {
|
|||||||
ByPath(Arc<dyn Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static>),
|
ByPath(Arc<dyn Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Filter(Arc<dyn Fn(&DirEntry) -> bool + Send + Sync + 'static>);
|
||||||
|
|
||||||
impl fmt::Debug for WalkBuilder {
|
impl fmt::Debug for WalkBuilder {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("WalkBuilder")
|
f.debug_struct("WalkBuilder")
|
||||||
.field("paths", &self.paths)
|
.field("paths", &self.paths)
|
||||||
.field("ig_builder", &self.ig_builder)
|
.field("ig_builder", &self.ig_builder)
|
||||||
@@ -528,6 +535,7 @@ impl WalkBuilder {
|
|||||||
sorter: None,
|
sorter: None,
|
||||||
threads: 0,
|
threads: 0,
|
||||||
skip: None,
|
skip: None,
|
||||||
|
filter: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,6 +584,7 @@ impl WalkBuilder {
|
|||||||
ig: ig_root.clone(),
|
ig: ig_root.clone(),
|
||||||
max_filesize: self.max_filesize,
|
max_filesize: self.max_filesize,
|
||||||
skip: self.skip.clone(),
|
skip: self.skip.clone(),
|
||||||
|
filter: self.filter.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,6 +603,7 @@ impl WalkBuilder {
|
|||||||
same_file_system: self.same_file_system,
|
same_file_system: self.same_file_system,
|
||||||
threads: self.threads,
|
threads: self.threads,
|
||||||
skip: self.skip.clone(),
|
skip: self.skip.clone(),
|
||||||
|
filter: self.filter.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -875,6 +885,23 @@ impl WalkBuilder {
|
|||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Yields only entries which satisfy the given predicate and skips
|
||||||
|
/// descending into directories that do not satisfy the given predicate.
|
||||||
|
///
|
||||||
|
/// The predicate is applied to all entries. If the predicate is
|
||||||
|
/// true, iteration carries on as normal. If the predicate is false, the
|
||||||
|
/// entry is ignored and if it is a directory, it is not descended into.
|
||||||
|
///
|
||||||
|
/// Note that the errors for reading entries that may not satisfy the
|
||||||
|
/// predicate will still be yielded.
|
||||||
|
pub fn filter_entry<P>(&mut self, filter: P) -> &mut WalkBuilder
|
||||||
|
where
|
||||||
|
P: Fn(&DirEntry) -> bool + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
self.filter = Some(Filter(Arc::new(filter)));
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walk is a recursive directory iterator over file paths in one or more
|
/// Walk is a recursive directory iterator over file paths in one or more
|
||||||
@@ -890,6 +917,7 @@ pub struct Walk {
|
|||||||
ig: Ignore,
|
ig: Ignore,
|
||||||
max_filesize: Option<u64>,
|
max_filesize: Option<u64>,
|
||||||
skip: Option<Arc<Handle>>,
|
skip: Option<Arc<Handle>>,
|
||||||
|
filter: Option<Filter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Walk {
|
impl Walk {
|
||||||
@@ -906,15 +934,23 @@ impl Walk {
|
|||||||
if ent.depth() == 0 {
|
if ent.depth() == 0 {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
// We ensure that trivial skipping is done before any other potentially
|
||||||
|
// expensive operations (stat, filesystem other) are done. This seems
|
||||||
|
// like an obvious optimization but becomes critical when filesystem
|
||||||
|
// operations even as simple as stat can result in significant
|
||||||
|
// overheads; an example of this was a bespoke filesystem layer in
|
||||||
|
// Windows that hosted files remotely and would download them on-demand
|
||||||
|
// when particular filesystem operations occurred. Users of this system
|
||||||
|
// who ensured correct file-type filters were being used could still
|
||||||
|
// get unnecessary file access resulting in large downloads.
|
||||||
|
if should_skip_entry(&self.ig, ent) {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
if let Some(ref stdout) = self.skip {
|
if let Some(ref stdout) = self.skip {
|
||||||
if path_equals(ent, stdout)? {
|
if path_equals(ent, stdout)? {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if should_skip_entry(&self.ig, ent) {
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
if self.max_filesize.is_some() && !ent.is_dir() {
|
if self.max_filesize.is_some() && !ent.is_dir() {
|
||||||
return Ok(skip_filesize(
|
return Ok(skip_filesize(
|
||||||
self.max_filesize.unwrap(),
|
self.max_filesize.unwrap(),
|
||||||
@@ -922,6 +958,11 @@ impl Walk {
|
|||||||
&ent.metadata().ok(),
|
&ent.metadata().ok(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
if let Some(Filter(filter)) = &self.filter {
|
||||||
|
if !filter(ent) {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1154,6 +1195,7 @@ pub struct WalkParallel {
|
|||||||
same_file_system: bool,
|
same_file_system: bool,
|
||||||
threads: usize,
|
threads: usize,
|
||||||
skip: Option<Arc<Handle>>,
|
skip: Option<Arc<Handle>>,
|
||||||
|
filter: Option<Filter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WalkParallel {
|
impl WalkParallel {
|
||||||
@@ -1184,18 +1226,11 @@ impl WalkParallel {
|
|||||||
/// visitor runs on only one thread, this build-up can be done without
|
/// visitor runs on only one thread, this build-up can be done without
|
||||||
/// synchronization. Then, once traversal is complete, all of the results
|
/// synchronization. Then, once traversal is complete, all of the results
|
||||||
/// can be merged together into a single data structure.
|
/// can be merged together into a single data structure.
|
||||||
pub fn visit(mut self, builder: &mut dyn ParallelVisitorBuilder) {
|
pub fn visit(mut self, builder: &mut dyn ParallelVisitorBuilder<'_>) {
|
||||||
let threads = self.threads();
|
let threads = self.threads();
|
||||||
// TODO: Figure out how to use a bounded channel here. With an
|
let stack = Arc::new(Mutex::new(vec![]));
|
||||||
// unbounded channel, the workers can run away and fill up memory
|
|
||||||
// with all of the file paths. But a bounded channel doesn't work since
|
|
||||||
// our producers are also are consumers, so they end up getting stuck.
|
|
||||||
//
|
|
||||||
// We probably need to rethink parallel traversal completely to fix
|
|
||||||
// this. The best case scenario would be finding a way to use rayon
|
|
||||||
// to do this.
|
|
||||||
let (tx, rx) = channel::unbounded();
|
|
||||||
{
|
{
|
||||||
|
let mut stack = stack.lock().unwrap();
|
||||||
let mut visitor = builder.build();
|
let mut visitor = builder.build();
|
||||||
let mut paths = Vec::new().into_iter();
|
let mut paths = Vec::new().into_iter();
|
||||||
std::mem::swap(&mut paths, &mut self.paths);
|
std::mem::swap(&mut paths, &mut self.paths);
|
||||||
@@ -1232,44 +1267,41 @@ impl WalkParallel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
tx.send(Message::Work(Work {
|
stack.push(Message::Work(Work {
|
||||||
dent: dent,
|
dent: dent,
|
||||||
ignore: self.ig_root.clone(),
|
ignore: self.ig_root.clone(),
|
||||||
root_device: root_device,
|
root_device: root_device,
|
||||||
}))
|
}));
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
// ... but there's no need to start workers if we don't need them.
|
// ... but there's no need to start workers if we don't need them.
|
||||||
if tx.is_empty() {
|
if stack.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Create the workers and then wait for them to finish.
|
// Create the workers and then wait for them to finish.
|
||||||
let quit_now = Arc::new(AtomicBool::new(false));
|
let quit_now = Arc::new(AtomicBool::new(false));
|
||||||
let num_pending = Arc::new(AtomicUsize::new(tx.len()));
|
let num_pending =
|
||||||
crossbeam_utils::thread::scope(|s| {
|
Arc::new(AtomicUsize::new(stack.lock().unwrap().len()));
|
||||||
|
std::thread::scope(|s| {
|
||||||
let mut handles = vec![];
|
let mut handles = vec![];
|
||||||
for _ in 0..threads {
|
for _ in 0..threads {
|
||||||
let worker = Worker {
|
let worker = Worker {
|
||||||
visitor: builder.build(),
|
visitor: builder.build(),
|
||||||
tx: tx.clone(),
|
stack: stack.clone(),
|
||||||
rx: rx.clone(),
|
|
||||||
quit_now: quit_now.clone(),
|
quit_now: quit_now.clone(),
|
||||||
num_pending: num_pending.clone(),
|
num_pending: num_pending.clone(),
|
||||||
max_depth: self.max_depth,
|
max_depth: self.max_depth,
|
||||||
max_filesize: self.max_filesize,
|
max_filesize: self.max_filesize,
|
||||||
follow_links: self.follow_links,
|
follow_links: self.follow_links,
|
||||||
skip: self.skip.clone(),
|
skip: self.skip.clone(),
|
||||||
|
filter: self.filter.clone(),
|
||||||
};
|
};
|
||||||
handles.push(s.spawn(|_| worker.run()));
|
handles.push(s.spawn(|| worker.run()));
|
||||||
}
|
}
|
||||||
drop(tx);
|
|
||||||
drop(rx);
|
|
||||||
for handle in handles {
|
for handle in handles {
|
||||||
handle.join().unwrap();
|
handle.join().unwrap();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.unwrap(); // Pass along panics from threads
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn threads(&self) -> usize {
|
fn threads(&self) -> usize {
|
||||||
@@ -1362,10 +1394,13 @@ impl Work {
|
|||||||
struct Worker<'s> {
|
struct Worker<'s> {
|
||||||
/// The caller's callback.
|
/// The caller's callback.
|
||||||
visitor: Box<dyn ParallelVisitor + 's>,
|
visitor: Box<dyn ParallelVisitor + 's>,
|
||||||
/// The push side of our mpmc queue.
|
/// A stack of work to do.
|
||||||
tx: channel::Sender<Message>,
|
///
|
||||||
/// The receive side of our mpmc queue.
|
/// We use a stack instead of a channel because a stack lets us visit
|
||||||
rx: channel::Receiver<Message>,
|
/// directories in depth first order. This can substantially reduce peak
|
||||||
|
/// memory usage by keeping both the number of files path and gitignore
|
||||||
|
/// matchers in memory lower.
|
||||||
|
stack: Arc<Mutex<Vec<Message>>>,
|
||||||
/// Whether all workers should terminate at the next opportunity. Note
|
/// Whether all workers should terminate at the next opportunity. Note
|
||||||
/// that we need this because we don't want other `Work` to be done after
|
/// that we need this because we don't want other `Work` to be done after
|
||||||
/// we quit. We wouldn't need this if have a priority channel.
|
/// we quit. We wouldn't need this if have a priority channel.
|
||||||
@@ -1384,6 +1419,9 @@ struct Worker<'s> {
|
|||||||
/// A file handle to skip, currently is either `None` or stdout, if it's
|
/// A file handle to skip, currently is either `None` or stdout, if it's
|
||||||
/// a file and it has been requested to skip files identical to stdout.
|
/// a file and it has been requested to skip files identical to stdout.
|
||||||
skip: Option<Arc<Handle>>,
|
skip: Option<Arc<Handle>>,
|
||||||
|
/// A predicate applied to dir entries. If true, the entry and all
|
||||||
|
/// children will be skipped.
|
||||||
|
filter: Option<Filter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> Worker<'s> {
|
impl<'s> Worker<'s> {
|
||||||
@@ -1518,6 +1556,11 @@ impl<'s> Worker<'s> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// N.B. See analogous call in the single-threaded implementation about
|
||||||
|
// why it's important for this to come before the checks below.
|
||||||
|
if should_skip_entry(ig, &dent) {
|
||||||
|
return WalkState::Continue;
|
||||||
|
}
|
||||||
if let Some(ref stdout) = self.skip {
|
if let Some(ref stdout) = self.skip {
|
||||||
let is_stdout = match path_equals(&dent, stdout) {
|
let is_stdout = match path_equals(&dent, stdout) {
|
||||||
Ok(is_stdout) => is_stdout,
|
Ok(is_stdout) => is_stdout,
|
||||||
@@ -1527,7 +1570,6 @@ impl<'s> Worker<'s> {
|
|||||||
return WalkState::Continue;
|
return WalkState::Continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let should_skip_path = should_skip_entry(ig, &dent);
|
|
||||||
let should_skip_filesize =
|
let should_skip_filesize =
|
||||||
if self.max_filesize.is_some() && !dent.is_dir() {
|
if self.max_filesize.is_some() && !dent.is_dir() {
|
||||||
skip_filesize(
|
skip_filesize(
|
||||||
@@ -1538,8 +1580,13 @@ impl<'s> Worker<'s> {
|
|||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
let should_skip_filtered =
|
||||||
if !should_skip_path && !should_skip_filesize {
|
if let Some(Filter(predicate)) = &self.filter {
|
||||||
|
!predicate(&dent)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if !should_skip_filesize && !should_skip_filtered {
|
||||||
self.send(Work { dent, ignore: ig.clone(), root_device });
|
self.send(Work { dent, ignore: ig.clone(), root_device });
|
||||||
}
|
}
|
||||||
WalkState::Continue
|
WalkState::Continue
|
||||||
@@ -1550,25 +1597,25 @@ impl<'s> Worker<'s> {
|
|||||||
/// If all work has been exhausted, then this returns None. The worker
|
/// If all work has been exhausted, then this returns None. The worker
|
||||||
/// should then subsequently quit.
|
/// should then subsequently quit.
|
||||||
fn get_work(&mut self) -> Option<Work> {
|
fn get_work(&mut self) -> Option<Work> {
|
||||||
let mut value = self.rx.try_recv();
|
let mut value = self.recv();
|
||||||
loop {
|
loop {
|
||||||
// Simulate a priority channel: If quit_now flag is set, we can
|
// Simulate a priority channel: If quit_now flag is set, we can
|
||||||
// receive only quit messages.
|
// receive only quit messages.
|
||||||
if self.is_quit_now() {
|
if self.is_quit_now() {
|
||||||
value = Ok(Message::Quit)
|
value = Some(Message::Quit)
|
||||||
}
|
}
|
||||||
match value {
|
match value {
|
||||||
Ok(Message::Work(work)) => {
|
Some(Message::Work(work)) => {
|
||||||
return Some(work);
|
return Some(work);
|
||||||
}
|
}
|
||||||
Ok(Message::Quit) => {
|
Some(Message::Quit) => {
|
||||||
// Repeat quit message to wake up sleeping threads, if
|
// Repeat quit message to wake up sleeping threads, if
|
||||||
// any. The domino effect will ensure that every thread
|
// any. The domino effect will ensure that every thread
|
||||||
// will quit.
|
// will quit.
|
||||||
self.tx.send(Message::Quit).unwrap();
|
self.send_quit();
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Err(TryRecvError::Empty) => {
|
None => {
|
||||||
// Once num_pending reaches 0, it is impossible for it to
|
// Once num_pending reaches 0, it is impossible for it to
|
||||||
// ever increase again. Namely, it only reaches 0 once
|
// ever increase again. Namely, it only reaches 0 once
|
||||||
// all jobs have run such that no jobs have produced more
|
// all jobs have run such that no jobs have produced more
|
||||||
@@ -1580,17 +1627,21 @@ impl<'s> Worker<'s> {
|
|||||||
if self.num_pending() == 0 {
|
if self.num_pending() == 0 {
|
||||||
// Every other thread is blocked at the next recv().
|
// Every other thread is blocked at the next recv().
|
||||||
// Send the initial quit message and quit.
|
// Send the initial quit message and quit.
|
||||||
self.tx.send(Message::Quit).unwrap();
|
self.send_quit();
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
// Wait for next `Work` or `Quit` message.
|
// Wait for next `Work` or `Quit` message.
|
||||||
value = Ok(self
|
loop {
|
||||||
.rx
|
if let Some(v) = self.recv() {
|
||||||
.recv()
|
value = Some(v);
|
||||||
.expect("channel disconnected while worker is alive"));
|
break;
|
||||||
|
}
|
||||||
|
// Our stack isn't blocking. Instead of burning the
|
||||||
|
// CPU waiting, we let the thread sleep for a bit. In
|
||||||
|
// general, this tends to only occur once the search is
|
||||||
|
// approaching termination.
|
||||||
|
thread::sleep(Duration::from_millis(1));
|
||||||
}
|
}
|
||||||
Err(TryRecvError::Disconnected) => {
|
|
||||||
unreachable!("channel disconnected while worker is alive");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1614,7 +1665,20 @@ impl<'s> Worker<'s> {
|
|||||||
/// Send work.
|
/// Send work.
|
||||||
fn send(&self, work: Work) {
|
fn send(&self, work: Work) {
|
||||||
self.num_pending.fetch_add(1, Ordering::SeqCst);
|
self.num_pending.fetch_add(1, Ordering::SeqCst);
|
||||||
self.tx.send(Message::Work(work)).unwrap();
|
let mut stack = self.stack.lock().unwrap();
|
||||||
|
stack.push(Message::Work(work));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send a quit message.
|
||||||
|
fn send_quit(&self) {
|
||||||
|
let mut stack = self.stack.lock().unwrap();
|
||||||
|
stack.push(Message::Quit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Receive work.
|
||||||
|
fn recv(&self) -> Option<Message> {
|
||||||
|
let mut stack = self.stack.lock().unwrap();
|
||||||
|
stack.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signal that work has been received.
|
/// Signal that work has been received.
|
||||||
@@ -1660,7 +1724,7 @@ fn skip_filesize(
|
|||||||
|
|
||||||
if let Some(fs) = filesize {
|
if let Some(fs) = filesize {
|
||||||
if fs > max_filesize {
|
if fs > max_filesize {
|
||||||
debug!("ignoring {}: {} bytes", path.display(), fs);
|
log::debug!("ignoring {}: {} bytes", path.display(), fs);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -1673,10 +1737,10 @@ fn skip_filesize(
|
|||||||
fn should_skip_entry(ig: &Ignore, dent: &DirEntry) -> bool {
|
fn should_skip_entry(ig: &Ignore, dent: &DirEntry) -> bool {
|
||||||
let m = ig.matched_dir_entry(dent);
|
let m = ig.matched_dir_entry(dent);
|
||||||
if m.is_ignore() {
|
if m.is_ignore() {
|
||||||
debug!("ignoring {}: {:?}", dent.path().display(), m);
|
log::debug!("ignoring {}: {:?}", dent.path().display(), m);
|
||||||
true
|
true
|
||||||
} else if m.is_whitelist() {
|
} else if m.is_whitelist() {
|
||||||
debug!("whitelisting {}: {:?}", dent.path().display(), m);
|
log::debug!("whitelisting {}: {:?}", dent.path().display(), m);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -1780,13 +1844,14 @@ fn device_num<P: AsRef<Path>>(_: P) -> io::Result<u64> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::ffi::OsStr;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use super::{DirEntry, WalkBuilder, WalkState};
|
use super::{DirEntry, WalkBuilder, WalkState};
|
||||||
use tests::TempDir;
|
use crate::tests::TempDir;
|
||||||
|
|
||||||
fn wfile<P: AsRef<Path>>(path: P, contents: &str) {
|
fn wfile<P: AsRef<Path>>(path: P, contents: &str) {
|
||||||
let mut file = File::create(path).unwrap();
|
let mut file = File::create(path).unwrap();
|
||||||
@@ -2161,4 +2226,26 @@ mod tests {
|
|||||||
let builder = WalkBuilder::new(&dir_path);
|
let builder = WalkBuilder::new(&dir_path);
|
||||||
assert_paths(dir_path.parent().unwrap(), &builder, &["root"]);
|
assert_paths(dir_path.parent().unwrap(), &builder, &["root"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn filter() {
|
||||||
|
let td = tmpdir();
|
||||||
|
mkdirp(td.path().join("a/b/c"));
|
||||||
|
mkdirp(td.path().join("x/y"));
|
||||||
|
wfile(td.path().join("a/b/foo"), "");
|
||||||
|
wfile(td.path().join("x/y/foo"), "");
|
||||||
|
|
||||||
|
assert_paths(
|
||||||
|
td.path(),
|
||||||
|
&WalkBuilder::new(td.path()),
|
||||||
|
&["x", "x/y", "x/y/foo", "a", "a/b", "a/b/foo", "a/b/c"],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_paths(
|
||||||
|
td.path(),
|
||||||
|
&WalkBuilder::new(td.path())
|
||||||
|
.filter_entry(|entry| entry.file_name() != OsStr::new("a")),
|
||||||
|
&["x", "x/y", "x/y/foo"],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
extern crate ignore;
|
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use ignore::gitignore::{Gitignore, GitignoreBuilder};
|
use ignore::gitignore::{Gitignore, GitignoreBuilder};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-matcher"
|
name = "grep-matcher"
|
||||||
version = "0.1.4" #:version
|
version = "0.1.5" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
A trait for regular expressions, with a focus on line oriented search.
|
A trait for regular expressions, with a focus on line oriented search.
|
||||||
@@ -10,8 +10,9 @@ homepage = "https://github.com/BurntSushi/ripgrep/tree/master/crates/matcher"
|
|||||||
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/matcher"
|
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/matcher"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["regex", "pattern", "trait"]
|
keywords = ["regex", "pattern", "trait"]
|
||||||
license = "Unlicense/MIT"
|
license = "Unlicense OR MIT"
|
||||||
autotests = false
|
autotests = false
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
memchr = "2.1"
|
memchr = "2.1"
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ This crate provides a low level interface for describing regular expression
|
|||||||
matchers. The `grep` crate uses this interface in order to make the regex
|
matchers. The `grep` crate uses this interface in order to make the regex
|
||||||
engine it uses pluggable.
|
engine it uses pluggable.
|
||||||
|
|
||||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
[](https://github.com/BurntSushi/ripgrep/actions)
|
||||||
[](https://ci.appveyor.com/project/BurntSushi/ripgrep)
|
|
||||||
[](https://crates.io/crates/grep-matcher)
|
[](https://crates.io/crates/grep-matcher)
|
||||||
|
|
||||||
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
@@ -28,9 +27,3 @@ Add this to your `Cargo.toml`:
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
grep-matcher = "0.1"
|
grep-matcher = "0.1"
|
||||||
```
|
```
|
||||||
|
|
||||||
and this to your crate root:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
extern crate grep_matcher;
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ pub fn interpolate<A, N>(
|
|||||||
/// `CaptureRef` represents a reference to a capture group inside some text.
|
/// `CaptureRef` represents a reference to a capture group inside some text.
|
||||||
/// The reference is either a capture group name or a number.
|
/// The reference is either a capture group name or a number.
|
||||||
///
|
///
|
||||||
/// It is also tagged with the position in the text immediately proceding the
|
/// It is also tagged with the position in the text immediately proceeding the
|
||||||
/// capture reference.
|
/// capture reference.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
struct CaptureRef<'a> {
|
struct CaptureRef<'a> {
|
||||||
@@ -92,7 +92,7 @@ impl From<usize> for Ref<'static> {
|
|||||||
/// starting at the beginning of `replacement`.
|
/// starting at the beginning of `replacement`.
|
||||||
///
|
///
|
||||||
/// If no such valid reference could be found, None is returned.
|
/// If no such valid reference could be found, None is returned.
|
||||||
fn find_cap_ref(replacement: &[u8]) -> Option<CaptureRef> {
|
fn find_cap_ref(replacement: &[u8]) -> Option<CaptureRef<'_>> {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
if replacement.len() <= 1 || replacement[0] != b'$' {
|
if replacement.len() <= 1 || replacement[0] != b'$' {
|
||||||
return None;
|
return None;
|
||||||
|
|||||||
@@ -38,14 +38,12 @@ implementations.
|
|||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
extern crate memchr;
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::u64;
|
use std::u64;
|
||||||
|
|
||||||
use interpolate::interpolate;
|
use crate::interpolate::interpolate;
|
||||||
|
|
||||||
mod interpolate;
|
mod interpolate;
|
||||||
|
|
||||||
@@ -118,7 +116,7 @@ impl Match {
|
|||||||
/// This method panics if `start > self.end`.
|
/// This method panics if `start > self.end`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_start(&self, start: usize) -> Match {
|
pub fn with_start(&self, start: usize) -> Match {
|
||||||
assert!(start <= self.end);
|
assert!(start <= self.end, "{} is not <= {}", start, self.end);
|
||||||
Match { start, ..*self }
|
Match { start, ..*self }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +128,7 @@ impl Match {
|
|||||||
/// This method panics if `self.start > end`.
|
/// This method panics if `self.start > end`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_end(&self, end: usize) -> Match {
|
pub fn with_end(&self, end: usize) -> Match {
|
||||||
assert!(self.start <= end);
|
assert!(self.start <= end, "{} is not <= {}", self.start, end);
|
||||||
Match { end, ..*self }
|
Match { end, ..*self }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +302,7 @@ pub struct ByteSet(BitSet);
|
|||||||
struct BitSet([u64; 4]);
|
struct BitSet([u64; 4]);
|
||||||
|
|
||||||
impl fmt::Debug for BitSet {
|
impl fmt::Debug for BitSet {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut fmtd = f.debug_set();
|
let mut fmtd = f.debug_set();
|
||||||
for b in (0..256).map(|b| b as u8) {
|
for b in (0..256).map(|b| b as u8) {
|
||||||
if ByteSet(*self).contains(b) {
|
if ByteSet(*self).contains(b) {
|
||||||
@@ -494,7 +492,7 @@ impl ::std::error::Error for NoError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for NoError {
|
impl fmt::Display for NoError {
|
||||||
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
panic!("BUG for NoError: an impossible error occurred")
|
panic!("BUG for NoError: an impossible error occurred")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -618,12 +616,31 @@ pub trait Matcher {
|
|||||||
fn find_iter<F>(
|
fn find_iter<F>(
|
||||||
&self,
|
&self,
|
||||||
haystack: &[u8],
|
haystack: &[u8],
|
||||||
|
matched: F,
|
||||||
|
) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(Match) -> bool,
|
||||||
|
{
|
||||||
|
self.find_iter_at(haystack, 0, matched)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executes the given function over successive non-overlapping matches
|
||||||
|
/// in `haystack`. If no match exists, then the given function is never
|
||||||
|
/// called. If the function returns `false`, then iteration stops.
|
||||||
|
///
|
||||||
|
/// The significance of the starting point is that it takes the surrounding
|
||||||
|
/// context into consideration. For example, the `\A` anchor can only
|
||||||
|
/// match when `at == 0`.
|
||||||
|
fn find_iter_at<F>(
|
||||||
|
&self,
|
||||||
|
haystack: &[u8],
|
||||||
|
at: usize,
|
||||||
mut matched: F,
|
mut matched: F,
|
||||||
) -> Result<(), Self::Error>
|
) -> Result<(), Self::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(Match) -> bool,
|
F: FnMut(Match) -> bool,
|
||||||
{
|
{
|
||||||
self.try_find_iter(haystack, |m| Ok(matched(m)))
|
self.try_find_iter_at(haystack, at, |m| Ok(matched(m)))
|
||||||
.map(|r: Result<(), ()>| r.unwrap())
|
.map(|r: Result<(), ()>| r.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,12 +654,35 @@ pub trait Matcher {
|
|||||||
fn try_find_iter<F, E>(
|
fn try_find_iter<F, E>(
|
||||||
&self,
|
&self,
|
||||||
haystack: &[u8],
|
haystack: &[u8],
|
||||||
|
matched: F,
|
||||||
|
) -> Result<Result<(), E>, Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(Match) -> Result<bool, E>,
|
||||||
|
{
|
||||||
|
self.try_find_iter_at(haystack, 0, matched)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executes the given function over successive non-overlapping matches
|
||||||
|
/// in `haystack`. If no match exists, then the given function is never
|
||||||
|
/// called. If the function returns `false`, then iteration stops.
|
||||||
|
/// Similarly, if the function returns an error then iteration stops and
|
||||||
|
/// the error is yielded. If an error occurs while executing the search,
|
||||||
|
/// then it is converted to
|
||||||
|
/// `E`.
|
||||||
|
///
|
||||||
|
/// The significance of the starting point is that it takes the surrounding
|
||||||
|
/// context into consideration. For example, the `\A` anchor can only
|
||||||
|
/// match when `at == 0`.
|
||||||
|
fn try_find_iter_at<F, E>(
|
||||||
|
&self,
|
||||||
|
haystack: &[u8],
|
||||||
|
at: usize,
|
||||||
mut matched: F,
|
mut matched: F,
|
||||||
) -> Result<Result<(), E>, Self::Error>
|
) -> Result<Result<(), E>, Self::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(Match) -> Result<bool, E>,
|
F: FnMut(Match) -> Result<bool, E>,
|
||||||
{
|
{
|
||||||
let mut last_end = 0;
|
let mut last_end = at;
|
||||||
let mut last_match = None;
|
let mut last_match = None;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -696,12 +736,33 @@ pub trait Matcher {
|
|||||||
&self,
|
&self,
|
||||||
haystack: &[u8],
|
haystack: &[u8],
|
||||||
caps: &mut Self::Captures,
|
caps: &mut Self::Captures,
|
||||||
|
matched: F,
|
||||||
|
) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(&Self::Captures) -> bool,
|
||||||
|
{
|
||||||
|
self.captures_iter_at(haystack, 0, caps, matched)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executes the given function over successive non-overlapping matches
|
||||||
|
/// in `haystack` with capture groups extracted from each match. If no
|
||||||
|
/// match exists, then the given function is never called. If the function
|
||||||
|
/// returns `false`, then iteration stops.
|
||||||
|
///
|
||||||
|
/// The significance of the starting point is that it takes the surrounding
|
||||||
|
/// context into consideration. For example, the `\A` anchor can only
|
||||||
|
/// match when `at == 0`.
|
||||||
|
fn captures_iter_at<F>(
|
||||||
|
&self,
|
||||||
|
haystack: &[u8],
|
||||||
|
at: usize,
|
||||||
|
caps: &mut Self::Captures,
|
||||||
mut matched: F,
|
mut matched: F,
|
||||||
) -> Result<(), Self::Error>
|
) -> Result<(), Self::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(&Self::Captures) -> bool,
|
F: FnMut(&Self::Captures) -> bool,
|
||||||
{
|
{
|
||||||
self.try_captures_iter(haystack, caps, |caps| Ok(matched(caps)))
|
self.try_captures_iter_at(haystack, at, caps, |caps| Ok(matched(caps)))
|
||||||
.map(|r: Result<(), ()>| r.unwrap())
|
.map(|r: Result<(), ()>| r.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,12 +777,36 @@ pub trait Matcher {
|
|||||||
&self,
|
&self,
|
||||||
haystack: &[u8],
|
haystack: &[u8],
|
||||||
caps: &mut Self::Captures,
|
caps: &mut Self::Captures,
|
||||||
|
matched: F,
|
||||||
|
) -> Result<Result<(), E>, Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(&Self::Captures) -> Result<bool, E>,
|
||||||
|
{
|
||||||
|
self.try_captures_iter_at(haystack, 0, caps, matched)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executes the given function over successive non-overlapping matches
|
||||||
|
/// in `haystack` with capture groups extracted from each match. If no
|
||||||
|
/// match exists, then the given function is never called. If the function
|
||||||
|
/// returns `false`, then iteration stops. Similarly, if the function
|
||||||
|
/// returns an error then iteration stops and the error is yielded. If
|
||||||
|
/// an error occurs while executing the search, then it is converted to
|
||||||
|
/// `E`.
|
||||||
|
///
|
||||||
|
/// The significance of the starting point is that it takes the surrounding
|
||||||
|
/// context into consideration. For example, the `\A` anchor can only
|
||||||
|
/// match when `at == 0`.
|
||||||
|
fn try_captures_iter_at<F, E>(
|
||||||
|
&self,
|
||||||
|
haystack: &[u8],
|
||||||
|
at: usize,
|
||||||
|
caps: &mut Self::Captures,
|
||||||
mut matched: F,
|
mut matched: F,
|
||||||
) -> Result<Result<(), E>, Self::Error>
|
) -> Result<Result<(), E>, Self::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(&Self::Captures) -> Result<bool, E>,
|
F: FnMut(&Self::Captures) -> Result<bool, E>,
|
||||||
{
|
{
|
||||||
let mut last_end = 0;
|
let mut last_end = at;
|
||||||
let mut last_match = None;
|
let mut last_match = None;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -819,13 +904,35 @@ pub trait Matcher {
|
|||||||
haystack: &[u8],
|
haystack: &[u8],
|
||||||
caps: &mut Self::Captures,
|
caps: &mut Self::Captures,
|
||||||
dst: &mut Vec<u8>,
|
dst: &mut Vec<u8>,
|
||||||
|
append: F,
|
||||||
|
) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(&Self::Captures, &mut Vec<u8>) -> bool,
|
||||||
|
{
|
||||||
|
self.replace_with_captures_at(haystack, 0, caps, dst, append)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replaces every match in the given haystack with the result of calling
|
||||||
|
/// `append` with the matching capture groups.
|
||||||
|
///
|
||||||
|
/// If the given `append` function returns `false`, then replacement stops.
|
||||||
|
///
|
||||||
|
/// The significance of the starting point is that it takes the surrounding
|
||||||
|
/// context into consideration. For example, the `\A` anchor can only
|
||||||
|
/// match when `at == 0`.
|
||||||
|
fn replace_with_captures_at<F>(
|
||||||
|
&self,
|
||||||
|
haystack: &[u8],
|
||||||
|
at: usize,
|
||||||
|
caps: &mut Self::Captures,
|
||||||
|
dst: &mut Vec<u8>,
|
||||||
mut append: F,
|
mut append: F,
|
||||||
) -> Result<(), Self::Error>
|
) -> Result<(), Self::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(&Self::Captures, &mut Vec<u8>) -> bool,
|
F: FnMut(&Self::Captures, &mut Vec<u8>) -> bool,
|
||||||
{
|
{
|
||||||
let mut last_match = 0;
|
let mut last_match = at;
|
||||||
self.captures_iter(haystack, caps, |caps| {
|
self.captures_iter_at(haystack, at, caps, |caps| {
|
||||||
let m = caps.get(0).unwrap();
|
let m = caps.get(0).unwrap();
|
||||||
dst.extend(&haystack[last_match..m.start]);
|
dst.extend(&haystack[last_match..m.start]);
|
||||||
last_match = m.end;
|
last_match = m.end;
|
||||||
@@ -1039,6 +1146,18 @@ impl<'a, M: Matcher> Matcher for &'a M {
|
|||||||
(*self).find_iter(haystack, matched)
|
(*self).find_iter(haystack, matched)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_iter_at<F>(
|
||||||
|
&self,
|
||||||
|
haystack: &[u8],
|
||||||
|
at: usize,
|
||||||
|
matched: F,
|
||||||
|
) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(Match) -> bool,
|
||||||
|
{
|
||||||
|
(*self).find_iter_at(haystack, at, matched)
|
||||||
|
}
|
||||||
|
|
||||||
fn try_find_iter<F, E>(
|
fn try_find_iter<F, E>(
|
||||||
&self,
|
&self,
|
||||||
haystack: &[u8],
|
haystack: &[u8],
|
||||||
@@ -1050,6 +1169,18 @@ impl<'a, M: Matcher> Matcher for &'a M {
|
|||||||
(*self).try_find_iter(haystack, matched)
|
(*self).try_find_iter(haystack, matched)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_find_iter_at<F, E>(
|
||||||
|
&self,
|
||||||
|
haystack: &[u8],
|
||||||
|
at: usize,
|
||||||
|
matched: F,
|
||||||
|
) -> Result<Result<(), E>, Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(Match) -> Result<bool, E>,
|
||||||
|
{
|
||||||
|
(*self).try_find_iter_at(haystack, at, matched)
|
||||||
|
}
|
||||||
|
|
||||||
fn captures(
|
fn captures(
|
||||||
&self,
|
&self,
|
||||||
haystack: &[u8],
|
haystack: &[u8],
|
||||||
@@ -1070,6 +1201,19 @@ impl<'a, M: Matcher> Matcher for &'a M {
|
|||||||
(*self).captures_iter(haystack, caps, matched)
|
(*self).captures_iter(haystack, caps, matched)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn captures_iter_at<F>(
|
||||||
|
&self,
|
||||||
|
haystack: &[u8],
|
||||||
|
at: usize,
|
||||||
|
caps: &mut Self::Captures,
|
||||||
|
matched: F,
|
||||||
|
) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(&Self::Captures) -> bool,
|
||||||
|
{
|
||||||
|
(*self).captures_iter_at(haystack, at, caps, matched)
|
||||||
|
}
|
||||||
|
|
||||||
fn try_captures_iter<F, E>(
|
fn try_captures_iter<F, E>(
|
||||||
&self,
|
&self,
|
||||||
haystack: &[u8],
|
haystack: &[u8],
|
||||||
@@ -1082,6 +1226,19 @@ impl<'a, M: Matcher> Matcher for &'a M {
|
|||||||
(*self).try_captures_iter(haystack, caps, matched)
|
(*self).try_captures_iter(haystack, caps, matched)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_captures_iter_at<F, E>(
|
||||||
|
&self,
|
||||||
|
haystack: &[u8],
|
||||||
|
at: usize,
|
||||||
|
caps: &mut Self::Captures,
|
||||||
|
matched: F,
|
||||||
|
) -> Result<Result<(), E>, Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(&Self::Captures) -> Result<bool, E>,
|
||||||
|
{
|
||||||
|
(*self).try_captures_iter_at(haystack, at, caps, matched)
|
||||||
|
}
|
||||||
|
|
||||||
fn replace<F>(
|
fn replace<F>(
|
||||||
&self,
|
&self,
|
||||||
haystack: &[u8],
|
haystack: &[u8],
|
||||||
@@ -1107,6 +1264,20 @@ impl<'a, M: Matcher> Matcher for &'a M {
|
|||||||
(*self).replace_with_captures(haystack, caps, dst, append)
|
(*self).replace_with_captures(haystack, caps, dst, append)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn replace_with_captures_at<F>(
|
||||||
|
&self,
|
||||||
|
haystack: &[u8],
|
||||||
|
at: usize,
|
||||||
|
caps: &mut Self::Captures,
|
||||||
|
dst: &mut Vec<u8>,
|
||||||
|
append: F,
|
||||||
|
) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(&Self::Captures, &mut Vec<u8>) -> bool,
|
||||||
|
{
|
||||||
|
(*self).replace_with_captures_at(haystack, at, caps, dst, append)
|
||||||
|
}
|
||||||
|
|
||||||
fn is_match(&self, haystack: &[u8]) -> Result<bool, Self::Error> {
|
fn is_match(&self, haystack: &[u8]) -> Result<bool, Self::Error> {
|
||||||
(*self).is_match(haystack)
|
(*self).is_match(haystack)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use grep_matcher::{Captures, Match, Matcher};
|
use grep_matcher::{Captures, Match, Matcher};
|
||||||
use regex::bytes::Regex;
|
use regex::bytes::Regex;
|
||||||
|
|
||||||
use util::{RegexMatcher, RegexMatcherNoCaps};
|
use crate::util::{RegexMatcher, RegexMatcherNoCaps};
|
||||||
|
|
||||||
fn matcher(pattern: &str) -> RegexMatcher {
|
fn matcher(pattern: &str) -> RegexMatcher {
|
||||||
RegexMatcher::new(Regex::new(pattern).unwrap())
|
RegexMatcher::new(Regex::new(pattern).unwrap())
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
extern crate grep_matcher;
|
|
||||||
extern crate regex;
|
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
mod test_matcher;
|
mod test_matcher;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-pcre2"
|
name = "grep-pcre2"
|
||||||
version = "0.1.4" #:version
|
version = "0.1.5" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Use PCRE2 with the 'grep' crate.
|
Use PCRE2 with the 'grep' crate.
|
||||||
@@ -10,8 +10,9 @@ homepage = "https://github.com/BurntSushi/ripgrep/tree/master/crates/pcre2"
|
|||||||
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/pcre2"
|
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/pcre2"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["regex", "grep", "pcre", "backreference", "look"]
|
keywords = ["regex", "grep", "pcre", "backreference", "look"]
|
||||||
license = "Unlicense/MIT"
|
license = "Unlicense OR MIT"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
grep-matcher = { version = "0.1.2", path = "../matcher" }
|
grep-matcher = { version = "0.1.5", path = "../matcher" }
|
||||||
pcre2 = "0.2.0"
|
pcre2 = "0.2.3"
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ The `grep-pcre2` crate provides an implementation of the `Matcher` trait from
|
|||||||
the `grep-matcher` crate. This implementation permits PCRE2 to be used in the
|
the `grep-matcher` crate. This implementation permits PCRE2 to be used in the
|
||||||
`grep` crate for fast line oriented searching.
|
`grep` crate for fast line oriented searching.
|
||||||
|
|
||||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
[](https://github.com/BurntSushi/ripgrep/actions)
|
||||||
[](https://ci.appveyor.com/project/BurntSushi/ripgrep)
|
|
||||||
[](https://crates.io/crates/grep-pcre2)
|
[](https://crates.io/crates/grep-pcre2)
|
||||||
|
|
||||||
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
@@ -31,9 +30,3 @@ Add this to your `Cargo.toml`:
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
grep-pcre2 = "0.1"
|
grep-pcre2 = "0.1"
|
||||||
```
|
```
|
||||||
|
|
||||||
and this to your crate root:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
extern crate grep_pcre2;
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ impl error::Error for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ErrorKind::Regex(ref s) => write!(f, "{}", s),
|
ErrorKind::Regex(ref s) => write!(f, "{}", s),
|
||||||
ErrorKind::__Nonexhaustive => unreachable!(),
|
ErrorKind::__Nonexhaustive => unreachable!(),
|
||||||
|
|||||||
@@ -5,11 +5,8 @@ An implementation of `grep-matcher`'s `Matcher` trait for
|
|||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
extern crate grep_matcher;
|
pub use crate::error::{Error, ErrorKind};
|
||||||
extern crate pcre2;
|
pub use crate::matcher::{RegexCaptures, RegexMatcher, RegexMatcherBuilder};
|
||||||
|
|
||||||
pub use error::{Error, ErrorKind};
|
|
||||||
pub use matcher::{RegexCaptures, RegexMatcher, RegexMatcherBuilder};
|
|
||||||
pub use pcre2::{is_jit_available, version};
|
pub use pcre2::{is_jit_available, version};
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::collections::HashMap;
|
|||||||
use grep_matcher::{Captures, Match, Matcher};
|
use grep_matcher::{Captures, Match, Matcher};
|
||||||
use pcre2::bytes::{CaptureLocations, Regex, RegexBuilder};
|
use pcre2::bytes::{CaptureLocations, Regex, RegexBuilder};
|
||||||
|
|
||||||
use error::Error;
|
use crate::error::Error;
|
||||||
|
|
||||||
/// A builder for configuring the compilation of a PCRE2 regex.
|
/// A builder for configuring the compilation of a PCRE2 regex.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-printer"
|
name = "grep-printer"
|
||||||
version = "0.1.4" #:version
|
version = "0.1.6" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
An implementation of the grep crate's Sink trait that provides standard
|
An implementation of the grep crate's Sink trait that provides standard
|
||||||
@@ -11,21 +11,21 @@ homepage = "https://github.com/BurntSushi/ripgrep/tree/master/crates/printer"
|
|||||||
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/printer"
|
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/printer"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["grep", "pattern", "print", "printer", "sink"]
|
keywords = ["grep", "pattern", "print", "printer", "sink"]
|
||||||
license = "Unlicense/MIT"
|
license = "Unlicense OR MIT"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["serde1"]
|
default = ["serde1"]
|
||||||
serde1 = ["base64", "serde", "serde_derive", "serde_json"]
|
serde1 = ["base64", "serde", "serde_json"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = { version = "0.11.0", optional = true }
|
base64 = { version = "0.20.0", optional = true }
|
||||||
bstr = "0.2.0"
|
bstr = "1.1.0"
|
||||||
grep-matcher = { version = "0.1.2", path = "../matcher" }
|
grep-matcher = { version = "0.1.5", path = "../matcher" }
|
||||||
grep-searcher = { version = "0.1.4", path = "../searcher" }
|
grep-searcher = { version = "0.1.8", path = "../searcher" }
|
||||||
termcolor = "1.0.4"
|
termcolor = "1.0.4"
|
||||||
serde = { version = "1.0.77", optional = true }
|
serde = { version = "1.0.77", optional = true, features = ["derive"] }
|
||||||
serde_derive = { version = "1.0.77", optional = true }
|
|
||||||
serde_json = { version = "1.0.27", optional = true }
|
serde_json = { version = "1.0.27", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
grep-regex = { version = "0.1.3", path = "../regex" }
|
grep-regex = { version = "0.1.9", path = "../regex" }
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ grep-printer
|
|||||||
Print results from line oriented searching in a human readable, aggregate or
|
Print results from line oriented searching in a human readable, aggregate or
|
||||||
JSON Lines format.
|
JSON Lines format.
|
||||||
|
|
||||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
[](https://github.com/BurntSushi/ripgrep/actions)
|
||||||
[](https://ci.appveyor.com/project/BurntSushi/ripgrep)
|
|
||||||
[](https://crates.io/crates/grep-printer)
|
[](https://crates.io/crates/grep-printer)
|
||||||
|
|
||||||
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
@@ -27,9 +26,3 @@ Add this to your `Cargo.toml`:
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
grep-printer = "0.1"
|
grep-printer = "0.1"
|
||||||
```
|
```
|
||||||
|
|
||||||
and this to your crate root:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
extern crate grep_printer;
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ impl ColorError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ColorError {
|
impl fmt::Display for ColorError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
ColorError::UnrecognizedOutType(ref name) => write!(
|
ColorError::UnrecognizedOutType(ref name) => write!(
|
||||||
f,
|
f,
|
||||||
@@ -147,9 +147,6 @@ pub struct ColorSpecs {
|
|||||||
/// A `UserColorSpec` can also be converted to a `termcolor::ColorSpec`:
|
/// A `UserColorSpec` can also be converted to a `termcolor::ColorSpec`:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate grep_printer;
|
|
||||||
/// extern crate termcolor;
|
|
||||||
///
|
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// use termcolor::{Color, ColorSpec};
|
/// use termcolor::{Color, ColorSpec};
|
||||||
/// use grep_printer::UserColorSpec;
|
/// use grep_printer::UserColorSpec;
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ use std::time::Instant;
|
|||||||
|
|
||||||
use grep_matcher::{Match, Matcher};
|
use grep_matcher::{Match, Matcher};
|
||||||
use grep_searcher::{
|
use grep_searcher::{
|
||||||
Searcher, Sink, SinkContext, SinkContextKind, SinkError, SinkFinish,
|
Searcher, Sink, SinkContext, SinkContextKind, SinkFinish, SinkMatch,
|
||||||
SinkMatch,
|
|
||||||
};
|
};
|
||||||
use serde_json as json;
|
use serde_json as json;
|
||||||
|
|
||||||
use counter::CounterWriter;
|
use crate::counter::CounterWriter;
|
||||||
use jsont;
|
use crate::jsont;
|
||||||
use stats::Stats;
|
use crate::stats::Stats;
|
||||||
|
use crate::util::find_iter_at_in_context;
|
||||||
|
|
||||||
/// The configuration for the JSON printer.
|
/// The configuration for the JSON printer.
|
||||||
///
|
///
|
||||||
@@ -112,7 +112,7 @@ impl JSONBuilder {
|
|||||||
///
|
///
|
||||||
/// ## Overview
|
/// ## Overview
|
||||||
///
|
///
|
||||||
/// The format of this printer is the [JSON Lines](http://jsonlines.org/)
|
/// The format of this printer is the [JSON Lines](https://jsonlines.org/)
|
||||||
/// format. Specifically, this printer emits a sequence of messages, where
|
/// format. Specifically, this printer emits a sequence of messages, where
|
||||||
/// each message is encoded as a single JSON value on a single line. There are
|
/// each message is encoded as a single JSON value on a single line. There are
|
||||||
/// four different types of messages (and this number may expand over time):
|
/// four different types of messages (and this number may expand over time):
|
||||||
@@ -147,7 +147,7 @@ impl JSONBuilder {
|
|||||||
/// is not limited to UTF-8 exclusively, which in turn implies that matches
|
/// is not limited to UTF-8 exclusively, which in turn implies that matches
|
||||||
/// may be reported that contain invalid UTF-8. Moreover, this printer may
|
/// may be reported that contain invalid UTF-8. Moreover, this printer may
|
||||||
/// also print file paths, and the encoding of file paths is itself not
|
/// also print file paths, and the encoding of file paths is itself not
|
||||||
/// guarnateed to be valid UTF-8. Therefore, this printer must deal with the
|
/// guaranteed to be valid UTF-8. Therefore, this printer must deal with the
|
||||||
/// presence of invalid UTF-8 somehow. The printer could silently ignore such
|
/// presence of invalid UTF-8 somehow. The printer could silently ignore such
|
||||||
/// things completely, or even lossily transcode invalid UTF-8 to valid UTF-8
|
/// things completely, or even lossily transcode invalid UTF-8 to valid UTF-8
|
||||||
/// by replacing all invalid sequences with the Unicode replacement character.
|
/// by replacing all invalid sequences with the Unicode replacement character.
|
||||||
@@ -507,7 +507,10 @@ impl<W: io::Write> JSON<W> {
|
|||||||
|
|
||||||
/// Write the given message followed by a new line. The new line is
|
/// Write the given message followed by a new line. The new line is
|
||||||
/// determined from the configuration of the given searcher.
|
/// determined from the configuration of the given searcher.
|
||||||
fn write_message(&mut self, message: &jsont::Message) -> io::Result<()> {
|
fn write_message(
|
||||||
|
&mut self,
|
||||||
|
message: &jsont::Message<'_>,
|
||||||
|
) -> io::Result<()> {
|
||||||
if self.config.pretty {
|
if self.config.pretty {
|
||||||
json::to_writer_pretty(&mut self.wtr, message)?;
|
json::to_writer_pretty(&mut self.wtr, message)?;
|
||||||
} else {
|
} else {
|
||||||
@@ -552,7 +555,7 @@ impl<W> JSON<W> {
|
|||||||
/// * `W` refers to the underlying writer that this printer is writing its
|
/// * `W` refers to the underlying writer that this printer is writing its
|
||||||
/// output to.
|
/// output to.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct JSONSink<'p, 's, M: Matcher, W: 's> {
|
pub struct JSONSink<'p, 's, M: Matcher, W> {
|
||||||
matcher: M,
|
matcher: M,
|
||||||
json: &'s mut JSON<W>,
|
json: &'s mut JSON<W>,
|
||||||
path: Option<&'p Path>,
|
path: Option<&'p Path>,
|
||||||
@@ -603,7 +606,12 @@ impl<'p, 's, M: Matcher, W: io::Write> JSONSink<'p, 's, M, W> {
|
|||||||
|
|
||||||
/// Execute the matcher over the given bytes and record the match
|
/// Execute the matcher over the given bytes and record the match
|
||||||
/// locations if the current configuration demands match granularity.
|
/// locations if the current configuration demands match granularity.
|
||||||
fn record_matches(&mut self, bytes: &[u8]) -> io::Result<()> {
|
fn record_matches(
|
||||||
|
&mut self,
|
||||||
|
searcher: &Searcher,
|
||||||
|
bytes: &[u8],
|
||||||
|
range: std::ops::Range<usize>,
|
||||||
|
) -> io::Result<()> {
|
||||||
self.json.matches.clear();
|
self.json.matches.clear();
|
||||||
// If printing requires knowing the location of each individual match,
|
// If printing requires knowing the location of each individual match,
|
||||||
// then compute and stored those right now for use later. While this
|
// then compute and stored those right now for use later. While this
|
||||||
@@ -612,12 +620,17 @@ impl<'p, 's, M: Matcher, W: io::Write> JSONSink<'p, 's, M, W> {
|
|||||||
// the extent that it's easy to ensure that we never do more than
|
// the extent that it's easy to ensure that we never do more than
|
||||||
// one search to find the matches.
|
// one search to find the matches.
|
||||||
let matches = &mut self.json.matches;
|
let matches = &mut self.json.matches;
|
||||||
self.matcher
|
find_iter_at_in_context(
|
||||||
.find_iter(bytes, |m| {
|
searcher,
|
||||||
matches.push(m);
|
&self.matcher,
|
||||||
|
bytes,
|
||||||
|
range.clone(),
|
||||||
|
|m| {
|
||||||
|
let (s, e) = (m.start() - range.start, m.end() - range.start);
|
||||||
|
matches.push(Match::new(s, e));
|
||||||
true
|
true
|
||||||
})
|
},
|
||||||
.map_err(io::Error::error_message)?;
|
)?;
|
||||||
// Don't report empty matches appearing at the end of the bytes.
|
// Don't report empty matches appearing at the end of the bytes.
|
||||||
if !matches.is_empty()
|
if !matches.is_empty()
|
||||||
&& matches.last().unwrap().is_empty()
|
&& matches.last().unwrap().is_empty()
|
||||||
@@ -644,6 +657,16 @@ impl<'p, 's, M: Matcher, W: io::Write> JSONSink<'p, 's, M, W> {
|
|||||||
self.after_context_remaining == 0
|
self.after_context_remaining == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether the current match count exceeds the configured limit.
|
||||||
|
/// If there is no limit, then this always returns false.
|
||||||
|
fn match_more_than_limit(&self) -> bool {
|
||||||
|
let limit = match self.json.config.max_matches {
|
||||||
|
None => return false,
|
||||||
|
Some(limit) => limit,
|
||||||
|
};
|
||||||
|
self.match_count > limit
|
||||||
|
}
|
||||||
|
|
||||||
/// Write the "begin" message.
|
/// Write the "begin" message.
|
||||||
fn write_begin_message(&mut self) -> io::Result<()> {
|
fn write_begin_message(&mut self) -> io::Result<()> {
|
||||||
if self.begin_printed {
|
if self.begin_printed {
|
||||||
@@ -662,13 +685,30 @@ impl<'p, 's, M: Matcher, W: io::Write> Sink for JSONSink<'p, 's, M, W> {
|
|||||||
fn matched(
|
fn matched(
|
||||||
&mut self,
|
&mut self,
|
||||||
searcher: &Searcher,
|
searcher: &Searcher,
|
||||||
mat: &SinkMatch,
|
mat: &SinkMatch<'_>,
|
||||||
) -> Result<bool, io::Error> {
|
) -> Result<bool, io::Error> {
|
||||||
self.write_begin_message()?;
|
self.write_begin_message()?;
|
||||||
|
|
||||||
self.match_count += 1;
|
self.match_count += 1;
|
||||||
|
// When we've exceeded our match count, then the remaining context
|
||||||
|
// lines should not be reset, but instead, decremented. This avoids a
|
||||||
|
// bug where we display more matches than a configured limit. The main
|
||||||
|
// idea here is that 'matched' might be called again while printing
|
||||||
|
// an after-context line. In that case, we should treat this as a
|
||||||
|
// contextual line rather than a matching line for the purposes of
|
||||||
|
// termination.
|
||||||
|
if self.match_more_than_limit() {
|
||||||
|
self.after_context_remaining =
|
||||||
|
self.after_context_remaining.saturating_sub(1);
|
||||||
|
} else {
|
||||||
self.after_context_remaining = searcher.after_context() as u64;
|
self.after_context_remaining = searcher.after_context() as u64;
|
||||||
self.record_matches(mat.bytes())?;
|
}
|
||||||
|
|
||||||
|
self.record_matches(
|
||||||
|
searcher,
|
||||||
|
mat.buffer(),
|
||||||
|
mat.bytes_range_in_buffer(),
|
||||||
|
)?;
|
||||||
self.stats.add_matches(self.json.matches.len() as u64);
|
self.stats.add_matches(self.json.matches.len() as u64);
|
||||||
self.stats.add_matched_lines(mat.lines().count() as u64);
|
self.stats.add_matched_lines(mat.lines().count() as u64);
|
||||||
|
|
||||||
@@ -687,7 +727,7 @@ impl<'p, 's, M: Matcher, W: io::Write> Sink for JSONSink<'p, 's, M, W> {
|
|||||||
fn context(
|
fn context(
|
||||||
&mut self,
|
&mut self,
|
||||||
searcher: &Searcher,
|
searcher: &Searcher,
|
||||||
ctx: &SinkContext,
|
ctx: &SinkContext<'_>,
|
||||||
) -> Result<bool, io::Error> {
|
) -> Result<bool, io::Error> {
|
||||||
self.write_begin_message()?;
|
self.write_begin_message()?;
|
||||||
self.json.matches.clear();
|
self.json.matches.clear();
|
||||||
@@ -697,7 +737,7 @@ impl<'p, 's, M: Matcher, W: io::Write> Sink for JSONSink<'p, 's, M, W> {
|
|||||||
self.after_context_remaining.saturating_sub(1);
|
self.after_context_remaining.saturating_sub(1);
|
||||||
}
|
}
|
||||||
let submatches = if searcher.invert_match() {
|
let submatches = if searcher.invert_match() {
|
||||||
self.record_matches(ctx.bytes())?;
|
self.record_matches(searcher, ctx.bytes(), 0..ctx.bytes().len())?;
|
||||||
SubMatches::new(ctx.bytes(), &self.json.matches)
|
SubMatches::new(ctx.bytes(), &self.json.matches)
|
||||||
} else {
|
} else {
|
||||||
SubMatches::empty()
|
SubMatches::empty()
|
||||||
@@ -799,7 +839,7 @@ impl<'a> SubMatches<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return this set of match ranges as a slice.
|
/// Return this set of match ranges as a slice.
|
||||||
fn as_slice(&self) -> &[jsont::SubMatch] {
|
fn as_slice(&self) -> &[jsont::SubMatch<'_>] {
|
||||||
match *self {
|
match *self {
|
||||||
SubMatches::Empty => &[],
|
SubMatches::Empty => &[],
|
||||||
SubMatches::Small(ref x) => x,
|
SubMatches::Small(ref x) => x,
|
||||||
@@ -871,6 +911,38 @@ and exhibited clearly, with a label attached.\
|
|||||||
assert_eq!(got.lines().count(), 3);
|
assert_eq!(got.lines().count(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn max_matches_after_context() {
|
||||||
|
let haystack = "\
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
e
|
||||||
|
d
|
||||||
|
e
|
||||||
|
d
|
||||||
|
e
|
||||||
|
d
|
||||||
|
e
|
||||||
|
";
|
||||||
|
let matcher = RegexMatcher::new(r"d").unwrap();
|
||||||
|
let mut printer =
|
||||||
|
JSONBuilder::new().max_matches(Some(1)).build(vec![]);
|
||||||
|
SearcherBuilder::new()
|
||||||
|
.after_context(2)
|
||||||
|
.build()
|
||||||
|
.search_reader(
|
||||||
|
&matcher,
|
||||||
|
haystack.as_bytes(),
|
||||||
|
printer.sink(&matcher),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let got = printer_contents(&mut printer);
|
||||||
|
|
||||||
|
assert_eq!(got.lines().count(), 5);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn no_match() {
|
fn no_match() {
|
||||||
let matcher = RegexMatcher::new(r"DOES NOT MATCH").unwrap();
|
let matcher = RegexMatcher::new(r"DOES NOT MATCH").unwrap();
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use std::str;
|
|||||||
use base64;
|
use base64;
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Serialize, Serializer};
|
||||||
|
|
||||||
use stats::Stats;
|
use crate::stats::Stats;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[serde(tag = "type", content = "data")]
|
#[serde(tag = "type", content = "data")]
|
||||||
@@ -90,7 +90,7 @@ enum Data<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Data<'a> {
|
impl<'a> Data<'a> {
|
||||||
fn from_bytes(bytes: &[u8]) -> Data {
|
fn from_bytes(bytes: &[u8]) -> Data<'_> {
|
||||||
match str::from_utf8(bytes) {
|
match str::from_utf8(bytes) {
|
||||||
Ok(text) => Data::Text { text: Cow::Borrowed(text) },
|
Ok(text) => Data::Text { text: Cow::Borrowed(text) },
|
||||||
Err(_) => Data::Bytes { bytes },
|
Err(_) => Data::Bytes { bytes },
|
||||||
@@ -98,7 +98,7 @@ impl<'a> Data<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn from_path(path: &Path) -> Data {
|
fn from_path(path: &Path) -> Data<'_> {
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
match path.to_str() {
|
match path.to_str() {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ statistics.
|
|||||||
|
|
||||||
The [`JSON`](struct.JSON.html) printer shows results in a machine readable
|
The [`JSON`](struct.JSON.html) printer shows results in a machine readable
|
||||||
format. To facilitate a stream of search results, the format uses
|
format. To facilitate a stream of search results, the format uses
|
||||||
[JSON Lines](http://jsonlines.org/)
|
[JSON Lines](https://jsonlines.org/)
|
||||||
by emitting a series of messages as search results are found.
|
by emitting a series of messages as search results are found.
|
||||||
|
|
||||||
The [`Summary`](struct.Summary.html) printer shows *aggregate* results for a
|
The [`Summary`](struct.Summary.html) printer shows *aggregate* results for a
|
||||||
@@ -27,10 +27,6 @@ contain matches.
|
|||||||
This example shows how to create a "standard" printer and execute a search.
|
This example shows how to create a "standard" printer and execute a search.
|
||||||
|
|
||||||
```
|
```
|
||||||
extern crate grep_regex;
|
|
||||||
extern crate grep_printer;
|
|
||||||
extern crate grep_searcher;
|
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use grep_regex::RegexMatcher;
|
use grep_regex::RegexMatcher;
|
||||||
@@ -68,29 +64,26 @@ fn example() -> Result<(), Box<Error>> {
|
|||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
pub use crate::color::{
|
||||||
|
default_color_specs, ColorError, ColorSpecs, UserColorSpec,
|
||||||
|
};
|
||||||
#[cfg(feature = "serde1")]
|
#[cfg(feature = "serde1")]
|
||||||
extern crate base64;
|
pub use crate::json::{JSONBuilder, JSONSink, JSON};
|
||||||
extern crate bstr;
|
pub use crate::standard::{Standard, StandardBuilder, StandardSink};
|
||||||
extern crate grep_matcher;
|
pub use crate::stats::Stats;
|
||||||
#[cfg(test)]
|
pub use crate::summary::{Summary, SummaryBuilder, SummaryKind, SummarySink};
|
||||||
extern crate grep_regex;
|
pub use crate::util::PrinterPath;
|
||||||
extern crate grep_searcher;
|
|
||||||
#[cfg(feature = "serde1")]
|
|
||||||
extern crate serde;
|
|
||||||
#[cfg(feature = "serde1")]
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
#[cfg(feature = "serde1")]
|
|
||||||
extern crate serde_json;
|
|
||||||
extern crate termcolor;
|
|
||||||
|
|
||||||
pub use color::{default_color_specs, ColorError, ColorSpecs, UserColorSpec};
|
// The maximum number of bytes to execute a search to account for look-ahead.
|
||||||
#[cfg(feature = "serde1")]
|
//
|
||||||
pub use json::{JSONBuilder, JSONSink, JSON};
|
// This is an unfortunate kludge since PCRE2 doesn't provide a way to search
|
||||||
pub use standard::{Standard, StandardBuilder, StandardSink};
|
// a substring of some input while accounting for look-ahead. In theory, we
|
||||||
pub use stats::Stats;
|
// could refactor the various 'grep' interfaces to account for it, but it would
|
||||||
pub use summary::{Summary, SummaryBuilder, SummaryKind, SummarySink};
|
// be a large change. So for now, we just let PCRE2 go looking a bit for a
|
||||||
pub use util::PrinterPath;
|
// match without searching the entire rest of the contents.
|
||||||
|
//
|
||||||
|
// Note that this kludge is only active in multi-line mode.
|
||||||
|
const MAX_LOOK_AHEAD: usize = 128;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|||||||
@@ -8,15 +8,18 @@ use std::time::Instant;
|
|||||||
use bstr::ByteSlice;
|
use bstr::ByteSlice;
|
||||||
use grep_matcher::{Match, Matcher};
|
use grep_matcher::{Match, Matcher};
|
||||||
use grep_searcher::{
|
use grep_searcher::{
|
||||||
LineStep, Searcher, Sink, SinkContext, SinkContextKind, SinkError,
|
LineStep, Searcher, Sink, SinkContext, SinkContextKind, SinkFinish,
|
||||||
SinkFinish, SinkMatch,
|
SinkMatch,
|
||||||
};
|
};
|
||||||
use termcolor::{ColorSpec, NoColor, WriteColor};
|
use termcolor::{ColorSpec, NoColor, WriteColor};
|
||||||
|
|
||||||
use color::ColorSpecs;
|
use crate::color::ColorSpecs;
|
||||||
use counter::CounterWriter;
|
use crate::counter::CounterWriter;
|
||||||
use stats::Stats;
|
use crate::stats::Stats;
|
||||||
use util::{trim_ascii_prefix, PrinterPath, Replacer, Sunk};
|
use crate::util::{
|
||||||
|
find_iter_at_in_context, trim_ascii_prefix, trim_line_terminator,
|
||||||
|
PrinterPath, Replacer, Sunk,
|
||||||
|
};
|
||||||
|
|
||||||
/// The configuration for the standard printer.
|
/// The configuration for the standard printer.
|
||||||
///
|
///
|
||||||
@@ -31,6 +34,7 @@ struct Config {
|
|||||||
path: bool,
|
path: bool,
|
||||||
only_matching: bool,
|
only_matching: bool,
|
||||||
per_match: bool,
|
per_match: bool,
|
||||||
|
per_match_one_line: bool,
|
||||||
replacement: Arc<Option<Vec<u8>>>,
|
replacement: Arc<Option<Vec<u8>>>,
|
||||||
max_columns: Option<u64>,
|
max_columns: Option<u64>,
|
||||||
max_columns_preview: bool,
|
max_columns_preview: bool,
|
||||||
@@ -55,6 +59,7 @@ impl Default for Config {
|
|||||||
path: true,
|
path: true,
|
||||||
only_matching: false,
|
only_matching: false,
|
||||||
per_match: false,
|
per_match: false,
|
||||||
|
per_match_one_line: false,
|
||||||
replacement: Arc::new(None),
|
replacement: Arc::new(None),
|
||||||
max_columns: None,
|
max_columns: None,
|
||||||
max_columns_preview: false,
|
max_columns_preview: false,
|
||||||
@@ -219,15 +224,36 @@ impl StandardBuilder {
|
|||||||
/// the `column` option, which will show the starting column number for
|
/// the `column` option, which will show the starting column number for
|
||||||
/// every match on every line.
|
/// every match on every line.
|
||||||
///
|
///
|
||||||
/// When multi-line mode is enabled, each match and its accompanying lines
|
/// When multi-line mode is enabled, each match is printed, including every
|
||||||
/// are printed. As with single line matches, if a line contains multiple
|
/// line in the match. As with single line matches, if a line contains
|
||||||
/// matches (even if only partially), then that line is printed once for
|
/// multiple matches (even if only partially), then that line is printed
|
||||||
/// each match it participates in.
|
/// once for each match it participates in, assuming it's the first line in
|
||||||
|
/// that match. In multi-line mode, column numbers only indicate the start
|
||||||
|
/// of a match. Subsequent lines in a multi-line match always have a column
|
||||||
|
/// number of `1`.
|
||||||
|
///
|
||||||
|
/// When a match contains multiple lines, enabling `per_match_one_line`
|
||||||
|
/// will cause only the first line each in match to be printed.
|
||||||
pub fn per_match(&mut self, yes: bool) -> &mut StandardBuilder {
|
pub fn per_match(&mut self, yes: bool) -> &mut StandardBuilder {
|
||||||
self.config.per_match = yes;
|
self.config.per_match = yes;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print at most one line per match when `per_match` is enabled.
|
||||||
|
///
|
||||||
|
/// By default, every line in each match found is printed when `per_match`
|
||||||
|
/// is enabled. However, this is sometimes undesirable, e.g., when you
|
||||||
|
/// only ever want one line per match.
|
||||||
|
///
|
||||||
|
/// This is only applicable when multi-line matching is enabled, since
|
||||||
|
/// otherwise, matches are guaranteed to span one line.
|
||||||
|
///
|
||||||
|
/// This is disabled by default.
|
||||||
|
pub fn per_match_one_line(&mut self, yes: bool) -> &mut StandardBuilder {
|
||||||
|
self.config.per_match_one_line = yes;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the bytes that will be used to replace each occurrence of a match
|
/// Set the bytes that will be used to replace each occurrence of a match
|
||||||
/// found.
|
/// found.
|
||||||
///
|
///
|
||||||
@@ -292,9 +318,6 @@ impl StandardBuilder {
|
|||||||
/// Column numbers are computed in terms of bytes from the start of the
|
/// Column numbers are computed in terms of bytes from the start of the
|
||||||
/// line being printed.
|
/// line being printed.
|
||||||
///
|
///
|
||||||
/// For matches that span multiple lines, the column number for each
|
|
||||||
/// matching line is in terms of the first matching line.
|
|
||||||
///
|
|
||||||
/// This is disabled by default.
|
/// This is disabled by default.
|
||||||
pub fn column(&mut self, yes: bool) -> &mut StandardBuilder {
|
pub fn column(&mut self, yes: bool) -> &mut StandardBuilder {
|
||||||
self.config.column = yes;
|
self.config.column = yes;
|
||||||
@@ -602,7 +625,7 @@ impl<W> Standard<W> {
|
|||||||
/// * `W` refers to the underlying writer that this printer is writing its
|
/// * `W` refers to the underlying writer that this printer is writing its
|
||||||
/// output to.
|
/// output to.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StandardSink<'p, 's, M: Matcher, W: 's> {
|
pub struct StandardSink<'p, 's, M: Matcher, W> {
|
||||||
matcher: M,
|
matcher: M,
|
||||||
standard: &'s mut Standard<W>,
|
standard: &'s mut Standard<W>,
|
||||||
replacer: Replacer<M>,
|
replacer: Replacer<M>,
|
||||||
@@ -662,7 +685,12 @@ impl<'p, 's, M: Matcher, W: WriteColor> StandardSink<'p, 's, M, W> {
|
|||||||
|
|
||||||
/// Execute the matcher over the given bytes and record the match
|
/// Execute the matcher over the given bytes and record the match
|
||||||
/// locations if the current configuration demands match granularity.
|
/// locations if the current configuration demands match granularity.
|
||||||
fn record_matches(&mut self, bytes: &[u8]) -> io::Result<()> {
|
fn record_matches(
|
||||||
|
&mut self,
|
||||||
|
searcher: &Searcher,
|
||||||
|
bytes: &[u8],
|
||||||
|
range: std::ops::Range<usize>,
|
||||||
|
) -> io::Result<()> {
|
||||||
self.standard.matches.clear();
|
self.standard.matches.clear();
|
||||||
if !self.needs_match_granularity {
|
if !self.needs_match_granularity {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -675,16 +703,21 @@ impl<'p, 's, M: Matcher, W: WriteColor> StandardSink<'p, 's, M, W> {
|
|||||||
// one search to find the matches (well, for replacements, we do one
|
// one search to find the matches (well, for replacements, we do one
|
||||||
// additional search to perform the actual replacement).
|
// additional search to perform the actual replacement).
|
||||||
let matches = &mut self.standard.matches;
|
let matches = &mut self.standard.matches;
|
||||||
self.matcher
|
find_iter_at_in_context(
|
||||||
.find_iter(bytes, |m| {
|
searcher,
|
||||||
matches.push(m);
|
&self.matcher,
|
||||||
|
bytes,
|
||||||
|
range.clone(),
|
||||||
|
|m| {
|
||||||
|
let (s, e) = (m.start() - range.start, m.end() - range.start);
|
||||||
|
matches.push(Match::new(s, e));
|
||||||
true
|
true
|
||||||
})
|
},
|
||||||
.map_err(io::Error::error_message)?;
|
)?;
|
||||||
// Don't report empty matches appearing at the end of the bytes.
|
// Don't report empty matches appearing at the end of the bytes.
|
||||||
if !matches.is_empty()
|
if !matches.is_empty()
|
||||||
&& matches.last().unwrap().is_empty()
|
&& matches.last().unwrap().is_empty()
|
||||||
&& matches.last().unwrap().start() >= bytes.len()
|
&& matches.last().unwrap().start() >= range.end
|
||||||
{
|
{
|
||||||
matches.pop().unwrap();
|
matches.pop().unwrap();
|
||||||
}
|
}
|
||||||
@@ -695,14 +728,25 @@ impl<'p, 's, M: Matcher, W: WriteColor> StandardSink<'p, 's, M, W> {
|
|||||||
/// replacement, lazily allocating memory if necessary.
|
/// replacement, lazily allocating memory if necessary.
|
||||||
///
|
///
|
||||||
/// To access the result of a replacement, use `replacer.replacement()`.
|
/// To access the result of a replacement, use `replacer.replacement()`.
|
||||||
fn replace(&mut self, bytes: &[u8]) -> io::Result<()> {
|
fn replace(
|
||||||
|
&mut self,
|
||||||
|
searcher: &Searcher,
|
||||||
|
bytes: &[u8],
|
||||||
|
range: std::ops::Range<usize>,
|
||||||
|
) -> io::Result<()> {
|
||||||
self.replacer.clear();
|
self.replacer.clear();
|
||||||
if self.standard.config.replacement.is_some() {
|
if self.standard.config.replacement.is_some() {
|
||||||
let replacement = (*self.standard.config.replacement)
|
let replacement = (*self.standard.config.replacement)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|r| &*r)
|
.map(|r| &*r)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.replacer.replace_all(&self.matcher, bytes, replacement)?;
|
self.replacer.replace_all(
|
||||||
|
searcher,
|
||||||
|
&self.matcher,
|
||||||
|
bytes,
|
||||||
|
range,
|
||||||
|
replacement,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -722,6 +766,16 @@ impl<'p, 's, M: Matcher, W: WriteColor> StandardSink<'p, 's, M, W> {
|
|||||||
}
|
}
|
||||||
self.after_context_remaining == 0
|
self.after_context_remaining == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether the current match count exceeds the configured limit.
|
||||||
|
/// If there is no limit, then this always returns false.
|
||||||
|
fn match_more_than_limit(&self) -> bool {
|
||||||
|
let limit = match self.standard.config.max_matches {
|
||||||
|
None => return false,
|
||||||
|
Some(limit) => limit,
|
||||||
|
};
|
||||||
|
self.match_count > limit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p, 's, M: Matcher, W: WriteColor> Sink for StandardSink<'p, 's, M, W> {
|
impl<'p, 's, M: Matcher, W: WriteColor> Sink for StandardSink<'p, 's, M, W> {
|
||||||
@@ -730,13 +784,29 @@ impl<'p, 's, M: Matcher, W: WriteColor> Sink for StandardSink<'p, 's, M, W> {
|
|||||||
fn matched(
|
fn matched(
|
||||||
&mut self,
|
&mut self,
|
||||||
searcher: &Searcher,
|
searcher: &Searcher,
|
||||||
mat: &SinkMatch,
|
mat: &SinkMatch<'_>,
|
||||||
) -> Result<bool, io::Error> {
|
) -> Result<bool, io::Error> {
|
||||||
self.match_count += 1;
|
self.match_count += 1;
|
||||||
|
// When we've exceeded our match count, then the remaining context
|
||||||
|
// lines should not be reset, but instead, decremented. This avoids a
|
||||||
|
// bug where we display more matches than a configured limit. The main
|
||||||
|
// idea here is that 'matched' might be called again while printing
|
||||||
|
// an after-context line. In that case, we should treat this as a
|
||||||
|
// contextual line rather than a matching line for the purposes of
|
||||||
|
// termination.
|
||||||
|
if self.match_more_than_limit() {
|
||||||
|
self.after_context_remaining =
|
||||||
|
self.after_context_remaining.saturating_sub(1);
|
||||||
|
} else {
|
||||||
self.after_context_remaining = searcher.after_context() as u64;
|
self.after_context_remaining = searcher.after_context() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
self.record_matches(mat.bytes())?;
|
self.record_matches(
|
||||||
self.replace(mat.bytes())?;
|
searcher,
|
||||||
|
mat.buffer(),
|
||||||
|
mat.bytes_range_in_buffer(),
|
||||||
|
)?;
|
||||||
|
self.replace(searcher, mat.buffer(), mat.bytes_range_in_buffer())?;
|
||||||
|
|
||||||
if let Some(ref mut stats) = self.stats {
|
if let Some(ref mut stats) = self.stats {
|
||||||
stats.add_matches(self.standard.matches.len() as u64);
|
stats.add_matches(self.standard.matches.len() as u64);
|
||||||
@@ -755,7 +825,7 @@ impl<'p, 's, M: Matcher, W: WriteColor> Sink for StandardSink<'p, 's, M, W> {
|
|||||||
fn context(
|
fn context(
|
||||||
&mut self,
|
&mut self,
|
||||||
searcher: &Searcher,
|
searcher: &Searcher,
|
||||||
ctx: &SinkContext,
|
ctx: &SinkContext<'_>,
|
||||||
) -> Result<bool, io::Error> {
|
) -> Result<bool, io::Error> {
|
||||||
self.standard.matches.clear();
|
self.standard.matches.clear();
|
||||||
self.replacer.clear();
|
self.replacer.clear();
|
||||||
@@ -765,8 +835,8 @@ impl<'p, 's, M: Matcher, W: WriteColor> Sink for StandardSink<'p, 's, M, W> {
|
|||||||
self.after_context_remaining.saturating_sub(1);
|
self.after_context_remaining.saturating_sub(1);
|
||||||
}
|
}
|
||||||
if searcher.invert_match() {
|
if searcher.invert_match() {
|
||||||
self.record_matches(ctx.bytes())?;
|
self.record_matches(searcher, ctx.bytes(), 0..ctx.bytes().len())?;
|
||||||
self.replace(ctx.bytes())?;
|
self.replace(searcher, ctx.bytes(), 0..ctx.bytes().len())?;
|
||||||
}
|
}
|
||||||
if searcher.binary_detection().convert_byte().is_some() {
|
if searcher.binary_detection().convert_byte().is_some() {
|
||||||
if self.binary_byte_offset.is_some() {
|
if self.binary_byte_offset.is_some() {
|
||||||
@@ -834,7 +904,7 @@ impl<'p, 's, M: Matcher, W: WriteColor> Sink for StandardSink<'p, 's, M, W> {
|
|||||||
/// A StandardImpl is initialized every time a match or a contextual line is
|
/// A StandardImpl is initialized every time a match or a contextual line is
|
||||||
/// reported.
|
/// reported.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct StandardImpl<'a, M: 'a + Matcher, W: 'a> {
|
struct StandardImpl<'a, M: Matcher, W> {
|
||||||
searcher: &'a Searcher,
|
searcher: &'a Searcher,
|
||||||
sink: &'a StandardSink<'a, 'a, M, W>,
|
sink: &'a StandardSink<'a, 'a, M, W>,
|
||||||
sunk: Sunk<'a>,
|
sunk: Sunk<'a>,
|
||||||
@@ -846,7 +916,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
|||||||
/// Bundle self with a searcher and return the core implementation of Sink.
|
/// Bundle self with a searcher and return the core implementation of Sink.
|
||||||
fn new(
|
fn new(
|
||||||
searcher: &'a Searcher,
|
searcher: &'a Searcher,
|
||||||
sink: &'a StandardSink<M, W>,
|
sink: &'a StandardSink<'_, '_, M, W>,
|
||||||
) -> StandardImpl<'a, M, W> {
|
) -> StandardImpl<'a, M, W> {
|
||||||
StandardImpl {
|
StandardImpl {
|
||||||
searcher: searcher,
|
searcher: searcher,
|
||||||
@@ -860,7 +930,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
|||||||
/// for use with handling matching lines.
|
/// for use with handling matching lines.
|
||||||
fn from_match(
|
fn from_match(
|
||||||
searcher: &'a Searcher,
|
searcher: &'a Searcher,
|
||||||
sink: &'a StandardSink<M, W>,
|
sink: &'a StandardSink<'_, '_, M, W>,
|
||||||
mat: &'a SinkMatch<'a>,
|
mat: &'a SinkMatch<'a>,
|
||||||
) -> StandardImpl<'a, M, W> {
|
) -> StandardImpl<'a, M, W> {
|
||||||
let sunk = Sunk::from_sink_match(
|
let sunk = Sunk::from_sink_match(
|
||||||
@@ -875,7 +945,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
|||||||
/// for use with handling contextual lines.
|
/// for use with handling contextual lines.
|
||||||
fn from_context(
|
fn from_context(
|
||||||
searcher: &'a Searcher,
|
searcher: &'a Searcher,
|
||||||
sink: &'a StandardSink<M, W>,
|
sink: &'a StandardSink<'_, '_, M, W>,
|
||||||
ctx: &'a SinkContext<'a>,
|
ctx: &'a SinkContext<'a>,
|
||||||
) -> StandardImpl<'a, M, W> {
|
) -> StandardImpl<'a, M, W> {
|
||||||
let sunk = Sunk::from_sink_context(
|
let sunk = Sunk::from_sink_context(
|
||||||
@@ -1090,7 +1160,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
|||||||
self.write_prelude(
|
self.write_prelude(
|
||||||
self.sunk.absolute_byte_offset() + line.start() as u64,
|
self.sunk.absolute_byte_offset() + line.start() as u64,
|
||||||
self.sunk.line_number().map(|n| n + count),
|
self.sunk.line_number().map(|n| n + count),
|
||||||
Some(m.start() as u64 + 1),
|
Some(m.start().saturating_sub(line.start()) as u64 + 1),
|
||||||
)?;
|
)?;
|
||||||
count += 1;
|
count += 1;
|
||||||
if self.exceeds_max_columns(&bytes[line]) {
|
if self.exceeds_max_columns(&bytes[line]) {
|
||||||
@@ -1115,6 +1185,15 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.write_line_term()?;
|
self.write_line_term()?;
|
||||||
|
// It turns out that vimgrep really only wants one line per
|
||||||
|
// match, even when a match spans multiple lines. So when
|
||||||
|
// that option is enabled, we just quit after printing the
|
||||||
|
// first line.
|
||||||
|
//
|
||||||
|
// See: https://github.com/BurntSushi/ripgrep/issues/1866
|
||||||
|
if self.config().per_match_one_line {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1358,25 +1437,24 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
|||||||
|
|
||||||
let bin = self.searcher.binary_detection();
|
let bin = self.searcher.binary_detection();
|
||||||
if let Some(byte) = bin.quit_byte() {
|
if let Some(byte) = bin.quit_byte() {
|
||||||
self.write(b"WARNING: stopped searching binary file ")?;
|
|
||||||
if let Some(path) = self.path() {
|
if let Some(path) = self.path() {
|
||||||
self.write_spec(self.config().colors.path(), path.as_bytes())?;
|
self.write_spec(self.config().colors.path(), path.as_bytes())?;
|
||||||
self.write(b" ")?;
|
self.write(b": ")?;
|
||||||
}
|
}
|
||||||
let remainder = format!(
|
let remainder = format!(
|
||||||
"after match (found {:?} byte around offset {})\n",
|
"WARNING: stopped searching binary file after match \
|
||||||
|
(found {:?} byte around offset {})\n",
|
||||||
[byte].as_bstr(),
|
[byte].as_bstr(),
|
||||||
offset,
|
offset,
|
||||||
);
|
);
|
||||||
self.write(remainder.as_bytes())?;
|
self.write(remainder.as_bytes())?;
|
||||||
} else if let Some(byte) = bin.convert_byte() {
|
} else if let Some(byte) = bin.convert_byte() {
|
||||||
self.write(b"Binary file ")?;
|
|
||||||
if let Some(path) = self.path() {
|
if let Some(path) = self.path() {
|
||||||
self.write_spec(self.config().colors.path(), path.as_bytes())?;
|
self.write_spec(self.config().colors.path(), path.as_bytes())?;
|
||||||
self.write(b" ")?;
|
self.write(b": ")?;
|
||||||
}
|
}
|
||||||
let remainder = format!(
|
let remainder = format!(
|
||||||
"matches (found {:?} byte around offset {})\n",
|
"binary file matches (found {:?} byte around offset {})\n",
|
||||||
[byte].as_bstr(),
|
[byte].as_bstr(),
|
||||||
offset,
|
offset,
|
||||||
);
|
);
|
||||||
@@ -1470,14 +1548,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn trim_line_terminator(&self, buf: &[u8], line: &mut Match) {
|
fn trim_line_terminator(&self, buf: &[u8], line: &mut Match) {
|
||||||
let lineterm = self.searcher.line_terminator();
|
trim_line_terminator(&self.searcher, buf, line);
|
||||||
if lineterm.is_suffix(&buf[*line]) {
|
|
||||||
let mut end = line.end() - 1;
|
|
||||||
if lineterm.is_crlf() && buf[end - 1] == b'\r' {
|
|
||||||
end -= 1;
|
|
||||||
}
|
|
||||||
*line = line.with_end(end);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_line_terminator(&self, buf: &[u8]) -> bool {
|
fn has_line_terminator(&self, buf: &[u8]) -> bool {
|
||||||
@@ -1523,7 +1594,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
|||||||
/// multiple lines.
|
/// multiple lines.
|
||||||
///
|
///
|
||||||
/// Note that this doesn't just return whether the searcher is in multi
|
/// Note that this doesn't just return whether the searcher is in multi
|
||||||
/// line mode, but also checks if the mater can match over multiple lines.
|
/// line mode, but also checks if the matter can match over multiple lines.
|
||||||
/// If it can't, then we don't need multi line handling, even if the
|
/// If it can't, then we don't need multi line handling, even if the
|
||||||
/// searcher has multi line mode enabled.
|
/// searcher has multi line mode enabled.
|
||||||
fn multi_line(&self) -> bool {
|
fn multi_line(&self) -> bool {
|
||||||
@@ -1546,11 +1617,12 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use grep_regex::RegexMatcher;
|
use grep_matcher::LineTerminator;
|
||||||
|
use grep_regex::{RegexMatcher, RegexMatcherBuilder};
|
||||||
use grep_searcher::SearcherBuilder;
|
use grep_searcher::SearcherBuilder;
|
||||||
use termcolor::NoColor;
|
use termcolor::{Ansi, NoColor};
|
||||||
|
|
||||||
use super::{Standard, StandardBuilder};
|
use super::{ColorSpecs, Standard, StandardBuilder};
|
||||||
|
|
||||||
const SHERLOCK: &'static str = "\
|
const SHERLOCK: &'static str = "\
|
||||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||||
@@ -1575,6 +1647,10 @@ and exhibited clearly, with a label attached.\
|
|||||||
String::from_utf8(printer.get_mut().get_ref().to_owned()).unwrap()
|
String::from_utf8(printer.get_mut().get_ref().to_owned()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn printer_contents_ansi(printer: &mut Standard<Ansi<Vec<u8>>>) -> String {
|
||||||
|
String::from_utf8(printer.get_mut().get_ref().to_owned()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reports_match() {
|
fn reports_match() {
|
||||||
let matcher = RegexMatcher::new("Sherlock").unwrap();
|
let matcher = RegexMatcher::new("Sherlock").unwrap();
|
||||||
@@ -2991,9 +3067,9 @@ Holmeses, success in the province of detective work must always
|
|||||||
let got = printer_contents(&mut printer);
|
let got = printer_contents(&mut printer);
|
||||||
let expected = "\
|
let expected = "\
|
||||||
1:16:For the Doctor Watsons of this world, as opposed to the Sherlock
|
1:16:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||||
2:16:Holmeses, success in the province of detective work must always
|
2:1:Holmeses, success in the province of detective work must always
|
||||||
5:12:but Doctor Watson has to have it taken out for him and dusted,
|
5:12:but Doctor Watson has to have it taken out for him and dusted,
|
||||||
6:12:and exhibited clearly, with a label attached.
|
6:1:and exhibited clearly, with a label attached.
|
||||||
";
|
";
|
||||||
assert_eq_printed!(expected, got);
|
assert_eq_printed!(expected, got);
|
||||||
}
|
}
|
||||||
@@ -3020,9 +3096,94 @@ Holmeses, success in the province of detective work must always
|
|||||||
let got = printer_contents(&mut printer);
|
let got = printer_contents(&mut printer);
|
||||||
let expected = "\
|
let expected = "\
|
||||||
1:16:For the Doctor Watsons of this world, as opposed to the Sherlock
|
1:16:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||||
2:16:Holmeses, success in the province of detective work must always
|
2:1:Holmeses, success in the province of detective work must always
|
||||||
2:123:Holmeses, success in the province of detective work must always
|
2:58:Holmeses, success in the province of detective work must always
|
||||||
3:123:be, to a very large extent, the result of luck. Sherlock Holmes
|
3:1:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||||
|
";
|
||||||
|
assert_eq_printed!(expected, got);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn per_match_multi_line1_only_first_line() {
|
||||||
|
let matcher =
|
||||||
|
RegexMatcher::new(r"(?s:.{0})(Doctor Watsons|Sherlock)").unwrap();
|
||||||
|
let mut printer = StandardBuilder::new()
|
||||||
|
.per_match(true)
|
||||||
|
.per_match_one_line(true)
|
||||||
|
.column(true)
|
||||||
|
.build(NoColor::new(vec![]));
|
||||||
|
SearcherBuilder::new()
|
||||||
|
.multi_line(true)
|
||||||
|
.line_number(true)
|
||||||
|
.build()
|
||||||
|
.search_reader(
|
||||||
|
&matcher,
|
||||||
|
SHERLOCK.as_bytes(),
|
||||||
|
printer.sink(&matcher),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let got = printer_contents(&mut printer);
|
||||||
|
let expected = "\
|
||||||
|
1:9:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||||
|
1:57:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||||
|
3:49:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||||
|
";
|
||||||
|
assert_eq_printed!(expected, got);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn per_match_multi_line2_only_first_line() {
|
||||||
|
let matcher =
|
||||||
|
RegexMatcher::new(r"(?s)Watson.+?(Holmeses|clearly)").unwrap();
|
||||||
|
let mut printer = StandardBuilder::new()
|
||||||
|
.per_match(true)
|
||||||
|
.per_match_one_line(true)
|
||||||
|
.column(true)
|
||||||
|
.build(NoColor::new(vec![]));
|
||||||
|
SearcherBuilder::new()
|
||||||
|
.multi_line(true)
|
||||||
|
.line_number(true)
|
||||||
|
.build()
|
||||||
|
.search_reader(
|
||||||
|
&matcher,
|
||||||
|
SHERLOCK.as_bytes(),
|
||||||
|
printer.sink(&matcher),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let got = printer_contents(&mut printer);
|
||||||
|
let expected = "\
|
||||||
|
1:16:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||||
|
5:12:but Doctor Watson has to have it taken out for him and dusted,
|
||||||
|
";
|
||||||
|
assert_eq_printed!(expected, got);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn per_match_multi_line3_only_first_line() {
|
||||||
|
let matcher =
|
||||||
|
RegexMatcher::new(r"(?s)Watson.+?Holmeses|always.+?be").unwrap();
|
||||||
|
let mut printer = StandardBuilder::new()
|
||||||
|
.per_match(true)
|
||||||
|
.per_match_one_line(true)
|
||||||
|
.column(true)
|
||||||
|
.build(NoColor::new(vec![]));
|
||||||
|
SearcherBuilder::new()
|
||||||
|
.multi_line(true)
|
||||||
|
.line_number(true)
|
||||||
|
.build()
|
||||||
|
.search_reader(
|
||||||
|
&matcher,
|
||||||
|
SHERLOCK.as_bytes(),
|
||||||
|
printer.sink(&matcher),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let got = printer_contents(&mut printer);
|
||||||
|
let expected = "\
|
||||||
|
1:16:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||||
|
2:58:Holmeses, success in the province of detective work must always
|
||||||
";
|
";
|
||||||
assert_eq_printed!(expected, got);
|
assert_eq_printed!(expected, got);
|
||||||
}
|
}
|
||||||
@@ -3081,6 +3242,80 @@ Holmeses, success in the province of detective work must always
|
|||||||
assert_eq_printed!(expected, got);
|
assert_eq_printed!(expected, got);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a somewhat weird test that checks the behavior of attempting
|
||||||
|
// to replace a line terminator with something else.
|
||||||
|
//
|
||||||
|
// See: https://github.com/BurntSushi/ripgrep/issues/1311
|
||||||
|
#[test]
|
||||||
|
fn replacement_multi_line() {
|
||||||
|
let matcher = RegexMatcher::new(r"\n").unwrap();
|
||||||
|
let mut printer = StandardBuilder::new()
|
||||||
|
.replacement(Some(b"?".to_vec()))
|
||||||
|
.build(NoColor::new(vec![]));
|
||||||
|
SearcherBuilder::new()
|
||||||
|
.line_number(true)
|
||||||
|
.multi_line(true)
|
||||||
|
.build()
|
||||||
|
.search_reader(
|
||||||
|
&matcher,
|
||||||
|
"hello\nworld\n".as_bytes(),
|
||||||
|
printer.sink(&matcher),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let got = printer_contents(&mut printer);
|
||||||
|
let expected = "1:hello?world?\n";
|
||||||
|
assert_eq_printed!(expected, got);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn replacement_multi_line_diff_line_term() {
|
||||||
|
let matcher = RegexMatcherBuilder::new()
|
||||||
|
.line_terminator(Some(b'\x00'))
|
||||||
|
.build(r"\n")
|
||||||
|
.unwrap();
|
||||||
|
let mut printer = StandardBuilder::new()
|
||||||
|
.replacement(Some(b"?".to_vec()))
|
||||||
|
.build(NoColor::new(vec![]));
|
||||||
|
SearcherBuilder::new()
|
||||||
|
.line_terminator(LineTerminator::byte(b'\x00'))
|
||||||
|
.line_number(true)
|
||||||
|
.multi_line(true)
|
||||||
|
.build()
|
||||||
|
.search_reader(
|
||||||
|
&matcher,
|
||||||
|
"hello\nworld\n".as_bytes(),
|
||||||
|
printer.sink(&matcher),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let got = printer_contents(&mut printer);
|
||||||
|
let expected = "1:hello?world?\x00";
|
||||||
|
assert_eq_printed!(expected, got);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn replacement_multi_line_combine_lines() {
|
||||||
|
let matcher = RegexMatcher::new(r"\n(.)?").unwrap();
|
||||||
|
let mut printer = StandardBuilder::new()
|
||||||
|
.replacement(Some(b"?$1".to_vec()))
|
||||||
|
.build(NoColor::new(vec![]));
|
||||||
|
SearcherBuilder::new()
|
||||||
|
.line_number(true)
|
||||||
|
.multi_line(true)
|
||||||
|
.build()
|
||||||
|
.search_reader(
|
||||||
|
&matcher,
|
||||||
|
"hello\nworld\n".as_bytes(),
|
||||||
|
printer.sink(&matcher),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let got = printer_contents(&mut printer);
|
||||||
|
let expected = "1:hello?world?\n";
|
||||||
|
assert_eq_printed!(expected, got);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn replacement_max_columns() {
|
fn replacement_max_columns() {
|
||||||
let matcher = RegexMatcher::new(r"Sherlock|Doctor (\w+)").unwrap();
|
let matcher = RegexMatcher::new(r"Sherlock|Doctor (\w+)").unwrap();
|
||||||
@@ -3387,4 +3622,57 @@ and xxx clearly, with a label attached.
|
|||||||
";
|
";
|
||||||
assert_eq_printed!(expected, got);
|
assert_eq_printed!(expected, got);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn regression_search_empty_with_crlf() {
|
||||||
|
let matcher =
|
||||||
|
RegexMatcherBuilder::new().crlf(true).build(r"x?").unwrap();
|
||||||
|
let mut printer = StandardBuilder::new()
|
||||||
|
.color_specs(ColorSpecs::default_with_color())
|
||||||
|
.build(Ansi::new(vec![]));
|
||||||
|
SearcherBuilder::new()
|
||||||
|
.line_terminator(LineTerminator::crlf())
|
||||||
|
.build()
|
||||||
|
.search_reader(&matcher, &b"\n"[..], printer.sink(&matcher))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let got = printer_contents_ansi(&mut printer);
|
||||||
|
assert!(!got.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn regression_after_context_with_match() {
|
||||||
|
let haystack = "\
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
e
|
||||||
|
d
|
||||||
|
e
|
||||||
|
d
|
||||||
|
e
|
||||||
|
d
|
||||||
|
e
|
||||||
|
";
|
||||||
|
|
||||||
|
let matcher = RegexMatcherBuilder::new().build(r"d").unwrap();
|
||||||
|
let mut printer = StandardBuilder::new()
|
||||||
|
.max_matches(Some(1))
|
||||||
|
.build(NoColor::new(vec![]));
|
||||||
|
SearcherBuilder::new()
|
||||||
|
.line_number(true)
|
||||||
|
.after_context(2)
|
||||||
|
.build()
|
||||||
|
.search_reader(
|
||||||
|
&matcher,
|
||||||
|
haystack.as_bytes(),
|
||||||
|
printer.sink(&matcher),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let got = printer_contents(&mut printer);
|
||||||
|
let expected = "4:d\n5-e\n6:d\n";
|
||||||
|
assert_eq_printed!(expected, got);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use util::NiceDuration;
|
use crate::util::NiceDuration;
|
||||||
|
|
||||||
/// Summary statistics produced at the end of a search.
|
/// Summary statistics produced at the end of a search.
|
||||||
///
|
///
|
||||||
/// When statistics are reported by a printer, they correspond to all searches
|
/// When statistics are reported by a printer, they correspond to all searches
|
||||||
/// executed with that printer.
|
/// executed with that printer.
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde1", derive(Serialize))]
|
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
|
||||||
pub struct Stats {
|
pub struct Stats {
|
||||||
elapsed: NiceDuration,
|
elapsed: NiceDuration,
|
||||||
searches: u64,
|
searches: u64,
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ use grep_matcher::Matcher;
|
|||||||
use grep_searcher::{Searcher, Sink, SinkError, SinkFinish, SinkMatch};
|
use grep_searcher::{Searcher, Sink, SinkError, SinkFinish, SinkMatch};
|
||||||
use termcolor::{ColorSpec, NoColor, WriteColor};
|
use termcolor::{ColorSpec, NoColor, WriteColor};
|
||||||
|
|
||||||
use color::ColorSpecs;
|
use crate::color::ColorSpecs;
|
||||||
use counter::CounterWriter;
|
use crate::counter::CounterWriter;
|
||||||
use stats::Stats;
|
use crate::stats::Stats;
|
||||||
use util::PrinterPath;
|
use crate::util::{find_iter_at_in_context, PrinterPath};
|
||||||
|
|
||||||
/// The configuration for the summary printer.
|
/// The configuration for the summary printer.
|
||||||
///
|
///
|
||||||
@@ -457,7 +457,7 @@ impl<W> Summary<W> {
|
|||||||
/// * `W` refers to the underlying writer that this printer is writing its
|
/// * `W` refers to the underlying writer that this printer is writing its
|
||||||
/// output to.
|
/// output to.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SummarySink<'p, 's, M: Matcher, W: 's> {
|
pub struct SummarySink<'p, 's, M: Matcher, W> {
|
||||||
matcher: M,
|
matcher: M,
|
||||||
summary: &'s mut Summary<W>,
|
summary: &'s mut Summary<W>,
|
||||||
path: Option<PrinterPath<'p>>,
|
path: Option<PrinterPath<'p>>,
|
||||||
@@ -504,6 +504,17 @@ impl<'p, 's, M: Matcher, W: WriteColor> SummarySink<'p, 's, M, W> {
|
|||||||
self.stats.as_ref()
|
self.stats.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if and only if the searcher may report matches over
|
||||||
|
/// multiple lines.
|
||||||
|
///
|
||||||
|
/// Note that this doesn't just return whether the searcher is in multi
|
||||||
|
/// line mode, but also checks if the matter can match over multiple lines.
|
||||||
|
/// If it can't, then we don't need multi line handling, even if the
|
||||||
|
/// searcher has multi line mode enabled.
|
||||||
|
fn multi_line(&self, searcher: &Searcher) -> bool {
|
||||||
|
searcher.multi_line_with_matcher(&self.matcher)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if this printer should quit.
|
/// Returns true if this printer should quit.
|
||||||
///
|
///
|
||||||
/// This implements the logic for handling quitting after seeing a certain
|
/// This implements the logic for handling quitting after seeing a certain
|
||||||
@@ -579,19 +590,39 @@ impl<'p, 's, M: Matcher, W: WriteColor> Sink for SummarySink<'p, 's, M, W> {
|
|||||||
|
|
||||||
fn matched(
|
fn matched(
|
||||||
&mut self,
|
&mut self,
|
||||||
_searcher: &Searcher,
|
searcher: &Searcher,
|
||||||
mat: &SinkMatch,
|
mat: &SinkMatch<'_>,
|
||||||
) -> Result<bool, io::Error> {
|
) -> Result<bool, io::Error> {
|
||||||
self.match_count += 1;
|
let is_multi_line = self.multi_line(searcher);
|
||||||
if let Some(ref mut stats) = self.stats {
|
let sink_match_count = if self.stats.is_none() && !is_multi_line {
|
||||||
let mut match_count = 0;
|
1
|
||||||
self.matcher
|
} else {
|
||||||
.find_iter(mat.bytes(), |_| {
|
// This gives us as many bytes as the searcher can offer. This
|
||||||
match_count += 1;
|
// isn't guaranteed to hold the necessary context to get match
|
||||||
|
// detection correct (because of look-around), but it does in
|
||||||
|
// practice.
|
||||||
|
let buf = mat.buffer();
|
||||||
|
let range = mat.bytes_range_in_buffer();
|
||||||
|
let mut count = 0;
|
||||||
|
find_iter_at_in_context(
|
||||||
|
searcher,
|
||||||
|
&self.matcher,
|
||||||
|
buf,
|
||||||
|
range,
|
||||||
|
|_| {
|
||||||
|
count += 1;
|
||||||
true
|
true
|
||||||
})
|
},
|
||||||
.map_err(io::Error::error_message)?;
|
)?;
|
||||||
stats.add_matches(match_count);
|
count
|
||||||
|
};
|
||||||
|
if is_multi_line {
|
||||||
|
self.match_count += sink_match_count;
|
||||||
|
} else {
|
||||||
|
self.match_count += 1;
|
||||||
|
}
|
||||||
|
if let Some(ref mut stats) = self.stats {
|
||||||
|
stats.add_matches(sink_match_count);
|
||||||
stats.add_matched_lines(mat.lines().count() as u64);
|
stats.add_matched_lines(mat.lines().count() as u64);
|
||||||
} else if self.summary.config.kind.quit_early() {
|
} else if self.summary.config.kind.quit_early() {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ use std::time;
|
|||||||
use bstr::{ByteSlice, ByteVec};
|
use bstr::{ByteSlice, ByteVec};
|
||||||
use grep_matcher::{Captures, LineTerminator, Match, Matcher};
|
use grep_matcher::{Captures, LineTerminator, Match, Matcher};
|
||||||
use grep_searcher::{
|
use grep_searcher::{
|
||||||
LineIter, SinkContext, SinkContextKind, SinkError, SinkMatch,
|
LineIter, Searcher, SinkContext, SinkContextKind, SinkError, SinkMatch,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "serde1")]
|
#[cfg(feature = "serde1")]
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Serialize, Serializer};
|
||||||
|
|
||||||
|
use crate::MAX_LOOK_AHEAD;
|
||||||
|
|
||||||
/// A type for handling replacements while amortizing allocation.
|
/// A type for handling replacements while amortizing allocation.
|
||||||
pub struct Replacer<M: Matcher> {
|
pub struct Replacer<M: Matcher> {
|
||||||
space: Option<Space<M>>,
|
space: Option<Space<M>>,
|
||||||
@@ -27,7 +29,7 @@ struct Space<M: Matcher> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<M: Matcher> fmt::Debug for Replacer<M> {
|
impl<M: Matcher> fmt::Debug for Replacer<M> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let (dst, matches) = self.replacement().unwrap_or((&[], &[]));
|
let (dst, matches) = self.replacement().unwrap_or((&[], &[]));
|
||||||
f.debug_struct("Replacer")
|
f.debug_struct("Replacer")
|
||||||
.field("dst", &dst)
|
.field("dst", &dst)
|
||||||
@@ -52,18 +54,41 @@ impl<M: Matcher> Replacer<M> {
|
|||||||
/// This can fail if the underlying matcher reports an error.
|
/// This can fail if the underlying matcher reports an error.
|
||||||
pub fn replace_all<'a>(
|
pub fn replace_all<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
|
searcher: &Searcher,
|
||||||
matcher: &M,
|
matcher: &M,
|
||||||
subject: &[u8],
|
mut subject: &[u8],
|
||||||
|
range: std::ops::Range<usize>,
|
||||||
replacement: &[u8],
|
replacement: &[u8],
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
|
// See the giant comment in 'find_iter_at_in_context' below for why we
|
||||||
|
// do this dance.
|
||||||
|
let is_multi_line = searcher.multi_line_with_matcher(&matcher);
|
||||||
|
if is_multi_line {
|
||||||
|
if subject[range.end..].len() >= MAX_LOOK_AHEAD {
|
||||||
|
subject = &subject[..range.end + MAX_LOOK_AHEAD];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// When searching a single line, we should remove the line
|
||||||
|
// terminator. Otherwise, it's possible for the regex (via
|
||||||
|
// look-around) to observe the line terminator and not match
|
||||||
|
// because of it.
|
||||||
|
let mut m = Match::new(0, range.end);
|
||||||
|
trim_line_terminator(searcher, subject, &mut m);
|
||||||
|
subject = &subject[..m.end()];
|
||||||
|
}
|
||||||
{
|
{
|
||||||
let &mut Space { ref mut dst, ref mut caps, ref mut matches } =
|
let &mut Space { ref mut dst, ref mut caps, ref mut matches } =
|
||||||
self.allocate(matcher)?;
|
self.allocate(matcher)?;
|
||||||
dst.clear();
|
dst.clear();
|
||||||
matches.clear();
|
matches.clear();
|
||||||
|
|
||||||
matcher
|
replace_with_captures_in_context(
|
||||||
.replace_with_captures(subject, caps, dst, |caps, dst| {
|
matcher,
|
||||||
|
subject,
|
||||||
|
range.clone(),
|
||||||
|
caps,
|
||||||
|
dst,
|
||||||
|
|caps, dst| {
|
||||||
let start = dst.len();
|
let start = dst.len();
|
||||||
caps.interpolate(
|
caps.interpolate(
|
||||||
|name| matcher.capture_index(name),
|
|name| matcher.capture_index(name),
|
||||||
@@ -74,7 +99,8 @@ impl<M: Matcher> Replacer<M> {
|
|||||||
let end = dst.len();
|
let end = dst.len();
|
||||||
matches.push(Match::new(start, end));
|
matches.push(Match::new(start, end));
|
||||||
true
|
true
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.map_err(io::Error::error_message)?;
|
.map_err(io::Error::error_message)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -304,7 +330,7 @@ impl<'a> PrinterPath<'a> {
|
|||||||
pub struct NiceDuration(pub time::Duration);
|
pub struct NiceDuration(pub time::Duration);
|
||||||
|
|
||||||
impl fmt::Display for NiceDuration {
|
impl fmt::Display for NiceDuration {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{:0.6}s", self.fractional_seconds())
|
write!(f, "{:0.6}s", self.fractional_seconds())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,3 +383,108 @@ pub fn trim_ascii_prefix(
|
|||||||
.count();
|
.count();
|
||||||
range.with_start(range.start() + count)
|
range.with_start(range.start() + count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_iter_at_in_context<M, F>(
|
||||||
|
searcher: &Searcher,
|
||||||
|
matcher: M,
|
||||||
|
mut bytes: &[u8],
|
||||||
|
range: std::ops::Range<usize>,
|
||||||
|
mut matched: F,
|
||||||
|
) -> io::Result<()>
|
||||||
|
where
|
||||||
|
M: Matcher,
|
||||||
|
F: FnMut(Match) -> bool,
|
||||||
|
{
|
||||||
|
// This strange dance is to account for the possibility of look-ahead in
|
||||||
|
// the regex. The problem here is that mat.bytes() doesn't include the
|
||||||
|
// lines beyond the match boundaries in mulit-line mode, which means that
|
||||||
|
// when we try to rediscover the full set of matches here, the regex may no
|
||||||
|
// longer match if it required some look-ahead beyond the matching lines.
|
||||||
|
//
|
||||||
|
// PCRE2 (and the grep-matcher interfaces) has no way of specifying an end
|
||||||
|
// bound of the search. So we kludge it and let the regex engine search the
|
||||||
|
// rest of the buffer... But to avoid things getting too crazy, we cap the
|
||||||
|
// buffer.
|
||||||
|
//
|
||||||
|
// If it weren't for multi-line mode, then none of this would be needed.
|
||||||
|
// Alternatively, if we refactored the grep interfaces to pass along the
|
||||||
|
// full set of matches (if available) from the searcher, then that might
|
||||||
|
// also help here. But that winds up paying an upfront unavoidable cost for
|
||||||
|
// the case where matches don't need to be counted. So then you'd have to
|
||||||
|
// introduce a way to pass along matches conditionally, only when needed.
|
||||||
|
// Yikes.
|
||||||
|
//
|
||||||
|
// Maybe the bigger picture thing here is that the searcher should be
|
||||||
|
// responsible for finding matches when necessary, and the printer
|
||||||
|
// shouldn't be involved in this business in the first place. Sigh. Live
|
||||||
|
// and learn. Abstraction boundaries are hard.
|
||||||
|
let is_multi_line = searcher.multi_line_with_matcher(&matcher);
|
||||||
|
if is_multi_line {
|
||||||
|
if bytes[range.end..].len() >= MAX_LOOK_AHEAD {
|
||||||
|
bytes = &bytes[..range.end + MAX_LOOK_AHEAD];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// When searching a single line, we should remove the line terminator.
|
||||||
|
// Otherwise, it's possible for the regex (via look-around) to observe
|
||||||
|
// the line terminator and not match because of it.
|
||||||
|
let mut m = Match::new(0, range.end);
|
||||||
|
trim_line_terminator(searcher, bytes, &mut m);
|
||||||
|
bytes = &bytes[..m.end()];
|
||||||
|
}
|
||||||
|
matcher
|
||||||
|
.find_iter_at(bytes, range.start, |m| {
|
||||||
|
if m.start() >= range.end {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
matched(m)
|
||||||
|
})
|
||||||
|
.map_err(io::Error::error_message)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given a buf and some bounds, if there is a line terminator at the end of
|
||||||
|
/// the given bounds in buf, then the bounds are trimmed to remove the line
|
||||||
|
/// terminator.
|
||||||
|
pub fn trim_line_terminator(
|
||||||
|
searcher: &Searcher,
|
||||||
|
buf: &[u8],
|
||||||
|
line: &mut Match,
|
||||||
|
) {
|
||||||
|
let lineterm = searcher.line_terminator();
|
||||||
|
if lineterm.is_suffix(&buf[*line]) {
|
||||||
|
let mut end = line.end() - 1;
|
||||||
|
if lineterm.is_crlf() && end > 0 && buf.get(end - 1) == Some(&b'\r') {
|
||||||
|
end -= 1;
|
||||||
|
}
|
||||||
|
*line = line.with_end(end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Like `Matcher::replace_with_captures_at`, but accepts an end bound.
|
||||||
|
///
|
||||||
|
/// See also: `find_iter_at_in_context` for why we need this.
|
||||||
|
fn replace_with_captures_in_context<M, F>(
|
||||||
|
matcher: M,
|
||||||
|
bytes: &[u8],
|
||||||
|
range: std::ops::Range<usize>,
|
||||||
|
caps: &mut M::Captures,
|
||||||
|
dst: &mut Vec<u8>,
|
||||||
|
mut append: F,
|
||||||
|
) -> Result<(), M::Error>
|
||||||
|
where
|
||||||
|
M: Matcher,
|
||||||
|
F: FnMut(&M::Captures, &mut Vec<u8>) -> bool,
|
||||||
|
{
|
||||||
|
let mut last_match = range.start;
|
||||||
|
matcher.captures_iter_at(bytes, range.start, caps, |caps| {
|
||||||
|
let m = caps.get(0).unwrap();
|
||||||
|
if m.start() >= range.end {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dst.extend(&bytes[last_match..m.start()]);
|
||||||
|
last_match = m.end();
|
||||||
|
append(caps, dst)
|
||||||
|
})?;
|
||||||
|
let end = std::cmp::min(bytes.len(), range.end);
|
||||||
|
dst.extend(&bytes[last_match..end]);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-regex"
|
name = "grep-regex"
|
||||||
version = "0.1.6" #:version
|
version = "0.1.10" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Use Rust's regex library with the 'grep' crate.
|
Use Rust's regex library with the 'grep' crate.
|
||||||
@@ -10,13 +10,14 @@ homepage = "https://github.com/BurntSushi/ripgrep/tree/master/crates/regex"
|
|||||||
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/regex"
|
repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/regex"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["regex", "grep", "search", "pattern", "line"]
|
keywords = ["regex", "grep", "search", "pattern", "line"]
|
||||||
license = "Unlicense/MIT"
|
license = "Unlicense OR MIT"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aho-corasick = "0.7.3"
|
aho-corasick = "0.7.3"
|
||||||
bstr = "0.2.10"
|
bstr = "1.1.0"
|
||||||
grep-matcher = { version = "0.1.2", path = "../matcher" }
|
grep-matcher = { version = "0.1.5", path = "../matcher" }
|
||||||
log = "0.4.5"
|
log = "0.4.5"
|
||||||
regex = "1.1"
|
regex = "1.1"
|
||||||
regex-syntax = "0.6.5"
|
regex-syntax = "0.6.5"
|
||||||
thread_local = "1"
|
thread_local = "1.1.2"
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ The `grep-regex` crate provides an implementation of the `Matcher` trait from
|
|||||||
the `grep-matcher` crate. This implementation permits Rust's regex engine to
|
the `grep-matcher` crate. This implementation permits Rust's regex engine to
|
||||||
be used in the `grep` crate for fast line oriented searching.
|
be used in the `grep` crate for fast line oriented searching.
|
||||||
|
|
||||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
[](https://github.com/BurntSushi/ripgrep/actions)
|
||||||
[](https://ci.appveyor.com/project/BurntSushi/ripgrep)
|
|
||||||
[](https://crates.io/crates/grep-regex)
|
[](https://crates.io/crates/grep-regex)
|
||||||
|
|
||||||
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
@@ -27,9 +26,3 @@ Add this to your `Cargo.toml`:
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
grep-regex = "0.1"
|
grep-regex = "0.1"
|
||||||
```
|
```
|
||||||
|
|
||||||
and this to your crate root:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
extern crate grep_regex;
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ use regex::bytes::{Regex, RegexBuilder};
|
|||||||
use regex_syntax::ast::{self, Ast};
|
use regex_syntax::ast::{self, Ast};
|
||||||
use regex_syntax::hir::{self, Hir};
|
use regex_syntax::hir::{self, Hir};
|
||||||
|
|
||||||
use ast::AstAnalysis;
|
use crate::ast::AstAnalysis;
|
||||||
use crlf::crlfify;
|
use crate::crlf::crlfify;
|
||||||
use error::Error;
|
use crate::error::Error;
|
||||||
use literal::LiteralSets;
|
use crate::literal::LiteralSets;
|
||||||
use multi::alternation_literals;
|
use crate::multi::alternation_literals;
|
||||||
use non_matching::non_matching_bytes;
|
use crate::non_matching::non_matching_bytes;
|
||||||
use strip::strip_from_match;
|
use crate::strip::strip_from_match;
|
||||||
|
|
||||||
/// Config represents the configuration of a regex matcher in this crate.
|
/// Config represents the configuration of a regex matcher in this crate.
|
||||||
/// The configuration is itself a rough combination of the knobs found in
|
/// The configuration is itself a rough combination of the knobs found in
|
||||||
@@ -175,6 +175,36 @@ impl ConfiguredHIR {
|
|||||||
self.config.crlf && self.expr.is_line_anchored_end()
|
self.config.crlf && self.expr.is_line_anchored_end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the line terminator configured on this expression.
|
||||||
|
///
|
||||||
|
/// When we have beginning/end anchors (NOT line anchors), the fast line
|
||||||
|
/// searching path isn't quite correct. Or at least, doesn't match the
|
||||||
|
/// slow path. Namely, the slow path strips line terminators while the
|
||||||
|
/// fast path does not. Since '$' (when multi-line mode is disabled)
|
||||||
|
/// doesn't match at line boundaries, the existence of a line terminator
|
||||||
|
/// might cause it to not match when it otherwise would with the line
|
||||||
|
/// terminator stripped.
|
||||||
|
///
|
||||||
|
/// Since searching with text anchors is exceptionally rare in the
|
||||||
|
/// context of line oriented searching (multi-line mode is basically
|
||||||
|
/// always enabled), we just disable this optimization when there are
|
||||||
|
/// text anchors. We disable it by not returning a line terminator, since
|
||||||
|
/// without a line terminator, the fast search path can't be executed.
|
||||||
|
///
|
||||||
|
/// See: <https://github.com/BurntSushi/ripgrep/issues/2260>
|
||||||
|
pub fn line_terminator(&self) -> Option<LineTerminator> {
|
||||||
|
if self.is_any_anchored() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.config.line_terminator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if and only if the underlying HIR has any text anchors.
|
||||||
|
fn is_any_anchored(&self) -> bool {
|
||||||
|
self.expr.is_any_anchored_start() || self.expr.is_any_anchored_end()
|
||||||
|
}
|
||||||
|
|
||||||
/// Builds a regular expression from this HIR expression.
|
/// Builds a regular expression from this HIR expression.
|
||||||
pub fn regex(&self) -> Result<Regex, Error> {
|
pub fn regex(&self) -> Result<Regex, Error> {
|
||||||
self.pattern_to_regex(&self.expr.to_string())
|
self.pattern_to_regex(&self.expr.to_string())
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ use grep_matcher::{Match, Matcher, NoError};
|
|||||||
use regex::bytes::Regex;
|
use regex::bytes::Regex;
|
||||||
use regex_syntax::hir::{self, Hir, HirKind};
|
use regex_syntax::hir::{self, Hir, HirKind};
|
||||||
|
|
||||||
use config::ConfiguredHIR;
|
use crate::config::ConfiguredHIR;
|
||||||
use error::Error;
|
use crate::error::Error;
|
||||||
use matcher::RegexCaptures;
|
use crate::matcher::RegexCaptures;
|
||||||
|
|
||||||
/// A matcher for implementing "word match" semantics.
|
/// A matcher for implementing "word match" semantics.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use util;
|
use crate::util;
|
||||||
|
|
||||||
/// An error that can occur in this crate.
|
/// An error that can occur in this crate.
|
||||||
///
|
///
|
||||||
@@ -72,7 +72,7 @@ impl error::Error for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ErrorKind::Regex(ref s) => write!(f, "{}", s),
|
ErrorKind::Regex(ref s) => write!(f, "{}", s),
|
||||||
ErrorKind::NotAllowed(ref lit) => {
|
ErrorKind::NotAllowed(ref lit) => {
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
/*!
|
/*!
|
||||||
An implementation of `grep-matcher`'s `Matcher` trait for Rust's regex engine.
|
An implementation of `grep-matcher`'s `Matcher` trait for Rust's regex engine.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
extern crate aho_corasick;
|
pub use crate::error::{Error, ErrorKind};
|
||||||
extern crate bstr;
|
pub use crate::matcher::{RegexCaptures, RegexMatcher, RegexMatcherBuilder};
|
||||||
extern crate grep_matcher;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
|
||||||
extern crate regex;
|
|
||||||
extern crate regex_syntax;
|
|
||||||
extern crate thread_local;
|
|
||||||
|
|
||||||
pub use error::{Error, ErrorKind};
|
|
||||||
pub use matcher::{RegexCaptures, RegexMatcher, RegexMatcherBuilder};
|
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
mod config;
|
mod config;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use bstr::ByteSlice;
|
|||||||
use regex_syntax::hir::literal::{Literal, Literals};
|
use regex_syntax::hir::literal::{Literal, Literals};
|
||||||
use regex_syntax::hir::{self, Hir, HirKind};
|
use regex_syntax::hir::{self, Hir, HirKind};
|
||||||
|
|
||||||
use util;
|
use crate::util;
|
||||||
|
|
||||||
/// Represents prefix, suffix and inner "required" literals for a regular
|
/// Represents prefix, suffix and inner "required" literals for a regular
|
||||||
/// expression.
|
/// expression.
|
||||||
@@ -55,7 +55,7 @@ impl LiteralSets {
|
|||||||
|
|
||||||
if !word {
|
if !word {
|
||||||
if self.prefixes.all_complete() && !self.prefixes.is_empty() {
|
if self.prefixes.all_complete() && !self.prefixes.is_empty() {
|
||||||
debug!("literal prefixes detected: {:?}", self.prefixes);
|
log::debug!("literal prefixes detected: {:?}", self.prefixes);
|
||||||
// When this is true, the regex engine will do a literal scan,
|
// When this is true, the regex engine will do a literal scan,
|
||||||
// so we don't need to return anything. But we only do this
|
// so we don't need to return anything. But we only do this
|
||||||
// if we aren't doing a word regex, since a word regex adds
|
// if we aren't doing a word regex, since a word regex adds
|
||||||
@@ -106,7 +106,7 @@ impl LiteralSets {
|
|||||||
&& !any_empty
|
&& !any_empty
|
||||||
&& !any_white
|
&& !any_white
|
||||||
{
|
{
|
||||||
debug!("required literals found: {:?}", req_lits);
|
log::debug!("required literals found: {:?}", req_lits);
|
||||||
let alts: Vec<String> = req_lits
|
let alts: Vec<String> = req_lits
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| util::bytes_to_regex(x))
|
.map(|x| util::bytes_to_regex(x))
|
||||||
@@ -116,7 +116,7 @@ impl LiteralSets {
|
|||||||
} else if lit.is_empty() {
|
} else if lit.is_empty() {
|
||||||
// If we're here, then we have no LCP. No LCS. And no detected
|
// If we're here, then we have no LCP. No LCS. And no detected
|
||||||
// inner required literals. In theory this shouldn't happen, but
|
// inner required literals. In theory this shouldn't happen, but
|
||||||
// the inner literal detector isn't as nice as we hope and doens't
|
// the inner literal detector isn't as nice as we hope and doesn't
|
||||||
// actually support returning a set of alternating required
|
// actually support returning a set of alternating required
|
||||||
// literals. (Instead, it only returns a set where EVERY literal
|
// literals. (Instead, it only returns a set where EVERY literal
|
||||||
// in it is required. It cannot currently express "either P or Q
|
// in it is required. It cannot currently express "either P or Q
|
||||||
@@ -141,32 +141,35 @@ impl LiteralSets {
|
|||||||
// (Not in theory---it could be better. But the current
|
// (Not in theory---it could be better. But the current
|
||||||
// implementation isn't good enough.) ... So we make up for it
|
// implementation isn't good enough.) ... So we make up for it
|
||||||
// here.
|
// here.
|
||||||
|
if !word {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let p_min_len = self.prefixes.min_len();
|
let p_min_len = self.prefixes.min_len();
|
||||||
let s_min_len = self.suffixes.min_len();
|
let s_min_len = self.suffixes.min_len();
|
||||||
let lits = match (p_min_len, s_min_len) {
|
let lits = match (p_min_len, s_min_len) {
|
||||||
(None, None) => return None,
|
(None, None) => return None,
|
||||||
(Some(_), None) => {
|
(Some(_), None) => {
|
||||||
debug!("prefix literals found");
|
log::debug!("prefix literals found");
|
||||||
self.prefixes.literals()
|
self.prefixes.literals()
|
||||||
}
|
}
|
||||||
(None, Some(_)) => {
|
(None, Some(_)) => {
|
||||||
debug!("suffix literals found");
|
log::debug!("suffix literals found");
|
||||||
self.suffixes.literals()
|
self.suffixes.literals()
|
||||||
}
|
}
|
||||||
(Some(p), Some(s)) => {
|
(Some(p), Some(s)) => {
|
||||||
if p >= s {
|
if p >= s {
|
||||||
debug!("prefix literals found");
|
log::debug!("prefix literals found");
|
||||||
self.prefixes.literals()
|
self.prefixes.literals()
|
||||||
} else {
|
} else {
|
||||||
debug!("suffix literals found");
|
log::debug!("suffix literals found");
|
||||||
self.suffixes.literals()
|
self.suffixes.literals()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("prefix/suffix literals found: {:?}", lits);
|
log::debug!("prefix/suffix literals found: {:?}", lits);
|
||||||
if has_only_whitespace(lits) {
|
if has_only_whitespace(lits) {
|
||||||
debug!("dropping literals because one was whitespace");
|
log::debug!("dropping literals because one was whitespace");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let alts: Vec<String> =
|
let alts: Vec<String> =
|
||||||
@@ -174,9 +177,9 @@ impl LiteralSets {
|
|||||||
// We're matching raw bytes, so disable Unicode mode.
|
// We're matching raw bytes, so disable Unicode mode.
|
||||||
Some(format!("(?-u:{})", alts.join("|")))
|
Some(format!("(?-u:{})", alts.join("|")))
|
||||||
} else {
|
} else {
|
||||||
debug!("required literal found: {:?}", util::show_bytes(lit));
|
log::debug!("required literal found: {:?}", util::show_bytes(lit));
|
||||||
if lit.chars().all(|c| c.is_whitespace()) {
|
if lit.chars().all(|c| c.is_whitespace()) {
|
||||||
debug!("dropping literal because one was whitespace");
|
log::debug!("dropping literal because one was whitespace");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(format!("(?-u:{})", util::bytes_to_regex(&lit)))
|
Some(format!("(?-u:{})", util::bytes_to_regex(&lit)))
|
||||||
@@ -323,12 +326,12 @@ fn is_simple(expr: &Hir) -> bool {
|
|||||||
HirKind::Empty
|
HirKind::Empty
|
||||||
| HirKind::Literal(_)
|
| HirKind::Literal(_)
|
||||||
| HirKind::Class(_)
|
| HirKind::Class(_)
|
||||||
| HirKind::Repetition(_)
|
|
||||||
| HirKind::Concat(_)
|
| HirKind::Concat(_)
|
||||||
| HirKind::Alternation(_) => true,
|
| HirKind::Alternation(_) => true,
|
||||||
HirKind::Anchor(_) | HirKind::WordBoundary(_) | HirKind::Group(_) => {
|
HirKind::Anchor(_)
|
||||||
false
|
| HirKind::WordBoundary(_)
|
||||||
}
|
| HirKind::Group(_)
|
||||||
|
| HirKind::Repetition(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,8 +412,17 @@ mod tests {
|
|||||||
// https://github.com/BurntSushi/ripgrep/issues/1319
|
// https://github.com/BurntSushi/ripgrep/issues/1319
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
one_regex(r"TTGAGTCCAGGAG[ATCG]{2}C"),
|
one_regex(r"TTGAGTCCAGGAG[ATCG]{2}C"),
|
||||||
pat("TTGAGTCCAGGAGA|TTGAGTCCAGGAGC|\
|
pat("TTGAGTCCAGGAG"),
|
||||||
TTGAGTCCAGGAGG|TTGAGTCCAGGAGT")
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn regression_1537() {
|
||||||
|
// Regression from:
|
||||||
|
// https://github.com/BurntSushi/ripgrep/issues/1537
|
||||||
|
assert_eq!(one_regex(r";(.*,)"), pat(";"));
|
||||||
|
assert_eq!(one_regex(r";((.*,))"), pat(";"));
|
||||||
|
assert_eq!(one_regex(r";(.*,)+"), pat(";"),);
|
||||||
|
assert_eq!(one_regex(r";(.*,){1}"), pat(";"),);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ use grep_matcher::{
|
|||||||
};
|
};
|
||||||
use regex::bytes::{CaptureLocations, Regex};
|
use regex::bytes::{CaptureLocations, Regex};
|
||||||
|
|
||||||
use config::{Config, ConfiguredHIR};
|
use crate::config::{Config, ConfiguredHIR};
|
||||||
use crlf::CRLFMatcher;
|
use crate::crlf::CRLFMatcher;
|
||||||
use error::Error;
|
use crate::error::Error;
|
||||||
use multi::MultiLiteralMatcher;
|
use crate::multi::MultiLiteralMatcher;
|
||||||
use word::WordMatcher;
|
use crate::word::WordMatcher;
|
||||||
|
|
||||||
/// A builder for constructing a `Matcher` using regular expressions.
|
/// A builder for constructing a `Matcher` using regular expressions.
|
||||||
///
|
///
|
||||||
@@ -19,7 +19,7 @@ use word::WordMatcher;
|
|||||||
/// types of optimizations.
|
/// types of optimizations.
|
||||||
///
|
///
|
||||||
/// The syntax supported is documented as part of the regex crate:
|
/// The syntax supported is documented as part of the regex crate:
|
||||||
/// https://docs.rs/regex/*/regex/#syntax
|
/// <https://docs.rs/regex/#syntax>.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct RegexMatcherBuilder {
|
pub struct RegexMatcherBuilder {
|
||||||
config: Config,
|
config: Config,
|
||||||
@@ -41,19 +41,23 @@ impl RegexMatcherBuilder {
|
|||||||
/// pattern.
|
/// pattern.
|
||||||
///
|
///
|
||||||
/// The syntax supported is documented as part of the regex crate:
|
/// The syntax supported is documented as part of the regex crate:
|
||||||
/// https://docs.rs/regex/*/regex/#syntax
|
/// <https://docs.rs/regex/#syntax>.
|
||||||
pub fn build(&self, pattern: &str) -> Result<RegexMatcher, Error> {
|
pub fn build(&self, pattern: &str) -> Result<RegexMatcher, Error> {
|
||||||
let chir = self.config.hir(pattern)?;
|
let chir = self.config.hir(pattern)?;
|
||||||
let fast_line_regex = chir.fast_line_regex()?;
|
let fast_line_regex = chir.fast_line_regex()?;
|
||||||
let non_matching_bytes = chir.non_matching_bytes();
|
let non_matching_bytes = chir.non_matching_bytes();
|
||||||
if let Some(ref re) = fast_line_regex {
|
if let Some(ref re) = fast_line_regex {
|
||||||
debug!("extracted fast line regex: {:?}", re);
|
log::debug!("extracted fast line regex: {:?}", re);
|
||||||
}
|
}
|
||||||
|
|
||||||
let matcher = RegexMatcherImpl::new(&chir)?;
|
let matcher = RegexMatcherImpl::new(&chir)?;
|
||||||
trace!("final regex: {:?}", matcher.regex());
|
log::trace!("final regex: {:?}", matcher.regex());
|
||||||
|
let mut config = self.config.clone();
|
||||||
|
// We override the line terminator in case the configured expr doesn't
|
||||||
|
// support it.
|
||||||
|
config.line_terminator = chir.line_terminator();
|
||||||
Ok(RegexMatcher {
|
Ok(RegexMatcher {
|
||||||
config: self.config.clone(),
|
config,
|
||||||
matcher,
|
matcher,
|
||||||
fast_line_regex,
|
fast_line_regex,
|
||||||
non_matching_bytes,
|
non_matching_bytes,
|
||||||
@@ -253,7 +257,7 @@ impl RegexMatcherBuilder {
|
|||||||
/// they should impose a limit on the length, in bytes, of the concrete
|
/// they should impose a limit on the length, in bytes, of the concrete
|
||||||
/// pattern string. In particular, this is viable since this parser
|
/// pattern string. In particular, this is viable since this parser
|
||||||
/// implementation will limit itself to heap space proportional to the
|
/// implementation will limit itself to heap space proportional to the
|
||||||
/// lenth of the pattern string.
|
/// length of the pattern string.
|
||||||
///
|
///
|
||||||
/// Note that a nest limit of `0` will return a nest limit error for most
|
/// Note that a nest limit of `0` will return a nest limit error for most
|
||||||
/// patterns but not all. For example, a nest limit of `0` permits `a` but
|
/// patterns but not all. For example, a nest limit of `0` permits `a` but
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ use aho_corasick::{AhoCorasick, AhoCorasickBuilder, MatchKind};
|
|||||||
use grep_matcher::{Match, Matcher, NoError};
|
use grep_matcher::{Match, Matcher, NoError};
|
||||||
use regex_syntax::hir::Hir;
|
use regex_syntax::hir::Hir;
|
||||||
|
|
||||||
use error::Error;
|
use crate::error::Error;
|
||||||
use matcher::RegexCaptures;
|
use crate::matcher::RegexCaptures;
|
||||||
|
|
||||||
/// A matcher for an alternation of literals.
|
/// A matcher for an alternation of literals.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ pub fn non_matching_bytes(expr: &Hir) -> ByteSet {
|
|||||||
/// the given expression.
|
/// the given expression.
|
||||||
fn remove_matching_bytes(expr: &Hir, set: &mut ByteSet) {
|
fn remove_matching_bytes(expr: &Hir, set: &mut ByteSet) {
|
||||||
match *expr.kind() {
|
match *expr.kind() {
|
||||||
HirKind::Empty | HirKind::Anchor(_) | HirKind::WordBoundary(_) => {}
|
HirKind::Empty | HirKind::WordBoundary(_) => {}
|
||||||
|
HirKind::Anchor(_) => {
|
||||||
|
set.remove(b'\n');
|
||||||
|
}
|
||||||
HirKind::Literal(hir::Literal::Unicode(c)) => {
|
HirKind::Literal(hir::Literal::Unicode(c)) => {
|
||||||
for &b in c.encode_utf8(&mut [0; 4]).as_bytes() {
|
for &b in c.encode_utf8(&mut [0; 4]).as_bytes() {
|
||||||
set.remove(b);
|
set.remove(b);
|
||||||
@@ -125,4 +128,12 @@ mod tests {
|
|||||||
assert_eq!(sparse(&extract(r"\xFF")), sparse_except(&[0xC3, 0xBF]));
|
assert_eq!(sparse(&extract(r"\xFF")), sparse_except(&[0xC3, 0xBF]));
|
||||||
assert_eq!(sparse(&extract(r"(?-u)\xFF")), sparse_except(&[0xFF]));
|
assert_eq!(sparse(&extract(r"(?-u)\xFF")), sparse_except(&[0xFF]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn anchor() {
|
||||||
|
assert_eq!(sparse(&extract(r"^")), sparse_except(&[b'\n']));
|
||||||
|
assert_eq!(sparse(&extract(r"$")), sparse_except(&[b'\n']));
|
||||||
|
assert_eq!(sparse(&extract(r"\A")), sparse_except(&[b'\n']));
|
||||||
|
assert_eq!(sparse(&extract(r"\z")), sparse_except(&[b'\n']));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use grep_matcher::LineTerminator;
|
use grep_matcher::LineTerminator;
|
||||||
use regex_syntax::hir::{self, Hir, HirKind};
|
use regex_syntax::hir::{self, Hir, HirKind};
|
||||||
|
|
||||||
use error::{Error, ErrorKind};
|
use crate::error::{Error, ErrorKind};
|
||||||
|
|
||||||
/// Return an HIR that is guaranteed to never match the given line terminator,
|
/// Return an HIR that is guaranteed to never match the given line terminator,
|
||||||
/// if possible.
|
/// if possible.
|
||||||
@@ -106,7 +106,7 @@ mod tests {
|
|||||||
use regex_syntax::Parser;
|
use regex_syntax::Parser;
|
||||||
|
|
||||||
use super::{strip_from_match, LineTerminator};
|
use super::{strip_from_match, LineTerminator};
|
||||||
use error::Error;
|
use crate::error::Error;
|
||||||
|
|
||||||
fn roundtrip(pattern: &str, byte: u8) -> String {
|
fn roundtrip(pattern: &str, byte: u8) -> String {
|
||||||
roundtrip_line_term(pattern, LineTerminator::byte(byte)).unwrap()
|
roundtrip_line_term(pattern, LineTerminator::byte(byte)).unwrap()
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user