mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-07-28 18:51:58 -07:00
Compare commits
83 Commits
ignore-0.2
...
0.7.1
Author | SHA1 | Date | |
---|---|---|---|
|
c4e1945384 | ||
|
04d17040e7 | ||
|
8c8c83a1f8 | ||
|
5714dbde09 | ||
|
311ccb1f6b | ||
|
efa4de8126 | ||
|
ad5fa56490 | ||
|
1bf9d29259 | ||
|
2a14bf2249 | ||
|
f0028a66ec | ||
|
08060a2105 | ||
|
cd575d99f8 | ||
|
1267f01c24 | ||
|
322d5515e5 | ||
|
f4770c2094 | ||
|
f887bc1f86 | ||
|
363a4fa9b7 | ||
|
712311fdc6 | ||
|
0d2354aca6 | ||
|
8dc513b5d2 | ||
|
a98156e71c | ||
|
cf94072429 | ||
|
db14046de4 | ||
|
36091591f0 | ||
|
12ffcb4296 | ||
|
e7c06b92fb | ||
|
353806b87a | ||
|
aebb132a86 | ||
|
ab4b6ab9c3 | ||
|
413178bc2c | ||
|
58fb4f987e | ||
|
4f1d6af296 | ||
|
6b79349f83 | ||
|
f858828f61 | ||
|
67b835fe2a | ||
|
214f2bef66 | ||
|
1136f8adab | ||
|
beb010d004 | ||
|
f9cbf7d3d4 | ||
|
7eb1dd129e | ||
|
a5f82e8826 | ||
|
ca6bd648ab | ||
|
af77dd55a2 | ||
|
3065a8c9c8 | ||
|
208c11af56 | ||
|
12a78a992c | ||
|
d97c80be63 | ||
|
5213bd30ea | ||
|
82d101907a | ||
|
30608f2444 | ||
|
3d323928a0 | ||
|
8b6a3bc858 | ||
|
e10544f819 | ||
|
dc7e39a6ba | ||
|
36c16eb00c | ||
|
fffee61f80 | ||
|
4cfb2b515b | ||
|
398326bfe2 | ||
|
01358a155c | ||
|
30ca3ecca6 | ||
|
dbc91644fd | ||
|
73c9ac4da5 | ||
|
fe7fe74b0a | ||
|
3d9acdab18 | ||
|
40bacbcd7c | ||
|
b3a9c34515 | ||
|
972ec1adc6 | ||
|
a2d4c03c71 | ||
|
b7c3cf314d | ||
|
6dce04963d | ||
|
d4b790fd8d | ||
|
9283dd122e | ||
|
4c41e9225b | ||
|
9f2b054550 | ||
|
5613df3034 | ||
|
79ad81626f | ||
|
354a5cad97 | ||
|
92e5fad27d | ||
|
f86f987d71 | ||
|
bfbd53eb92 | ||
|
0668c74ed4 | ||
|
1c03298903 | ||
|
e0e8f26c56 |
19
.travis.yml
19
.travis.yml
@@ -4,19 +4,26 @@ env:
|
||||
global:
|
||||
- PROJECT_NAME=ripgrep
|
||||
- RUST_BACKTRACE: full
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# Needed for completion-function test
|
||||
- zsh
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# Nightly channel.
|
||||
# (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-2017-03-13
|
||||
rust: nightly
|
||||
env: TARGET=i686-unknown-linux-musl
|
||||
- os: linux
|
||||
rust: nightly-2017-03-13
|
||||
rust: nightly
|
||||
env: TARGET=x86_64-unknown-linux-musl
|
||||
- os: osx
|
||||
rust: nightly-2017-03-13
|
||||
rust: nightly
|
||||
env: TARGET=x86_64-apple-darwin
|
||||
# Beta channel.
|
||||
- os: linux
|
||||
@@ -27,10 +34,10 @@ matrix:
|
||||
env: TARGET=x86_64-unknown-linux-gnu
|
||||
# Minimum Rust supported channel.
|
||||
- os: linux
|
||||
rust: 1.12.0
|
||||
rust: 1.17.0
|
||||
env: TARGET=x86_64-unknown-linux-gnu
|
||||
- os: linux
|
||||
rust: 1.12.0
|
||||
rust: 1.17.0
|
||||
env: TARGET=x86_64-unknown-linux-musl
|
||||
|
||||
before_install:
|
||||
@@ -58,7 +65,7 @@ deploy:
|
||||
# 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-2017-03-13
|
||||
condition: $TRAVIS_RUST_VERSION = nightly
|
||||
tags: true
|
||||
|
||||
branches:
|
||||
|
115
CHANGELOG.md
115
CHANGELOG.md
@@ -1,3 +1,118 @@
|
||||
0.7.1 (2017-10-22)
|
||||
==================
|
||||
This is a patch release of ripgrep that includes a fix to very bad regression
|
||||
introduced in ripgrep 0.7.0.
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* [BUG #648](https://github.com/BurntSushi/ripgrep/issues/648):
|
||||
Fix a bug where it was very easy to exceed standard file descriptor limits.
|
||||
|
||||
|
||||
0.7.0 (2017-10-20)
|
||||
==================
|
||||
This is a new minor version release of ripgrep that includes mostly bug fixes.
|
||||
|
||||
ripgrep continues to require Rust 1.17, and there are no known breaking changes
|
||||
introduced in this release.
|
||||
|
||||
Feature enhancements:
|
||||
|
||||
* Added or improved file type filtering for config & license files, Elm,
|
||||
Purescript, Standard ML, sh, systemd, Terraform
|
||||
* [FEATURE #593](https://github.com/BurntSushi/ripgrep/pull/593):
|
||||
Using both `-o/--only-matching` and `-r/--replace` does the right thing.
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* [BUG #200](https://github.com/BurntSushi/ripgrep/issues/200):
|
||||
ripgrep will stop when its pipe is closed.
|
||||
* [BUG #402](https://github.com/BurntSushi/ripgrep/issues/402):
|
||||
Fix context printing bug when the `-m/--max-count` flag is used.
|
||||
* [BUG #521](https://github.com/BurntSushi/ripgrep/issues/521):
|
||||
Fix interaction between `-r/--replace` and terminal colors.
|
||||
* [BUG #559](https://github.com/BurntSushi/ripgrep/issues/559):
|
||||
Ignore test that tried reading a non-UTF-8 file path on macOS.
|
||||
* [BUG #599](https://github.com/BurntSushi/ripgrep/issues/599):
|
||||
Fix color escapes on empty matches.
|
||||
* [BUG #600](https://github.com/BurntSushi/ripgrep/issues/600):
|
||||
Avoid expensive (on Windows) file handle check when using --files.
|
||||
* [BUG #618](https://github.com/BurntSushi/ripgrep/issues/618):
|
||||
Clarify installation instructions for Ubuntu users.
|
||||
* [BUG #633](https://github.com/BurntSushi/ripgrep/issues/633):
|
||||
Faster symlink loop checking on Windows.
|
||||
|
||||
|
||||
0.6.0 (2017-08-23)
|
||||
==================
|
||||
This is a new minor version release of ripgrep that includes many bug fixes
|
||||
and a few new features such as `--iglob` and `-x/--line-regexp`.
|
||||
|
||||
Note that this release increases the minimum supported Rust version from 1.12
|
||||
to 1.17.
|
||||
|
||||
Feature enhancements:
|
||||
|
||||
* Added or improved file type filtering for BitBake, C++, Cabal, cshtml, Julia,
|
||||
Make, msbuild, QMake, Yocto
|
||||
* [FEATURE #163](https://github.com/BurntSushi/ripgrep/issues/163):
|
||||
Add an `--iglob` flag that is like `-g/--glob`, but matches globs
|
||||
case insensitively.
|
||||
* [FEATURE #520](https://github.com/BurntSushi/ripgrep/pull/518):
|
||||
Add `-x/--line-regexp` flag, which requires a match to span an entire line.
|
||||
* [FEATURE #551](https://github.com/BurntSushi/ripgrep/pull/551),
|
||||
[FEATURE #554](https://github.com/BurntSushi/ripgrep/pull/554):
|
||||
`ignore`: add new `matched_path_or_any_parents` method.
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* [BUG #342](https://github.com/BurntSushi/ripgrep/issues/342):
|
||||
Fix invisible text in some PowerShell environments by changing the
|
||||
default color scheme on Windows.
|
||||
* [BUG #413](https://github.com/BurntSushi/ripgrep/issues/413):
|
||||
Release binaries on Unix are now `strip`'d by default. This decreases
|
||||
binary size by an order of magnitude.
|
||||
* [BUG #483](https://github.com/BurntSushi/ripgrep/issues/483):
|
||||
When `--quiet` is passed, `--files` should be quiet.
|
||||
* [BUG #488](https://github.com/BurntSushi/ripgrep/pull/488):
|
||||
When `--vimgrep` is passed, `--with-filename` should be enabled
|
||||
automatically.
|
||||
* [BUG #493](https://github.com/BurntSushi/ripgrep/issues/493):
|
||||
Fix another bug in the implementation of the `-o/--only-matching`
|
||||
flag.
|
||||
* [BUG #499](https://github.com/BurntSushi/ripgrep/pull/499):
|
||||
Permit certain flags to override others.
|
||||
* [BUG #523](https://github.com/BurntSushi/ripgrep/pull/523):
|
||||
`wincolor`: Re-fetch Windows console on all calls.
|
||||
* [BUG #523](https://github.com/BurntSushi/ripgrep/issues/524):
|
||||
`--version` now shows enabled compile-time features.
|
||||
* [BUG #532](https://github.com/BurntSushi/ripgrep/issues/532),
|
||||
[BUG #536](https://github.com/BurntSushi/ripgrep/pull/536),
|
||||
[BUG #538](https://github.com/BurntSushi/ripgrep/pull/538),
|
||||
[BUG #540](https://github.com/BurntSushi/ripgrep/pull/540),
|
||||
[BUG #560](https://github.com/BurntSushi/ripgrep/pull/560),
|
||||
[BUG #565](https://github.com/BurntSushi/ripgrep/pull/565):
|
||||
Improve zsh completion.
|
||||
* [BUG #578](https://github.com/BurntSushi/ripgrep/pull/578):
|
||||
Enable SIMD for `encoding_rs` when appropriate.
|
||||
* [BUG #580](https://github.com/BurntSushi/ripgrep/issues/580):
|
||||
Fix `-w/--word-regexp` in the presence of capturing groups.
|
||||
* [BUG #581](https://github.com/BurntSushi/ripgrep/issues/581):
|
||||
Document that ripgrep may terminate unexpectedly when searching via
|
||||
memory maps (which can happen using default settings).
|
||||
|
||||
Friends of ripgrep:
|
||||
|
||||
I'd like to give a big Thank You to @okdana for their recent hard work on
|
||||
ripgrep. This includes new features like `--line-regexp`, heroic effort on
|
||||
zsh auto-completion and thinking through some thorny argv issues with me.
|
||||
|
||||
I'd also like to thank @ericbn for their work on improving ripgrep's argv
|
||||
parsing by allowing some flags to override others.
|
||||
|
||||
Thanks @okdana and @ericbn!
|
||||
|
||||
|
||||
0.5.2 (2017-05-11)
|
||||
==================
|
||||
Feature enhancements:
|
||||
|
232
Cargo.lock
generated
232
Cargo.lock
generated
@@ -1,23 +1,23 @@
|
||||
[root]
|
||||
name = "ripgrep"
|
||||
version = "0.5.2"
|
||||
version = "0.7.1"
|
||||
dependencies = [
|
||||
"atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytecount 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.24.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding_rs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"grep 0.1.6",
|
||||
"ignore 0.2.0",
|
||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytecount 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.26.2 (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)",
|
||||
"grep 0.1.7",
|
||||
"ignore 0.3.1",
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.2",
|
||||
"same-file 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -25,7 +25,7 @@ name = "aho-corasick"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -35,45 +35,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.8.2"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bytecount"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"simd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.24.1"
|
||||
version = "2.26.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.8.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.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -83,18 +84,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.5.1"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"simd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -104,47 +106,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "fs2"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grep"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
dependencies = [
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.2.0"
|
||||
version = "0.3.1"
|
||||
dependencies = [
|
||||
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"globset 0.2.0",
|
||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"globset 0.2.1",
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -158,25 +161,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.23"
|
||||
version = "0.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.3.7"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -184,18 +195,31 @@ name = "memmap"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.4.0"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -204,10 +228,10 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -218,7 +242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "0.1.3"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -230,6 +254,11 @@ name = "simd"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "simd"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.6.0"
|
||||
@@ -241,40 +270,45 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
dependencies = [
|
||||
"wincolor 0.1.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread-id"
|
||||
version = "3.1.0"
|
||||
name = "termion"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.3"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.4"
|
||||
@@ -282,7 +316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "0.1.1"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -295,7 +329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -305,12 +339,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "1.0.7"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -334,37 +366,41 @@ dependencies = [
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
|
||||
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
|
||||
"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
|
||||
"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
|
||||
"checksum bytecount 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1e8f09fbc8c6726a4b616dcfbd4f54491068d6bb1b93ac03c78ac18ff9a5924a"
|
||||
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
|
||||
"checksum clap 2.24.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7541069be0b8aec41030802abe8b5cdef0490070afaa55418adea93b1e431e0"
|
||||
"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
|
||||
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
||||
"checksum bytecount 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4bbeb7c30341fce29f6078b4bdf876ea4779600866e98f5b2d203a534f195050"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3451e409013178663435d6f15fdb212f14ee4424a3d74f979d081d0a66b6f1f2"
|
||||
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
|
||||
"checksum encoding_rs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e4bc519d572af08cf72c4d61e0de9b05e9fa66d1fdb5e739fb5c405860b42d43"
|
||||
"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
|
||||
"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 fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
|
||||
"checksum fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34edaee07555859dc13ca387e6ae05686bb4d0364c95d649b6dab959511f4baf"
|
||||
"checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
|
||||
"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e"
|
||||
"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
|
||||
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
|
||||
"checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5"
|
||||
"checksum libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "56cce3130fd040c28df6f495c8492e5ec5808fb4c9093c310df02b0c8f030148"
|
||||
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
|
||||
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
|
||||
"checksum memchr 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e01e64d9017d18e7fc09d8e4fe0e28ff6931019e979fb8019319db7ca827f8a6"
|
||||
"checksum memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46f3c7359028b31999287dae4e5047ddfe90a23b7dca2282ce759b491080c99b"
|
||||
"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"
|
||||
"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
|
||||
"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
|
||||
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
|
||||
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
|
||||
"checksum same-file 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70a18720d745fb9ca6a041b37cb36d0b21066006b6cff8b5b360142d4b81fb60"
|
||||
"checksum simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63b5847c2d766ca7ce7227672850955802fabd779ba616aeabead4c2c3877023"
|
||||
"checksum simd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a94d14a2ae1f1f110937de5fb69e494372560181c7e1739a097fcc2cee37ba0"
|
||||
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
|
||||
"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
|
||||
"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773"
|
||||
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
|
||||
"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8e08afc40ae3459e4838f303e465aa50d823df8d7f83ca88108f6d3afe7edd"
|
||||
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
|
||||
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
||||
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
|
||||
"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.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8cdc8b93bd0198ed872357fb2e667f7125646b1762f16d60b2c96350d361897"
|
||||
"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 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
|
||||
"checksum walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b6d201f4f8998a837196b6de9c73e35af14c992cbb92c4ab641d2c2dce52de"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
28
Cargo.toml
28
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ripgrep"
|
||||
version = "0.5.2" #:version
|
||||
version = "0.7.1" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
Line oriented search tool using Rust's regex library. Combines the raw
|
||||
@@ -16,6 +16,10 @@ license = "Unlicense/MIT"
|
||||
exclude = ["HomebrewFormula"]
|
||||
build = "build.rs"
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "BurntSushi/ripgrep" }
|
||||
appveyor = { repository = "BurntSushi/ripgrep" }
|
||||
|
||||
[[bin]]
|
||||
bench = false
|
||||
path = "src/main.rs"
|
||||
@@ -28,28 +32,32 @@ path = "tests/tests.rs"
|
||||
[dependencies]
|
||||
atty = "0.2.2"
|
||||
bytecount = "0.1.4"
|
||||
clap = "2.24.1"
|
||||
encoding_rs = "0.5.0"
|
||||
clap = "2.26"
|
||||
encoding_rs = "0.7"
|
||||
env_logger = { version = "0.4", default-features = false }
|
||||
grep = { version = "0.1.5", path = "grep" }
|
||||
ignore = { version = "0.2.0", path = "ignore" }
|
||||
grep = { version = "0.1.7", path = "grep" }
|
||||
ignore = { version = "0.3.1", path = "ignore" }
|
||||
lazy_static = "0.2"
|
||||
libc = "0.2"
|
||||
log = "0.3"
|
||||
memchr = "1"
|
||||
memchr = "2"
|
||||
memmap = "0.5"
|
||||
num_cpus = "1"
|
||||
regex = "0.2.1"
|
||||
same-file = "0.1.1"
|
||||
termcolor = { version = "0.3.0", path = "termcolor" }
|
||||
same-file = "1"
|
||||
termcolor = { version = "0.3.3", path = "termcolor" }
|
||||
|
||||
[build-dependencies]
|
||||
clap = "2.24.1"
|
||||
clap = "2.26"
|
||||
lazy_static = "0.2"
|
||||
|
||||
[features]
|
||||
avx-accel = ["bytecount/avx-accel"]
|
||||
simd-accel = ["bytecount/simd-accel", "regex/simd-accel"]
|
||||
simd-accel = [
|
||||
"bytecount/simd-accel",
|
||||
"regex/simd-accel",
|
||||
"encoding_rs/simd-accel",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
|
75
README.md
75
README.md
@@ -1,10 +1,10 @@
|
||||
ripgrep (rg)
|
||||
------------
|
||||
`ripgrep` is a line oriented search tool that combines the usability of The
|
||||
Silver Searcher (similar to `ack`) with the raw speed of GNU grep. `ripgrep`
|
||||
works by recursively searching your current directory for a regex pattern.
|
||||
`ripgrep` has first class support on Windows, Mac and Linux, with binary
|
||||
downloads available for
|
||||
`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).
|
||||
|
||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
||||
@@ -71,9 +71,9 @@ increases the times to `3.081s` for ripgrep and `11.403s` for GNU grep.
|
||||
|
||||
### Why should I use `ripgrep`?
|
||||
|
||||
* It can replace both The Silver Searcher and GNU grep because it is 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.)
|
||||
* 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
|
||||
and won't search files ignored by your `.gitignore` files. It also ignores
|
||||
hidden and binary files by default. `ripgrep` also implements full support
|
||||
@@ -118,7 +118,7 @@ multiline search, then `ripgrep` may not quite meet your needs (yet).
|
||||
|
||||
### Is it really faster than everything else?
|
||||
|
||||
Yes. A large number of benchmarks with detailed analysis for each is
|
||||
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:
|
||||
@@ -146,15 +146,19 @@ Summarizing, `ripgrep` is fast because:
|
||||
|
||||
The binary name for `ripgrep` is `rg`.
|
||||
|
||||
[Binaries for `ripgrep` are available for Windows, Mac and
|
||||
Linux.](https://github.com/BurntSushi/ripgrep/releases) Linux binaries are
|
||||
static executables. Windows binaries are available either as built with MinGW
|
||||
(GNU) or with Microsoft Visual C++ (MSVC). When possible, prefer MSVC over GNU,
|
||||
but you'll need to have the
|
||||
[Microsoft VC++ 2015 redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=48145)
|
||||
**[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 and Ubuntu) are advised
|
||||
to download one of these archives.
|
||||
|
||||
Linux binaries are static executables. Windows binaries are available either as
|
||||
built with MinGW (GNU) or with Microsoft Visual C++ (MSVC). When possible,
|
||||
prefer MSVC over GNU, but you'll need to have the [Microsoft VC++ 2015
|
||||
redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=48145)
|
||||
installed.
|
||||
|
||||
If you're a **Mac OS X Homebrew** user, then you can install ripgrep either
|
||||
If you're a **macOS Homebrew** or a **Linuxbrew** user,
|
||||
then you can install ripgrep either
|
||||
from homebrew-core, (compiled with rust stable, no SIMD):
|
||||
|
||||
```
|
||||
@@ -209,8 +213,12 @@ $ nix-env --install ripgrep
|
||||
$ # (Or using the attribute name, which is also `ripgrep`.)
|
||||
```
|
||||
|
||||
If you're a **Rust programmer**, `ripgrep` can be installed with `cargo`. Note
|
||||
that this requires you to have **Rust 1.12 or newer** installed.
|
||||
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**,
|
||||
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
|
||||
the file size, run `strip` on the binary.
|
||||
|
||||
```
|
||||
$ cargo install ripgrep
|
||||
@@ -346,7 +354,7 @@ 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.
|
||||
`. /path/to/_rg.ps1` instead.
|
||||
|
||||
For **zsh**, move `complete/_rg` to one of your `$fpath` directories.
|
||||
|
||||
@@ -354,7 +362,7 @@ For **zsh**, move `complete/_rg` to one of your `$fpath` directories.
|
||||
|
||||
`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.12 (stable) or newer. Building is easy:
|
||||
`ripgrep` compiles with Rust 1.17 (stable) or newer. Building is easy:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/BurntSushi/ripgrep
|
||||
@@ -392,7 +400,7 @@ from the repository root.
|
||||
##### 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 run command `Get-Command $profile | Select-Object -ExpandProperty Definition`
|
||||
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.
|
||||
@@ -449,7 +457,7 @@ Example `$OutputEncoding` settings:
|
||||
`$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
|
||||
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.
|
||||
@@ -479,3 +487,26 @@ was later deprecated in
|
||||
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'`
|
||||
|
@@ -1082,7 +1082,7 @@ def download_subtitles_en(suite_dir):
|
||||
if not os.path.exists(en_path):
|
||||
if not os.path.exists(en_path_gz):
|
||||
run_cmd(['curl', '-LO', SUBTITLES_EN_URL], cwd=subtitle_dir)
|
||||
run_cmd(['gunzip', en_path_gz], cwd=subtitle_dir)
|
||||
run_cmd(['gunzip', en_path_gz])
|
||||
if not os.path.exists(en_path_sample):
|
||||
# Get a sample roughly the same size as the Russian corpus so that
|
||||
# benchmarks finish in a reasonable time.
|
||||
@@ -1109,7 +1109,7 @@ def download_subtitles_ru(suite_dir):
|
||||
if not os.path.exists(ru_path):
|
||||
if not os.path.exists(ru_path_gz):
|
||||
run_cmd(['curl', '-LO', SUBTITLES_RU_URL], cwd=subtitle_dir)
|
||||
run_cmd(['gunzip', ru_path_gz], cwd=subtitle_dir)
|
||||
run_cmd(['gunzip', ru_path_gz])
|
||||
|
||||
|
||||
def has_subtitles_ru(suite_dir):
|
||||
@@ -1184,6 +1184,7 @@ def collect_benchmarks(suite_dir, filter_pat=None,
|
||||
name,
|
||||
' '.join(['--download %s' % n for n in e.missing_names]),
|
||||
))
|
||||
continue
|
||||
except MissingCommands as e:
|
||||
fmt = 'missing commands: %s, skipping benchmark %s ' \
|
||||
'(run with --allow-missing to run incomplete benchmarks)'
|
||||
@@ -1239,7 +1240,7 @@ def main():
|
||||
benchmarks = collect_benchmarks(
|
||||
args.dir, filter_pat=args.bench,
|
||||
allow_missing_commands=args.allow_missing,
|
||||
disabled_cmds=args.disabled.split(','),
|
||||
disabled_cmds=(args.disabled or '').split(','),
|
||||
warmup_iter=args.warmup_iter, bench_iter=args.bench_iter)
|
||||
for b in benchmarks:
|
||||
print(b.name)
|
||||
@@ -1266,7 +1267,7 @@ def main():
|
||||
benchmarks = collect_benchmarks(
|
||||
args.dir, filter_pat=args.bench,
|
||||
allow_missing_commands=args.allow_missing,
|
||||
disabled_cmds=args.disabled.split(','),
|
||||
disabled_cmds=(args.disabled or '').split(','),
|
||||
warmup_iter=args.warmup_iter, bench_iter=args.bench_iter)
|
||||
for i, b in enumerate(benchmarks):
|
||||
result = b.run()
|
||||
|
@@ -18,9 +18,12 @@ mk_tarball() {
|
||||
mkdir "$td/$name"
|
||||
mkdir "$td/$name/complete"
|
||||
|
||||
cp target/$TARGET/release/rg "$td/$name/"
|
||||
cp target/$TARGET/release/rg "$td/$name/rg"
|
||||
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 \
|
||||
target/$TARGET/release/build/ripgrep-*/out/{rg.bash-completion,rg.fish,_rg.ps1} \
|
||||
"$td/$name/complete/"
|
||||
cp complete/_rg "$td/$name/complete/"
|
||||
|
||||
pushd $td
|
||||
|
@@ -1,83 +1,94 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
##
|
||||
# Compares options in `rg --help` output to options in zsh completion function
|
||||
|
||||
set -e
|
||||
emulate -R zsh
|
||||
setopt extended_glob
|
||||
setopt no_function_argzero
|
||||
setopt no_unset
|
||||
|
||||
get_comp_args() {
|
||||
setopt local_options unset
|
||||
|
||||
# Our completion function recognises a special variable which tells it to
|
||||
# dump the _arguments specs and then just return. But do this in a sub-shell
|
||||
# anyway to avoid any weirdness
|
||||
( _RG_COMPLETE_LIST_ARGS=1 source $1 )
|
||||
return $?
|
||||
}
|
||||
|
||||
main() {
|
||||
local rg="target/${TARGET}/release/rg"
|
||||
local _rg='complete/_rg'
|
||||
local ret='0'
|
||||
local helpTemp="$( mktemp )"
|
||||
local compTemp="$( mktemp )"
|
||||
local diff
|
||||
local rg="${${0:a}:h}/../target/${TARGET:-}/release/rg"
|
||||
local _rg="${${0:a}:h}/../complete/_rg"
|
||||
local -a help_args comp_args
|
||||
|
||||
[ -e "${rg}" ] || rg="target/${TARGET}/debug/rg"
|
||||
[[ -e $rg ]] || rg=${rg/%\/release\/rg/\/debug\/rg}
|
||||
|
||||
if [ ! -e "${rg}" ]; then
|
||||
printf 'File not found: %s\n' "${rg}" >&2
|
||||
ret='1'
|
||||
elif [ ! -e "${_rg}" ]; then
|
||||
printf 'File not found: %s\n' "${_rg}" >&2
|
||||
ret='1'
|
||||
else
|
||||
# 'Parse' options out of the `--help` output. To prevent false positives
|
||||
# we only look at lines where the first non-white-space character is `-`
|
||||
"${rg}" --help |
|
||||
"${rg}" -- '^\s*-' |
|
||||
"${rg}" -io -- '[\t ,](-[a-z0-9]|--[a-z0-9-]+)\b' |
|
||||
[[ -e $rg ]] || {
|
||||
printf >&2 'File not found: %s\n' $rg
|
||||
return 1
|
||||
}
|
||||
[[ -e $_rg ]] || {
|
||||
printf >&2 'File not found: %s\n' $_rg
|
||||
return 1
|
||||
}
|
||||
|
||||
printf 'Comparing options:\n-%s\n+%s\n' $rg $_rg
|
||||
|
||||
# 'Parse' options out of the `--help` output. To prevent false positives we
|
||||
# only look at lines where the first non-white-space character is `-`
|
||||
help_args=( ${(f)"$(
|
||||
$rg --help |
|
||||
$rg -- '^\s*-' |
|
||||
$rg -io -- '[\t ,](-[a-z0-9]|--[a-z0-9-]+)\b' |
|
||||
tr -d '\t ,' |
|
||||
sort -u > "${helpTemp}"
|
||||
sort -u
|
||||
)"} )
|
||||
|
||||
# 'Parse' options out of the completion-function file. To prevent false
|
||||
# negatives, we:
|
||||
#
|
||||
# * Exclude lines that look like comments
|
||||
# * Exclude lines that don't appear to have a bracketed description
|
||||
# suitable for `_arguments`
|
||||
# * Exclude those bracketed descriptions so we don't match options
|
||||
# which might be referenced in them
|
||||
# * Exclude parenthetical lists of exclusive options so we don't match
|
||||
# those
|
||||
#
|
||||
# This does of course make the following assumptions:
|
||||
#
|
||||
# * Each option definition is on its own (single) line
|
||||
# * Each option definition has a description
|
||||
# * Option names are static — i.e., they aren't constructed from
|
||||
# variables or command substitutions. Brace expansion is OK as long as
|
||||
# each component of the expression is a complete option flag — in
|
||||
# other words, `{--foo,--bar}` is valid, but `--{foo,bar}` is not
|
||||
"${rg}" -v -- '^\s*#' "${_rg}" |
|
||||
"${rg}" --replace '$1' -- '^.*?(?:\(.+?\).*?)?(-.+)\[.+\].*' |
|
||||
tr -d "\t (){}*=+:'\"" |
|
||||
tr ',' '\n' |
|
||||
sort -u > "${compTemp}"
|
||||
# 'Parse' options out of the completion function
|
||||
comp_args=( ${(f)"$( get_comp_args $_rg )"} )
|
||||
|
||||
diff="$(
|
||||
if diff --help 2>&1 | grep -qF -- '--label'; then
|
||||
diff -U2 \
|
||||
--label '`rg --help`' \
|
||||
--label "${_rg}" \
|
||||
"${helpTemp}" "${compTemp}" || true
|
||||
else
|
||||
diff -U2 \
|
||||
-L '`rg --help`' \
|
||||
-L "${_rg}" \
|
||||
"${helpTemp}" "${compTemp}" || true
|
||||
fi
|
||||
)"
|
||||
comp_args=( ${comp_args#\(*\)} ) # Strip excluded options
|
||||
comp_args=( ${comp_args#\*} ) # Strip repetition indicator
|
||||
comp_args=( ${comp_args%%-[:[]*} ) # Strip everything after -optname-
|
||||
comp_args=( ${comp_args%%[:+=[]*} ) # Strip everything after other optspecs
|
||||
comp_args=( ${comp_args##[^-]*} ) # Remove non-options
|
||||
|
||||
[ -n "${diff}" ] && {
|
||||
printf '%s\n' 'zsh completion options differ from `--help` options:' >&2
|
||||
printf '%s\n' "${diff}" >&2
|
||||
ret='1'
|
||||
}
|
||||
fi
|
||||
# This probably isn't necessary, but we should ensure the same order
|
||||
comp_args=( ${(f)"$( printf '%s\n' $comp_args | sort -u )"} )
|
||||
|
||||
rm -f "${helpTemp}" "${compTemp}"
|
||||
(( $#help_args )) || {
|
||||
printf >&2 'Failed to get help_args\n'
|
||||
return 1
|
||||
}
|
||||
(( $#comp_args )) || {
|
||||
printf >&2 'Failed to get comp_args\n'
|
||||
return 1
|
||||
}
|
||||
|
||||
return "${ret}"
|
||||
diff="$(
|
||||
if diff --help 2>&1 | grep -qF -- '--label'; then
|
||||
diff -U2 \
|
||||
--label '`rg --help`' \
|
||||
--label '`_rg`' \
|
||||
=( printf '%s\n' $help_args ) =( printf '%s\n' $comp_args )
|
||||
else
|
||||
diff -U2 \
|
||||
-L '`rg --help`' \
|
||||
-L '`_rg`' \
|
||||
=( printf '%s\n' $help_args ) =( printf '%s\n' $comp_args )
|
||||
fi
|
||||
)"
|
||||
|
||||
(( $#diff )) && {
|
||||
printf >&2 '%s\n' 'zsh completion options differ from `--help` options:'
|
||||
printf >&2 '%s\n' $diff
|
||||
return 1
|
||||
}
|
||||
printf 'OK\n'
|
||||
return 0
|
||||
}
|
||||
|
||||
main "${@}"
|
||||
|
366
complete/_rg
366
complete/_rg
@@ -1,4 +1,210 @@
|
||||
#compdef rg
|
||||
|
||||
##
|
||||
# zsh completion function for ripgrep
|
||||
#
|
||||
# Run ci/test_complete.sh after building to ensure that the options supported by
|
||||
# this function stay in synch with the `rg` binary.
|
||||
#
|
||||
# @see https://github.com/zsh-users/zsh/blob/master/Etc/completion-style-guide
|
||||
#
|
||||
# Based on code from the zsh-users project — see copyright notice below.
|
||||
|
||||
_rg() {
|
||||
local state_descr ret curcontext="${curcontext:-}"
|
||||
local -a context line state
|
||||
local -A opt_args val_args
|
||||
local -a rg_args
|
||||
|
||||
# Sort by long option name to match `rg --help`
|
||||
rg_args=(
|
||||
'(-A -C --after-context --context)'{-A+,--after-context=}'[specify lines to show after each match]:number of lines'
|
||||
'(-B -C --before-context --context)'{-B+,--before-context=}'[specify lines to show before each match]:number of lines'
|
||||
'(-i -s -S --ignore-case --case-sensitive --smart-case)'{-s,--case-sensitive}'[search case-sensitively]'
|
||||
'--color=[specify when to use colors in output]:when:( never auto always ansi )'
|
||||
'*--colors=[specify color settings and styles]: :->colorspec'
|
||||
'--column[show column numbers]'
|
||||
'(-A -B -C --after-context --before-context --context)'{-C+,--context=}'[specify lines to show before and after each match]:number of lines'
|
||||
'--context-separator=[specify string used to separate non-continuous context lines in output]:separator'
|
||||
'(-c --count)'{-c,--count}'[only show count of matches for each file]'
|
||||
'--debug[show debug messages]'
|
||||
'--dfa-size-limit=[specify upper size limit of generated DFA]:DFA size'
|
||||
'(-E --encoding)'{-E+,--encoding=}'[specify text encoding of files to search]: :_rg_encodings'
|
||||
'*'{-f+,--file=}'[specify file containing patterns to search for]:file:_files'
|
||||
"(1)--files[show each file that would be searched (but don't search)]"
|
||||
'(-l --files-with-matches --files-without-match)'{-l,--files-with-matches}'[only show names of files with matches]'
|
||||
'(-l --files-with-matches --files-without-match)--files-without-match[only show names of files without matches]'
|
||||
'(-F --fixed-strings)'{-F,--fixed-strings}'[treat pattern as literal string instead of regular expression]'
|
||||
'(-L --follow)'{-L,--follow}'[follow symlinks]'
|
||||
'*'{-g+,--glob=}'[include or exclude files for searching that match the specified glob]:glob'
|
||||
'(: -)'{-h,--help}'[display help information]'
|
||||
'(-p --no-heading --pretty --vimgrep)--heading[show matches grouped by file name]'
|
||||
'--hidden[search hidden files and directories]'
|
||||
'*--iglob=[include or exclude files for searching that match the specified case-insensitive glob]:glob'
|
||||
'(-i -s -S --case-sensitive --ignore-case --smart-case)'{-i,--ignore-case}'[search case-insensitively]'
|
||||
'--ignore-file=[specify additional ignore file]:file:_files'
|
||||
'(-v --invert-match)'{-v,--invert-match}'[invert matching]'
|
||||
'(-n -N --line-number --no-line-number)'{-n,--line-number}'[show line numbers]'
|
||||
'(-w -x --line-regexp --word-regexp)'{-x,--line-regexp}'[only show matches surrounded by line boundaries]'
|
||||
'(-M --max-columns)'{-M+,--max-columns=}'[specify max length of lines to print]:number of bytes'
|
||||
'(-m --max-count)'{-m+,--max-count=}'[specify max number of matches per file]:number of matches'
|
||||
'--max-filesize=[specify size above which files should be ignored]:file size'
|
||||
'--maxdepth=[specify max number of directories to descend]:number of directories'
|
||||
'(--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-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]"
|
||||
'(-n -N --line-number --no-line-number)'{-N,--no-line-number}'[suppress line numbers]'
|
||||
'--no-messages[suppress all error messages]'
|
||||
"(--mmap --no-mmap)--no-mmap[don't search using memory maps]"
|
||||
'(-0 --null)'{-0,--null}'[print NUL byte after file names]'
|
||||
'(-o --only-matching -r --replace)'{-o,--only-matching}'[show only matching part of each line]'
|
||||
'--path-separator=[specify path separator to use when printing file names]:separator'
|
||||
'(-p --heading --no-heading --pretty --vimgrep)'{-p,--pretty}'[alias for --color=always --heading -n]'
|
||||
'(-q --quiet)'{-q,--quiet}'[suppress normal output]'
|
||||
'--regex-size-limit=[specify upper size limit of compiled regex]:regex size'
|
||||
'(1 -f --file)*'{-e+,--regexp=}'[specify pattern]:pattern'
|
||||
'(-o --only-matching -r --replace)'{-r+,--replace=}'[specify string used to replace matches]:replace string'
|
||||
'(-i -s -S --ignore-case --case-sensitive --smart-case)'{-S,--smart-case}'[search case-insensitively if the pattern is all lowercase]'
|
||||
'(-j --threads)--sort-files[sort results by file path (disables parallelism)]'
|
||||
'(-a --text)'{-a,--text}'[search binary files as if they were text]'
|
||||
'(-j --sort-files --threads)'{-j+,--threads=}'[specify approximate number of threads to use]:number of threads'
|
||||
'*'{-t+,--type=}'[only search files matching specified type]: :_rg_types'
|
||||
'*--type-add=[add new glob for file type]: :->typespec'
|
||||
'*--type-clear=[clear globs previously defined for specified file type]: :_rg_types'
|
||||
# This should actually be exclusive with everything but other type options
|
||||
'(:)--type-list[show all supported file types and their associated globs]'
|
||||
'*'{-T+,--type-not=}"[don't search files matching specified type]: :_rg_types"
|
||||
'*'{-u,--unrestricted}'[reduce level of "smart" searching]'
|
||||
'(: -)'{-V,--version}'[display version information]'
|
||||
'(-p --heading --no-heading --pretty)--vimgrep[show results in vim-compatible format]'
|
||||
'(-H --no-filename --with-filename)'{-H,--with-filename}'[display the file name for matches]'
|
||||
'(-w -x --line-regexp --word-regexp)'{-w,--word-regexp}'[only show matches surrounded by word boundaries]'
|
||||
'(-e -f --file --files --regexp --type-list)1: :_rg_pattern'
|
||||
'(--type-list)*:file:_files'
|
||||
)
|
||||
|
||||
[[ ${_RG_COMPLETE_LIST_ARGS:-} == (1|t*|y*) ]] && {
|
||||
printf '%s\n' "${rg_args[@]}"
|
||||
return 0
|
||||
}
|
||||
|
||||
_arguments -s -S : "${rg_args[@]}" && return 0
|
||||
|
||||
while (( $#state )); do
|
||||
case "${state[1]}" in
|
||||
colorspec)
|
||||
# @todo I don't like this because it allows you to do weird things like
|
||||
# `line:line:bg:`. Also, i would like the `compadd -q` behaviour
|
||||
[[ -prefix *:none: ]] && return 1
|
||||
[[ -prefix *:*:*:* ]] && return 1
|
||||
|
||||
_values -S ':' 'color/style type' \
|
||||
'column[specify coloring for column numbers]: :->attribute' \
|
||||
'line[specify coloring for line numbers]: :->attribute' \
|
||||
'match[specify coloring for match text]: :->attribute' \
|
||||
'path[specify color for file names]: :->attribute' && return 0
|
||||
|
||||
[[ "${state}" == 'attribute' ]] &&
|
||||
_values -S ':' 'color/style attribute' \
|
||||
'none[clear color/style for type]' \
|
||||
'bg[specify background color]: :->color' \
|
||||
'fg[specify foreground color]: :->color' \
|
||||
'style[specify text style]: :->style' && return 0
|
||||
|
||||
[[ "${state}" == 'color' ]] &&
|
||||
_values -S ':' 'color value' \
|
||||
black blue green red cyan magenta yellow white && return 0
|
||||
|
||||
[[ "${state}" == 'style' ]] &&
|
||||
_values -S ':' 'style value' \
|
||||
bold nobold intense nointense && return 0
|
||||
;;
|
||||
|
||||
typespec)
|
||||
if compset -P '[^:]##:include:'; then
|
||||
_sequence -s ',' _rg_types && return 0
|
||||
# @todo This bit in particular could be better, but it's a little
|
||||
# complex, and attempting to solve it seems to run us up against a crash
|
||||
# bug — zsh # 40362
|
||||
elif compset -P '[^:]##:'; then
|
||||
_message 'glob or include directive' && return 1
|
||||
elif [[ ! -prefix *:* ]]; then
|
||||
_rg_types -qS ':' && return 0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
shift state
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# zsh 5.1 refuses to complete options if a 'match-less' operand like our pattern
|
||||
# could be 'completed' instead. We can use _guard() to avoid this problem, but
|
||||
# it introduces another one: zsh won't print the message if we try to complete
|
||||
# the pattern after having passed `--`. To work around *that* problem, we can
|
||||
# use this function to bypass the _guard() when `--` is on the command line.
|
||||
# This is inaccurate (it'd get confused by e.g. `rg -e --`), but zsh's handling
|
||||
# of `--` isn't accurate anyway
|
||||
_rg_pattern() {
|
||||
if (( ${words[(I)--]} )); then
|
||||
_message 'pattern'
|
||||
else
|
||||
_guard '^-*' 'pattern'
|
||||
fi
|
||||
}
|
||||
|
||||
# Complete encodings
|
||||
_rg_encodings() {
|
||||
local -a expl
|
||||
local -aU _encodings
|
||||
|
||||
# This is impossible to read, but these encodings rarely if ever change, so it
|
||||
# probably doesn't matter. They are derived from the list given here:
|
||||
# https://encoding.spec.whatwg.org/#concept-encoding-get
|
||||
_encodings=(
|
||||
{{,us-}ascii,arabic,chinese,cyrillic,greek{,8},hebrew,korean}
|
||||
logical visual mac {,cs}macintosh x-mac-{cyrillic,roman,ukrainian}
|
||||
866 ibm{819,866} csibm866
|
||||
big5{,-hkscs} {cn-,cs}big5 x-x-big5
|
||||
cp{819,866,125{0..8}} x-cp125{0..8}
|
||||
csiso2022{jp,kr} csiso8859{6,8}{e,i}
|
||||
csisolatin{{1..6},9} csisolatin{arabic,cyrillic,greek,hebrew}
|
||||
ecma-{114,118} asmo-708 elot_928 sun_eu_greek
|
||||
euc-{jp,kr} x-euc-jp cseuckr cseucpkdfmtjapanese
|
||||
{,x-}gbk csiso58gb231280 gb18030 {,cs}gb2312 gb_2312{,-80} hz-gb-2312
|
||||
iso-2022-{cn,cn-ext,jp,kr}
|
||||
iso8859{,-}{{1..11},13,14,15}
|
||||
iso-8859-{{1..11},{6,8}-{e,i},13,14,15,16} iso_8859-{{1..9},15}
|
||||
iso_8859-{1,2,6,7}:1987 iso_8859-{3,4,5,8}:1988 iso_8859-9:1989
|
||||
iso-ir-{58,100,101,109,110,126,127,138,144,148,149,157}
|
||||
koi{,8,8-r,8-ru,8-u,8_r} cskoi8r
|
||||
ks_c_5601-{1987,1989} ksc{,_}5691 csksc56011987
|
||||
latin{1..6} l{{1..6},9}
|
||||
shift{-,_}jis csshiftjis {,x-}sjis ms_kanji ms932
|
||||
utf{,-}8 utf-16{,be,le} unicode-1-1-utf-8
|
||||
windows-{31j,874,949,125{0..8}} dos-874 tis-620 ansi_x3.4-1968
|
||||
x-user-defined auto
|
||||
)
|
||||
|
||||
_wanted rg-encodings expl 'encoding' compadd -a "${@}" - _encodings
|
||||
}
|
||||
|
||||
# Complete file types
|
||||
_rg_types() {
|
||||
local -a expl
|
||||
local -aU _types
|
||||
|
||||
_types=( ${${(f)"$( _call_program rg-types rg --type-list )"}%%:*} )
|
||||
|
||||
_wanted rg-types expl 'file type' compadd -a "${@}" - _types
|
||||
}
|
||||
|
||||
_rg "${@}"
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright (c) 2011 Github zsh-users - http://github.com/zsh-users
|
||||
# All rights reserved.
|
||||
@@ -39,166 +245,6 @@
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
local context state state_descr line
|
||||
local -A opt_args
|
||||
local -i ret=1
|
||||
|
||||
local -a common_options
|
||||
common_options=(
|
||||
'(-a --text)'{-a,--text}'[search binary files as if they were text]'
|
||||
'(-c, --count)'{-c,--count}'[only show count of matches for each file]'
|
||||
'--color=[specify when to use colors in output]:when:( never auto always ansi )'
|
||||
'(1)*'{-e,--regexp=}'[specify pattern]:pattern'
|
||||
'(-E --encoding)'{-E,--encoding=}'[specify text encoding of files to search]: :->encoding'
|
||||
'(-F --fixed-strings)'{-F,--fixed-strings}'[treat pattern as literal string instead of regular expression]'
|
||||
'*'{-g,--glob=}'[include or exclude files for searching that match the specified glob]:glob'
|
||||
'(-h --help)'{-h,--help}'[display help information]'
|
||||
'(-i -s -S --ignore-case --case-sensitive --smart-case)'{-i,--ignore-case}'[search case-insensitively]'
|
||||
'(-n -N --line-number --no-line-number)'{-n,--line-number}'[show line numbers]'
|
||||
'(-n -N --line-number --no-line-number)'{-N,--no-line-number}'[suppress line numbers]'
|
||||
'(-o --only-matching)'{-o,--only-matching}'[show only matching part of each line]'
|
||||
'(-q --quiet)'{-q,--quiet}'[suppress normal output]'
|
||||
'(-T --type-not)*'{-t,--type=}'[only search files matching specified type]: :->type'
|
||||
'(-t --type)*'{-T,--type-not=}"[don't search files matching specified type]: :->type"
|
||||
'*'{-u,--unrestricted}'[reduce level of "smart" searching]'
|
||||
'(-v --invert-match)'{-v,--invert-match}'[invert matching]'
|
||||
'(-w --word-regexp)'{-w,--word-regexp}'[only show matches surrounded by word boundaries]'
|
||||
)
|
||||
|
||||
local -a less_common_options
|
||||
less_common_options=(
|
||||
'(-A -C --after-context --context)'{-A,--after-context=}'[specify lines to show after each match]:number of lines'
|
||||
'(-B -C --before-context --context)'{-B,--before-context=}'[specify lines to show before each match]:number of lines'
|
||||
'(-A -B -C --after-context --before-context --context)'{-C,--context=}'[specify lines to show before and after each match]:number of lines'
|
||||
'*--colors=[specify color settings and styles]: :->colorspec'
|
||||
'--column[show column numbers]'
|
||||
'--context-separator=[specify string used to separate non-continuous context lines in output]:separator string'
|
||||
'--debug[show debug messages]'
|
||||
'--dfa-size-limit=[specify upper size limit of generated DFA]:DFA size'
|
||||
'*'{-f,--file=}'[specify file containing patterns to search for]:file:_files'
|
||||
"--ignore-file=[specify additional ignore file]:file:_files"
|
||||
"--files[show each file that would be searched (but don't search)]"
|
||||
'(-l --files-with-matches --files-without-match)'{-l,--files-with-matches}'[only show names of files with matches]'
|
||||
'(-l --files-with-matches --files-without-match)--files-without-match[only show names of files without matches]'
|
||||
'(-H --with-filename --no-filename)'{-H,--with-filename}'[prefix each match with name of file that contains it]'
|
||||
'(-H --with-filename --no-filename)--no-filename[suppress all file names]'
|
||||
'(-p --no-heading --pretty --vimgrep)--heading[show matches grouped by file name]'
|
||||
"(-p --heading --pretty --vimgrep)--no-heading[don't group matches by file name]"
|
||||
'--hidden[search hidden files and directories]'
|
||||
'*--iglob=[include or exclude files for searching that match the specified case-insensitive glob]:glob'
|
||||
'(-L --follow)'{-L,--follow}'[follow symlinks]'
|
||||
'(-M --max-columns)'{-M,--max-columns=}'[specify max length of lines to print]:number of bytes'
|
||||
'(-m --max-count)'{-m,--max-count=}'[specify max number of matches per file]:number of matches'
|
||||
'--max-filesize=[specify size above which files should be ignored]:size'
|
||||
'--maxdepth[specify max number of directories to descend]:number of directories'
|
||||
'(--no-mmap)--mmap[search using memory maps when possible]'
|
||||
'--no-messages[suppress all error messages]'
|
||||
"(--mmap)--no-mmap[don't search using memory maps]"
|
||||
"(--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]"
|
||||
'(-0 --null)'{-0,--null}'[print NUL byte after file names]'
|
||||
'--path-separator=[specify path separator to use when printing file names]'
|
||||
'(-p --heading --no-heading --pretty --vimgrep)'{-p,--pretty}'[alias for --color=always --heading -n]'
|
||||
'--regex-size-limit=[specify upper size limit of compiled regex]:regex size'
|
||||
'(-r --replace)'{-r,--replace=}'[specify string used to replace matches]:replace string'
|
||||
'(-i -s -S --ignore-case --case-sensitive --smart-case)'{-s,--case-sensitive}'[search case-sensitively]'
|
||||
'(-i -s -S --ignore-case --case-sensitive --smart-case)'{-S,--smart-case}'[search case-insensitively if the pattern is all lowercase]'
|
||||
'--sort-files[sort results by file path (disables parallelism)]'
|
||||
'(-j --threads)'{-j,--threads=}'[specify approximate number of threads to use]:number of threads'
|
||||
'(-v --version)'{-V,--version}'[display version information]'
|
||||
'(-p --heading --no-heading --pretty)--vimgrep[show results in vim-compatible format]'
|
||||
)
|
||||
|
||||
local -a file_type_management_options
|
||||
file_type_management_options=(
|
||||
'--type-list[show all supported file types and their associated globs]'
|
||||
'*--type-add=[add new glob for file type]: :->typespec'
|
||||
'*--type-clear=[clear globs previously defined for specified file type]: :->type'
|
||||
)
|
||||
|
||||
_arguments -S -s : \
|
||||
$common_options \
|
||||
$less_common_options \
|
||||
$file_type_management_options \
|
||||
'(-e --regexp)1: :_guard "^--*" pattern' \
|
||||
'*:file:_files' \
|
||||
&& ret=0
|
||||
|
||||
case "$state" in
|
||||
colorspec)
|
||||
_values -S ':' 'color/style type' \
|
||||
'column[specify coloring for column numbers]: :->attribute' \
|
||||
'line[specify coloring for line numbers]: :->attribute' \
|
||||
'match[specify coloring for match text]: :->attribute' \
|
||||
'path[specify color for file names]: :->attribute' && ret=0
|
||||
|
||||
[[ "$state" == 'attribute' ]] &&
|
||||
_values -S ':' 'color/style attribute' \
|
||||
'none[clear color/style for type]' \
|
||||
'bg[specify background color]: :->color' \
|
||||
'fg[specify foreground color]: :->color' \
|
||||
'style[specify text style]: :->style' && ret=0
|
||||
|
||||
[[ "$state" == 'color' ]] &&
|
||||
_values -S ':' 'color value' \
|
||||
black blue green red cyan magenta yellow white && ret=0
|
||||
|
||||
[[ "$state" == 'style' ]] &&
|
||||
_values -S ':' 'style value' \
|
||||
bold nobold intense nointense && ret=0
|
||||
;;
|
||||
|
||||
encoding)
|
||||
# This is impossible to read, but these encodings rarely if ever change, so
|
||||
# it probably doesn't matter. They are derived from the list given here:
|
||||
# https://encoding.spec.whatwg.org/#concept-encoding-get
|
||||
local -U encodings
|
||||
encodings=(
|
||||
{{,us-}ascii,arabic,chinese,cyrillic,greek{,8},hebrew,korean}
|
||||
logical visual mac {,cs}macintosh x-mac-{cyrillic,roman,ukrainian}
|
||||
866 ibm{819,866} csibm866
|
||||
big5{,-hkscs} {cn-,cs}big5 x-x-big5
|
||||
cp{819,866,125{0..8}} x-cp125{0..8}
|
||||
csiso2022{jp,kr} csiso8859{6,8}{e,i}
|
||||
csisolatin{{1..6},9} csisolatin{arabic,cyrillic,greek,hebrew}
|
||||
ecma-{114,118} asmo-708 elot_928 sun_eu_greek
|
||||
euc-{jp,kr} x-euc-jp cseuckr cseucpkdfmtjapanese
|
||||
{,x-}gbk csiso58gb231280 gb18030 {,cs}gb2312 gb_2312{,-80} hz-gb-2312
|
||||
iso-2022-{cn,cn-ext,jp,kr}
|
||||
iso8859{,-}{{1..11},13,14,15}
|
||||
iso-8859-{{1..11},{6,8}-{e,i},13,14,15,16} iso_8859-{{1..9},15}
|
||||
iso_8859-{1,2,6,7}\\:1987 iso_8859-{3,4,5,8}\\:1988 iso_8859-9\\:1989
|
||||
iso-ir-{58,100,101,109,110,126,127,138,144,148,149,157}
|
||||
koi{,8,8-r,8-ru,8-u,8_r} cskoi8r
|
||||
ks_c_5601-{1987,1989} ksc{,_}5691 csksc56011987
|
||||
latin{1..6} l{{1..6},9}
|
||||
shift{-,_}jis csshiftjis {,x-}sjis ms_kanji ms932
|
||||
utf{,-}8 utf-16{,be,le} unicode-1-1-utf-8
|
||||
windows-{31j,874,949,125{0..8}} dos-874 tis-620 ansi_x3.4-1968
|
||||
x-user-defined auto
|
||||
)
|
||||
|
||||
_describe -t encodings 'encoding' encodings && ret=0
|
||||
;;
|
||||
|
||||
type|typespec)
|
||||
local -U types
|
||||
types=( ${${(f)"$(_call_program types rg --type-list)"}%%:*} )
|
||||
|
||||
if [[ "$case" == 'type' ]]; then
|
||||
_describe -t types "type" types && ret=0
|
||||
else
|
||||
# @todo: Would be nice to complete type names if an include: directive is
|
||||
# provided here
|
||||
_values -S ':' 'type spec' \
|
||||
${^types}':glob or include directive' && ret=0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
return ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# coding: utf-8-unix
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#!/bin/sh
|
||||
#!/bin/sh -e
|
||||
|
||||
pandoc -s -t man rg.1.md -o rg.1
|
||||
sed -i 's/\.TH.*/.TH "rg" "1"/g' 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
|
||||
|
35
doc/rg.1
35
doc/rg.1
@@ -29,6 +29,10 @@ 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 COMMON OPTIONS
|
||||
.TP
|
||||
@@ -45,7 +49,10 @@ Only show count of line matches for each file.
|
||||
.B \-\-color \f[I]WHEN\f[]
|
||||
Whether to use color in the output.
|
||||
Valid values are never, auto, always or ansi.
|
||||
[default: auto]
|
||||
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
|
||||
@@ -156,6 +163,12 @@ 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
|
||||
.SH LESS COMMON OPTIONS
|
||||
.TP
|
||||
.B \-A, \-\-after\-context \f[I]NUM\f[]
|
||||
@@ -261,8 +274,11 @@ Only show path of each file with no matches.
|
||||
.RE
|
||||
.TP
|
||||
.B \-H, \-\-with\-filename
|
||||
Prefix each match with the file name that contains it.
|
||||
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
|
||||
@@ -293,6 +309,17 @@ Search hidden directories and files.
|
||||
.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
|
||||
@@ -421,8 +448,8 @@ rg\ \[aq]^.*([0\-9]{3}\-[0\-9]{3}\-[0\-9]{4}).*$\[aq]\ \-\-replace\ \[aq]$1\[aq]
|
||||
.RE
|
||||
.TP
|
||||
.B \-s, \-\-case\-sensitive
|
||||
Search case sensitively.
|
||||
This overrides \-\-ignore\-case and \-\-smart\-case.
|
||||
Search case sensitively (default).
|
||||
Overrides \-\-ignore\-case and \-\-smart\-case.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
|
27
doc/rg.1.md
27
doc/rg.1.md
@@ -25,6 +25,10 @@ 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
|
||||
|
||||
# COMMON OPTIONS
|
||||
@@ -37,7 +41,9 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
||||
|
||||
--color *WHEN*
|
||||
: Whether to use color in the output. Valid values are never, auto, always or
|
||||
ansi. [default: auto]
|
||||
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
|
||||
@@ -105,6 +111,10 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
||||
: 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.
|
||||
|
||||
# LESS COMMON OPTIONS
|
||||
|
||||
-A, --after-context *NUM*
|
||||
@@ -172,8 +182,10 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
||||
: Only show path of each file with no matches.
|
||||
|
||||
-H, --with-filename
|
||||
: Prefix each match with the file name that contains it. This is the
|
||||
default when more than one file is searched.
|
||||
: 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
|
||||
@@ -192,6 +204,13 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
||||
: 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
|
||||
@@ -276,7 +295,7 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
||||
rg '^.*([0-9]{3}-[0-9]{3}-[0-9]{4}).*$' --replace '$1'
|
||||
|
||||
-s, --case-sensitive
|
||||
: Search case sensitively. This overrides --ignore-case and --smart-case.
|
||||
: Search case sensitively (default). Overrides --ignore-case and --smart-case.
|
||||
|
||||
-S, --smart-case
|
||||
: Search case insensitively if the pattern is all lowercase.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "globset"
|
||||
version = "0.2.0" #:version
|
||||
version = "0.2.1" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
Cross platform single glob and glob set matching. Glob set matching is the
|
||||
@@ -22,7 +22,7 @@ bench = false
|
||||
aho-corasick = "0.6.0"
|
||||
fnv = "1.0"
|
||||
log = "0.3"
|
||||
memchr = "1"
|
||||
memchr = "2"
|
||||
regex = "0.2.1"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@@ -20,7 +20,7 @@ Add this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
globset = "0.1"
|
||||
globset = "0.2"
|
||||
```
|
||||
|
||||
and this to your crate root:
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "grep"
|
||||
version = "0.1.6" #:version
|
||||
version = "0.1.7" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
Fast line oriented regex searching as a library.
|
||||
@@ -14,6 +14,6 @@ license = "Unlicense/MIT"
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
memchr = "1"
|
||||
memchr = "2"
|
||||
regex = "0.2.1"
|
||||
regex-syntax = "0.4.0"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ignore"
|
||||
version = "0.2.1" #:version
|
||||
version = "0.3.1" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
A fast library for efficiently matching ignore files such as `.gitignore`
|
||||
@@ -19,13 +19,14 @@ bench = false
|
||||
|
||||
[dependencies]
|
||||
crossbeam = "0.2"
|
||||
globset = { version = "0.2.0", path = "../globset" }
|
||||
globset = { version = "0.2.1", path = "../globset" }
|
||||
lazy_static = "0.2"
|
||||
log = "0.3"
|
||||
memchr = "1"
|
||||
memchr = "2"
|
||||
regex = "0.2.1"
|
||||
same-file = "1"
|
||||
thread_local = "0.3.2"
|
||||
walkdir = "1.0.7"
|
||||
walkdir = "2"
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3.5"
|
||||
|
@@ -127,7 +127,6 @@ struct IgnoreInner {
|
||||
|
||||
impl Ignore {
|
||||
/// Return the directory path of this matcher.
|
||||
#[allow(dead_code)]
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.0.dir
|
||||
}
|
||||
|
@@ -220,15 +220,17 @@ impl Gitignore {
|
||||
!path.has_root(),
|
||||
"path is expect to be under the root"
|
||||
);
|
||||
loop {
|
||||
match self.matched_stripped(path, is_dir) {
|
||||
Match::None => match path.parent() {
|
||||
Some(parent) => path = parent,
|
||||
None => return Match::None,
|
||||
},
|
||||
match self.matched_stripped(path, is_dir) {
|
||||
Match::None => (), // walk up
|
||||
a_match => return a_match,
|
||||
}
|
||||
while let Some(parent) = path.parent() {
|
||||
match self.matched_stripped(parent, /* is_dir */ true) {
|
||||
Match::None => path = parent, // walk up
|
||||
a_match => return a_match,
|
||||
}
|
||||
}
|
||||
Match::None
|
||||
}
|
||||
|
||||
/// Like matched, but takes a path that has already been stripped.
|
||||
|
@@ -54,6 +54,7 @@ extern crate lazy_static;
|
||||
extern crate log;
|
||||
extern crate memchr;
|
||||
extern crate regex;
|
||||
extern crate same_file;
|
||||
#[cfg(test)]
|
||||
extern crate tempdir;
|
||||
extern crate thread_local;
|
||||
@@ -198,6 +199,29 @@ impl Error {
|
||||
}
|
||||
errline.with_path(path)
|
||||
}
|
||||
|
||||
/// Build an error from a walkdir error.
|
||||
fn from_walkdir(err: walkdir::Error) -> Error {
|
||||
let depth = err.depth();
|
||||
if let (Some(anc), Some(child)) = (err.loop_ancestor(), err.path()) {
|
||||
return Error::WithDepth {
|
||||
depth: depth,
|
||||
err: Box::new(Error::Loop {
|
||||
ancestor: anc.to_path_buf(),
|
||||
child: child.to_path_buf(),
|
||||
}),
|
||||
};
|
||||
}
|
||||
let path = err.path().map(|p| p.to_path_buf());
|
||||
let mut ig_err = Error::Io(io::Error::from(err));
|
||||
if let Some(path) = path {
|
||||
ig_err = Error::WithPath {
|
||||
path: path,
|
||||
err: Box::new(ig_err),
|
||||
};
|
||||
}
|
||||
ig_err
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
@@ -258,30 +282,6 @@ impl From<io::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<walkdir::Error> for Error {
|
||||
fn from(err: walkdir::Error) -> Error {
|
||||
let depth = err.depth();
|
||||
if let (Some(anc), Some(child)) = (err.loop_ancestor(), err.path()) {
|
||||
return Error::WithDepth {
|
||||
depth: depth,
|
||||
err: Box::new(Error::Loop {
|
||||
ancestor: anc.to_path_buf(),
|
||||
child: child.to_path_buf(),
|
||||
}),
|
||||
};
|
||||
}
|
||||
let path = err.path().map(|p| p.to_path_buf());
|
||||
let mut ig_err = Error::Io(io::Error::from(err));
|
||||
if let Some(path) = path {
|
||||
ig_err = Error::WithPath {
|
||||
path: path,
|
||||
err: Box::new(ig_err),
|
||||
};
|
||||
}
|
||||
ig_err
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct PartialErrorBuilder(Vec<Error>);
|
||||
|
||||
|
@@ -101,6 +101,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("asciidoc", &["*.adoc", "*.asc", "*.asciidoc"]),
|
||||
("asm", &["*.asm", "*.s", "*.S"]),
|
||||
("awk", &["*.awk"]),
|
||||
("bitbake", &["*.bb", "*.bbappend", "*.bbclass", "*.conf", "*.inc"]),
|
||||
("c", &["*.c", "*.h", "*.H"]),
|
||||
("cabal", &["*.cabal"]),
|
||||
("cbor", &["*.cbor"]),
|
||||
@@ -109,7 +110,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("cmake", &["*.cmake", "CMakeLists.txt"]),
|
||||
("coffeescript", &["*.coffee"]),
|
||||
("creole", &["*.creole"]),
|
||||
("config", &["*.config"]),
|
||||
("config", &["*.cfg", "*.conf", "*.config", "*.ini"]),
|
||||
("cpp", &[
|
||||
"*.C", "*.cc", "*.cpp", "*.cxx",
|
||||
"*.h", "*.H", "*.hh", "*.hpp", "*.inl",
|
||||
@@ -122,8 +123,10 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("cython", &["*.pyx"]),
|
||||
("dart", &["*.dart"]),
|
||||
("d", &["*.d"]),
|
||||
("docker", &["*Dockerfile*"]),
|
||||
("elisp", &["*.el"]),
|
||||
("elixir", &["*.ex", "*.eex", "*.exs"]),
|
||||
("elm", &["*.elm"]),
|
||||
("erlang", &["*.erl", "*.hrl"]),
|
||||
("fish", &["*.fish"]),
|
||||
("fortran", &[
|
||||
@@ -138,26 +141,60 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("haskell", &["*.hs", "*.lhs"]),
|
||||
("html", &["*.htm", "*.html", "*.ejs"]),
|
||||
("java", &["*.java"]),
|
||||
("jinja", &["*.jinja", "*.jinja2"]),
|
||||
("jinja", &["*.j2", "*.jinja", "*.jinja2"]),
|
||||
("js", &[
|
||||
"*.js", "*.jsx", "*.vue",
|
||||
]),
|
||||
("json", &["*.json"]),
|
||||
("json", &["*.json", "composer.lock"]),
|
||||
("jsonl", &["*.jsonl"]),
|
||||
("julia", &["*.jl"]),
|
||||
("jl", &["*.jl"]),
|
||||
("kotlin", &["*.kt", "*.kts"]),
|
||||
("less", &["*.less"]),
|
||||
("license", &[
|
||||
// General
|
||||
"COPYING", "COPYING[.-]*",
|
||||
"COPYRIGHT", "COPYRIGHT[.-]*",
|
||||
"EULA", "EULA[.-]*",
|
||||
"licen[cs]e", "licen[cs]e.*",
|
||||
"LICEN[CS]E", "LICEN[CS]E[.-]*", "*[.-]LICEN[CS]E*",
|
||||
"NOTICE", "NOTICE[.-]*",
|
||||
"PATENTS", "PATENTS[.-]*",
|
||||
"UNLICEN[CS]E", "UNLICEN[CS]E[.-]*",
|
||||
// GPL (gpl.txt, etc.)
|
||||
"agpl[.-]*",
|
||||
"gpl[.-]*",
|
||||
"lgpl[.-]*",
|
||||
// Other license-specific (APACHE-2.0.txt, etc.)
|
||||
"AGPL-*[0-9]*",
|
||||
"APACHE-*[0-9]*",
|
||||
"BSD-*[0-9]*",
|
||||
"CC-BY-*",
|
||||
"GFDL-*[0-9]*",
|
||||
"GNU-*[0-9]*",
|
||||
"GPL-*[0-9]*",
|
||||
"LGPL-*[0-9]*",
|
||||
"MIT-*[0-9]*",
|
||||
"MPL-*[0-9]*",
|
||||
"OFL-*[0-9]*",
|
||||
]),
|
||||
("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]),
|
||||
("log", &["*.log"]),
|
||||
("lua", &["*.lua"]),
|
||||
("m4", &["*.ac", "*.m4"]),
|
||||
("make", &["gnumakefile", "Gnumakefile", "makefile", "Makefile", "*.mk", "*.mak"]),
|
||||
("make", &[
|
||||
"gnumakefile", "Gnumakefile", "GNUmakefile",
|
||||
"makefile", "Makefile",
|
||||
"*.mk", "*.mak"
|
||||
]),
|
||||
("markdown", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
|
||||
("md", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
|
||||
("matlab", &["*.m"]),
|
||||
("mk", &["mkfile"]),
|
||||
("ml", &["*.ml"]),
|
||||
("msbuild", &["*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets"]),
|
||||
("msbuild", &[
|
||||
"*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets"
|
||||
]),
|
||||
("nim", &["*.nim"]),
|
||||
("nix", &["*.nix"]),
|
||||
("objc", &["*.h", "*.m"]),
|
||||
@@ -169,8 +206,9 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("php", &["*.php", "*.php3", "*.php4", "*.php5", "*.phtml"]),
|
||||
("pod", &["*.pod"]),
|
||||
("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]),
|
||||
("purs", &["*.purs"]),
|
||||
("py", &["*.py"]),
|
||||
("qmake", &["*.pro", "*.pri"]),
|
||||
("qmake", &["*.pro", "*.pri", "*.prf"]),
|
||||
("readme", &["README*", "*README"]),
|
||||
("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
|
||||
("rdoc", &["*.rdoc"]),
|
||||
@@ -179,18 +217,47 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("rust", &["*.rs"]),
|
||||
("sass", &["*.sass", "*.scss"]),
|
||||
("scala", &["*.scala"]),
|
||||
("sh", &["*.bash", "*.csh", "*.ksh", "*.sh", "*.tcsh"]),
|
||||
("sh", &[
|
||||
// Portable/misc. init files
|
||||
".login", ".logout", ".profile", "profile",
|
||||
// bash-specific init files
|
||||
".bash_login", "bash_login",
|
||||
".bash_logout", "bash_logout",
|
||||
".bash_profile", "bash_profile",
|
||||
".bashrc", "bashrc", "*.bashrc",
|
||||
// csh-specific init files
|
||||
".cshrc", "*.cshrc",
|
||||
// ksh-specific init files
|
||||
".kshrc", "*.kshrc",
|
||||
// tcsh-specific init files
|
||||
".tcshrc",
|
||||
// zsh-specific init files
|
||||
".zshenv", "zshenv",
|
||||
".zlogin", "zlogin",
|
||||
".zlogout", "zlogout",
|
||||
".zprofile", "zprofile",
|
||||
".zshrc", "zshrc",
|
||||
// Extensions
|
||||
"*.bash", "*.csh", "*.ksh", "*.sh", "*.tcsh", "*.zsh",
|
||||
]),
|
||||
("sml", &["*.sml", "*.sig"]),
|
||||
("spark", &["*.spark"]),
|
||||
("sql", &["*.sql", "*.psql"]),
|
||||
("stylus", &["*.styl"]),
|
||||
("sql", &["*.sql"]),
|
||||
("sv", &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]),
|
||||
("svg", &["*.svg"]),
|
||||
("swift", &["*.swift"]),
|
||||
("swig", &["*.def", "*.i"]),
|
||||
("systemd", &[
|
||||
"*.automount", "*.conf", "*.device", "*.link", "*.mount", "*.path",
|
||||
"*.scope", "*.service", "*.slice", "*.socket", "*.swap", "*.target",
|
||||
"*.timer",
|
||||
]),
|
||||
("taskpaper", &["*.taskpaper"]),
|
||||
("tcl", &["*.tcl"]),
|
||||
("tex", &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib"]),
|
||||
("textile", &["*.textile"]),
|
||||
("tf", &["*.tf"]),
|
||||
("ts", &["*.ts", "*.tsx"]),
|
||||
("txt", &["*.txt"]),
|
||||
("toml", &["*.toml", "Cargo.lock"]),
|
||||
@@ -200,11 +267,17 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("vim", &["*.vim"]),
|
||||
("vimscript", &["*.vim"]),
|
||||
("wiki", &["*.mediawiki", "*.wiki"]),
|
||||
("xml", &["*.xml"]),
|
||||
("xml", &["*.xml", "*.xml.dist"]),
|
||||
("yacc", &["*.y"]),
|
||||
("yaml", &["*.yaml", "*.yml"]),
|
||||
("yocto", &["*.bb", "*.bbappend", "*.bbclass"]),
|
||||
("zsh", &["zshenv", ".zshenv", "zprofile", ".zprofile", "zshrc", ".zshrc", "zlogin", ".zlogin", "zlogout", ".zlogout", "*.zsh"]),
|
||||
("yaml", &["*.yaml", "*.yml", "yarn.lock"]),
|
||||
("zsh", &[
|
||||
".zshenv", "zshenv",
|
||||
".zlogin", "zlogin",
|
||||
".zlogout", "zlogout",
|
||||
".zprofile", "zprofile",
|
||||
".zshrc", "zshrc",
|
||||
"*.zsh",
|
||||
]),
|
||||
];
|
||||
|
||||
/// Glob represents a single glob in a set of file type definitions.
|
||||
|
@@ -1,5 +1,5 @@
|
||||
use std::cmp;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::ffi::OsStr;
|
||||
use std::fmt;
|
||||
use std::fs::{self, FileType, Metadata};
|
||||
use std::io;
|
||||
@@ -11,7 +11,8 @@ use std::time::Duration;
|
||||
use std::vec;
|
||||
|
||||
use crossbeam::sync::MsQueue;
|
||||
use walkdir::{self, WalkDir, WalkDirIterator, is_same_file};
|
||||
use same_file::Handle;
|
||||
use walkdir::{self, WalkDir};
|
||||
|
||||
use dir::{Ignore, IgnoreBuilder};
|
||||
use gitignore::GitignoreBuilder;
|
||||
@@ -36,8 +37,8 @@ impl DirEntry {
|
||||
}
|
||||
|
||||
/// Whether this entry corresponds to a symbolic link or not.
|
||||
pub fn path_is_symbolic_link(&self) -> bool {
|
||||
self.dent.path_is_symbolic_link()
|
||||
pub fn path_is_symlink(&self) -> bool {
|
||||
self.dent.path_is_symlink()
|
||||
}
|
||||
|
||||
/// Returns true if and only if this entry corresponds to stdin.
|
||||
@@ -137,12 +138,12 @@ impl DirEntryInner {
|
||||
}
|
||||
}
|
||||
|
||||
fn path_is_symbolic_link(&self) -> bool {
|
||||
fn path_is_symlink(&self) -> bool {
|
||||
use self::DirEntryInner::*;
|
||||
match *self {
|
||||
Stdin => false,
|
||||
Walkdir(ref x) => x.path_is_symbolic_link(),
|
||||
Raw(ref x) => x.path_is_symbolic_link(),
|
||||
Walkdir(ref x) => x.path_is_symlink(),
|
||||
Raw(ref x) => x.path_is_symlink(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +200,7 @@ impl DirEntryInner {
|
||||
|
||||
#[cfg(unix)]
|
||||
fn ino(&self) -> Option<u64> {
|
||||
use walkdir::DirEntryExt;
|
||||
use self::DirEntryInner::*;
|
||||
match *self {
|
||||
Stdin => None,
|
||||
@@ -244,7 +246,7 @@ impl DirEntryRaw {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn path_is_symbolic_link(&self) -> bool {
|
||||
fn path_is_symlink(&self) -> bool {
|
||||
self.ty.is_symlink() || self.follow_link
|
||||
}
|
||||
|
||||
@@ -404,7 +406,9 @@ pub struct WalkBuilder {
|
||||
max_depth: Option<usize>,
|
||||
max_filesize: Option<u64>,
|
||||
follow_links: bool,
|
||||
sorter: Option<Arc<Fn(&OsString, &OsString) -> cmp::Ordering + 'static>>,
|
||||
sorter: Option<Arc<
|
||||
Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static
|
||||
>>,
|
||||
threads: usize,
|
||||
}
|
||||
|
||||
@@ -458,7 +462,9 @@ impl WalkBuilder {
|
||||
}
|
||||
if let Some(ref cmp) = cmp {
|
||||
let cmp = cmp.clone();
|
||||
wd = wd.sort_by(move |a, b| cmp(a, b));
|
||||
wd = wd.sort_by(move |a, b| {
|
||||
cmp(a.file_name(), b.file_name())
|
||||
});
|
||||
}
|
||||
(p.to_path_buf(), Some(WalkEventIter::from(wd)))
|
||||
}
|
||||
@@ -571,6 +577,29 @@ impl WalkBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Enables all the standard ignore filters.
|
||||
///
|
||||
/// This toggles, as a group, all the filters that are enabled by default:
|
||||
///
|
||||
/// - [hidden()](#method.hidden)
|
||||
/// - [parents()](#method.parents)
|
||||
/// - [ignore()](#method.ignore)
|
||||
/// - [git_ignore()](#method.git_ignore)
|
||||
/// - [git_global()](#method.git_global)
|
||||
/// - [git_exclude()](#method.git_exclude)
|
||||
///
|
||||
/// They may still be toggled individually after calling this function.
|
||||
///
|
||||
/// This is (by definition) enabled by default.
|
||||
pub fn standard_filters(&mut self, yes: bool) -> &mut WalkBuilder {
|
||||
self.hidden(yes)
|
||||
.parents(yes)
|
||||
.ignore(yes)
|
||||
.git_ignore(yes)
|
||||
.git_global(yes)
|
||||
.git_exclude(yes)
|
||||
}
|
||||
|
||||
/// Enables ignoring hidden files.
|
||||
///
|
||||
/// This is enabled by default.
|
||||
@@ -610,6 +639,8 @@ impl WalkBuilder {
|
||||
/// does not exist or does not specify `core.excludesFile`, then
|
||||
/// `$XDG_CONFIG_HOME/git/ignore` is read. If `$XDG_CONFIG_HOME` is not
|
||||
/// set or is empty, then `$HOME/.config/git/ignore` is used instead.
|
||||
///
|
||||
/// This is enabled by default.
|
||||
pub fn git_global(&mut self, yes: bool) -> &mut WalkBuilder {
|
||||
self.ig_builder.git_global(yes);
|
||||
self
|
||||
@@ -637,7 +668,7 @@ impl WalkBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a function for sorting directory entries.
|
||||
/// Set a function for sorting directory entries by file name.
|
||||
///
|
||||
/// If a compare function is set, the resulting iterator will return all
|
||||
/// paths in sorted order. The compare function will be called to compare
|
||||
@@ -645,8 +676,9 @@ impl WalkBuilder {
|
||||
/// entry.
|
||||
///
|
||||
/// Note that this is not used in the parallel iterator.
|
||||
pub fn sort_by<F>(&mut self, cmp: F) -> &mut WalkBuilder
|
||||
where F: Fn(&OsString, &OsString) -> cmp::Ordering + 'static {
|
||||
pub fn sort_by_file_name<F>(&mut self, cmp: F) -> &mut WalkBuilder
|
||||
where F: Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static
|
||||
{
|
||||
self.sorter = Some(Arc::new(cmp));
|
||||
self
|
||||
}
|
||||
@@ -727,7 +759,7 @@ impl Iterator for Walk {
|
||||
};
|
||||
match ev {
|
||||
Err(err) => {
|
||||
return Some(Err(Error::from(err)));
|
||||
return Some(Err(Error::from_walkdir(err)));
|
||||
}
|
||||
Ok(WalkEvent::Exit) => {
|
||||
self.ig = self.ig.parent().unwrap();
|
||||
@@ -763,7 +795,7 @@ impl Iterator for Walk {
|
||||
/// the entire contents of a directory have been enumerated.
|
||||
struct WalkEventIter {
|
||||
depth: usize,
|
||||
it: walkdir::Iter,
|
||||
it: walkdir::IntoIter,
|
||||
next: Option<Result<walkdir::DirEntry, walkdir::Error>>,
|
||||
}
|
||||
|
||||
@@ -1276,11 +1308,14 @@ fn check_symlink_loop(
|
||||
child_path: &Path,
|
||||
child_depth: usize,
|
||||
) -> Result<(), Error> {
|
||||
let hchild = Handle::from_path(child_path).map_err(|err| {
|
||||
Error::from(err).with_path(child_path).with_depth(child_depth)
|
||||
})?;
|
||||
for ig in ig_parent.parents().take_while(|ig| !ig.is_absolute_parent()) {
|
||||
let same = try!(is_same_file(ig.path(), child_path).map_err(|err| {
|
||||
let h = Handle::from_path(ig.path()).map_err(|err| {
|
||||
Error::from(err).with_path(child_path).with_depth(child_depth)
|
||||
}));
|
||||
if same {
|
||||
})?;
|
||||
if hchild == h {
|
||||
return Err(Error::Loop {
|
||||
ancestor: ig.path().to_path_buf(),
|
||||
child: child_path.to_path_buf(),
|
||||
|
@@ -92,172 +92,206 @@ fn test_files_in_deep() {
|
||||
#[test]
|
||||
fn test_dirs_in_root() {
|
||||
let gitignore = get_gitignore();
|
||||
let m = |path: &str| gitignore.matched_path_or_any_parents(Path::new(path), true);
|
||||
let m =
|
||||
|path: &str, is_dir: bool| gitignore.matched_path_or_any_parents(Path::new(path), is_dir);
|
||||
|
||||
// 00
|
||||
assert!(m("ROOT/dir_root_00").is_ignore());
|
||||
assert!(m("ROOT/dir_root_00/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_00/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_00", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_00/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_00/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_00/child_dir/file", false).is_ignore());
|
||||
|
||||
// 01
|
||||
assert!(m("ROOT/dir_root_01").is_ignore());
|
||||
assert!(m("ROOT/dir_root_01/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_01/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_01", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_01/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_01/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_01/child_dir/file", false).is_ignore());
|
||||
|
||||
// 02
|
||||
assert!(m("ROOT/dir_root_02").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/dir_root_02/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_02/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_02", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/dir_root_02/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_02/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_02/child_dir/file", false).is_ignore());
|
||||
|
||||
// 03
|
||||
assert!(m("ROOT/dir_root_03").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/dir_root_03/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_03/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_03", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/dir_root_03/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_03/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_03/child_dir/file", false).is_ignore());
|
||||
|
||||
// 10
|
||||
assert!(m("ROOT/dir_root_10").is_ignore());
|
||||
assert!(m("ROOT/dir_root_10/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_10/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_10", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_10/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_10/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_10/child_dir/file", false).is_ignore());
|
||||
|
||||
// 11
|
||||
assert!(m("ROOT/dir_root_11").is_ignore());
|
||||
assert!(m("ROOT/dir_root_11/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_11/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_11", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_11/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_11/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_11/child_dir/file", false).is_ignore());
|
||||
|
||||
// 12
|
||||
assert!(m("ROOT/dir_root_12").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/dir_root_12/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_12/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_12", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/dir_root_12/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_12/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_12/child_dir/file", false).is_ignore());
|
||||
|
||||
// 13
|
||||
assert!(m("ROOT/dir_root_13").is_none());
|
||||
assert!(m("ROOT/dir_root_13/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_13/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_13", true).is_none());
|
||||
assert!(m("ROOT/dir_root_13/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_13/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_13/child_dir/file", false).is_ignore());
|
||||
|
||||
// 20
|
||||
assert!(m("ROOT/dir_root_20").is_none());
|
||||
assert!(m("ROOT/dir_root_20/file").is_none());
|
||||
assert!(m("ROOT/dir_root_20/child_dir/file").is_none());
|
||||
assert!(m("ROOT/dir_root_20", true).is_none());
|
||||
assert!(m("ROOT/dir_root_20/file", false).is_none());
|
||||
assert!(m("ROOT/dir_root_20/child_dir", true).is_none());
|
||||
assert!(m("ROOT/dir_root_20/child_dir/file", false).is_none());
|
||||
|
||||
// 21
|
||||
assert!(m("ROOT/dir_root_21").is_none());
|
||||
assert!(m("ROOT/dir_root_21/file").is_none());
|
||||
assert!(m("ROOT/dir_root_21/child_dir/file").is_none());
|
||||
assert!(m("ROOT/dir_root_21", true).is_none());
|
||||
assert!(m("ROOT/dir_root_21/file", false).is_none());
|
||||
assert!(m("ROOT/dir_root_21/child_dir", true).is_none());
|
||||
assert!(m("ROOT/dir_root_21/child_dir/file", false).is_none());
|
||||
|
||||
// 22
|
||||
assert!(m("ROOT/dir_root_22").is_none());
|
||||
assert!(m("ROOT/dir_root_22/file").is_none());
|
||||
assert!(m("ROOT/dir_root_22/child_dir/file").is_none());
|
||||
assert!(m("ROOT/dir_root_22", true).is_none());
|
||||
assert!(m("ROOT/dir_root_22/file", false).is_none());
|
||||
assert!(m("ROOT/dir_root_22/child_dir", true).is_none());
|
||||
assert!(m("ROOT/dir_root_22/child_dir/file", false).is_none());
|
||||
|
||||
// 23
|
||||
assert!(m("ROOT/dir_root_23").is_none());
|
||||
assert!(m("ROOT/dir_root_23/file").is_none());
|
||||
assert!(m("ROOT/dir_root_23/child_dir/file").is_none());
|
||||
assert!(m("ROOT/dir_root_23", true).is_none());
|
||||
assert!(m("ROOT/dir_root_23/file", false).is_none());
|
||||
assert!(m("ROOT/dir_root_23/child_dir", true).is_none());
|
||||
assert!(m("ROOT/dir_root_23/child_dir/file", false).is_none());
|
||||
|
||||
// 30
|
||||
assert!(m("ROOT/dir_root_30").is_ignore());
|
||||
assert!(m("ROOT/dir_root_30/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_30/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_30", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_30/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_30/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_30/child_dir/file", false).is_ignore());
|
||||
|
||||
// 31
|
||||
assert!(m("ROOT/dir_root_31").is_ignore());
|
||||
assert!(m("ROOT/dir_root_31/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_31/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_31", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_31/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_31/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_31/child_dir/file", false).is_ignore());
|
||||
|
||||
// 32
|
||||
assert!(m("ROOT/dir_root_32").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/dir_root_32/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_32/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_32", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/dir_root_32/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_32/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_32/child_dir/file", false).is_ignore());
|
||||
|
||||
// 33
|
||||
assert!(m("ROOT/dir_root_33").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/dir_root_33/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_33/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/dir_root_33", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/dir_root_33/file", false).is_ignore());
|
||||
assert!(m("ROOT/dir_root_33/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/dir_root_33/child_dir/file", false).is_ignore());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_dirs_in_deep() {
|
||||
let gitignore = get_gitignore();
|
||||
let m = |path: &str| gitignore.matched_path_or_any_parents(Path::new(path), true);
|
||||
let m =
|
||||
|path: &str, is_dir: bool| gitignore.matched_path_or_any_parents(Path::new(path), is_dir);
|
||||
|
||||
// 00
|
||||
assert!(m("ROOT/parent_dir/dir_deep_00").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_00/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_00/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_00", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_00/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_00/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_00/child_dir/file", false).is_ignore());
|
||||
|
||||
// 01
|
||||
assert!(m("ROOT/parent_dir/dir_deep_01").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_01/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_01/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_01", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_01/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_01/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_01/child_dir/file", false).is_ignore());
|
||||
|
||||
// 02
|
||||
assert!(m("ROOT/parent_dir/dir_deep_02").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_02/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_02/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_02", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_02/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_02/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_02/child_dir/file", false).is_ignore());
|
||||
|
||||
// 03
|
||||
assert!(m("ROOT/parent_dir/dir_deep_03").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_03/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_03/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_03", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_03/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_03/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_03/child_dir/file", false).is_ignore());
|
||||
|
||||
// 10
|
||||
assert!(m("ROOT/parent_dir/dir_deep_10").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_10/file").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_10/child_dir/file").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_10", true).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_10/file", false).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_10/child_dir", true).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_10/child_dir/file", false).is_none());
|
||||
|
||||
// 11
|
||||
assert!(m("ROOT/parent_dir/dir_deep_11").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_11/file").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_11/child_dir/file").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_11", true).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_11/file", false).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_11/child_dir", true).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_11/child_dir/file", false).is_none());
|
||||
|
||||
// 12
|
||||
assert!(m("ROOT/parent_dir/dir_deep_12").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_12/file").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_12/child_dir/file").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_12", true).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_12/file", false).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_12/child_dir", true).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_12/child_dir/file", false).is_none());
|
||||
|
||||
// 13
|
||||
assert!(m("ROOT/parent_dir/dir_deep_13").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_13/file").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_13/child_dir/file").is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_13", true).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_13/file", false).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_13/child_dir", true).is_none());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_13/child_dir/file", false).is_none());
|
||||
|
||||
// 20
|
||||
assert!(m("ROOT/parent_dir/dir_deep_20").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_20/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_20/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_20", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_20/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_20/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_20/child_dir/file", false).is_ignore());
|
||||
|
||||
// 21
|
||||
assert!(m("ROOT/parent_dir/dir_deep_21").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_21/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_21/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_21", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_21/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_21/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_21/child_dir/file", false).is_ignore());
|
||||
|
||||
// 22
|
||||
assert!(m("ROOT/parent_dir/dir_deep_22").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_22/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_22/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_22", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_22/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_22/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_22/child_dir/file", false).is_ignore());
|
||||
|
||||
// 23
|
||||
assert!(m("ROOT/parent_dir/dir_deep_23").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_23/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_23/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_23", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_23/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_23/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_23/child_dir/file", false).is_ignore());
|
||||
|
||||
// 30
|
||||
assert!(m("ROOT/parent_dir/dir_deep_30").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_30/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_30/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_30", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_30/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_30/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_30/child_dir/file", false).is_ignore());
|
||||
|
||||
// 31
|
||||
assert!(m("ROOT/parent_dir/dir_deep_31").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_31/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_31/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_31", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_31/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_31/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_31/child_dir/file", false).is_ignore());
|
||||
|
||||
// 32
|
||||
assert!(m("ROOT/parent_dir/dir_deep_32").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_32/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_32/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_32", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_32/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_32/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_32/child_dir/file", false).is_ignore());
|
||||
|
||||
// 33
|
||||
assert!(m("ROOT/parent_dir/dir_deep_33").is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_33/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_33/child_dir/file").is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_33", true).is_none()); // dir itself doesn't match
|
||||
assert!(m("ROOT/parent_dir/dir_deep_33/file", false).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_33/child_dir", true).is_ignore());
|
||||
assert!(m("ROOT/parent_dir/dir_deep_33/child_dir/file", false).is_ignore());
|
||||
}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
class RipgrepBin < Formula
|
||||
version '0.5.2'
|
||||
version '0.7.0'
|
||||
desc "Search tool like grep and The Silver Searcher."
|
||||
homepage "https://github.com/BurntSushi/ripgrep"
|
||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
|
||||
sha256 "a0326a84af8517ad707d8c7cccba6e112de27822c391cc0937e4727fbb6c48f4"
|
||||
sha256 "ef5e76acde453bed774cecaeef8dbd96652d616d957ec1763d450c6f6d9e1d0d"
|
||||
|
||||
conflicts_with "ripgrep"
|
||||
|
||||
|
29
src/app.rs
29
src/app.rs
@@ -9,6 +9,10 @@ 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
|
||||
|
||||
Use -h for short descriptions and --help for more details.";
|
||||
@@ -90,9 +94,11 @@ pub fn app() -> App<'static, 'static> {
|
||||
.arg(flag("fixed-strings").short("F"))
|
||||
.arg(flag("glob").short("g")
|
||||
.takes_value(true).multiple(true).number_of_values(1)
|
||||
.set(ArgSettings::AllowLeadingHyphen)
|
||||
.value_name("GLOB"))
|
||||
.arg(flag("iglob")
|
||||
.takes_value(true).multiple(true).number_of_values(1)
|
||||
.set(ArgSettings::AllowLeadingHyphen)
|
||||
.value_name("GLOB"))
|
||||
.arg(flag("ignore-case").short("i"))
|
||||
.arg(flag("line-number").short("n"))
|
||||
@@ -107,7 +113,8 @@ pub fn app() -> App<'static, 'static> {
|
||||
.arg(flag("unrestricted").short("u")
|
||||
.multiple(true))
|
||||
.arg(flag("invert-match").short("v"))
|
||||
.arg(flag("word-regexp").short("w"))
|
||||
.arg(flag("word-regexp").short("w").overrides_with("line-regexp"))
|
||||
.arg(flag("line-regexp").short("x"))
|
||||
// Third, set up less common flags.
|
||||
.arg(flag("after-context").short("A")
|
||||
.value_name("NUM").takes_value(true)
|
||||
@@ -126,6 +133,7 @@ pub fn app() -> App<'static, 'static> {
|
||||
.arg(flag("debug"))
|
||||
.arg(flag("file").short("f")
|
||||
.value_name("FILE").takes_value(true)
|
||||
.set(ArgSettings::AllowLeadingHyphen)
|
||||
.multiple(true).number_of_values(1))
|
||||
.arg(flag("files-with-matches").short("l"))
|
||||
.arg(flag("files-without-match"))
|
||||
@@ -136,6 +144,7 @@ pub fn app() -> App<'static, 'static> {
|
||||
.arg(flag("hidden"))
|
||||
.arg(flag("ignore-file")
|
||||
.value_name("FILE").takes_value(true)
|
||||
.set(ArgSettings::AllowLeadingHyphen)
|
||||
.multiple(true).number_of_values(1))
|
||||
.arg(flag("follow").short("L"))
|
||||
.arg(flag("max-count")
|
||||
@@ -153,10 +162,12 @@ pub fn app() -> App<'static, 'static> {
|
||||
.arg(flag("no-ignore-parent"))
|
||||
.arg(flag("no-ignore-vcs"))
|
||||
.arg(flag("null").short("0"))
|
||||
.arg(flag("only-matching").short("o").conflicts_with("replace"))
|
||||
.arg(flag("only-matching").short("o"))
|
||||
.arg(flag("path-separator").value_name("SEPARATOR").takes_value(true))
|
||||
.arg(flag("pretty").short("p"))
|
||||
.arg(flag("replace").short("r").value_name("ARG").takes_value(true))
|
||||
.arg(flag("replace").short("r")
|
||||
.set(ArgSettings::AllowLeadingHyphen)
|
||||
.value_name("ARG").takes_value(true))
|
||||
.arg(flag("regex-size-limit")
|
||||
.value_name("NUM+SUFFIX?").takes_value(true))
|
||||
.arg(flag("case-sensitive").short("s"))
|
||||
@@ -342,6 +353,10 @@ lazy_static! {
|
||||
"Only show matches surrounded by word boundaries. This is \
|
||||
equivalent to putting \\b before and after all of the search \
|
||||
patterns.");
|
||||
doc!(h, "line-regexp",
|
||||
"Only show matches surrounded by line boundaries.",
|
||||
"Only show matches surrounded by line boundaries. This is \
|
||||
equivalent to putting ^...$ around all of the search patterns.");
|
||||
|
||||
doc!(h, "after-context",
|
||||
"Show NUM lines after each match.");
|
||||
@@ -383,8 +398,10 @@ lazy_static! {
|
||||
"Only show the paths that contains zero matches.");
|
||||
doc!(h, "with-filename",
|
||||
"Show file name for each match.",
|
||||
"Prefix each match with the file name that contains it. This is \
|
||||
the default when more than one file is searched.");
|
||||
"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.");
|
||||
doc!(h, "no-filename",
|
||||
"Never show the file name for a match.",
|
||||
"Never show the file name for a match. This is the default when \
|
||||
@@ -494,7 +511,7 @@ lazy_static! {
|
||||
is 10M. \n\nThe argument accepts the same size suffixes as \
|
||||
allowed in the 'max-filesize' argument.");
|
||||
doc!(h, "case-sensitive",
|
||||
"Search case sensitively.",
|
||||
"Search case sensitively (default).",
|
||||
"Search case sensitively. This overrides -i/--ignore-case and \
|
||||
-S/--smart-case.");
|
||||
doc!(h, "smart-case",
|
||||
|
26
src/args.rs
26
src/args.rs
@@ -287,7 +287,7 @@ impl Args {
|
||||
wd.parents(!self.no_ignore_parent);
|
||||
wd.threads(self.threads());
|
||||
if self.sort_files {
|
||||
wd.sort_by(|a, b| a.cmp(b));
|
||||
wd.sort_by_file_name(|a, b| a.cmp(b));
|
||||
}
|
||||
wd
|
||||
}
|
||||
@@ -427,7 +427,8 @@ impl<'a> ArgMatches<'a> {
|
||||
///
|
||||
/// Note that if -F/--fixed-strings is set, then all patterns will be
|
||||
/// escaped. Similarly, if -w/--word-regexp is set, then all patterns
|
||||
/// are surrounded by `\b`.
|
||||
/// are surrounded by `\b`, and if -x/--line-regexp is set, then all
|
||||
/// patterns are surrounded by `^...$`.
|
||||
///
|
||||
/// If any pattern is invalid UTF-8, then an error is returned.
|
||||
fn patterns(&self) -> Result<Vec<String>> {
|
||||
@@ -470,7 +471,7 @@ impl<'a> ArgMatches<'a> {
|
||||
Ok(pats)
|
||||
}
|
||||
|
||||
/// Converts an OsStr pattern to a String pattern, including word
|
||||
/// Converts an OsStr pattern to a String pattern, including line/word
|
||||
/// boundaries or escapes if applicable.
|
||||
///
|
||||
/// If the pattern is not valid UTF-8, then an error is returned.
|
||||
@@ -479,10 +480,12 @@ impl<'a> ArgMatches<'a> {
|
||||
Ok(self.str_pattern(s))
|
||||
}
|
||||
|
||||
/// Converts a &str pattern to a String pattern, including word
|
||||
/// Converts a &str pattern to a String pattern, including line/word
|
||||
/// boundaries or escapes if applicable.
|
||||
fn str_pattern(&self, pat: &str) -> String {
|
||||
let s = self.word_pattern(self.literal_pattern(pat.to_string()));
|
||||
let litpat = self.literal_pattern(pat.to_string());
|
||||
let s = self.line_pattern(self.word_pattern(litpat));
|
||||
|
||||
if s.is_empty() {
|
||||
self.empty_pattern()
|
||||
} else {
|
||||
@@ -511,6 +514,16 @@ impl<'a> ArgMatches<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the given pattern as a line pattern if the -x/--line-regexp
|
||||
/// flag is set. Otherwise, the pattern is returned unchanged.
|
||||
fn line_pattern(&self, pat: String) -> String {
|
||||
if self.is_present("line-regexp") {
|
||||
format!(r"^(?:{})$", pat)
|
||||
} else {
|
||||
pat
|
||||
}
|
||||
}
|
||||
|
||||
/// Empty pattern returns a pattern that is guaranteed to produce an empty
|
||||
/// regular expression that is valid in any position.
|
||||
fn empty_pattern(&self) -> String {
|
||||
@@ -692,7 +705,10 @@ impl<'a> ArgMatches<'a> {
|
||||
fn color_specs(&self) -> Result<ColorSpecs> {
|
||||
// Start with a default set of color specs.
|
||||
let mut specs = vec![
|
||||
#[cfg(unix)]
|
||||
"path:fg:magenta".parse().unwrap(),
|
||||
#[cfg(windows)]
|
||||
"path:fg:cyan".parse().unwrap(),
|
||||
"line:fg:green".parse().unwrap(),
|
||||
"match:fg:red".parse().unwrap(),
|
||||
"match:style:bold".parse().unwrap(),
|
||||
|
28
src/main.rs
28
src/main.rs
@@ -8,7 +8,6 @@ extern crate grep;
|
||||
extern crate ignore;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate libc;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate memchr;
|
||||
@@ -55,6 +54,7 @@ mod worker;
|
||||
pub type Result<T> = result::Result<T, Box<Error + Send + Sync>>;
|
||||
|
||||
fn main() {
|
||||
reset_sigpipe();
|
||||
match Args::parse().map(Arc::new).and_then(run) {
|
||||
Ok(0) => process::exit(1),
|
||||
Ok(_) => process::exit(0),
|
||||
@@ -108,6 +108,7 @@ fn run_parallel(args: Arc<Args>) -> Result<u64> {
|
||||
let dent = match get_or_log_dir_entry(
|
||||
result,
|
||||
args.stdout_handle(),
|
||||
args.files(),
|
||||
args.no_messages(),
|
||||
) {
|
||||
None => return Continue,
|
||||
@@ -154,6 +155,7 @@ fn run_one_thread(args: Arc<Args>) -> Result<u64> {
|
||||
let dent = match get_or_log_dir_entry(
|
||||
result,
|
||||
args.stdout_handle(),
|
||||
args.files(),
|
||||
args.no_messages(),
|
||||
) {
|
||||
None => continue,
|
||||
@@ -206,6 +208,7 @@ fn run_files_parallel(args: Arc<Args>) -> Result<u64> {
|
||||
if let Some(dent) = get_or_log_dir_entry(
|
||||
result,
|
||||
args.stdout_handle(),
|
||||
args.files(),
|
||||
args.no_messages(),
|
||||
) {
|
||||
tx.send(dent).unwrap();
|
||||
@@ -224,6 +227,7 @@ fn run_files_one_thread(args: Arc<Args>) -> Result<u64> {
|
||||
let dent = match get_or_log_dir_entry(
|
||||
result,
|
||||
args.stdout_handle(),
|
||||
args.files(),
|
||||
args.no_messages(),
|
||||
) {
|
||||
None => continue,
|
||||
@@ -251,6 +255,7 @@ fn run_types(args: Arc<Args>) -> Result<u64> {
|
||||
fn get_or_log_dir_entry(
|
||||
result: result::Result<ignore::DirEntry, ignore::Error>,
|
||||
stdout_handle: Option<&same_file::Handle>,
|
||||
files_only: bool,
|
||||
no_messages: bool,
|
||||
) -> Option<ignore::DirEntry> {
|
||||
match result {
|
||||
@@ -279,7 +284,7 @@ fn get_or_log_dir_entry(
|
||||
}
|
||||
// If we are redirecting stdout to a file, then don't search that
|
||||
// file.
|
||||
if is_stdout_file(&dent, stdout_handle, no_messages) {
|
||||
if !files_only && is_stdout_file(&dent, stdout_handle, no_messages) {
|
||||
return None;
|
||||
}
|
||||
Some(dent)
|
||||
@@ -330,3 +335,22 @@ fn eprint_nothing_searched() {
|
||||
applied a filter you didn't expect. \
|
||||
Try running again with --debug.");
|
||||
}
|
||||
|
||||
// The Rust standard library suppresses the default SIGPIPE behavior, so that
|
||||
// writing to a closed pipe doesn't kill the process. The goal is to instead
|
||||
// handle errors through the normal result mechanism. Ripgrep needs some
|
||||
// refactoring before it will be able to do that, however, so we re-enable the
|
||||
// standard SIGPIPE behavior as a workaround. See
|
||||
// https://github.com/BurntSushi/ripgrep/issues/200.
|
||||
#[cfg(unix)]
|
||||
fn reset_sigpipe() {
|
||||
extern crate libc;
|
||||
unsafe {
|
||||
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn reset_sigpipe() {
|
||||
// no-op
|
||||
}
|
||||
|
102
src/printer.rs
102
src/printer.rs
@@ -3,29 +3,58 @@ use std::fmt;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
use regex::bytes::{Captures, Regex, Replacer};
|
||||
use regex::bytes::{Captures, Match, Regex, Replacer};
|
||||
use termcolor::{Color, ColorSpec, ParseColorError, WriteColor};
|
||||
|
||||
use pathutil::strip_prefix;
|
||||
use ignore::types::FileTypeDef;
|
||||
|
||||
/// Track the start and end of replacements to allow coloring them on output.
|
||||
#[derive(Debug)]
|
||||
struct Offset {
|
||||
start: usize,
|
||||
end: usize,
|
||||
}
|
||||
|
||||
impl Offset {
|
||||
fn new(start: usize, end: usize) -> Offset {
|
||||
Offset { start: start, end: end }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'m, 'r> From<&'m Match<'r>> for Offset {
|
||||
fn from(m: &'m Match<'r>) -> Self {
|
||||
Offset{ start: m.start(), end: m.end() }
|
||||
}
|
||||
}
|
||||
|
||||
/// CountingReplacer implements the Replacer interface for Regex,
|
||||
/// and counts how often replacement is being performed.
|
||||
struct CountingReplacer<'r> {
|
||||
replace: &'r [u8],
|
||||
count: &'r mut usize,
|
||||
offsets: &'r mut Vec<Offset>,
|
||||
}
|
||||
|
||||
impl<'r> CountingReplacer<'r> {
|
||||
fn new(replace: &'r [u8], count: &'r mut usize) -> CountingReplacer<'r> {
|
||||
CountingReplacer { replace: replace, count: count }
|
||||
fn new(
|
||||
replace: &'r [u8],
|
||||
count: &'r mut usize,
|
||||
offsets: &'r mut Vec<Offset>,
|
||||
) -> CountingReplacer<'r> {
|
||||
CountingReplacer { replace: replace, count: count, offsets: offsets, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Replacer for CountingReplacer<'r> {
|
||||
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
|
||||
*self.count += 1;
|
||||
let start = dst.len();
|
||||
caps.expand(self.replace, dst);
|
||||
let end = dst.len();
|
||||
if start != end {
|
||||
self.offsets.push(Offset::new(start, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,10 +312,16 @@ impl<W: WriteColor> Printer<W> {
|
||||
}
|
||||
if self.replace.is_some() {
|
||||
let mut count = 0;
|
||||
let mut offsets = Vec::new();
|
||||
let line = {
|
||||
let replacer = CountingReplacer::new(
|
||||
self.replace.as_ref().unwrap(), &mut count);
|
||||
re.replace_all(&buf[start..end], replacer)
|
||||
self.replace.as_ref().unwrap(), &mut count, &mut offsets);
|
||||
if self.only_matching {
|
||||
re.replace_all(
|
||||
&buf[start + match_start..start + match_end], replacer)
|
||||
} else {
|
||||
re.replace_all(&buf[start..end], replacer)
|
||||
}
|
||||
};
|
||||
if self.max_columns.map_or(false, |m| line.len() > m) {
|
||||
let msg = format!(
|
||||
@@ -295,44 +330,45 @@ impl<W: WriteColor> Printer<W> {
|
||||
self.write_eol();
|
||||
return;
|
||||
}
|
||||
self.write(&line);
|
||||
if line.last() != Some(&self.eol) {
|
||||
self.write_eol();
|
||||
}
|
||||
self.write_matched_line(offsets, &*line, false);
|
||||
} else {
|
||||
if self.only_matching {
|
||||
let buf = &buf[start + match_start..start + match_end];
|
||||
self.write_matched_line(re, buf, true);
|
||||
let buf = if self.only_matching {
|
||||
&buf[start + match_start..start + match_end]
|
||||
} else {
|
||||
self.write_matched_line(re, &buf[start..end], false);
|
||||
&buf[start..end]
|
||||
};
|
||||
if self.max_columns.map_or(false, |m| buf.len() > m) {
|
||||
let count = re.find_iter(buf).count();
|
||||
let msg = format!("[Omitted long line with {} matches]", count);
|
||||
self.write_colored(msg.as_bytes(), |colors| colors.matched());
|
||||
self.write_eol();
|
||||
return;
|
||||
}
|
||||
let only_match = self.only_matching;
|
||||
self.write_matched_line(
|
||||
re.find_iter(buf).map(|x| Offset::from(&x)), buf, only_match);
|
||||
}
|
||||
}
|
||||
|
||||
fn write_matched_line(
|
||||
&mut self,
|
||||
re: &Regex,
|
||||
buf: &[u8],
|
||||
only_match: bool,
|
||||
) {
|
||||
if self.max_columns.map_or(false, |m| buf.len() > m) {
|
||||
let count = re.find_iter(buf).count();
|
||||
let msg = format!("[Omitted long line with {} matches]", count);
|
||||
self.write_colored(msg.as_bytes(), |colors| colors.matched());
|
||||
self.write_eol();
|
||||
return;
|
||||
}
|
||||
fn write_matched_line<I>(&mut self, offsets: I, buf: &[u8], only_match: bool)
|
||||
where I: IntoIterator<Item=Offset>,
|
||||
{
|
||||
if !self.wtr.supports_color() || self.colors.matched().is_none() {
|
||||
self.write(buf);
|
||||
} else if only_match {
|
||||
self.write_colored(buf, |colors| colors.matched());
|
||||
} else {
|
||||
let mut last_written = 0;
|
||||
for m in re.find_iter(buf) {
|
||||
self.write(&buf[last_written..m.start()]);
|
||||
self.write_colored(
|
||||
&buf[m.start()..m.end()], |colors| colors.matched());
|
||||
last_written = m.end();
|
||||
for o in offsets {
|
||||
self.write(&buf[last_written..o.start]);
|
||||
// This conditional checks if the match is both empty *and*
|
||||
// past the end of the line. In this case, we never want to
|
||||
// emit an additional color escape.
|
||||
if o.start != o.end || o.end != buf.len() {
|
||||
self.write_colored(
|
||||
&buf[o.start..o.end], |colors| colors.matched());
|
||||
}
|
||||
last_written = o.end;
|
||||
}
|
||||
self.write(&buf[last_written..]);
|
||||
}
|
||||
@@ -443,7 +479,7 @@ impl<W: WriteColor> Printer<W> {
|
||||
fn write_colored<F>(&mut self, buf: &[u8], get_color: F)
|
||||
where F: Fn(&ColorSpecs) -> &ColorSpec
|
||||
{
|
||||
let _ = self.wtr.set_color( get_color(&self.colors) );
|
||||
let _ = self.wtr.set_color(get_color(&self.colors));
|
||||
self.write(buf);
|
||||
let _ = self.wtr.reset();
|
||||
}
|
||||
@@ -576,7 +612,7 @@ pub struct ColorSpecs {
|
||||
/// Valid colors are `black`, `blue`, `green`, `red`, `cyan`, `magenta`,
|
||||
/// `yellow`, `white`.
|
||||
///
|
||||
/// Valid style instructions are `nobold` and `bold`.
|
||||
/// Valid style instructions are `nobold`, `bold`, `intense`, `nointense`.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Spec {
|
||||
ty: OutType,
|
||||
|
@@ -299,6 +299,15 @@ impl<'a, R: io::Read, W: WriteColor> Searcher<'a, R, W> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.after_context_remaining > 0 {
|
||||
if self.last_printed == self.inp.lastnl {
|
||||
try!(self.fill());
|
||||
}
|
||||
let upto = self.inp.lastnl;
|
||||
if upto > 0 {
|
||||
self.print_after_context(upto);
|
||||
}
|
||||
}
|
||||
if self.match_count > 0 {
|
||||
if self.opts.count {
|
||||
self.printer.path_count(self.path, self.match_count);
|
||||
@@ -1247,6 +1256,23 @@ fn main() {
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_context_invert_one_max_count_two() {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.line_number(true)
|
||||
.invert_match(true)
|
||||
.after_context(1)
|
||||
.max_count(Some(2))
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
assert_eq!(out, "\
|
||||
/baz.rs:2:Holmeses, success in the province of detective work must always
|
||||
/baz.rs-3-be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
/baz.rs:4:can extract a clew from a wisp of straw or a flake of cigar ash;
|
||||
/baz.rs-5-but Doctor Watson has to have it taken out for him and dusted,
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_context_two1() {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
@@ -1290,6 +1316,23 @@ fn main() {
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_context_two_max_count_two() {
|
||||
let (count, out) = search_smallcap(
|
||||
"Doctor", SHERLOCK, |s| {
|
||||
s.line_number(true).after_context(2).max_count(Some(2))
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
assert_eq!(out, "\
|
||||
/baz.rs:1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
/baz.rs-2-Holmeses, success in the province of detective work must always
|
||||
/baz.rs-3-be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
--
|
||||
/baz.rs:5:but Doctor Watson has to have it taken out for him and dusted,
|
||||
/baz.rs-6-and exhibited clearly, with a label attached.
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_context_three1() {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "termcolor"
|
||||
version = "0.3.2" #:version
|
||||
version = "0.3.3" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
A simple cross platform library for writing colored text to a terminal.
|
||||
|
@@ -202,15 +202,23 @@ enum IoStandardStream {
|
||||
impl IoStandardStream {
|
||||
fn new(sty: StandardStreamType) -> IoStandardStream {
|
||||
match sty {
|
||||
StandardStreamType::Stdout => IoStandardStream::Stdout(io::stdout()),
|
||||
StandardStreamType::Stderr => IoStandardStream::Stderr(io::stderr()),
|
||||
StandardStreamType::Stdout => {
|
||||
IoStandardStream::Stdout(io::stdout())
|
||||
}
|
||||
StandardStreamType::Stderr => {
|
||||
IoStandardStream::Stderr(io::stderr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lock(&self) -> IoStandardStreamLock {
|
||||
match *self {
|
||||
IoStandardStream::Stdout(ref s) => IoStandardStreamLock::StdoutLock(s.lock()),
|
||||
IoStandardStream::Stderr(ref s) => IoStandardStreamLock::StderrLock(s.lock()),
|
||||
IoStandardStream::Stdout(ref s) => {
|
||||
IoStandardStreamLock::StdoutLock(s.lock())
|
||||
}
|
||||
IoStandardStream::Stderr(ref s) => {
|
||||
IoStandardStreamLock::StderrLock(s.lock())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,7 +239,7 @@ impl io::Write for IoStandardStream {
|
||||
}
|
||||
}
|
||||
|
||||
/// Same rigamorale 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>),
|
||||
@@ -257,7 +265,7 @@ impl<'a> io::Write for IoStandardStreamLock<'a> {
|
||||
/// Satisfies `io::Write` and `WriteColor`, and supports optional coloring
|
||||
/// to either of the standard output streams, stdout and stderr.
|
||||
pub struct StandardStream {
|
||||
wtr: LossyStandardStream<WriterInner<'static, IoStandardStream>>,
|
||||
wtr: LossyStandardStream<WriterInner<IoStandardStream>>,
|
||||
}
|
||||
|
||||
/// `StandardStreamLock` is a locked reference to a `StandardStream`.
|
||||
@@ -265,26 +273,34 @@ pub struct StandardStream {
|
||||
/// This implements the `io::Write` and `WriteColor` traits, and is constructed
|
||||
/// via the `Write::lock` method.
|
||||
///
|
||||
/// The lifetime `'a` refers to the lifetime of the corresponding `StandardStream`.
|
||||
/// The lifetime `'a` refers to the lifetime of the corresponding
|
||||
/// `StandardStream`.
|
||||
pub struct StandardStreamLock<'a> {
|
||||
wtr: LossyStandardStream<WriterInner<'a, IoStandardStreamLock<'a>>>,
|
||||
wtr: LossyStandardStream<WriterInnerLock<'a, IoStandardStreamLock<'a>>>,
|
||||
}
|
||||
|
||||
/// WriterInner is a (limited) generic representation of a writer. It is
|
||||
/// limited because W should only ever be stdout/stderr on Windows.
|
||||
enum WriterInner<'a, W> {
|
||||
enum WriterInner<W> {
|
||||
NoColor(NoColor<W>),
|
||||
Ansi(Ansi<W>),
|
||||
#[cfg(windows)]
|
||||
Windows { wtr: W, console: Mutex<wincolor::Console> },
|
||||
}
|
||||
|
||||
/// WriterInnerLock is a (limited) generic representation of a writer. It is
|
||||
/// limited because W should only ever be stdout/stderr on Windows.
|
||||
enum WriterInnerLock<'a, W> {
|
||||
NoColor(NoColor<W>),
|
||||
Ansi(Ansi<W>),
|
||||
/// What a gross hack. On Windows, we need to specify a lifetime for the
|
||||
/// console when in a locked state, but obviously don't need to do that
|
||||
/// on Unix, which make the `'a` unused. To satisfy the compiler, we need
|
||||
/// on Unix, which makes the `'a` unused. To satisfy the compiler, we need
|
||||
/// a PhantomData.
|
||||
#[allow(dead_code)]
|
||||
Unreachable(::std::marker::PhantomData<&'a ()>),
|
||||
#[cfg(windows)]
|
||||
Windows { wtr: W, console: Mutex<wincolor::Console> },
|
||||
#[cfg(windows)]
|
||||
WindowsLocked { wtr: W, console: MutexGuard<'a, wincolor::Console> },
|
||||
Windows { wtr: W, console: MutexGuard<'a, wincolor::Console> },
|
||||
}
|
||||
|
||||
impl StandardStream {
|
||||
@@ -332,7 +348,9 @@ impl StandardStream {
|
||||
} else {
|
||||
WriterInner::NoColor(NoColor(IoStandardStream::new(sty)))
|
||||
};
|
||||
StandardStream { wtr: LossyStandardStream::new(wtr).is_console(is_win_console) }
|
||||
StandardStream {
|
||||
wtr: LossyStandardStream::new(wtr).is_console(is_win_console),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new `StandardStream` with the given color preferences that
|
||||
@@ -375,12 +393,11 @@ impl<'a> StandardStreamLock<'a> {
|
||||
#[cfg(not(windows))]
|
||||
fn from_stream(stream: &StandardStream) -> StandardStreamLock {
|
||||
let locked = match *stream.wtr.get_ref() {
|
||||
WriterInner::Unreachable(_) => unreachable!(),
|
||||
WriterInner::NoColor(ref w) => {
|
||||
WriterInner::NoColor(NoColor(w.0.lock()))
|
||||
WriterInnerLock::NoColor(NoColor(w.0.lock()))
|
||||
}
|
||||
WriterInner::Ansi(ref w) => {
|
||||
WriterInner::Ansi(Ansi(w.0.lock()))
|
||||
WriterInnerLock::Ansi(Ansi(w.0.lock()))
|
||||
}
|
||||
};
|
||||
StandardStreamLock { wtr: stream.wtr.wrap(locked) }
|
||||
@@ -389,24 +406,19 @@ impl<'a> StandardStreamLock<'a> {
|
||||
#[cfg(windows)]
|
||||
fn from_stream(stream: &StandardStream) -> StandardStreamLock {
|
||||
let locked = match *stream.wtr.get_ref() {
|
||||
WriterInner::Unreachable(_) => unreachable!(),
|
||||
WriterInner::NoColor(ref w) => {
|
||||
WriterInner::NoColor(NoColor(w.0.lock()))
|
||||
WriterInnerLock::NoColor(NoColor(w.0.lock()))
|
||||
}
|
||||
WriterInner::Ansi(ref w) => {
|
||||
WriterInner::Ansi(Ansi(w.0.lock()))
|
||||
WriterInnerLock::Ansi(Ansi(w.0.lock()))
|
||||
}
|
||||
#[cfg(windows)]
|
||||
WriterInner::Windows { ref wtr, ref console } => {
|
||||
WriterInner::WindowsLocked {
|
||||
WriterInnerLock::Windows {
|
||||
wtr: wtr.lock(),
|
||||
console: console.lock().unwrap(),
|
||||
}
|
||||
}
|
||||
#[cfg(windows)]
|
||||
WriterInner::WindowsLocked{..} => {
|
||||
panic!("cannot call StandardStream.lock while a StandardStreamLock is alive");
|
||||
}
|
||||
};
|
||||
StandardStreamLock { wtr: stream.wtr.wrap(locked) }
|
||||
}
|
||||
@@ -438,48 +450,38 @@ impl<'a> WriteColor for StandardStreamLock<'a> {
|
||||
fn reset(&mut self) -> io::Result<()> { self.wtr.reset() }
|
||||
}
|
||||
|
||||
impl<'a, W: io::Write> io::Write for WriterInner<'a, W> {
|
||||
impl<W: io::Write> io::Write for WriterInner<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
match *self {
|
||||
WriterInner::Unreachable(_) => unreachable!(),
|
||||
WriterInner::NoColor(ref mut wtr) => wtr.write(buf),
|
||||
WriterInner::Ansi(ref mut wtr) => wtr.write(buf),
|
||||
#[cfg(windows)]
|
||||
WriterInner::Windows { ref mut wtr, .. } => wtr.write(buf),
|
||||
#[cfg(windows)]
|
||||
WriterInner::WindowsLocked { ref mut wtr, .. } => wtr.write(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
match *self {
|
||||
WriterInner::Unreachable(_) => unreachable!(),
|
||||
WriterInner::NoColor(ref mut wtr) => wtr.flush(),
|
||||
WriterInner::Ansi(ref mut wtr) => wtr.flush(),
|
||||
#[cfg(windows)]
|
||||
WriterInner::Windows { ref mut wtr, .. } => wtr.flush(),
|
||||
#[cfg(windows)]
|
||||
WriterInner::WindowsLocked { ref mut wtr, .. } => wtr.flush(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: io::Write> WriteColor for WriterInner<'a, W> {
|
||||
impl<W: io::Write> WriteColor for WriterInner<W> {
|
||||
fn supports_color(&self) -> bool {
|
||||
match *self {
|
||||
WriterInner::Unreachable(_) => unreachable!(),
|
||||
WriterInner::NoColor(_) => false,
|
||||
WriterInner::Ansi(_) => true,
|
||||
#[cfg(windows)]
|
||||
WriterInner::Windows { .. } => true,
|
||||
#[cfg(windows)]
|
||||
WriterInner::WindowsLocked { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
|
||||
match *self {
|
||||
WriterInner::Unreachable(_) => unreachable!(),
|
||||
WriterInner::NoColor(ref mut wtr) => wtr.set_color(spec),
|
||||
WriterInner::Ansi(ref mut wtr) => wtr.set_color(spec),
|
||||
#[cfg(windows)]
|
||||
@@ -488,17 +490,11 @@ impl<'a, W: io::Write> WriteColor for WriterInner<'a, W> {
|
||||
let mut console = console.lock().unwrap();
|
||||
spec.write_console(&mut *console)
|
||||
}
|
||||
#[cfg(windows)]
|
||||
WriterInner::WindowsLocked { ref mut wtr, ref mut console } => {
|
||||
try!(wtr.flush());
|
||||
spec.write_console(console)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> io::Result<()> {
|
||||
match *self {
|
||||
WriterInner::Unreachable(_) => unreachable!(),
|
||||
WriterInner::NoColor(ref mut wtr) => wtr.reset(),
|
||||
WriterInner::Ansi(ref mut wtr) => wtr.reset(),
|
||||
#[cfg(windows)]
|
||||
@@ -507,8 +503,63 @@ impl<'a, W: io::Write> WriteColor for WriterInner<'a, W> {
|
||||
try!(console.lock().unwrap().reset());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: io::Write> io::Write for WriterInnerLock<'a, W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
match *self {
|
||||
WriterInnerLock::Unreachable(_) => unreachable!(),
|
||||
WriterInnerLock::NoColor(ref mut wtr) => wtr.write(buf),
|
||||
WriterInnerLock::Ansi(ref mut wtr) => wtr.write(buf),
|
||||
#[cfg(windows)]
|
||||
WriterInner::WindowsLocked { ref mut wtr, ref mut console } => {
|
||||
WriterInnerLock::Windows { ref mut wtr, .. } => wtr.write(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
match *self {
|
||||
WriterInnerLock::Unreachable(_) => unreachable!(),
|
||||
WriterInnerLock::NoColor(ref mut wtr) => wtr.flush(),
|
||||
WriterInnerLock::Ansi(ref mut wtr) => wtr.flush(),
|
||||
#[cfg(windows)]
|
||||
WriterInnerLock::Windows { ref mut wtr, .. } => wtr.flush(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: io::Write> WriteColor for WriterInnerLock<'a, W> {
|
||||
fn supports_color(&self) -> bool {
|
||||
match *self {
|
||||
WriterInnerLock::Unreachable(_) => unreachable!(),
|
||||
WriterInnerLock::NoColor(_) => false,
|
||||
WriterInnerLock::Ansi(_) => true,
|
||||
#[cfg(windows)]
|
||||
WriterInnerLock::Windows { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
|
||||
match *self {
|
||||
WriterInnerLock::Unreachable(_) => unreachable!(),
|
||||
WriterInnerLock::NoColor(ref mut wtr) => wtr.set_color(spec),
|
||||
WriterInnerLock::Ansi(ref mut wtr) => wtr.set_color(spec),
|
||||
#[cfg(windows)]
|
||||
WriterInnerLock::Windows { ref mut wtr, ref mut console } => {
|
||||
try!(wtr.flush());
|
||||
spec.write_console(console)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> io::Result<()> {
|
||||
match *self {
|
||||
WriterInnerLock::Unreachable(_) => unreachable!(),
|
||||
WriterInnerLock::NoColor(ref mut wtr) => wtr.reset(),
|
||||
WriterInnerLock::Ansi(ref mut wtr) => wtr.reset(),
|
||||
#[cfg(windows)]
|
||||
WriterInnerLock::Windows { ref mut wtr, ref mut console } => {
|
||||
try!(wtr.flush());
|
||||
try!(console.reset());
|
||||
Ok(())
|
||||
@@ -565,7 +616,8 @@ impl BufferWriter {
|
||||
StandardStreamType::Stdout => wincolor::Console::stdout(),
|
||||
StandardStreamType::Stderr => wincolor::Console::stderr(),
|
||||
}.ok().map(Mutex::new);
|
||||
let stream = LossyStandardStream::new(IoStandardStream::new(sty)).is_console(con.is_some());
|
||||
let stream = LossyStandardStream::new(IoStandardStream::new(sty))
|
||||
.is_console(con.is_some());
|
||||
BufferWriter {
|
||||
stream: stream,
|
||||
printed: AtomicBool::new(false),
|
||||
@@ -1253,7 +1305,9 @@ struct LossyStandardStream<W> {
|
||||
|
||||
impl<W: io::Write> LossyStandardStream<W> {
|
||||
#[cfg(not(windows))]
|
||||
fn new(wtr: W) -> LossyStandardStream<W> { LossyStandardStream { wtr: wtr } }
|
||||
fn new(wtr: W) -> LossyStandardStream<W> {
|
||||
LossyStandardStream { wtr: wtr }
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn new(wtr: W) -> LossyStandardStream<W> {
|
||||
@@ -1320,3 +1374,15 @@ fn write_lossy_utf8<W: io::Write>(mut w: W, buf: &[u8]) -> io::Result<usize> {
|
||||
Err(e) => w.write(&buf[..e.valid_up_to()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::StandardStream;
|
||||
|
||||
fn assert_is_send<T: Send>() {}
|
||||
|
||||
#[test]
|
||||
fn standard_stream_is_send() {
|
||||
assert_is_send::<StandardStream>();
|
||||
}
|
||||
}
|
||||
|
@@ -209,6 +209,16 @@ For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(line, "Watson|and exhibited clearly, with a label attached.",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-x");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
and exhibited clearly, with a label attached.
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(literal, "()", "file", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file", "blib\n()\nblab\n");
|
||||
cmd.arg("-F");
|
||||
@@ -256,6 +266,20 @@ but Watson, Doctor has to have it taken out for him and dusted,
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(replace_with_only_matching, "of (\\w+)",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-o").arg("-r").arg("$1");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
this
|
||||
detective
|
||||
luck
|
||||
straw
|
||||
cigar
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(file_types, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file.py", "Sherlock");
|
||||
wd.create("file.rs", "Sherlock");
|
||||
@@ -1004,12 +1028,15 @@ fn regression_210() {
|
||||
let badutf8 = OsStr::from_bytes(&b"foo\xffbar"[..]);
|
||||
|
||||
let wd = WorkDir::new("regression_210");
|
||||
let mut cmd = wd.command();
|
||||
wd.create(badutf8, "test");
|
||||
cmd.arg("-H").arg("test").arg(badutf8);
|
||||
// APFS does not support creating files with invalid UTF-8 bytes.
|
||||
// https://github.com/BurntSushi/ripgrep/issues/559
|
||||
if wd.try_create(badutf8, "test").is_ok() {
|
||||
let mut cmd = wd.command();
|
||||
cmd.arg("-H").arg("test").arg(badutf8);
|
||||
|
||||
let out = wd.output(&mut cmd);
|
||||
assert_eq!(out.stdout, b"foo\xffbar:test\n".to_vec());
|
||||
let out = wd.output(&mut cmd);
|
||||
assert_eq!(out.stdout, b"foo\xffbar:test\n".to_vec());
|
||||
}
|
||||
}
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/228
|
||||
@@ -1080,16 +1107,19 @@ clean!(regression_405, "test", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/428
|
||||
clean!(regression_428_color_context_path, "foo", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
#[cfg(not(windows))]
|
||||
clean!(regression_428_color_context_path, "foo", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("sherlock", "foo\nbar");
|
||||
cmd.arg("-A1").arg("-H").arg("--no-heading").arg("-N")
|
||||
.arg("--colors=match:none").arg("--color=always");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = format!("\
|
||||
{colored_path}:foo
|
||||
{colored_path}-bar
|
||||
", colored_path=format!("\x1b\x5b\x6d\x1b\x5b\x33\x35\x6d{path}\x1b\x5b\x6d", path=path("sherlock")));
|
||||
let expected = format!(
|
||||
"{colored_path}:foo\n{colored_path}-bar\n",
|
||||
colored_path=format!(
|
||||
"\x1b\x5b\x6d\x1b\x5b\x33\x35\x6d{path}\x1b\x5b\x6d",
|
||||
path=path("sherlock")));
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
@@ -1116,6 +1146,29 @@ clean!(regression_493, " 're ", "input.txt", |wd: WorkDir, mut cmd: Command| {
|
||||
assert_eq!(lines, " 're \n");
|
||||
});
|
||||
|
||||
// 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");
|
||||
cmd.args(&[
|
||||
"--color", "ansi",
|
||||
"--colors", "path:none",
|
||||
"--colors", "line:none",
|
||||
"--colors", "match:fg:red",
|
||||
"--colors", "match:style:nobold",
|
||||
"--line-number",
|
||||
]);
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
// Technically, the expected output should only be two lines, but:
|
||||
// https://github.com/BurntSushi/ripgrep/issues/441
|
||||
let expected = "\
|
||||
[m1[m:[m[31m[m
|
||||
[m2[m:[m[31m[m
|
||||
[m4[m:
|
||||
";
|
||||
assert_eq!(expected, lines);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/1
|
||||
clean!(feature_1_sjis, "Шерлок Холмс", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
let sherlock =
|
||||
@@ -1705,6 +1758,7 @@ fn regression_483_non_matching_exit_code() {
|
||||
|
||||
wd.assert_err(&mut cmd);
|
||||
}
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/506
|
||||
#[test]
|
||||
fn regression_506_word_boundaries_not_parenthesized() {
|
||||
@@ -1720,7 +1774,29 @@ fn regression_506_word_boundaries_not_parenthesized() {
|
||||
let expected = "min\nmax\n";
|
||||
|
||||
assert_eq!(lines, expected);
|
||||
}
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/568
|
||||
#[test]
|
||||
fn regression_568_leading_hyphen_option_arguments() {
|
||||
let wd = WorkDir::new("regression_568_leading_hyphen_option_arguments");
|
||||
let path = "file";
|
||||
wd.create(path, "foo bar -baz\n");
|
||||
|
||||
let mut cmd = wd.command();
|
||||
cmd.arg("-e-baz").arg("-e").arg("-baz").arg(path);
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "foo bar -baz\n");
|
||||
|
||||
let mut cmd = wd.command();
|
||||
cmd.arg("-rni").arg("bar").arg(path);
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "foo ni -baz\n");
|
||||
|
||||
let mut cmd = wd.command();
|
||||
cmd.arg("-r").arg("-n").arg("-i").arg("bar").arg(path);
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "foo -n -baz\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@@ -41,11 +41,19 @@ impl WorkDir {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new file with the given name and contents in this directory.
|
||||
/// Create a new file with the given name and contents in this directory,
|
||||
/// or panic on error.
|
||||
pub fn create<P: AsRef<Path>>(&self, name: P, contents: &str) {
|
||||
self.create_bytes(name, contents.as_bytes());
|
||||
}
|
||||
|
||||
/// Try to create a new file with the given name and contents in this
|
||||
/// directory.
|
||||
pub fn try_create<P: AsRef<Path>>(&self, name: P, contents: &str) -> io::Result<()> {
|
||||
let path = self.dir.join(name);
|
||||
self.try_create_bytes(path, contents.as_bytes())
|
||||
}
|
||||
|
||||
/// Create a new file with the given name and size.
|
||||
pub fn create_size<P: AsRef<Path>>(&self, name: P, filesize: u64) {
|
||||
let path = self.dir.join(name);
|
||||
@@ -53,12 +61,19 @@ impl WorkDir {
|
||||
nice_err(&path, file.set_len(filesize));
|
||||
}
|
||||
|
||||
/// Create a new file with the given name and contents in this directory.
|
||||
/// Create a new file with the given name and contents in this directory,
|
||||
/// or panic on error.
|
||||
pub fn create_bytes<P: AsRef<Path>>(&self, name: P, contents: &[u8]) {
|
||||
let path = self.dir.join(name);
|
||||
let mut file = nice_err(&path, File::create(&path));
|
||||
nice_err(&path, file.write_all(contents));
|
||||
nice_err(&path, file.flush());
|
||||
nice_err(&path, self.try_create_bytes(&path, contents));
|
||||
}
|
||||
|
||||
/// Try to create a new file with the given name and contents in this
|
||||
/// directory.
|
||||
fn try_create_bytes<P: AsRef<Path>>(&self, path: P, contents: &[u8]) -> io::Result<()> {
|
||||
let mut file = File::create(&path)?;
|
||||
file.write_all(contents)?;
|
||||
file.flush()
|
||||
}
|
||||
|
||||
/// Remove a file with the given name from this directory.
|
||||
|
Reference in New Issue
Block a user