mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-05-19 09:40:22 -07:00
Compare commits
68 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6dfaec03e8 | ||
|
5fbc4fee64 | ||
|
004370bd16 | ||
|
de4baa1002 | ||
|
163ac157d3 | ||
|
e2362d4d51 | ||
|
d6b59feff8 | ||
|
94305125ef | ||
|
79cbe89deb | ||
|
bf63fe8f25 | ||
|
8bd5950296 | ||
|
6e0539ab91 | ||
|
4649aa9700 | ||
|
c009652e77 | ||
|
b9f7a9ba2b | ||
|
a1960877cf | ||
|
bb0925af91 | ||
|
be117dbafa | ||
|
06dc13ad2d | ||
|
c6c2e69b8f | ||
|
e67c868ddd | ||
|
d33f2e2f70 | ||
|
082edafffa | ||
|
7c8dc332b3 | ||
|
ea961915b5 | ||
|
7943bdfe82 | ||
|
312a7884fc | ||
|
ac02f54c89 | ||
|
24b337b940 | ||
|
a5083f99ce | ||
|
f89cdba5df | ||
|
f7b677d136 | ||
|
3f68a8f3d7 | ||
|
9d738ad0c0 | ||
|
6c5108ed17 | ||
|
e0f1000df6 | ||
|
ea99421ec8 | ||
|
af8c386d5e | ||
|
71d71d2d98 | ||
|
c9ebcbd8ab | ||
|
dec0dc3196 | ||
|
2f0a269f07 | ||
|
0a0893a765 | ||
|
35160a1cdb | ||
|
f1d23c06e3 | ||
|
22b677900f | ||
|
bb6f0f5519 | ||
|
b6ef99ee55 | ||
|
bb8601b2ba | ||
|
02b47b7469 | ||
|
d922b7ac11 | ||
|
2acf25c689 | ||
|
80007698d3 | ||
|
3ad0e83471 | ||
|
eca13f08a2 | ||
|
4f99f82b19 | ||
|
327d74f161 | ||
|
9da0995df4 | ||
|
e9abbc1a02 | ||
|
9bd30e8e48 | ||
|
59212d08d3 | ||
|
6ebebb2aaa | ||
|
e92e2ef813 | ||
|
4a30819302 | ||
|
9b42af96f0 | ||
|
648a65f197 | ||
|
bdf01f46a6 | ||
|
1c775f3a82 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
github: [BurntSushi]
|
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -24,7 +24,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: What version of ripgrep are you using?
|
label: What version of ripgrep are you using?
|
||||||
description: Enter the output of `rg --version`.
|
description: Enter the output of `rg --version`.
|
||||||
placeholder: ex. ripgrep 13.0.0
|
placeholder: ex. ripgrep 0.2.1
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
@ -189,6 +189,21 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: ${{ env.CARGO }} test --bin rg ${{ env.TARGET_FLAGS }} flags::defs::tests::available_shorts -- --nocapture
|
run: ${{ env.CARGO }} test --bin rg ${{ env.TARGET_FLAGS }} flags::defs::tests::available_shorts -- --nocapture
|
||||||
|
|
||||||
|
# Setup and compile on the wasm32-wasip1 target
|
||||||
|
wasm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Install Rust
|
||||||
|
uses: dtolnay/rust-toolchain@master
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
- name: Add wasm32-wasip1 target
|
||||||
|
run: rustup target add wasm32-wasip1
|
||||||
|
- name: Basic build
|
||||||
|
run: cargo build --verbose
|
||||||
|
|
||||||
rustfmt:
|
rustfmt:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
31
CHANGELOG.md
31
CHANGELOG.md
@ -1,5 +1,32 @@
|
|||||||
14.1.0 (TBD)
|
TBD
|
||||||
============
|
===
|
||||||
|
Unreleased changes. Release notes have not yet been written.
|
||||||
|
|
||||||
|
|
||||||
|
14.1.1 (2024-09-08)
|
||||||
|
===================
|
||||||
|
This is a minor release with a bug fix for a matching bug. In particular, a bug
|
||||||
|
was found that could cause ripgrep to ignore lines that should match. That is,
|
||||||
|
false negatives. It is difficult to characterize the specific set of regexes
|
||||||
|
in which this occurs as it requires multiple different optimization strategies
|
||||||
|
to collide and produce an incorrect result. But as one reported example, in
|
||||||
|
ripgrep, the regex `(?i:e.x|ex)` does not match `e-x` when it should. (This
|
||||||
|
bug is a result of an inner literal optimization performed in the `grep-regex`
|
||||||
|
crate and not in the `regex` crate.)
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* [BUG #2884](https://github.com/BurntSushi/ripgrep/issues/2884):
|
||||||
|
Fix bug where ripgrep could miss some matches that it should report.
|
||||||
|
|
||||||
|
Miscellaneous:
|
||||||
|
|
||||||
|
* [MISC #2748](https://github.com/BurntSushi/ripgrep/issues/2748):
|
||||||
|
Remove ripgrep's `simd-accel` feature because it was frequently broken.
|
||||||
|
|
||||||
|
|
||||||
|
14.1.0 (2024-01-06)
|
||||||
|
===================
|
||||||
This is a minor release with a few small new features and bug fixes. This
|
This is a minor release with a few small new features and bug fixes. This
|
||||||
release contains a bug fix for unbounded memory growth while walking a
|
release contains a bug fix for unbounded memory growth while walking a
|
||||||
directory tree. This release also includes improvements to the completions for
|
directory tree. This release also includes improvements to the completions for
|
||||||
|
287
Cargo.lock
generated
287
Cargo.lock
generated
@ -4,30 +4,24 @@ version = 3
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.2"
|
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 = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.79"
|
version = "1.0.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "1.9.0"
|
version = "1.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
|
checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata",
|
"regex-automata",
|
||||||
@ -36,12 +30,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.83"
|
version = "1.1.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
|
"shlex",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -52,53 +47,45 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.10"
|
version = "0.5.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2"
|
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.4"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
|
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
|
||||||
"crossbeam-epoch",
|
"crossbeam-epoch",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-epoch"
|
name = "crossbeam-epoch"
|
||||||
version = "0.9.17"
|
version = "0.9.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d"
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
|
||||||
"cfg-if",
|
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.18"
|
version = "0.8.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c"
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.33"
|
version = "0.8.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
|
checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"packed_simd",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -118,7 +105,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.14"
|
version = "0.4.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"bstr",
|
"bstr",
|
||||||
@ -132,7 +119,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep"
|
name = "grep"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"grep-cli",
|
"grep-cli",
|
||||||
"grep-matcher",
|
"grep-matcher",
|
||||||
@ -146,7 +133,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-cli"
|
name = "grep-cli"
|
||||||
version = "0.1.10"
|
version = "0.1.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"globset",
|
"globset",
|
||||||
@ -166,7 +153,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-pcre2"
|
name = "grep-pcre2"
|
||||||
version = "0.1.7"
|
version = "0.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"grep-matcher",
|
"grep-matcher",
|
||||||
"log",
|
"log",
|
||||||
@ -175,7 +162,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-printer"
|
name = "grep-printer"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"grep-matcher",
|
"grep-matcher",
|
||||||
@ -189,7 +176,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-regex"
|
name = "grep-regex"
|
||||||
version = "0.1.12"
|
version = "0.1.13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"grep-matcher",
|
"grep-matcher",
|
||||||
@ -200,7 +187,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-searcher"
|
name = "grep-searcher"
|
||||||
version = "0.1.13"
|
version = "0.1.14"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
@ -215,7 +202,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.4.22"
|
version = "0.4.23"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
@ -231,9 +218,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.10"
|
version = "1.0.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jemalloc-sys"
|
name = "jemalloc-sys"
|
||||||
@ -257,9 +244,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.27"
|
version = "0.1.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
|
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@ -272,62 +259,36 @@ checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.151"
|
version = "0.2.158"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libm"
|
|
||||||
version = "0.2.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.20"
|
version = "0.4.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.1"
|
version = "2.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memmap2"
|
name = "memmap2"
|
||||||
version = "0.9.3"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "45fd3a57831bf88bc63f8cebc0cf956116276e97fef3966103e96416209f7c92"
|
checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-traits"
|
|
||||||
version = "0.2.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"libm",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "packed_simd"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pcre2"
|
name = "pcre2"
|
||||||
version = "0.2.6"
|
version = "0.2.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c9d53a8ea5fc3d3568d3de4bebc12606fd0eb8234c602576f1f1ee4880488a7"
|
checksum = "3be55c43ac18044541d58d897e8f4c55157218428953ebd39d86df3ba0286b2b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
@ -336,9 +297,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pcre2-sys"
|
name = "pcre2-sys"
|
||||||
version = "0.2.8"
|
version = "0.2.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "25b8a7b5253a4465b873a21ee7e8d6ec561a57eed5d319621bec36bea35c86ae"
|
checksum = "550f5d18fb1b90c20b87e161852c10cde77858c3900c5059b5ad2a1449f11d8a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@ -347,33 +308,33 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
|
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.76"
|
version = "1.0.86"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
|
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.35"
|
version = "1.0.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.10.2"
|
version = "1.10.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -383,9 +344,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.4.3"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -394,13 +355,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.2"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ripgrep"
|
name = "ripgrep"
|
||||||
version = "14.1.0"
|
version = "14.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bstr",
|
"bstr",
|
||||||
@ -419,9 +380,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.16"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
@ -434,18 +395,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.195"
|
version = "1.0.210"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
|
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.195"
|
version = "1.0.210"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
|
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -454,20 +415,27 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.111"
|
version = "1.0.128"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
|
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
|
"memchr",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "shlex"
|
||||||
version = "2.0.48"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.77"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -476,18 +444,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.4.0"
|
version = "1.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
|
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.16.0"
|
version = "0.16.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
|
checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
@ -497,41 +465,92 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.4.0"
|
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 = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"same-file",
|
"same-file",
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-i686-pc-windows-gnu",
|
|
||||||
"winapi-x86_64-pc-windows-gnu",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.6"
|
version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "windows-sys"
|
||||||
version = "0.4.0"
|
version = "0.59.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ripgrep"
|
name = "ripgrep"
|
||||||
version = "14.1.0" #:version
|
version = "14.1.1" #: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 the current
|
ripgrep is a line-oriented search tool that recursively searches the current
|
||||||
@ -51,8 +51,8 @@ members = [
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.75"
|
anyhow = "1.0.75"
|
||||||
bstr = "1.7.0"
|
bstr = "1.7.0"
|
||||||
grep = { version = "0.3.1", path = "crates/grep" }
|
grep = { version = "0.3.2", path = "crates/grep" }
|
||||||
ignore = { version = "0.4.22", path = "crates/ignore" }
|
ignore = { version = "0.4.23", path = "crates/ignore" }
|
||||||
lexopt = "0.3.0"
|
lexopt = "0.3.0"
|
||||||
log = "0.4.5"
|
log = "0.4.5"
|
||||||
serde_json = "1.0.23"
|
serde_json = "1.0.23"
|
||||||
@ -68,7 +68,6 @@ serde_derive = "1.0.77"
|
|||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
simd-accel = ["grep/simd-accel"]
|
|
||||||
pcre2 = ["grep/pcre2"]
|
pcre2 = ["grep/pcre2"]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
23
FAQ.md
23
FAQ.md
@ -94,7 +94,7 @@ Does ripgrep have support for shell auto-completion?
|
|||||||
|
|
||||||
Yes! If you installed ripgrep through a package manager on a Unix system, then
|
Yes! If you installed ripgrep through a package manager on a Unix system, then
|
||||||
the shell completion files included in the release archive should have been
|
the shell completion files included in the release archive should have been
|
||||||
installed for you automatically. If not, you can generate completes using
|
installed for you automatically. If not, you can generate completions using
|
||||||
ripgrep's command line interface.
|
ripgrep's command line interface.
|
||||||
|
|
||||||
For **bash**:
|
For **bash**:
|
||||||
@ -113,14 +113,31 @@ $ mkdir -p "$dir"
|
|||||||
$ rg --generate complete-fish > "$dir/rg.fish"
|
$ rg --generate complete-fish > "$dir/rg.fish"
|
||||||
```
|
```
|
||||||
|
|
||||||
For **zsh**:
|
For **zsh**, the recommended approach is:
|
||||||
|
|
||||||
```
|
```zsh
|
||||||
$ dir="$HOME/.zsh-complete"
|
$ dir="$HOME/.zsh-complete"
|
||||||
$ mkdir -p "$dir"
|
$ mkdir -p "$dir"
|
||||||
$ rg --generate complete-zsh > "$dir/_rg"
|
$ rg --generate complete-zsh > "$dir/_rg"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
And then add `$HOME/.zsh-complete` to your `fpath` in, e.g., your
|
||||||
|
`$HOME/.zshrc` file:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
fpath=($HOME/.zsh-complete $fpath)
|
||||||
|
```
|
||||||
|
|
||||||
|
Or if you'd prefer to load and generate completions at the same time, you can
|
||||||
|
add the following to your `$HOME/.zshrc` file:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
$ source <(rg --generate complete-zsh)
|
||||||
|
```
|
||||||
|
|
||||||
|
Note though that while this approach is easier to setup, is generally slower
|
||||||
|
than the previous method, and will add more time to loading your shell prompt.
|
||||||
|
|
||||||
For **PowerShell**, create the completions:
|
For **PowerShell**, create the completions:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
46
README.md
46
README.md
@ -98,7 +98,7 @@ files for patterns without any opportunities for literal optimizations:
|
|||||||
| Tool | Command | Line count | Time |
|
| Tool | Command | Line count | Time |
|
||||||
| ---- | ------- | ---------- | ---- |
|
| ---- | ------- | ---------- | ---- |
|
||||||
| ripgrep | `rg '[A-Za-z]{30}'` | 6749 | **15.569s** (1.00x) |
|
| ripgrep | `rg '[A-Za-z]{30}'` | 6749 | **15.569s** (1.00x) |
|
||||||
| [ugrep](https://github.com/Genivia/ugrep) | `ugrep -w '[A-Z]\w+ Sherlock [A-Z]\w+'` | 6749 | 21.857s (1.40x) |
|
| [ugrep](https://github.com/Genivia/ugrep) | `ugrep -E '[A-Za-z]{30}'` | 6749 | 21.857s (1.40x) |
|
||||||
| [GNU grep](https://www.gnu.org/software/grep/) | `LC_ALL=C grep -E '[A-Za-z]{30}'` | 6749 | 32.409s (2.08x) |
|
| [GNU grep](https://www.gnu.org/software/grep/) | `LC_ALL=C grep -E '[A-Za-z]{30}'` | 6749 | 32.409s (2.08x) |
|
||||||
| [GNU grep (Unicode)](https://www.gnu.org/software/grep/) | `LC_ALL=en_US.UTF-8 grep -E '[A-Za-z]{30}'` | 6795 | 8m30s (32.74x) |
|
| [GNU grep (Unicode)](https://www.gnu.org/software/grep/) | `LC_ALL=en_US.UTF-8 grep -E '[A-Za-z]{30}'` | 6795 | 8m30s (32.74x) |
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ generally speaking):
|
|||||||
backreferences in your patterns, which are not supported in ripgrep's default
|
backreferences in your patterns, which are not supported in ripgrep's default
|
||||||
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)` option.
|
||||||
* ripgrep has [rudimentary support for replacements](GUIDE.md#replacements),
|
* ripgrep has [rudimentary support for replacements](GUIDE.md#replacements),
|
||||||
which permit rewriting output based on what was matched.
|
which permit rewriting output based on what was matched.
|
||||||
* ripgrep supports [searching files in text encodings](GUIDE.md#file-encoding)
|
* ripgrep supports [searching files in text encodings](GUIDE.md#file-encoding)
|
||||||
@ -220,6 +220,16 @@ configuration files, passthru, support for searching compressed files,
|
|||||||
multiline search and opt-in fancy regex support via PCRE2.
|
multiline search and opt-in fancy regex support via PCRE2.
|
||||||
|
|
||||||
|
|
||||||
|
### Playground
|
||||||
|
|
||||||
|
If you'd like to try ripgrep before installing, there's an unofficial
|
||||||
|
[playground](https://codapi.org/ripgrep/) and an [interactive
|
||||||
|
tutorial](https://codapi.org/try/ripgrep/).
|
||||||
|
|
||||||
|
If you have any questions about these, please open an issue in the [tutorial
|
||||||
|
repo](https://github.com/nalgeon/tryxinyminutes).
|
||||||
|
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
The binary name for ripgrep is `rg`.
|
The binary name for ripgrep is `rg`.
|
||||||
@ -308,6 +318,12 @@ If you're a **Nix** user, you can install ripgrep from
|
|||||||
$ nix-env --install ripgrep
|
$ nix-env --install ripgrep
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you're a **Flox** user, you can install ripgrep as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ flox install ripgrep
|
||||||
|
```
|
||||||
|
|
||||||
If you're a **Guix** user, you can install ripgrep from the official
|
If you're a **Guix** user, you can install ripgrep from the official
|
||||||
package collection:
|
package collection:
|
||||||
|
|
||||||
@ -320,8 +336,8 @@ 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/13.0.0/ripgrep_13.0.0_amd64.deb
|
$ curl -LO https://github.com/BurntSushi/ripgrep/releases/download/14.1.0/ripgrep_14.1.0-1_amd64.deb
|
||||||
$ sudo dpkg -i ripgrep_13.0.0_amd64.deb
|
$ sudo dpkg -i ripgrep_14.1.0-1_amd64.deb
|
||||||
```
|
```
|
||||||
|
|
||||||
If you run Debian stable, ripgrep is [officially maintained by
|
If you run Debian stable, ripgrep is [officially maintained by
|
||||||
@ -432,18 +448,13 @@ $ ./target/release/rg --version
|
|||||||
0.1.3
|
0.1.3
|
||||||
```
|
```
|
||||||
|
|
||||||
If you have a Rust nightly compiler and a recent Intel CPU, then you can enable
|
**NOTE:** In the past, ripgrep supported a `simd-accel` Cargo feature when
|
||||||
additional optional SIMD acceleration like so:
|
using a Rust nightly compiler. This only benefited UTF-16 transcoding.
|
||||||
|
Since it required unstable features, this build mode was prone to breakage.
|
||||||
```
|
Because of that, support for it has been removed. If you want SIMD
|
||||||
RUSTFLAGS="-C target-cpu=native" cargo build --release --features 'simd-accel'
|
optimizations for UTF-16 transcoding, then you'll have to petition the
|
||||||
```
|
[`encoding_rs`](https://github.com/hsivonen/encoding_rs) project to use stable
|
||||||
|
APIs.
|
||||||
The `simd-accel` feature enables SIMD support in certain ripgrep dependencies
|
|
||||||
(responsible for transcoding). They are not necessary to get SIMD optimizations
|
|
||||||
for search; those are enabled automatically. Hopefully, some day, the
|
|
||||||
`simd-accel` feature will similarly become unnecessary. **WARNING:** Currently,
|
|
||||||
enabling this option can increase compilation times dramatically.
|
|
||||||
|
|
||||||
Finally, optional PCRE2 support can be built with ripgrep by enabling the
|
Finally, optional PCRE2 support can be built with ripgrep by enabling the
|
||||||
`pcre2` feature:
|
`pcre2` feature:
|
||||||
@ -452,9 +463,6 @@ Finally, optional PCRE2 support can be built with ripgrep by enabling the
|
|||||||
$ cargo build --release --features 'pcre2'
|
$ cargo build --release --features 'pcre2'
|
||||||
```
|
```
|
||||||
|
|
||||||
(Tip: use `--features 'pcre2 simd-accel'` to also include compile time SIMD
|
|
||||||
optimizations, which will only work with a nightly compiler.)
|
|
||||||
|
|
||||||
Enabling the PCRE2 feature works with a stable Rust compiler and will
|
Enabling the PCRE2 feature works with a stable Rust compiler and will
|
||||||
attempt to automatically find and link with your system's PCRE2 library via
|
attempt to automatically find and link with your system's PCRE2 library via
|
||||||
`pkg-config`. If one doesn't exist, then ripgrep will build PCRE2 from source
|
`pkg-config`. If one doesn't exist, then ripgrep will build PCRE2 from source
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-cli"
|
name = "grep-cli"
|
||||||
version = "0.1.10" #:version
|
version = "0.1.11" #: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.
|
||||||
@ -15,7 +15,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bstr = { version = "1.6.2", features = ["std"] }
|
bstr = { version = "1.6.2", features = ["std"] }
|
||||||
globset = { version = "0.4.14", path = "../globset" }
|
globset = { version = "0.4.15", path = "../globset" }
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
termcolor = "1.3.0"
|
termcolor = "1.3.0"
|
||||||
|
|
||||||
|
@ -25,10 +25,10 @@ pub fn hostname() -> io::Result<OsString> {
|
|||||||
}
|
}
|
||||||
#[cfg(not(any(windows, unix)))]
|
#[cfg(not(any(windows, unix)))]
|
||||||
{
|
{
|
||||||
io::Error::new(
|
Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"hostname could not be found on unsupported platform",
|
"hostname could not be found on unsupported platform",
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,22 +178,71 @@ pub fn is_readable_stdin() -> bool {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let stdin = std::io::stdin();
|
let stdin = std::io::stdin();
|
||||||
let Ok(fd) = stdin.as_fd().try_clone_to_owned() else { return false };
|
let fd = match stdin.as_fd().try_clone_to_owned() {
|
||||||
|
Ok(fd) => fd,
|
||||||
|
Err(err) => {
|
||||||
|
log::debug!(
|
||||||
|
"for heuristic stdin detection on Unix, \
|
||||||
|
could not clone stdin file descriptor \
|
||||||
|
(thus assuming stdin is not readable): {err}",
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
let file = File::from(fd);
|
let file = File::from(fd);
|
||||||
let Ok(md) = file.metadata() else { return false };
|
let md = match file.metadata() {
|
||||||
|
Ok(md) => md,
|
||||||
|
Err(err) => {
|
||||||
|
log::debug!(
|
||||||
|
"for heuristic stdin detection on Unix, \
|
||||||
|
could not get file metadata for stdin \
|
||||||
|
(thus assuming stdin is not readable): {err}",
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
let ft = md.file_type();
|
let ft = md.file_type();
|
||||||
ft.is_file() || ft.is_fifo() || ft.is_socket()
|
let is_file = ft.is_file();
|
||||||
|
let is_fifo = ft.is_fifo();
|
||||||
|
let is_socket = ft.is_socket();
|
||||||
|
let is_readable = is_file || is_fifo || is_socket;
|
||||||
|
log::debug!(
|
||||||
|
"for heuristic stdin detection on Unix, \
|
||||||
|
found that \
|
||||||
|
is_file={is_file}, is_fifo={is_fifo} and is_socket={is_socket}, \
|
||||||
|
and thus concluded that is_stdin_readable={is_readable}",
|
||||||
|
);
|
||||||
|
is_readable
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn imp() -> bool {
|
fn imp() -> bool {
|
||||||
winapi_util::file::typ(winapi_util::HandleRef::stdin())
|
let stdin = winapi_util::HandleRef::stdin();
|
||||||
.map(|t| t.is_disk() || t.is_pipe())
|
let typ = match winapi_util::file::typ(stdin) {
|
||||||
.unwrap_or(false)
|
Ok(typ) => typ,
|
||||||
|
Err(err) => {
|
||||||
|
log::debug!(
|
||||||
|
"for heuristic stdin detection on Windows, \
|
||||||
|
could not get file type of stdin \
|
||||||
|
(thus assuming stdin is not readable): {err}",
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let is_disk = typ.is_disk();
|
||||||
|
let is_pipe = typ.is_pipe();
|
||||||
|
let is_readable = is_disk || is_pipe;
|
||||||
|
log::debug!(
|
||||||
|
"for heuristic stdin detection on Windows, \
|
||||||
|
found that is_disk={is_disk} and is_pipe={is_pipe}, \
|
||||||
|
and thus concluded that is_stdin_readable={is_readable}",
|
||||||
|
);
|
||||||
|
is_readable
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(unix, windows)))]
|
#[cfg(not(any(unix, windows)))]
|
||||||
fn imp() -> bool {
|
fn imp() -> bool {
|
||||||
|
log::debug!("on non-{{Unix,Windows}}, assuming stdin is not readable");
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::io::{self, IsTerminal};
|
use std::io::{self, IsTerminal};
|
||||||
|
|
||||||
use termcolor::{self, HyperlinkSpec};
|
use termcolor::HyperlinkSpec;
|
||||||
|
|
||||||
/// A writer that supports coloring with either line or block buffering.
|
/// A writer that supports coloring with either line or block buffering.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -434,7 +434,15 @@ _rg_types() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Don't run the completion function when being sourced by itself.
|
||||||
|
#
|
||||||
|
# See https://github.com/BurntSushi/ripgrep/issues/2956
|
||||||
|
# See https://github.com/BurntSushi/ripgrep/pull/2957
|
||||||
|
if [[ $funcstack[1] == _rg ]] || (( ! $+functions[compdef] )); then
|
||||||
_rg "$@"
|
_rg "$@"
|
||||||
|
else
|
||||||
|
compdef _rg rg
|
||||||
|
fi
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# ZSH COMPLETION REFERENCE
|
# ZSH COMPLETION REFERENCE
|
||||||
|
@ -2627,7 +2627,7 @@ of printing the file path as a prefix for each matched line.
|
|||||||
This is the default mode when printing to a tty.
|
This is the default mode when printing to a tty.
|
||||||
.sp
|
.sp
|
||||||
When \fBstdout\fP is not a tty, then ripgrep will default to the standard
|
When \fBstdout\fP is not a tty, then ripgrep will default to the standard
|
||||||
grep-like format. Once can force this format in Unix-like environments by
|
grep-like format. One can force this format in Unix-like environments by
|
||||||
piping the output of ripgrep to \fBcat\fP. For example, \fBrg\fP \fIfoo\fP \fB|
|
piping the output of ripgrep to \fBcat\fP. For example, \fBrg\fP \fIfoo\fP \fB|
|
||||||
cat\fP.
|
cat\fP.
|
||||||
"
|
"
|
||||||
@ -2746,7 +2746,7 @@ impl Flag for Hidden {
|
|||||||
Search hidden files and directories. By default, hidden files and directories
|
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
|
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.
|
an ignore file, then it will be searched even if this flag isn't provided.
|
||||||
Similarly if a hidden file or directory is given explicitly as an argumnet to
|
Similarly if a hidden file or directory is given explicitly as an argument to
|
||||||
ripgrep.
|
ripgrep.
|
||||||
.sp
|
.sp
|
||||||
A file or directory is considered hidden if its base name starts with a dot
|
A file or directory is considered hidden if its base name starts with a dot
|
||||||
@ -7261,7 +7261,7 @@ impl Flag for Vimgrep {
|
|||||||
Category::Output
|
Category::Output
|
||||||
}
|
}
|
||||||
fn doc_short(&self) -> &'static str {
|
fn doc_short(&self) -> &'static str {
|
||||||
r"Print results im a vim compatible format."
|
r"Print results in a vim compatible format."
|
||||||
}
|
}
|
||||||
fn doc_long(&self) -> &'static str {
|
fn doc_long(&self) -> &'static str {
|
||||||
r"
|
r"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH RG 1 2023-11-26 "!!VERSION!!" "User Commands"
|
.TH RG 1 2024-09-08 "!!VERSION!!" "User Commands"
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
.SH NAME
|
.SH NAME
|
||||||
@ -43,10 +43,10 @@ configuration file. The file can specify one shell argument per line. Lines
|
|||||||
starting with \fB#\fP are ignored. For more details, see \fBCONFIGURATION
|
starting with \fB#\fP are ignored. For more details, see \fBCONFIGURATION
|
||||||
FILES\fP below.
|
FILES\fP below.
|
||||||
.sp
|
.sp
|
||||||
ripgrep will automatically detect if stdin exists and search stdin for a regex
|
ripgrep will automatically detect if stdin is a readable file and search stdin
|
||||||
pattern, e.g. \fBls | rg foo\fP. In some environments, stdin may exist when
|
for a regex pattern, e.g. \fBls | rg foo\fP. In some environments, stdin may
|
||||||
it shouldn't. To turn off stdin detection, one can explicitly specify the
|
exist when it shouldn't. To turn off stdin detection, one can explicitly
|
||||||
directory to search, e.g. \fBrg foo ./\fP.
|
specify the directory to search, e.g. \fBrg foo ./\fP.
|
||||||
.sp
|
.sp
|
||||||
Like other tools such as \fBls\fP, ripgrep will alter its output depending on
|
Like other tools such as \fBls\fP, ripgrep will alter its output depending on
|
||||||
whether stdout is connected to a tty. By default, when printing a tty, ripgrep
|
whether stdout is connected to a tty. By default, when printing a tty, ripgrep
|
||||||
|
@ -161,9 +161,6 @@ fn compile_cpu_features() -> Vec<String> {
|
|||||||
fn features() -> Vec<String> {
|
fn features() -> Vec<String> {
|
||||||
let mut features = vec![];
|
let mut features = vec![];
|
||||||
|
|
||||||
let simd_accel = cfg!(feature = "simd-accel");
|
|
||||||
features.push(format!("{sign}simd-accel", sign = sign(simd_accel)));
|
|
||||||
|
|
||||||
let pcre2 = cfg!(feature = "pcre2");
|
let pcre2 = cfg!(feature = "pcre2");
|
||||||
features.push(format!("{sign}pcre2", sign = sign(pcre2)));
|
features.push(format!("{sign}pcre2", sign = sign(pcre2)));
|
||||||
|
|
||||||
|
@ -484,9 +484,9 @@ impl HiArgs {
|
|||||||
if self.crlf {
|
if self.crlf {
|
||||||
builder.crlf(true);
|
builder.crlf(true);
|
||||||
}
|
}
|
||||||
// We don't need to set this in multiline mode since mulitline
|
// We don't need to set this in multiline mode since multiline
|
||||||
// matchers don't use optimizations related to line terminators.
|
// matchers don't use optimizations related to line terminators.
|
||||||
// Moreover, a mulitline regex used with --null-data should
|
// Moreover, a multiline regex used with --null-data should
|
||||||
// be allowed to match NUL bytes explicitly, which this would
|
// be allowed to match NUL bytes explicitly, which this would
|
||||||
// otherwise forbid.
|
// otherwise forbid.
|
||||||
if self.null_data {
|
if self.null_data {
|
||||||
@ -1080,9 +1080,18 @@ impl Paths {
|
|||||||
}
|
}
|
||||||
paths.push(path);
|
paths.push(path);
|
||||||
}
|
}
|
||||||
|
log::debug!("number of paths given to search: {}", paths.len());
|
||||||
if !paths.is_empty() {
|
if !paths.is_empty() {
|
||||||
let is_one_file = paths.len() == 1
|
let is_one_file = paths.len() == 1
|
||||||
&& (paths[0] == Path::new("-") || paths[0].is_file());
|
// Note that we specifically use `!paths[0].is_dir()` here
|
||||||
|
// instead of `paths[0].is_file()`. Namely, the latter can
|
||||||
|
// return `false` even when the path is something resembling
|
||||||
|
// a file. So instead, we just consider the path a file as
|
||||||
|
// long as we know it isn't a directory.
|
||||||
|
//
|
||||||
|
// See: https://github.com/BurntSushi/ripgrep/issues/2736
|
||||||
|
&& (paths[0] == Path::new("-") || !paths[0].is_dir());
|
||||||
|
log::debug!("is_one_file? {is_one_file:?}");
|
||||||
return Ok(Paths { paths, has_implicit_path: false, is_one_file });
|
return Ok(Paths { paths, has_implicit_path: false, is_one_file });
|
||||||
}
|
}
|
||||||
// N.B. is_readable_stdin is a heuristic! Part of the issue is that a
|
// N.B. is_readable_stdin is a heuristic! Part of the issue is that a
|
||||||
|
@ -323,7 +323,7 @@ enum FlagLookup<'a> {
|
|||||||
UnrecognizedLong(String),
|
UnrecognizedLong(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The info about a flag associated with a flag's ID in the the flag map.
|
/// The info about a flag associated with a flag's ID in the flag map.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct FlagInfo {
|
struct FlagInfo {
|
||||||
/// The flag object and its associated metadata.
|
/// The flag object and its associated metadata.
|
||||||
|
@ -6,7 +6,7 @@ print to stderr. We therefore avoid bringing in extra dependencies just for
|
|||||||
this functionality.
|
this functionality.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use log::{self, Log};
|
use log::Log;
|
||||||
|
|
||||||
/// The simplest possible logger that logs to stderr.
|
/// The simplest possible logger that logs to stderr.
|
||||||
///
|
///
|
||||||
|
@ -28,7 +28,7 @@ static ERRORED: AtomicBool = AtomicBool::new(false);
|
|||||||
///
|
///
|
||||||
/// This locks stdout, not stderr, even though this prints to stderr. This
|
/// This locks stdout, not stderr, even though this prints to stderr. This
|
||||||
/// avoids the appearance of interleaving output when stdout and stderr both
|
/// avoids the appearance of interleaving output when stdout and stderr both
|
||||||
/// correspond to a tty.)
|
/// correspond to a tty.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! eprintln_locked {
|
macro_rules! eprintln_locked {
|
||||||
($($tt:tt)*) => {{
|
($($tt:tt)*) => {{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.14" #:version
|
version = "0.4.16" #: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
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use std::fmt::Write;
|
||||||
use std::path::{is_separator, Path};
|
use std::path::{is_separator, Path};
|
||||||
|
|
||||||
use regex_automata::meta::Regex;
|
use regex_automata::meta::Regex;
|
||||||
@ -732,7 +733,9 @@ impl Tokens {
|
|||||||
/// Convert a Unicode scalar value to an escaped string suitable for use as
|
/// Convert a Unicode scalar value to an escaped string suitable for use as
|
||||||
/// a literal in a non-Unicode regex.
|
/// a literal in a non-Unicode regex.
|
||||||
fn char_to_escaped_literal(c: char) -> String {
|
fn char_to_escaped_literal(c: char) -> String {
|
||||||
bytes_to_escaped_literal(&c.to_string().into_bytes())
|
let mut buf = [0; 4];
|
||||||
|
let bytes = c.encode_utf8(&mut buf).as_bytes();
|
||||||
|
bytes_to_escaped_literal(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an arbitrary sequence of bytes to a UTF-8 string. All non-ASCII
|
/// Converts an arbitrary sequence of bytes to a UTF-8 string. All non-ASCII
|
||||||
@ -741,11 +744,12 @@ fn bytes_to_escaped_literal(bs: &[u8]) -> String {
|
|||||||
let mut s = String::with_capacity(bs.len());
|
let mut s = String::with_capacity(bs.len());
|
||||||
for &b in bs {
|
for &b in bs {
|
||||||
if b <= 0x7F {
|
if b <= 0x7F {
|
||||||
s.push_str(®ex_syntax::escape(
|
regex_syntax::escape_into(
|
||||||
char::from(b).encode_utf8(&mut [0; 4]),
|
char::from(b).encode_utf8(&mut [0; 4]),
|
||||||
));
|
&mut s,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
s.push_str(&format!("\\x{:02x}", b));
|
write!(&mut s, "\\x{:02x}", b).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s
|
s
|
||||||
|
@ -928,13 +928,26 @@ impl RequiredExtensionStrategyBuilder {
|
|||||||
///
|
///
|
||||||
/// The escaping works by surrounding meta-characters with brackets. For
|
/// The escaping works by surrounding meta-characters with brackets. For
|
||||||
/// example, `*` becomes `[*]`.
|
/// example, `*` becomes `[*]`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use globset::escape;
|
||||||
|
///
|
||||||
|
/// assert_eq!(escape("foo*bar"), "foo[*]bar");
|
||||||
|
/// assert_eq!(escape("foo?bar"), "foo[?]bar");
|
||||||
|
/// assert_eq!(escape("foo[bar"), "foo[[]bar");
|
||||||
|
/// assert_eq!(escape("foo]bar"), "foo[]]bar");
|
||||||
|
/// assert_eq!(escape("foo{bar"), "foo[{]bar");
|
||||||
|
/// assert_eq!(escape("foo}bar"), "foo[}]bar");
|
||||||
|
/// ```
|
||||||
pub fn escape(s: &str) -> String {
|
pub fn escape(s: &str) -> String {
|
||||||
let mut escaped = String::with_capacity(s.len());
|
let mut escaped = String::with_capacity(s.len());
|
||||||
for c in s.chars() {
|
for c in s.chars() {
|
||||||
match c {
|
match c {
|
||||||
// note that ! does not need escaping because it is only special
|
// note that ! does not need escaping because it is only special
|
||||||
// inside brackets
|
// inside brackets
|
||||||
'?' | '*' | '[' | ']' => {
|
'?' | '*' | '[' | ']' | '{' | '}' => {
|
||||||
escaped.push('[');
|
escaped.push('[');
|
||||||
escaped.push(c);
|
escaped.push(c);
|
||||||
escaped.push(']');
|
escaped.push(']');
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep"
|
name = "grep"
|
||||||
version = "0.3.1" #:version
|
version = "0.3.2" #: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.
|
||||||
@ -14,20 +14,20 @@ license = "Unlicense OR MIT"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
grep-cli = { version = "0.1.10", path = "../cli" }
|
grep-cli = { version = "0.1.11", path = "../cli" }
|
||||||
grep-matcher = { version = "0.1.7", path = "../matcher" }
|
grep-matcher = { version = "0.1.7", path = "../matcher" }
|
||||||
grep-pcre2 = { version = "0.1.7", path = "../pcre2", optional = true }
|
grep-pcre2 = { version = "0.1.8", path = "../pcre2", optional = true }
|
||||||
grep-printer = { version = "0.2.1", path = "../printer" }
|
grep-printer = { version = "0.2.2", path = "../printer" }
|
||||||
grep-regex = { version = "0.1.12", path = "../regex" }
|
grep-regex = { version = "0.1.13", path = "../regex" }
|
||||||
grep-searcher = { version = "0.1.13", path = "../searcher" }
|
grep-searcher = { version = "0.1.14", path = "../searcher" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
termcolor = "1.0.4"
|
termcolor = "1.0.4"
|
||||||
walkdir = "2.2.7"
|
walkdir = "2.2.7"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
simd-accel = ["grep-searcher/simd-accel"]
|
|
||||||
pcre2 = ["grep-pcre2"]
|
pcre2 = ["grep-pcre2"]
|
||||||
|
|
||||||
# This feature is DEPRECATED. Runtime dispatch is used for SIMD now.
|
# These features are DEPRECATED. Runtime dispatch is used for SIMD now.
|
||||||
|
simd-accel = []
|
||||||
avx-accel = []
|
avx-accel = []
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.4.22" #:version
|
version = "0.4.23" #: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`
|
||||||
@ -20,7 +20,7 @@ bench = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
crossbeam-deque = "0.8.3"
|
crossbeam-deque = "0.8.3"
|
||||||
globset = { version = "0.4.14", path = "../globset" }
|
globset = { version = "0.4.15", path = "../globset" }
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
memchr = "2.6.3"
|
memchr = "2.6.3"
|
||||||
same-file = "1.0.6"
|
same-file = "1.0.6"
|
||||||
@ -36,7 +36,7 @@ version = "0.1.2"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bstr = { version = "1.6.2", default-features = false, features = ["std"] }
|
bstr = { version = "1.6.2", default-features = false, features = ["std"] }
|
||||||
crossbeam-channel = "0.5.8"
|
crossbeam-channel = "0.5.15"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# DEPRECATED. It is a no-op. SIMD is done automatically through runtime
|
# DEPRECATED. It is a no-op. SIMD is done automatically through runtime
|
||||||
|
@ -232,6 +232,7 @@ pub(crate) const DEFAULT_TYPES: &[(&[&str], &[&str])] = &[
|
|||||||
(&["rust"], &["*.rs"]),
|
(&["rust"], &["*.rs"]),
|
||||||
(&["sass"], &["*.sass", "*.scss"]),
|
(&["sass"], &["*.sass", "*.scss"]),
|
||||||
(&["scala"], &["*.scala", "*.sbt"]),
|
(&["scala"], &["*.scala", "*.sbt"]),
|
||||||
|
(&["seed7"], &["*.sd7", "*.s7i"]),
|
||||||
(&["sh"], &[
|
(&["sh"], &[
|
||||||
// Portable/misc. init files
|
// Portable/misc. init files
|
||||||
".login", ".logout", ".profile", "profile",
|
".login", ".logout", ".profile", "profile",
|
||||||
@ -265,6 +266,7 @@ pub(crate) const DEFAULT_TYPES: &[(&[&str], &[&str])] = &[
|
|||||||
(&["sql"], &["*.sql", "*.psql"]),
|
(&["sql"], &["*.sql", "*.psql"]),
|
||||||
(&["stylus"], &["*.styl"]),
|
(&["stylus"], &["*.styl"]),
|
||||||
(&["sv"], &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]),
|
(&["sv"], &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]),
|
||||||
|
(&["svelte"], &["*.svelte"]),
|
||||||
(&["svg"], &["*.svg"]),
|
(&["svg"], &["*.svg"]),
|
||||||
(&["swift"], &["*.swift"]),
|
(&["swift"], &["*.swift"]),
|
||||||
(&["swig"], &["*.def", "*.i"]),
|
(&["swig"], &["*.def", "*.i"]),
|
||||||
@ -302,7 +304,9 @@ pub(crate) const DEFAULT_TYPES: &[(&[&str], &[&str])] = &[
|
|||||||
(&["vimscript"], &[
|
(&["vimscript"], &[
|
||||||
"*.vim", ".vimrc", ".gvimrc", "vimrc", "gvimrc", "_vimrc", "_gvimrc",
|
"*.vim", ".vimrc", ".gvimrc", "vimrc", "gvimrc", "_vimrc", "_gvimrc",
|
||||||
]),
|
]),
|
||||||
|
(&["vue"], &["*.vue"]),
|
||||||
(&["webidl"], &["*.idl", "*.webidl", "*.widl"]),
|
(&["webidl"], &["*.idl", "*.webidl", "*.widl"]),
|
||||||
|
(&["wgsl"], &["*.wgsl"]),
|
||||||
(&["wiki"], &["*.mediawiki", "*.wiki"]),
|
(&["wiki"], &["*.mediawiki", "*.wiki"]),
|
||||||
(&["xml"], &[
|
(&["xml"], &[
|
||||||
"*.xml", "*.xml.dist", "*.dtd", "*.xsl", "*.xslt", "*.xsd", "*.xjb",
|
"*.xml", "*.xml.dist", "*.dtd", "*.xsl", "*.xslt", "*.xsd", "*.xjb",
|
||||||
|
@ -390,6 +390,7 @@ impl GitignoreBuilder {
|
|||||||
Err(err) => return Some(Error::Io(err).with_path(path)),
|
Err(err) => return Some(Error::Io(err).with_path(path)),
|
||||||
Ok(file) => file,
|
Ok(file) => file,
|
||||||
};
|
};
|
||||||
|
log::debug!("opened gitignore file: {}", path.display());
|
||||||
let rdr = BufReader::new(file);
|
let rdr = BufReader::new(file);
|
||||||
let mut errs = PartialErrorBuilder::default();
|
let mut errs = PartialErrorBuilder::default();
|
||||||
for (i, line) in rdr.lines().enumerate() {
|
for (i, line) in rdr.lines().enumerate() {
|
||||||
|
@ -11,7 +11,7 @@ use std::{
|
|||||||
use {
|
use {
|
||||||
crossbeam_deque::{Stealer, Worker as Deque},
|
crossbeam_deque::{Stealer, Worker as Deque},
|
||||||
same_file::Handle,
|
same_file::Handle,
|
||||||
walkdir::{self, WalkDir},
|
walkdir::WalkDir,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -591,7 +591,7 @@ impl WalkBuilder {
|
|||||||
///
|
///
|
||||||
/// Note that this *doesn't* return something that implements `Iterator`.
|
/// Note that this *doesn't* return something that implements `Iterator`.
|
||||||
/// Instead, the returned value must be run with a closure. e.g.,
|
/// Instead, the returned value must be run with a closure. e.g.,
|
||||||
/// `builder.build_parallel().run(|| |path| println!("{:?}", path))`.
|
/// `builder.build_parallel().run(|| |path| { println!("{path:?}"); WalkState::Continue })`.
|
||||||
pub fn build_parallel(&self) -> WalkParallel {
|
pub fn build_parallel(&self) -> WalkParallel {
|
||||||
WalkParallel {
|
WalkParallel {
|
||||||
paths: self.paths.clone().into_iter(),
|
paths: self.paths.clone().into_iter(),
|
||||||
|
@ -389,6 +389,15 @@ pub trait Captures {
|
|||||||
/// for the overall match.
|
/// for the overall match.
|
||||||
fn get(&self, i: usize) -> Option<Match>;
|
fn get(&self, i: usize) -> Option<Match>;
|
||||||
|
|
||||||
|
/// Return the overall match for the capture.
|
||||||
|
///
|
||||||
|
/// This returns the match for index `0`. That is it is equivalent to
|
||||||
|
/// `get(0).unwrap()`
|
||||||
|
#[inline]
|
||||||
|
fn as_match(&self) -> Match {
|
||||||
|
self.get(0).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if and only if these captures are empty. This occurs
|
/// Returns true if and only if these captures are empty. This occurs
|
||||||
/// when `len` is `0`.
|
/// when `len` is `0`.
|
||||||
///
|
///
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-pcre2"
|
name = "grep-pcre2"
|
||||||
version = "0.1.7" #:version
|
version = "0.1.8" #: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.
|
||||||
|
@ -428,7 +428,7 @@ fn has_uppercase_literal(pattern: &str) -> bool {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use grep_matcher::{LineMatchKind, Matcher};
|
use grep_matcher::LineMatchKind;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-printer"
|
name = "grep-printer"
|
||||||
version = "0.2.1" #:version
|
version = "0.2.2" #: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
|
||||||
@ -21,14 +21,14 @@ serde = ["dep:serde", "dep:serde_json"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
bstr = "1.6.2"
|
bstr = "1.6.2"
|
||||||
grep-matcher = { version = "0.1.7", path = "../matcher" }
|
grep-matcher = { version = "0.1.7", path = "../matcher" }
|
||||||
grep-searcher = { version = "0.1.13", path = "../searcher" }
|
grep-searcher = { version = "0.1.14", path = "../searcher" }
|
||||||
log = "0.4.5"
|
log = "0.4.5"
|
||||||
termcolor = "1.3.0"
|
termcolor = "1.3.0"
|
||||||
serde = { version = "1.0.193", optional = true }
|
serde = { version = "1.0.193", optional = true }
|
||||||
serde_json = { version = "1.0.107", optional = true }
|
serde_json = { version = "1.0.107", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
grep-regex = { version = "0.1.12", path = "../regex" }
|
grep-regex = { version = "0.1.13", path = "../regex" }
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
# We want to document all features.
|
# We want to document all features.
|
||||||
|
@ -811,6 +811,13 @@ impl HyperlinkPath {
|
|||||||
Some(HyperlinkPath::encode(with_slash.as_bytes()))
|
Some(HyperlinkPath::encode(with_slash.as_bytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For other platforms (not windows, not unix), return None and log a debug message.
|
||||||
|
#[cfg(not(any(windows, unix)))]
|
||||||
|
pub(crate) fn from_path(original_path: &Path) -> Option<HyperlinkPath> {
|
||||||
|
log::debug!("hyperlinks are not supported on this platform");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
/// Percent-encodes a path.
|
/// Percent-encodes a path.
|
||||||
///
|
///
|
||||||
/// The alphanumeric ASCII characters and "-", ".", "_", "~" are unreserved
|
/// The alphanumeric ASCII characters and "-", ".", "_", "~" are unreserved
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-regex"
|
name = "grep-regex"
|
||||||
version = "0.1.12" #:version
|
version = "0.1.13" #: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.
|
||||||
|
@ -233,7 +233,7 @@ impl ConfiguredHIR {
|
|||||||
&self.config
|
&self.config
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a reference to the underyling HIR.
|
/// Return a reference to the underlying HIR.
|
||||||
pub(crate) fn hir(&self) -> &Hir {
|
pub(crate) fn hir(&self) -> &Hir {
|
||||||
&self.hir
|
&self.hir
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ use crate::{config::ConfiguredHIR, error::Error};
|
|||||||
/// that are in turn used to build a simpler regex that is more amenable to
|
/// that are in turn used to build a simpler regex that is more amenable to
|
||||||
/// optimization.
|
/// optimization.
|
||||||
///
|
///
|
||||||
/// The main idea underyling the validity of this technique is the fact
|
/// The main idea underlying the validity of this technique is the fact
|
||||||
/// that ripgrep searches individuals lines and not across lines. (Unless
|
/// that ripgrep searches individuals lines and not across lines. (Unless
|
||||||
/// -U/--multiline is enabled.) Namely, we can pluck literals out of the regex,
|
/// -U/--multiline is enabled.) Namely, we can pluck literals out of the regex,
|
||||||
/// search for them, find the bounds of the line in which that literal occurs
|
/// search for them, find the bounds of the line in which that literal occurs
|
||||||
@ -430,6 +430,7 @@ impl Extractor {
|
|||||||
}
|
}
|
||||||
seq1.union(seq2);
|
seq1.union(seq2);
|
||||||
assert!(seq1.len().map_or(true, |x| x <= self.limit_total));
|
assert!(seq1.len().map_or(true, |x| x <= self.limit_total));
|
||||||
|
seq1.prefix = seq1.prefix && seq2.prefix;
|
||||||
seq1
|
seq1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,10 +587,15 @@ impl TSeq {
|
|||||||
lits.iter().any(is_poisonous)
|
lits.iter().any(is_poisonous)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare the two sequences and return the one that is believed to be best
|
/// Compare the two sequences and return the one that is believed to be
|
||||||
/// according to a hodge podge of heuristics.
|
/// best according to a hodge podge of heuristics.
|
||||||
fn choose(self, other: TSeq) -> TSeq {
|
fn choose(self, other: TSeq) -> TSeq {
|
||||||
let (seq1, seq2) = (self, other);
|
let (mut seq1, mut seq2) = (self, other);
|
||||||
|
// Whichever one we pick, by virtue of picking one, we choose
|
||||||
|
// to not take the other. So we must consider the result inexact.
|
||||||
|
seq1.make_inexact();
|
||||||
|
seq2.make_inexact();
|
||||||
|
|
||||||
if !seq1.is_finite() {
|
if !seq1.is_finite() {
|
||||||
return seq2;
|
return seq2;
|
||||||
} else if !seq2.is_finite() {
|
} else if !seq2.is_finite() {
|
||||||
@ -681,7 +687,7 @@ mod tests {
|
|||||||
assert_eq!(e(r"foo"), seq([E("foo")]));
|
assert_eq!(e(r"foo"), seq([E("foo")]));
|
||||||
assert_eq!(e(r"[a-z]foo[a-z]"), seq([I("foo")]));
|
assert_eq!(e(r"[a-z]foo[a-z]"), seq([I("foo")]));
|
||||||
assert_eq!(e(r"[a-z](foo)(bar)[a-z]"), seq([I("foobar")]));
|
assert_eq!(e(r"[a-z](foo)(bar)[a-z]"), seq([I("foobar")]));
|
||||||
assert_eq!(e(r"[a-z]([a-z]foo)(bar[a-z])[a-z]"), seq([I("foobar")]));
|
assert_eq!(e(r"[a-z]([a-z]foo)(bar[a-z])[a-z]"), seq([I("foo")]));
|
||||||
assert_eq!(e(r"[a-z]([a-z]foo)([a-z]foo)[a-z]"), seq([I("foo")]));
|
assert_eq!(e(r"[a-z]([a-z]foo)([a-z]foo)[a-z]"), seq([I("foo")]));
|
||||||
assert_eq!(e(r"(\d{1,3}\.){3}\d{1,3}"), seq([I(".")]));
|
assert_eq!(e(r"(\d{1,3}\.){3}\d{1,3}"), seq([I(".")]));
|
||||||
assert_eq!(e(r"[a-z]([a-z]foo){3}[a-z]"), seq([I("foo")]));
|
assert_eq!(e(r"[a-z]([a-z]foo){3}[a-z]"), seq([I("foo")]));
|
||||||
@ -689,7 +695,7 @@ mod tests {
|
|||||||
assert_eq!(e(r"[a-z]([a-z]foo[a-z]){3}[a-z]"), seq([I("foo")]));
|
assert_eq!(e(r"[a-z]([a-z]foo[a-z]){3}[a-z]"), seq([I("foo")]));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
e(r"[a-z]([a-z]foo){3}(bar[a-z]){3}[a-z]"),
|
e(r"[a-z]([a-z]foo){3}(bar[a-z]){3}[a-z]"),
|
||||||
seq([I("foobar")])
|
seq([I("foo")])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -935,14 +941,14 @@ mod tests {
|
|||||||
assert_eq!(Seq::infinite(), e(r"[A-Z]+"));
|
assert_eq!(Seq::infinite(), e(r"[A-Z]+"));
|
||||||
assert_eq!(seq([I("1")]), e(r"1[A-Z]"));
|
assert_eq!(seq([I("1")]), e(r"1[A-Z]"));
|
||||||
assert_eq!(seq([I("1")]), e(r"1[A-Z]2"));
|
assert_eq!(seq([I("1")]), e(r"1[A-Z]2"));
|
||||||
assert_eq!(seq([E("123")]), e(r"[A-Z]+123"));
|
assert_eq!(seq([I("123")]), e(r"[A-Z]+123"));
|
||||||
assert_eq!(seq([I("123")]), e(r"[A-Z]+123[A-Z]+"));
|
assert_eq!(seq([I("123")]), e(r"[A-Z]+123[A-Z]+"));
|
||||||
assert_eq!(Seq::infinite(), e(r"1|[A-Z]|3"));
|
assert_eq!(Seq::infinite(), e(r"1|[A-Z]|3"));
|
||||||
assert_eq!(seq([E("1"), I("2"), E("3")]), e(r"1|2[A-Z]|3"),);
|
assert_eq!(seq([E("1"), I("2"), E("3")]), e(r"1|2[A-Z]|3"),);
|
||||||
assert_eq!(seq([E("1"), I("2"), E("3")]), e(r"1|[A-Z]2[A-Z]|3"),);
|
assert_eq!(seq([E("1"), I("2"), E("3")]), e(r"1|[A-Z]2[A-Z]|3"),);
|
||||||
assert_eq!(seq([E("1"), E("2"), E("3")]), e(r"1|[A-Z]2|3"),);
|
assert_eq!(seq([E("1"), I("2"), E("3")]), e(r"1|[A-Z]2|3"),);
|
||||||
assert_eq!(seq([E("1"), I("2"), E("4")]), e(r"1|2[A-Z]3|4"),);
|
assert_eq!(seq([E("1"), I("2"), E("4")]), e(r"1|2[A-Z]3|4"),);
|
||||||
assert_eq!(seq([E("2")]), e(r"(?:|1)[A-Z]2"));
|
assert_eq!(seq([I("2")]), e(r"(?:|1)[A-Z]2"));
|
||||||
assert_eq!(inexact([I("a")]), e(r"a.z"));
|
assert_eq!(inexact([I("a")]), e(r"a.z"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1005,4 +1011,11 @@ mod tests {
|
|||||||
let s = e(r"foobarfoo|foo| |foofoo");
|
let s = e(r"foobarfoo|foo| |foofoo");
|
||||||
assert_eq!(Seq::infinite(), s);
|
assert_eq!(Seq::infinite(), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Regression test for: https://github.com/BurntSushi/ripgrep/issues/2884
|
||||||
|
#[test]
|
||||||
|
fn case_insensitive_alternation() {
|
||||||
|
let s = e(r"(?i:e.x|ex)");
|
||||||
|
assert_eq!(s, seq([I("X"), I("x")]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -552,8 +552,6 @@ impl RegexCaptures {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use grep_matcher::{LineMatchKind, Matcher};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// Test that enabling word matches does the right thing and demonstrate
|
// Test that enabling word matches does the right thing and demonstrate
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-searcher"
|
name = "grep-searcher"
|
||||||
version = "0.1.13" #:version
|
version = "0.1.14" #: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.
|
||||||
@ -23,11 +23,10 @@ memchr = "2.6.3"
|
|||||||
memmap = { package = "memmap2", version = "0.9.0" }
|
memmap = { package = "memmap2", version = "0.9.0" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
grep-regex = { version = "0.1.12", path = "../regex" }
|
grep-regex = { version = "0.1.13", path = "../regex" }
|
||||||
regex = "1.9.5"
|
regex = "1.9.5"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
simd-accel = ["encoding_rs/simd-accel"]
|
# These features are DEPRECATED. Runtime dispatch is used for SIMD now.
|
||||||
|
simd-accel = []
|
||||||
# This feature is DEPRECATED. Runtime dispatch is used for SIMD now.
|
|
||||||
avx-accel = []
|
avx-accel = []
|
||||||
|
@ -548,7 +548,7 @@ fn replace_bytes(
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use bstr::{ByteSlice, ByteVec};
|
use bstr::ByteVec;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -198,8 +198,6 @@ fn preceding_by_pos(
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use grep_matcher::Match;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
const SHERLOCK: &'static str = "\
|
const SHERLOCK: &'static str = "\
|
||||||
|
@ -7,7 +7,6 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use {
|
use {
|
||||||
encoding_rs,
|
|
||||||
encoding_rs_io::DecodeReaderBytesBuilder,
|
encoding_rs_io::DecodeReaderBytesBuilder,
|
||||||
grep_matcher::{LineTerminator, Match, Matcher},
|
grep_matcher::{LineTerminator, Match, Matcher},
|
||||||
};
|
};
|
||||||
@ -1005,6 +1004,7 @@ fn slice_has_bom(slice: &[u8]) -> bool {
|
|||||||
None => return false,
|
None => return false,
|
||||||
Some((enc, _)) => enc,
|
Some((enc, _)) => enc,
|
||||||
};
|
};
|
||||||
|
log::trace!("found byte-order mark (BOM) for encoding {enc:?}");
|
||||||
[encoding_rs::UTF_16LE, encoding_rs::UTF_16BE, encoding_rs::UTF_8]
|
[encoding_rs::UTF_16LE, encoding_rs::UTF_16BE, encoding_rs::UTF_8]
|
||||||
.contains(&enc)
|
.contains(&enc)
|
||||||
}
|
}
|
||||||
|
@ -725,8 +725,6 @@ impl TesterConfig {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use grep_matcher::{Match, Matcher};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn m(start: usize, end: usize) -> Match {
|
fn m(start: usize, end: usize) -> Match {
|
||||||
|
317
doc/rg.1.txt.tpl
317
doc/rg.1.txt.tpl
@ -1,317 +0,0 @@
|
|||||||
rg(1)
|
|
||||||
=====
|
|
||||||
|
|
||||||
Name
|
|
||||||
----
|
|
||||||
rg - recursively search the current directory for lines matching a pattern
|
|
||||||
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
*rg* [_OPTIONS_] _PATTERN_ [_PATH_...]
|
|
||||||
|
|
||||||
*rg* [_OPTIONS_] *-e* _PATTERN_... [_PATH_...]
|
|
||||||
|
|
||||||
*rg* [_OPTIONS_] *-f* _PATTERNFILE_... [_PATH_...]
|
|
||||||
|
|
||||||
*rg* [_OPTIONS_] *--files* [_PATH_...]
|
|
||||||
|
|
||||||
*rg* [_OPTIONS_] *--type-list*
|
|
||||||
|
|
||||||
*command* | *rg* [_OPTIONS_] _PATTERN_
|
|
||||||
|
|
||||||
*rg* [_OPTIONS_] *--help*
|
|
||||||
|
|
||||||
*rg* [_OPTIONS_] *--version*
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
-----------
|
|
||||||
ripgrep (rg) recursively searches the current directory for a regex pattern.
|
|
||||||
By default, ripgrep will respect your .gitignore and automatically skip hidden
|
|
||||||
files/directories and binary files.
|
|
||||||
|
|
||||||
ripgrep's default regex engine uses finite automata and guarantees linear
|
|
||||||
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*.
|
|
||||||
|
|
||||||
|
|
||||||
REGEX SYNTAX
|
|
||||||
------------
|
|
||||||
ripgrep uses Rust's regex engine by default, which documents its syntax:
|
|
||||||
https://docs.rs/regex/*/regex/#syntax
|
|
||||||
|
|
||||||
ripgrep uses byte-oriented regexes, which has some additional documentation:
|
|
||||||
https://docs.rs/regex/*/regex/bytes/index.html#syntax
|
|
||||||
|
|
||||||
To a first approximation, ripgrep uses Perl-like regexes without look-around or
|
|
||||||
backreferences. This makes them very similar to the "extended" (ERE) regular
|
|
||||||
expressions supported by *egrep*, but with a few additional features like
|
|
||||||
Unicode character classes.
|
|
||||||
|
|
||||||
If you're using ripgrep with the *--pcre2* flag, then please consult
|
|
||||||
https://www.pcre.org or the PCRE2 man pages for documentation on the supported
|
|
||||||
syntax.
|
|
||||||
|
|
||||||
|
|
||||||
POSITIONAL ARGUMENTS
|
|
||||||
--------------------
|
|
||||||
_PATTERN_::
|
|
||||||
A regular expression used for searching. To match a pattern beginning with a
|
|
||||||
dash, use the -e/--regexp option.
|
|
||||||
|
|
||||||
_PATH_::
|
|
||||||
A file or directory to search. Directories are searched recursively. File
|
|
||||||
paths specified explicitly on the command line override glob and ignore
|
|
||||||
rules.
|
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
|
||||||
-------
|
|
||||||
Note that many options can be disabled via flags. In some cases, those flags
|
|
||||||
are not listed in a first class way below. For example, the *--column*
|
|
||||||
flag (listed below) enables column numbers in ripgrep's output, but the
|
|
||||||
*--no-column* flag (not listed below) disables them. The reverse can also
|
|
||||||
exist. For example, the *--no-ignore* flag (listed below) disables ripgrep's
|
|
||||||
*gitignore* logic, but the *--ignore* flag (not listed below) enables it. These
|
|
||||||
flags are useful for overriding a ripgrep configuration file on the command
|
|
||||||
line. Each flag's documentation notes whether an inverted flag exists. In all
|
|
||||||
cases, the flag specified last takes precedence.
|
|
||||||
|
|
||||||
{OPTIONS}
|
|
||||||
|
|
||||||
|
|
||||||
EXIT STATUS
|
|
||||||
-----------
|
|
||||||
If ripgrep finds a match, then the exit status of the program is 0. If no match
|
|
||||||
could be found, then the exit status is 1. If an error occurred, then the exit
|
|
||||||
status is always 2 unless ripgrep was run with the *--quiet* flag and a match
|
|
||||||
was found. In summary:
|
|
||||||
|
|
||||||
* `0` exit status occurs only when at least one match was found, and if
|
|
||||||
no error occurred, unless *--quiet* was given.
|
|
||||||
* `1` exit status occurs only when no match was found and no error occurred.
|
|
||||||
* `2` exit status occurs when an error occurred. This is true for both
|
|
||||||
catastrophic errors (e.g., a regex syntax error) and for soft errors (e.g.,
|
|
||||||
unable to read a file).
|
|
||||||
|
|
||||||
|
|
||||||
AUTOMATIC FILTERING
|
|
||||||
-------------------
|
|
||||||
TL;DR - To disable automatic filtering, use 'rg -uuu'.
|
|
||||||
|
|
||||||
One of ripgrep's most important features is its automatic smart filtering.
|
|
||||||
It is the most apparent differentiating feature between ripgrep and other tools
|
|
||||||
like 'grep'. As such, its behavior may be surprising to users that aren't
|
|
||||||
expecting it.
|
|
||||||
|
|
||||||
ripgrep does four types of filtering automatically:
|
|
||||||
|
|
||||||
1. Files and directories that match ignore rules are not searched.
|
|
||||||
2. Hidden files and directories are not searched.
|
|
||||||
3. Binary files (files with a 'NUL' byte) are not searched.
|
|
||||||
4. Symbolic links are not followed.
|
|
||||||
|
|
||||||
The first type of filtering is the most sophisticated. ripgrep will attempt to
|
|
||||||
respect your gitignore rules as faithfully as possible. In particular, this
|
|
||||||
includes the following:
|
|
||||||
|
|
||||||
* Any global rules, e.g., in '$HOME/.config/git/ignore'.
|
|
||||||
* Any rules in '.gitignore'.
|
|
||||||
* Any local rules, e.g., in '.git/info/exclude'.
|
|
||||||
|
|
||||||
In some cases, ripgrep and git will not always be in sync in terms of which
|
|
||||||
files are ignored. For example, a file that is ignored via '.gitignore' but is
|
|
||||||
tracked by git would not be searched by ripgrep even though git tracks it. This
|
|
||||||
is unlikely to ever be fixed. Instead, you should either make sure your exclude
|
|
||||||
rules match the files you track precisely, or otherwise use 'git grep' for
|
|
||||||
search.
|
|
||||||
|
|
||||||
Additional ignore rules can be provided outside of a git context:
|
|
||||||
|
|
||||||
* Any rules in '.ignore'.
|
|
||||||
* Any rules in '.rgignore'.
|
|
||||||
* Any rules in files specified with the '--ignore-file' flag.
|
|
||||||
|
|
||||||
The precedence of ignore rules is as follows, with later items overriding
|
|
||||||
earlier items:
|
|
||||||
|
|
||||||
* Files given by '--ignore-file'.
|
|
||||||
* Global gitignore rules, e.g., from '$HOME/.config/git/ignore'.
|
|
||||||
* Local rules from '.git/info/exclude'.
|
|
||||||
* Rules from '.gitignore'.
|
|
||||||
* Rules from '.ignore'.
|
|
||||||
* Rules from '.rgignore'.
|
|
||||||
|
|
||||||
So for example, if 'foo' were in a '.gitignore' and '!foo' were in an
|
|
||||||
'.rgignore', then 'foo' would not be ignored since '.rgignore' takes precedence
|
|
||||||
over '.gitignore'.
|
|
||||||
|
|
||||||
Each of the types of filtering can be configured via command line flags:
|
|
||||||
|
|
||||||
* There are several flags starting with '--no-ignore' that toggle which,
|
|
||||||
if any, ignore rules are respected. '--no-ignore' by itself will disable
|
|
||||||
all of them.
|
|
||||||
* '-./--hidden' will force ripgrep to search hidden files and directories.
|
|
||||||
* '--binary' will force ripgrep to search binary files.
|
|
||||||
* '-L/--follow' will force ripgrep to follow symlinks.
|
|
||||||
|
|
||||||
As a special short hand, the `-u` flag can be specified up to three times. Each
|
|
||||||
additional time incrementally decreases filtering:
|
|
||||||
|
|
||||||
* '-u' is equivalent to '--no-ignore'.
|
|
||||||
* '-uu' is equivalent to '--no-ignore --hidden'.
|
|
||||||
* '-uuu' is equivalent to '--no-ignore --hidden --binary'.
|
|
||||||
|
|
||||||
In particular, 'rg -uuu' should search the same exact content as 'grep -r'.
|
|
||||||
|
|
||||||
|
|
||||||
CONFIGURATION FILES
|
|
||||||
-------------------
|
|
||||||
ripgrep supports reading configuration files that change ripgrep's default
|
|
||||||
behavior. The format of the configuration file is an "rc" style and is very
|
|
||||||
simple. It is defined by two rules:
|
|
||||||
|
|
||||||
1. Every line is a shell argument, after trimming whitespace.
|
|
||||||
2. Lines starting with *#* (optionally preceded by any amount of
|
|
||||||
whitespace) are ignored.
|
|
||||||
|
|
||||||
ripgrep will look for a single configuration file if and only if the
|
|
||||||
*RIPGREP_CONFIG_PATH* environment variable is set and is non-empty. ripgrep
|
|
||||||
will parse shell arguments from this file on startup and will behave as if
|
|
||||||
the arguments in this file were prepended to any explicit arguments given to
|
|
||||||
ripgrep on the command line. Note though that the 'rg' command you run must
|
|
||||||
still be valid. That is, it must always contain at least one pattern at the
|
|
||||||
command line, even if the configuration file uses the '-e/--regexp' flag.
|
|
||||||
|
|
||||||
For example, if your ripgreprc file contained a single line:
|
|
||||||
|
|
||||||
--smart-case
|
|
||||||
|
|
||||||
then the following command
|
|
||||||
|
|
||||||
RIPGREP_CONFIG_PATH=wherever/.ripgreprc rg foo
|
|
||||||
|
|
||||||
would behave identically to the following command
|
|
||||||
|
|
||||||
rg --smart-case foo
|
|
||||||
|
|
||||||
another example is adding types
|
|
||||||
|
|
||||||
--type-add
|
|
||||||
web:*.{html,css,js}*
|
|
||||||
|
|
||||||
would behave identically to the following command
|
|
||||||
|
|
||||||
rg --type-add 'web:*.{html,css,js}*' foo
|
|
||||||
|
|
||||||
same with using globs
|
|
||||||
|
|
||||||
--glob=!.git
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
--glob
|
|
||||||
!.git
|
|
||||||
|
|
||||||
would behave identically to the following command
|
|
||||||
|
|
||||||
rg --glob '!.git' foo
|
|
||||||
|
|
||||||
The bottom line is that every shell argument needs to be on its own line. So
|
|
||||||
for example, a config file containing
|
|
||||||
|
|
||||||
-j 4
|
|
||||||
|
|
||||||
is probably not doing what you intend. Instead, you want
|
|
||||||
|
|
||||||
-j
|
|
||||||
4
|
|
||||||
|
|
||||||
ripgrep also provides a flag, *--no-config*, that when present will suppress
|
|
||||||
any and all support for configuration. This includes any future support
|
|
||||||
for auto-loading configuration files from pre-determined paths.
|
|
||||||
|
|
||||||
Conflicts between configuration files and explicit arguments are handled
|
|
||||||
exactly like conflicts in the same command line invocation. That is,
|
|
||||||
this command:
|
|
||||||
|
|
||||||
RIPGREP_CONFIG_PATH=wherever/.ripgreprc rg foo --case-sensitive
|
|
||||||
|
|
||||||
is exactly equivalent to
|
|
||||||
|
|
||||||
rg --smart-case foo --case-sensitive
|
|
||||||
|
|
||||||
in which case, the *--case-sensitive* flag would override the *--smart-case*
|
|
||||||
flag.
|
|
||||||
|
|
||||||
|
|
||||||
SHELL COMPLETION
|
|
||||||
----------------
|
|
||||||
Shell completion files are included in the release tarball for Bash, Fish, Zsh
|
|
||||||
and PowerShell.
|
|
||||||
|
|
||||||
For *bash*, move *rg.bash* to *$XDG_CONFIG_HOME/bash_completion*
|
|
||||||
or */etc/bash_completion.d/*.
|
|
||||||
|
|
||||||
For *fish*, move *rg.fish* to *$HOME/.config/fish/completions*.
|
|
||||||
|
|
||||||
For *zsh*, move *_rg* to one of your *$fpath* directories.
|
|
||||||
|
|
||||||
|
|
||||||
CAVEATS
|
|
||||||
-------
|
|
||||||
ripgrep may abort unexpectedly when using default settings if it searches a
|
|
||||||
file that is simultaneously truncated. This behavior can be avoided by passing
|
|
||||||
the *--no-mmap* flag which will forcefully disable the use of memory maps in
|
|
||||||
all cases.
|
|
||||||
|
|
||||||
ripgrep may use a large amount of memory depending on a few factors. Firstly,
|
|
||||||
if ripgrep uses parallelism for search (the default), then the entire output
|
|
||||||
for each individual file is buffered into memory in order to prevent
|
|
||||||
interleaving matches in the output. To avoid this, you can disable parallelism
|
|
||||||
with the *-j1* flag. Secondly, ripgrep always needs to have at least a single
|
|
||||||
line in memory in order to execute a search. A file with a very long line can
|
|
||||||
thus cause ripgrep to use a lot of memory. Generally, this only occurs when
|
|
||||||
searching binary data with the *-a* flag enabled. (When the *-a* flag isn't
|
|
||||||
enabled, ripgrep will replace all NUL bytes with line terminators, which
|
|
||||||
typically prevents exorbitant memory usage.) Thirdly, when ripgrep searches
|
|
||||||
a large file using a memory map, the process will report its resident memory
|
|
||||||
usage as the size of the file. However, this does not mean ripgrep actually
|
|
||||||
needed to use that much memory; the operating system will generally handle this
|
|
||||||
for you.
|
|
||||||
|
|
||||||
|
|
||||||
VERSION
|
|
||||||
-------
|
|
||||||
{VERSION}
|
|
||||||
|
|
||||||
|
|
||||||
HOMEPAGE
|
|
||||||
--------
|
|
||||||
https://github.com/BurntSushi/ripgrep
|
|
||||||
|
|
||||||
Please report bugs and feature requests in the issue tracker. Please do your
|
|
||||||
best to provide a reproducible test case for bugs. This should include the
|
|
||||||
corpus being searched, the *rg* command, the actual output and the expected
|
|
||||||
output. Please also include the output of running the same *rg* command but
|
|
||||||
with the *--debug* flag.
|
|
||||||
|
|
||||||
|
|
||||||
AUTHORS
|
|
||||||
-------
|
|
||||||
Andrew Gallant <jamslam@gmail.com>
|
|
@ -1,14 +1,14 @@
|
|||||||
class RipgrepBin < Formula
|
class RipgrepBin < Formula
|
||||||
version '14.0.2'
|
version '14.1.1'
|
||||||
desc "Recursively search directories for a regex pattern."
|
desc "Recursively search directories for a regex pattern."
|
||||||
homepage "https://github.com/BurntSushi/ripgrep"
|
homepage "https://github.com/BurntSushi/ripgrep"
|
||||||
|
|
||||||
if OS.mac?
|
if OS.mac?
|
||||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
|
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
|
||||||
sha256 "dd06bebd3a9d75981f8e3271b6c69286990f3fc1a374f0e5b0fc2866ec69bc4c"
|
sha256 "fc87e78f7cb3fea12d69072e7ef3b21509754717b746368fd40d88963630e2b3"
|
||||||
elsif OS.linux?
|
elsif OS.linux?
|
||||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-unknown-linux-musl.tar.gz"
|
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-unknown-linux-musl.tar.gz"
|
||||||
sha256 "62cd0efc4d6f1817b9c852859987b4720cd52e0de008418266e8503028dc0c7a"
|
sha256 "4cf9f2741e6c465ffdb7c26f38056a59e2a2544b51f7cc128ef28337eeae4d8e"
|
||||||
end
|
end
|
||||||
|
|
||||||
conflicts_with "ripgrep"
|
conflicts_with "ripgrep"
|
||||||
|
@ -284,16 +284,7 @@ impl TestCommand {
|
|||||||
/// Runs and captures the stdout of the given command.
|
/// Runs and captures the stdout of the given command.
|
||||||
pub fn stdout(&mut self) -> String {
|
pub fn stdout(&mut self) -> String {
|
||||||
let o = self.output();
|
let o = self.output();
|
||||||
let stdout = String::from_utf8_lossy(&o.stdout);
|
String::from_utf8_lossy(&o.stdout).into_owned()
|
||||||
match stdout.parse() {
|
|
||||||
Ok(t) => t,
|
|
||||||
Err(err) => {
|
|
||||||
panic!(
|
|
||||||
"could not convert from string: {:?}\n\n{}",
|
|
||||||
err, stdout
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pipe `input` to a command, and collect the output.
|
/// Pipe `input` to a command, and collect the output.
|
||||||
@ -313,16 +304,7 @@ impl TestCommand {
|
|||||||
let output = self.expect_success(child.wait_with_output().unwrap());
|
let output = self.expect_success(child.wait_with_output().unwrap());
|
||||||
worker.join().unwrap().unwrap();
|
worker.join().unwrap().unwrap();
|
||||||
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
String::from_utf8_lossy(&output.stdout).into_owned()
|
||||||
match stdout.parse() {
|
|
||||||
Ok(t) => t,
|
|
||||||
Err(err) => {
|
|
||||||
panic!(
|
|
||||||
"could not convert from string: {:?}\n\n{}",
|
|
||||||
err, stdout
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the output of a command. If the command failed, then this panics.
|
/// Gets the output of a command. If the command failed, then this panics.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user