mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-08-03 13:42:06 -07:00
Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
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 |
34
CHANGELOG.md
34
CHANGELOG.md
@@ -1,3 +1,37 @@
|
|||||||
|
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)
|
0.6.0 (2017-08-23)
|
||||||
==================
|
==================
|
||||||
This is a new minor version release of ripgrep that includes many bug fixes
|
This is a new minor version release of ripgrep that includes many bug fixes
|
||||||
|
153
Cargo.lock
generated
153
Cargo.lock
generated
@@ -1,22 +1,23 @@
|
|||||||
[root]
|
[root]
|
||||||
name = "ripgrep"
|
name = "ripgrep"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty 0.2.2 (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)",
|
"bytecount 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"clap 2.26.0 (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.6.11 (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)",
|
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"grep 0.1.6",
|
"grep 0.1.7",
|
||||||
"ignore 0.2.2",
|
"ignore 0.3.0",
|
||||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"memchr 1.0.1 (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)",
|
"memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num_cpus 1.6.2 (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)",
|
"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)",
|
"same-file 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"termcolor 0.3.2",
|
"termcolor 0.3.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -24,7 +25,7 @@ name = "aho-corasick"
|
|||||||
version = "0.6.3"
|
version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
@@ -34,11 +35,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.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.29 (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)",
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -62,16 +64,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.26.0"
|
version = "2.26.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -83,7 +84,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.6.11"
|
version = "0.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -109,43 +110,44 @@ version = "0.4.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.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.29 (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)",
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"memchr 1.0.1 (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 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep"
|
name = "grep"
|
||||||
version = "0.1.6"
|
version = "0.1.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"memchr 1.0.1 (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 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)",
|
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.2.2"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"globset 0.2.0",
|
"globset 0.2.1",
|
||||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"memchr 1.0.1 (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 0.2.2 (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)",
|
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -159,12 +161,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "0.2.8"
|
version = "0.2.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.29"
|
version = "0.2.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -174,10 +176,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "1.0.1"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.29 (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]]
|
[[package]]
|
||||||
@@ -187,16 +197,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"fs2 0.4.2 (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)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.29 (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)",
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_cpus"
|
name = "num_cpus"
|
||||||
version = "1.6.2"
|
version = "1.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.29 (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]]
|
[[package]]
|
||||||
@@ -205,7 +228,7 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -219,7 +242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "0.1.3"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -247,20 +270,30 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.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.29 (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)",
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wincolor 0.1.4",
|
"wincolor 0.1.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termion"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"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]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.7.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -272,15 +305,10 @@ name = "thread_local"
|
|||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static 0.2.8 (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)",
|
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-segmentation"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
@@ -311,12 +339,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "1.0.7"
|
version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"same-file 1.0.0 (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)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -340,38 +366,41 @@ dependencies = [
|
|||||||
[metadata]
|
[metadata]
|
||||||
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
|
"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 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 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 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 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 cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||||
"checksum clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2267a8fdd4dce6956ba6649e130f62fb279026e5e84b92aa939ac8f85ce3f9f0"
|
"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 crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
|
||||||
"checksum encoding_rs 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e00a1b1e95eb46988805ceee6f34cd95c46a6753e290cb3ff0486931989d4a4c"
|
"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 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 fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
|
||||||
"checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
|
"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 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 lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5"
|
||||||
"checksum libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "8a014d9226c2cc402676fbe9ea2e15dd5222cd1dd57f576b5b283178c944a264"
|
"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 log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
|
||||||
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
|
"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 memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46f3c7359028b31999287dae4e5047ddfe90a23b7dca2282ce759b491080c99b"
|
||||||
"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"
|
"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 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 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.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 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 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 term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
|
||||||
"checksum textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f728584ea33b0ad19318e20557cb0a39097751dbb07171419673502f848c7af6"
|
"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 thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
|
||||||
"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
|
|
||||||
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
||||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
"checksum 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 utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
|
||||||
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
|
"checksum 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 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 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"
|
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||||
|
21
Cargo.toml
21
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ripgrep"
|
name = "ripgrep"
|
||||||
version = "0.6.0" #:version
|
version = "0.7.0" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Line oriented search tool using Rust's regex library. Combines the raw
|
Line oriented search tool using Rust's regex library. Combines the raw
|
||||||
@@ -33,18 +33,19 @@ path = "tests/tests.rs"
|
|||||||
atty = "0.2.2"
|
atty = "0.2.2"
|
||||||
bytecount = "0.1.4"
|
bytecount = "0.1.4"
|
||||||
clap = "2.26"
|
clap = "2.26"
|
||||||
encoding_rs = "0.6"
|
encoding_rs = "0.7"
|
||||||
env_logger = { version = "0.4", default-features = false }
|
env_logger = { version = "0.4", default-features = false }
|
||||||
grep = { version = "0.1.5", path = "grep" }
|
grep = { version = "0.1.7", path = "grep" }
|
||||||
ignore = { version = "0.2.2", path = "ignore" }
|
ignore = { version = "0.3.0", path = "ignore" }
|
||||||
lazy_static = "0.2"
|
lazy_static = "0.2"
|
||||||
|
libc = "0.2"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
memchr = "1"
|
memchr = "2"
|
||||||
memmap = "0.5"
|
memmap = "0.5"
|
||||||
num_cpus = "1"
|
num_cpus = "1"
|
||||||
regex = "0.2.1"
|
regex = "0.2.1"
|
||||||
same-file = "0.1.1"
|
same-file = "1"
|
||||||
termcolor = { version = "0.3.0", path = "termcolor" }
|
termcolor = { version = "0.3.3", path = "termcolor" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
clap = "2.26"
|
clap = "2.26"
|
||||||
@@ -52,7 +53,11 @@ lazy_static = "0.2"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
avx-accel = ["bytecount/avx-accel"]
|
avx-accel = ["bytecount/avx-accel"]
|
||||||
simd-accel = ["bytecount/simd-accel", "regex/simd-accel", "encoding_rs/simd-accel"]
|
simd-accel = [
|
||||||
|
"bytecount/simd-accel",
|
||||||
|
"regex/simd-accel",
|
||||||
|
"encoding_rs/simd-accel",
|
||||||
|
]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = true
|
debug = true
|
||||||
|
73
README.md
73
README.md
@@ -1,10 +1,10 @@
|
|||||||
ripgrep (rg)
|
ripgrep (rg)
|
||||||
------------
|
------------
|
||||||
`ripgrep` is a line oriented search tool that combines the usability of The
|
`ripgrep` is a line oriented search tool that recursively searches your current
|
||||||
Silver Searcher (similar to `ack`) with the raw speed of GNU grep. `ripgrep`
|
directory for a regex pattern while respecting your gitignore rules. To a first
|
||||||
works by recursively searching your current directory for a regex pattern.
|
approximation, ripgrep combines the usability of The Silver Searcher (similar
|
||||||
`ripgrep` has first class support on Windows, Mac and Linux, with binary
|
to `ack`) with the raw speed of GNU grep. `ripgrep` has first class support on
|
||||||
downloads available for
|
Windows, macOS and Linux, with binary downloads available for
|
||||||
[every release](https://github.com/BurntSushi/ripgrep/releases).
|
[every release](https://github.com/BurntSushi/ripgrep/releases).
|
||||||
|
|
||||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
[](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`?
|
### Why should I use `ripgrep`?
|
||||||
|
|
||||||
* It can replace both The Silver Searcher and GNU grep because it is faster
|
* It can replace both The Silver Searcher and GNU grep because it is generally
|
||||||
than both. (N.B. It is not, strictly speaking, a "drop-in" replacement for
|
faster than both. (N.B. It is not, strictly speaking, a "drop-in" replacement
|
||||||
both, but the feature sets are far more similar than different.)
|
for both, but the feature sets are far more similar than different.)
|
||||||
* Like The Silver Searcher, `ripgrep` defaults to recursive directory search
|
* Like The Silver Searcher, `ripgrep` defaults to recursive directory search
|
||||||
and won't search files ignored by your `.gitignore` files. It also ignores
|
and won't search files ignored by your `.gitignore` files. It also ignores
|
||||||
hidden and binary files by default. `ripgrep` also implements full support
|
hidden and binary files by default. `ripgrep` also implements full support
|
||||||
@@ -118,7 +118,7 @@ multiline search, then `ripgrep` may not quite meet your needs (yet).
|
|||||||
|
|
||||||
### Is it really faster than everything else?
|
### 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/).
|
[available on my blog](http://blog.burntsushi.net/ripgrep/).
|
||||||
|
|
||||||
Summarizing, `ripgrep` is fast because:
|
Summarizing, `ripgrep` is fast because:
|
||||||
@@ -146,15 +146,19 @@ Summarizing, `ripgrep` is fast because:
|
|||||||
|
|
||||||
The binary name for `ripgrep` is `rg`.
|
The binary name for `ripgrep` is `rg`.
|
||||||
|
|
||||||
[Binaries for `ripgrep` are available for Windows, Mac and
|
**[Archives of precompiled binaries for `ripgrep` are available for Windows,
|
||||||
Linux.](https://github.com/BurntSushi/ripgrep/releases) Linux binaries are
|
macOS and Linux.](https://github.com/BurntSushi/ripgrep/releases)** Users of
|
||||||
static executables. Windows binaries are available either as built with MinGW
|
platforms not explicitly mentioned below (such as Debian and Ubuntu) are advised
|
||||||
(GNU) or with Microsoft Visual C++ (MSVC). When possible, prefer MSVC over GNU,
|
to download one of these archives.
|
||||||
but you'll need to have the
|
|
||||||
[Microsoft VC++ 2015 redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=48145)
|
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.
|
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):
|
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`.)
|
$ # (Or using the attribute name, which is also `ripgrep`.)
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're a **Rust programmer**, `ripgrep` can be installed with `cargo`. Note
|
If you're a **Rust programmer**, `ripgrep` can be installed with `cargo`.
|
||||||
that this requires you to have **Rust 1.12 or newer** installed.
|
* 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
|
$ 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
|
For **PowerShell**, add `. _rg.ps1` to your PowerShell
|
||||||
[profile](https://technet.microsoft.com/en-us/library/bb613488(v=vs.85).aspx)
|
[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
|
(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.
|
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
|
`ripgrep` is written in Rust, so you'll need to grab a
|
||||||
[Rust installation](https://www.rust-lang.org/) in order to compile it.
|
[Rust installation](https://www.rust-lang.org/) in order to compile it.
|
||||||
`ripgrep` compiles with Rust 1.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
|
$ git clone https://github.com/BurntSushi/ripgrep
|
||||||
@@ -449,7 +457,7 @@ Example `$OutputEncoding` settings:
|
|||||||
`$OutputEncoding = [System.Console]::OutputEncoding`
|
`$OutputEncoding = [System.Console]::OutputEncoding`
|
||||||
|
|
||||||
If you continue to have encoding problems, you can also force the encoding
|
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
|
`[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8`. This
|
||||||
will also reset when PowerShell is restarted, so you can add that line
|
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.
|
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].
|
available [here][msys issue explanation].
|
||||||
|
|
||||||
[msys issue explanation]: https://github.com/BurntSushi/ripgrep/issues/281#issuecomment-269093893
|
[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'`
|
||||||
|
@@ -80,7 +80,7 @@ _rg() {
|
|||||||
'*'{-u,--unrestricted}'[reduce level of "smart" searching]'
|
'*'{-u,--unrestricted}'[reduce level of "smart" searching]'
|
||||||
'(: -)'{-V,--version}'[display version information]'
|
'(: -)'{-V,--version}'[display version information]'
|
||||||
'(-p --heading --no-heading --pretty)--vimgrep[show results in vim-compatible format]'
|
'(-p --heading --no-heading --pretty)--vimgrep[show results in vim-compatible format]'
|
||||||
'(-H --no-filename --with-filename)'{-H,--with-filename}'[prefix each match with name of file that contains it]'
|
'(-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]'
|
'(-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'
|
'(-e -f --file --files --regexp --type-list)1: :_rg_pattern'
|
||||||
'(--type-list)*:file:_files'
|
'(--type-list)*:file:_files'
|
||||||
|
9
doc/rg.1
9
doc/rg.1
@@ -274,8 +274,11 @@ Only show path of each file with no matches.
|
|||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
.B \-H, \-\-with\-filename
|
.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.
|
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
|
.RS
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
@@ -445,8 +448,8 @@ rg\ \[aq]^.*([0\-9]{3}\-[0\-9]{3}\-[0\-9]{4}).*$\[aq]\ \-\-replace\ \[aq]$1\[aq]
|
|||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
.B \-s, \-\-case\-sensitive
|
.B \-s, \-\-case\-sensitive
|
||||||
Search case sensitively.
|
Search case sensitively (default).
|
||||||
This overrides \-\-ignore\-case and \-\-smart\-case.
|
Overrides \-\-ignore\-case and \-\-smart\-case.
|
||||||
.RS
|
.RS
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
|
@@ -182,8 +182,10 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
|||||||
: Only show path of each file with no matches.
|
: Only show path of each file with no matches.
|
||||||
|
|
||||||
-H, --with-filename
|
-H, --with-filename
|
||||||
: Prefix each match with the file name that contains it. This is the
|
: Display the file name for matches. This is the default when
|
||||||
default when more than one file is searched.
|
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
|
--no-filename
|
||||||
: Never show the filename for a match. This is the default when
|
: Never show the filename for a match. This is the default when
|
||||||
@@ -293,7 +295,7 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
|||||||
rg '^.*([0-9]{3}-[0-9]{3}-[0-9]{4}).*$' --replace '$1'
|
rg '^.*([0-9]{3}-[0-9]{3}-[0-9]{4}).*$' --replace '$1'
|
||||||
|
|
||||||
-s, --case-sensitive
|
-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
|
-S, --smart-case
|
||||||
: Search case insensitively if the pattern is all lowercase.
|
: Search case insensitively if the pattern is all lowercase.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.2.0" #:version
|
version = "0.2.1" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Cross platform single glob and glob set matching. Glob set matching is the
|
Cross platform single glob and glob set matching. Glob set matching is the
|
||||||
@@ -22,7 +22,7 @@ bench = false
|
|||||||
aho-corasick = "0.6.0"
|
aho-corasick = "0.6.0"
|
||||||
fnv = "1.0"
|
fnv = "1.0"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
memchr = "1"
|
memchr = "2"
|
||||||
regex = "0.2.1"
|
regex = "0.2.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@@ -20,7 +20,7 @@ Add this to your `Cargo.toml`:
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
globset = "0.1"
|
globset = "0.2"
|
||||||
```
|
```
|
||||||
|
|
||||||
and this to your crate root:
|
and this to your crate root:
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep"
|
name = "grep"
|
||||||
version = "0.1.6" #:version
|
version = "0.1.7" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Fast line oriented regex searching as a library.
|
Fast line oriented regex searching as a library.
|
||||||
@@ -14,6 +14,6 @@ license = "Unlicense/MIT"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
memchr = "1"
|
memchr = "2"
|
||||||
regex = "0.2.1"
|
regex = "0.2.1"
|
||||||
regex-syntax = "0.4.0"
|
regex-syntax = "0.4.0"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.2.2" #:version
|
version = "0.3.0" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
A fast library for efficiently matching ignore files such as `.gitignore`
|
A fast library for efficiently matching ignore files such as `.gitignore`
|
||||||
@@ -19,13 +19,14 @@ bench = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
crossbeam = "0.2"
|
crossbeam = "0.2"
|
||||||
globset = { version = "0.2.0", path = "../globset" }
|
globset = { version = "0.2.1", path = "../globset" }
|
||||||
lazy_static = "0.2"
|
lazy_static = "0.2"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
memchr = "1"
|
memchr = "2"
|
||||||
regex = "0.2.1"
|
regex = "0.2.1"
|
||||||
|
same-file = "1"
|
||||||
thread_local = "0.3.2"
|
thread_local = "0.3.2"
|
||||||
walkdir = "1.0.7"
|
walkdir = "2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempdir = "0.3.5"
|
tempdir = "0.3.5"
|
||||||
|
@@ -21,6 +21,7 @@ use std::sync::{Arc, RwLock};
|
|||||||
use gitignore::{self, Gitignore, GitignoreBuilder};
|
use gitignore::{self, Gitignore, GitignoreBuilder};
|
||||||
use pathutil::{is_hidden, strip_prefix};
|
use pathutil::{is_hidden, strip_prefix};
|
||||||
use overrides::{self, Override};
|
use overrides::{self, Override};
|
||||||
|
use same_file::Handle;
|
||||||
use types::{self, Types};
|
use types::{self, Types};
|
||||||
use {Error, Match, PartialErrorBuilder};
|
use {Error, Match, PartialErrorBuilder};
|
||||||
|
|
||||||
@@ -95,6 +96,9 @@ struct IgnoreInner {
|
|||||||
compiled: Arc<RwLock<HashMap<OsString, Ignore>>>,
|
compiled: Arc<RwLock<HashMap<OsString, Ignore>>>,
|
||||||
/// The path to the directory that this matcher was built from.
|
/// The path to the directory that this matcher was built from.
|
||||||
dir: PathBuf,
|
dir: PathBuf,
|
||||||
|
/// An open handle to the directory, for checking symlink loops in the
|
||||||
|
/// parallel iterator.
|
||||||
|
handle: Arc<Option<Handle>>,
|
||||||
/// An override matcher (default is empty).
|
/// An override matcher (default is empty).
|
||||||
overrides: Arc<Override>,
|
overrides: Arc<Override>,
|
||||||
/// A file type matcher.
|
/// A file type matcher.
|
||||||
@@ -127,11 +131,15 @@ struct IgnoreInner {
|
|||||||
|
|
||||||
impl Ignore {
|
impl Ignore {
|
||||||
/// Return the directory path of this matcher.
|
/// Return the directory path of this matcher.
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn path(&self) -> &Path {
|
pub fn path(&self) -> &Path {
|
||||||
&self.0.dir
|
&self.0.dir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a handle to the directory of this matcher.
|
||||||
|
pub fn handle(&self) -> Option<&Handle> {
|
||||||
|
(*self.0.handle).as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
/// Return true if this matcher has no parent.
|
/// Return true if this matcher has no parent.
|
||||||
pub fn is_root(&self) -> bool {
|
pub fn is_root(&self) -> bool {
|
||||||
self.0.parent.is_none()
|
self.0.parent.is_none()
|
||||||
@@ -238,9 +246,17 @@ impl Ignore {
|
|||||||
errs.maybe_push(err);
|
errs.maybe_push(err);
|
||||||
m
|
m
|
||||||
};
|
};
|
||||||
|
let handle = match Handle::from_path(dir) {
|
||||||
|
Ok(handle) => Some(handle),
|
||||||
|
Err(err) => {
|
||||||
|
errs.push(Error::from(err).with_path(dir));
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
let ig = IgnoreInner {
|
let ig = IgnoreInner {
|
||||||
compiled: self.0.compiled.clone(),
|
compiled: self.0.compiled.clone(),
|
||||||
dir: dir.to_path_buf(),
|
dir: dir.to_path_buf(),
|
||||||
|
handle: Arc::new(handle),
|
||||||
overrides: self.0.overrides.clone(),
|
overrides: self.0.overrides.clone(),
|
||||||
types: self.0.types.clone(),
|
types: self.0.types.clone(),
|
||||||
parent: Some(self.clone()),
|
parent: Some(self.clone()),
|
||||||
@@ -451,9 +467,14 @@ impl IgnoreBuilder {
|
|||||||
}
|
}
|
||||||
gi
|
gi
|
||||||
};
|
};
|
||||||
|
let handle = match Handle::from_path(&self.dir) {
|
||||||
|
Ok(handle) => Some(handle),
|
||||||
|
Err(_) => None,
|
||||||
|
};
|
||||||
Ignore(Arc::new(IgnoreInner {
|
Ignore(Arc::new(IgnoreInner {
|
||||||
compiled: Arc::new(RwLock::new(HashMap::new())),
|
compiled: Arc::new(RwLock::new(HashMap::new())),
|
||||||
dir: self.dir.clone(),
|
dir: self.dir.clone(),
|
||||||
|
handle: Arc::new(handle),
|
||||||
overrides: self.overrides.clone(),
|
overrides: self.overrides.clone(),
|
||||||
types: self.types.clone(),
|
types: self.types.clone(),
|
||||||
parent: None,
|
parent: None,
|
||||||
|
@@ -54,6 +54,7 @@ extern crate lazy_static;
|
|||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate memchr;
|
extern crate memchr;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
extern crate same_file;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate tempdir;
|
extern crate tempdir;
|
||||||
extern crate thread_local;
|
extern crate thread_local;
|
||||||
@@ -198,6 +199,29 @@ impl Error {
|
|||||||
}
|
}
|
||||||
errline.with_path(path)
|
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 {
|
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)]
|
#[derive(Debug, Default)]
|
||||||
struct PartialErrorBuilder(Vec<Error>);
|
struct PartialErrorBuilder(Vec<Error>);
|
||||||
|
|
||||||
|
@@ -110,7 +110,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
|||||||
("cmake", &["*.cmake", "CMakeLists.txt"]),
|
("cmake", &["*.cmake", "CMakeLists.txt"]),
|
||||||
("coffeescript", &["*.coffee"]),
|
("coffeescript", &["*.coffee"]),
|
||||||
("creole", &["*.creole"]),
|
("creole", &["*.creole"]),
|
||||||
("config", &["*.config"]),
|
("config", &["*.cfg", "*.conf", "*.config", "*.ini"]),
|
||||||
("cpp", &[
|
("cpp", &[
|
||||||
"*.C", "*.cc", "*.cpp", "*.cxx",
|
"*.C", "*.cc", "*.cpp", "*.cxx",
|
||||||
"*.h", "*.H", "*.hh", "*.hpp", "*.inl",
|
"*.h", "*.H", "*.hh", "*.hpp", "*.inl",
|
||||||
@@ -123,8 +123,10 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
|||||||
("cython", &["*.pyx"]),
|
("cython", &["*.pyx"]),
|
||||||
("dart", &["*.dart"]),
|
("dart", &["*.dart"]),
|
||||||
("d", &["*.d"]),
|
("d", &["*.d"]),
|
||||||
|
("docker", &["*Dockerfile*"]),
|
||||||
("elisp", &["*.el"]),
|
("elisp", &["*.el"]),
|
||||||
("elixir", &["*.ex", "*.eex", "*.exs"]),
|
("elixir", &["*.ex", "*.eex", "*.exs"]),
|
||||||
|
("elm", &["*.elm"]),
|
||||||
("erlang", &["*.erl", "*.hrl"]),
|
("erlang", &["*.erl", "*.hrl"]),
|
||||||
("fish", &["*.fish"]),
|
("fish", &["*.fish"]),
|
||||||
("fortran", &[
|
("fortran", &[
|
||||||
@@ -139,27 +141,60 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
|||||||
("haskell", &["*.hs", "*.lhs"]),
|
("haskell", &["*.hs", "*.lhs"]),
|
||||||
("html", &["*.htm", "*.html", "*.ejs"]),
|
("html", &["*.htm", "*.html", "*.ejs"]),
|
||||||
("java", &["*.java"]),
|
("java", &["*.java"]),
|
||||||
("jinja", &["*.jinja", "*.jinja2"]),
|
("jinja", &["*.j2", "*.jinja", "*.jinja2"]),
|
||||||
("js", &[
|
("js", &[
|
||||||
"*.js", "*.jsx", "*.vue",
|
"*.js", "*.jsx", "*.vue",
|
||||||
]),
|
]),
|
||||||
("json", &["*.json"]),
|
("json", &["*.json", "composer.lock"]),
|
||||||
("jsonl", &["*.jsonl"]),
|
("jsonl", &["*.jsonl"]),
|
||||||
("julia", &["*.jl"]),
|
("julia", &["*.jl"]),
|
||||||
("jl", &["*.jl"]),
|
("jl", &["*.jl"]),
|
||||||
("kotlin", &["*.kt", "*.kts"]),
|
("kotlin", &["*.kt", "*.kts"]),
|
||||||
("less", &["*.less"]),
|
("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"]),
|
("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]),
|
||||||
("log", &["*.log"]),
|
("log", &["*.log"]),
|
||||||
("lua", &["*.lua"]),
|
("lua", &["*.lua"]),
|
||||||
("m4", &["*.ac", "*.m4"]),
|
("m4", &["*.ac", "*.m4"]),
|
||||||
("make", &["gnumakefile", "Gnumakefile", "GNUmakefile", "makefile", "Makefile", "*.mk", "*.mak"]),
|
("make", &[
|
||||||
|
"gnumakefile", "Gnumakefile", "GNUmakefile",
|
||||||
|
"makefile", "Makefile",
|
||||||
|
"*.mk", "*.mak"
|
||||||
|
]),
|
||||||
("markdown", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
|
("markdown", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
|
||||||
("md", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
|
("md", &["*.markdown", "*.md", "*.mdown", "*.mkdn"]),
|
||||||
("matlab", &["*.m"]),
|
("matlab", &["*.m"]),
|
||||||
("mk", &["mkfile"]),
|
("mk", &["mkfile"]),
|
||||||
("ml", &["*.ml"]),
|
("ml", &["*.ml"]),
|
||||||
("msbuild", &["*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets"]),
|
("msbuild", &[
|
||||||
|
"*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets"
|
||||||
|
]),
|
||||||
("nim", &["*.nim"]),
|
("nim", &["*.nim"]),
|
||||||
("nix", &["*.nix"]),
|
("nix", &["*.nix"]),
|
||||||
("objc", &["*.h", "*.m"]),
|
("objc", &["*.h", "*.m"]),
|
||||||
@@ -171,6 +206,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
|||||||
("php", &["*.php", "*.php3", "*.php4", "*.php5", "*.phtml"]),
|
("php", &["*.php", "*.php3", "*.php4", "*.php5", "*.phtml"]),
|
||||||
("pod", &["*.pod"]),
|
("pod", &["*.pod"]),
|
||||||
("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]),
|
("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]),
|
||||||
|
("purs", &["*.purs"]),
|
||||||
("py", &["*.py"]),
|
("py", &["*.py"]),
|
||||||
("qmake", &["*.pro", "*.pri", "*.prf"]),
|
("qmake", &["*.pro", "*.pri", "*.prf"]),
|
||||||
("readme", &["README*", "*README"]),
|
("readme", &["README*", "*README"]),
|
||||||
@@ -181,18 +217,47 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
|||||||
("rust", &["*.rs"]),
|
("rust", &["*.rs"]),
|
||||||
("sass", &["*.sass", "*.scss"]),
|
("sass", &["*.sass", "*.scss"]),
|
||||||
("scala", &["*.scala"]),
|
("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"]),
|
("spark", &["*.spark"]),
|
||||||
|
("sql", &["*.sql", "*.psql"]),
|
||||||
("stylus", &["*.styl"]),
|
("stylus", &["*.styl"]),
|
||||||
("sql", &["*.sql"]),
|
|
||||||
("sv", &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]),
|
("sv", &["*.v", "*.vg", "*.sv", "*.svh", "*.h"]),
|
||||||
("svg", &["*.svg"]),
|
("svg", &["*.svg"]),
|
||||||
("swift", &["*.swift"]),
|
("swift", &["*.swift"]),
|
||||||
("swig", &["*.def", "*.i"]),
|
("swig", &["*.def", "*.i"]),
|
||||||
|
("systemd", &[
|
||||||
|
"*.automount", "*.conf", "*.device", "*.link", "*.mount", "*.path",
|
||||||
|
"*.scope", "*.service", "*.slice", "*.socket", "*.swap", "*.target",
|
||||||
|
"*.timer",
|
||||||
|
]),
|
||||||
("taskpaper", &["*.taskpaper"]),
|
("taskpaper", &["*.taskpaper"]),
|
||||||
("tcl", &["*.tcl"]),
|
("tcl", &["*.tcl"]),
|
||||||
("tex", &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib"]),
|
("tex", &["*.tex", "*.ltx", "*.cls", "*.sty", "*.bib"]),
|
||||||
("textile", &["*.textile"]),
|
("textile", &["*.textile"]),
|
||||||
|
("tf", &["*.tf"]),
|
||||||
("ts", &["*.ts", "*.tsx"]),
|
("ts", &["*.ts", "*.tsx"]),
|
||||||
("txt", &["*.txt"]),
|
("txt", &["*.txt"]),
|
||||||
("toml", &["*.toml", "Cargo.lock"]),
|
("toml", &["*.toml", "Cargo.lock"]),
|
||||||
@@ -202,10 +267,17 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
|||||||
("vim", &["*.vim"]),
|
("vim", &["*.vim"]),
|
||||||
("vimscript", &["*.vim"]),
|
("vimscript", &["*.vim"]),
|
||||||
("wiki", &["*.mediawiki", "*.wiki"]),
|
("wiki", &["*.mediawiki", "*.wiki"]),
|
||||||
("xml", &["*.xml"]),
|
("xml", &["*.xml", "*.xml.dist"]),
|
||||||
("yacc", &["*.y"]),
|
("yacc", &["*.y"]),
|
||||||
("yaml", &["*.yaml", "*.yml"]),
|
("yaml", &["*.yaml", "*.yml", "yarn.lock"]),
|
||||||
("zsh", &["zshenv", ".zshenv", "zprofile", ".zprofile", "zshrc", ".zshrc", "zlogin", ".zlogin", "zlogout", ".zlogout", "*.zsh"]),
|
("zsh", &[
|
||||||
|
".zshenv", "zshenv",
|
||||||
|
".zlogin", "zlogin",
|
||||||
|
".zlogout", "zlogout",
|
||||||
|
".zprofile", "zprofile",
|
||||||
|
".zshrc", "zshrc",
|
||||||
|
"*.zsh",
|
||||||
|
]),
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Glob represents a single glob in a set of file type definitions.
|
/// Glob represents a single glob in a set of file type definitions.
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::ffi::{OsStr, OsString};
|
use std::ffi::OsStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fs::{self, FileType, Metadata};
|
use std::fs::{self, FileType, Metadata};
|
||||||
use std::io;
|
use std::io;
|
||||||
@@ -11,7 +11,8 @@ use std::time::Duration;
|
|||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
use crossbeam::sync::MsQueue;
|
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 dir::{Ignore, IgnoreBuilder};
|
||||||
use gitignore::GitignoreBuilder;
|
use gitignore::GitignoreBuilder;
|
||||||
@@ -36,8 +37,8 @@ impl DirEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this entry corresponds to a symbolic link or not.
|
/// Whether this entry corresponds to a symbolic link or not.
|
||||||
pub fn path_is_symbolic_link(&self) -> bool {
|
pub fn path_is_symlink(&self) -> bool {
|
||||||
self.dent.path_is_symbolic_link()
|
self.dent.path_is_symlink()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if and only if this entry corresponds to stdin.
|
/// 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::*;
|
use self::DirEntryInner::*;
|
||||||
match *self {
|
match *self {
|
||||||
Stdin => false,
|
Stdin => false,
|
||||||
Walkdir(ref x) => x.path_is_symbolic_link(),
|
Walkdir(ref x) => x.path_is_symlink(),
|
||||||
Raw(ref x) => x.path_is_symbolic_link(),
|
Raw(ref x) => x.path_is_symlink(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +200,7 @@ impl DirEntryInner {
|
|||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn ino(&self) -> Option<u64> {
|
fn ino(&self) -> Option<u64> {
|
||||||
|
use walkdir::DirEntryExt;
|
||||||
use self::DirEntryInner::*;
|
use self::DirEntryInner::*;
|
||||||
match *self {
|
match *self {
|
||||||
Stdin => None,
|
Stdin => None,
|
||||||
@@ -244,7 +246,7 @@ impl DirEntryRaw {
|
|||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_is_symbolic_link(&self) -> bool {
|
fn path_is_symlink(&self) -> bool {
|
||||||
self.ty.is_symlink() || self.follow_link
|
self.ty.is_symlink() || self.follow_link
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,7 +406,9 @@ pub struct WalkBuilder {
|
|||||||
max_depth: Option<usize>,
|
max_depth: Option<usize>,
|
||||||
max_filesize: Option<u64>,
|
max_filesize: Option<u64>,
|
||||||
follow_links: bool,
|
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,
|
threads: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,7 +462,9 @@ impl WalkBuilder {
|
|||||||
}
|
}
|
||||||
if let Some(ref cmp) = cmp {
|
if let Some(ref cmp) = cmp {
|
||||||
let cmp = cmp.clone();
|
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)))
|
(p.to_path_buf(), Some(WalkEventIter::from(wd)))
|
||||||
}
|
}
|
||||||
@@ -571,6 +577,29 @@ impl WalkBuilder {
|
|||||||
self
|
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.
|
/// Enables ignoring hidden files.
|
||||||
///
|
///
|
||||||
/// This is enabled by default.
|
/// This is enabled by default.
|
||||||
@@ -610,6 +639,8 @@ impl WalkBuilder {
|
|||||||
/// does not exist or does not specify `core.excludesFile`, then
|
/// does not exist or does not specify `core.excludesFile`, then
|
||||||
/// `$XDG_CONFIG_HOME/git/ignore` is read. If `$XDG_CONFIG_HOME` is not
|
/// `$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.
|
/// 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 {
|
pub fn git_global(&mut self, yes: bool) -> &mut WalkBuilder {
|
||||||
self.ig_builder.git_global(yes);
|
self.ig_builder.git_global(yes);
|
||||||
self
|
self
|
||||||
@@ -637,7 +668,7 @@ impl WalkBuilder {
|
|||||||
self
|
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
|
/// If a compare function is set, the resulting iterator will return all
|
||||||
/// paths in sorted order. The compare function will be called to compare
|
/// paths in sorted order. The compare function will be called to compare
|
||||||
@@ -645,8 +676,9 @@ impl WalkBuilder {
|
|||||||
/// entry.
|
/// entry.
|
||||||
///
|
///
|
||||||
/// Note that this is not used in the parallel iterator.
|
/// Note that this is not used in the parallel iterator.
|
||||||
pub fn sort_by<F>(&mut self, cmp: F) -> &mut WalkBuilder
|
pub fn sort_by_file_name<F>(&mut self, cmp: F) -> &mut WalkBuilder
|
||||||
where F: Fn(&OsString, &OsString) -> cmp::Ordering + 'static {
|
where F: Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static
|
||||||
|
{
|
||||||
self.sorter = Some(Arc::new(cmp));
|
self.sorter = Some(Arc::new(cmp));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -727,7 +759,7 @@ impl Iterator for Walk {
|
|||||||
};
|
};
|
||||||
match ev {
|
match ev {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Some(Err(Error::from(err)));
|
return Some(Err(Error::from_walkdir(err)));
|
||||||
}
|
}
|
||||||
Ok(WalkEvent::Exit) => {
|
Ok(WalkEvent::Exit) => {
|
||||||
self.ig = self.ig.parent().unwrap();
|
self.ig = self.ig.parent().unwrap();
|
||||||
@@ -763,7 +795,7 @@ impl Iterator for Walk {
|
|||||||
/// the entire contents of a directory have been enumerated.
|
/// the entire contents of a directory have been enumerated.
|
||||||
struct WalkEventIter {
|
struct WalkEventIter {
|
||||||
depth: usize,
|
depth: usize,
|
||||||
it: walkdir::Iter,
|
it: walkdir::IntoIter,
|
||||||
next: Option<Result<walkdir::DirEntry, walkdir::Error>>,
|
next: Option<Result<walkdir::DirEntry, walkdir::Error>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1276,11 +1308,11 @@ fn check_symlink_loop(
|
|||||||
child_path: &Path,
|
child_path: &Path,
|
||||||
child_depth: usize,
|
child_depth: usize,
|
||||||
) -> Result<(), Error> {
|
) -> 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()) {
|
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| {
|
if ig.handle().map_or(true, |parent| parent == &hchild) {
|
||||||
Error::from(err).with_path(child_path).with_depth(child_depth)
|
|
||||||
}));
|
|
||||||
if same {
|
|
||||||
return Err(Error::Loop {
|
return Err(Error::Loop {
|
||||||
ancestor: ig.path().to_path_buf(),
|
ancestor: ig.path().to_path_buf(),
|
||||||
child: child_path.to_path_buf(),
|
child: child_path.to_path_buf(),
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
class RipgrepBin < Formula
|
class RipgrepBin < Formula
|
||||||
version '0.5.2'
|
version '0.6.0'
|
||||||
desc "Search tool like grep and The Silver Searcher."
|
desc "Search tool like grep and The Silver Searcher."
|
||||||
homepage "https://github.com/BurntSushi/ripgrep"
|
homepage "https://github.com/BurntSushi/ripgrep"
|
||||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
|
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
|
||||||
sha256 "a0326a84af8517ad707d8c7cccba6e112de27822c391cc0937e4727fbb6c48f4"
|
sha256 "2aeffe25322f886bcd846ac15b6574dc769865fb44b28a9b0c356f3004019685"
|
||||||
|
|
||||||
conflicts_with "ripgrep"
|
conflicts_with "ripgrep"
|
||||||
|
|
||||||
|
10
src/app.rs
10
src/app.rs
@@ -162,7 +162,7 @@ pub fn app() -> App<'static, 'static> {
|
|||||||
.arg(flag("no-ignore-parent"))
|
.arg(flag("no-ignore-parent"))
|
||||||
.arg(flag("no-ignore-vcs"))
|
.arg(flag("no-ignore-vcs"))
|
||||||
.arg(flag("null").short("0"))
|
.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("path-separator").value_name("SEPARATOR").takes_value(true))
|
||||||
.arg(flag("pretty").short("p"))
|
.arg(flag("pretty").short("p"))
|
||||||
.arg(flag("replace").short("r")
|
.arg(flag("replace").short("r")
|
||||||
@@ -398,8 +398,10 @@ lazy_static! {
|
|||||||
"Only show the paths that contains zero matches.");
|
"Only show the paths that contains zero matches.");
|
||||||
doc!(h, "with-filename",
|
doc!(h, "with-filename",
|
||||||
"Show file name for each match.",
|
"Show file name for each match.",
|
||||||
"Prefix each match with the file name that contains it. This is \
|
"Display the file name for matches. This is the default when \
|
||||||
the default when more than one file is searched.");
|
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",
|
doc!(h, "no-filename",
|
||||||
"Never show the file name for a match.",
|
"Never show the file name for a match.",
|
||||||
"Never show the file name for a match. This is the default when \
|
"Never show the file name for a match. This is the default when \
|
||||||
@@ -509,7 +511,7 @@ lazy_static! {
|
|||||||
is 10M. \n\nThe argument accepts the same size suffixes as \
|
is 10M. \n\nThe argument accepts the same size suffixes as \
|
||||||
allowed in the 'max-filesize' argument.");
|
allowed in the 'max-filesize' argument.");
|
||||||
doc!(h, "case-sensitive",
|
doc!(h, "case-sensitive",
|
||||||
"Search case sensitively.",
|
"Search case sensitively (default).",
|
||||||
"Search case sensitively. This overrides -i/--ignore-case and \
|
"Search case sensitively. This overrides -i/--ignore-case and \
|
||||||
-S/--smart-case.");
|
-S/--smart-case.");
|
||||||
doc!(h, "smart-case",
|
doc!(h, "smart-case",
|
||||||
|
@@ -287,7 +287,7 @@ impl Args {
|
|||||||
wd.parents(!self.no_ignore_parent);
|
wd.parents(!self.no_ignore_parent);
|
||||||
wd.threads(self.threads());
|
wd.threads(self.threads());
|
||||||
if self.sort_files {
|
if self.sort_files {
|
||||||
wd.sort_by(|a, b| a.cmp(b));
|
wd.sort_by_file_name(|a, b| a.cmp(b));
|
||||||
}
|
}
|
||||||
wd
|
wd
|
||||||
}
|
}
|
||||||
|
27
src/main.rs
27
src/main.rs
@@ -54,6 +54,7 @@ mod worker;
|
|||||||
pub type Result<T> = result::Result<T, Box<Error + Send + Sync>>;
|
pub type Result<T> = result::Result<T, Box<Error + Send + Sync>>;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
reset_sigpipe();
|
||||||
match Args::parse().map(Arc::new).and_then(run) {
|
match Args::parse().map(Arc::new).and_then(run) {
|
||||||
Ok(0) => process::exit(1),
|
Ok(0) => process::exit(1),
|
||||||
Ok(_) => process::exit(0),
|
Ok(_) => process::exit(0),
|
||||||
@@ -107,6 +108,7 @@ fn run_parallel(args: Arc<Args>) -> Result<u64> {
|
|||||||
let dent = match get_or_log_dir_entry(
|
let dent = match get_or_log_dir_entry(
|
||||||
result,
|
result,
|
||||||
args.stdout_handle(),
|
args.stdout_handle(),
|
||||||
|
args.files(),
|
||||||
args.no_messages(),
|
args.no_messages(),
|
||||||
) {
|
) {
|
||||||
None => return Continue,
|
None => return Continue,
|
||||||
@@ -153,6 +155,7 @@ fn run_one_thread(args: Arc<Args>) -> Result<u64> {
|
|||||||
let dent = match get_or_log_dir_entry(
|
let dent = match get_or_log_dir_entry(
|
||||||
result,
|
result,
|
||||||
args.stdout_handle(),
|
args.stdout_handle(),
|
||||||
|
args.files(),
|
||||||
args.no_messages(),
|
args.no_messages(),
|
||||||
) {
|
) {
|
||||||
None => continue,
|
None => continue,
|
||||||
@@ -205,6 +208,7 @@ fn run_files_parallel(args: Arc<Args>) -> Result<u64> {
|
|||||||
if let Some(dent) = get_or_log_dir_entry(
|
if let Some(dent) = get_or_log_dir_entry(
|
||||||
result,
|
result,
|
||||||
args.stdout_handle(),
|
args.stdout_handle(),
|
||||||
|
args.files(),
|
||||||
args.no_messages(),
|
args.no_messages(),
|
||||||
) {
|
) {
|
||||||
tx.send(dent).unwrap();
|
tx.send(dent).unwrap();
|
||||||
@@ -223,6 +227,7 @@ fn run_files_one_thread(args: Arc<Args>) -> Result<u64> {
|
|||||||
let dent = match get_or_log_dir_entry(
|
let dent = match get_or_log_dir_entry(
|
||||||
result,
|
result,
|
||||||
args.stdout_handle(),
|
args.stdout_handle(),
|
||||||
|
args.files(),
|
||||||
args.no_messages(),
|
args.no_messages(),
|
||||||
) {
|
) {
|
||||||
None => continue,
|
None => continue,
|
||||||
@@ -250,6 +255,7 @@ fn run_types(args: Arc<Args>) -> Result<u64> {
|
|||||||
fn get_or_log_dir_entry(
|
fn get_or_log_dir_entry(
|
||||||
result: result::Result<ignore::DirEntry, ignore::Error>,
|
result: result::Result<ignore::DirEntry, ignore::Error>,
|
||||||
stdout_handle: Option<&same_file::Handle>,
|
stdout_handle: Option<&same_file::Handle>,
|
||||||
|
files_only: bool,
|
||||||
no_messages: bool,
|
no_messages: bool,
|
||||||
) -> Option<ignore::DirEntry> {
|
) -> Option<ignore::DirEntry> {
|
||||||
match result {
|
match result {
|
||||||
@@ -278,7 +284,7 @@ fn get_or_log_dir_entry(
|
|||||||
}
|
}
|
||||||
// If we are redirecting stdout to a file, then don't search that
|
// If we are redirecting stdout to a file, then don't search that
|
||||||
// file.
|
// file.
|
||||||
if is_stdout_file(&dent, stdout_handle, no_messages) {
|
if !files_only && is_stdout_file(&dent, stdout_handle, no_messages) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(dent)
|
Some(dent)
|
||||||
@@ -329,3 +335,22 @@ fn eprint_nothing_searched() {
|
|||||||
applied a filter you didn't expect. \
|
applied a filter you didn't expect. \
|
||||||
Try running again with --debug.");
|
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
|
||||||
|
}
|
||||||
|
100
src/printer.rs
100
src/printer.rs
@@ -3,29 +3,58 @@ use std::fmt;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use regex::bytes::{Captures, Regex, Replacer};
|
use regex::bytes::{Captures, Match, Regex, Replacer};
|
||||||
use termcolor::{Color, ColorSpec, ParseColorError, WriteColor};
|
use termcolor::{Color, ColorSpec, ParseColorError, WriteColor};
|
||||||
|
|
||||||
use pathutil::strip_prefix;
|
use pathutil::strip_prefix;
|
||||||
use ignore::types::FileTypeDef;
|
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,
|
/// CountingReplacer implements the Replacer interface for Regex,
|
||||||
/// and counts how often replacement is being performed.
|
/// and counts how often replacement is being performed.
|
||||||
struct CountingReplacer<'r> {
|
struct CountingReplacer<'r> {
|
||||||
replace: &'r [u8],
|
replace: &'r [u8],
|
||||||
count: &'r mut usize,
|
count: &'r mut usize,
|
||||||
|
offsets: &'r mut Vec<Offset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> CountingReplacer<'r> {
|
impl<'r> CountingReplacer<'r> {
|
||||||
fn new(replace: &'r [u8], count: &'r mut usize) -> CountingReplacer<'r> {
|
fn new(
|
||||||
CountingReplacer { replace: replace, count: count }
|
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> {
|
impl<'r> Replacer for CountingReplacer<'r> {
|
||||||
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
|
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
|
||||||
*self.count += 1;
|
*self.count += 1;
|
||||||
|
let start = dst.len();
|
||||||
caps.expand(self.replace, dst);
|
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() {
|
if self.replace.is_some() {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
let mut offsets = Vec::new();
|
||||||
let line = {
|
let line = {
|
||||||
let replacer = CountingReplacer::new(
|
let replacer = CountingReplacer::new(
|
||||||
self.replace.as_ref().unwrap(), &mut count);
|
self.replace.as_ref().unwrap(), &mut count, &mut offsets);
|
||||||
re.replace_all(&buf[start..end], replacer)
|
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) {
|
if self.max_columns.map_or(false, |m| line.len() > m) {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
@@ -295,44 +330,45 @@ impl<W: WriteColor> Printer<W> {
|
|||||||
self.write_eol();
|
self.write_eol();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.write(&line);
|
self.write_matched_line(offsets, &*line, false);
|
||||||
if line.last() != Some(&self.eol) {
|
|
||||||
self.write_eol();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if self.only_matching {
|
let buf = if self.only_matching {
|
||||||
let buf = &buf[start + match_start..start + match_end];
|
&buf[start + match_start..start + match_end]
|
||||||
self.write_matched_line(re, buf, true);
|
|
||||||
} else {
|
} 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(
|
fn write_matched_line<I>(&mut self, offsets: I, buf: &[u8], only_match: bool)
|
||||||
&mut self,
|
where I: IntoIterator<Item=Offset>,
|
||||||
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;
|
|
||||||
}
|
|
||||||
if !self.wtr.supports_color() || self.colors.matched().is_none() {
|
if !self.wtr.supports_color() || self.colors.matched().is_none() {
|
||||||
self.write(buf);
|
self.write(buf);
|
||||||
} else if only_match {
|
} else if only_match {
|
||||||
self.write_colored(buf, |colors| colors.matched());
|
self.write_colored(buf, |colors| colors.matched());
|
||||||
} else {
|
} else {
|
||||||
let mut last_written = 0;
|
let mut last_written = 0;
|
||||||
for m in re.find_iter(buf) {
|
for o in offsets {
|
||||||
self.write(&buf[last_written..m.start()]);
|
self.write(&buf[last_written..o.start]);
|
||||||
self.write_colored(
|
// This conditional checks if the match is both empty *and*
|
||||||
&buf[m.start()..m.end()], |colors| colors.matched());
|
// past the end of the line. In this case, we never want to
|
||||||
last_written = m.end();
|
// 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..]);
|
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)
|
fn write_colored<F>(&mut self, buf: &[u8], get_color: F)
|
||||||
where F: Fn(&ColorSpecs) -> &ColorSpec
|
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);
|
self.write(buf);
|
||||||
let _ = self.wtr.reset();
|
let _ = self.wtr.reset();
|
||||||
}
|
}
|
||||||
|
@@ -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.match_count > 0 {
|
||||||
if self.opts.count {
|
if self.opts.count {
|
||||||
self.printer.path_count(self.path, self.match_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]
|
#[test]
|
||||||
fn after_context_two1() {
|
fn after_context_two1() {
|
||||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
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]
|
#[test]
|
||||||
fn after_context_three1() {
|
fn after_context_three1() {
|
||||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "0.3.2" #:version
|
version = "0.3.3" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
A simple cross platform library for writing colored text to a terminal.
|
A simple cross platform library for writing colored text to a terminal.
|
||||||
|
@@ -202,15 +202,23 @@ enum IoStandardStream {
|
|||||||
impl IoStandardStream {
|
impl IoStandardStream {
|
||||||
fn new(sty: StandardStreamType) -> IoStandardStream {
|
fn new(sty: StandardStreamType) -> IoStandardStream {
|
||||||
match sty {
|
match sty {
|
||||||
StandardStreamType::Stdout => IoStandardStream::Stdout(io::stdout()),
|
StandardStreamType::Stdout => {
|
||||||
StandardStreamType::Stderr => IoStandardStream::Stderr(io::stderr()),
|
IoStandardStream::Stdout(io::stdout())
|
||||||
|
}
|
||||||
|
StandardStreamType::Stderr => {
|
||||||
|
IoStandardStream::Stderr(io::stderr())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lock(&self) -> IoStandardStreamLock {
|
fn lock(&self) -> IoStandardStreamLock {
|
||||||
match *self {
|
match *self {
|
||||||
IoStandardStream::Stdout(ref s) => IoStandardStreamLock::StdoutLock(s.lock()),
|
IoStandardStream::Stdout(ref s) => {
|
||||||
IoStandardStream::Stderr(ref s) => IoStandardStreamLock::StderrLock(s.lock()),
|
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> {
|
enum IoStandardStreamLock<'a> {
|
||||||
StdoutLock(io::StdoutLock<'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
|
/// Satisfies `io::Write` and `WriteColor`, and supports optional coloring
|
||||||
/// to either of the standard output streams, stdout and stderr.
|
/// to either of the standard output streams, stdout and stderr.
|
||||||
pub struct StandardStream {
|
pub struct StandardStream {
|
||||||
wtr: LossyStandardStream<WriterInner<'static, IoStandardStream>>,
|
wtr: LossyStandardStream<WriterInner<IoStandardStream>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `StandardStreamLock` is a locked reference to a `StandardStream`.
|
/// `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
|
/// This implements the `io::Write` and `WriteColor` traits, and is constructed
|
||||||
/// via the `Write::lock` method.
|
/// 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> {
|
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
|
/// WriterInner is a (limited) generic representation of a writer. It is
|
||||||
/// limited because W should only ever be stdout/stderr on Windows.
|
/// 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>),
|
NoColor(NoColor<W>),
|
||||||
Ansi(Ansi<W>),
|
Ansi(Ansi<W>),
|
||||||
/// What a gross hack. On Windows, we need to specify a lifetime for the
|
/// 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
|
/// 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.
|
/// a PhantomData.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Unreachable(::std::marker::PhantomData<&'a ()>),
|
Unreachable(::std::marker::PhantomData<&'a ()>),
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
Windows { wtr: W, console: Mutex<wincolor::Console> },
|
Windows { wtr: W, console: MutexGuard<'a, wincolor::Console> },
|
||||||
#[cfg(windows)]
|
|
||||||
WindowsLocked { wtr: W, console: MutexGuard<'a, wincolor::Console> },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StandardStream {
|
impl StandardStream {
|
||||||
@@ -332,7 +348,9 @@ impl StandardStream {
|
|||||||
} else {
|
} else {
|
||||||
WriterInner::NoColor(NoColor(IoStandardStream::new(sty)))
|
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
|
/// Create a new `StandardStream` with the given color preferences that
|
||||||
@@ -375,12 +393,11 @@ impl<'a> StandardStreamLock<'a> {
|
|||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
fn from_stream(stream: &StandardStream) -> StandardStreamLock {
|
fn from_stream(stream: &StandardStream) -> StandardStreamLock {
|
||||||
let locked = match *stream.wtr.get_ref() {
|
let locked = match *stream.wtr.get_ref() {
|
||||||
WriterInner::Unreachable(_) => unreachable!(),
|
|
||||||
WriterInner::NoColor(ref w) => {
|
WriterInner::NoColor(ref w) => {
|
||||||
WriterInner::NoColor(NoColor(w.0.lock()))
|
WriterInnerLock::NoColor(NoColor(w.0.lock()))
|
||||||
}
|
}
|
||||||
WriterInner::Ansi(ref w) => {
|
WriterInner::Ansi(ref w) => {
|
||||||
WriterInner::Ansi(Ansi(w.0.lock()))
|
WriterInnerLock::Ansi(Ansi(w.0.lock()))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
StandardStreamLock { wtr: stream.wtr.wrap(locked) }
|
StandardStreamLock { wtr: stream.wtr.wrap(locked) }
|
||||||
@@ -389,24 +406,19 @@ impl<'a> StandardStreamLock<'a> {
|
|||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn from_stream(stream: &StandardStream) -> StandardStreamLock {
|
fn from_stream(stream: &StandardStream) -> StandardStreamLock {
|
||||||
let locked = match *stream.wtr.get_ref() {
|
let locked = match *stream.wtr.get_ref() {
|
||||||
WriterInner::Unreachable(_) => unreachable!(),
|
|
||||||
WriterInner::NoColor(ref w) => {
|
WriterInner::NoColor(ref w) => {
|
||||||
WriterInner::NoColor(NoColor(w.0.lock()))
|
WriterInnerLock::NoColor(NoColor(w.0.lock()))
|
||||||
}
|
}
|
||||||
WriterInner::Ansi(ref w) => {
|
WriterInner::Ansi(ref w) => {
|
||||||
WriterInner::Ansi(Ansi(w.0.lock()))
|
WriterInnerLock::Ansi(Ansi(w.0.lock()))
|
||||||
}
|
}
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
WriterInner::Windows { ref wtr, ref console } => {
|
WriterInner::Windows { ref wtr, ref console } => {
|
||||||
WriterInner::WindowsLocked {
|
WriterInnerLock::Windows {
|
||||||
wtr: wtr.lock(),
|
wtr: wtr.lock(),
|
||||||
console: console.lock().unwrap(),
|
console: console.lock().unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(windows)]
|
|
||||||
WriterInner::WindowsLocked{..} => {
|
|
||||||
panic!("cannot call StandardStream.lock while a StandardStreamLock is alive");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
StandardStreamLock { wtr: stream.wtr.wrap(locked) }
|
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() }
|
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> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
match *self {
|
match *self {
|
||||||
WriterInner::Unreachable(_) => unreachable!(),
|
|
||||||
WriterInner::NoColor(ref mut wtr) => wtr.write(buf),
|
WriterInner::NoColor(ref mut wtr) => wtr.write(buf),
|
||||||
WriterInner::Ansi(ref mut wtr) => wtr.write(buf),
|
WriterInner::Ansi(ref mut wtr) => wtr.write(buf),
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
WriterInner::Windows { ref mut wtr, .. } => wtr.write(buf),
|
WriterInner::Windows { ref mut wtr, .. } => wtr.write(buf),
|
||||||
#[cfg(windows)]
|
|
||||||
WriterInner::WindowsLocked { ref mut wtr, .. } => wtr.write(buf),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
match *self {
|
match *self {
|
||||||
WriterInner::Unreachable(_) => unreachable!(),
|
|
||||||
WriterInner::NoColor(ref mut wtr) => wtr.flush(),
|
WriterInner::NoColor(ref mut wtr) => wtr.flush(),
|
||||||
WriterInner::Ansi(ref mut wtr) => wtr.flush(),
|
WriterInner::Ansi(ref mut wtr) => wtr.flush(),
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
WriterInner::Windows { ref mut wtr, .. } => wtr.flush(),
|
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 {
|
fn supports_color(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
WriterInner::Unreachable(_) => unreachable!(),
|
|
||||||
WriterInner::NoColor(_) => false,
|
WriterInner::NoColor(_) => false,
|
||||||
WriterInner::Ansi(_) => true,
|
WriterInner::Ansi(_) => true,
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
WriterInner::Windows { .. } => true,
|
WriterInner::Windows { .. } => true,
|
||||||
#[cfg(windows)]
|
|
||||||
WriterInner::WindowsLocked { .. } => true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
|
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
|
||||||
match *self {
|
match *self {
|
||||||
WriterInner::Unreachable(_) => unreachable!(),
|
|
||||||
WriterInner::NoColor(ref mut wtr) => wtr.set_color(spec),
|
WriterInner::NoColor(ref mut wtr) => wtr.set_color(spec),
|
||||||
WriterInner::Ansi(ref mut wtr) => wtr.set_color(spec),
|
WriterInner::Ansi(ref mut wtr) => wtr.set_color(spec),
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@@ -488,17 +490,11 @@ impl<'a, W: io::Write> WriteColor for WriterInner<'a, W> {
|
|||||||
let mut console = console.lock().unwrap();
|
let mut console = console.lock().unwrap();
|
||||||
spec.write_console(&mut *console)
|
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<()> {
|
fn reset(&mut self) -> io::Result<()> {
|
||||||
match *self {
|
match *self {
|
||||||
WriterInner::Unreachable(_) => unreachable!(),
|
|
||||||
WriterInner::NoColor(ref mut wtr) => wtr.reset(),
|
WriterInner::NoColor(ref mut wtr) => wtr.reset(),
|
||||||
WriterInner::Ansi(ref mut wtr) => wtr.reset(),
|
WriterInner::Ansi(ref mut wtr) => wtr.reset(),
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@@ -507,8 +503,63 @@ impl<'a, W: io::Write> WriteColor for WriterInner<'a, W> {
|
|||||||
try!(console.lock().unwrap().reset());
|
try!(console.lock().unwrap().reset());
|
||||||
Ok(())
|
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)]
|
#[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!(wtr.flush());
|
||||||
try!(console.reset());
|
try!(console.reset());
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -565,7 +616,8 @@ impl BufferWriter {
|
|||||||
StandardStreamType::Stdout => wincolor::Console::stdout(),
|
StandardStreamType::Stdout => wincolor::Console::stdout(),
|
||||||
StandardStreamType::Stderr => wincolor::Console::stderr(),
|
StandardStreamType::Stderr => wincolor::Console::stderr(),
|
||||||
}.ok().map(Mutex::new);
|
}.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 {
|
BufferWriter {
|
||||||
stream: stream,
|
stream: stream,
|
||||||
printed: AtomicBool::new(false),
|
printed: AtomicBool::new(false),
|
||||||
@@ -1253,7 +1305,9 @@ struct LossyStandardStream<W> {
|
|||||||
|
|
||||||
impl<W: io::Write> LossyStandardStream<W> {
|
impl<W: io::Write> LossyStandardStream<W> {
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
fn new(wtr: W) -> LossyStandardStream<W> { LossyStandardStream { wtr: wtr } }
|
fn new(wtr: W) -> LossyStandardStream<W> {
|
||||||
|
LossyStandardStream { wtr: wtr }
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn new(wtr: W) -> LossyStandardStream<W> {
|
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()]),
|
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>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -266,6 +266,20 @@ but Watson, Doctor has to have it taken out for him and dusted,
|
|||||||
assert_eq!(lines, expected);
|
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| {
|
sherlock!(file_types, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||||
wd.create("file.py", "Sherlock");
|
wd.create("file.py", "Sherlock");
|
||||||
wd.create("file.rs", "Sherlock");
|
wd.create("file.rs", "Sherlock");
|
||||||
@@ -1014,12 +1028,15 @@ fn regression_210() {
|
|||||||
let badutf8 = OsStr::from_bytes(&b"foo\xffbar"[..]);
|
let badutf8 = OsStr::from_bytes(&b"foo\xffbar"[..]);
|
||||||
|
|
||||||
let wd = WorkDir::new("regression_210");
|
let wd = WorkDir::new("regression_210");
|
||||||
let mut cmd = wd.command();
|
// APFS does not support creating files with invalid UTF-8 bytes.
|
||||||
wd.create(badutf8, "test");
|
// https://github.com/BurntSushi/ripgrep/issues/559
|
||||||
cmd.arg("-H").arg("test").arg(badutf8);
|
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);
|
let out = wd.output(&mut cmd);
|
||||||
assert_eq!(out.stdout, b"foo\xffbar:test\n".to_vec());
|
assert_eq!(out.stdout, b"foo\xffbar:test\n".to_vec());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// See: https://github.com/BurntSushi/ripgrep/issues/228
|
// See: https://github.com/BurntSushi/ripgrep/issues/228
|
||||||
@@ -1129,6 +1146,29 @@ clean!(regression_493, " 're ", "input.txt", |wd: WorkDir, mut cmd: Command| {
|
|||||||
assert_eq!(lines, " 're \n");
|
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
|
// See: https://github.com/BurntSushi/ripgrep/issues/1
|
||||||
clean!(feature_1_sjis, "Шерлок Холмс", ".", |wd: WorkDir, mut cmd: Command| {
|
clean!(feature_1_sjis, "Шерлок Холмс", ".", |wd: WorkDir, mut cmd: Command| {
|
||||||
let sherlock =
|
let sherlock =
|
||||||
|
@@ -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) {
|
pub fn create<P: AsRef<Path>>(&self, name: P, contents: &str) {
|
||||||
self.create_bytes(name, contents.as_bytes());
|
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.
|
/// Create a new file with the given name and size.
|
||||||
pub fn create_size<P: AsRef<Path>>(&self, name: P, filesize: u64) {
|
pub fn create_size<P: AsRef<Path>>(&self, name: P, filesize: u64) {
|
||||||
let path = self.dir.join(name);
|
let path = self.dir.join(name);
|
||||||
@@ -53,12 +61,19 @@ impl WorkDir {
|
|||||||
nice_err(&path, file.set_len(filesize));
|
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]) {
|
pub fn create_bytes<P: AsRef<Path>>(&self, name: P, contents: &[u8]) {
|
||||||
let path = self.dir.join(name);
|
let path = self.dir.join(name);
|
||||||
let mut file = nice_err(&path, File::create(&path));
|
nice_err(&path, self.try_create_bytes(&path, contents));
|
||||||
nice_err(&path, file.write_all(contents));
|
}
|
||||||
nice_err(&path, file.flush());
|
|
||||||
|
/// 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.
|
/// Remove a file with the given name from this directory.
|
||||||
|
Reference in New Issue
Block a user