mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-07-29 03:01:57 -07:00
Compare commits
61 Commits
wincolor-0
...
ignore-0.4
Author | SHA1 | Date | |
---|---|---|---|
|
2b5c488814 | ||
|
cb47be938e | ||
|
fe9be658f4 | ||
|
8c800adab7 | ||
|
d65966efbc | ||
|
597bf04a56 | ||
|
c78ab9e669 | ||
|
d57fc58081 | ||
|
d09538c974 | ||
|
94768881e1 | ||
|
f3a9ced82c | ||
|
18f549d289 | ||
|
c749b604dc | ||
|
d6748a3445 | ||
|
9b7f420faa | ||
|
361698b90a | ||
|
b71a110ccf | ||
|
5c1af3c25d | ||
|
ad3f55b0e5 | ||
|
b8e6d50bbe | ||
|
81afe8c5a0 | ||
|
c4e0d4bd7b | ||
|
23d1b91ead | ||
|
ac83ed4992 | ||
|
555fbd1201 | ||
|
f3146f8316 | ||
|
56341973ee | ||
|
a431160d4c | ||
|
5d15f49f0c | ||
|
7718ee362e | ||
|
739f8f596b | ||
|
e818d7529b | ||
|
a2a7f58aa6 | ||
|
c4a5bc06c5 | ||
|
96ee4482cd | ||
|
3effea0b7c | ||
|
2d68054b1d | ||
|
65a63788bc | ||
|
7e5589f07d | ||
|
09c5b2c4ea | ||
|
904c75bd30 | ||
|
ca3e0e8a49 | ||
|
ae2d036dd4 | ||
|
8e93fa0e7f | ||
|
7f5c07434b | ||
|
874f0b96a6 | ||
|
706323ad8f | ||
|
8460d7fe3d | ||
|
e1f1ede17d | ||
|
6553940328 | ||
|
b50ae9a99c | ||
|
224c112e05 | ||
|
8cb5833ef9 | ||
|
85cd3f0a6e | ||
|
c57d0fb4e8 | ||
|
d83bab4d3f | ||
|
ce84e1ef04 | ||
|
c8e755f11f | ||
|
68dac7c4b0 | ||
|
3535047094 | ||
|
fe00255494 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,6 +6,7 @@ target
|
||||
/ignore/Cargo.lock
|
||||
/termcolor/Cargo.lock
|
||||
/wincolor/Cargo.lock
|
||||
/deployment
|
||||
|
||||
# Snapcraft files
|
||||
stage
|
||||
@@ -13,4 +14,4 @@ prime
|
||||
parts
|
||||
*.snap
|
||||
*.pyc
|
||||
ripgrep*_source.tar.bz2
|
||||
ripgrep*_source.tar.bz2
|
||||
|
74
.travis.yml
74
.travis.yml
@@ -1,25 +1,27 @@
|
||||
language: rust
|
||||
cache: cargo
|
||||
|
||||
env:
|
||||
global:
|
||||
- PROJECT_NAME=ripgrep
|
||||
- PROJECT_NAME: ripgrep
|
||||
- RUST_BACKTRACE: full
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# For generating man page.
|
||||
- libxslt1-dev
|
||||
- asciidoc
|
||||
- docbook-xsl
|
||||
- xsltproc
|
||||
- libxml2-utils
|
||||
# Needed for completion-function test.
|
||||
- zsh
|
||||
# Needed for testing decompression search.
|
||||
- xz-utils
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
# Nightly channel.
|
||||
# (All *nix releases are done on the nightly channel to take advantage
|
||||
# of the regex library's multiple pattern SIMD search.)
|
||||
# All *nix releases are done on the nightly channel to take advantage
|
||||
# of the regex library's multiple pattern SIMD search.
|
||||
- os: linux
|
||||
rust: nightly
|
||||
env: TARGET=i686-unknown-linux-musl
|
||||
@@ -39,14 +41,22 @@ matrix:
|
||||
- binutils-arm-linux-gnueabihf
|
||||
- libc6-armhf-cross
|
||||
- libc6-dev-armhf-cross
|
||||
# Beta channel.
|
||||
# For generating man page.
|
||||
- libxslt1-dev
|
||||
- asciidoc
|
||||
- docbook-xsl
|
||||
- xsltproc
|
||||
- libxml2-utils
|
||||
# Beta channel. We enable these to make sure there are no regressions in
|
||||
# Rust beta releases.
|
||||
- os: linux
|
||||
rust: beta
|
||||
env: TARGET=x86_64-unknown-linux-musl
|
||||
- os: linux
|
||||
rust: beta
|
||||
env: TARGET=x86_64-unknown-linux-gnu
|
||||
# Minimum Rust supported channel.
|
||||
# Minimum Rust supported channel. We enable these to make sure ripgrep
|
||||
# continues to work on the advertised minimum Rust version.
|
||||
- os: linux
|
||||
rust: 1.20.0
|
||||
env: TARGET=x86_64-unknown-linux-gnu
|
||||
@@ -63,43 +73,33 @@ matrix:
|
||||
- binutils-arm-linux-gnueabihf
|
||||
- libc6-armhf-cross
|
||||
- libc6-dev-armhf-cross
|
||||
|
||||
before_install:
|
||||
- export PATH="$PATH:$HOME/.cargo/bin"
|
||||
|
||||
install:
|
||||
- bash ci/install.sh
|
||||
|
||||
script:
|
||||
- bash ci/script.sh
|
||||
|
||||
before_deploy:
|
||||
- bash ci/before_deploy.sh
|
||||
|
||||
# For generating man page.
|
||||
- libxslt1-dev
|
||||
- asciidoc
|
||||
- docbook-xsl
|
||||
- xsltproc
|
||||
- libxml2-utils
|
||||
install: ci/install.sh
|
||||
script: ci/script.sh
|
||||
before_deploy: ci/before_deploy.sh
|
||||
deploy:
|
||||
provider: releases
|
||||
file_glob: true
|
||||
file: deployment/${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}.tar.gz
|
||||
skip_cleanup: true
|
||||
on:
|
||||
condition: $TRAVIS_RUST_VERSION = nightly
|
||||
branch: master
|
||||
tags: true
|
||||
api_key:
|
||||
secure: "IbSnsbGkxSydR/sozOf1/SRvHplzwRUHzcTjM7BKnr7GccL86gRPUrsrvD103KjQUGWIc1TnK1YTq5M0Onswg/ORDjqa1JEJPkPdPnVh9ipbF7M2De/7IlB4X4qXLKoApn8+bx2x/mfYXu4G+G1/2QdbaKK2yfXZKyjz0YFx+6CNrVCT2Nk8q7aHvOOzAL58vsG8iPDpupuhxlMDDn/UhyOWVInmPPQ0iJR1ZUJN8xJwXvKvBbfp3AhaBiAzkhXHNLgBR8QC5noWWMXnuVDMY3k4f3ic0V+p/qGUCN/nhptuceLxKFicMCYObSZeUzE5RAI0/OBW7l3z2iCoc+TbAnn+JrX/ObJCfzgAOXAU3tLaBFMiqQPGFKjKg1ltSYXomOFP/F7zALjpvFp4lYTBajRR+O3dqaxA9UQuRjw27vOeUpMcga4ZzL4VXFHzrxZKBHN//XIGjYAVhJ1NSSeGpeJV5/+jYzzWKfwSagRxQyVCzMooYFFXzn8Yxdm3PJlmp3GaAogNkdB9qKcrEvRINCelalzALPi0hD/HUDi8DD2PNTCLLMo6VSYtvc685Zbe+KgNzDV1YyTrRCUW6JotrS0r2ULLwnsh40hSB//nNv3XmwNmC/CmW5QAnIGj8cBMF4S2t6ohADIndojdAfNiptmaZOIT6owK7bWMgPMyopo="
|
||||
file_glob: true
|
||||
file: ${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}.*
|
||||
# don't delete the artifacts from previous phases
|
||||
skip_cleanup: true
|
||||
# deploy when a new tag is pushed
|
||||
on:
|
||||
# channel to use to produce the release artifacts
|
||||
# NOTE make sure you only release *once* per target
|
||||
# TODO you may want to pick a different channel
|
||||
condition: $TRAVIS_RUST_VERSION = nightly
|
||||
tags: true
|
||||
|
||||
branches:
|
||||
only:
|
||||
# Pushes and PR to the master branch
|
||||
- master
|
||||
# IMPORTANT Ruby regex to match tags. Required, or travis won't trigger deploys when a new tag
|
||||
# is pushed. This regex matches semantic versions like v1.2.3-rc4+2016.02.22
|
||||
# Ruby regex to match tags. Required, or travis won't trigger deploys when
|
||||
# a new tag is pushed.
|
||||
- /^\d+\.\d+\.\d+.*$/
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: never
|
||||
|
132
CHANGELOG.md
132
CHANGELOG.md
@@ -1,3 +1,135 @@
|
||||
0.8.0 (2018-02-11)
|
||||
==================
|
||||
This is a new minor version releae of ripgrep that satisfies several popular
|
||||
feature requests (config files, search compressed files, true colors), fixes
|
||||
many bugs and improves the quality of life for ripgrep maintainers. This
|
||||
release also includes greatly improved documentation in the form of a
|
||||
[User Guide](GUIDE.md) and a [FAQ](FAQ.md).
|
||||
|
||||
This release increases the **minimum supported Rust version** from 1.17 to
|
||||
1.20.
|
||||
|
||||
**BREAKING CHANGES**:
|
||||
|
||||
Note that these are all very minor and unlikely to impact most users.
|
||||
|
||||
* In order to support configuration files, flag overrides needed to be
|
||||
rethought. In some cases, this changed ripgrep's behavior. For example,
|
||||
in ripgrep 0.7.1, `rg foo -s -i` will perform a case sensitive search
|
||||
since the `-s/--case-sensitive` flag was defined to always take precedence
|
||||
over the `-i/--ignore-case` flag, regardless of position. In ripgrep 0.8.0
|
||||
however, the override rule for all flags has changed to "the most recent
|
||||
flag wins among competing flags." That is, `rg foo -s -i` now performs a
|
||||
case insensitive search.
|
||||
* The `-M/--max-columns` flag was tweaked so that specifying a value of `0`
|
||||
now makes ripgrep behave as if the flag was absent. This makes it possible
|
||||
to set a default value in a configuration file and then override it. The
|
||||
previous ripgrep behavior was to suppress all matching non-empty lines.
|
||||
* In all globs, `[^...]` is now equivalent to `[!...]` (indicating class
|
||||
negation). Previously, `^` had no special significance in a character class.
|
||||
* For **downstream packagers**, the directory hierarchy in ripgrep's archive
|
||||
releases has changed. The root directory now only contains the executable,
|
||||
README and license. There is now a new directory called `doc` which contains
|
||||
the man page (previously in the root), a user guide (new), a FAQ (new) and
|
||||
the CHANGELOG (previously not included in release). The `complete`
|
||||
directory remains the same.
|
||||
|
||||
Feature enhancements:
|
||||
|
||||
* Added or improved file type filtering for
|
||||
Apache Avro, C++, GN, Google Closure Templates, Jupyter notebooks, man pages,
|
||||
Protocol Buffers, Smarty and Web IDL.
|
||||
* [FEATURE #196](https://github.com/BurntSushi/ripgrep/issues/196):
|
||||
Support a configuration file. See
|
||||
[the new user guide](GUIDE.md#configuration-file)
|
||||
for details.
|
||||
* [FEATURE #261](https://github.com/BurntSushi/ripgrep/issues/261):
|
||||
Add extended or "true" color support. Works in Windows 10!
|
||||
[See the FAQ for details.](FAQ.md#colors)
|
||||
* [FEATURE #539](https://github.com/BurntSushi/ripgrep/issues/539):
|
||||
Search gzip, bzip2, lzma or xz files when given `-z/--search-zip` flag.
|
||||
* [FEATURE #544](https://github.com/BurntSushi/ripgrep/issues/544):
|
||||
Add support for line number alignment via a new `--line-number-width` flag.
|
||||
* [FEATURE #654](https://github.com/BurntSushi/ripgrep/pull/654):
|
||||
Support linuxbrew in ripgrep's Brew tap.
|
||||
* [FEATURE #673](https://github.com/BurntSushi/ripgrep/issues/673):
|
||||
Bring back `.rgignore` files. (A higher precedent, application specific
|
||||
version of `.ignore`.)
|
||||
* [FEATURE #676](https://github.com/BurntSushi/ripgrep/issues/676):
|
||||
Provide ARM binaries. **WARNING:** This will be provided on a best effort
|
||||
basis.
|
||||
* [FEATURE #709](https://github.com/BurntSushi/ripgrep/issues/709):
|
||||
Suggest `-F/--fixed-strings` flag on a regex syntax error.
|
||||
* [FEATURE #740](https://github.com/BurntSushi/ripgrep/issues/740):
|
||||
Add a `--passthru` flag that causes ripgrep to print every line it reads.
|
||||
* [FEATURE #785](https://github.com/BurntSushi/ripgrep/pull/785):
|
||||
Overhaul documentation. Cleaned up README, added user guide and FAQ.
|
||||
* [FEATURE 7f5c07](https://github.com/BurntSushi/ripgrep/commit/7f5c07434be92103b5bf7e216b9c7494aed2d8cb):
|
||||
Add hidden flags for convenient overrides (e.g., `--no-text`).
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* [BUG #553](https://github.com/BurntSushi/ripgrep/issues/553):
|
||||
Permit flags to be repeated.
|
||||
* [BUG #633](https://github.com/BurntSushi/ripgrep/issues/633):
|
||||
Fix a bug where ripgrep would panic on Windows while following symlinks.
|
||||
* [BUG #649](https://github.com/BurntSushi/ripgrep/issues/649):
|
||||
Fix handling of `!**/` in `.gitignore`.
|
||||
* [BUG #663](https://github.com/BurntSushi/ripgrep/issues/663):
|
||||
**BREAKING CHANGE:** Support `[^...]` glob syntax (as identical to `[!...]`).
|
||||
* [BUG #693](https://github.com/BurntSushi/ripgrep/issues/693):
|
||||
Don't display context separators when not printing matches.
|
||||
* [BUG #705](https://github.com/BurntSushi/ripgrep/issues/705):
|
||||
Fix a bug that prevented ripgrep from searching OneDrive directories.
|
||||
* [BUG #717](https://github.com/BurntSushi/ripgrep/issues/717):
|
||||
Improve `--smart-case` uppercase character detection.
|
||||
* [BUG #725](https://github.com/BurntSushi/ripgrep/issues/725):
|
||||
Clarify that globs do not override explicitly given paths to search.
|
||||
* [BUG #742](https://github.com/BurntSushi/ripgrep/pull/742):
|
||||
Write ANSI reset code as `\x1B[0m` instead of `\x1B[m`.
|
||||
* [BUG #747](https://github.com/BurntSushi/ripgrep/issues/747):
|
||||
Remove `yarn.lock` from YAML file type.
|
||||
* [BUG #760](https://github.com/BurntSushi/ripgrep/issues/760):
|
||||
ripgrep can now search `/sys/devices/system/cpu/vulnerabilities/*` files.
|
||||
* [BUG #761](https://github.com/BurntSushi/ripgrep/issues/761):
|
||||
Fix handling of gitignore patterns that contain a `/`.
|
||||
* [BUG #776](https://github.com/BurntSushi/ripgrep/pull/776):
|
||||
**BREAKING CHANGE:** `--max-columns=0` now disables the limit.
|
||||
* [BUG #779](https://github.com/BurntSushi/ripgrep/issues/779):
|
||||
Clarify documentation for `--files-without-match`.
|
||||
* [BUG #780](https://github.com/BurntSushi/ripgrep/issues/780),
|
||||
[BUG #781](https://github.com/BurntSushi/ripgrep/issues/781):
|
||||
Fix bug where ripgrep missed some matching lines.
|
||||
|
||||
Maintenance fixes:
|
||||
|
||||
* [MAINT #772](https://github.com/BurntSushi/ripgrep/pull/772):
|
||||
Drop `env_logger` in favor of simpler logger to avoid many new dependencies.
|
||||
* [MAINT #772](https://github.com/BurntSushi/ripgrep/pull/772):
|
||||
Add git revision hash to ripgrep's version string.
|
||||
* [MAINT #772](https://github.com/BurntSushi/ripgrep/pull/772):
|
||||
(Seemingly) improve compile times.
|
||||
* [MAINT #776](https://github.com/BurntSushi/ripgrep/pull/776):
|
||||
Automatically generate man page during build.
|
||||
* [MAINT #786](https://github.com/BurntSushi/ripgrep/pull/786):
|
||||
Remove use of `unsafe` in `globset`. :tada:
|
||||
* [MAINT e9d448](https://github.com/BurntSushi/ripgrep/commit/e9d448e93bb4e1fb3b0c1afc29adb5af6ed5283d):
|
||||
Add an issue template (has already drastically improved bug reports).
|
||||
* [MAINT ae2d03](https://github.com/BurntSushi/ripgrep/commit/ae2d036dd4ba2a46acac9c2d77c32e7c667eb850):
|
||||
Remove the `compile` script.
|
||||
|
||||
Friends of ripgrep:
|
||||
|
||||
I'd like to extend my gratitude to
|
||||
[@balajisivaraman](https://github.com/balajisivaraman)
|
||||
for their recent hard work in a number of areas, and in particular, for
|
||||
implementing the "search compressed files" feature. Their work in sketching out
|
||||
a specification for that and other work has been exemplary.
|
||||
|
||||
Thanks
|
||||
[@balajisivaraman](https://github.com/balajisivaraman)!
|
||||
|
||||
|
||||
0.7.1 (2017-10-22)
|
||||
==================
|
||||
This is a patch release of ripgrep that includes a fix to very bad regression
|
||||
|
194
Cargo.lock
generated
194
Cargo.lock
generated
@@ -16,9 +16,9 @@ name = "atty"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -41,16 +41,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.29.0"
|
||||
version = "2.29.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -60,21 +59,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"simd 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.6"
|
||||
@@ -82,16 +73,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon-sys"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -101,41 +92,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.2.1"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grep"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
dependencies = [
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.3.1"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"globset 0.2.1",
|
||||
"globset 0.3.0",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -145,20 +136,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.34"
|
||||
version = "0.2.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -169,7 +152,7 @@ name = "memchr"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -177,8 +160,8 @@ name = "memmap"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -186,21 +169,32 @@ name = "num_cpus"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.3.19"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.33"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -208,12 +202,12 @@ name = "redox_termios"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"redox_syscall 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.2.4"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -231,34 +225,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ripgrep"
|
||||
version = "0.7.1"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytecount 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"globset 0.2.1",
|
||||
"grep 0.1.7",
|
||||
"ignore 0.3.1",
|
||||
"clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"globset 0.3.0",
|
||||
"grep 0.1.8",
|
||||
"ignore 0.4.1",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.3",
|
||||
"winapi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.4",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -268,7 +261,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -276,14 +269,14 @@ name = "tempdir"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "0.3.3"
|
||||
version = "0.3.4"
|
||||
dependencies = [
|
||||
"wincolor 0.1.4",
|
||||
"wincolor 0.1.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -291,8 +284,8 @@ name = "termion"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -331,11 +324,6 @@ name = "utf8-ranges"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
@@ -343,37 +331,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.1.3"
|
||||
version = "2.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"same-file 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.2"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.3.2"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.3.2"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wincolor"
|
||||
version = "0.1.4"
|
||||
version = "0.1.6"
|
||||
dependencies = [
|
||||
"winapi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
@@ -383,29 +371,28 @@ dependencies = [
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum bytecount 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "882585cd7ec84e902472df34a5e01891202db3bf62614e1f0afe459c1afcf744"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
|
||||
"checksum clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b8f59bcebcfe4269b09f71dab0da15b355c75916a8f975d3876ce81561893ee"
|
||||
"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
|
||||
"checksum encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5215aabf22b83153be3ee44dfe3f940214541b2ce13d419c55e7a115c8c51a9"
|
||||
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
|
||||
"checksum encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98fd0f24d1fb71a4a6b9330c8ca04cbd4e7cc5d846b54ca74ff376bc7c9f798d"
|
||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||
"checksum fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd510087c325af53ba24f3be8f1c081b0982319adcb8b03cad764512923ccc19"
|
||||
"checksum fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "08b3a6f13ad6b96572b53ce7af74543132f1a7055ccceb6d073dd36c54481859"
|
||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
||||
"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
|
||||
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
|
||||
"checksum log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a89a0c46ba789b8a247d4c567aed4d7c68e624672d238b45cc3ec20dc9f940"
|
||||
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121"
|
||||
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
|
||||
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
||||
"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
|
||||
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
|
||||
"checksum rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7944d95d25ace8f377da3ac7068ce517e4c646754c43a1b1849177bbf72e59"
|
||||
"checksum redox_syscall 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "07b8f011e3254d5a9b318fde596d409a0001c9ae4c6e7907520c2eaa4d988c99"
|
||||
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
|
||||
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
|
||||
"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum regex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "42af8b40717e6a4dae0c00e09d65733e3c68aecfa865c3cc75ea1ed0e66d5149"
|
||||
"checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b"
|
||||
"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
|
||||
"checksum same-file 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3257af0472da4b8b8902102a57bafffd9991f0f43772a8af6153d597e6e4ae2"
|
||||
"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
|
||||
"checksum simd 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd0805c7363ab51a829a1511ad24b6ed0349feaa756c4bc2f977f9f496e6673"
|
||||
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
|
||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
|
||||
@@ -413,9 +400,8 @@ dependencies = [
|
||||
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
|
||||
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum walkdir 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b167e9a4420d8dddb260e70c90a4a375a1e5691f21f70e715553da87b6c2503a"
|
||||
"checksum winapi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "890b38836c01d72fdb636d15c9cfc52ec7fd783b330abc93cd1686f4308dfccc"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec6667f60c23eca65c561e63a13d81b44234c2e38a6b6c959025ee907ec614cc"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98f12c52b2630cd05d2c3ffd8e008f7f48252c042b4871c72aed9dc733b96668"
|
||||
"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
|
||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
27
Cargo.toml
27
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ripgrep"
|
||||
version = "0.7.1" #:version
|
||||
version = "0.8.0" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
Line oriented search tool using Rust's regex library. Combines the raw
|
||||
@@ -30,35 +30,42 @@ name = "integration"
|
||||
path = "tests/tests.rs"
|
||||
|
||||
[workspace]
|
||||
members = [ "grep", "globset", "ignore", "termcolor", "wincolor" ]
|
||||
members = ["grep", "globset", "ignore", "termcolor", "wincolor"]
|
||||
|
||||
[dependencies]
|
||||
atty = "0.2.2"
|
||||
bytecount = "0.3.1"
|
||||
clap = "2.26"
|
||||
encoding_rs = "0.7"
|
||||
env_logger = { version = "0.4", default-features = false }
|
||||
grep = { version = "0.1.7", path = "grep" }
|
||||
ignore = { version = "0.3.1", path = "ignore" }
|
||||
globset = { version = "0.3.0", path = "globset" }
|
||||
grep = { version = "0.1.8", path = "grep" }
|
||||
ignore = { version = "0.4.0", path = "ignore" }
|
||||
lazy_static = "1"
|
||||
libc = "0.2"
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
memchr = "2"
|
||||
memmap = "0.6"
|
||||
num_cpus = "1"
|
||||
regex = "0.2.4"
|
||||
same-file = "1"
|
||||
termcolor = { version = "0.3.3", path = "termcolor" }
|
||||
globset = { version = "0.2.1", path = "globset" }
|
||||
termcolor = { version = "0.3.4", path = "termcolor" }
|
||||
|
||||
[dependencies.clap]
|
||||
version = "2.29.4"
|
||||
default-features = false
|
||||
features = ["suggestions", "color"]
|
||||
|
||||
[target.'cfg(windows)'.dependencies.winapi]
|
||||
version = "0.3"
|
||||
features = ["std", "winnt"]
|
||||
|
||||
[build-dependencies]
|
||||
clap = "2.26"
|
||||
lazy_static = "1"
|
||||
|
||||
[build-dependencies.clap]
|
||||
version = "2.29.4"
|
||||
default-features = false
|
||||
features = ["suggestions", "color"]
|
||||
|
||||
[features]
|
||||
avx-accel = ["bytecount/avx-accel"]
|
||||
simd-accel = [
|
||||
|
532
FAQ.md
Normal file
532
FAQ.md
Normal file
@@ -0,0 +1,532 @@
|
||||
## FAQ
|
||||
|
||||
* [Does ripgrep support configuration files?](#config)
|
||||
* [What's changed in ripgrep recently?](#changelog)
|
||||
* [When is the next release?](#release)
|
||||
* [Does ripgrep have a man page?](#manpage)
|
||||
* [Does ripgrep have support for shell auto-completion?](#complete)
|
||||
* [How do I use lookaround and/or backreferences?](#fancy)
|
||||
* [How do I configure ripgrep's colors?](#colors)
|
||||
* [How do I enable true colors on Windows?](#truecolors-windows)
|
||||
* [How do I stop ripgrep from messing up colors when I kill it?](#stop-ripgrep)
|
||||
* [How can I get results in a consistent order?](#order)
|
||||
* [How do I search files that aren't UTF-8?](#encoding)
|
||||
* [How do I search compressed files?](#compressed)
|
||||
* [How do I search over multiple lines?](#multiline)
|
||||
* [How do I get around the regex size limit?](#size-limit)
|
||||
* [How do I make the `-f/--file` flag faster?](#dfa-size)
|
||||
* [How do I make the output look like The Silver Searcher's output?](#silver-searcher-output)
|
||||
* [When I run `rg`, why does it execute some other command?](#rg-other-cmd)
|
||||
* [How do I create an alias for ripgrep on Windows?](#rg-alias-windows)
|
||||
* [How do I create a PowerShell profile?](#powershell-profile)
|
||||
* [How do I pipe non-ASCII content to ripgrep on Windows?](#pipe-non-ascii-windows)
|
||||
* [Can ripgrep replace grep?](#posix4ever)
|
||||
|
||||
|
||||
<h3 name="config">
|
||||
Does ripgrep support configuration files?
|
||||
</h3>
|
||||
|
||||
Yes. See the
|
||||
[guide's section on configuration files](GUIDE.md#configuration-file).
|
||||
|
||||
|
||||
<h3 name="changelog">
|
||||
What's changed in ripgrep recently?
|
||||
</h3>
|
||||
|
||||
Please consult ripgrep's [CHANGELOG](CHANGELOG.md).
|
||||
|
||||
|
||||
<h3 name="release">
|
||||
When is the next release?
|
||||
</h3>
|
||||
|
||||
ripgrep is a project whose contributors are volunteers. A release schedule
|
||||
adds undue stress to said volunteers. Therefore, releases are made on a best
|
||||
effort basis and no dates **will ever be given**.
|
||||
|
||||
One exception to this is high impact bugs. If a ripgrep release contains a
|
||||
significant regression, then there will generally be a strong push to get a
|
||||
patch release out with a fix.
|
||||
|
||||
|
||||
<h3 name="manpage">
|
||||
Does ripgrep have a man page?
|
||||
</h3>
|
||||
|
||||
Yes! Whenever ripgrep is compiled on a system with `asciidoc` present, then a
|
||||
man page is generated from ripgrep's argv parser. After compiling ripgrep, you
|
||||
can find the man page like so from the root of the repository:
|
||||
|
||||
```
|
||||
$ find ./target -name rg.1 -print0 | xargs -0 ls -t | head -n1
|
||||
./target/debug/build/ripgrep-79899d0edd4129ca/out/rg.1
|
||||
```
|
||||
|
||||
Running `man -l ./target/debug/build/ripgrep-79899d0edd4129ca/out/rg.1` will
|
||||
show the man page in your normal pager.
|
||||
|
||||
Note that the man page's documentation for options is equivalent to the output
|
||||
shown in `rg --help`. To see more condensed documentation (one line per flag),
|
||||
run `rg -h`.
|
||||
|
||||
The man page is also included in all
|
||||
[ripgrep binary releases](https://github.com/BurntSushi/ripgrep/releases).
|
||||
|
||||
|
||||
<h3 name="complete">
|
||||
Does ripgrep have support for shell auto-completion?
|
||||
</h3>
|
||||
|
||||
Yes! Shell completions can be found in the
|
||||
[same directory as the man page](#manpage)
|
||||
after building ripgrep. Zsh completions are maintained separately and committed
|
||||
to the repository in `complete/_rg`.
|
||||
|
||||
Shell completions are also included in all
|
||||
[ripgrep binary releases](https://github.com/BurntSushi/ripgrep/releases).
|
||||
|
||||
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.
|
||||
|
||||
For **PowerShell**, add `. _rg.ps1` to your PowerShell
|
||||
[profile](https://technet.microsoft.com/en-us/library/bb613488(v=vs.85).aspx)
|
||||
(note the leading period). If the `_rg.ps1` file is not on your `PATH`, do
|
||||
`. /path/to/_rg.ps1` instead.
|
||||
|
||||
|
||||
<h3 name="order">
|
||||
How can I get results in a consistent order?
|
||||
</h3>
|
||||
|
||||
By default, ripgrep uses parallelism to execute its search because this makes
|
||||
the search much faster on most modern systems. This in turn means that ripgrep
|
||||
has a non-deterministic aspect to it, since the interleaving of threads during
|
||||
the execution of the program is itself non-deterministic. This has the effect
|
||||
of printing results in a somewhat arbitrary order, and this order can change
|
||||
from run to run of ripgrep.
|
||||
|
||||
The only way to make the order of results consistent is to ask ripgrep to
|
||||
sort the output. Currently, this will disable all parallelism. (On smaller
|
||||
repositories, you might not notice much of a performance difference!) You
|
||||
can achieve this with the `--sort-files` flag.
|
||||
|
||||
There is more discussion on this topic here:
|
||||
https://github.com/BurntSushi/ripgrep/issues/152
|
||||
|
||||
|
||||
<h3 name="encoding">
|
||||
How do I search files that aren't UTF-8?
|
||||
</h3>
|
||||
|
||||
See the [guide's section on file encoding](GUIDE.md#file-encoding).
|
||||
|
||||
|
||||
<h3 name="compressed">
|
||||
How do I search compressed files?
|
||||
</h3>
|
||||
|
||||
ripgrep's `-z/--search-zip` flag will cause it to search compressed files
|
||||
automatically. Currently, this supports gzip, bzip2, lzma and xz only and
|
||||
requires the corresponding `gzip`, `bzip2` and `xz` binaries to be installed on
|
||||
your system. (That is, ripgrep does decompression by shelling out to another
|
||||
process.)
|
||||
|
||||
ripgrep currently does not search archive formats, so `*.tar.gz` files, for
|
||||
example, are skipped.
|
||||
|
||||
|
||||
<h3 name="multiline">
|
||||
How do I search over multiple lines?
|
||||
</h3>
|
||||
|
||||
This isn't currently possible. ripgrep is fundamentally a line-oriented search
|
||||
tool. With that said,
|
||||
[multiline search is a planned opt-in feature](https://github.com/BurntSushi/ripgrep/issues/176).
|
||||
|
||||
|
||||
<h3 name="fancy">
|
||||
How do I use lookaround and/or backreferences?
|
||||
</h3>
|
||||
|
||||
This isn't currently possible. ripgrep uses finite automata to implement
|
||||
regular expression search, and in turn, guarantees linear time searching on all
|
||||
inputs. It is difficult to efficiently support lookaround and backreferences in
|
||||
finite automata engines, so ripgrep does not provide these features.
|
||||
|
||||
If a production quality regular expression engine with these features is ever
|
||||
written in Rust, then it is possible ripgrep will provide it as an opt-in
|
||||
feature.
|
||||
|
||||
|
||||
<h3 name="colors">
|
||||
How do I configure ripgrep's colors?
|
||||
</h3>
|
||||
|
||||
ripgrep has two flags related to colors:
|
||||
|
||||
* `--color` controls *when* to use colors.
|
||||
* `--colors` controls *which* colors to use.
|
||||
|
||||
The `--color` flag accepts one of the following possible values: `never`,
|
||||
`auto`, `always` or `ansi`. The `auto` value is the default and will cause
|
||||
ripgrep to only enable colors when it is printing to a terminal. But if you
|
||||
pipe ripgrep to a file or some other process, then it will suppress colors.
|
||||
|
||||
The --colors` flag is a bit more complicated. The general format is:
|
||||
|
||||
```
|
||||
--colors '{type}:{attribute}:{value}'
|
||||
```
|
||||
|
||||
* `{type}` should be one of `path`, `line`, `column` or `match`. Each of these
|
||||
correspond to the four different types of things that ripgrep will add color
|
||||
to in its output. Select the type whose color you want to change.
|
||||
* `{attribute}` should be one of `fg`, `bg` or `style`, corresponding to
|
||||
foreground color, background color, or miscellaneous styling (such as whether
|
||||
to bold the output or not).
|
||||
* `{value}` is determined by the value of `{attribute}`. If
|
||||
`{attribute}` is `style`, then `{value}` should be one of `nobold`,
|
||||
`bold`, `nointense`, `intense`, `nounderline` or `underline`. If
|
||||
`{attribute}` is `fg` or `bg`, then `{value}` should be a color.
|
||||
|
||||
A color is specified by either one of eight of English names, a single 256-bit
|
||||
number or an RGB triple (with over 16 million possible values, or "true
|
||||
color").
|
||||
|
||||
The color names are `red`, `blue`, `green`, `cyan`, `magenta`, `yellow`,
|
||||
`white` or `black`.
|
||||
|
||||
A single 256-bit number is a value in the range 0-255 (inclusive). It can
|
||||
either be in decimal format (e.g., `62`) or hexadecimal format (e.g., `0x3E`).
|
||||
|
||||
An RGB triple corresponds to three numbers (decimal or hexadecimal) separated
|
||||
by commas.
|
||||
|
||||
As a special case, `--colors '{type}:none'` will clear all colors and styles
|
||||
associated with `{type}`, which lets you start with a clean slate (instead of
|
||||
building on top of ripgrep's default color settings).
|
||||
|
||||
Here's an example that makes highlights the matches with a nice blue background
|
||||
with bolded white text:
|
||||
|
||||
```
|
||||
$ rg somepattern \
|
||||
--colors 'match:none' \
|
||||
--colors 'match:bg:0x33,0x66,0xFF' \
|
||||
--colors 'match:fg:white' \
|
||||
--colors 'match:style:bold'
|
||||
```
|
||||
|
||||
Colors are an ideal candidate to set in your
|
||||
[configuration file](GUIDE.md#configuration-file). See the
|
||||
[question on emulating The Silver Searcher's output style](#silver-searcher-output)
|
||||
for an example specific to colors.
|
||||
|
||||
|
||||
<h3 name="truecolors-windows">
|
||||
How do I enable true colors on Windows?
|
||||
</h3>
|
||||
|
||||
First, see the previous question's
|
||||
[answer on configuring colors](#colors).
|
||||
|
||||
Secondly, coloring on Windows is a bit complicated. If you're using a terminal
|
||||
like Cygwin, then it's likely true color support already works out of the box.
|
||||
However, if you are using a normal Windows console (`cmd` or `PowerShell`) and
|
||||
a version of Windows prior to 10, then there is no known way to get true
|
||||
color support. If you are on Windows 10 and using a Windows console, then
|
||||
true colors should work out of the box with one caveat: you might need to
|
||||
clear ripgrep's default color settings first. That is, instead of this:
|
||||
|
||||
```
|
||||
$ rg somepattern --colors 'match:fg:0x33,0x66,0xFF'
|
||||
```
|
||||
|
||||
you should do this
|
||||
|
||||
```
|
||||
$ rg somepattern --colors 'match:none' --colors 'match:fg:0x33,0x66,0xFF'
|
||||
```
|
||||
|
||||
This is because ripgrep might set the default style for `match` to `bold`, and
|
||||
it seems like Windows 10's VT100 support doesn't permit bold and true color
|
||||
ANSI escapes to be used simultaneously. The work-around above will clear
|
||||
ripgrep's default styling, allowing you to craft it exactly as desired.
|
||||
|
||||
|
||||
<h3 name="stop-ripgrep">
|
||||
How do I stop ripgrep from messing up colors when I kill it?
|
||||
</h3>
|
||||
|
||||
Type in `color` in cmd.exe (Command Prompt) and `echo -ne "\033[0m"` on
|
||||
Unix-like systems to restore your original foreground color.
|
||||
|
||||
In PowerShell, you can add the following code to your profile which will
|
||||
restore the original foreground color when `Reset-ForegroundColor` is called.
|
||||
Including the `Set-Alias` line will allow you to call it with simply `color`.
|
||||
|
||||
```powershell
|
||||
$OrigFgColor = $Host.UI.RawUI.ForegroundColor
|
||||
function Reset-ForegroundColor {
|
||||
$Host.UI.RawUI.ForegroundColor = $OrigFgColor
|
||||
}
|
||||
Set-Alias -Name color -Value Reset-ForegroundColor
|
||||
```
|
||||
|
||||
PR [#187](https://github.com/BurntSushi/ripgrep/pull/187) fixed this, and it
|
||||
was later deprecated in
|
||||
[#281](https://github.com/BurntSushi/ripgrep/issues/281). A full explanation is
|
||||
available
|
||||
[here](https://github.com/BurntSushi/ripgrep/issues/281#issuecomment-269093893).
|
||||
|
||||
|
||||
<h3 name="size-limit">
|
||||
How do I get around the regex size limit?
|
||||
</h3>
|
||||
|
||||
If you've given ripgrep a particularly large pattern (or a large number of
|
||||
smaller patterns), then it is possible that it will fail to compile because it
|
||||
hit a pre-set limit. For example:
|
||||
|
||||
```
|
||||
$ rg '\pL{1000}'
|
||||
Compiled regex exceeds size limit of 10485760 bytes.
|
||||
```
|
||||
|
||||
(Note: `\pL{1000}` may look small, but `\pL` is the character class containing
|
||||
all Unicode letters, which is quite large. *And* it's repeated 1000 times.)
|
||||
|
||||
In this case, you can work around by simply increasing the limit:
|
||||
|
||||
```
|
||||
$ rg '\pL{1000}' --regex-size-limit 1G
|
||||
```
|
||||
|
||||
Increasing the limit to 1GB does not necessarily mean that ripgrep will use
|
||||
that much memory. The limit just says that it's allowed to (approximately) use
|
||||
that much memory for constructing the regular expression.
|
||||
|
||||
|
||||
<h3 name="dfa-size">
|
||||
How do I make the <code>-f/--file</code> flag faster?
|
||||
</h3>
|
||||
|
||||
The `-f/--file` permits one to give a file to ripgrep which contains a pattern
|
||||
on each line. ripgrep will then report any line that matches any of the
|
||||
patterns.
|
||||
|
||||
If this pattern file gets too big, then it is possible ripgrep will slow down
|
||||
dramatically. *Typically* this is because an internal cache is too small, and
|
||||
will cause ripgrep to spill over to a slower but more robust regular expression
|
||||
engine. If this is indeed the problem, then it is possible to increase this
|
||||
cache and regain speed. The cache can be controlled via the `--dfa-size-limit`
|
||||
flag. For example, using `--dfa-size-limit 1G` will set the cache size to 1GB.
|
||||
(Note that this doesn't mean ripgrep will use 1GB of memory automatically, but
|
||||
it will allow the regex engine to if it needs to.)
|
||||
|
||||
|
||||
<h3 name="silver-searcher-output">
|
||||
How do I make the output look like The Silver Searcher's output?
|
||||
</h3>
|
||||
|
||||
Use the `--colors` flag, like so:
|
||||
|
||||
```
|
||||
rg --colors line:fg:yellow \
|
||||
--colors line:style:bold \
|
||||
--colors path:fg:green \
|
||||
--colors path:style:bold \
|
||||
--colors match:fg:black \
|
||||
--colors match:bg:yellow \
|
||||
--colors match:style:nobold \
|
||||
foo
|
||||
```
|
||||
|
||||
Alternatively, add your color configuration to your ripgrep config file (which
|
||||
is activated by setting the `RIPGREP_CONFIG_PATH` environment variable to point
|
||||
to your config file). For example:
|
||||
|
||||
```
|
||||
$ cat $HOME/.config/ripgrep/rc
|
||||
--colors=line:fg:yellow
|
||||
--colors=line:style:bold
|
||||
--colors=path:fg:green
|
||||
--colors=path:style:bold
|
||||
--colors=match:fg:black
|
||||
--colors=match:bg:yellow
|
||||
--colors=match:style:nobold
|
||||
$ RIPGREP_CONFIG_PATH=$HOME/.config/ripgrep/rc rg foo
|
||||
```
|
||||
|
||||
|
||||
<h3 name="rg-other-cmd">
|
||||
When I run <code>rg</code>, why does it execute some other command?
|
||||
</h3>
|
||||
|
||||
It's likely that you have a shell alias or even another tool called `rg` which
|
||||
is interfering with ripgrep. Run `which rg` to see what it is.
|
||||
|
||||
(Notably, the Rails plug-in for
|
||||
[Oh My Zsh](https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins#rails) sets
|
||||
up an `rg` alias for `rails generate`.)
|
||||
|
||||
Problems like this can be resolved in one of several ways:
|
||||
|
||||
* If you're using the OMZ Rails plug-in, disable it by editing the `plugins`
|
||||
array in your zsh configuration.
|
||||
* Temporarily bypass an existing `rg` alias by calling ripgrep as
|
||||
`command rg`, `\rg`, or `'rg'`.
|
||||
* Temporarily bypass an existing alias or another tool named `rg` by calling
|
||||
ripgrep by its full path (e.g., `/usr/bin/rg` or `/usr/local/bin/rg`).
|
||||
* Permanently disable an existing `rg` alias by adding `unalias rg` to the
|
||||
bottom of your shell configuration file (e.g., `.bash_profile` or `.zshrc`).
|
||||
* Give ripgrep its own alias that doesn't conflict with other tools/aliases by
|
||||
adding a line like the following to the bottom of your shell configuration
|
||||
file: `alias ripgrep='command rg'`.
|
||||
|
||||
|
||||
<h3 name="rg-alias-windows">
|
||||
How do I create an alias for ripgrep on Windows?
|
||||
</h3>
|
||||
|
||||
Often you can find a need to make alias for commands you use a lot that set
|
||||
certain flags. But PowerShell function aliases do not behave like your typical
|
||||
linux shell alias. You always need to propagate arguments and `stdin` input.
|
||||
But it cannot be done simply as
|
||||
`function grep() { $input | rg.exe --hidden $args }`
|
||||
|
||||
Use below example as reference to how setup alias in PowerShell.
|
||||
|
||||
```powershell
|
||||
function grep {
|
||||
$count = @($input).Count
|
||||
$input.Reset()
|
||||
|
||||
if ($count) {
|
||||
$input | rg.exe --hidden $args
|
||||
}
|
||||
else {
|
||||
rg.exe --hidden $args
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
PowerShell special variables:
|
||||
|
||||
* input - is powershell `stdin` object that allows you to access its content.
|
||||
* args - is array of arguments passed to this function.
|
||||
|
||||
This alias checks whether there is `stdin` input and propagates only if there
|
||||
is some lines. Otherwise empty `$input` will make powershell to trigger `rg` to
|
||||
search empty `stdin`.
|
||||
|
||||
|
||||
<h3 name="powershell-profile">
|
||||
How do I create a PowerShell profile?
|
||||
</h3>
|
||||
|
||||
To customize powershell on start-up, there is a special PowerShell script that
|
||||
has to be created. In order to find its location, type `$profile`.
|
||||
See
|
||||
[Microsoft's documentation](https://technet.microsoft.com/en-us/library/bb613488(v=vs.85).aspx)
|
||||
for more details.
|
||||
|
||||
Any PowerShell code in this file gets evaluated at the start of console. This
|
||||
way you can have own aliases to be created at start.
|
||||
|
||||
|
||||
<h3 name="pipe-non-ascii-windows">
|
||||
How do I pipe non-ASCII content to ripgrep on Windows?
|
||||
</h3>
|
||||
|
||||
When piping input into native executables in PowerShell, the encoding of the
|
||||
input is controlled by the `$OutputEncoding` variable. By default, this is set
|
||||
to US-ASCII, and any characters in the pipeline that don't have encodings in
|
||||
US-ASCII are converted to `?` (question mark) characters.
|
||||
|
||||
To change this setting, set `$OutputEncoding` to a different encoding, as
|
||||
represented by a .NET encoding object. Some common examples are below. The
|
||||
value of this variable is reset when PowerShell restarts, so to make this
|
||||
change take effect every time PowerShell is started add a line setting the
|
||||
variable into your PowerShell profile.
|
||||
|
||||
Example `$OutputEncoding` settings:
|
||||
|
||||
* UTF-8 without BOM: `$OutputEncoding = [System.Text.UTF8Encoding]::new()`
|
||||
* The console's output encoding:
|
||||
`$OutputEncoding = [System.Console]::OutputEncoding`
|
||||
|
||||
If you continue to have encoding problems, you can also force the encoding
|
||||
that the console will use for printing to UTF-8 with
|
||||
`[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8`. This
|
||||
will also reset when PowerShell is restarted, so you can add that line
|
||||
to your profile as well if you want to make the setting permanent.
|
||||
|
||||
|
||||
<h3 name="posix4ever">
|
||||
Can ripgrep replace grep?
|
||||
</h3>
|
||||
|
||||
Yes and no.
|
||||
|
||||
If, upon hearing that "ripgrep can replace grep," you *actually* hear, "ripgrep
|
||||
can be used in every instance grep can be used, in exactly the same way, for
|
||||
the same use cases, with exactly the same bug-for-bug behavior," then no,
|
||||
ripgrep trivially *cannot* replace grep. Moreover, ripgrep will *never* replace
|
||||
grep.
|
||||
|
||||
If, upon hearing that "ripgrep can replace grep," you *actually* hear, "ripgrep
|
||||
can replace grep in some cases and not in other use cases," then yes, that is
|
||||
indeed true!
|
||||
|
||||
Let's go over some of those use cases in favor of ripgrep. Some of these may
|
||||
not apply to you. That's OK. There may be other use cases not listed here that
|
||||
do apply to you. That's OK too.
|
||||
|
||||
(For all claims related to performance in the following words, see my
|
||||
[blog post](https://blog.burntsushi.net/ripgrep/)
|
||||
introducing ripgrep.)
|
||||
|
||||
* Are you frequently searching a repository of code? If so, ripgrep might be a
|
||||
good choice since there's likely a good chunk of your repository that you
|
||||
don't want to search. grep, can, of course, be made to filter files using
|
||||
recursive search, and if you don't mind writing out the requisite `--exclude`
|
||||
rules or writing wrapper scripts, then grep might be sufficient. (I'm not
|
||||
kidding, I myself did this with grep for almost a decade before writing
|
||||
ripgrep.) But if you instead enjoy having a search tool respect your
|
||||
`.gitignore`, then ripgrep might be perfect for you!
|
||||
* Are you frequently searching non-ASCII text that is UTF-8 encoded? One of
|
||||
ripgrep's key features is that it can handle Unicode features in your
|
||||
patterns in a way that tends to be faster than GNU grep. Unicode features
|
||||
in ripgrep are enabled by default; there is no need to configure your locale
|
||||
settings to use ripgrep properly because ripgrep doesn't respect your locale
|
||||
settings.
|
||||
* Do you need to search UTF-16 files and you don't want to bother explicitly
|
||||
transcoding them? Great. ripgrep does this for you automatically. No need
|
||||
to enable it.
|
||||
* Do you need to search a large directory of large files? ripgrep uses
|
||||
parallelism by default, which tends to make it faster than a standard
|
||||
`grep -r` search. However, if you're OK writing the occasional
|
||||
`find ./ -print0 | xargs -P8 -0 grep` command, then maybe grep is good
|
||||
enough.
|
||||
|
||||
Here are some cases where you might *not* want to use ripgrep. The same caveats
|
||||
for the previous section apply.
|
||||
|
||||
* Are you writing portable shell scripts intended to work in a variety of
|
||||
environments? Great, probably not a good idea to use ripgrep! ripgrep is has
|
||||
nowhere near the ubquity of grep, so if you do use ripgrep, you might need
|
||||
to futz with the installation process more than you would with grep.
|
||||
* Do you care about POSIX compatibility? If so, then you can't use ripgrep
|
||||
because it never was, isn't and never will be POSIX compatible.
|
||||
* Do you hate tools that try to do something smart? If so, ripgrep is all about
|
||||
being smart, so you might prefer to just stick with grep.
|
||||
* Is there a particular feature of grep you rely on that ripgrep either doesn't
|
||||
have or never will have? If the former, file a bug report, maybe ripgrep can
|
||||
do it! If the latter, well, then, just use grep.
|
680
GUIDE.md
Normal file
680
GUIDE.md
Normal file
@@ -0,0 +1,680 @@
|
||||
## User Guide
|
||||
|
||||
This guide is intended to give an elementary description of ripgrep and an
|
||||
overview of its capabilities. This guide assumes that ripgrep is
|
||||
[installed](README.md#installation)
|
||||
and that readers have passing familiarity with using command line tools. This
|
||||
also assumes a Unix-like system, although most commands are probably easily
|
||||
translatable to any command line shell environment.
|
||||
|
||||
|
||||
### Table of Contents
|
||||
|
||||
* [Basics](#basics)
|
||||
* [Recursive search](#recursive-search)
|
||||
* [Automatic filtering](#automatic-filtering)
|
||||
* [Manual filtering: globs](#manual-filtering-globs)
|
||||
* [Manual filtering: file types](#manual-filtering-file-types)
|
||||
* [Replacements](#replacements)
|
||||
* [Configuration file](#configuration-file)
|
||||
* [File encoding](#file-encoding)
|
||||
* [Common options](#common-options)
|
||||
|
||||
|
||||
### Basics
|
||||
|
||||
ripgrep is a command line tool that searches your files for patterns that
|
||||
you give it. ripgrep behaves as if reading each file line by line. If a line
|
||||
matches the pattern provided to ripgrep, then that line will be printed. If a
|
||||
line does not match the pattern, then the line is not printed.
|
||||
|
||||
The best way to see how this works is with an example. To show an example, we
|
||||
need something to search. Let's try searching ripgrep's source code. First
|
||||
grab a ripgrep source archive from
|
||||
https://github.com/BurntSushi/ripgrep/archive/0.7.1.zip
|
||||
and extract it:
|
||||
|
||||
```
|
||||
$ curl -LO https://github.com/BurntSushi/ripgrep/archive/0.7.1.zip
|
||||
$ unzip 0.7.1.zip
|
||||
$ cd ripgrep-0.7.1
|
||||
$ ls
|
||||
benchsuite grep tests Cargo.toml LICENSE-MIT
|
||||
ci ignore wincolor CHANGELOG.md README.md
|
||||
complete pkg appveyor.yml compile snapcraft.yaml
|
||||
doc src build.rs COPYING UNLICENSE
|
||||
globset termcolor Cargo.lock HomebrewFormula
|
||||
```
|
||||
|
||||
Let's try our first search by looking for all occurrences of the word `fast`
|
||||
in `README.md`:
|
||||
|
||||
```
|
||||
$ rg fast README.md
|
||||
75: faster than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
|
||||
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast while
|
||||
119:### Is it really faster than everything else?
|
||||
124:Summarizing, `ripgrep` is fast because:
|
||||
129: optimizations to make searching very fast.
|
||||
```
|
||||
|
||||
(**Note:** If you see an error message from ripgrep saying that it didn't
|
||||
search any files, then re-run ripgrep with the `--debug` flag. One likely cause
|
||||
of this is that you have a `*` rule in a `$HOME/.gitignore` file.)
|
||||
|
||||
So what happened here? ripgrep read the contents of `README.md`, and for each
|
||||
line that contained `fast`, ripgrep printed it to your terminal. ripgrep also
|
||||
included the line number for each line by default. If your terminal supports
|
||||
colors, then your output might actually look something like this screenshot:
|
||||
|
||||
[](https://burntsushi.net/stuff/ripgrep-guide-sample.png)
|
||||
|
||||
In this example, we searched for something called a "literal" string. This
|
||||
means that our pattern was just some normal text that we asked ripgrep to
|
||||
find. But ripgrep supports the ability to specify patterns via [regular
|
||||
expressions](https://en.wikipedia.org/wiki/Regular_expression). As an example,
|
||||
what if we wanted to find all lines have a word that contains `fast` followed
|
||||
by some number of other letters?
|
||||
|
||||
```
|
||||
$ rg 'fast\w+' README.md
|
||||
75: faster than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
|
||||
119:### Is it really faster than everything else?
|
||||
```
|
||||
|
||||
In this example, we used the pattern `fast\w+`. This pattern tells ripgrep to
|
||||
look for any lines containing the letters `fast` followed by *one or more*
|
||||
word-like characters. Namely, `\w` matches characters that compose words (like
|
||||
`a` and `L` but unlike `.` and ` `). The `+` after the `\w` means, "match the
|
||||
previous pattern one or more times." This means that the word `fast` won't
|
||||
match because there are no word characters following the final `t`. But a word
|
||||
like `faster` will. `faste` would also match!
|
||||
|
||||
Here's a different variation on this same theme:
|
||||
|
||||
```
|
||||
$ rg 'fast\w*' README.md
|
||||
75: faster than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
|
||||
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast while
|
||||
119:### Is it really faster than everything else?
|
||||
124:Summarizing, `ripgrep` is fast because:
|
||||
129: optimizations to make searching very fast.
|
||||
```
|
||||
|
||||
In this case, we used `fast\w*` for our pattern instead of `fast\w+`. The `*`
|
||||
means that it should match *zero* or more times. In this case, ripgrep will
|
||||
print the same lines as the pattern `fast`, but if your terminal supports
|
||||
colors, you'll notice that `faster` will be highlighted instead of just the
|
||||
`fast` prefix.
|
||||
|
||||
It is beyond the scope of this guide to provide a full tutorial on regular
|
||||
expressions, but ripgrep's specific syntax is documented here:
|
||||
https://docs.rs/regex/0.2.5/regex/#syntax
|
||||
|
||||
|
||||
### Recursive search
|
||||
|
||||
In the previous section, we showed how to use ripgrep to search a single file.
|
||||
In this section, we'll show how to use ripgrep to search an entire directory
|
||||
of files. In fact, *recursively* searching your current working directory is
|
||||
the default mode of operation for ripgrep, which means doing this is very
|
||||
simple.
|
||||
|
||||
Using our unzipped archive of ripgrep source code, here's how to find all
|
||||
function definitions whose name is `write`:
|
||||
|
||||
```
|
||||
$ rg 'fn write\('
|
||||
src/printer.rs
|
||||
469: fn write(&mut self, buf: &[u8]) {
|
||||
|
||||
termcolor/src/lib.rs
|
||||
227: fn write(&mut self, b: &[u8]) -> io::Result<usize> {
|
||||
250: fn write(&mut self, b: &[u8]) -> io::Result<usize> {
|
||||
428: fn write(&mut self, b: &[u8]) -> io::Result<usize> { self.wtr.write(b) }
|
||||
441: fn write(&mut self, b: &[u8]) -> io::Result<usize> { self.wtr.write(b) }
|
||||
454: fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
511: fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
848: fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
915: fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
949: fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
1114: fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
1348: fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
1353: fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
```
|
||||
|
||||
(**Note:** We escape the `(` here because `(` has special significance inside
|
||||
regular expressions. You could also use `rg -F 'fn write('` to achieve the
|
||||
same thing, where `-F` interprets your pattern as a literal string instead of
|
||||
a regular expression.)
|
||||
|
||||
In this example, we didn't specify a file at all. Instead, ripgrep defaulted
|
||||
to searching your current directory in the absence of a path. In general,
|
||||
`rg foo` is equivalent to `rg foo ./`.
|
||||
|
||||
This particular search showed us results in both the `src` and `termcolor`
|
||||
directories. The `src` directory is the core ripgrep code where as `termcolor`
|
||||
is a dependency of ripgrep (and is used by other tools). What if we only wanted
|
||||
to search core ripgrep code? Well, that's easy, just specify the directory you
|
||||
want:
|
||||
|
||||
```
|
||||
$ rg 'fn write\(' src
|
||||
src/printer.rs
|
||||
469: fn write(&mut self, buf: &[u8]) {
|
||||
```
|
||||
|
||||
Here, ripgrep limited its search to the `src` directory. Another way of doing
|
||||
this search would be to `cd` into the `src` directory and simply use `rg 'fn
|
||||
write\('` again.
|
||||
|
||||
|
||||
### Automatic filtering
|
||||
|
||||
After recursive search, ripgrep's most important feature is what it *doesn't*
|
||||
search. By default, when you search a directory, ripgrep will ignore all of
|
||||
the following:
|
||||
|
||||
1. Files and directories that match the rules in your `.gitignore` glob
|
||||
pattern.
|
||||
2. Hidden files and directories.
|
||||
3. Binary files. (ripgrep considers any file with a `NUL` byte to be binary.)
|
||||
4. Symbolic links aren't followed.
|
||||
|
||||
All of these things can be toggled using various flags provided by ripgrep:
|
||||
|
||||
1. You can disable `.gitignore` handling with the `--no-ignore` flag.
|
||||
2. Hidden files and directories can be searched with the `--hidden` flag.
|
||||
3. Binary files can be searched via the `--text` (`-a` for short) flag.
|
||||
Be careful with this flag! Binary files may emit control characters to your
|
||||
terminal, which might cause strange behavior.
|
||||
4. ripgrep can follow symlinks with the `--follow` (`-L` for short) flag.
|
||||
|
||||
As a special convenience, ripgrep also provides a flag called `--unrestricted`
|
||||
(`-u` for short). Repeated uses of this flag will cause ripgrep to disable
|
||||
more and more of its filtering. That is, `-u` will disable `.gitignore`
|
||||
handling, `-uu` will search hidden files and directories and `-uuu` will search
|
||||
binary files. This is useful when you're using ripgrep and you aren't sure
|
||||
whether its filtering is hiding results from you. Tacking on a couple `-u`
|
||||
flags is a quick way to find out. (Use the `--debug` flag if you're still
|
||||
perplexed, and if that doesn't help,
|
||||
[file an issue](https://github.com/BurntSushi/ripgrep/issues/new).)
|
||||
|
||||
ripgrep's `.gitignore` handling actually goes a bit beyond just `.gitignore`
|
||||
files. ripgrep will also respect repository specific rules found in
|
||||
`$GIT_DIR/info/exclude`, as well as any global ignore rules in your
|
||||
`core.excludesFile` (which is usually `$XDG_CONFIG_HOME/git/ignore` on
|
||||
Unix-like systems).
|
||||
|
||||
Sometimes you want to search files that are in your `.gitignore`, so it is
|
||||
possible to specify additional ignore rules or overrides in a `.ignore`
|
||||
(application agnostic) or `.rgignore` (ripgrep specific) file.
|
||||
|
||||
For example, let's say you have a `.gitignore` file that looks like this:
|
||||
|
||||
```
|
||||
log/
|
||||
```
|
||||
|
||||
This generally means that any `log` directory won't be tracked by `git`.
|
||||
However, perhaps it contains useful output that you'd like to include in your
|
||||
searches, but you still don't want to track it in `git`. You can achieve this
|
||||
by creating a `.ignore` file in the same directory as the `.gitignore` file
|
||||
with the following contents:
|
||||
|
||||
```
|
||||
!log/
|
||||
```
|
||||
|
||||
ripgrep treats `.ignore` files with higher precedence than `.gitignore` files
|
||||
(and treats `.rgignore` files with higher precdence than `.ignore` files).
|
||||
This means ripgrep will see the `!log/` whitelist rule first and search that
|
||||
directory.
|
||||
|
||||
Like `.gitignore`, a `.ignore` file can be placed in any directory. Its rules
|
||||
will be processed with respect to the directory it resides in, just like
|
||||
`.gitignore`.
|
||||
|
||||
For a more in depth description of how glob patterns in a `.gitignore` file
|
||||
are interpreted, please see `man gitignore`.
|
||||
|
||||
|
||||
### Manual filtering: globs
|
||||
|
||||
In the previous section, we talked about ripgrep's filtering that it does by
|
||||
default. It is "automatic" because it reacts to your environment. That is, it
|
||||
uses already existing `.gitignore` files to produce more relevant search
|
||||
results.
|
||||
|
||||
In addition to automatic filtering, ripgrep also provides more manual or ad hoc
|
||||
filtering. This comes in two varieties: additional glob patterns specified in
|
||||
your ripgrep commands and file type filtering. This section covers glob
|
||||
patterns while the next section covers file type filtering.
|
||||
|
||||
In our ripgrep source code (see [Basics](#basics) for instructions on how to
|
||||
get a source archive to search), let's say we wanted to see which things depend
|
||||
on `clap`, our argument parser.
|
||||
|
||||
We could do this:
|
||||
|
||||
```
|
||||
$ rg clap
|
||||
[lots of results]
|
||||
```
|
||||
|
||||
But this shows us many things, and we're only interested in where we wrote
|
||||
`clap` as a dependency. Instead, we could limit ourselves to TOML files, which
|
||||
is how dependencies are communicated to Rust's build tool, Cargo:
|
||||
|
||||
```
|
||||
$ rg clap -g '*.toml'
|
||||
Cargo.toml
|
||||
35:clap = "2.26"
|
||||
51:clap = "2.26"
|
||||
```
|
||||
|
||||
The `-g '*.toml'` syntax says, "make sure every file searched matches this
|
||||
glob pattern." Note that we put `'*.toml'` in single quotes to prevent our
|
||||
shell from expanding the `*`.
|
||||
|
||||
If we wanted, we could tell ripgrep to search anything *but* `*.toml` files:
|
||||
|
||||
```
|
||||
$ rg clap -g '!*.toml'
|
||||
[lots of results]
|
||||
```
|
||||
|
||||
This will give you a lot of results again as above, but they won't include
|
||||
files ending with `.toml`. Note that the use of a `!` here to mean "negation"
|
||||
is a bit non-standard, but it was chosen to be consistent with how globs in
|
||||
`.gitignore` files are written. (Although, the meaning is reversed. In
|
||||
`.gitignore` files, a `!` prefix means whitelist, and on the command line, a
|
||||
`!` means blacklist.)
|
||||
|
||||
Globs are interpreted in exactly the same way as `.gitignore` patterns. That
|
||||
is, later globs will override earlier globs. For example, the following command
|
||||
will search only `*.toml` files:
|
||||
|
||||
```
|
||||
$ rg clap -g '!*.toml' -g '*.toml'
|
||||
```
|
||||
|
||||
Interestingly, reversing the order of the globs in this case will match
|
||||
nothing, since the presence of at least one non-blacklist glob will institute a
|
||||
requirement that every file searched must match at least one glob. In this
|
||||
case, the blacklist glob takes precedence over the previous glob and prevents
|
||||
any file from being searched at all!
|
||||
|
||||
|
||||
### Manual filtering: file types
|
||||
|
||||
Over time, you might notice that you use the same glob patterns over and over.
|
||||
For example, you might find yourself doing a lot of searches where you only
|
||||
want to see results for Rust files:
|
||||
|
||||
```
|
||||
$ rg 'fn run' -g '*.rs'
|
||||
```
|
||||
|
||||
Instead of writing out the glob every time, you can use ripgrep's support for
|
||||
file types:
|
||||
|
||||
```
|
||||
$ rg 'fn run' --type rust
|
||||
```
|
||||
|
||||
or, more succinctly,
|
||||
|
||||
```
|
||||
$ rg 'fn run' -trust
|
||||
```
|
||||
|
||||
The way the `--type` flag functions is simple. It acts as a name that is
|
||||
assigned to one or more globs that match the relevant files. This lets you
|
||||
write a single type that might encompass a broad range of file extensions. For
|
||||
example, if you wanted to search C files, you'd have to check both C source
|
||||
files and C header files:
|
||||
|
||||
```
|
||||
$ rg 'int main' -g '*.{c,h}'
|
||||
```
|
||||
|
||||
or you could just use the C file type:
|
||||
|
||||
```
|
||||
$ rg 'int main' -tc
|
||||
```
|
||||
|
||||
Just as you can write blacklist globs, you can blacklist file types too:
|
||||
|
||||
```
|
||||
$ rg clap --type-not rust
|
||||
```
|
||||
|
||||
or, more succinctly,
|
||||
|
||||
```
|
||||
$ rg clap -Trust
|
||||
```
|
||||
|
||||
That is, `-t` means "include files of this type" where as `-T` means "exclude
|
||||
files of this type."
|
||||
|
||||
To see the globs that make up a type, run `rg --type-list`:
|
||||
|
||||
```
|
||||
$ rg --type-list | rg '^make:'
|
||||
make: *.mak, *.mk, GNUmakefile, Gnumakefile, Makefile, gnumakefile, makefile
|
||||
```
|
||||
|
||||
By default, ripgrep comes with a bunch of pre-defined types. Generally, these
|
||||
types correspond to well known public formats. But you can define your own
|
||||
types as well. For example, perhaps you frequently search "web" files, which
|
||||
consist of Javascript, HTML and CSS:
|
||||
|
||||
```
|
||||
$ rg --type-add 'web:*.html' --type-add 'web:*.css' --type-add 'web:*.js' -tweb title
|
||||
```
|
||||
|
||||
or, more succinctly,
|
||||
|
||||
```
|
||||
$ rg --type-add 'web:*.{html,css,js}' -tweb title
|
||||
```
|
||||
|
||||
The above command defines a new type, `web`, corresponding to the glob
|
||||
`*.{html,css,js}`. It then applies the new filter with `-tweb` and searches for
|
||||
the pattern `title`. If you ran
|
||||
|
||||
```
|
||||
$ rg --type-add 'web:*.{html,css,js}' --type-list
|
||||
```
|
||||
|
||||
Then you would see your `web` type show up in the list, even though it is not
|
||||
part of ripgrep's built-in types.
|
||||
|
||||
It is important to stress here that the `--type-add` flag only applies to the
|
||||
current command. It does not add a new file type and save it somewhere in a
|
||||
persistent form. If you want a type to be available in every ripgrep command,
|
||||
then you should either create a shell alias:
|
||||
|
||||
```
|
||||
alias rg="rg --type-add 'web:*.{html,css,js}'"
|
||||
```
|
||||
|
||||
or add `--type-add=web:*.{html,css,js}` to your ripgrep configuration file.
|
||||
([Configuration files](#configuration-file) are covered in more detail later.)
|
||||
|
||||
|
||||
### Replacements
|
||||
|
||||
ripgrep provides a limited ability to modify its output by replacing matched
|
||||
text with some other text. This is easiest to explain with an example. Remember
|
||||
when we searched for the word `fast` in ripgrep's README?
|
||||
|
||||
```
|
||||
$ rg fast README.md
|
||||
75: faster than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
|
||||
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast while
|
||||
119:### Is it really faster than everything else?
|
||||
124:Summarizing, `ripgrep` is fast because:
|
||||
129: optimizations to make searching very fast.
|
||||
```
|
||||
|
||||
What if we wanted to *replace* all occurrences of `fast` with `FAST`? That's
|
||||
easy with ripgrep's `--replace` flag:
|
||||
|
||||
```
|
||||
$ rg fast README.md --replace FAST
|
||||
75: FASTer than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
|
||||
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays FAST while
|
||||
119:### Is it really FASTer than everything else?
|
||||
124:Summarizing, `ripgrep` is FAST because:
|
||||
129: optimizations to make searching very FAST.
|
||||
```
|
||||
|
||||
or, more succinctly,
|
||||
|
||||
```
|
||||
$ rg fast README.md -r FAST
|
||||
[snip]
|
||||
```
|
||||
|
||||
In essence, the `--replace` flag applies *only* to the matching portion of text
|
||||
in the output. If you instead wanted to replace an entire line of text, then
|
||||
you need to include the entire line in your match. For example:
|
||||
|
||||
```
|
||||
$ rg '^.*fast.*$' README.md -r FAST
|
||||
75:FAST
|
||||
88:FAST
|
||||
119:FAST
|
||||
124:FAST
|
||||
129:FAST
|
||||
```
|
||||
|
||||
Alternatively, you can combine the `--only-matching` (or `-o` for short) with
|
||||
the `--replace` flag to achieve the same result:
|
||||
|
||||
```
|
||||
$ rg fast README.md --only-matching --replace FAST
|
||||
75:FAST
|
||||
88:FAST
|
||||
119:FAST
|
||||
124:FAST
|
||||
129:FAST
|
||||
```
|
||||
|
||||
or, more succinctly,
|
||||
|
||||
```
|
||||
$ rg fast README.md -or FAST
|
||||
[snip]
|
||||
```
|
||||
|
||||
Finally, replacements can include capturing groups. For example, let's say
|
||||
we wanted to find all occurrences of `fast` followed by another word and
|
||||
join them together with a dash. The pattern we might use for that is
|
||||
`fast\s+(\w+)`, which matches `fast`, followed by any amount of whitespace,
|
||||
followed by any number of "word" characters. We put the `\w+` in a "capturing
|
||||
group" (indicated by parentheses) so that we can reference it later in our
|
||||
replacement string. For example:
|
||||
|
||||
```
|
||||
$ rg 'fast\s+(\w+)' README.md -r 'fast-$1'
|
||||
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast-while
|
||||
124:Summarizing, `ripgrep` is fast-because:
|
||||
```
|
||||
|
||||
Our replacement string here, `fast-$1`, consists of `fast-` followed by the
|
||||
contents of the capturing group at index `1`. (Capturing groups actually start
|
||||
at index 0, but the `0`th capturing group always corresponds to the entire
|
||||
match. The capturing group at index `1` always corresponds to the first
|
||||
explicit capturing group found in the regex pattern.)
|
||||
|
||||
Capturing groups can also be named, which is sometimes more convenient than
|
||||
using the indices. For example, the following command is equivalent to the
|
||||
above command:
|
||||
|
||||
```
|
||||
$ rg 'fast\s+(?P<word>\w+)' README.md -r 'fast-$word'
|
||||
88: color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast-while
|
||||
124:Summarizing, `ripgrep` is fast-because:
|
||||
```
|
||||
|
||||
It is important to note that ripgrep **will never modify your files**. The
|
||||
`--replace` flag only controls ripgrep's output. (And there is no flag to let
|
||||
you do a replacement in a file.)
|
||||
|
||||
|
||||
### Configuration file
|
||||
|
||||
It is possible that ripgrep's default options aren't suitable in every case.
|
||||
For that reason, and because shell aliases aren't always convenient, ripgrep
|
||||
supports configuration files.
|
||||
|
||||
Setting up a configuration file is simple. ripgrep will not look in any
|
||||
predetermined directory for a config file automatically. Instead, you need to
|
||||
set the `RIPGREP_CONFIG_PATH` environment variable to the file path of your
|
||||
config file. Once the environment variable is set, open the file and just type
|
||||
in the flags you want set automatically. There are only two rules for
|
||||
describing the format of the config file:
|
||||
|
||||
1. Every line is a shell argument, after trimming ASCII whitespace.
|
||||
2. Lines starting with `#` (optionally preceded by any amount of
|
||||
ASCII whitespace) are ignored.
|
||||
|
||||
In particular, there is no escaping. Each line is given to ripgrep as a single
|
||||
command line argument verbatim.
|
||||
|
||||
Here's an example of a configuration file, which demonstrates some of the
|
||||
formatting peculiarities:
|
||||
|
||||
```
|
||||
$ cat $HOME/.ripgreprc
|
||||
# Don't let ripgrep vomit really long lines to my terminal.
|
||||
--max-columns=150
|
||||
|
||||
# Add my 'web' type.
|
||||
--type-add
|
||||
web:*.{html,css,js}*
|
||||
|
||||
# Set the colors.
|
||||
--colors=line:none
|
||||
--colors=line:style:bold
|
||||
|
||||
# Because who cares about case!?
|
||||
--smart-case
|
||||
```
|
||||
|
||||
When we use a flag that has a value, we either put the flag and the value on
|
||||
the same line but delimited by an `=` sign (e.g., `--max-columns=150`), or we
|
||||
put the flag and the value on two different lines. This is because ripgrep's
|
||||
argument parser knows to treat the single argument `--max-columns=150` as a
|
||||
flag with a value, but if we had written `--max-columns 150` in our
|
||||
configuration file, then ripgrep's argument parser wouldn't know what to do
|
||||
with it.
|
||||
|
||||
Putting the flag and value on different lines is exactly equivalent and is a
|
||||
matter of style.
|
||||
|
||||
Comments are encouraged so that you remember what the config is doing. Empty
|
||||
lines are OK too.
|
||||
|
||||
So let's say you're using the above configuration file, but while you're at a
|
||||
terminal, you really want to be able to see lines longer than 150 columns. What
|
||||
do you do? Thankfully, all you need to do is pass `--max-columns 0` (or `-M0`
|
||||
for short) on the command line, which will override your configuration file's
|
||||
setting. This works because ripgrep's configuration file is *prepended* to the
|
||||
explicit arguments you give it on the command line. Since flags given later
|
||||
override flags given earlier, everything works as expected. This works for most
|
||||
other flags as well, and each flag's documentation states which other flags
|
||||
override it.
|
||||
|
||||
If you're confused about what configuration file ripgrep is reading arguments
|
||||
from, then running ripgrep with the `--debug` flag should help clarify things.
|
||||
The debug output should note what config file is being loaded and the arugments
|
||||
that have been read from the configuration.
|
||||
|
||||
Finally, if you want to make absolutely sure that ripgrep *isn't* reading a
|
||||
configuration file, then you can pass the `--no-config` flag, which will always
|
||||
prevent ripgrep from reading extraneous configuration from the environment,
|
||||
regardless of what other methods of configuration are added to ripgrep in the
|
||||
future.
|
||||
|
||||
|
||||
### File encoding
|
||||
|
||||
[Text encoding](https://en.wikipedia.org/wiki/Character_encoding) is a complex
|
||||
topic, but we can try to summarize its relevancy to ripgrep:
|
||||
|
||||
* Files are generally just a bundle of bytes. There is no reliable way to know
|
||||
their encoding.
|
||||
* Either the encoding of the pattern must match the encoding of the files being
|
||||
searched, or a form of transcoding must be performed converts either the
|
||||
pattern or the file to the same encoding as the other.
|
||||
* ripgrep tends to work best on plain text files, and among plain text files,
|
||||
the most popular encodings likely consist of ASCII, latin1 or UTF-8. As
|
||||
a special exception, UTF-16 is prevalent in Windows environments
|
||||
|
||||
In light of the above, here is how ripgrep behaves:
|
||||
|
||||
* All input is assumed to be ASCII compatible (which means every byte that
|
||||
corresponds to an ASCII codepoint actually is an ASCII codepoint). This
|
||||
includes ASCII itself, latin1 and UTF-8.
|
||||
* ripgrep works best with UTF-8. For example, ripgrep's regular expression
|
||||
engine supports Unicode features. Namely, character classes like `\w` will
|
||||
match all word characters by Unicode's definition and `.` will match any
|
||||
Unicode codepoint instead of any byte. These constructions assume UTF-8,
|
||||
so they simply won't match when they come across bytes in a file that aren't
|
||||
UTF-8.
|
||||
* To handle the UTF-16 case, ripgrep will do something called "BOM sniffing"
|
||||
by default. That is, the first three bytes of a file will be read, and if
|
||||
they correspond to a UTF-16 BOM, then ripgrep will transcode the contents of
|
||||
the file from UTF-16 to UTF-8, and then execute the search on the transcoded
|
||||
version of the file. (This incurs a performance penalty since transcoding
|
||||
is slower than regex searching.)
|
||||
* To handle other cases, ripgrep provides a `-E/--encoding` flag, which permits
|
||||
you to specify an encoding from the
|
||||
[Encoding Standard](https://encoding.spec.whatwg.org/#concept-encoding-get).
|
||||
ripgrep will assume *all* files searched are the encoding specified and
|
||||
will perform a transcoding step just like in the UTF-16 case described above.
|
||||
|
||||
By default, ripgrep will not require its input be valid UTF-8. That is, ripgrep
|
||||
can and will search arbitrary bytes. The key here is that if you're searching
|
||||
content that isn't UTF-8, then the usefulness of your pattern will degrade. If
|
||||
you're searching bytes that aren't ASCII compatible, then it's likely the
|
||||
pattern won't find anything. With all that said, this mode of operation is
|
||||
important, because it lets you find ASCII or UTF-8 *within* files that are
|
||||
otherwise arbitrary bytes.
|
||||
|
||||
Finally, it is possible to disable ripgrep's Unicode support from within the
|
||||
pattern regular expression. For example, let's say you wanted `.` to match any
|
||||
byte rather than any Unicode codepoint. (You might want this while searching a
|
||||
binary file, since `.` by default will not match invalid UTF-8.) You could do
|
||||
this by disabling Unicode via a regular expression flag:
|
||||
|
||||
```
|
||||
$ rg '(?-u:.)'
|
||||
```
|
||||
|
||||
This works for any part of the pattern. For example, the following will find
|
||||
any Unicode word character followed by any ASCII word character followed by
|
||||
another Unicode word character:
|
||||
|
||||
```
|
||||
$ rg '\w(?-u:\w)\w'
|
||||
```
|
||||
|
||||
|
||||
### Common options
|
||||
|
||||
ripgrep has a lot of flags. Too many to keep in your head at once. This section
|
||||
is intended to give you a sampling of some of the most important and frequently
|
||||
used options that will likely impact how you use ripgrep on a regular basis.
|
||||
|
||||
* `-h`: Show ripgrep's condensed help output.
|
||||
* `--help`: Show ripgrep's longer form help output. (Nearly what you'd find in
|
||||
ripgrep's man page, so pipe it into a pager!)
|
||||
* `-i/--ignore-case`: When searching for a pattern, ignore case differences.
|
||||
That is `rg -i fast` matches `fast`, `fASt`, `FAST`, etc.
|
||||
* `-S/--smart-case`: This is similar to `--ignore-case`, but disables itself
|
||||
if the pattern contains any uppercase letters. Usually this flag is put into
|
||||
alias or a config file.
|
||||
* `-w/--word-regexp`: Require that all matches of the pattern be surrounded
|
||||
by word boundaries. That is, given `pattern`, the `--word-regexp` flag will
|
||||
cause ripgrep to behave as if `pattern` were actually `\b(?:pattern)\b`.
|
||||
* `-c/--count`: Report a count of total matched lines.
|
||||
* `--files`: Print the files that ripgrep *would* search, but don't actually
|
||||
search them.
|
||||
* `-a/--text`: Search binary files as if they were plain text.
|
||||
* `-z/--search-zip`: Search compressed files (gzip, bzip2, lzma, xz). This is
|
||||
disabled by default.
|
||||
* `-C/--context`: Show the lines surrounding a match.
|
||||
* `--sort-files`: Force ripgrep to sort its output by file name. (This disables
|
||||
parallelism, so it might be slower.)
|
||||
* `-L/--follow`: Follow symbolic links while recursively searching.
|
||||
* `-M/--max-columns`: Limit the length of lines printed by ripgrep.
|
||||
* `--debug`: Shows ripgrep's debug output. This is useful for understanding
|
||||
why a particular file might be ignored from search, or what kinds of
|
||||
configuration ripgrep is loading from the environment.
|
408
README.md
408
README.md
@@ -1,11 +1,11 @@
|
||||
ripgrep (rg)
|
||||
------------
|
||||
`ripgrep` is a line-oriented search tool that recursively searches your current
|
||||
directory for a regex pattern while respecting your gitignore rules. To a first
|
||||
approximation, ripgrep combines the usability of The Silver Searcher (similar
|
||||
to `ack`) with the raw speed of GNU grep. `ripgrep` has first class support on
|
||||
Windows, macOS and Linux, with binary downloads available for
|
||||
[every release](https://github.com/BurntSushi/ripgrep/releases).
|
||||
ripgrep is a line-oriented search tool that recursively searches your current
|
||||
directory for a regex pattern while respecting your gitignore rules. ripgrep
|
||||
has first class support on Windows, macOS and Linux, with binary downloads
|
||||
available for [every release](https://github.com/BurntSushi/ripgrep/releases).
|
||||
ripgrep is similar to other popular search tools like The Silver Searcher,
|
||||
ack and grep.
|
||||
|
||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
||||
[](https://ci.appveyor.com/project/BurntSushi/ripgrep)
|
||||
@@ -13,23 +13,36 @@ Windows, macOS and Linux, with binary downloads available for
|
||||
|
||||
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
||||
|
||||
|
||||
### CHANGELOG
|
||||
|
||||
Please see the [CHANGELOG](CHANGELOG.md) for a release history.
|
||||
|
||||
### Documentation quick links
|
||||
|
||||
* [Installation](#installation)
|
||||
* [User Guide](GUIDE.md)
|
||||
* [Frequently Asked Questions](FAQ.md)
|
||||
* [Regex syntax](https://docs.rs/regex/0.2.5/regex/#syntax)
|
||||
* [Configuration files](GUIDE.md#configuration-file)
|
||||
* [Shell completions](FAQ.md#complete)
|
||||
* [Building](#building)
|
||||
|
||||
|
||||
### Screenshot of search results
|
||||
|
||||
[](http://burntsushi.net/stuff/ripgrep1.png)
|
||||
|
||||
|
||||
### Quick examples comparing tools
|
||||
|
||||
This example searches the entire Linux kernel source tree (after running
|
||||
`make defconfig && make -j8`) for `[A-Z]+_SUSPEND`, where all matches must be
|
||||
words. Timings were collected on a system with an Intel i7-6900K 3.2 GHz, and
|
||||
ripgrep was compiled using the `compile` script in this repo.
|
||||
ripgrep was compiled with SIMD enabled.
|
||||
|
||||
Please remember that a single benchmark is never enough! See my
|
||||
[blog post on `ripgrep`](http://blog.burntsushi.net/ripgrep/)
|
||||
[blog post on ripgrep](http://blog.burntsushi.net/ripgrep/)
|
||||
for a very detailed comparison with more benchmarks and analysis.
|
||||
|
||||
| Tool | Command | Line count | Time |
|
||||
@@ -69,65 +82,62 @@ large file (~9.3GB,
|
||||
In the above benchmark, passing the `-n` flag (for showing line numbers)
|
||||
increases the times to `2.640s` for ripgrep and `10.277s` for GNU grep.
|
||||
|
||||
### Why should I use `ripgrep`?
|
||||
|
||||
* It can replace both The Silver Searcher and GNU grep because it is generally
|
||||
faster than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
|
||||
for both, but the feature sets are far more similar than different.)
|
||||
* Like The Silver Searcher, `ripgrep` defaults to recursive directory search
|
||||
### Why should I use ripgrep?
|
||||
|
||||
* It can replace many use cases served by both The Silver Searcher and GNU grep
|
||||
because it is generally faster than both. (See [the FAQ](FAQ.md#posix4ever)
|
||||
for more details on whether ripgrep can truly replace grep.)
|
||||
* Like The Silver Searcher, ripgrep defaults to recursive directory search
|
||||
and won't search files ignored by your `.gitignore` files. It also ignores
|
||||
hidden and binary files by default. `ripgrep` also implements full support
|
||||
hidden and binary files by default. ripgrep also implements full support
|
||||
for `.gitignore`, whereas there are many bugs related to that functionality
|
||||
in The Silver Searcher.
|
||||
* `ripgrep` can search specific types of files. For example, `rg -tpy foo`
|
||||
* ripgrep can search specific types of files. For example, `rg -tpy foo`
|
||||
limits your search to Python files and `rg -Tjs foo` excludes Javascript
|
||||
files from your search. `ripgrep` can be taught about new file types with
|
||||
files from your search. ripgrep can be taught about new file types with
|
||||
custom matching rules.
|
||||
* `ripgrep` supports many features found in `grep`, such as showing the context
|
||||
* ripgrep supports many features found in `grep`, such as showing the context
|
||||
of search results, searching multiple patterns, highlighting matches with
|
||||
color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast while
|
||||
color and full Unicode support. Unlike GNU grep, ripgrep stays fast while
|
||||
supporting Unicode (which is always on).
|
||||
* `ripgrep` supports searching files in text encodings other than UTF-8, such
|
||||
* ripgrep supports searching files in text encodings other than UTF-8, such
|
||||
as UTF-16, latin-1, GBK, EUC-JP, Shift_JIS and more. (Some support for
|
||||
automatically detecting UTF-16 is provided. Other text encodings must be
|
||||
specifically specified with the `-E/--encoding` flag.)
|
||||
* `ripgrep` supports searching files compressed in a common format (gzip, xz,
|
||||
* ripgrep supports searching files compressed in a common format (gzip, xz,
|
||||
lzma or bzip2 current) with the `-z/--search-zip` flag.
|
||||
|
||||
In other words, use `ripgrep` if you like speed, filtering by default, fewer
|
||||
In other words, use ripgrep if you like speed, filtering by default, fewer
|
||||
bugs, and Unicode support.
|
||||
|
||||
### Why shouldn't I use `ripgrep`?
|
||||
|
||||
I'd like to try to convince you why you *shouldn't* use `ripgrep`. This should
|
||||
### Why shouldn't I use ripgrep?
|
||||
|
||||
I'd like to try to convince you why you *shouldn't* use ripgrep. This should
|
||||
give you a glimpse at some important downsides or missing features of
|
||||
`ripgrep`.
|
||||
ripgrep.
|
||||
|
||||
* `ripgrep` uses a regex engine based on finite automata, so if you want fancy
|
||||
regex features such as backreferences or lookaround, `ripgrep` won't provide
|
||||
them to you. `ripgrep` does support lots of things though, including, but not
|
||||
* ripgrep uses a regex engine based on finite automata, so if you want fancy
|
||||
regex features such as backreferences or lookaround, ripgrep won't provide
|
||||
them to you. ripgrep does support lots of things though, including, but not
|
||||
limited to: lazy quantification (e.g., `a+?`), repetitions (e.g., `a{2,5}`),
|
||||
begin/end assertions (e.g., `^\w+$`), word boundaries (e.g., `\bfoo\b`), and
|
||||
support for Unicode categories (e.g., `\p{Sc}` to match currency symbols or
|
||||
`\p{Lu}` to match any uppercase letter). (Fancier regexes will never be
|
||||
supported.)
|
||||
* `ripgrep` doesn't have multiline search. (Unlikely to ever be supported.)
|
||||
* ripgrep doesn't have multiline search. (Will happen as an opt-in feature.)
|
||||
|
||||
In other words, if you like fancy regexes or multiline search, then `ripgrep`
|
||||
In other words, if you like fancy regexes or multiline search, then ripgrep
|
||||
may not quite meet your needs (yet).
|
||||
|
||||
### Feature comparison
|
||||
|
||||
Andy Lester, author of [ack](https://beyondgrep.com/), has published an
|
||||
excellent table comparing the features of ack, ag, git-grep, GNU grep and
|
||||
ripgrep: https://beyondgrep.com/feature-comparison/
|
||||
|
||||
### Is it really faster than everything else?
|
||||
|
||||
Generally, yes. A large number of benchmarks with detailed analysis for each is
|
||||
[available on my blog](http://blog.burntsushi.net/ripgrep/).
|
||||
|
||||
Summarizing, `ripgrep` is fast because:
|
||||
Summarizing, ripgrep is fast because:
|
||||
|
||||
* It is built on top of
|
||||
[Rust's regex engine](https://github.com/rust-lang-nursery/regex).
|
||||
@@ -138,7 +148,7 @@ Summarizing, `ripgrep` is fast because:
|
||||
engine.
|
||||
* It supports searching with either memory maps or by searching incrementally
|
||||
with an intermediate buffer. The former is better for single files and the
|
||||
latter is better for large directories. `ripgrep` chooses the best searching
|
||||
latter is better for large directories. ripgrep chooses the best searching
|
||||
strategy for you automatically.
|
||||
* Applies your ignore patterns in `.gitignore` files using a
|
||||
[`RegexSet`](https://doc.rust-lang.org/regex/regex/struct.RegexSet.html).
|
||||
@@ -148,14 +158,22 @@ Summarizing, `ripgrep` is fast because:
|
||||
[`crossbeam`](https://docs.rs/crossbeam) and
|
||||
[`ignore`](https://docs.rs/ignore).
|
||||
|
||||
|
||||
### Feature comparison
|
||||
|
||||
Andy Lester, author of [ack](https://beyondgrep.com/), has published an
|
||||
excellent table comparing the features of ack, ag, git-grep, GNU grep and
|
||||
ripgrep: https://beyondgrep.com/feature-comparison/
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
The binary name for `ripgrep` is `rg`.
|
||||
The binary name for ripgrep is `rg`.
|
||||
|
||||
**[Archives of precompiled binaries for `ripgrep` are available for Windows,
|
||||
**[Archives of precompiled binaries for ripgrep are available for Windows,
|
||||
macOS and Linux.](https://github.com/BurntSushi/ripgrep/releases)** Users of
|
||||
platforms not explicitly mentioned below (such as Debian) are advised
|
||||
to download one of these archives.
|
||||
platforms not explicitly mentioned below are advised to download one of these
|
||||
archives.
|
||||
|
||||
Linux binaries are static executables. Windows binaries are available either as
|
||||
built with MinGW (GNU) or with Microsoft Visual C++ (MSVC). When possible,
|
||||
@@ -179,63 +197,73 @@ $ brew tap burntsushi/ripgrep https://github.com/BurntSushi/ripgrep.git
|
||||
$ brew install burntsushi/ripgrep/ripgrep-bin
|
||||
```
|
||||
|
||||
If you're a **Windows Chocolatey** user, then you can install `ripgrep` from the [official repo](https://chocolatey.org/packages/ripgrep):
|
||||
If you're a **Windows Chocolatey** user, then you can install ripgrep from the [official repo](https://chocolatey.org/packages/ripgrep):
|
||||
|
||||
```
|
||||
$ choco install ripgrep
|
||||
```
|
||||
|
||||
If you're an **Arch Linux** user, then you can install `ripgrep` from the official repos:
|
||||
If you're an **Arch Linux** user, then you can install ripgrep from the official repos:
|
||||
|
||||
```
|
||||
$ pacman -S ripgrep
|
||||
```
|
||||
|
||||
If you're a **Gentoo** user, you can install `ripgrep` from the [official repo](https://packages.gentoo.org/packages/sys-apps/ripgrep):
|
||||
If you're a **Gentoo** user, you can install ripgrep from the [official repo](https://packages.gentoo.org/packages/sys-apps/ripgrep):
|
||||
|
||||
```
|
||||
$ emerge sys-apps/ripgrep
|
||||
```
|
||||
|
||||
If you're a **Fedora 27+** user, you can install `ripgrep` from official repositories.
|
||||
If you're a **Fedora 27+** user, you can install ripgrep from official repositories.
|
||||
|
||||
```
|
||||
$ sudo dnf install ripgrep
|
||||
```
|
||||
|
||||
If you're a **Fedora 24+** user, you can install `ripgrep` from [copr](https://copr.fedorainfracloud.org/coprs/carlwgeorge/ripgrep/):
|
||||
If you're a **Fedora 24+** user, you can install ripgrep from [copr](https://copr.fedorainfracloud.org/coprs/carlwgeorge/ripgrep/):
|
||||
|
||||
```
|
||||
$ sudo dnf copr enable carlwgeorge/ripgrep
|
||||
$ sudo dnf install ripgrep
|
||||
```
|
||||
|
||||
If you're a **RHEL/CentOS 7** user, you can install `ripgrep` from [copr](https://copr.fedorainfracloud.org/coprs/carlwgeorge/ripgrep/):
|
||||
If you're a **RHEL/CentOS 7** user, you can install ripgrep from [copr](https://copr.fedorainfracloud.org/coprs/carlwgeorge/ripgrep/):
|
||||
|
||||
```
|
||||
$ sudo yum-config-manager --add-repo=https://copr.fedorainfracloud.org/coprs/carlwgeorge/ripgrep/repo/epel-7/carlwgeorge-ripgrep-epel-7.repo
|
||||
$ sudo yum install ripgrep
|
||||
```
|
||||
|
||||
If you're a **Nix** user, you can install `ripgrep` from
|
||||
If you're a **Nix** user, you can install ripgrep from
|
||||
[nixpkgs](https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/text/ripgrep/default.nix):
|
||||
|
||||
```
|
||||
$ nix-env --install ripgrep
|
||||
$ # (Or using the attribute name, which is also `ripgrep`.)
|
||||
$ # (Or using the attribute name, which is also ripgrep.)
|
||||
```
|
||||
|
||||
If you're an **Ubuntu** user, `ripgrep` can be installed from the `snap` store.
|
||||
If you're a **Debian** user (or a user of a Debian derivative like **Ubuntu**),
|
||||
then ripgrep can be installed using a binary `.deb` file provided in each
|
||||
[ripgrep release](https://github.com/BurntSushi/ripgrep/releases). Note that
|
||||
ripgrep is not in the official Debian or Ubuntu repositories.
|
||||
|
||||
```
|
||||
$ curl -LO https://github.com/BurntSushi/ripgrep/releases/download/0.8.0/ripgrep_0.8.0_amd64.deb
|
||||
$ sudo dpkg -i ripgrep_0.8.0_amd64.deb
|
||||
```
|
||||
|
||||
If you're an **Ubuntu** user, ripgrep can be installed from the `snap` store.
|
||||
* Note that if you are using `16.04 LTS` or later, snap is already installed.
|
||||
* For older versions you can install snap using
|
||||
[this guide](https://docs.snapcraft.io/core/install-ubuntu).
|
||||
|
||||
```
|
||||
sudo snap install rg
|
||||
$ sudo snap install rg
|
||||
```
|
||||
|
||||
If you're a **Rust programmer**, `ripgrep` can be installed with `cargo`.
|
||||
* Note that the minimum supported version of Rust for ripgrep is **1.17**,
|
||||
If you're a **Rust programmer**, ripgrep can be installed with `cargo`.
|
||||
* Note that the minimum supported version of Rust for ripgrep is **1.20**,
|
||||
although ripgrep may work with older versions.
|
||||
* Note that the binary may be bigger than expected because it contains debug
|
||||
symbols. This is intentional. To remove debug symbols and therefore reduce
|
||||
@@ -245,145 +273,15 @@ If you're a **Rust programmer**, `ripgrep` can be installed with `cargo`.
|
||||
$ cargo install ripgrep
|
||||
```
|
||||
|
||||
`ripgrep` isn't currently in any other package repositories.
|
||||
ripgrep isn't currently in any other package repositories.
|
||||
[I'd like to change that](https://github.com/BurntSushi/ripgrep/issues/10).
|
||||
|
||||
### Whirlwind tour
|
||||
|
||||
The command-line usage of `ripgrep` doesn't differ much from other tools that
|
||||
perform a similar function, so you probably already know how to use `ripgrep`.
|
||||
The full details can be found in `rg --help`, but let's go on a whirlwind tour.
|
||||
|
||||
`ripgrep` detects when its printing to a terminal, and will automatically
|
||||
colorize your output and show line numbers, just like The Silver Searcher.
|
||||
Coloring works on Windows too! Colors can be controlled more granularly with
|
||||
the `--color` flag.
|
||||
|
||||
One last thing before we get started: generally speaking, `ripgrep` assumes the
|
||||
input it is reading to be UTF-8. However, if ripgrep notices a file is encoded as
|
||||
UTF-16, then it will know how to search it. For other encodings, you'll need to
|
||||
explicitly specify them with the `-E/--encoding` flag.
|
||||
|
||||
To recursively search the current directory, while respecting all `.gitignore`
|
||||
files, ignore hidden files and directories and skip binary files:
|
||||
|
||||
```
|
||||
$ rg foobar
|
||||
```
|
||||
|
||||
The above command also respects all `.ignore` files, including in parent
|
||||
directories. `.ignore` files can be used when `.gitignore` files are
|
||||
insufficient. In all cases, `.ignore` patterns take precedence over
|
||||
`.gitignore`.
|
||||
|
||||
To ignore all ignore files, use `-u`. To additionally search hidden files
|
||||
and directories, use `-uu`. To additionally search binary files, use `-uuu`.
|
||||
(In other words, "search everything, dammit!") In particular, `rg -uuu` is
|
||||
similar to `grep -a -r`.
|
||||
|
||||
```
|
||||
$ rg -uu foobar # similar to `grep -r`
|
||||
$ rg -uuu foobar # similar to `grep -a -r`
|
||||
```
|
||||
|
||||
(Tip: If your ignore files aren't being adhered to like you expect, run your
|
||||
search with the `--debug` flag.)
|
||||
|
||||
Make the search case insensitive with `-i`, invert the search with `-v` or
|
||||
show the 2 lines before and after every search result with `-C2`.
|
||||
|
||||
Force all matches to be surrounded by word boundaries with `-w`.
|
||||
|
||||
Search and replace (find first and last names and swap them):
|
||||
|
||||
```
|
||||
$ rg '([A-Z][a-z]+)\s+([A-Z][a-z]+)' --replace '$2, $1'
|
||||
```
|
||||
|
||||
Named groups are supported:
|
||||
|
||||
```
|
||||
$ rg '(?P<first>[A-Z][a-z]+)\s+(?P<last>[A-Z][a-z]+)' --replace '$last, $first'
|
||||
```
|
||||
|
||||
Up the ante with full Unicode support, by matching any uppercase Unicode letter
|
||||
followed by any sequence of lowercase Unicode letters (good luck doing this
|
||||
with other search tools!):
|
||||
|
||||
```
|
||||
$ rg '(\p{Lu}\p{Ll}+)\s+(\p{Lu}\p{Ll}+)' --replace '$2, $1'
|
||||
```
|
||||
|
||||
Search only files matching a particular glob:
|
||||
|
||||
```
|
||||
$ rg foo -g 'README.*'
|
||||
```
|
||||
|
||||
<!--*-->
|
||||
|
||||
Or exclude files matching a particular glob:
|
||||
|
||||
```
|
||||
$ rg foo -g '!*.min.js'
|
||||
```
|
||||
|
||||
Search and return paths matching a particular glob (i.e., `-g` flag in ag/ack):
|
||||
|
||||
```
|
||||
$ rg -g 'doc*' --files
|
||||
```
|
||||
|
||||
Search only HTML and CSS files:
|
||||
|
||||
```
|
||||
$ rg -thtml -tcss foobar
|
||||
```
|
||||
|
||||
Search everything except for Javascript files:
|
||||
|
||||
```
|
||||
$ rg -Tjs foobar
|
||||
```
|
||||
|
||||
To see a list of types supported, run `rg --type-list`. To add a new type, use
|
||||
`--type-add`, which must be accompanied by a pattern for searching (`rg` won't
|
||||
persist your type settings):
|
||||
|
||||
```
|
||||
$ rg --type-add 'foo:*.{foo,foobar}' -tfoo bar
|
||||
```
|
||||
|
||||
The type `foo` will now match any file ending with the `.foo` or `.foobar`
|
||||
extensions.
|
||||
|
||||
### Regex syntax
|
||||
|
||||
The syntax supported is
|
||||
[documented as part of Rust's regex library](https://doc.rust-lang.org/regex/regex/index.html#syntax).
|
||||
|
||||
### Shell completions
|
||||
|
||||
Shell completion files are included in the release tarball for Bash, Fish, Zsh
|
||||
and PowerShell.
|
||||
|
||||
For **bash**, move `complete/rg.bash-completion` to `$XDG_CONFIG_HOME/bash_completion`
|
||||
or `/etc/bash_completion.d/`.
|
||||
|
||||
For **fish**, move `complete/rg.fish` to `$HOME/.config/fish/completions/`.
|
||||
|
||||
For **PowerShell**, add `. _rg.ps1` to your PowerShell
|
||||
[profile](https://technet.microsoft.com/en-us/library/bb613488(v=vs.85).aspx)
|
||||
(note the leading period). If the `_rg.ps1` file is not on your `PATH`, do
|
||||
`. /path/to/_rg.ps1` instead.
|
||||
|
||||
For **zsh**, move `complete/_rg` to one of your `$fpath` directories.
|
||||
|
||||
### Building
|
||||
|
||||
`ripgrep` is written in Rust, so you'll need to grab a
|
||||
ripgrep is written in Rust, so you'll need to grab a
|
||||
[Rust installation](https://www.rust-lang.org/) in order to compile it.
|
||||
`ripgrep` compiles with Rust 1.17 (stable) or newer. Building is easy:
|
||||
ripgrep compiles with Rust 1.20 (stable) or newer. Building is easy:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/BurntSushi/ripgrep
|
||||
@@ -393,8 +291,8 @@ $ ./target/release/rg --version
|
||||
0.1.3
|
||||
```
|
||||
|
||||
If you have a Rust nightly compiler, then you can enable optional SIMD
|
||||
acceleration like so:
|
||||
If you have a Rust nightly compiler and a recent Intel CPU, then you can enable
|
||||
optional SIMD acceleration like so:
|
||||
|
||||
```
|
||||
RUSTFLAGS="-C target-cpu=native" cargo build --release --features 'simd-accel avx-accel'
|
||||
@@ -403,144 +301,14 @@ RUSTFLAGS="-C target-cpu=native" cargo build --release --features 'simd-accel av
|
||||
If your machine doesn't support AVX instructions, then simply remove
|
||||
`avx-accel` from the features list. Similarly for SIMD.
|
||||
|
||||
|
||||
### Running tests
|
||||
|
||||
`ripgrep` is relatively well-tested, including both unit tests and integration
|
||||
ripgrep is relatively well-tested, including both unit tests and integration
|
||||
tests. To run the full test suite, use:
|
||||
|
||||
```
|
||||
$ cargo test
|
||||
$ cargo test --all
|
||||
```
|
||||
|
||||
from the repository root.
|
||||
|
||||
### Tips
|
||||
|
||||
#### Windows Powershell
|
||||
|
||||
##### Powershell Profile
|
||||
|
||||
To customize powershell on start-up, there is a special powershell script that has to be created.
|
||||
In order to find its location, type `$profile`
|
||||
See [more](https://technet.microsoft.com/en-us/library/bb613488(v=vs.85).aspx) for profile details.
|
||||
|
||||
Any powershell code in this file gets evaluated at the start of console.
|
||||
This way you can have own aliases to be created at start.
|
||||
|
||||
##### Setup function alias
|
||||
|
||||
Often you can find a need to make alias for the favourite utility.
|
||||
|
||||
But powershell function aliases do not behave like your typical linux shell alias.
|
||||
|
||||
You always need to propagate arguments and **Stdin** input.
|
||||
But it cannot be done simply as `function grep() { $input | rg.exe --hidden $args }`
|
||||
|
||||
Use below example as reference to how setup alias in powershell.
|
||||
|
||||
```powershell
|
||||
function grep {
|
||||
$count = @($input).Count
|
||||
$input.Reset()
|
||||
|
||||
if ($count) {
|
||||
$input | rg.exe --hidden $args
|
||||
}
|
||||
else {
|
||||
rg.exe --hidden $args
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Powershell special variables:
|
||||
* input - is powershell **Stdin** object that allows you to access its content.
|
||||
* args - is array of arguments passed to this function.
|
||||
|
||||
This alias checks whether there is **Stdin** input and propagates only if there is some lines.
|
||||
Otherwise empty `$input` will make powershell to trigger `rg` to search empty **Stdin**
|
||||
|
||||
##### Piping non-ASCII content to ripgrep
|
||||
|
||||
When piping input into native executables in PowerShell, the encoding of the
|
||||
input is controlled by the `$OutputEncoding` variable. By default, this is set
|
||||
to US-ASCII, and any characters in the pipeline that don't have encodings in
|
||||
US-ASCII are converted to `?` (question mark) characters.
|
||||
|
||||
To change this setting, set `$OutputEncoding` to a different encoding, as
|
||||
represented by a .NET encoding object. Some common examples are below. The
|
||||
value of this variable is reset when PowerShell restarts, so to make this
|
||||
change take effect every time PowerShell is started add a line setting the
|
||||
variable into your PowerShell profile.
|
||||
|
||||
Example `$OutputEncoding` settings:
|
||||
* UTF-8 without BOM: `$OutputEncoding = [System.Text.UTF8Encoding]::new()`
|
||||
* The console's output encoding:
|
||||
`$OutputEncoding = [System.Console]::OutputEncoding`
|
||||
|
||||
If you continue to have encoding problems, you can also force the encoding
|
||||
that the console will use for printing to UTF-8 with
|
||||
`[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8`. This
|
||||
will also reset when PowerShell is restarted, so you can add that line
|
||||
to your profile as well if you want to make the setting permanent.
|
||||
|
||||
#### How do I make the output look like ag's?
|
||||
|
||||
Use the `--colors` flag, like so:
|
||||
|
||||
rg --colors line:fg:yellow \
|
||||
--colors line:style:bold \
|
||||
--colors path:fg:green \
|
||||
--colors path:style:bold \
|
||||
--colors match:fg:black \
|
||||
--colors match:bg:yellow \
|
||||
--colors match:style:nobold \
|
||||
foo
|
||||
|
||||
### Known issues
|
||||
|
||||
#### I just hit Ctrl+C in the middle of ripgrep's output and now my terminal's foreground color is wrong!
|
||||
|
||||
Type in `color` in cmd.exe (Command Prompt) and `echo -ne "\033[0m"` on Unix
|
||||
to restore your original foreground color.
|
||||
|
||||
In PowerShell, you can add the following code to your profile which will
|
||||
restore the original foreground color when `Reset-ForegroundColor` is called.
|
||||
Including the `Set-Alias` line will allow you to call it with simply `color`.
|
||||
|
||||
```powershell
|
||||
$OrigFgColor = $Host.UI.RawUI.ForegroundColor
|
||||
function Reset-ForegroundColor {
|
||||
$Host.UI.RawUI.ForegroundColor = $OrigFgColor
|
||||
}
|
||||
Set-Alias -Name color -Value Reset-ForegroundColor
|
||||
```
|
||||
|
||||
PR [#187](https://github.com/BurntSushi/ripgrep/pull/187) fixed this, and it
|
||||
was later deprecated in
|
||||
[#281](https://github.com/BurntSushi/ripgrep/issues/281). A full explanation is
|
||||
available [here][msys issue explanation].
|
||||
|
||||
[msys issue explanation]: https://github.com/BurntSushi/ripgrep/issues/281#issuecomment-269093893
|
||||
|
||||
#### When I run `rg` it executes some other command!
|
||||
|
||||
It's likely that you have a shell alias or even another tool called `rg` which
|
||||
is interfering with `ripgrep` — run `which rg` to see what it is.
|
||||
|
||||
(Notably, the `rails` plug-in for
|
||||
[Oh My Zsh](https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins#rails) sets
|
||||
up an `rg` alias for `rails generate`.)
|
||||
|
||||
Problems like this can be resolved in one of several ways:
|
||||
|
||||
* If you're using the OMZ `rails` plug-in, disable it by editing the `plugins`
|
||||
array in your zsh configuration.
|
||||
* Temporarily bypass an existing `rg` alias by calling `ripgrep` as
|
||||
`command rg`, `\rg`, or `'rg'`.
|
||||
* Temporarily bypass an existing alias or another tool named `rg` by calling
|
||||
`ripgrep` by its full path (e.g., `/usr/bin/rg` or `/usr/local/bin/rg`).
|
||||
* Permanently disable an existing `rg` alias by adding `unalias rg` to the
|
||||
bottom of your shell configuration file (e.g., `.bash_profile` or `.zshrc`).
|
||||
* Give `ripgrep` its own alias that doesn't conflict with other tools/aliases by
|
||||
adding a line like the following to the bottom of your shell configuration
|
||||
file: `alias ripgrep='command rg'`
|
||||
|
162
build.rs
162
build.rs
@@ -4,23 +4,181 @@ extern crate clap;
|
||||
extern crate lazy_static;
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{self, Read, Write};
|
||||
use std::path::Path;
|
||||
use std::process;
|
||||
|
||||
use clap::Shell;
|
||||
|
||||
use app::{RGArg, RGArgKind};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[path = "src/app.rs"]
|
||||
mod app;
|
||||
|
||||
fn main() {
|
||||
// OUT_DIR is set by Cargo and it's where any additional build artifacts
|
||||
// are written.
|
||||
let outdir = match env::var_os("OUT_DIR") {
|
||||
None => return,
|
||||
Some(outdir) => outdir,
|
||||
None => {
|
||||
eprintln!(
|
||||
"OUT_DIR environment variable not defined. \
|
||||
Please file a bug: \
|
||||
https://github.com/BurntSushi/ripgrep/issues/new");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
fs::create_dir_all(&outdir).unwrap();
|
||||
|
||||
let stamp_path = Path::new(&outdir).join("ripgrep-stamp");
|
||||
if let Err(err) = File::create(&stamp_path) {
|
||||
panic!("failed to write {}: {}", stamp_path.display(), err);
|
||||
}
|
||||
if let Err(err) = generate_man_page(&outdir) {
|
||||
eprintln!("failed to generate man page: {}", err);
|
||||
}
|
||||
|
||||
// Use clap to build completion files.
|
||||
let mut app = app::app();
|
||||
app.gen_completions("rg", Shell::Bash, &outdir);
|
||||
app.gen_completions("rg", Shell::Fish, &outdir);
|
||||
app.gen_completions("rg", Shell::PowerShell, &outdir);
|
||||
// Note that we do not use clap's support for zsh. Instead, zsh completions
|
||||
// are manually maintained in `complete/_rg`.
|
||||
|
||||
// Make the current git hash available to the build.
|
||||
if let Some(rev) = git_revision_hash() {
|
||||
println!("cargo:rustc-env=RIPGREP_BUILD_GIT_HASH={}", rev);
|
||||
}
|
||||
}
|
||||
|
||||
fn git_revision_hash() -> Option<String> {
|
||||
let result = process::Command::new("git")
|
||||
.args(&["rev-parse", "--short=10", "HEAD"])
|
||||
.output();
|
||||
result.ok().and_then(|output| {
|
||||
let v = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
if v.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(v)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_man_page<P: AsRef<Path>>(outdir: P) -> io::Result<()> {
|
||||
// If asciidoc isn't installed, then don't do anything.
|
||||
if let Err(err) = process::Command::new("a2x").output() {
|
||||
eprintln!("Could not run 'a2x' binary, skipping man page generation.");
|
||||
eprintln!("Error from running 'a2x': {}", err);
|
||||
return Ok(());
|
||||
}
|
||||
// 1. Read asciidoc template.
|
||||
// 2. Interpolate template with auto-generated docs.
|
||||
// 3. Save interpolation to disk.
|
||||
// 4. Use a2x (part of asciidoc) to convert to man page.
|
||||
let outdir = outdir.as_ref();
|
||||
let cwd = env::current_dir()?;
|
||||
let tpl_path = cwd.join("doc").join("rg.1.txt.tpl");
|
||||
let txt_path = outdir.join("rg.1.txt");
|
||||
|
||||
let mut tpl = String::new();
|
||||
File::open(&tpl_path)?.read_to_string(&mut tpl)?;
|
||||
tpl = tpl.replace("{OPTIONS}", &formatted_options()?);
|
||||
|
||||
let githash = git_revision_hash();
|
||||
let githash = githash.as_ref().map(|x| &**x);
|
||||
tpl = tpl.replace("{VERSION}", &app::long_version(githash));
|
||||
|
||||
File::create(&txt_path)?.write_all(tpl.as_bytes())?;
|
||||
let result = process::Command::new("a2x")
|
||||
.arg("--no-xmllint")
|
||||
.arg("--doctype").arg("manpage")
|
||||
.arg("--format").arg("manpage")
|
||||
.arg(&txt_path)
|
||||
.spawn()?
|
||||
.wait()?;
|
||||
if !result.success() {
|
||||
let msg = format!("'a2x' failed with exit code {:?}", result.code());
|
||||
return Err(ioerr(msg));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn formatted_options() -> io::Result<String> {
|
||||
let mut args = app::all_args_and_flags();
|
||||
args.sort_by(|x1, x2| x1.name.cmp(&x2.name));
|
||||
|
||||
let mut formatted = vec![];
|
||||
for arg in args {
|
||||
if arg.hidden {
|
||||
continue;
|
||||
}
|
||||
// ripgrep only has two positional arguments, and probably will only
|
||||
// ever have two positional arguments, so we just hardcode them into
|
||||
// the template.
|
||||
if let app::RGArgKind::Positional{..} = arg.kind {
|
||||
continue;
|
||||
}
|
||||
formatted.push(formatted_arg(&arg)?);
|
||||
}
|
||||
Ok(formatted.join("\n\n"))
|
||||
}
|
||||
|
||||
fn formatted_arg(arg: &RGArg) -> io::Result<String> {
|
||||
match arg.kind {
|
||||
RGArgKind::Positional{..} => panic!("unexpected positional argument"),
|
||||
RGArgKind::Switch { long, short, multiple } => {
|
||||
let mut out = vec![];
|
||||
|
||||
let mut header = format!("--{}", long);
|
||||
if let Some(short) = short {
|
||||
header = format!("-{}, {}", short, header);
|
||||
}
|
||||
if multiple {
|
||||
header = format!("*{}* ...::", header);
|
||||
} else {
|
||||
header = format!("*{}*::", header);
|
||||
}
|
||||
writeln!(out, "{}", header)?;
|
||||
writeln!(out, "{}", formatted_doc_txt(arg)?)?;
|
||||
|
||||
Ok(String::from_utf8(out).unwrap())
|
||||
}
|
||||
RGArgKind::Flag { long, short, value_name, multiple, .. } => {
|
||||
let mut out = vec![];
|
||||
|
||||
let mut header = format!("--{}", long);
|
||||
if let Some(short) = short {
|
||||
header = format!("-{}, {}", short, header);
|
||||
}
|
||||
if multiple {
|
||||
header = format!("*{}* _{}_ ...::", header, value_name);
|
||||
} else {
|
||||
header = format!("*{}* _{}_::", header, value_name);
|
||||
}
|
||||
writeln!(out, "{}", header)?;
|
||||
writeln!(out, "{}", formatted_doc_txt(arg)?)?;
|
||||
|
||||
Ok(String::from_utf8(out).unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn formatted_doc_txt(arg: &RGArg) -> io::Result<String> {
|
||||
let paragraphs: Vec<&str> = arg.doc_long.split("\n\n").collect();
|
||||
if paragraphs.is_empty() {
|
||||
return Err(ioerr(format!("missing docs for --{}", arg.name)));
|
||||
}
|
||||
let first = format!(" {}", paragraphs[0].replace("\n", "\n "));
|
||||
if paragraphs.len() == 1 {
|
||||
return Ok(first);
|
||||
}
|
||||
Ok(format!("{}\n+\n{}", first, paragraphs[1..].join("\n+\n")))
|
||||
}
|
||||
|
||||
fn ioerr(msg: String) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, msg)
|
||||
}
|
||||
|
57
ci/before_deploy.sh
Normal file → Executable file
57
ci/before_deploy.sh
Normal file → Executable file
@@ -1,40 +1,55 @@
|
||||
# `before_deploy` phase: here we package the build artifacts
|
||||
#!/bin/bash
|
||||
|
||||
# package the build artifacts
|
||||
|
||||
set -ex
|
||||
|
||||
. $(dirname $0)/utils.sh
|
||||
. "$(dirname $0)/utils.sh"
|
||||
|
||||
# Generate artifacts for release
|
||||
mk_artifacts() {
|
||||
if is_ssse3_target; then
|
||||
RUSTFLAGS="-C target-feature=+ssse3" \
|
||||
cargo build --target $TARGET --release --features simd-accel
|
||||
cargo build --target "$TARGET" --release --features simd-accel
|
||||
else
|
||||
cargo build --target $TARGET --release
|
||||
cargo build --target "$TARGET" --release
|
||||
fi
|
||||
}
|
||||
|
||||
mk_tarball() {
|
||||
# create a "staging" directory
|
||||
local td=$(mktempd)
|
||||
local out_dir=$(pwd)
|
||||
local name="${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}"
|
||||
# When cross-compiling, use the right `strip` tool on the binary.
|
||||
local gcc_prefix="$(gcc_prefix)"
|
||||
mkdir "${td:?}/${name}"
|
||||
mkdir "$td/$name/complete"
|
||||
# Create a temporary dir that contains our staging area.
|
||||
# $tmpdir/$name is what eventually ends up as the deployed archive.
|
||||
local tmpdir="$(mktemp -d)"
|
||||
local name="${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}"
|
||||
local staging="$tmpdir/$name"
|
||||
mkdir -p "$staging"/{complete,doc}
|
||||
# The deployment directory is where the final archive will reside.
|
||||
# This path is known by the .travis.yml configuration.
|
||||
local out_dir="$(pwd)/deployment"
|
||||
mkdir -p "$out_dir"
|
||||
# Find the correct (most recent) Cargo "out" directory. The out directory
|
||||
# contains shell completion files and the man page.
|
||||
local cargo_out_dir="$(cargo_out_dir "target/$TARGET")"
|
||||
|
||||
cp target/$TARGET/release/rg "$td/$name/rg"
|
||||
${gcc_prefix}strip "$td/$name/rg"
|
||||
cp {doc/rg.1,README.md,UNLICENSE,COPYING,LICENSE-MIT} "$td/$name/"
|
||||
cp \
|
||||
target/$TARGET/release/build/ripgrep-*/out/{rg.bash-completion,rg.fish,_rg.ps1} \
|
||||
"$td/$name/complete/"
|
||||
cp complete/_rg "$td/$name/complete/"
|
||||
# Copy the ripgrep binary and strip it.
|
||||
cp "target/$TARGET/release/rg" "$staging/rg"
|
||||
"${gcc_prefix}strip" "$staging/rg"
|
||||
# Copy the licenses and README.
|
||||
cp {README.md,UNLICENSE,COPYING,LICENSE-MIT} "$staging/"
|
||||
# Copy documentation and man page.
|
||||
cp {CHANGELOG.md,FAQ.md,GUIDE.md} "$staging/doc/"
|
||||
if command -V a2x 2>&1 > /dev/null; then
|
||||
# The man page should only exist if we have asciidoc installed.
|
||||
cp "$cargo_out_dir/rg.1" "$staging/doc/"
|
||||
fi
|
||||
# Copy shell completion files.
|
||||
cp "$cargo_out_dir"/{rg.bash,rg.fish,_rg.ps1} "$staging/complete/"
|
||||
cp complete/_rg "$staging/complete/"
|
||||
|
||||
pushd $td
|
||||
tar czf "$out_dir/$name.tar.gz" *
|
||||
popd
|
||||
rm -r $td
|
||||
(cd "$tmpdir" && tar czf "$out_dir/$name.tar.gz" "$name")
|
||||
rm -rf "$tmpdir"
|
||||
}
|
||||
|
||||
main() {
|
||||
|
47
ci/install.sh
Normal file → Executable file
47
ci/install.sh
Normal file → Executable file
@@ -1,43 +1,46 @@
|
||||
# `install` phase: install stuff needed for the `script` phase
|
||||
#!/bin/bash
|
||||
|
||||
# install stuff needed for the `script` phase
|
||||
|
||||
# Where rustup gets installed.
|
||||
export PATH="$PATH:$HOME/.cargo/bin"
|
||||
|
||||
set -ex
|
||||
|
||||
. $(dirname $0)/utils.sh
|
||||
|
||||
install_c_toolchain() {
|
||||
case $TARGET in
|
||||
aarch64-unknown-linux-gnu)
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross
|
||||
;;
|
||||
*)
|
||||
# For other targets, this is handled by addons.apt.packages in .travis.yml
|
||||
;;
|
||||
esac
|
||||
}
|
||||
. "$(dirname $0)/utils.sh"
|
||||
|
||||
install_rustup() {
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain=$TRAVIS_RUST_VERSION
|
||||
|
||||
curl https://sh.rustup.rs -sSf \
|
||||
| sh -s -- -y --default-toolchain="$TRAVIS_RUST_VERSION"
|
||||
rustc -V
|
||||
cargo -V
|
||||
}
|
||||
|
||||
install_standard_crates() {
|
||||
install_targets() {
|
||||
if [ $(host) != "$TARGET" ]; then
|
||||
rustup target add $TARGET
|
||||
fi
|
||||
}
|
||||
|
||||
install_osx_dependencies() {
|
||||
if ! is_osx; then
|
||||
return
|
||||
fi
|
||||
|
||||
brew install asciidoc
|
||||
}
|
||||
|
||||
configure_cargo() {
|
||||
local prefix=$(gcc_prefix)
|
||||
if [ -n "${prefix}" ]; then
|
||||
local gcc_suffix=
|
||||
test -n "${GCC_VERSION}" && gcc_suffix="-${GCC_VERSION}" || :
|
||||
if [ -n "$GCC_VERSION" ]; then
|
||||
gcc_suffix="-$GCC_VERSION"
|
||||
fi
|
||||
local gcc="${prefix}gcc${gcc_suffix}"
|
||||
|
||||
# information about the cross compiler
|
||||
${gcc} -v
|
||||
"${gcc}" -v
|
||||
|
||||
# tell cargo which linker to use for cross compilation
|
||||
mkdir -p .cargo
|
||||
@@ -49,12 +52,10 @@ EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
install_c_toolchain
|
||||
install_osx_dependencies
|
||||
install_rustup
|
||||
install_standard_crates
|
||||
install_targets
|
||||
configure_cargo
|
||||
|
||||
# TODO if you need to install extra stuff add it here
|
||||
}
|
||||
|
||||
main
|
||||
|
54
ci/script.sh
Normal file → Executable file
54
ci/script.sh
Normal file → Executable file
@@ -1,30 +1,46 @@
|
||||
# `script` phase: you usually build, test and generate docs in this phase
|
||||
#!/bin/bash
|
||||
|
||||
# build, test and generate docs in this phase
|
||||
|
||||
set -ex
|
||||
|
||||
. $(dirname $0)/utils.sh
|
||||
|
||||
# NOTE Workaround for rust-lang/rust#31907 - disable doc tests when cross compiling
|
||||
# This has been fixed in the nightly channel but it would take a while to reach the other channels
|
||||
disable_cross_doctests() {
|
||||
if [ $(host) != "$TARGET" ] && [ "$TRAVIS_RUST_VERSION" = "stable" ]; then
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
brew install gnu-sed --default-names
|
||||
fi
|
||||
find src -name '*.rs' -type f | xargs sed -i -e 's:\(//.\s*```\):\1 ignore,:g'
|
||||
fi
|
||||
}
|
||||
. "$(dirname $0)/utils.sh"
|
||||
|
||||
main() {
|
||||
# disable_cross_doctests
|
||||
cargo build --target "${TARGET}" --verbose --all
|
||||
if [ "$(architecture)" = "amd64" ] || [ "$(architecture)" = "i386" ]; then
|
||||
cargo test --target "${TARGET}" --verbose --all
|
||||
"$( dirname "${0}" )/test_complete.sh"
|
||||
# Test a normal debug build.
|
||||
cargo build --target "$TARGET" --verbose --all
|
||||
|
||||
# Show the output of the most recent build.rs stderr.
|
||||
set +x
|
||||
stderr="$(find "target/$TARGET/debug" -name stderr -print0 | xargs -0 ls -t | head -n1)"
|
||||
if [ -s "$stderr" ]; then
|
||||
echo "===== $stderr ====="
|
||||
cat "$stderr"
|
||||
echo "====="
|
||||
fi
|
||||
set -x
|
||||
|
||||
# sanity check the file type
|
||||
file target/$TARGET/debug/rg
|
||||
file target/"$TARGET"/debug/rg
|
||||
|
||||
# Check that we've generated man page and other shell completions.
|
||||
outdir="$(cargo_out_dir "target/$TARGET/debug")"
|
||||
file "$outdir/rg.bash"
|
||||
file "$outdir/rg.fish"
|
||||
file "$outdir/_rg.ps1"
|
||||
file "$outdir/rg.1"
|
||||
|
||||
# Apparently tests don't work on arm, so just bail now. I guess we provide
|
||||
# ARM releases on a best effort basis?
|
||||
if is_arm; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Test that zsh completions are in sync with ripgrep's actual args.
|
||||
"$(dirname "${0}")/test_complete.sh"
|
||||
|
||||
# Run tests for ripgrep and all sub-crates.
|
||||
cargo test --target "$TARGET" --verbose --all
|
||||
}
|
||||
|
||||
main
|
||||
|
0
ci/sha256.sh
Normal file → Executable file
0
ci/sha256.sh
Normal file → Executable file
93
ci/utils.sh
93
ci/utils.sh
@@ -1,5 +1,19 @@
|
||||
mktempd() {
|
||||
echo $(mktemp -d 2>/dev/null || mktemp -d -t tmp)
|
||||
#!/bin/bash
|
||||
|
||||
# Various utility functions used through CI.
|
||||
|
||||
# Finds Cargo's `OUT_DIR` directory from the most recent build.
|
||||
#
|
||||
# This requires one parameter corresponding to the target directory
|
||||
# to search for the build output.
|
||||
cargo_out_dir() {
|
||||
# This works by finding the most recent stamp file, which is produced by
|
||||
# every ripgrep build.
|
||||
target_dir="$1"
|
||||
find "$target_dir" -name ripgrep-stamp -print0 \
|
||||
| xargs -0 ls -t \
|
||||
| head -n1 \
|
||||
| xargs dirname
|
||||
}
|
||||
|
||||
host() {
|
||||
@@ -13,33 +27,8 @@ host() {
|
||||
esac
|
||||
}
|
||||
|
||||
gcc_prefix() {
|
||||
case "$TARGET" in
|
||||
aarch64-unknown-linux-gnu)
|
||||
echo aarch64-linux-gnu-
|
||||
;;
|
||||
arm*-gnueabihf)
|
||||
echo arm-linux-gnueabihf-
|
||||
;;
|
||||
*)
|
||||
return
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
dobin() {
|
||||
[ -z $MAKE_DEB ] && die 'dobin: $MAKE_DEB not set'
|
||||
[ $# -lt 1 ] && die "dobin: at least one argument needed"
|
||||
|
||||
local f prefix=$(gcc_prefix)
|
||||
for f in "$@"; do
|
||||
install -m0755 $f $dtd/debian/usr/bin/
|
||||
${prefix}strip -s $dtd/debian/usr/bin/$(basename $f)
|
||||
done
|
||||
}
|
||||
|
||||
architecture() {
|
||||
case ${TARGET:?} in
|
||||
case "$TARGET" in
|
||||
x86_64-*)
|
||||
echo amd64
|
||||
;;
|
||||
@@ -55,10 +44,48 @@ architecture() {
|
||||
esac
|
||||
}
|
||||
|
||||
is_ssse3_target() {
|
||||
case "${TARGET}" in
|
||||
i686-unknown-netbsd) return 1 ;; # i686-unknown-netbsd - SSE2
|
||||
i686*|x86_64*) return 0 ;;
|
||||
gcc_prefix() {
|
||||
case "$(architecture)" in
|
||||
armhf)
|
||||
echo arm-linux-gnueabihf-
|
||||
;;
|
||||
*)
|
||||
return
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_ssse3_target() {
|
||||
case "$(architecture)" in
|
||||
amd64) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_x86() {
|
||||
case "$(architecture)" in
|
||||
amd64|i386) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_arm() {
|
||||
case "$(architecture)" in
|
||||
armhf) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_linux() {
|
||||
case "$TRAVIS_OS_NAME" in
|
||||
linux) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_osx() {
|
||||
case "$TRAVIS_OS_NAME" in
|
||||
osx) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
8
compile
8
compile
@@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# export RUSTFLAGS="-C target-feature=+ssse3"
|
||||
# cargo build --release --features 'simd-accel'
|
||||
|
||||
export RUSTFLAGS="-C target-cpu=native"
|
||||
cargo build --release --features 'simd-accel avx-accel'
|
||||
# cargo build --release --features 'simd-accel avx-accel' --target x86_64-unknown-linux-musl
|
@@ -54,6 +54,7 @@ _rg() {
|
||||
'(--mmap --no-mmap)--mmap[search using memory maps when possible]'
|
||||
'(-H --with-filename --no-filename)--no-filename[suppress all file names]'
|
||||
"(-p --heading --pretty --vimgrep)--no-heading[don't group matches by file name]"
|
||||
"--no-config[don't load configuration files]"
|
||||
"(--no-ignore-parent)--no-ignore[don't respect ignore files]"
|
||||
"--no-ignore-parent[don't respect ignore files in parent directories]"
|
||||
"--no-ignore-vcs[don't respect version control ignore files]"
|
||||
@@ -124,7 +125,7 @@ _rg() {
|
||||
|
||||
[[ "${state}" == 'style' ]] &&
|
||||
_values -S ':' 'style value' \
|
||||
bold nobold intense nointense && return 0
|
||||
bold nobold intense nointense underline nounderline && return 0
|
||||
;;
|
||||
|
||||
typespec)
|
||||
|
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
pandoc -s -f markdown-smart -t man rg.1.md -o rg.1
|
||||
sed -i.bak 's/\.TH.*/.TH "rg" "1"/g' rg.1
|
||||
rm -f rg.1.bak # BSD `sed` requires the creation of a back-up file
|
610
doc/rg.1
610
doc/rg.1
@@ -1,610 +0,0 @@
|
||||
.\" Automatically generated by Pandoc 2.0.6
|
||||
.\"
|
||||
.TH "rg" "1"
|
||||
.hy
|
||||
.SH NAME
|
||||
.PP
|
||||
rg \- recursively search current directory for lines matching a pattern
|
||||
.SH SYNOPSIS
|
||||
.PP
|
||||
rg [\f[I]OPTIONS\f[]] \f[I]PATTERN\f[] [\f[I]PATH\f[] ...]
|
||||
.PP
|
||||
rg [\f[I]OPTIONS\f[]] [\-e \f[I]PATTERN\f[] ...] [\-f \f[I]FILE\f[] ...]
|
||||
[\f[I]PATH\f[] ...]
|
||||
.PP
|
||||
rg [\f[I]OPTIONS\f[]] \-\-files [\f[I]PATH\f[] ...]
|
||||
.PP
|
||||
rg [\f[I]OPTIONS\f[]] \-\-type\-list
|
||||
.PP
|
||||
rg [\f[I]OPTIONS\f[]] \-\-help
|
||||
.PP
|
||||
rg [\f[I]OPTIONS\f[]] \-\-version
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
ripgrep (rg) combines the usability of The Silver Searcher (an ack
|
||||
clone) with the raw speed of grep.
|
||||
.PP
|
||||
ripgrep\[aq]s regex engine uses finite automata and guarantees linear
|
||||
time searching.
|
||||
Because of this, features like backreferences and arbitrary lookaround
|
||||
are not supported.
|
||||
.PP
|
||||
Note that 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.
|
||||
.PP
|
||||
Project home page: https://github.com/BurntSushi/ripgrep
|
||||
.SH POSITIONAL ARGUMENTS
|
||||
.TP
|
||||
.B \f[I]PATTERN\f[]
|
||||
A regular expression used for searching.
|
||||
To match a pattern beginning with a dash, use the \-e/\-\-regexp option.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \f[I]PATH\f[]
|
||||
A file or directory to search.
|
||||
Directories are searched recursively.
|
||||
Paths specified expicitly on the command line override glob and ignore
|
||||
rules.
|
||||
.RS
|
||||
.RE
|
||||
.SH COMMON OPTIONS
|
||||
.TP
|
||||
.B \-a, \-\-text
|
||||
Search binary files as if they were text.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-c, \-\-count
|
||||
Only show count of line matches for each file.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-color \f[I]WHEN\f[]
|
||||
Whether to use color in the output.
|
||||
Valid values are never, auto, always or ansi.
|
||||
The default is auto.
|
||||
When always is used, coloring is attempted based on your environment.
|
||||
When ansi is used, coloring is forcefully done using ANSI escape color
|
||||
codes.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-e, \-\-regexp \f[I]PATTERN\f[] ...
|
||||
Use PATTERN to search.
|
||||
This option can be provided multiple times, where all patterns given are
|
||||
searched.
|
||||
This is also useful when searching for patterns that start with a dash.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-F, \-\-fixed\-strings
|
||||
Treat the pattern as a literal string instead of a regular expression.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-g, \-\-glob \f[I]GLOB\f[] ...
|
||||
Include or exclude files for searching that match the given glob.
|
||||
This always overrides any other ignore logic if there is a conflict, but
|
||||
is otherwise applied in addition to ignore files (e.g., .gitignore or
|
||||
\&.ignore).
|
||||
Multiple glob flags may be used.
|
||||
Globbing rules match .gitignore globs.
|
||||
Precede a glob with a \[aq]!\[aq] to exclude it.
|
||||
.RS
|
||||
.PP
|
||||
The \-\-glob flag subsumes the functionality of both the \-\-include and
|
||||
\-\-exclude flags commonly found in other tools.
|
||||
.PP
|
||||
Values given to \-g must be quoted or your shell will expand them and
|
||||
result in unexpected behavior.
|
||||
.PP
|
||||
Combine with the \-\-files flag to return matched filenames (i.e., to
|
||||
replicate ack/ag\[aq]s \-g flag).
|
||||
For example:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
rg\ \-g\ \[aq]*.foo\[aq]\ \-\-files
|
||||
\f[]
|
||||
.fi
|
||||
.RE
|
||||
.TP
|
||||
.B \-h, \-\-help
|
||||
Show this usage message.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-i, \-\-ignore\-case
|
||||
Case insensitive search.
|
||||
Overridden by \-\-case\-sensitive.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-n, \-\-line\-number
|
||||
Show line numbers (1\-based).
|
||||
This is enabled by default at a tty.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-N, \-\-no\-line\-number
|
||||
Suppress line numbers.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-q, \-\-quiet
|
||||
Do not print anything to stdout.
|
||||
If a match is found in a file, stop searching that file.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-t, \-\-type \f[I]TYPE\f[] ...
|
||||
Only search files matching TYPE.
|
||||
Multiple type flags may be provided.
|
||||
Use the \-\-type\-list flag to list all available types.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-T, \-\-type\-not \f[I]TYPE\f[] ...
|
||||
Do not search files matching TYPE.
|
||||
Multiple not\-type flags may be provided.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-u, \-\-unrestricted ...
|
||||
Reduce the level of \[aq]smart\[aq] searching.
|
||||
A single \-u doesn\[aq]t respect .gitignore (etc.) files.
|
||||
Two \-u flags will search hidden files and directories.
|
||||
Three \-u flags will search binary files.
|
||||
\-uu is equivalent to \f[C]grep\ \-r\f[], and \-uuu is equivalent to
|
||||
\f[C]grep\ \-a\ \-r\f[].
|
||||
.RS
|
||||
.PP
|
||||
Note that the \-u flags are convenient aliases for other combinations of
|
||||
flags.
|
||||
\-u aliases \-\-no\-ignore.
|
||||
\-uu aliases \-\-no\-ignore \-\-hidden.
|
||||
\-uuu aliases \-\-no\-ignore \-\-hidden \-\-text.
|
||||
.RE
|
||||
.TP
|
||||
.B \-v, \-\-invert\-match
|
||||
Invert matching.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-w, \-\-word\-regexp
|
||||
Only show matches surrounded by word boundaries.
|
||||
This is equivalent to putting \\b before and after the search pattern.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-x, \-\-line\-regexp
|
||||
Only show matches surrounded by line boundaries.
|
||||
This is equivalent to putting ^...$ around the search pattern.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-z, \-\-search\-zip
|
||||
Search in compressed files.
|
||||
Currently gz, bz2, xz and lzma formats are supported.
|
||||
.RS
|
||||
.PP
|
||||
Note that ripgrep expects to find the decompression binaries for the
|
||||
respective formats in your system\[aq]s PATH for use with this flag.
|
||||
.RE
|
||||
.SH LESS COMMON OPTIONS
|
||||
.TP
|
||||
.B \-A, \-\-after\-context \f[I]NUM\f[]
|
||||
Show NUM lines after each match.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-B, \-\-before\-context \f[I]NUM\f[]
|
||||
Show NUM lines before each match.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-C, \-\-context \f[I]NUM\f[]
|
||||
Show NUM lines before and after each match.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-colors \f[I]SPEC\f[] ...
|
||||
This flag specifies color settings for use in the output.
|
||||
This flag may be provided multiple times.
|
||||
Settings are applied iteratively.
|
||||
Colors are limited to one of eight choices: red, blue, green, cyan,
|
||||
magenta, yellow, white and black.
|
||||
Styles are limited to nobold, bold, nointense or intense.
|
||||
.RS
|
||||
.PP
|
||||
The format of the flag is {type}:{attribute}:{value}.
|
||||
{type} should be one of path, line, column or match.
|
||||
{attribute} can be fg, bg or style.
|
||||
Value is either a color (for fg and bg) or a text style.
|
||||
A special format, {type}:none, will clear all color settings for {type}.
|
||||
.PP
|
||||
For example, the following command will change the match color to
|
||||
magenta and the background color for line numbers to yellow:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
rg\ \-\-colors\ \[aq]match:fg:magenta\[aq]\ \-\-colors\ \[aq]line:bg:yellow\[aq]\ foo.
|
||||
\f[]
|
||||
.fi
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-column
|
||||
Show column numbers (1 based) in output.
|
||||
This only shows the column numbers for the first match on each line.
|
||||
Note that this doesn\[aq]t try to account for Unicode.
|
||||
One byte is equal to one column.
|
||||
This implies \-\-line\-number.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-context\-separator \f[I]SEPARATOR\f[]
|
||||
The string to use when separating non\-continuous context lines.
|
||||
Escape sequences may be used.
|
||||
[default: \-\-]
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-debug
|
||||
Show debug messages.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-E, \-\-encoding \f[I]ENCODING\f[]
|
||||
Specify the text encoding that ripgrep will use on all files searched.
|
||||
The default value is \[aq]auto\[aq], which will cause ripgrep to do a
|
||||
best effort automatic detection of encoding on a per\-file basis.
|
||||
Other supported values can be found in the list of labels here:
|
||||
https://encoding.spec.whatwg.org/#concept\-encoding\-get
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-f, \-\-file \f[I]FILE\f[] ...
|
||||
Search for patterns from the given file, with one pattern per line.
|
||||
When this flag is used or multiple times or in combination with the
|
||||
\-e/\-\-regexp flag, then all patterns provided are searched.
|
||||
Empty pattern lines will match all input lines, and the newline is not
|
||||
counted as part of the pattern.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-files
|
||||
Print each file that would be searched (but don\[aq]t search).
|
||||
.RS
|
||||
.PP
|
||||
Combine with the \-g flag to return matched paths, for example:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
rg\ \-g\ \[aq]*.foo\[aq]\ \-\-files
|
||||
\f[]
|
||||
.fi
|
||||
.RE
|
||||
.TP
|
||||
.B \-l, \-\-files\-with\-matches
|
||||
Only show path of each file with matches.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-files\-without\-match
|
||||
Only show path of each file with no matches.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-H, \-\-with\-filename
|
||||
Display the file name for matches.
|
||||
This is the default when more than one file is searched.
|
||||
If \-\-heading is enabled, the file name will be shown above clusters of
|
||||
matches from each file; otherwise, the file name will be shown on each
|
||||
match.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-no\-filename
|
||||
Never show the filename for a match.
|
||||
This is the default when one file is searched.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-heading
|
||||
Show the file name above clusters of matches from each file instead of
|
||||
showing the file name for every match.
|
||||
This is the default mode at a tty.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-no\-heading
|
||||
Don\[aq]t group matches by each file.
|
||||
If \-H/\-\-with\-filename is enabled, then file names will be shown for
|
||||
every line matched.
|
||||
This is the default mode when not at a tty.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-hidden
|
||||
Search hidden directories and files.
|
||||
(Hidden directories and files are skipped by default.)
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-iglob \f[I]GLOB\f[] ...
|
||||
Include or exclude files/directories case insensitively.
|
||||
This always overrides any other ignore logic if there is a conflict, but
|
||||
is otherwise applied in addition to ignore files (e.g., .gitignore or
|
||||
\&.ignore).
|
||||
Multiple glob flags may be used.
|
||||
Globbing rules match .gitignore globs.
|
||||
Precede a glob with a \[aq]!\[aq] to exclude it.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-ignore\-file \f[I]FILE\f[] ...
|
||||
Specify additional ignore files for filtering file paths.
|
||||
Ignore files should be in the gitignore format and are matched relative
|
||||
to the current working directory.
|
||||
These ignore files have lower precedence than all other ignore files.
|
||||
When specifying multiple ignore files, earlier files have lower
|
||||
precedence than later files.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-L, \-\-follow
|
||||
Follow symlinks.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-line\-number\-width \f[I]NUM\f[]
|
||||
Specify a width for the displayed line number.
|
||||
If number of digits in the line number is less than this number, it is
|
||||
left padded with spaces.
|
||||
Note: This setting has no effect if \-\-no\-line\-number is enabled.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-M, \-\-max\-columns \f[I]NUM\f[]
|
||||
Don\[aq]t print lines longer than this limit in bytes.
|
||||
Longer lines are omitted, and only the number of matches in that line is
|
||||
printed.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-m, \-\-max\-count \f[I]NUM\f[]
|
||||
Limit the number of matching lines per file searched to NUM.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-max\-filesize \f[I]NUM\f[]+\f[I]SUFFIX\f[]?
|
||||
Ignore files larger than \f[I]NUM\f[] in size.
|
||||
Directories will never be ignored.
|
||||
.RS
|
||||
.PP
|
||||
\f[I]SUFFIX\f[] is optional and may be one of K, M or G.
|
||||
These correspond to kilobytes, megabytes and gigabytes respectively.
|
||||
If omitted the input is treated as bytes.
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-maxdepth \f[I]NUM\f[]
|
||||
Descend at most NUM directories below the command line arguments.
|
||||
A value of zero searches only the starting\-points themselves.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-mmap
|
||||
Search using memory maps when possible.
|
||||
This is enabled by default when ripgrep thinks it will be faster.
|
||||
(Note that mmap searching doesn\[aq]t currently support the various
|
||||
context related options.)
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-no\-messages
|
||||
Suppress all error messages.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-no\-mmap
|
||||
Never use memory maps, even when they might be faster.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-no\-ignore
|
||||
Don\[aq]t respect ignore files (.gitignore, .ignore, etc.) This implies
|
||||
\-\-no\-ignore\-parent.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-no\-ignore\-parent
|
||||
Don\[aq]t respect ignore files in parent directories.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-no\-ignore\-vcs
|
||||
Don\[aq]t respect version control ignore files (e.g., .gitignore).
|
||||
Note that .ignore files will continue to be respected.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-0, \-\-null
|
||||
Whenever a file name is printed, follow it with a NUL byte.
|
||||
This includes printing filenames before matches, and when printing a
|
||||
list of matching files such as with \-\-count, \-\-files\-with\-matches
|
||||
and \-\-files.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-o, \-\-only\-matching
|
||||
Print only the matched (non\-empty) parts of a matching line, with each
|
||||
such part on a separate output line.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-passthru, \-\-passthrough
|
||||
Show both matching and non\-matching lines.
|
||||
This option cannot be used with \-\-only\-matching or \-\-replace.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-path\-separator \f[I]SEPARATOR\f[]
|
||||
The path separator to use when printing file paths.
|
||||
This defaults to your platform\[aq]s path separator, which is / on Unix
|
||||
and \\ on Windows.
|
||||
This flag is intended for overriding the default when the environment
|
||||
demands it (e.g., cygwin).
|
||||
A path separator is limited to a single byte.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-p, \-\-pretty
|
||||
Alias for \-\-color=always \-\-heading \-\-line\-number.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-r, \-\-replace \f[I]ARG\f[]
|
||||
Replace every match with the string given when printing search results.
|
||||
Neither this flag nor any other flag will modify your files.
|
||||
.RS
|
||||
.PP
|
||||
Capture group indices (e.g., $5) and names (e.g., $foo) are supported in
|
||||
the replacement string.
|
||||
.PP
|
||||
Note that the replacement by default replaces each match, and NOT the
|
||||
entire line.
|
||||
To replace the entire line, you should match the entire line.
|
||||
For example, to emit only the first phone numbers in each line:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
rg\ \[aq]^.*([0\-9]{3}\-[0\-9]{3}\-[0\-9]{4}).*$\[aq]\ \-\-replace\ \[aq]$1\[aq]
|
||||
\f[]
|
||||
.fi
|
||||
.RE
|
||||
.TP
|
||||
.B \-s, \-\-case\-sensitive
|
||||
Search case sensitively (default).
|
||||
Overrides \-\-ignore\-case and \-\-smart\-case.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-S, \-\-smart\-case
|
||||
Search case insensitively if the pattern is all lowercase.
|
||||
Search case sensitively otherwise.
|
||||
This is overridden by either \-\-case\-sensitive or \-\-ignore\-case.
|
||||
Note: This feature is smart enough to treat simple classes like \\S as
|
||||
lowercase, but may not handle more complex syntax like \\p{Ll} as
|
||||
expected.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-sort\-files
|
||||
Sort results by file path.
|
||||
Note that this currently disables all parallelism and runs search in a
|
||||
single thread.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-j, \-\-threads \f[I]ARG\f[]
|
||||
The number of threads to use.
|
||||
0 means use the number of logical CPUs (capped at 12).
|
||||
[default: 0]
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-version
|
||||
Show the version number of ripgrep and exit.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-vimgrep
|
||||
Show results with every match on its own line, including line numbers
|
||||
and column numbers.
|
||||
With this option, a line with more than one match will be printed more
|
||||
than once.
|
||||
.RS
|
||||
.PP
|
||||
Recommended .vimrc configuration:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
\ \ set\ grepprg=rg\\\ \-\-vimgrep
|
||||
\ \ set\ grepformat^=%f:%l:%c:%m
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
Use :grep to grep for something, then :cn and :cp to navigate through
|
||||
the matches.
|
||||
.RE
|
||||
.SH FILE TYPE MANAGEMENT OPTIONS
|
||||
.TP
|
||||
.B \-\-type\-list
|
||||
Show all supported file types and their associated globs.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-type\-add \f[I]ARG\f[] ...
|
||||
Add a new glob for a particular file type.
|
||||
Only one glob can be added at a time.
|
||||
Multiple \-\-type\-add flags can be provided.
|
||||
Unless \-\-type\-clear is used, globs are added to any existing globs
|
||||
inside of ripgrep.
|
||||
Note that this must be passed to every invocation of rg.
|
||||
Type settings are NOT persisted.
|
||||
Example:
|
||||
.RS
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
\ \ rg\ \-\-type\-add\ \[aq]foo:*.foo\[aq]\ \-tfoo\ PATTERN
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
\-\-type\-add can also be used to include rules from other types with
|
||||
the special include directive.
|
||||
The include directive permits specifying one or more other type names
|
||||
(separated by a comma) that have been defined and its rules will
|
||||
automatically be imported into the type specified.
|
||||
For example, to create a type called src that matches C++, Python and
|
||||
Markdown files, one can use:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
\ \ \-\-type\-add\ \[aq]src:include:cpp,py,md\[aq]
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
Additional glob rules can still be added to the src type by using the
|
||||
\-\-type\-add flag again:
|
||||
.IP
|
||||
.nf
|
||||
\f[C]
|
||||
\ \ \-\-type\-add\ \[aq]src:include:cpp,py,md\[aq]\ \-\-type\-add\ \[aq]src:*.foo\[aq]
|
||||
\f[]
|
||||
.fi
|
||||
.PP
|
||||
Note that type names must consist only of Unicode letters or numbers.
|
||||
Punctuation characters are not allowed.
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-type\-clear \f[I]TYPE\f[] ...
|
||||
Clear the file type globs previously defined for TYPE.
|
||||
This only clears the default type definitions that are found inside of
|
||||
ripgrep.
|
||||
Note that this must be passed to every invocation of rg.
|
||||
.RS
|
||||
.RE
|
||||
.SH SHELL COMPLETION
|
||||
.PP
|
||||
Shell completion files are included in the release tarball for Bash,
|
||||
Fish, Zsh and PowerShell.
|
||||
.PP
|
||||
For \f[B]bash\f[], move \f[C]rg.bash\-completion\f[] to
|
||||
\f[C]$XDG_CONFIG_HOME/bash_completion\f[] or
|
||||
\f[C]/etc/bash_completion.d/\f[].
|
||||
.PP
|
||||
For \f[B]fish\f[], move \f[C]rg.fish\f[] to
|
||||
\f[C]$HOME/.config/fish/completions\f[].
|
403
doc/rg.1.md
403
doc/rg.1.md
@@ -1,403 +0,0 @@
|
||||
# NAME
|
||||
|
||||
rg - recursively search current directory for lines matching a pattern
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
rg [*OPTIONS*] *PATTERN* [*PATH* ...]
|
||||
|
||||
rg [*OPTIONS*] [-e *PATTERN* ...] [-f *FILE* ...] [*PATH* ...]
|
||||
|
||||
rg [*OPTIONS*] --files [*PATH* ...]
|
||||
|
||||
rg [*OPTIONS*] --type-list
|
||||
|
||||
rg [*OPTIONS*] --help
|
||||
|
||||
rg [*OPTIONS*] --version
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
ripgrep (rg) combines the usability of The Silver Searcher (an ack clone) with
|
||||
the raw speed of grep.
|
||||
|
||||
ripgrep's regex engine uses finite automata and guarantees linear time
|
||||
searching. Because of this, features like backreferences and arbitrary
|
||||
lookaround are not supported.
|
||||
|
||||
Note that 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.
|
||||
|
||||
Project home page: https://github.com/BurntSushi/ripgrep
|
||||
|
||||
# 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. Paths
|
||||
specified expicitly on the command line override glob and ignore rules.
|
||||
|
||||
# COMMON OPTIONS
|
||||
|
||||
-a, --text
|
||||
: Search binary files as if they were text.
|
||||
|
||||
-c, --count
|
||||
: Only show count of line matches for each file.
|
||||
|
||||
--color *WHEN*
|
||||
: Whether to use color in the output. Valid values are never, auto, always or
|
||||
ansi. The default is auto. When always is used, coloring is attempted based
|
||||
on your environment. When ansi is used, coloring is forcefully done using
|
||||
ANSI escape color codes.
|
||||
|
||||
-e, --regexp *PATTERN* ...
|
||||
: Use PATTERN to search. This option can be provided multiple times, where all
|
||||
patterns given are searched. This is also useful when searching for patterns
|
||||
that start with a dash.
|
||||
|
||||
-F, --fixed-strings
|
||||
: Treat the pattern as a literal string instead of a regular expression.
|
||||
|
||||
-g, --glob *GLOB* ...
|
||||
: Include or exclude files for searching that match the given glob. This always
|
||||
overrides any other ignore logic if there is a conflict, but is otherwise
|
||||
applied in addition to ignore files (e.g., .gitignore or .ignore). Multiple
|
||||
glob flags may be used. Globbing rules match .gitignore globs. Precede a
|
||||
glob with a '!' to exclude it.
|
||||
|
||||
The --glob flag subsumes the functionality of both the --include and
|
||||
--exclude flags commonly found in other tools.
|
||||
|
||||
Values given to -g must be quoted or your shell will expand them and result
|
||||
in unexpected behavior.
|
||||
|
||||
Combine with the --files flag to return matched filenames
|
||||
(i.e., to replicate ack/ag's -g flag). For example:
|
||||
|
||||
rg -g '*.foo' --files
|
||||
|
||||
-h, --help
|
||||
: Show this usage message.
|
||||
|
||||
-i, --ignore-case
|
||||
: Case insensitive search. Overridden by --case-sensitive.
|
||||
|
||||
-n, --line-number
|
||||
: Show line numbers (1-based). This is enabled by default at a tty.
|
||||
|
||||
-N, --no-line-number
|
||||
: Suppress line numbers.
|
||||
|
||||
-q, --quiet
|
||||
: Do not print anything to stdout. If a match is found in a file, stop
|
||||
searching that file.
|
||||
|
||||
-t, --type *TYPE* ...
|
||||
: Only search files matching TYPE. Multiple type flags may be provided. Use the
|
||||
--type-list flag to list all available types.
|
||||
|
||||
-T, --type-not *TYPE* ...
|
||||
: Do not search files matching TYPE. Multiple not-type flags may be provided.
|
||||
|
||||
-u, --unrestricted ...
|
||||
: Reduce the level of 'smart' searching. A single -u doesn't respect .gitignore
|
||||
(etc.) files. Two -u flags will search hidden files and directories. Three
|
||||
-u flags will search binary files. -uu is equivalent to `grep -r`, and -uuu
|
||||
is equivalent to `grep -a -r`.
|
||||
|
||||
Note that the -u flags are convenient aliases for other combinations of
|
||||
flags. -u aliases --no-ignore. -uu aliases --no-ignore --hidden.
|
||||
-uuu aliases --no-ignore --hidden --text.
|
||||
|
||||
-v, --invert-match
|
||||
: Invert matching.
|
||||
|
||||
-w, --word-regexp
|
||||
: Only show matches surrounded by word boundaries. This is equivalent to
|
||||
putting \\b before and after the search pattern.
|
||||
|
||||
-x, --line-regexp
|
||||
: Only show matches surrounded by line boundaries. This is equivalent to
|
||||
putting ^...$ around the search pattern.
|
||||
|
||||
-z, --search-zip
|
||||
: Search in compressed files. Currently gz, bz2, xz and lzma
|
||||
formats are supported.
|
||||
|
||||
Note that ripgrep expects to find the decompression binaries for the
|
||||
respective formats in your system's PATH for use with this flag.
|
||||
|
||||
# LESS COMMON OPTIONS
|
||||
|
||||
-A, --after-context *NUM*
|
||||
: Show NUM lines after each match.
|
||||
|
||||
-B, --before-context *NUM*
|
||||
: Show NUM lines before each match.
|
||||
|
||||
-C, --context *NUM*
|
||||
: Show NUM lines before and after each match.
|
||||
|
||||
--colors *SPEC* ...
|
||||
: This flag specifies color settings for use in the output. This flag may be
|
||||
provided multiple times. Settings are applied iteratively. Colors are limited
|
||||
to one of eight choices: red, blue, green, cyan, magenta, yellow, white and
|
||||
black. Styles are limited to nobold, bold, nointense or intense.
|
||||
|
||||
The format of the flag is {type}:{attribute}:{value}. {type} should be one
|
||||
of path, line, column or match. {attribute} can be fg, bg or style. Value
|
||||
is either a color (for fg and bg) or a text style. A special format,
|
||||
{type}:none, will clear all color settings for {type}.
|
||||
|
||||
For example, the following command will change the match color to magenta
|
||||
and the background color for line numbers to yellow:
|
||||
|
||||
rg --colors 'match:fg:magenta' --colors 'line:bg:yellow' foo.
|
||||
|
||||
--column
|
||||
: Show column numbers (1 based) in output. This only shows the column
|
||||
numbers for the first match on each line. Note that this doesn't try
|
||||
to account for Unicode. One byte is equal to one column. This implies
|
||||
--line-number.
|
||||
|
||||
--context-separator *SEPARATOR*
|
||||
: The string to use when separating non-continuous context lines. Escape
|
||||
sequences may be used. [default: --]
|
||||
|
||||
--debug
|
||||
: Show debug messages.
|
||||
|
||||
-E, --encoding *ENCODING*
|
||||
: Specify the text encoding that ripgrep will use on all files
|
||||
searched. The default value is 'auto', which will cause ripgrep to do
|
||||
a best effort automatic detection of encoding on a per-file basis.
|
||||
Other supported values can be found in the list of labels here:
|
||||
https://encoding.spec.whatwg.org/#concept-encoding-get
|
||||
|
||||
-f, --file *FILE* ...
|
||||
: Search for patterns from the given file, with one pattern per line. When this
|
||||
flag is used or multiple times or in combination with the -e/--regexp flag,
|
||||
then all patterns provided are searched. Empty pattern lines will match all
|
||||
input lines, and the newline is not counted as part of the pattern.
|
||||
|
||||
--files
|
||||
: Print each file that would be searched (but don't search).
|
||||
|
||||
Combine with the -g flag to return matched paths, for example:
|
||||
|
||||
rg -g '*.foo' --files
|
||||
|
||||
-l, --files-with-matches
|
||||
: Only show path of each file with matches.
|
||||
|
||||
--files-without-match
|
||||
: Only show path of each file with no matches.
|
||||
|
||||
-H, --with-filename
|
||||
: Display the file name for matches. This is the default when
|
||||
more than one file is searched. If --heading is enabled, the
|
||||
file name will be shown above clusters of matches from each
|
||||
file; otherwise, the file name will be shown on each match.
|
||||
|
||||
--no-filename
|
||||
: Never show the filename for a match. This is the default when
|
||||
one file is searched.
|
||||
|
||||
--heading
|
||||
: Show the file name above clusters of matches from each file instead of
|
||||
showing the file name for every match. This is the default mode at a tty.
|
||||
|
||||
--no-heading
|
||||
: Don't group matches by each file. If -H/--with-filename is enabled, then
|
||||
file names will be shown for every line matched. This is the default mode
|
||||
when not at a tty.
|
||||
|
||||
--hidden
|
||||
: Search hidden directories and files. (Hidden directories and files are
|
||||
skipped by default.)
|
||||
|
||||
--iglob *GLOB* ...
|
||||
: Include or exclude files/directories case insensitively. This always
|
||||
overrides any other ignore logic if there is a conflict, but is otherwise
|
||||
applied in addition to ignore files (e.g., .gitignore or .ignore). Multiple
|
||||
glob flags may be used. Globbing rules match .gitignore globs. Precede a
|
||||
glob with a '!' to exclude it.
|
||||
|
||||
--ignore-file *FILE* ...
|
||||
: Specify additional ignore files for filtering file paths.
|
||||
Ignore files should be in the gitignore format and are matched
|
||||
relative to the current working directory. These ignore files
|
||||
have lower precedence than all other ignore files. When
|
||||
specifying multiple ignore files, earlier files have lower
|
||||
precedence than later files.
|
||||
|
||||
-L, --follow
|
||||
: Follow symlinks.
|
||||
|
||||
--line-number-width *NUM*
|
||||
: Specify a width for the displayed line number. If number of digits
|
||||
in the line number is less than this number, it is left padded with
|
||||
spaces. Note: This setting has no effect if --no-line-number is
|
||||
enabled.
|
||||
|
||||
-M, --max-columns *NUM*
|
||||
: Don't print lines longer than this limit in bytes. Longer lines are omitted,
|
||||
and only the number of matches in that line is printed.
|
||||
|
||||
-m, --max-count *NUM*
|
||||
: Limit the number of matching lines per file searched to NUM.
|
||||
|
||||
--max-filesize *NUM*+*SUFFIX*?
|
||||
: Ignore files larger than *NUM* in size. Directories will never be ignored.
|
||||
|
||||
*SUFFIX* is optional and may be one of K, M or G. These correspond to
|
||||
kilobytes, megabytes and gigabytes respectively. If omitted the input is
|
||||
treated as bytes.
|
||||
|
||||
--maxdepth *NUM*
|
||||
: Descend at most NUM directories below the command line arguments.
|
||||
A value of zero searches only the starting-points themselves.
|
||||
|
||||
--mmap
|
||||
: Search using memory maps when possible. This is enabled by default
|
||||
when ripgrep thinks it will be faster. (Note that mmap searching
|
||||
doesn't currently support the various context related options.)
|
||||
|
||||
--no-messages
|
||||
: Suppress all error messages.
|
||||
|
||||
--no-mmap
|
||||
: Never use memory maps, even when they might be faster.
|
||||
|
||||
--no-ignore
|
||||
: Don't respect ignore files (.gitignore, .ignore, etc.)
|
||||
This implies --no-ignore-parent.
|
||||
|
||||
--no-ignore-parent
|
||||
: Don't respect ignore files in parent directories.
|
||||
|
||||
--no-ignore-vcs
|
||||
: Don't respect version control ignore files (e.g., .gitignore).
|
||||
Note that .ignore files will continue to be respected.
|
||||
|
||||
-0, --null
|
||||
: Whenever a file name is printed, follow it with a NUL byte.
|
||||
This includes printing filenames before matches, and when printing
|
||||
a list of matching files such as with --count, --files-with-matches
|
||||
and --files.
|
||||
|
||||
-o, --only-matching
|
||||
: Print only the matched (non-empty) parts of a matching line, with each such
|
||||
part on a separate output line.
|
||||
|
||||
--passthru, --passthrough
|
||||
: Show both matching and non-matching lines. This option cannot be used with
|
||||
--only-matching or --replace.
|
||||
|
||||
--path-separator *SEPARATOR*
|
||||
: The path separator to use when printing file paths. This defaults to your
|
||||
platform's path separator, which is / on Unix and \\ on Windows. This flag is
|
||||
intended for overriding the default when the environment demands it (e.g.,
|
||||
cygwin). A path separator is limited to a single byte.
|
||||
|
||||
-p, --pretty
|
||||
: Alias for --color=always --heading --line-number.
|
||||
|
||||
-r, --replace *ARG*
|
||||
: Replace every match with the string given when printing search results.
|
||||
Neither this flag nor any other flag will modify your files.
|
||||
|
||||
Capture group indices (e.g., $5) and names (e.g., $foo) are supported
|
||||
in the replacement string.
|
||||
|
||||
Note that the replacement by default replaces each match, and NOT the
|
||||
entire line. To replace the entire line, you should match the entire line.
|
||||
For example, to emit only the first phone numbers in each line:
|
||||
|
||||
rg '^.*([0-9]{3}-[0-9]{3}-[0-9]{4}).*$' --replace '$1'
|
||||
|
||||
-s, --case-sensitive
|
||||
: Search case sensitively (default). Overrides --ignore-case and --smart-case.
|
||||
|
||||
-S, --smart-case
|
||||
: Search case insensitively if the pattern is all lowercase.
|
||||
Search case sensitively otherwise. This is overridden by either
|
||||
--case-sensitive or --ignore-case. Note: This feature is smart enough
|
||||
to treat simple classes like \\S as lowercase, but may not handle more
|
||||
complex syntax like \\p{Ll} as expected.
|
||||
|
||||
--sort-files
|
||||
: Sort results by file path. Note that this currently
|
||||
disables all parallelism and runs search in a single thread.
|
||||
|
||||
-j, --threads *ARG*
|
||||
: The number of threads to use. 0 means use the number of logical CPUs
|
||||
(capped at 12). [default: 0]
|
||||
|
||||
--version
|
||||
: Show the version number of ripgrep and exit.
|
||||
|
||||
--vimgrep
|
||||
: Show results with every match on its own line, including
|
||||
line numbers and column numbers. With this option, a line with
|
||||
more than one match will be printed more than once.
|
||||
|
||||
Recommended .vimrc configuration:
|
||||
|
||||
set grepprg=rg\ --vimgrep
|
||||
set grepformat^=%f:%l:%c:%m
|
||||
|
||||
Use :grep to grep for something, then :cn and :cp to navigate through the
|
||||
matches.
|
||||
|
||||
# FILE TYPE MANAGEMENT OPTIONS
|
||||
|
||||
--type-list
|
||||
: Show all supported file types and their associated globs.
|
||||
|
||||
--type-add *ARG* ...
|
||||
: Add a new glob for a particular file type. Only one glob can be added
|
||||
at a time. Multiple --type-add flags can be provided. Unless --type-clear
|
||||
is used, globs are added to any existing globs inside of ripgrep. Note that
|
||||
this must be passed to every invocation of rg. Type settings are NOT
|
||||
persisted. Example:
|
||||
|
||||
rg --type-add 'foo:*.foo' -tfoo PATTERN
|
||||
|
||||
--type-add can also be used to include rules from other types
|
||||
with the special include directive. The include directive
|
||||
permits specifying one or more other type names (separated by a
|
||||
comma) that have been defined and its rules will automatically
|
||||
be imported into the type specified. For example, to create a
|
||||
type called src that matches C++, Python and Markdown files, one
|
||||
can use:
|
||||
|
||||
--type-add 'src:include:cpp,py,md'
|
||||
|
||||
Additional glob rules can still be added to the src type by
|
||||
using the --type-add flag again:
|
||||
|
||||
--type-add 'src:include:cpp,py,md' --type-add 'src:*.foo'
|
||||
|
||||
Note that type names must consist only of Unicode letters or
|
||||
numbers. Punctuation characters are not allowed.
|
||||
|
||||
--type-clear *TYPE* ...
|
||||
: Clear the file type globs previously defined for TYPE. This only clears
|
||||
the default type definitions that are found inside of ripgrep. Note
|
||||
that this must be passed to every invocation of rg.
|
||||
|
||||
# SHELL COMPLETION
|
||||
|
||||
Shell completion files are included in the release tarball for Bash, Fish, Zsh
|
||||
and PowerShell.
|
||||
|
||||
For **bash**, move `rg.bash-completion` to `$XDG_CONFIG_HOME/bash_completion`
|
||||
or `/etc/bash_completion.d/`.
|
||||
|
||||
For **fish**, move `rg.fish` to `$HOME/.config/fish/completions`.
|
154
doc/rg.1.txt.tpl
Normal file
154
doc/rg.1.txt.tpl
Normal file
@@ -0,0 +1,154 @@
|
||||
rg(1)
|
||||
=====
|
||||
|
||||
Name
|
||||
----
|
||||
rg - recursively search current directory for lines matching a pattern
|
||||
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
*rg* [_OPTIONS_] _PATTERN_ [_PATH_...]
|
||||
|
||||
*rg* [_OPTIONS_] *-e* _PATTERN_... [_PATH_...]
|
||||
|
||||
*rg* [_OPTIONS_] *-f* _PATH_... [_PATH_...]
|
||||
|
||||
*rg* [_OPTIONS_] *--files* [_PATH_...]
|
||||
|
||||
*rg* [_OPTIONS_] *--type-list*
|
||||
|
||||
*rg* [_OPTIONS_] *--help*
|
||||
|
||||
*rg* [_OPTIONS_] *--version*
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
ripgrep (rg) recursively searches your current directory for a regex pattern.
|
||||
By default, ripgrep will respect your `.gitignore` and automatically skip
|
||||
hidden files/directories and binary files.
|
||||
|
||||
ripgrep's regex engine uses finite automata and guarantees linear time
|
||||
searching. Because of this, features like backreferences and arbitrary
|
||||
lookaround are not supported.
|
||||
|
||||
|
||||
REGEX SYNTAX
|
||||
------------
|
||||
ripgrep uses Rust's regex engine, which documents its syntax:
|
||||
https://docs.rs/regex/0.2.5/regex/#syntax
|
||||
|
||||
ripgrep uses byte-oriented regexes, which has some additional documentation:
|
||||
https://docs.rs/regex/0.2.5/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.
|
||||
|
||||
|
||||
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. Paths
|
||||
specified expicitly on the command line override glob and ignore rules.
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
{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 non-zero.
|
||||
|
||||
|
||||
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 ASCII whitespace.
|
||||
2. Lines starting with _#_ (optionally preceded by any amount of
|
||||
ASCII 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.
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
|
||||
VERSION
|
||||
-------
|
||||
{VERSION}
|
||||
|
||||
|
||||
HOMEPAGE
|
||||
--------
|
||||
https://github.com/BurntSushi/ripgrep
|
||||
|
||||
Please report bugs and feature requests in the issue tracker.
|
||||
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
Andrew Gallant <jamslam@gmail.com>
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "globset"
|
||||
version = "0.2.1" #:version
|
||||
version = "0.3.0" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
Cross platform single glob and glob set matching. Glob set matching is the
|
||||
@@ -21,7 +21,7 @@ bench = false
|
||||
[dependencies]
|
||||
aho-corasick = "0.6.0"
|
||||
fnv = "1.0"
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
memchr = "2"
|
||||
regex = "0.2.1"
|
||||
|
||||
|
@@ -1,4 +1,3 @@
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fmt;
|
||||
use std::hash;
|
||||
use std::iter;
|
||||
@@ -28,7 +27,7 @@ pub enum MatchStrategy {
|
||||
BasenameLiteral(String),
|
||||
/// A pattern matches if and only if the file path's extension matches this
|
||||
/// literal string.
|
||||
Extension(OsString),
|
||||
Extension(String),
|
||||
/// A pattern matches if and only if this prefix literal is a prefix of the
|
||||
/// candidate file path.
|
||||
Prefix(String),
|
||||
@@ -47,7 +46,7 @@ pub enum MatchStrategy {
|
||||
/// extension. Note that this is a necessary but NOT sufficient criterion.
|
||||
/// Namely, if the extension matches, then a full regex search is still
|
||||
/// required.
|
||||
RequiredExtension(OsString),
|
||||
RequiredExtension(String),
|
||||
/// A regex needs to be used for matching.
|
||||
Regex,
|
||||
}
|
||||
@@ -154,7 +153,7 @@ impl GlobStrategic {
|
||||
lit.as_bytes() == &*candidate.basename
|
||||
}
|
||||
MatchStrategy::Extension(ref ext) => {
|
||||
candidate.ext == ext
|
||||
ext.as_bytes() == &*candidate.ext
|
||||
}
|
||||
MatchStrategy::Prefix(ref pre) => {
|
||||
starts_with(pre.as_bytes(), byte_path)
|
||||
@@ -166,7 +165,8 @@ impl GlobStrategic {
|
||||
ends_with(suffix.as_bytes(), byte_path)
|
||||
}
|
||||
MatchStrategy::RequiredExtension(ref ext) => {
|
||||
candidate.ext == ext && self.re.is_match(byte_path)
|
||||
let ext = ext.as_bytes();
|
||||
&*candidate.ext == ext && self.re.is_match(byte_path)
|
||||
}
|
||||
MatchStrategy::Regex => self.re.is_match(byte_path),
|
||||
}
|
||||
@@ -295,7 +295,7 @@ impl Glob {
|
||||
/// std::path::Path::extension returns. Namely, this extension includes
|
||||
/// the '.'. Also, paths like `.rs` are considered to have an extension
|
||||
/// of `.rs`.
|
||||
fn ext(&self) -> Option<OsString> {
|
||||
fn ext(&self) -> Option<String> {
|
||||
if self.opts.case_insensitive {
|
||||
return None;
|
||||
}
|
||||
@@ -319,11 +319,11 @@ impl Glob {
|
||||
Some(&Token::Literal('.')) => {}
|
||||
_ => return None,
|
||||
}
|
||||
let mut lit = OsStr::new(".").to_os_string();
|
||||
let mut lit = ".".to_string();
|
||||
for t in self.tokens[start + 2..].iter() {
|
||||
match *t {
|
||||
Token::Literal('.') | Token::Literal('/') => return None,
|
||||
Token::Literal(c) => lit.push(c.to_string()),
|
||||
Token::Literal(c) => lit.push(c),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
@@ -337,7 +337,7 @@ impl Glob {
|
||||
/// This is like `ext`, but returns an extension even if it isn't sufficent
|
||||
/// to imply a match. Namely, if an extension is returned, then it is
|
||||
/// necessary but not sufficient for a match.
|
||||
fn required_ext(&self) -> Option<OsString> {
|
||||
fn required_ext(&self) -> Option<String> {
|
||||
if self.opts.case_insensitive {
|
||||
return None;
|
||||
}
|
||||
@@ -360,7 +360,7 @@ impl Glob {
|
||||
None
|
||||
} else {
|
||||
ext.reverse();
|
||||
Some(OsString::from(ext.into_iter().collect::<String>()))
|
||||
Some(ext.into_iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,8 +927,6 @@ fn ends_with(needle: &[u8], haystack: &[u8]) -> bool {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::ffi::{OsStr, OsString};
|
||||
|
||||
use {GlobSetBuilder, ErrorKind};
|
||||
use super::{Glob, GlobBuilder, Token};
|
||||
use super::Token::*;
|
||||
@@ -1021,7 +1019,6 @@ mod tests {
|
||||
}
|
||||
|
||||
fn s(string: &str) -> String { string.to_string() }
|
||||
fn os(string: &str) -> OsString { OsStr::new(string).to_os_string() }
|
||||
|
||||
fn class(s: char, e: char) -> Token {
|
||||
Class { negated: false, ranges: vec![(s, e)] }
|
||||
@@ -1155,6 +1152,7 @@ mod tests {
|
||||
matches!(matchrec22, ".*/**", ".abc/abc");
|
||||
matches!(matchrec23, "foo/**", "foo");
|
||||
matches!(matchrec24, "**/foo/bar", "foo/bar");
|
||||
matches!(matchrec25, "some/*/needle.txt", "some/one/needle.txt");
|
||||
|
||||
matches!(matchrange1, "a[0-9]b", "a0b");
|
||||
matches!(matchrange2, "a[0-9]b", "a9b");
|
||||
@@ -1243,6 +1241,13 @@ mod tests {
|
||||
nmatches!(matchnot27, "a[^0-9]b", "a0b");
|
||||
nmatches!(matchnot28, "a[^0-9]b", "a9b");
|
||||
nmatches!(matchnot29, "[^-]", "-");
|
||||
nmatches!(matchnot30, "some/*/needle.txt", "some/needle.txt");
|
||||
nmatches!(
|
||||
matchrec31,
|
||||
"some/*/needle.txt", "some/one/two/needle.txt", SLASHLIT);
|
||||
nmatches!(
|
||||
matchrec32,
|
||||
"some/*/needle.txt", "some/one/two/three/needle.txt", SLASHLIT);
|
||||
|
||||
macro_rules! extract {
|
||||
($which:ident, $name:ident, $pat:expr, $expect:expr) => {
|
||||
@@ -1311,19 +1316,19 @@ mod tests {
|
||||
Literal('f'), Literal('o'), ZeroOrMore, Literal('o'),
|
||||
]), SLASHLIT);
|
||||
|
||||
ext!(extract_ext1, "**/*.rs", Some(os(".rs")));
|
||||
ext!(extract_ext1, "**/*.rs", Some(s(".rs")));
|
||||
ext!(extract_ext2, "**/*.rs.bak", None);
|
||||
ext!(extract_ext3, "*.rs", Some(os(".rs")));
|
||||
ext!(extract_ext3, "*.rs", Some(s(".rs")));
|
||||
ext!(extract_ext4, "a*.rs", None);
|
||||
ext!(extract_ext5, "/*.c", None);
|
||||
ext!(extract_ext6, "*.c", None, SLASHLIT);
|
||||
ext!(extract_ext7, "*.c", Some(os(".c")));
|
||||
ext!(extract_ext7, "*.c", Some(s(".c")));
|
||||
|
||||
required_ext!(extract_req_ext1, "*.rs", Some(os(".rs")));
|
||||
required_ext!(extract_req_ext2, "/foo/bar/*.rs", Some(os(".rs")));
|
||||
required_ext!(extract_req_ext3, "/foo/bar/*.rs", Some(os(".rs")));
|
||||
required_ext!(extract_req_ext4, "/foo/bar/.rs", Some(os(".rs")));
|
||||
required_ext!(extract_req_ext5, ".rs", Some(os(".rs")));
|
||||
required_ext!(extract_req_ext1, "*.rs", Some(s(".rs")));
|
||||
required_ext!(extract_req_ext2, "/foo/bar/*.rs", Some(s(".rs")));
|
||||
required_ext!(extract_req_ext3, "/foo/bar/*.rs", Some(s(".rs")));
|
||||
required_ext!(extract_req_ext4, "/foo/bar/.rs", Some(s(".rs")));
|
||||
required_ext!(extract_req_ext5, ".rs", Some(s(".rs")));
|
||||
required_ext!(extract_req_ext6, "./rs", None);
|
||||
required_ext!(extract_req_ext7, "foo", None);
|
||||
required_ext!(extract_req_ext8, ".foo/", None);
|
||||
|
@@ -108,7 +108,7 @@ extern crate regex;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::error::Error as StdError;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::ffi::OsStr;
|
||||
use std::fmt;
|
||||
use std::hash;
|
||||
use std::path::Path;
|
||||
@@ -458,7 +458,7 @@ impl GlobSetBuilder {
|
||||
pub struct Candidate<'a> {
|
||||
path: Cow<'a, [u8]>,
|
||||
basename: Cow<'a, [u8]>,
|
||||
ext: &'a OsStr,
|
||||
ext: Cow<'a, [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> Candidate<'a> {
|
||||
@@ -469,7 +469,7 @@ impl<'a> Candidate<'a> {
|
||||
Candidate {
|
||||
path: normalize_path(path_bytes(path)),
|
||||
basename: os_str_bytes(basename),
|
||||
ext: file_name_ext(basename).unwrap_or(OsStr::new("")),
|
||||
ext: file_name_ext(basename).unwrap_or(Cow::Borrowed(b"")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,22 +584,22 @@ impl BasenameLiteralStrategy {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct ExtensionStrategy(HashMap<OsString, Vec<usize>, Fnv>);
|
||||
struct ExtensionStrategy(HashMap<Vec<u8>, Vec<usize>, Fnv>);
|
||||
|
||||
impl ExtensionStrategy {
|
||||
fn new() -> ExtensionStrategy {
|
||||
ExtensionStrategy(HashMap::with_hasher(Fnv::default()))
|
||||
}
|
||||
|
||||
fn add(&mut self, global_index: usize, ext: OsString) {
|
||||
self.0.entry(ext).or_insert(vec![]).push(global_index);
|
||||
fn add(&mut self, global_index: usize, ext: String) {
|
||||
self.0.entry(ext.into_bytes()).or_insert(vec![]).push(global_index);
|
||||
}
|
||||
|
||||
fn is_match(&self, candidate: &Candidate) -> bool {
|
||||
if candidate.ext.is_empty() {
|
||||
return false;
|
||||
}
|
||||
self.0.contains_key(candidate.ext)
|
||||
self.0.contains_key(&*candidate.ext)
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
@@ -607,7 +607,7 @@ impl ExtensionStrategy {
|
||||
if candidate.ext.is_empty() {
|
||||
return;
|
||||
}
|
||||
if let Some(hits) = self.0.get(candidate.ext) {
|
||||
if let Some(hits) = self.0.get(&*candidate.ext) {
|
||||
matches.extend(hits);
|
||||
}
|
||||
}
|
||||
@@ -670,14 +670,14 @@ impl SuffixStrategy {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct RequiredExtensionStrategy(HashMap<OsString, Vec<(usize, Regex)>, Fnv>);
|
||||
struct RequiredExtensionStrategy(HashMap<Vec<u8>, Vec<(usize, Regex)>, Fnv>);
|
||||
|
||||
impl RequiredExtensionStrategy {
|
||||
fn is_match(&self, candidate: &Candidate) -> bool {
|
||||
if candidate.ext.is_empty() {
|
||||
return false;
|
||||
}
|
||||
match self.0.get(candidate.ext) {
|
||||
match self.0.get(&*candidate.ext) {
|
||||
None => false,
|
||||
Some(regexes) => {
|
||||
for &(_, ref re) in regexes {
|
||||
@@ -695,7 +695,7 @@ impl RequiredExtensionStrategy {
|
||||
if candidate.ext.is_empty() {
|
||||
return;
|
||||
}
|
||||
if let Some(regexes) = self.0.get(candidate.ext) {
|
||||
if let Some(regexes) = self.0.get(&*candidate.ext) {
|
||||
for &(global_index, ref re) in regexes {
|
||||
if re.is_match(&*candidate.path) {
|
||||
matches.push(global_index);
|
||||
@@ -775,7 +775,7 @@ impl MultiStrategyBuilder {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct RequiredExtensionStrategyBuilder(
|
||||
HashMap<OsString, Vec<(usize, String)>>,
|
||||
HashMap<Vec<u8>, Vec<(usize, String)>>,
|
||||
);
|
||||
|
||||
impl RequiredExtensionStrategyBuilder {
|
||||
@@ -783,8 +783,11 @@ impl RequiredExtensionStrategyBuilder {
|
||||
RequiredExtensionStrategyBuilder(HashMap::new())
|
||||
}
|
||||
|
||||
fn add(&mut self, global_index: usize, ext: OsString, regex: String) {
|
||||
self.0.entry(ext).or_insert(vec![]).push((global_index, regex));
|
||||
fn add(&mut self, global_index: usize, ext: String, regex: String) {
|
||||
self.0
|
||||
.entry(ext.into_bytes())
|
||||
.or_insert(vec![])
|
||||
.push((global_index, regex));
|
||||
}
|
||||
|
||||
fn build(self) -> Result<RequiredExtensionStrategy, Error> {
|
||||
|
@@ -54,34 +54,28 @@ pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
|
||||
/// a pattern like `*.rs` is obviously trying to match files with a `rs`
|
||||
/// extension, but it also matches files like `.rs`, which doesn't have an
|
||||
/// extension according to std::path::Path::extension.
|
||||
pub fn file_name_ext(name: &OsStr) -> Option<&OsStr> {
|
||||
// Yes, these functions are awful, and yes, we are completely violating
|
||||
// the abstraction barrier of std::ffi. The barrier we're violating is
|
||||
// that an OsStr's encoding is *ASCII compatible*. While this is obviously
|
||||
// true on Unix systems, it's also true on Windows because an OsStr uses
|
||||
// WTF-8 internally: https://simonsapin.github.io/wtf-8/
|
||||
//
|
||||
// We should consider doing the same for the other path utility functions.
|
||||
// Right now, we don't break any barriers, but Windows users are paying
|
||||
// for it.
|
||||
//
|
||||
// Got any better ideas that don't cost anything? Hit me up. ---AG
|
||||
unsafe fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
|
||||
::std::mem::transmute(s)
|
||||
}
|
||||
unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
|
||||
::std::mem::transmute(s)
|
||||
}
|
||||
pub fn file_name_ext(name: &OsStr) -> Option<Cow<[u8]>> {
|
||||
if name.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let name = unsafe { os_str_as_u8_slice(name) };
|
||||
for (i, &b) in name.iter().enumerate().rev() {
|
||||
if b == b'.' {
|
||||
return Some(unsafe { u8_slice_as_os_str(&name[i..]) });
|
||||
let name = os_str_bytes(name);
|
||||
let last_dot_at = {
|
||||
let result = name
|
||||
.iter().enumerate().rev()
|
||||
.find(|&(_, &b)| b == b'.')
|
||||
.map(|(i, _)| i);
|
||||
match result {
|
||||
None => return None,
|
||||
Some(i) => i,
|
||||
}
|
||||
}
|
||||
None
|
||||
};
|
||||
Some(match name {
|
||||
Cow::Borrowed(name) => Cow::Borrowed(&name[last_dot_at..]),
|
||||
Cow::Owned(mut name) => {
|
||||
name.drain(..last_dot_at);
|
||||
Cow::Owned(name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Return raw bytes of a path, transcoded to UTF-8 if necessary.
|
||||
@@ -144,7 +138,7 @@ mod tests {
|
||||
#[test]
|
||||
fn $name() {
|
||||
let got = file_name_ext(OsStr::new($file_name));
|
||||
assert_eq!($ext.map(OsStr::new), got);
|
||||
assert_eq!($ext.map(|s| Cow::Borrowed(s.as_bytes())), got);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "grep"
|
||||
version = "0.1.7" #:version
|
||||
version = "0.1.8" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
Fast line oriented regex searching as a library.
|
||||
@@ -13,7 +13,7 @@ keywords = ["regex", "grep", "egrep", "search", "pattern"]
|
||||
license = "Unlicense/MIT"
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
memchr = "2"
|
||||
regex = "0.2.1"
|
||||
regex-syntax = "0.4.0"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ignore"
|
||||
version = "0.3.1" #:version
|
||||
version = "0.4.1" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
A fast library for efficiently matching ignore files such as `.gitignore`
|
||||
@@ -19,9 +19,9 @@ bench = false
|
||||
|
||||
[dependencies]
|
||||
crossbeam = "0.3"
|
||||
globset = { version = "0.2.1", path = "../globset" }
|
||||
globset = { version = "0.3.0", path = "../globset" }
|
||||
lazy_static = "1"
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
memchr = "2"
|
||||
regex = "0.2.1"
|
||||
same-file = "1"
|
||||
|
@@ -73,13 +73,6 @@ struct IgnoreOptions {
|
||||
git_exclude: bool,
|
||||
}
|
||||
|
||||
impl IgnoreOptions {
|
||||
/// Returns true if at least one type of ignore rules should be matched.
|
||||
fn has_any_ignore_options(&self) -> bool {
|
||||
self.ignore || self.git_global || self.git_ignore || self.git_exclude
|
||||
}
|
||||
}
|
||||
|
||||
/// Ignore is a matcher useful for recursively walking one or more directories.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Ignore(Arc<IgnoreInner>);
|
||||
@@ -267,6 +260,15 @@ impl Ignore {
|
||||
(ig, errs.into_error_option())
|
||||
}
|
||||
|
||||
/// Returns true if at least one type of ignore rule should be matched.
|
||||
fn has_any_ignore_rules(&self) -> bool {
|
||||
let opts = self.0.opts;
|
||||
let has_custom_ignore_files = !self.0.custom_ignore_filenames.is_empty();
|
||||
|
||||
opts.ignore || opts.git_global || opts.git_ignore
|
||||
|| opts.git_exclude || has_custom_ignore_files
|
||||
}
|
||||
|
||||
/// Returns a match indicating whether the given file path should be
|
||||
/// ignored or not.
|
||||
///
|
||||
@@ -295,7 +297,7 @@ impl Ignore {
|
||||
}
|
||||
}
|
||||
let mut whitelisted = Match::None;
|
||||
if self.0.opts.has_any_ignore_options() {
|
||||
if self.has_any_ignore_rules() {
|
||||
let mat = self.matched_ignore(path, is_dir);
|
||||
if mat.is_ignore() {
|
||||
return mat;
|
||||
|
@@ -66,6 +66,12 @@ impl Glob {
|
||||
pub fn is_only_dir(&self) -> bool {
|
||||
self.is_only_dir
|
||||
}
|
||||
|
||||
/// Returns true if and only if this glob has a `**/` prefix.
|
||||
fn has_doublestar_prefix(&self) -> bool {
|
||||
self.actual.starts_with("**/")
|
||||
|| (self.actual == "**" && self.is_only_dir)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gitignore is a matcher for the globs in one or more gitignore files
|
||||
@@ -278,7 +284,10 @@ impl Gitignore {
|
||||
// BUT, a file name might not have any directory components to it,
|
||||
// in which case, we don't want to accidentally strip any part of the
|
||||
// file name.
|
||||
if !is_file_name(path) {
|
||||
//
|
||||
// As an additional special case, if the root is just `.`, then we
|
||||
// shouldn't try to strip anything, e.g., when path begins with a `.`.
|
||||
if self.root != Path::new(".") && !is_file_name(path) {
|
||||
if let Some(p) = strip_prefix(&self.root, path) {
|
||||
path = p;
|
||||
// If we're left with a leading slash, get rid of it.
|
||||
@@ -454,7 +463,7 @@ impl GitignoreBuilder {
|
||||
// prefix.
|
||||
if !literal_separator {
|
||||
// ... but only if we don't already have a **/ prefix.
|
||||
if !(glob.actual.starts_with("**/") || (glob.actual == "**" && glob.is_only_dir)) {
|
||||
if !glob.has_doublestar_prefix() {
|
||||
glob.actual = format!("**/{}", glob.actual);
|
||||
}
|
||||
}
|
||||
@@ -620,6 +629,12 @@ mod tests {
|
||||
ignored!(ig29, ROOT, "node_modules/ ", "node_modules", true);
|
||||
ignored!(ig30, ROOT, "**/", "foo/bar", true);
|
||||
ignored!(ig31, ROOT, "path1/*", "path1/foo");
|
||||
ignored!(ig32, ROOT, ".a/b", ".a/b");
|
||||
ignored!(ig33, "./", ".a/b", ".a/b");
|
||||
ignored!(ig34, ".", ".a/b", ".a/b");
|
||||
ignored!(ig35, "./.", ".a/b", ".a/b");
|
||||
ignored!(ig36, "././", ".a/b", ".a/b");
|
||||
ignored!(ig37, "././.", ".a/b", ".a/b");
|
||||
|
||||
not_ignored!(ignot1, ROOT, "amonths", "months");
|
||||
not_ignored!(ignot2, ROOT, "monthsa", "months");
|
||||
|
@@ -122,6 +122,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("csharp", &["*.cs"]),
|
||||
("cshtml", &["*.cshtml"]),
|
||||
("css", &["*.css", "*.scss"]),
|
||||
("csv", &["*.csv"]),
|
||||
("cython", &["*.pyx"]),
|
||||
("dart", &["*.dart"]),
|
||||
("d", &["*.d"]),
|
||||
@@ -274,6 +275,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("twig", &["*.twig"]),
|
||||
("vala", &["*.vala"]),
|
||||
("vb", &["*.vb"]),
|
||||
("vhdl", &["*.vhd", "*.vhdl"]),
|
||||
("vim", &["*.vim"]),
|
||||
("vimscript", &["*.vim"]),
|
||||
("wiki", &["*.mediawiki", "*.wiki"]),
|
||||
|
@@ -249,6 +249,14 @@ struct DirEntryRaw {
|
||||
/// The underlying inode number (Unix only).
|
||||
#[cfg(unix)]
|
||||
ino: u64,
|
||||
/// The underlying metadata (Windows only). We store this on Windows
|
||||
/// because this comes for free while reading a directory.
|
||||
///
|
||||
/// We use this to determine whether an entry is a directory or not, which
|
||||
/// works around a bug in Rust's standard library:
|
||||
/// https://github.com/rust-lang/rust/issues/46484
|
||||
#[cfg(windows)]
|
||||
metadata: fs::Metadata,
|
||||
}
|
||||
|
||||
impl fmt::Debug for DirEntryRaw {
|
||||
@@ -274,6 +282,20 @@ impl DirEntryRaw {
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
self.metadata_internal()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn metadata_internal(&self) -> Result<fs::Metadata, Error> {
|
||||
if self.follow_link {
|
||||
fs::metadata(&self.path)
|
||||
} else {
|
||||
Ok(self.metadata.clone())
|
||||
}.map_err(|err| Error::Io(io::Error::from(err)).with_path(&self.path))
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn metadata_internal(&self) -> Result<fs::Metadata, Error> {
|
||||
if self.follow_link {
|
||||
fs::metadata(&self.path)
|
||||
} else {
|
||||
@@ -309,21 +331,29 @@ impl DirEntryRaw {
|
||||
err: Box::new(err),
|
||||
}
|
||||
})?;
|
||||
Ok(DirEntryRaw::from_entry_os(depth, ent, ty))
|
||||
DirEntryRaw::from_entry_os(depth, ent, ty)
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
#[cfg(windows)]
|
||||
fn from_entry_os(
|
||||
depth: usize,
|
||||
ent: &fs::DirEntry,
|
||||
ty: fs::FileType,
|
||||
) -> DirEntryRaw {
|
||||
DirEntryRaw {
|
||||
) -> Result<DirEntryRaw, Error> {
|
||||
let md = ent.metadata().map_err(|err| {
|
||||
let err = Error::Io(io::Error::from(err)).with_path(ent.path());
|
||||
Error::WithDepth {
|
||||
depth: depth,
|
||||
err: Box::new(err),
|
||||
}
|
||||
})?;
|
||||
Ok(DirEntryRaw {
|
||||
path: ent.path(),
|
||||
ty: ty,
|
||||
follow_link: false,
|
||||
depth: depth,
|
||||
}
|
||||
metadata: md,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
@@ -331,16 +361,16 @@ impl DirEntryRaw {
|
||||
depth: usize,
|
||||
ent: &fs::DirEntry,
|
||||
ty: fs::FileType,
|
||||
) -> DirEntryRaw {
|
||||
) -> Result<DirEntryRaw, Error> {
|
||||
use std::os::unix::fs::DirEntryExt;
|
||||
|
||||
DirEntryRaw {
|
||||
Ok(DirEntryRaw {
|
||||
path: ent.path(),
|
||||
ty: ty,
|
||||
follow_link: false,
|
||||
depth: depth,
|
||||
ino: ent.ino(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
@@ -353,6 +383,7 @@ impl DirEntryRaw {
|
||||
ty: md.file_type(),
|
||||
follow_link: true,
|
||||
depth: depth,
|
||||
metadata: md,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1026,6 +1057,11 @@ impl Work {
|
||||
self.dent.is_dir()
|
||||
}
|
||||
|
||||
/// Returns true if and only if this work item is a symlink.
|
||||
fn is_symlink(&self) -> bool {
|
||||
self.dent.file_type().map_or(false, |ft| ft.is_symlink())
|
||||
}
|
||||
|
||||
/// Adds ignore rules for parent directories.
|
||||
///
|
||||
/// Note that this only applies to entries at depth 0. On all other
|
||||
@@ -1112,7 +1148,7 @@ impl Worker {
|
||||
while let Some(mut work) = self.get_work() {
|
||||
// If the work is not a directory, then we can just execute the
|
||||
// caller's callback immediately and move on.
|
||||
if !work.is_dir() {
|
||||
if work.is_symlink() || !work.is_dir() {
|
||||
if (self.f)(Ok(work.dent)).is_quit() {
|
||||
self.quit_now();
|
||||
return;
|
||||
@@ -1585,6 +1621,26 @@ mod tests {
|
||||
assert_paths(td.path(), &builder, &["bar", "a", "a/bar"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_ignore_exclusive_use() {
|
||||
let td = TempDir::new("walk-test-").unwrap();
|
||||
let custom_ignore = ".customignore";
|
||||
mkdirp(td.path().join("a"));
|
||||
wfile(td.path().join(custom_ignore), "foo");
|
||||
wfile(td.path().join("foo"), "");
|
||||
wfile(td.path().join("a/foo"), "");
|
||||
wfile(td.path().join("bar"), "");
|
||||
wfile(td.path().join("a/bar"), "");
|
||||
|
||||
let mut builder = WalkBuilder::new(td.path());
|
||||
builder.ignore(false);
|
||||
builder.git_ignore(false);
|
||||
builder.git_global(false);
|
||||
builder.git_exclude(false);
|
||||
builder.add_custom_ignore_filename(&custom_ignore);
|
||||
assert_paths(td.path(), &builder, &["bar", "a", "a/bar"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gitignore() {
|
||||
let td = TempDir::new("walk-test-").unwrap();
|
||||
|
4
pkg/archlinux/.gitignore
vendored
4
pkg/archlinux/.gitignore
vendored
@@ -1,4 +0,0 @@
|
||||
*.xz
|
||||
src
|
||||
pkg
|
||||
*.gz
|
@@ -1,37 +0,0 @@
|
||||
# Contributor: Andrew Gallant <jamslam@gmail.com>
|
||||
# Maintainer: Andrew Gallant
|
||||
pkgname=ripgrep
|
||||
pkgver=0.2.3
|
||||
pkgrel=1
|
||||
pkgdesc="A search tool that combines the usability of The Silver Searcher with the raw speed of grep."
|
||||
arch=('i686' 'x86_64')
|
||||
url="https://github.com/BurntSushi/ripgrep"
|
||||
license=('UNLICENSE')
|
||||
makedepends=('cargo')
|
||||
source=("https://github.com/BurntSushi/$pkgname/archive/$pkgver.tar.gz")
|
||||
sha256sums=('a88531558d2023df76190ea2e52bee50d739eabece8a57df29abbad0c6bdb917')
|
||||
|
||||
build() {
|
||||
cd "$pkgname-$pkgver"
|
||||
if command -v rustup > /dev/null 2>&1; then
|
||||
RUSTFLAGS="-C target-cpu=native" rustup run nightly \
|
||||
cargo build --release --features simd-accel
|
||||
elif rustc --version | grep -q nightly; then
|
||||
RUSTFLAGS="-C target-cpu=native" \
|
||||
cargo build --release --features simd-accel
|
||||
else
|
||||
cargo build --release
|
||||
fi
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$pkgname-$pkgver"
|
||||
|
||||
install -Dm755 "target/release/rg" "$pkgdir/usr/bin/rg"
|
||||
install -Dm644 "doc/rg.1" "$pkgdir/usr/share/man/man1/rg.1"
|
||||
install -Dm644 "README.md" "$pkgdir/usr/share/doc/ripgrep/README.md"
|
||||
install -Dm644 "COPYING" "$pkgdir/usr/share/doc/ripgrep/COPYING"
|
||||
install -Dm644 "LICENSE-MIT" "$pkgdir/usr/share/doc/ripgrep/LICENSE-MIT"
|
||||
install -Dm644 "UNLICENSE" "$pkgdir/usr/share/doc/ripgrep/UNLICENSE"
|
||||
install -Dm644 "CHANGELOG.md" "$pkgdir/usr/share/doc/ripgrep/CHANGELOG.md"
|
||||
}
|
@@ -1,23 +1,23 @@
|
||||
class RipgrepBin < Formula
|
||||
version '0.7.1'
|
||||
desc "Search tool like grep and The Silver Searcher."
|
||||
version '0.8.0'
|
||||
desc "Recursively search directories for a regex pattern."
|
||||
homepage "https://github.com/BurntSushi/ripgrep"
|
||||
|
||||
if OS.mac?
|
||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
|
||||
sha256 "ee670b0fba46323ee9a2d1c5b8bee46fa3e45778f6f105f2e8e9ee29e8bd0d45"
|
||||
sha256 "fb35e92fd57d28a1e68daf964764c3da7f027ad30cca7a07a1848224776f36b2"
|
||||
elsif OS.linux?
|
||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-unknown-linux-musl.tar.gz"
|
||||
sha256 "ac595c2239b9a30e0e0744578afa6b73e32cdd8ae61d4f1c0ee5d6b55adbadcf"
|
||||
sha256 "621f2f16f65203aa37e7c10ecfb22384c4c01e70ebbd30a13c0d6944ffc6e59e"
|
||||
end
|
||||
|
||||
conflicts_with "ripgrep"
|
||||
|
||||
def install
|
||||
bin.install "rg"
|
||||
man1.install "rg.1"
|
||||
man1.install "doc/rg.1"
|
||||
|
||||
bash_completion.install "complete/rg.bash-completion"
|
||||
bash_completion.install "complete/rg.bash"
|
||||
fish_completion.install "complete/rg.fish"
|
||||
zsh_completion.install "complete/_rg"
|
||||
end
|
||||
|
2163
src/app.rs
2163
src/app.rs
File diff suppressed because it is too large
Load Diff
133
src/args.rs
133
src/args.rs
@@ -3,14 +3,12 @@ use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::io::{self, BufRead};
|
||||
use std::ops;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use clap;
|
||||
use encoding_rs::Encoding;
|
||||
use env_logger;
|
||||
use grep::{Grep, GrepBuilder, Error as GrepError};
|
||||
use log;
|
||||
use num_cpus;
|
||||
@@ -27,6 +25,8 @@ use printer::{ColorSpecs, Printer};
|
||||
use unescape::unescape;
|
||||
use worker::{Worker, WorkerBuilder};
|
||||
|
||||
use config;
|
||||
use logger::Logger;
|
||||
use Result;
|
||||
|
||||
/// `Args` are transformed/normalized from `ArgMatches`.
|
||||
@@ -89,18 +89,59 @@ impl Args {
|
||||
///
|
||||
/// Also, initialize a global logger.
|
||||
pub fn parse() -> Result<Args> {
|
||||
let matches = app::app().get_matches();
|
||||
// We parse the args given on CLI. This does not include args from
|
||||
// the config. We use the CLI args as an initial configuration while
|
||||
// trying to parse config files. If a config file exists and has
|
||||
// arguments, then we re-parse argv, otherwise we just use the matches
|
||||
// we have here.
|
||||
let early_matches = ArgMatches(app::app().get_matches());
|
||||
|
||||
let mut logb = env_logger::LogBuilder::new();
|
||||
if matches.is_present("debug") {
|
||||
logb.filter(None, log::LogLevelFilter::Debug);
|
||||
} else {
|
||||
logb.filter(None, log::LogLevelFilter::Warn);
|
||||
}
|
||||
if let Err(err) = logb.init() {
|
||||
if let Err(err) = Logger::init() {
|
||||
errored!("failed to initialize logger: {}", err);
|
||||
}
|
||||
ArgMatches(matches).to_args()
|
||||
if early_matches.is_present("debug") {
|
||||
log::set_max_level(log::LevelFilter::Debug);
|
||||
} else {
|
||||
log::set_max_level(log::LevelFilter::Warn);
|
||||
}
|
||||
|
||||
let matches = Args::matches(early_matches);
|
||||
// The logging level may have changed if we brought in additional
|
||||
// arguments from a configuration file, so recheck it and set the log
|
||||
// level as appropriate.
|
||||
if matches.is_present("debug") {
|
||||
log::set_max_level(log::LevelFilter::Debug);
|
||||
} else {
|
||||
log::set_max_level(log::LevelFilter::Warn);
|
||||
}
|
||||
matches.to_args()
|
||||
}
|
||||
|
||||
/// Run clap and return the matches. If clap determines a problem with the
|
||||
/// user provided arguments (or if --help or --version are given), then an
|
||||
/// error/usage/version will be printed and the process will exit.
|
||||
///
|
||||
/// If there are no additional arguments from the environment (e.g., a
|
||||
/// config file), then the given matches are returned as is.
|
||||
fn matches(early_matches: ArgMatches<'static>) -> ArgMatches<'static> {
|
||||
// If the end user says no config, then respect it.
|
||||
if early_matches.is_present("no-config") {
|
||||
debug!("not reading config files because --no-config is present");
|
||||
return early_matches;
|
||||
}
|
||||
// If the user wants ripgrep to use a config file, then parse args
|
||||
// from that first.
|
||||
let mut args = config::args(early_matches.is_present("no-messages"));
|
||||
if args.is_empty() {
|
||||
return early_matches;
|
||||
}
|
||||
let mut cliargs = env::args_os();
|
||||
if let Some(bin) = cliargs.next() {
|
||||
args.insert(0, bin);
|
||||
}
|
||||
args.extend(cliargs);
|
||||
debug!("final argv: {:?}", args);
|
||||
ArgMatches(app::app().get_matches_from(args))
|
||||
}
|
||||
|
||||
/// Returns true if ripgrep should print the files it will search and exit
|
||||
@@ -306,11 +347,6 @@ impl Args {
|
||||
/// several options/flags.
|
||||
struct ArgMatches<'a>(clap::ArgMatches<'a>);
|
||||
|
||||
impl<'a> ops::Deref for ArgMatches<'a> {
|
||||
type Target = clap::ArgMatches<'a>;
|
||||
fn deref(&self) -> &clap::ArgMatches<'a> { &self.0 }
|
||||
}
|
||||
|
||||
impl<'a> ArgMatches<'a> {
|
||||
/// Convert the result of parsing CLI arguments into ripgrep's
|
||||
/// configuration.
|
||||
@@ -345,8 +381,8 @@ impl<'a> ArgMatches<'a> {
|
||||
line_number: line_number,
|
||||
line_number_width: try!(self.usize_of("line-number-width")),
|
||||
line_per_match: self.is_present("vimgrep"),
|
||||
max_columns: self.usize_of("max-columns")?,
|
||||
max_count: self.usize_of("max-count")?.map(|max| max as u64),
|
||||
max_columns: self.usize_of_nonzero("max-columns")?,
|
||||
max_count: self.usize_of("max-count")?.map(|n| n as u64),
|
||||
max_filesize: self.max_filesize()?,
|
||||
maxdepth: self.usize_of("maxdepth")?,
|
||||
mmap: mmap,
|
||||
@@ -377,7 +413,7 @@ impl<'a> ArgMatches<'a> {
|
||||
|
||||
/// Return all file paths that ripgrep should search.
|
||||
fn paths(&self) -> Vec<PathBuf> {
|
||||
let mut paths: Vec<PathBuf> = match self.values_of_os("PATH") {
|
||||
let mut paths: Vec<PathBuf> = match self.values_of_os("path") {
|
||||
None => vec![],
|
||||
Some(vals) => vals.map(|p| Path::new(p).to_path_buf()).collect(),
|
||||
};
|
||||
@@ -386,7 +422,7 @@ impl<'a> ArgMatches<'a> {
|
||||
if self.is_present("file")
|
||||
|| self.is_present("files")
|
||||
|| self.is_present("regexp") {
|
||||
if let Some(path) = self.value_of_os("PATTERN") {
|
||||
if let Some(path) = self.value_of_os("pattern") {
|
||||
paths.insert(0, Path::new(path).to_path_buf());
|
||||
}
|
||||
}
|
||||
@@ -452,7 +488,7 @@ impl<'a> ArgMatches<'a> {
|
||||
match self.values_of_os("regexp") {
|
||||
None => {
|
||||
if self.values_of_os("file").is_none() {
|
||||
if let Some(os_pat) = self.value_of_os("PATTERN") {
|
||||
if let Some(os_pat) = self.value_of_os("pattern") {
|
||||
pats.push(self.os_str_pattern(os_pat)?);
|
||||
}
|
||||
}
|
||||
@@ -646,7 +682,7 @@ impl<'a> ArgMatches<'a> {
|
||||
|
||||
/// Returns the replacement string as UTF-8 bytes if it exists.
|
||||
fn replace(&self) -> Option<Vec<u8>> {
|
||||
self.value_of_lossy("replace").map(|s| s.into_owned().into_bytes())
|
||||
self.value_of_lossy("replace").map(|s| s.into_bytes())
|
||||
}
|
||||
|
||||
/// Returns the unescaped context separator in UTF-8 bytes.
|
||||
@@ -696,9 +732,9 @@ impl<'a> ArgMatches<'a> {
|
||||
/// Returns the user's color choice based on command line parameters and
|
||||
/// environment.
|
||||
fn color_choice(&self) -> termcolor::ColorChoice {
|
||||
let preference = match self.0.value_of_lossy("color") {
|
||||
let preference = match self.value_of_lossy("color") {
|
||||
None => "auto".to_string(),
|
||||
Some(v) => v.into_owned(),
|
||||
Some(v) => v,
|
||||
};
|
||||
if preference == "always" {
|
||||
termcolor::ColorChoice::Always
|
||||
@@ -744,7 +780,7 @@ impl<'a> ArgMatches<'a> {
|
||||
/// A `None` encoding implies that the encoding should be automatically
|
||||
/// detected on a per-file basis.
|
||||
fn encoding(&self) -> Result<Option<&'static Encoding>> {
|
||||
match self.0.value_of_lossy("encoding") {
|
||||
match self.value_of_lossy("encoding") {
|
||||
None => Ok(None),
|
||||
Some(label) => {
|
||||
if label == "auto" {
|
||||
@@ -935,6 +971,24 @@ impl<'a> ArgMatches<'a> {
|
||||
self.values_of_lossy(name).unwrap_or_else(Vec::new)
|
||||
}
|
||||
|
||||
/// Safely reads an arg value with the given name, and if it's present,
|
||||
/// tries to parse it as a usize value.
|
||||
///
|
||||
/// If the number is zero, then it is considered absent and `None` is
|
||||
/// returned.
|
||||
fn usize_of_nonzero(&self, name: &str) -> Result<Option<usize>> {
|
||||
match self.value_of_lossy(name) {
|
||||
None => Ok(None),
|
||||
Some(v) => v.parse().map_err(From::from).map(|n| {
|
||||
if n == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(n)
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// Safely reads an arg value with the given name, and if it's present,
|
||||
/// tries to parse it as a usize value.
|
||||
fn usize_of(&self, name: &str) -> Result<Option<usize>> {
|
||||
@@ -943,6 +997,35 @@ impl<'a> ArgMatches<'a> {
|
||||
Some(v) => v.parse().map(Some).map_err(From::from),
|
||||
}
|
||||
}
|
||||
|
||||
// The following methods mostly dispatch to the underlying clap methods
|
||||
// directly. Methods that would otherwise get a single value will fetch
|
||||
// all values and return the last one. (Clap returns the first one.) We
|
||||
// only define the ones we need.
|
||||
|
||||
fn is_present(&self, name: &str) -> bool {
|
||||
self.0.is_present(name)
|
||||
}
|
||||
|
||||
fn occurrences_of(&self, name: &str) -> u64 {
|
||||
self.0.occurrences_of(name)
|
||||
}
|
||||
|
||||
fn value_of_lossy(&self, name: &str) -> Option<String> {
|
||||
self.0.value_of_lossy(name).map(|s| s.into_owned())
|
||||
}
|
||||
|
||||
fn values_of_lossy(&self, name: &str) -> Option<Vec<String>> {
|
||||
self.0.values_of_lossy(name)
|
||||
}
|
||||
|
||||
fn value_of_os(&'a self, name: &str) -> Option<&'a OsStr> {
|
||||
self.0.value_of_os(name)
|
||||
}
|
||||
|
||||
fn values_of_os(&'a self, name: &str) -> Option<clap::OsValues<'a>> {
|
||||
self.0.values_of_os(name)
|
||||
}
|
||||
}
|
||||
|
||||
fn pattern_to_str(s: &OsStr) -> Result<&str> {
|
||||
|
195
src/config.rs
Normal file
195
src/config.rs
Normal file
@@ -0,0 +1,195 @@
|
||||
// This module provides routines for reading ripgrep config "rc" files. The
|
||||
// primary output of these routines is a sequence of arguments, where each
|
||||
// argument corresponds precisely to one shell argument.
|
||||
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::io::{self, BufRead};
|
||||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use Result;
|
||||
|
||||
/// Return a sequence of arguments derived from ripgrep rc configuration files.
|
||||
///
|
||||
/// If no_messages is false and there was a problem reading a config file,
|
||||
/// then errors are printed to stderr.
|
||||
pub fn args(no_messages: bool) -> Vec<OsString> {
|
||||
let config_path = match env::var_os("RIPGREP_CONFIG_PATH") {
|
||||
None => return vec![],
|
||||
Some(config_path) => {
|
||||
if config_path.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
PathBuf::from(config_path)
|
||||
}
|
||||
};
|
||||
let (args, errs) = match parse(&config_path) {
|
||||
Ok((args, errs)) => (args, errs),
|
||||
Err(err) => {
|
||||
if !no_messages {
|
||||
eprintln!("{}", err);
|
||||
}
|
||||
return vec![];
|
||||
}
|
||||
};
|
||||
if !no_messages && !errs.is_empty() {
|
||||
for err in errs {
|
||||
eprintln!("{}:{}", config_path.display(), err);
|
||||
}
|
||||
}
|
||||
debug!(
|
||||
"{}: arguments loaded from config file: {:?}",
|
||||
config_path.display(), args);
|
||||
args
|
||||
}
|
||||
|
||||
/// Parse a single ripgrep rc file from the given path.
|
||||
///
|
||||
/// On success, this returns a set of shell arguments, in order, that should
|
||||
/// be pre-pended to the arguments given to ripgrep at the command line.
|
||||
///
|
||||
/// If the file could not be read, then an error is returned. If there was
|
||||
/// a problem parsing one or more lines in the file, then errors are returned
|
||||
/// for each line in addition to successfully parsed arguments.
|
||||
fn parse<P: AsRef<Path>>(
|
||||
path: P,
|
||||
) -> Result<(Vec<OsString>, Vec<Box<Error>>)> {
|
||||
let path = path.as_ref();
|
||||
match File::open(&path) {
|
||||
Ok(file) => parse_reader(file),
|
||||
Err(err) => errored!("{}: {}", path.display(), err),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a single ripgrep rc file from the given reader.
|
||||
///
|
||||
/// Callers should not provided a buffered reader, as this routine will use its
|
||||
/// own buffer internally.
|
||||
///
|
||||
/// On success, this returns a set of shell arguments, in order, that should
|
||||
/// be pre-pended to the arguments given to ripgrep at the command line.
|
||||
///
|
||||
/// If the reader could not be read, then an error is returned. If there was a
|
||||
/// problem parsing one or more lines, then errors are returned for each line
|
||||
/// in addition to successfully parsed arguments.
|
||||
fn parse_reader<R: io::Read>(
|
||||
rdr: R,
|
||||
) -> Result<(Vec<OsString>, Vec<Box<Error>>)> {
|
||||
let mut bufrdr = io::BufReader::new(rdr);
|
||||
let (mut args, mut errs) = (vec![], vec![]);
|
||||
let mut line = vec![];
|
||||
let mut line_number = 0;
|
||||
while {
|
||||
line.clear();
|
||||
line_number += 1;
|
||||
bufrdr.read_until(b'\n', &mut line)? > 0
|
||||
} {
|
||||
trim(&mut line);
|
||||
if line.is_empty() || line[0] == b'#' {
|
||||
continue;
|
||||
}
|
||||
match bytes_to_os_string(&line) {
|
||||
Ok(osstr) => {
|
||||
args.push(osstr);
|
||||
}
|
||||
Err(err) => {
|
||||
errs.push(format!("{}: {}", line_number, err).into());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok((args, errs))
|
||||
}
|
||||
|
||||
/// Trim the given bytes of whitespace according to the ASCII definition.
|
||||
fn trim(x: &mut Vec<u8>) {
|
||||
let upto = x.iter().take_while(|b| is_space(**b)).count();
|
||||
x.drain(..upto);
|
||||
let revto = x.len() - x.iter().rev().take_while(|b| is_space(**b)).count();
|
||||
x.drain(revto..);
|
||||
}
|
||||
|
||||
/// Returns true if and only if the given byte is an ASCII space character.
|
||||
fn is_space(b: u8) -> bool {
|
||||
b == b'\t'
|
||||
|| b == b'\n'
|
||||
|| b == b'\x0B'
|
||||
|| b == b'\x0C'
|
||||
|| b == b'\r'
|
||||
|| b == b' '
|
||||
}
|
||||
|
||||
/// On Unix, get an OsString from raw bytes.
|
||||
#[cfg(unix)]
|
||||
fn bytes_to_os_string(bytes: &[u8]) -> Result<OsString> {
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
Ok(OsString::from_vec(bytes.to_vec()))
|
||||
}
|
||||
|
||||
/// On non-Unix (like Windows), require UTF-8.
|
||||
#[cfg(not(unix))]
|
||||
fn bytes_to_os_string(bytes: &[u8]) -> Result<OsString> {
|
||||
String::from_utf8(bytes.to_vec()).map(OsString::from).map_err(From::from)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::ffi::OsString;
|
||||
use super::parse_reader;
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
let (args, errs) = parse_reader(&b"\
|
||||
# Test
|
||||
--context=0
|
||||
--smart-case
|
||||
-u
|
||||
|
||||
|
||||
# --bar
|
||||
--foo
|
||||
"[..]).unwrap();
|
||||
assert!(errs.is_empty());
|
||||
let args: Vec<String> =
|
||||
args.into_iter().map(|s| s.into_string().unwrap()).collect();
|
||||
assert_eq!(args, vec![
|
||||
"--context=0", "--smart-case", "-u", "--foo",
|
||||
]);
|
||||
}
|
||||
|
||||
// We test that we can handle invalid UTF-8 on Unix-like systems.
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn error() {
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
|
||||
let (args, errs) = parse_reader(&b"\
|
||||
quux
|
||||
foo\xFFbar
|
||||
baz
|
||||
"[..]).unwrap();
|
||||
assert!(errs.is_empty());
|
||||
assert_eq!(args, vec![
|
||||
OsString::from("quux"),
|
||||
OsString::from_vec(b"foo\xFFbar".to_vec()),
|
||||
OsString::from("baz"),
|
||||
]);
|
||||
}
|
||||
|
||||
// ... but test that invalid UTF-8 fails on Windows.
|
||||
#[test]
|
||||
#[cfg(not(unix))]
|
||||
fn error() {
|
||||
let (args, errs) = parse_reader(&b"\
|
||||
quux
|
||||
foo\xFFbar
|
||||
baz
|
||||
"[..]).unwrap();
|
||||
assert_eq!(errs.len(), 1);
|
||||
assert_eq!(args, vec![
|
||||
OsString::from("quux"),
|
||||
OsString::from("baz"),
|
||||
]);
|
||||
}
|
||||
}
|
57
src/logger.rs
Normal file
57
src/logger.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
// This module defines a super simple logger that works with the `log` crate.
|
||||
// We don't need anything fancy; just basic log levels and the ability to
|
||||
// print to stderr. We therefore avoid bringing in extra dependencies just
|
||||
// for this functionality.
|
||||
|
||||
use log::{self, Log};
|
||||
|
||||
/// The simplest possible logger that logs to stderr.
|
||||
///
|
||||
/// This logger does no filtering. Instead, it relies on the `log` crates
|
||||
/// filtering via its global max_level setting.
|
||||
#[derive(Debug)]
|
||||
pub struct Logger(());
|
||||
|
||||
const LOGGER: &'static Logger = &Logger(());
|
||||
|
||||
impl Logger {
|
||||
/// Create a new logger that logs to stderr and initialize it as the
|
||||
/// global logger. If there was a problem setting the logger, then an
|
||||
/// error is returned.
|
||||
pub fn init() -> Result<(), log::SetLoggerError> {
|
||||
log::set_logger(LOGGER)
|
||||
}
|
||||
}
|
||||
|
||||
impl Log for Logger {
|
||||
fn enabled(&self, _: &log::Metadata) -> bool {
|
||||
// We set the log level via log::set_max_level, so we don't need to
|
||||
// implement filtering here.
|
||||
true
|
||||
}
|
||||
|
||||
fn log(&self, record: &log::Record) {
|
||||
match (record.file(), record.line()) {
|
||||
(Some(file), Some(line)) => {
|
||||
eprintln!(
|
||||
"{}/{}/{}:{}: {}",
|
||||
record.level(), record.target(),
|
||||
file, line, record.args());
|
||||
}
|
||||
(Some(file), None) => {
|
||||
eprintln!(
|
||||
"{}/{}/{}: {}",
|
||||
record.level(), record.target(), file, record.args());
|
||||
}
|
||||
_ => {
|
||||
eprintln!(
|
||||
"{}/{}: {}",
|
||||
record.level(), record.target(), record.args());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {
|
||||
// We use eprintln! which is flushed on every call.
|
||||
}
|
||||
}
|
@@ -3,7 +3,6 @@ extern crate bytecount;
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate encoding_rs;
|
||||
extern crate env_logger;
|
||||
extern crate globset;
|
||||
extern crate grep;
|
||||
extern crate ignore;
|
||||
@@ -40,8 +39,10 @@ macro_rules! errored {
|
||||
|
||||
mod app;
|
||||
mod args;
|
||||
mod config;
|
||||
mod decoder;
|
||||
mod decompressor;
|
||||
mod logger;
|
||||
mod pathutil;
|
||||
mod printer;
|
||||
mod search_buffer;
|
||||
@@ -49,7 +50,7 @@ mod search_stream;
|
||||
mod unescape;
|
||||
mod worker;
|
||||
|
||||
pub type Result<T> = result::Result<T, Box<Error + Send + Sync>>;
|
||||
pub type Result<T> = result::Result<T, Box<Error>>;
|
||||
|
||||
fn main() {
|
||||
reset_sigpipe();
|
||||
|
@@ -555,7 +555,8 @@ impl fmt::Display for Error {
|
||||
}
|
||||
Error::UnrecognizedStyle(ref name) => {
|
||||
write!(f, "Unrecognized style attribute '{}'. Choose from: \
|
||||
nobold, bold, nointense, intense.", name)
|
||||
nobold, bold, nointense, intense, nounderline, \
|
||||
underline.", name)
|
||||
}
|
||||
Error::InvalidFormat(ref original) => {
|
||||
write!(
|
||||
@@ -627,7 +628,8 @@ pub struct ColorSpecs {
|
||||
/// Valid colors are `black`, `blue`, `green`, `red`, `cyan`, `magenta`,
|
||||
/// `yellow`, `white`.
|
||||
///
|
||||
/// Valid style instructions are `nobold`, `bold`, `intense`, `nointense`.
|
||||
/// Valid style instructions are `nobold`, `bold`, `intense`, `nointense`,
|
||||
/// `underline`, `nounderline`.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Spec {
|
||||
ty: OutType,
|
||||
@@ -668,6 +670,8 @@ enum Style {
|
||||
NoBold,
|
||||
Intense,
|
||||
NoIntense,
|
||||
Underline,
|
||||
NoUnderline
|
||||
}
|
||||
|
||||
impl ColorSpecs {
|
||||
@@ -727,6 +731,8 @@ impl SpecValue {
|
||||
Style::NoBold => { cspec.set_bold(false); }
|
||||
Style::Intense => { cspec.set_intense(true); }
|
||||
Style::NoIntense => { cspec.set_intense(false); }
|
||||
Style::Underline => { cspec.set_underline(true); }
|
||||
Style::NoUnderline => { cspec.set_underline(false); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -806,6 +812,8 @@ impl FromStr for Style {
|
||||
"nobold" => Ok(Style::NoBold),
|
||||
"intense" => Ok(Style::Intense),
|
||||
"nointense" => Ok(Style::NoIntense),
|
||||
"underline" => Ok(Style::Underline),
|
||||
"nounderline" => Ok(Style::NoUnderline),
|
||||
_ => Err(Error::UnrecognizedStyle(s.to_string())),
|
||||
}
|
||||
}
|
||||
@@ -859,6 +867,12 @@ mod tests {
|
||||
value: SpecValue::Style(Style::Intense),
|
||||
});
|
||||
|
||||
let spec: Spec = "match:style:underline".parse().unwrap();
|
||||
assert_eq!(spec, Spec {
|
||||
ty: OutType::Match,
|
||||
value: SpecValue::Style(Style::Underline),
|
||||
});
|
||||
|
||||
let spec: Spec = "line:none".parse().unwrap();
|
||||
assert_eq!(spec, Spec {
|
||||
ty: OutType::Line,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "termcolor"
|
||||
version = "0.3.3" #:version
|
||||
version = "0.3.4" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
A simple cross platform library for writing colored text to a terminal.
|
||||
@@ -17,4 +17,4 @@ name = "termcolor"
|
||||
bench = false
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
wincolor = { version = "0.1.3", path = "../wincolor" }
|
||||
wincolor = { version = "0.1.6", path = "../wincolor" }
|
||||
|
@@ -104,7 +104,7 @@ pub trait WriteColor: io::Write {
|
||||
fn reset(&mut self) -> io::Result<()>;
|
||||
}
|
||||
|
||||
impl<'a, T: WriteColor> WriteColor for &'a mut T {
|
||||
impl<'a, T: ?Sized + WriteColor> WriteColor for &'a mut T {
|
||||
fn supports_color(&self) -> bool { (&**self).supports_color() }
|
||||
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
|
||||
(&mut **self).set_color(spec)
|
||||
@@ -239,7 +239,7 @@ impl io::Write for IoStandardStream {
|
||||
}
|
||||
}
|
||||
|
||||
/// Same rigmarole for the locked variants of the standard streams.
|
||||
// Same rigmarole for the locked variants of the standard streams.
|
||||
|
||||
enum IoStandardStreamLock<'a> {
|
||||
StdoutLock(io::StdoutLock<'a>),
|
||||
@@ -328,14 +328,17 @@ impl StandardStream {
|
||||
/// the `WriteColor` trait.
|
||||
#[cfg(windows)]
|
||||
fn create(sty: StandardStreamType, choice: ColorChoice) -> StandardStream {
|
||||
let con = match sty {
|
||||
let mut con = match sty {
|
||||
StandardStreamType::Stdout => wincolor::Console::stdout(),
|
||||
StandardStreamType::Stderr => wincolor::Console::stderr(),
|
||||
};
|
||||
let is_win_console = con.is_ok();
|
||||
let is_console_virtual = con.as_mut().map(|con| {
|
||||
con.set_virtual_terminal_processing(true).is_ok()
|
||||
}).unwrap_or(false);
|
||||
let wtr =
|
||||
if choice.should_attempt_color() {
|
||||
if choice.should_ansi() {
|
||||
if choice.should_ansi() || is_console_virtual {
|
||||
WriterInner::Ansi(Ansi(IoStandardStream::new(sty)))
|
||||
} else if let Ok(console) = con {
|
||||
WriterInner::Windows {
|
||||
@@ -612,10 +615,18 @@ impl BufferWriter {
|
||||
/// the buffers themselves.
|
||||
#[cfg(windows)]
|
||||
fn create(sty: StandardStreamType, choice: ColorChoice) -> BufferWriter {
|
||||
let con = match sty {
|
||||
let mut con = match sty {
|
||||
StandardStreamType::Stdout => wincolor::Console::stdout(),
|
||||
StandardStreamType::Stderr => wincolor::Console::stderr(),
|
||||
}.ok().map(Mutex::new);
|
||||
}.ok();
|
||||
let is_console_virtual = con.as_mut().map(|con| {
|
||||
con.set_virtual_terminal_processing(true).is_ok()
|
||||
}).unwrap_or(false);
|
||||
// If we can enable ANSI on Windows, then we don't need the console
|
||||
// anymore.
|
||||
if is_console_virtual {
|
||||
con = None;
|
||||
}
|
||||
let stream = LossyStandardStream::new(IoStandardStream::new(sty))
|
||||
.is_console(con.is_some());
|
||||
BufferWriter {
|
||||
@@ -623,7 +634,7 @@ impl BufferWriter {
|
||||
printed: AtomicBool::new(false),
|
||||
separator: None,
|
||||
color_choice: choice,
|
||||
console: con,
|
||||
console: con.map(Mutex::new),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -969,6 +980,9 @@ impl<W: io::Write> WriteColor for Ansi<W> {
|
||||
if spec.bold {
|
||||
self.write_str("\x1B[1m")?;
|
||||
}
|
||||
if spec.underline {
|
||||
self.write_str("\x1B[4m")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1201,6 +1215,7 @@ pub struct ColorSpec {
|
||||
bg_color: Option<Color>,
|
||||
bold: bool,
|
||||
intense: bool,
|
||||
underline: bool,
|
||||
}
|
||||
|
||||
impl ColorSpec {
|
||||
@@ -1240,10 +1255,37 @@ impl ColorSpec {
|
||||
self
|
||||
}
|
||||
|
||||
/// Get whether this is underline or not.
|
||||
///
|
||||
/// Note that the underline setting has no effect in a Windows console.
|
||||
pub fn underline(&self) -> bool { self.underline }
|
||||
|
||||
/// Set whether the text is underlined or not.
|
||||
///
|
||||
/// Note that the underline setting has no effect in a Windows console.
|
||||
pub fn set_underline(&mut self, yes: bool) -> &mut ColorSpec {
|
||||
self.underline = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Get whether this is intense or not.
|
||||
///
|
||||
/// On Unix-like systems, this will output the ANSI escape sequence
|
||||
/// that will print a high-intensity version of the color
|
||||
/// specified.
|
||||
///
|
||||
/// On Windows systems, this will output the ANSI escape sequence
|
||||
/// that will print a brighter version of the color specified.
|
||||
pub fn intense(&self) -> bool { self.intense }
|
||||
|
||||
/// Set whether the text is intense or not.
|
||||
///
|
||||
/// On Unix-like systems, this will output the ANSI escape sequence
|
||||
/// that will print a high-intensity version of the color
|
||||
/// specified.
|
||||
///
|
||||
/// On Windows systems, this will output the ANSI escape sequence
|
||||
/// that will print a brighter version of the color specified.
|
||||
pub fn set_intense(&mut self, yes: bool) -> &mut ColorSpec {
|
||||
self.intense = yes;
|
||||
self
|
||||
@@ -1251,7 +1293,8 @@ impl ColorSpec {
|
||||
|
||||
/// Returns true if this color specification has no colors or styles.
|
||||
pub fn is_none(&self) -> bool {
|
||||
self.fg_color.is_none() && self.bg_color.is_none() && !self.bold
|
||||
self.fg_color.is_none() && self.bg_color.is_none()
|
||||
&& !self.bold && !self.underline
|
||||
}
|
||||
|
||||
/// Clears this color specification so that it has no color/style settings.
|
||||
@@ -1259,6 +1302,7 @@ impl ColorSpec {
|
||||
self.fg_color = None;
|
||||
self.bg_color = None;
|
||||
self.bold = false;
|
||||
self.underline = false;
|
||||
}
|
||||
|
||||
/// Writes this color spec to the given Windows console.
|
||||
@@ -1293,7 +1337,18 @@ impl ColorSpec {
|
||||
/// on Windows using the console. If they are used on Windows, then they are
|
||||
/// silently ignored and no colors will be emitted.
|
||||
///
|
||||
/// Note that this set may expand over time.
|
||||
/// This set may expand over time.
|
||||
///
|
||||
/// This type has a `FromStr` impl that can parse colors from their human
|
||||
/// readable form. The format is as follows:
|
||||
///
|
||||
/// 1. Any of the explicitly listed colors in English. They are matched
|
||||
/// case insensitively.
|
||||
/// 2. A single 8-bit integer, in either decimal or hexadecimal format.
|
||||
/// 3. A triple of 8-bit integers separated by a comma, where each integer is
|
||||
/// in decimal or hexadecimal format.
|
||||
///
|
||||
/// Hexadecimal numbers are written with a `0x` prefix.
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Color {
|
||||
@@ -1311,9 +1366,9 @@ pub enum Color {
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl Color {
|
||||
/// Translate this color to a wincolor::Color.
|
||||
#[cfg(windows)]
|
||||
fn to_windows(&self) -> Option<wincolor::Color> {
|
||||
match *self {
|
||||
Color::Black => Some(wincolor::Color::Black),
|
||||
@@ -1329,6 +1384,68 @@ impl Color {
|
||||
Color::__Nonexhaustive => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a numeric color string, either ANSI or RGB.
|
||||
fn from_str_numeric(s: &str) -> Result<Color, ParseColorError> {
|
||||
// The "ansi256" format is a single number (decimal or hex)
|
||||
// corresponding to one of 256 colors.
|
||||
//
|
||||
// The "rgb" format is a triple of numbers (decimal or hex) delimited
|
||||
// by a comma corresponding to one of 256^3 colors.
|
||||
|
||||
fn parse_number(s: &str) -> Option<u8> {
|
||||
use std::u8;
|
||||
|
||||
if s.starts_with("0x") {
|
||||
u8::from_str_radix(&s[2..], 16).ok()
|
||||
} else {
|
||||
u8::from_str_radix(s, 10).ok()
|
||||
}
|
||||
}
|
||||
|
||||
let codes: Vec<&str> = s.split(',').collect();
|
||||
if codes.len() == 1 {
|
||||
if let Some(n) = parse_number(&codes[0]) {
|
||||
Ok(Color::Ansi256(n))
|
||||
} else {
|
||||
if s.chars().all(|c| c.is_digit(16)) {
|
||||
Err(ParseColorError {
|
||||
kind: ParseColorErrorKind::InvalidAnsi256,
|
||||
given: s.to_string(),
|
||||
})
|
||||
} else {
|
||||
Err(ParseColorError {
|
||||
kind: ParseColorErrorKind::InvalidName,
|
||||
given: s.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if codes.len() == 3 {
|
||||
let mut v = vec![];
|
||||
for code in codes {
|
||||
let n = parse_number(code).ok_or_else(|| {
|
||||
ParseColorError {
|
||||
kind: ParseColorErrorKind::InvalidRgb,
|
||||
given: s.to_string(),
|
||||
}
|
||||
})?;
|
||||
v.push(n);
|
||||
}
|
||||
Ok(Color::Rgb(v[0], v[1], v[2]))
|
||||
} else {
|
||||
Err(if s.contains(",") {
|
||||
ParseColorError {
|
||||
kind: ParseColorErrorKind::InvalidRgb,
|
||||
given: s.to_string(),
|
||||
}
|
||||
} else {
|
||||
ParseColorError {
|
||||
kind: ParseColorErrorKind::InvalidName,
|
||||
given: s.to_string(),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An error from parsing an invalid color specification.
|
||||
@@ -1373,13 +1490,13 @@ impl fmt::Display for ParseColorError {
|
||||
}
|
||||
InvalidAnsi256 => {
|
||||
write!(f, "unrecognized ansi256 color number, \
|
||||
should be '[0-255]', but is '{}'",
|
||||
should be '[0-255]' (or a hex number), but is '{}'",
|
||||
self.given)
|
||||
}
|
||||
InvalidRgb => {
|
||||
write!(f, "unrecognized RGB color triple, \
|
||||
should be '[0-255],[0-255],[0-255]', but is '{}'",
|
||||
self.given)
|
||||
should be '[0-255],[0-255],[0-255]' (or a hex \
|
||||
triple), but is '{}'", self.given)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1398,52 +1515,7 @@ impl FromStr for Color {
|
||||
"magenta" => Ok(Color::Magenta),
|
||||
"yellow" => Ok(Color::Yellow),
|
||||
"white" => Ok(Color::White),
|
||||
_ => {
|
||||
// - Ansi256: '[0-255]'
|
||||
// - Rgb: '[0-255],[0-255],[0-255]'
|
||||
let codes: Vec<&str> = s.split(',').collect();
|
||||
if codes.len() == 1 {
|
||||
if let Ok(n) = codes[0].parse::<u8>() {
|
||||
Ok(Color::Ansi256(n))
|
||||
} else {
|
||||
if s.chars().all(|c| c.is_digit(10)) {
|
||||
Err(ParseColorError {
|
||||
kind: ParseColorErrorKind::InvalidAnsi256,
|
||||
given: s.to_string(),
|
||||
})
|
||||
} else {
|
||||
Err(ParseColorError {
|
||||
kind: ParseColorErrorKind::InvalidName,
|
||||
given: s.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if codes.len() == 3 {
|
||||
let mut v = vec![];
|
||||
for code in codes {
|
||||
let n = code.parse::<u8>().map_err(|_| {
|
||||
ParseColorError {
|
||||
kind: ParseColorErrorKind::InvalidRgb,
|
||||
given: s.to_string(),
|
||||
}
|
||||
})?;
|
||||
v.push(n);
|
||||
}
|
||||
Ok(Color::Rgb(v[0], v[1], v[2]))
|
||||
} else {
|
||||
Err(if s.contains(",") {
|
||||
ParseColorError {
|
||||
kind: ParseColorErrorKind::InvalidRgb,
|
||||
given: s.to_string(),
|
||||
}
|
||||
} else {
|
||||
ParseColorError {
|
||||
kind: ParseColorErrorKind::InvalidName,
|
||||
given: s.to_string(),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => Color::from_str_numeric(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1550,9 +1622,11 @@ mod tests {
|
||||
let color = "7".parse::<Color>();
|
||||
assert_eq!(color, Ok(Color::Ansi256(7)));
|
||||
|
||||
// In range of standard color codes
|
||||
let color = "32".parse::<Color>();
|
||||
assert_eq!(color, Ok(Color::Ansi256(32)));
|
||||
|
||||
let color = "0xFF".parse::<Color>();
|
||||
assert_eq!(color, Ok(Color::Ansi256(0xFF)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1571,6 +1645,12 @@ mod tests {
|
||||
|
||||
let color = "0,128,255".parse::<Color>();
|
||||
assert_eq!(color, Ok(Color::Rgb(0, 128, 255)));
|
||||
|
||||
let color = "0x0,0x0,0x0".parse::<Color>();
|
||||
assert_eq!(color, Ok(Color::Rgb(0, 0, 0)));
|
||||
|
||||
let color = "0x33,0x66,0xFF".parse::<Color>();
|
||||
assert_eq!(color, Ok(Color::Rgb(0x33, 0x66, 0xFF)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@@ -1152,7 +1152,8 @@ clean!(regression_428_unrecognized_style, "Sherlok", ".",
|
||||
let output = cmd.output().unwrap();
|
||||
let err = String::from_utf8_lossy(&output.stderr);
|
||||
let expected = "\
|
||||
Unrecognized style attribute ''. Choose from: nobold, bold, nointense, intense.
|
||||
Unrecognized style attribute ''. Choose from: nobold, bold, nointense, intense, \
|
||||
nounderline, underline.
|
||||
";
|
||||
assert_eq!(err, expected);
|
||||
});
|
||||
@@ -1166,6 +1167,49 @@ clean!(regression_493, " 're ", "input.txt", |wd: WorkDir, mut cmd: Command| {
|
||||
assert_eq!(lines, " 're \n");
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/553
|
||||
sherlock!(regression_553_switch, "sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-i");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
|
||||
// This repeats the `-i` flag.
|
||||
cmd.arg("-i");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(regression_553_flag, "world|attached",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-C").arg("1");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
Holmeses, success in the province of detective work must always
|
||||
--
|
||||
but Doctor Watson has to have it taken out for him and dusted,
|
||||
and exhibited clearly, with a label attached.
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
|
||||
cmd.arg("-C").arg("0");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
and exhibited clearly, with a label attached.
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/599
|
||||
clean!(regression_599, "^$", "input.txt", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("input.txt", "\n\ntest\n");
|
||||
@@ -1189,6 +1233,19 @@ clean!(regression_599, "^$", "input.txt", |wd: WorkDir, mut cmd: Command| {
|
||||
assert_eq!(expected, lines);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/807
|
||||
clean!(regression_807, "test", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create(".gitignore", ".a/b");
|
||||
wd.create_dir(".a/b");
|
||||
wd.create_dir(".a/c");
|
||||
wd.create(".a/b/file", "test");
|
||||
wd.create(".a/c/file", "test");
|
||||
|
||||
cmd.arg("--hidden");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, format!("{}:test\n", path(".a/c/file")));
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/1
|
||||
clean!(feature_1_sjis, "Шерлок Холмс", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
let sherlock =
|
||||
@@ -1711,6 +1768,22 @@ fn compressed_failing_gzip() {
|
||||
assert_eq!(err.contains("not in gzip format"), true);
|
||||
}
|
||||
|
||||
sherlock!(feature_196_persistent_config, "sherlock",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
// Make sure we get no matches by default.
|
||||
wd.assert_err(&mut cmd);
|
||||
|
||||
// Now add our config file, and make sure it impacts ripgrep.
|
||||
wd.create(".ripgreprc", "--ignore-case");
|
||||
cmd.env("RIPGREP_CONFIG_PATH", ".ripgreprc");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
#[test]
|
||||
fn feature_740_passthru() {
|
||||
let wd = WorkDir::new("feature_740");
|
||||
|
@@ -93,6 +93,7 @@ impl WorkDir {
|
||||
/// this working directory.
|
||||
pub fn command(&self) -> process::Command {
|
||||
let mut cmd = process::Command::new(&self.bin());
|
||||
cmd.env_remove("RIPGREP_CONFIG_PATH");
|
||||
cmd.current_dir(&self.dir);
|
||||
cmd
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wincolor"
|
||||
version = "0.1.5" #:version
|
||||
version = "0.1.6" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
A simple Windows specific API for controlling text color in a Windows console.
|
||||
@@ -16,5 +16,6 @@ license = "Unlicense/MIT"
|
||||
name = "wincolor"
|
||||
bench = false
|
||||
|
||||
[dependencies]
|
||||
winapi = { version = "0.3", features = ["minwindef", "processenv", "winbase", "wincon"] }
|
||||
[dependencies.winapi]
|
||||
version = "0.3"
|
||||
features = ["consoleapi", "minwindef", "processenv", "winbase", "wincon"]
|
||||
|
@@ -2,6 +2,7 @@ use std::io;
|
||||
use std::mem;
|
||||
|
||||
use winapi::shared::minwindef::{DWORD, WORD};
|
||||
use winapi::um::consoleapi;
|
||||
use winapi::um::processenv;
|
||||
use winapi::um::winbase::{STD_ERROR_HANDLE, STD_OUTPUT_HANDLE};
|
||||
use winapi::um::wincon::{
|
||||
@@ -115,6 +116,41 @@ impl Console {
|
||||
self.cur_attr = self.start_attr;
|
||||
self.set()
|
||||
}
|
||||
|
||||
/// Toggle virtual terminal processing.
|
||||
///
|
||||
/// This method attempts to toggle virtual terminal processing for this
|
||||
/// console. If there was a problem toggling it, then an error returned.
|
||||
/// On success, the caller may assume that toggling it was successful.
|
||||
///
|
||||
/// When virtual terminal processing is enabled, characters emitted to the
|
||||
/// console are parsed for VT100 and similar control character sequences
|
||||
/// that control color and other similar operations.
|
||||
pub fn set_virtual_terminal_processing(
|
||||
&mut self,
|
||||
yes: bool,
|
||||
) -> io::Result<()> {
|
||||
let vt = wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
|
||||
let mut old_mode = 0;
|
||||
let handle = unsafe { processenv::GetStdHandle(self.handle_id) };
|
||||
if unsafe { consoleapi::GetConsoleMode(handle, &mut old_mode) } == 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
let new_mode =
|
||||
if yes {
|
||||
old_mode | vt
|
||||
} else {
|
||||
old_mode & !vt
|
||||
};
|
||||
if old_mode == new_mode {
|
||||
return Ok(());
|
||||
}
|
||||
if unsafe { consoleapi::SetConsoleMode(handle, new_mode) } == 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A representation of text attributes for the Windows console.
|
||||
|
Reference in New Issue
Block a user