mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-07-27 02:01:58 -07:00
Compare commits
115 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
263e2b012f | ||
|
b80a986721 | ||
|
8a91d3132f | ||
|
525d051172 | ||
|
5a9883d27c | ||
|
f462d092e7 | ||
|
fe84928c85 | ||
|
f7eaf67fc3 | ||
|
c1c92e4fee | ||
|
5644bbe43a | ||
|
aeb3a5ba0f | ||
|
24e14a0341 | ||
|
2a2b1506d4 | ||
|
4d6b3c727e | ||
|
c2bf9e3d45 | ||
|
dad73b92eb | ||
|
b0d8ff6f4a | ||
|
0263a401f6 | ||
|
4cb1b9ccc0 | ||
|
6f80e2e126 | ||
|
f9bff90842 | ||
|
5af4ec0056 | ||
|
9e2f10b893 | ||
|
69095cf5c3 | ||
|
7402db7b43 | ||
|
7698b60256 | ||
|
e7fb0fd267 | ||
|
29b59074c7 | ||
|
ee5eb2d659 | ||
|
bf8094344a | ||
|
a0819978aa | ||
|
5b7c17e2fb | ||
|
bf56b3bb8e | ||
|
9299d84d41 | ||
|
2cf1a08969 | ||
|
665b6016e3 | ||
|
33231622f3 | ||
|
919c5c7299 | ||
|
f9bf1e4a22 | ||
|
f7ee914dd3 | ||
|
0a63158a61 | ||
|
6cb604f38f | ||
|
bfbbfbf979 | ||
|
403ba5fdc8 | ||
|
8f87a4e8ac | ||
|
d27d3e675f | ||
|
bf5d873099 | ||
|
bc9d12c4c8 | ||
|
5a0c873f61 | ||
|
65fec147d6 | ||
|
7fbf2f014c | ||
|
d22a3ca3e5 | ||
|
e9ec52b7f9 | ||
|
0d14c74e63 | ||
|
1c5884b2f9 | ||
|
8203a80ac7 | ||
|
0e46171e3b | ||
|
f5c85827ce | ||
|
7cefc55238 | ||
|
92c918ebd9 | ||
|
c24f8fd50f | ||
|
73272cf8a6 | ||
|
4212a8b9cb | ||
|
983c7fd6f9 | ||
|
7cd02e9b7e | ||
|
5fdfae2f15 | ||
|
7057ee91de | ||
|
fdca74148d | ||
|
f11d9fb922 | ||
|
1115c23a4c | ||
|
8c5eaa40b2 | ||
|
3c05954c86 | ||
|
cf3a33cea7 | ||
|
8aa2ba3eb1 | ||
|
466cd70a8e | ||
|
954fbeb1d8 | ||
|
68fa50709e | ||
|
ab91e4b874 | ||
|
2b943eda47 | ||
|
37544c092f | ||
|
9bf7696ec8 | ||
|
cb0f8fd2fa | ||
|
fa8112ec34 | ||
|
cf21b4a97e | ||
|
19615245cd | ||
|
98a48b44bc | ||
|
e3da726836 | ||
|
5b36c86c15 | ||
|
76331e5fec | ||
|
1e678d7052 | ||
|
dd986d7fe9 | ||
|
f83cd63b11 | ||
|
9a4527d107 | ||
|
8f0d3d78ca | ||
|
3f7cd977bc | ||
|
cc6b6dcf5b | ||
|
48878bbb8f | ||
|
0766617e07 | ||
|
afd99c43d7 | ||
|
96e87ab738 | ||
|
a744ec133d | ||
|
0042dce949 | ||
|
ca058d7584 | ||
|
af3b56a623 | ||
|
5938bed339 | ||
|
feff1849c8 | ||
|
9948e0ca07 | ||
|
fd3e5069b6 | ||
|
0891b4a3c0 | ||
|
af48aaa647 | ||
|
ee7f300ae2 | ||
|
a4d8db16f7 | ||
|
3bb387abdd | ||
|
7f0273c347 | ||
|
5b42999a3d |
12
.gitignore
vendored
12
.gitignore
vendored
@@ -1,14 +1,4 @@
|
||||
.*.swp
|
||||
tags
|
||||
target
|
||||
*.lock
|
||||
tmp
|
||||
*.csv
|
||||
*.fst
|
||||
*-got
|
||||
*.csv.idx
|
||||
words
|
||||
98m*
|
||||
dict
|
||||
test
|
||||
months
|
||||
/grep/Cargo.lock
|
||||
|
51
.travis.yml
51
.travis.yml
@@ -1,37 +1,46 @@
|
||||
#language: rust
|
||||
#rust:
|
||||
# - stable
|
||||
# - beta
|
||||
# - nightly
|
||||
#script:
|
||||
# - cargo build --verbose
|
||||
# - cargo doc
|
||||
# - cargo test --verbose
|
||||
# - if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
|
||||
# cargo bench --verbose;
|
||||
# fi
|
||||
|
||||
language: rust
|
||||
cache: cargo
|
||||
|
||||
env:
|
||||
global:
|
||||
- PROJECT_NAME=xrep
|
||||
- PROJECT_NAME=ripgrep
|
||||
matrix:
|
||||
include:
|
||||
# Nightly channel
|
||||
- os: osx
|
||||
rust: nightly
|
||||
env: TARGET=i686-apple-darwin
|
||||
- os: osx
|
||||
rust: nightly
|
||||
env: TARGET=x86_64-apple-darwin
|
||||
# Nightly channel.
|
||||
# (All *nix releases are done on the nightly channel to take advantage
|
||||
# of the regex library's multiple pattern SIMD search.)
|
||||
- os: linux
|
||||
rust: nightly
|
||||
env: TARGET=i686-unknown-linux-musl
|
||||
- os: linux
|
||||
rust: nightly
|
||||
env: TARGET=x86_64-unknown-linux-musl
|
||||
- os: osx
|
||||
rust: nightly
|
||||
env: TARGET=i686-apple-darwin
|
||||
- os: osx
|
||||
rust: nightly
|
||||
env: TARGET=x86_64-apple-darwin
|
||||
# Beta channel.
|
||||
- os: linux
|
||||
rust: beta
|
||||
env: TARGET=x86_64-unknown-linux-musl
|
||||
- os: linux
|
||||
rust: beta
|
||||
env: TARGET=x86_64-unknown-linux-gnu
|
||||
- os: osx
|
||||
rust: beta
|
||||
env: TARGET=x86_64-apple-darwin
|
||||
# Minimum Rust supported channel.
|
||||
- os: linux
|
||||
rust: 1.9.0
|
||||
env: TARGET=x86_64-unknown-linux-musl
|
||||
- os: linux
|
||||
rust: 1.9.0
|
||||
env: TARGET=x86_64-unknown-linux-gnu
|
||||
- os: osx
|
||||
rust: 1.9.0
|
||||
env: TARGET=x86_64-apple-darwin
|
||||
|
||||
before_install:
|
||||
- export PATH="$PATH:$HOME/.cargo/bin"
|
||||
|
261
Cargo.lock
generated
Normal file
261
Cargo.lock
generated
Normal file
@@ -0,0 +1,261 @@
|
||||
[root]
|
||||
name = "ripgrep"
|
||||
version = "0.1.13"
|
||||
dependencies = [
|
||||
"deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"docopt 0.6.83 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"grep 0.1.2",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deque"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "docopt"
|
||||
version = "0.6.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "fs2"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "grep"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memmap"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fs2 0.2.5 (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.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.1.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.3.5 (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.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "simd"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread-id"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
|
||||
"checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf"
|
||||
"checksum docopt 0.6.83 (registry+https://github.com/rust-lang/crates.io-index)" = "fc42c6077823a361410c37d47c2535b73a190cbe10838dc4f400fe87c10c8c3b"
|
||||
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
|
||||
"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
|
||||
"checksum fs2 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bcd414e5a1a979b931bb92f41b7a54106d3f6d2e6c253e9ce943b7cd468251ef"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
|
||||
"checksum libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "408014cace30ee0f767b1c4517980646a573ec61a57957aeeabcac8ac0a02e8d"
|
||||
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
|
||||
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
|
||||
"checksum memmap 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f20f72ed93291a72e22e8b16bb18762183bb4943f0f483da5b8be1a9e8192752"
|
||||
"checksum num_cpus 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8890e6084723d57d0df8d2720b0d60c6ee67d6c93e7169630e4371e88765dcad"
|
||||
"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
|
||||
"checksum regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)" = "64b03446c466d35b42f2a8b203c8e03ed8b91c0f17b56e1f84f7210a257aa665"
|
||||
"checksum regex-syntax 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279401017ae31cf4e15344aa3f085d0e2e5c1e70067289ef906906fdbe92c8fd"
|
||||
"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
|
||||
"checksum simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63b5847c2d766ca7ce7227672850955802fabd779ba616aeabead4c2c3877023"
|
||||
"checksum strsim 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "50c069df92e4b01425a8bf3576d5d417943a6a7272fbabaf5bd80b1aaa76442e"
|
||||
"checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a"
|
||||
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
|
||||
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
|
||||
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
|
||||
"checksum walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780"
|
||||
"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"
|
29
Cargo.toml
29
Cargo.toml
@@ -1,14 +1,14 @@
|
||||
[package]
|
||||
publish = false
|
||||
name = "xrep"
|
||||
version = "0.1.0" #:version
|
||||
name = "ripgrep"
|
||||
version = "0.1.13" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
Line oriented search tool using Rust's regex library.
|
||||
Line oriented search tool using Rust's regex library. Combines the raw
|
||||
performance of grep with the usability of the silver searcher.
|
||||
"""
|
||||
documentation = "https://github.com/BurntSushi/xrep"
|
||||
homepage = "https://github.com/BurntSushi/xrep"
|
||||
repository = "https://github.com/BurntSushi/xrep"
|
||||
documentation = "https://github.com/BurntSushi/ripgrep"
|
||||
homepage = "https://github.com/BurntSushi/ripgrep"
|
||||
repository = "https://github.com/BurntSushi/ripgrep"
|
||||
readme = "README.md"
|
||||
keywords = ["regex", "grep", "egrep", "search", "pattern"]
|
||||
license = "Unlicense/MIT"
|
||||
@@ -16,24 +16,27 @@ license = "Unlicense/MIT"
|
||||
[[bin]]
|
||||
bench = false
|
||||
path = "src/main.rs"
|
||||
name = "xrep"
|
||||
name = "rg"
|
||||
|
||||
[[test]]
|
||||
name = "integration"
|
||||
path = "tests/tests.rs"
|
||||
|
||||
[dependencies]
|
||||
crossbeam = "0.2"
|
||||
deque = "0.3"
|
||||
docopt = "0.6"
|
||||
env_logger = "0.3"
|
||||
grep = { version = "0.1", path = "grep" }
|
||||
fnv = "1.0"
|
||||
grep = { version = "0.1.2", path = "grep" }
|
||||
lazy_static = "0.2"
|
||||
libc = "0.2"
|
||||
log = "0.3"
|
||||
memchr = "0.1"
|
||||
memmap = "0.2"
|
||||
num_cpus = "1"
|
||||
regex = "0.1.75"
|
||||
regex-syntax = "0.3.5"
|
||||
regex = "0.1.77"
|
||||
rustc-serialize = "0.3"
|
||||
term = "0.4"
|
||||
thread_local = "0.2"
|
||||
walkdir = "0.1"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
|
14
Makefile
14
Makefile
@@ -1,14 +0,0 @@
|
||||
all:
|
||||
echo Nothing to do...
|
||||
|
||||
ctags:
|
||||
ctags --options=ctags.rust --languages=Rust src/*.rs src/*/*.rs
|
||||
|
||||
docs:
|
||||
cargo doc
|
||||
in-dir ./target/doc fix-perms
|
||||
rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/
|
||||
|
||||
push:
|
||||
git push origin master
|
||||
git push github master
|
258
README-NEW.md
Normal file
258
README-NEW.md
Normal file
@@ -0,0 +1,258 @@
|
||||
ripgrep (rg)
|
||||
------------
|
||||
`ripgrep` is a command line search tool that combines the usability of The
|
||||
Silver Searcher (an `ack` clone) with the raw speed of GNU grep. `ripgrep` has
|
||||
first class support on Windows, Mac and Linux, with binary downloads available
|
||||
for [every release](https://github.com/BurntSushi/ripgrep/releases).
|
||||
|
||||
[](https://travis-ci.org/BurntSushi/ripgrep)
|
||||
[](https://ci.appveyor.com/project/BurntSushi/ripgrep)
|
||||
[](https://crates.io/crates/ripgrep)
|
||||
|
||||
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
||||
|
||||
### Screenshot of search results
|
||||
|
||||
[](http://burntsushi.net/stuff/ripgrep1.png)
|
||||
|
||||
### Quick example comparing tools
|
||||
|
||||
This example searches the entire Linux kernel source tree (after running
|
||||
`make defconfig && make -j8`) for `[A-Z]+_SUSPEND`, where all matches must be
|
||||
words. Timings were collected on a system with an Intel i7-6900K 3.2 GHz.
|
||||
|
||||
Please remember that a single benchmark is never enough! See my
|
||||
[blog post on `ripgrep`](http://blog.burntsushi.net/ripgrep/)
|
||||
for a very detailed comparison with more benchmarks and analysis.
|
||||
|
||||
| Tool | Command | Line count | Time |
|
||||
| ---- | ------- | ---------- | ---- |
|
||||
| ripgrep | `rg -n -w '[A-Z]+_SUSPEND'` | 450 | **0.245s** |
|
||||
| [The Silver Searcher](https://github.com/ggreer/the_silver_searcher) | `ag -w '[A-Z]+_SUSPEND'` | 450 | 0.753s |
|
||||
| [git grep](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `LC_ALL=C git grep -E -n -w '[A-Z]+_SUSPEND'` | 450 | 0.823s |
|
||||
| [git grep](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `LC_ALL=en_US.UTF-8 git grep -E -n -w '[A-Z]+_SUSPEND'` | 450 | 2.880s |
|
||||
| [sift](https://github.com/svent/sift) | `sift --git -n -w '[A-Z]+_SUSPEND'` | 450 | 3.656s |
|
||||
| [The Platinum Searcher](https://github.com/monochromegane/the_platinum_searcher) | `pt -w -e '[A-Z]+_SUSPEND'` | 450 | 12.369s |
|
||||
| [ack](http://beyondgrep.com/) | `ack -w '[A-Z]+_SUSPEND'` | 1878 | 16.952s |
|
||||
|
||||
(Yes, `ack` [has](https://github.com/petdance/ack2/issues/445) a
|
||||
[bug](https://github.com/petdance/ack2/issues/14).)
|
||||
|
||||
### Why should I use `ripgrep`?
|
||||
|
||||
* It can replace both The Silver Searcher and GNU grep because it is faster
|
||||
than both. (N.B. It is not, strictly speaking, a "drop-in" replacement for
|
||||
both, but the feature sets are far more similar than different.)
|
||||
* Like The Silver Searcher, `ripgrep` defaults to recursive directory search
|
||||
and won't search files ignored by your `.gitignore` files. It also ignores
|
||||
hidden and binary files by default. `ripgrep` also implements full support
|
||||
for `.gitignore`, where as there are many bugs related to that functionality
|
||||
in The Silver Searcher.
|
||||
* `ripgrep` can search specific types of files. For example, `rg -tpy foo`
|
||||
limits your search to Python files and `rg -Tjs foo` excludes Javascript
|
||||
files from your search. `ripgrep` can be taught about new file types with
|
||||
custom matching rules.
|
||||
* `ripgrep` supports many features found in `grep`, such as showing the context
|
||||
of search results, searching multiple patterns, highlighting matches with
|
||||
color and full Unicode support. Unlike GNU grep, `ripgrep` stays fast while
|
||||
supporting Unicode (which is always on).
|
||||
|
||||
In other words, use `ripgrep` if you like speed, sane defaults, fewer bugs and
|
||||
Unicode.
|
||||
|
||||
### Is it really faster than everything else?
|
||||
|
||||
Yes. A large number of benchmarks with detailed analysis for each is
|
||||
[available on my blog](http://blog.burntsushi.net/ripgrep/).
|
||||
|
||||
Summarizing, `ripgrep` is fast because:
|
||||
|
||||
* It is built on top of
|
||||
[Rust's regex engine](https://github.com/rust-lang-nursery/regex).
|
||||
Rust's regex engine uses finite automata, SIMD and aggressive literal
|
||||
optimizations to make searching very fast.
|
||||
* Rust's regex library maintains performance with full Unicode support by
|
||||
building UTF-8 decoding directly into its deterministic finite automaton
|
||||
engine.
|
||||
* It supports searching with either memory maps or by searching incrementally
|
||||
with an intermediate buffer. The former is better for single files and the
|
||||
latter is better for large directories. `ripgrep` chooses the best searching
|
||||
strategy for you automatically.
|
||||
* Applies your ignore patterns in `.gitignore` files using a
|
||||
[`RegexSet`](https://doc.rust-lang.org/regex/regex/struct.RegexSet.html).
|
||||
That means a single file path can be matched against multiple glob patterns
|
||||
simultaneously.
|
||||
* Uses a Chase-Lev work-stealing queue for quickly distributing work to
|
||||
multiple threads.
|
||||
|
||||
### Installation
|
||||
|
||||
The binary name for `ripgrep` is `rg`.
|
||||
|
||||
[Binaries for `ripgrep` are available for Windows, Mac and
|
||||
Linux.](https://github.com/BurntSushi/ripgrep/releases) Linux binaries are
|
||||
static executables. Windows binaries are available either as built with MinGW
|
||||
(GNU) or with Microsoft Visual C++ (MSVC). When possible, prefer MSVC over GNU,
|
||||
but you'll need to have the
|
||||
[Microsoft Visual C++ Build
|
||||
Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools)
|
||||
installed.
|
||||
|
||||
If you're a **Homebrew** user, then you can install it with a custom formula
|
||||
(N.B. `ripgrep` isn't actually in Homebrew yet. This just installs the binary
|
||||
directly):
|
||||
|
||||
```
|
||||
$ brew install https://raw.githubusercontent.com/BurntSushi/ripgrep/master/pkg/brew/ripgrep.rb
|
||||
```
|
||||
|
||||
If you're an **Archlinux** user, then you can install `ripgrep` from the
|
||||
[`ripgrep` AUR package](https://aur.archlinux.org/packages/ripgrep/), e.g.,
|
||||
|
||||
```
|
||||
$ yaourt -S ripgrep
|
||||
```
|
||||
|
||||
If you're a **Rust programmer**, `ripgrep` can be installed with `cargo`:
|
||||
|
||||
```
|
||||
$ cargo install ripgrep
|
||||
```
|
||||
|
||||
`ripgrep` isn't currently in any other package repositories.
|
||||
[I'd like to change that](https://github.com/BurntSushi/ripgrep/issues/10).
|
||||
|
||||
### Whirlwind tour
|
||||
|
||||
The command line usage of `ripgrep` doesn't differ much from other tools that
|
||||
perform a similar function, so you probably already know how to use `ripgrep`.
|
||||
The full details can be found in `rg --help`, but let's go on a whirlwind tour.
|
||||
|
||||
`ripgrep` detects when its printing to a terminal, and will automatically
|
||||
colorize your output and show line numbers, just like The Silver Searcher.
|
||||
Coloring works on Windows too! Colors can be controlled more granularly with
|
||||
the `--color` flag.
|
||||
|
||||
One last thing before we get started: `ripgrep` assumes UTF-8 *everywhere*. It
|
||||
can still search files that are invalid UTF-8 (like, say, latin-1), but it will
|
||||
simply not work on UTF-16 encoded files or other more exotic encodings.
|
||||
[Support for other encodings may
|
||||
happen.](https://github.com/BurntSushi/ripgrep/issues/1)
|
||||
|
||||
To recursively search the current directory, while respecting all `.gitignore`
|
||||
files, ignore hidden files and directories and skip binary files:
|
||||
|
||||
```
|
||||
$ rg foobar
|
||||
```
|
||||
|
||||
The above command also respects all `.rgignore` files, including in parent
|
||||
directories. `.rgignore` files can be used when `.gitignore` files are
|
||||
insufficient. In all cases, `.rgignore` patterns take precedence over
|
||||
`.gitignore`.
|
||||
|
||||
To ignore all ignore files, use `-u`. To additionally search hidden files
|
||||
and directories, use `-uu`. To additionally search binary files, use `-uuu`.
|
||||
(In other words, "search everything, dammit!") In particular, `rg -uuu` is
|
||||
equivalent to `grep -a -r`.
|
||||
|
||||
```
|
||||
$ rg -uu foobar # equivalent to `grep -r`
|
||||
$ rg -uuu foobar # equivalent to `grep -a -r`
|
||||
```
|
||||
|
||||
(Tip: If your ignore files aren't being adhered to like you expect, run your
|
||||
search with the `--debug` flag.)
|
||||
|
||||
Make the search case insensitive with `-i`, invert the search with `-v` or
|
||||
show the 2 lines before and after every search result with `-C2`.
|
||||
|
||||
Force all matches to be surrounded by word boundaries with `-w`.
|
||||
|
||||
Search and replace (find first and last names and swap them):
|
||||
|
||||
```
|
||||
$ rg '([A-Z][a-z]+)\s+([A-Z][a-z]+)' --replace '$2, $1'
|
||||
```
|
||||
|
||||
Named groups are supported:
|
||||
|
||||
```
|
||||
$ rg '(?P<first>[A-Z][a-z]+)\s+(?P<last>[A-Z][a-z]+)' --replace '$last, $first'
|
||||
```
|
||||
|
||||
Up the ante with full Unicode support, by matching any uppercase Unicode letter
|
||||
followed by any sequence of lowercase Unicode letters (good luck doing this
|
||||
with other search tools!):
|
||||
|
||||
```
|
||||
$ rg '(\p{Lu}\p{Ll}+)\s+(\p{Lu}\p{Ll}+)' --replace '$2, $1'
|
||||
```
|
||||
|
||||
Search only files matching a particular glob:
|
||||
|
||||
```
|
||||
$ rg foo -g 'README.*'
|
||||
```
|
||||
|
||||
<!--*-->
|
||||
|
||||
Or exclude files matching a particular glob:
|
||||
|
||||
```
|
||||
$ rg foo -g '!*.min.js'
|
||||
```
|
||||
|
||||
Search only HTML and CSS files:
|
||||
|
||||
```
|
||||
$ rg -thtml -tcss foobar
|
||||
```
|
||||
|
||||
Search everything except for Javascript files:
|
||||
|
||||
```
|
||||
$ rg -Tjs foobar
|
||||
```
|
||||
|
||||
To see a list of types supported, run `rg --type-list`. To add a new type, use
|
||||
`--type-add`:
|
||||
|
||||
```
|
||||
$ rg --type-add 'foo:*.foo,*.foobar'
|
||||
```
|
||||
|
||||
The type `foo` will now match any file ending with the `.foo` or `.foobar`
|
||||
extensions.
|
||||
|
||||
### Building
|
||||
|
||||
`ripgrep` is written in Rust, so you'll need to grab a
|
||||
[Rust installation](https://www.rust-lang.org/) in order to compile it.
|
||||
`ripgrep` compiles with Rust 1.9 (stable) or newer. Building is easy:
|
||||
|
||||
```
|
||||
$ git clone git://github.com/BurntSushi/ripgrep
|
||||
$ cd ripgrep
|
||||
$ cargo build --release
|
||||
$ ./target/release/rg --version
|
||||
0.1.3
|
||||
```
|
||||
|
||||
If you have a Rust nightly compiler, then you can enable optional SIMD
|
||||
acceleration like so:
|
||||
|
||||
```
|
||||
RUSTFLAGS="-C target-cpu=native" cargo build --release --features simd-accel
|
||||
```
|
||||
|
||||
### Running tests
|
||||
|
||||
`ripgrep` is relatively well tested, including both unit tests and integration
|
||||
tests. To run the full test suite, use:
|
||||
|
||||
```
|
||||
$ cargo test
|
||||
```
|
||||
|
||||
from the repository root.
|
11
README.md
11
README.md
@@ -1,5 +1,6 @@
|
||||
rep
|
||||
---
|
||||
A faster `grep`, written in Rust using the
|
||||
[`regex`](https://github.com/rust-lang-nursery/regex)
|
||||
crate.
|
||||
**UNDER DEVELOPMENT.**
|
||||
|
||||
ripgrep (rg)
|
||||
------------
|
||||
ripgrep combines the usability of the silver searcher with the raw speed of
|
||||
grep.
|
||||
|
34
appveyor.yml
34
appveyor.yml
@@ -1,28 +1,23 @@
|
||||
environment:
|
||||
global:
|
||||
PROJECT_NAME: xrep
|
||||
PROJECT_NAME: ripgrep
|
||||
matrix:
|
||||
# Nightly channel
|
||||
- TARGET: i686-pc-windows-gnu
|
||||
CHANNEL: nightly
|
||||
CHANNEL: stable
|
||||
- TARGET: i686-pc-windows-msvc
|
||||
CHANNEL: nightly
|
||||
CHANNEL: stable
|
||||
- TARGET: x86_64-pc-windows-gnu
|
||||
CHANNEL: nightly
|
||||
CHANNEL: stable
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
CHANNEL: nightly
|
||||
CHANNEL: stable
|
||||
|
||||
# Install Rust and Cargo
|
||||
# (Based on from https://github.com/rust-lang/libc/blob/master/appveyor.yml)
|
||||
install:
|
||||
- ps: Start-FileDownload "https://static.rust-lang.org/dist/channel-rust-stable"
|
||||
- ps: $env:RUST_VERSION = Get-Content channel-rust-stable | select -first 1 | %{$_.split('-')[1]}
|
||||
- if NOT "%CHANNEL%" == "stable" set RUST_VERSION=%CHANNEL%
|
||||
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:RUST_VERSION}-${env:TARGET}.exe"
|
||||
- rust-%RUST_VERSION%-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
|
||||
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
|
||||
- if "%TARGET%" == "i686-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw32\bin
|
||||
- if "%TARGET%" == "x86_64-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw64\bin
|
||||
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
|
||||
- rustup-init.exe -y --default-host %TARGET%
|
||||
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
||||
- if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin
|
||||
- rustc -V
|
||||
- cargo -V
|
||||
|
||||
@@ -32,15 +27,14 @@ build: false
|
||||
# Equivalent to Travis' `script` phase
|
||||
# TODO modify this phase as you see fit
|
||||
test_script:
|
||||
- cargo build --verbose
|
||||
- cargo test
|
||||
- cargo test --verbose
|
||||
|
||||
before_deploy:
|
||||
# Generate artifacts for release
|
||||
- RUSTFLAGS="-C target-feature=+ssse3" cargo build --release --features simd-accel
|
||||
# TODO(burntsushi): How can we enable SSSE3 on Windows?
|
||||
- cargo build --release
|
||||
- mkdir staging
|
||||
# TODO update this part to copy the artifacts that make sense for your project
|
||||
- copy target\release\xrep.exe staging
|
||||
- copy target\release\rg.exe staging
|
||||
- cd staging
|
||||
# release zipfile will look like 'rust-everywhere-v1.2.3-x86_64-pc-windows-msvc'
|
||||
- 7z a ../%PROJECT_NAME%-%APPVEYOR_REPO_TAG_NAME%-%TARGET%.zip *
|
||||
@@ -58,7 +52,7 @@ deploy:
|
||||
# channel to use to produce the release artifacts
|
||||
# NOTE make sure you only release *once* per target
|
||||
# TODO you may want to pick a different channel
|
||||
CHANNEL: nightly
|
||||
CHANNEL: stable
|
||||
appveyor_repo_tag: true
|
||||
|
||||
branches:
|
||||
|
5
benches/README.md
Normal file
5
benches/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
These are internal microbenchmarks for tracking the peformance of individual
|
||||
components inside of ripgrep. At the moment, they aren't heavily used.
|
||||
|
||||
For performance benchmarks of ripgrep proper, see the sibling `benchsuite`
|
||||
directory.
|
@@ -1,3 +1,7 @@
|
||||
/*!
|
||||
This module benchmarks the glob implementation. For benchmarks on the ripgrep
|
||||
tool itself, see the benchsuite directory.
|
||||
*/
|
||||
#![feature(test)]
|
||||
|
||||
extern crate glob;
|
||||
|
1303
benchsuite/benchsuite
Executable file
1303
benchsuite/benchsuite
Executable file
File diff suppressed because it is too large
Load Diff
343
benchsuite/raw.csv
Normal file
343
benchsuite/raw.csv
Normal file
@@ -0,0 +1,343 @@
|
||||
benchmark,warmup_iter,iter,name,command,duration,lines,env
|
||||
linux_alternates,1,3,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.24781584739685059,68,
|
||||
linux_alternates,1,3,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.23398137092590332,68,
|
||||
linux_alternates,1,3,rg,rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.23497819900512695,68,
|
||||
linux_alternates,1,3,rg-novcs,rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.11090731620788574,68,
|
||||
linux_alternates,1,3,rg-novcs,rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.14237189292907715,68,
|
||||
linux_alternates,1,3,rg-novcs,rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.11315393447875977,68,
|
||||
linux_alternates,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.39145565032958984,68,
|
||||
linux_alternates,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.39217114448547363,68,
|
||||
linux_alternates,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.39917516708374023,68,
|
||||
linux_alternates,1,3,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.4898416996002197,68,
|
||||
linux_alternates,1,3,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5078432559967041,68,
|
||||
linux_alternates,1,3,ag,ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.4942047595977783,68,
|
||||
linux_alternates,1,3,ag-novcs,ag --skip-vcs-ignores -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.4839494228363037,68,
|
||||
linux_alternates,1,3,ag-novcs,ag --skip-vcs-ignores -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.4806060791015625,68,
|
||||
linux_alternates,1,3,ag-novcs,ag --skip-vcs-ignores -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.6986649036407471,68,
|
||||
linux_alternates,1,3,ucg,ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.1494297981262207,68,
|
||||
linux_alternates,1,3,ucg,ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.15127253532409668,68,
|
||||
linux_alternates,1,3,ucg,ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.1573657989501953,68,
|
||||
linux_alternates,1,3,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.25092005729675293,68,LC_ALL=C
|
||||
linux_alternates,1,3,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.2663850784301758,68,LC_ALL=C
|
||||
linux_alternates,1,3,git grep,git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.24485993385314941,68,LC_ALL=C
|
||||
linux_alternates_casei,1,3,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.24762463569641113,160,
|
||||
linux_alternates_casei,1,3,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.21982502937316895,160,
|
||||
linux_alternates_casei,1,3,rg,rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.2219092845916748,160,
|
||||
linux_alternates_casei,1,3,rg-novcs,rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.12809348106384277,160,
|
||||
linux_alternates_casei,1,3,rg-novcs,rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.12208032608032227,160,
|
||||
linux_alternates_casei,1,3,rg-novcs,rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.12648415565490723,160,
|
||||
linux_alternates_casei,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.39945435523986816,160,
|
||||
linux_alternates_casei,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.39914917945861816,160,
|
||||
linux_alternates_casei,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.3931403160095215,160,
|
||||
linux_alternates_casei,1,3,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.26180100440979,160,
|
||||
linux_alternates_casei,1,3,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.6076450347900391,160,
|
||||
linux_alternates_casei,1,3,ag,ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.6092875003814697,160,
|
||||
linux_alternates_casei,1,3,ag-novcs,ag --skip-vcs-ignores -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5668354034423828,160,
|
||||
linux_alternates_casei,1,3,ag-novcs,ag --skip-vcs-ignores -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5638954639434814,160,
|
||||
linux_alternates_casei,1,3,ag-novcs,ag --skip-vcs-ignores -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.6463086605072021,160,
|
||||
linux_alternates_casei,1,3,ucg,ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.23877739906311035,160,
|
||||
linux_alternates_casei,1,3,ucg,ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.2357316017150879,160,
|
||||
linux_alternates_casei,1,3,ucg,ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.23951983451843262,160,
|
||||
linux_alternates_casei,1,3,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.8604335784912109,160,LC_ALL=C
|
||||
linux_alternates_casei,1,3,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.9313437938690186,160,LC_ALL=C
|
||||
linux_alternates_casei,1,3,git grep,git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.9674036502838135,160,LC_ALL=C
|
||||
linux_literal,1,3,rg,rg -n PM_RESUME,0.2203836441040039,16,
|
||||
linux_literal,1,3,rg,rg -n PM_RESUME,0.21490192413330078,16,
|
||||
linux_literal,1,3,rg,rg -n PM_RESUME,0.21895813941955566,16,
|
||||
linux_literal,1,3,rg-novcs,rg --no-ignore -n PM_RESUME,0.10370588302612305,16,
|
||||
linux_literal,1,3,rg-novcs,rg --no-ignore -n PM_RESUME,0.12161660194396973,16,
|
||||
linux_literal,1,3,rg-novcs,rg --no-ignore -n PM_RESUME,0.10118246078491211,16,
|
||||
linux_literal,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n PM_RESUME,0.3846700191497803,16,
|
||||
linux_literal,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n PM_RESUME,0.3972609043121338,16,
|
||||
linux_literal,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n PM_RESUME,0.3864939212799072,16,
|
||||
linux_literal,1,3,ag,ag -s PM_RESUME,0.5170495510101318,16,
|
||||
linux_literal,1,3,ag,ag -s PM_RESUME,0.5066406726837158,16,
|
||||
linux_literal,1,3,ag,ag -s PM_RESUME,0.5110535621643066,16,
|
||||
linux_literal,1,3,ag-novcs,ag --skip-vcs-ignores -s PM_RESUME,0.5622231960296631,16,
|
||||
linux_literal,1,3,ag-novcs,ag --skip-vcs-ignores -s PM_RESUME,0.7810573577880859,16,
|
||||
linux_literal,1,3,ag-novcs,ag --skip-vcs-ignores -s PM_RESUME,1.2847375869750977,16,
|
||||
linux_literal,1,3,ucg,ucg --nosmart-case PM_RESUME,0.16497445106506348,16,
|
||||
linux_literal,1,3,ucg,ucg --nosmart-case PM_RESUME,0.16525840759277344,16,
|
||||
linux_literal,1,3,ucg,ucg --nosmart-case PM_RESUME,0.1590101718902588,16,
|
||||
linux_literal,1,3,git grep,git grep -I -n PM_RESUME,0.1928420066833496,16,LC_ALL=C
|
||||
linux_literal,1,3,git grep,git grep -I -n PM_RESUME,0.19345307350158691,16,LC_ALL=C
|
||||
linux_literal,1,3,git grep,git grep -I -n PM_RESUME,0.1954176425933838,16,LC_ALL=C
|
||||
linux_literal,1,3,pt,pt PM_RESUME,0.20350170135498047,16,
|
||||
linux_literal,1,3,pt,pt PM_RESUME,0.17547011375427246,16,
|
||||
linux_literal,1,3,pt,pt PM_RESUME,0.21206402778625488,16,
|
||||
linux_literal,1,3,sift,sift -n --binary-skip --exclude-files .* PM_RESUME,0.14285612106323242,16,
|
||||
linux_literal,1,3,sift,sift -n --binary-skip --exclude-files .* PM_RESUME,0.14221596717834473,16,
|
||||
linux_literal,1,3,sift,sift -n --binary-skip --exclude-files .* PM_RESUME,0.1395282745361328,16,
|
||||
linux_literal_casei,1,3,rg,rg -n -i PM_RESUME,0.32401490211486816,370,
|
||||
linux_literal_casei,1,3,rg,rg -n -i PM_RESUME,0.26114439964294434,370,
|
||||
linux_literal_casei,1,3,rg,rg -n -i PM_RESUME,0.21575093269348145,370,
|
||||
linux_literal_casei,1,3,rg-novcs,rg --no-ignore -n -i PM_RESUME,0.13971185684204102,399,
|
||||
linux_literal_casei,1,3,rg-novcs,rg --no-ignore -n -i PM_RESUME,0.11648797988891602,399,
|
||||
linux_literal_casei,1,3,rg-novcs,rg --no-ignore -n -i PM_RESUME,0.11060571670532227,399,
|
||||
linux_literal_casei,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n -i PM_RESUME,0.41420912742614746,399,
|
||||
linux_literal_casei,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n -i PM_RESUME,0.3933844566345215,399,
|
||||
linux_literal_casei,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n -i PM_RESUME,0.4015076160430908,399,
|
||||
linux_literal_casei,1,3,ag,ag -i PM_RESUME,0.45723628997802734,370,
|
||||
linux_literal_casei,1,3,ag,ag -i PM_RESUME,0.41663575172424316,370,
|
||||
linux_literal_casei,1,3,ag,ag -i PM_RESUME,0.4088137149810791,370,
|
||||
linux_literal_casei,1,3,ag-novcs,ag --skip-vcs-ignores -i PM_RESUME,0.44587063789367676,399,
|
||||
linux_literal_casei,1,3,ag-novcs,ag --skip-vcs-ignores -i PM_RESUME,0.45557403564453125,399,
|
||||
linux_literal_casei,1,3,ag-novcs,ag --skip-vcs-ignores -i PM_RESUME,0.41840505599975586,399,
|
||||
linux_literal_casei,1,3,ucg,ucg -i PM_RESUME,0.1598954200744629,370,
|
||||
linux_literal_casei,1,3,ucg,ucg -i PM_RESUME,0.15562868118286133,370,
|
||||
linux_literal_casei,1,3,ucg,ucg -i PM_RESUME,0.15644288063049316,370,
|
||||
linux_literal_casei,1,3,git grep,git grep -I -n -i PM_RESUME,0.1857764720916748,370,LC_ALL=C
|
||||
linux_literal_casei,1,3,git grep,git grep -I -n -i PM_RESUME,0.17730069160461426,370,LC_ALL=C
|
||||
linux_literal_casei,1,3,git grep,git grep -I -n -i PM_RESUME,0.18560075759887695,370,LC_ALL=C
|
||||
linux_literal_casei,1,3,sift,sift -n --binary-skip --exclude-files .* -i PM_RESUME,0.20816397666931152,399,
|
||||
linux_literal_casei,1,3,sift,sift -n --binary-skip --exclude-files .* -i PM_RESUME,0.1995244026184082,399,
|
||||
linux_literal_casei,1,3,sift,sift -n --binary-skip --exclude-files .* -i PM_RESUME,0.2000412940979004,399,
|
||||
linux_literal_default,1,3,rg,rg PM_RESUME,0.21781229972839355,16,
|
||||
linux_literal_default,1,3,rg,rg PM_RESUME,0.2195730209350586,16,
|
||||
linux_literal_default,1,3,rg,rg PM_RESUME,0.259692907333374,16,
|
||||
linux_literal_default,1,3,ag,ag PM_RESUME,0.39571118354797363,16,
|
||||
linux_literal_default,1,3,ag,ag PM_RESUME,0.48991870880126953,16,
|
||||
linux_literal_default,1,3,ag,ag PM_RESUME,0.49497532844543457,16,
|
||||
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.166459321975708,16,
|
||||
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.1644885540008545,16,
|
||||
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.16440844535827637,16,
|
||||
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.1860334873199463,16,LC_ALL=C
|
||||
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.16703486442565918,16,LC_ALL=C
|
||||
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.20740580558776855,16,LC_ALL=C
|
||||
linux_literal_default,1,3,pt,pt PM_RESUME,0.15500974655151367,16,
|
||||
linux_literal_default,1,3,pt,pt PM_RESUME,0.15694642066955566,16,
|
||||
linux_literal_default,1,3,pt,pt PM_RESUME,0.15679144859313965,16,
|
||||
linux_literal_default,1,3,sift,sift PM_RESUME,0.11694097518920898,16,
|
||||
linux_literal_default,1,3,sift,sift PM_RESUME,0.11726593971252441,16,
|
||||
linux_literal_default,1,3,sift,sift PM_RESUME,0.11739015579223633,16,
|
||||
linux_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.3873450756072998,490,
|
||||
linux_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.38909482955932617,490,
|
||||
linux_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.4019286632537842,490,
|
||||
linux_no_literal,1,3,rg-whitelist,rg -tall --no-ignore -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.32698678970336914,419,
|
||||
linux_no_literal,1,3,rg-whitelist,rg -tall --no-ignore -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.3220486640930176,419,
|
||||
linux_no_literal,1,3,rg-whitelist,rg -tall --no-ignore -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.32451391220092773,419,
|
||||
linux_no_literal,1,3,rg (no Unicode),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.2920851707458496,490,
|
||||
linux_no_literal,1,3,rg (no Unicode),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.3335237503051758,490,
|
||||
linux_no_literal,1,3,rg (no Unicode),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.28688979148864746,490,
|
||||
linux_no_literal,1,3,rg-whitelist (no Unicode),rg -tall --no-ignore -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.222395658493042,419,
|
||||
linux_no_literal,1,3,rg-whitelist (no Unicode),rg -tall --no-ignore -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.22271037101745605,419,
|
||||
linux_no_literal,1,3,rg-whitelist (no Unicode),rg -tall --no-ignore -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.23732328414916992,419,
|
||||
linux_no_literal,1,3,ag (no Unicode),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.7565908432006836,766,
|
||||
linux_no_literal,1,3,ag (no Unicode),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.9270203113555908,766,
|
||||
linux_no_literal,1,3,ag (no Unicode),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.7432494163513184,766,
|
||||
linux_no_literal,1,3,ag-novcs (no Unicode),ag --skip-vcs-ignores -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.6899797916412354,767,
|
||||
linux_no_literal,1,3,ag-novcs (no Unicode),ag --skip-vcs-ignores -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.7057938575744629,767,
|
||||
linux_no_literal,1,3,ag-novcs (no Unicode),ag --skip-vcs-ignores -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.7126791477203369,767,
|
||||
linux_no_literal,1,3,ucg (no Unicode),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.44383835792541504,416,
|
||||
linux_no_literal,1,3,ucg (no Unicode),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.4448375701904297,416,
|
||||
linux_no_literal,1,3,ucg (no Unicode),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.4412264823913574,416,
|
||||
linux_no_literal,1,3,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},9.985018730163574,490,LC_ALL=en_US.UTF-8
|
||||
linux_no_literal,1,3,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},9.671714782714844,490,LC_ALL=en_US.UTF-8
|
||||
linux_no_literal,1,3,git grep,git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},9.0708589553833,490,LC_ALL=en_US.UTF-8
|
||||
linux_no_literal,1,3,git grep (no Unicode),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.9452569484710693,490,LC_ALL=C
|
||||
linux_no_literal,1,3,git grep (no Unicode),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},2.3153109550476074,490,LC_ALL=C
|
||||
linux_no_literal,1,3,git grep (no Unicode),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.876504898071289,490,LC_ALL=C
|
||||
linux_no_literal,1,3,sift (no Unicode),sift -n --binary-skip --exclude-files .* \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},8.800794124603271,491,
|
||||
linux_no_literal,1,3,sift (no Unicode),sift -n --binary-skip --exclude-files .* \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},8.91090989112854,491,
|
||||
linux_no_literal,1,3,sift (no Unicode),sift -n --binary-skip --exclude-files .* \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},8.970277547836304,491,
|
||||
linux_re_literal_suffix,1,3,rg,rg -n [A-Z]+_RESUME,0.21518707275390625,1652,
|
||||
linux_re_literal_suffix,1,3,rg,rg -n [A-Z]+_RESUME,0.2159252166748047,1652,
|
||||
linux_re_literal_suffix,1,3,rg,rg -n [A-Z]+_RESUME,0.2178945541381836,1652,
|
||||
linux_re_literal_suffix,1,3,rg-novcs,rg --no-ignore -n [A-Z]+_RESUME,0.10395693778991699,1653,
|
||||
linux_re_literal_suffix,1,3,rg-novcs,rg --no-ignore -n [A-Z]+_RESUME,0.101318359375,1653,
|
||||
linux_re_literal_suffix,1,3,rg-novcs,rg --no-ignore -n [A-Z]+_RESUME,0.09963226318359375,1653,
|
||||
linux_re_literal_suffix,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n [A-Z]+_RESUME,0.40993452072143555,1653,
|
||||
linux_re_literal_suffix,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n [A-Z]+_RESUME,0.4102144241333008,1653,
|
||||
linux_re_literal_suffix,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n [A-Z]+_RESUME,0.3837263584136963,1653,
|
||||
linux_re_literal_suffix,1,3,ag,ag -s [A-Z]+_RESUME,1.7373137474060059,1652,
|
||||
linux_re_literal_suffix,1,3,ag,ag -s [A-Z]+_RESUME,1.7011380195617676,1652,
|
||||
linux_re_literal_suffix,1,3,ag,ag -s [A-Z]+_RESUME,0.7572276592254639,1652,
|
||||
linux_re_literal_suffix,1,3,ag-novcs,ag --skip-vcs-ignores -s [A-Z]+_RESUME,0.5061535835266113,1653,
|
||||
linux_re_literal_suffix,1,3,ag-novcs,ag --skip-vcs-ignores -s [A-Z]+_RESUME,0.5377681255340576,1653,
|
||||
linux_re_literal_suffix,1,3,ag-novcs,ag --skip-vcs-ignores -s [A-Z]+_RESUME,0.5237703323364258,1653,
|
||||
linux_re_literal_suffix,1,3,ucg,ucg --nosmart-case [A-Z]+_RESUME,0.13993382453918457,1630,
|
||||
linux_re_literal_suffix,1,3,ucg,ucg --nosmart-case [A-Z]+_RESUME,0.14264798164367676,1630,
|
||||
linux_re_literal_suffix,1,3,ucg,ucg --nosmart-case [A-Z]+_RESUME,0.1370248794555664,1630,
|
||||
linux_re_literal_suffix,1,3,git grep,git grep -E -I -n [A-Z]+_RESUME,0.5916049480438232,1652,LC_ALL=C
|
||||
linux_re_literal_suffix,1,3,git grep,git grep -E -I -n [A-Z]+_RESUME,0.5460302829742432,1652,LC_ALL=C
|
||||
linux_re_literal_suffix,1,3,git grep,git grep -E -I -n [A-Z]+_RESUME,0.5453126430511475,1652,LC_ALL=C
|
||||
linux_re_literal_suffix,1,3,sift,sift -n --binary-skip --exclude-files .* [A-Z]+_RESUME,4.272618055343628,1653,
|
||||
linux_re_literal_suffix,1,3,sift,sift -n --binary-skip --exclude-files .* [A-Z]+_RESUME,3.953784704208374,1653,
|
||||
linux_re_literal_suffix,1,3,sift,sift -n --binary-skip --exclude-files .* [A-Z]+_RESUME,4.050055742263794,1653,
|
||||
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.2921295166015625,23,
|
||||
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.2845008373260498,23,
|
||||
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.295884370803833,23,
|
||||
linux_unicode_greek,1,3,sift,sift -n --binary-skip --exclude-files .* --exclude-files *.pdf \p{Greek},2.8051228523254395,23,
|
||||
linux_unicode_greek,1,3,sift,sift -n --binary-skip --exclude-files .* --exclude-files *.pdf \p{Greek},2.824496269226074,23,
|
||||
linux_unicode_greek,1,3,sift,sift -n --binary-skip --exclude-files .* --exclude-files *.pdf \p{Greek},2.8370847702026367,23,
|
||||
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.2810385227203369,103,
|
||||
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.3430476188659668,103,
|
||||
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.34683680534362793,103,
|
||||
linux_unicode_greek_casei,1,3,sift,sift -n --binary-skip --exclude-files .* --exclude-files *.pdf \p{Greek},2.8701119422912598,23,
|
||||
linux_unicode_greek_casei,1,3,sift,sift -n --binary-skip --exclude-files .* --exclude-files *.pdf \p{Greek},2.9307808876037598,23,
|
||||
linux_unicode_greek_casei,1,3,sift,sift -n --binary-skip --exclude-files .* --exclude-files *.pdf \p{Greek},2.9754345417022705,23,
|
||||
linux_unicode_word,1,3,rg,rg -n \wAh,0.21484971046447754,186,
|
||||
linux_unicode_word,1,3,rg,rg -n \wAh,0.2730236053466797,186,
|
||||
linux_unicode_word,1,3,rg,rg -n \wAh,0.21688318252563477,186,
|
||||
linux_unicode_word,1,3,rg (no Unicode),rg -n (?-u)\wAh,0.23591041564941406,174,
|
||||
linux_unicode_word,1,3,rg (no Unicode),rg -n (?-u)\wAh,0.23375535011291504,174,
|
||||
linux_unicode_word,1,3,rg (no Unicode),rg -n (?-u)\wAh,0.23137831687927246,174,
|
||||
linux_unicode_word,1,3,rg-novcs,rg --no-ignore -n \wAh,0.11421418190002441,186,
|
||||
linux_unicode_word,1,3,rg-novcs,rg --no-ignore -n \wAh,0.11203289031982422,186,
|
||||
linux_unicode_word,1,3,rg-novcs,rg --no-ignore -n \wAh,0.10834765434265137,186,
|
||||
linux_unicode_word,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n \wAh,0.39345431327819824,186,
|
||||
linux_unicode_word,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n \wAh,0.40348386764526367,186,
|
||||
linux_unicode_word,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n \wAh,0.40167927742004395,186,
|
||||
linux_unicode_word,1,3,ag (no Unicode),ag -s \wAh,0.9391078948974609,174,
|
||||
linux_unicode_word,1,3,ag (no Unicode),ag -s \wAh,0.9322304725646973,174,
|
||||
linux_unicode_word,1,3,ag (no Unicode),ag -s \wAh,0.9393062591552734,174,
|
||||
linux_unicode_word,1,3,ag-novcs (no Unicode),ag --skip-vcs-ignores -s \wAh,0.9509954452514648,174,
|
||||
linux_unicode_word,1,3,ag-novcs (no Unicode),ag --skip-vcs-ignores -s \wAh,0.9229059219360352,174,
|
||||
linux_unicode_word,1,3,ag-novcs (no Unicode),ag --skip-vcs-ignores -s \wAh,0.8915724754333496,174,
|
||||
linux_unicode_word,1,3,ucg (no Unicode),ucg --nosmart-case \wAh,0.1719198226928711,168,
|
||||
linux_unicode_word,1,3,ucg (no Unicode),ucg --nosmart-case \wAh,0.18027615547180176,168,
|
||||
linux_unicode_word,1,3,ucg (no Unicode),ucg --nosmart-case \wAh,0.17251205444335938,168,
|
||||
linux_unicode_word,1,3,git grep,git grep -E -I -n \wAh,4.980919122695923,186,LC_ALL=en_US.UTF-8
|
||||
linux_unicode_word,1,3,git grep,git grep -E -I -n \wAh,4.995086193084717,186,LC_ALL=en_US.UTF-8
|
||||
linux_unicode_word,1,3,git grep,git grep -E -I -n \wAh,4.941043376922607,186,LC_ALL=en_US.UTF-8
|
||||
linux_unicode_word,1,3,git grep (no Unicode),git grep -E -I -n \wAh,1.5811383724212646,174,LC_ALL=C
|
||||
linux_unicode_word,1,3,git grep (no Unicode),git grep -E -I -n \wAh,1.5947043895721436,174,LC_ALL=C
|
||||
linux_unicode_word,1,3,git grep (no Unicode),git grep -E -I -n \wAh,1.522637128829956,174,LC_ALL=C
|
||||
linux_unicode_word,1,3,sift (no Unicode),sift -n --binary-skip --exclude-files .* \wAh,4.356529951095581,174,
|
||||
linux_unicode_word,1,3,sift (no Unicode),sift -n --binary-skip --exclude-files .* \wAh,4.129682540893555,174,
|
||||
linux_unicode_word,1,3,sift (no Unicode),sift -n --binary-skip --exclude-files .* \wAh,4.098994731903076,174,
|
||||
linux_word,1,3,rg,rg -n -w PM_RESUME,0.21953463554382324,6,
|
||||
linux_word,1,3,rg,rg -n -w PM_RESUME,0.2401576042175293,6,
|
||||
linux_word,1,3,rg,rg -n -w PM_RESUME,0.21302008628845215,6,
|
||||
linux_word,1,3,rg-novcs,rg --no-ignore -n -w PM_RESUME,0.14854192733764648,6,
|
||||
linux_word,1,3,rg-novcs,rg --no-ignore -n -w PM_RESUME,0.09938955307006836,6,
|
||||
linux_word,1,3,rg-novcs,rg --no-ignore -n -w PM_RESUME,0.1005239486694336,6,
|
||||
linux_word,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n -w PM_RESUME,0.3981668949127197,6,
|
||||
linux_word,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n -w PM_RESUME,0.3999497890472412,6,
|
||||
linux_word,1,3,rg-novcs-mmap,rg --mmap --no-ignore -n -w PM_RESUME,0.38619542121887207,6,
|
||||
linux_word,1,3,ag,ag -s -w PM_RESUME,0.6837906837463379,6,
|
||||
linux_word,1,3,ag,ag -s -w PM_RESUME,0.6158981323242188,6,
|
||||
linux_word,1,3,ag,ag -s -w PM_RESUME,0.41248440742492676,6,
|
||||
linux_word,1,3,ag-novcs,ag --skip-vcs-ignores -s -w PM_RESUME,0.42545604705810547,6,
|
||||
linux_word,1,3,ag-novcs,ag --skip-vcs-ignores -s -w PM_RESUME,0.4142575263977051,6,
|
||||
linux_word,1,3,ag-novcs,ag --skip-vcs-ignores -s -w PM_RESUME,0.4717123508453369,6,
|
||||
linux_word,1,3,ucg,ucg --nosmart-case -w PM_RESUME,0.1639394760131836,6,
|
||||
linux_word,1,3,ucg,ucg --nosmart-case -w PM_RESUME,0.16333961486816406,6,
|
||||
linux_word,1,3,ucg,ucg --nosmart-case -w PM_RESUME,0.16097497940063477,6,
|
||||
linux_word,1,3,git grep,git grep -E -I -n -w PM_RESUME,0.17300987243652344,6,LC_ALL=C
|
||||
linux_word,1,3,git grep,git grep -E -I -n -w PM_RESUME,0.171494722366333,6,LC_ALL=C
|
||||
linux_word,1,3,git grep,git grep -E -I -n -w PM_RESUME,0.19692277908325195,6,LC_ALL=C
|
||||
linux_word,1,3,sift,sift -n --binary-skip --exclude-files .* -w PM_RESUME,3.190856695175171,6,
|
||||
linux_word,1,3,sift,sift -n --binary-skip --exclude-files .* -w PM_RESUME,3.1970269680023193,6,
|
||||
linux_word,1,3,sift,sift -n --binary-skip --exclude-files .* -w PM_RESUME,3.094048500061035,6,
|
||||
subtitles_en_literal,1,3,rg,rg -n Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.41990160942077637,629,
|
||||
subtitles_en_literal,1,3,rg,rg -n Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5151379108428955,629,
|
||||
subtitles_en_literal,1,3,rg,rg -n Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5245285034179688,629,
|
||||
subtitles_en_literal,1,3,rg (no line numbers),rg Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.2494678497314453,629,
|
||||
subtitles_en_literal,1,3,rg (no line numbers),rg Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.2570071220397949,629,
|
||||
subtitles_en_literal,1,3,rg (no line numbers),rg Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.20493078231811523,629,
|
||||
subtitles_en_literal,1,3,ag,ag -s Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.0035574436187744,629,
|
||||
subtitles_en_literal,1,3,ag,ag -s Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,2.004251003265381,629,
|
||||
subtitles_en_literal,1,3,ag,ag -s Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.998549222946167,629,
|
||||
subtitles_en_literal,1,3,ucg,ucg --nosmart-case Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.750638484954834,629,
|
||||
subtitles_en_literal,1,3,ucg,ucg --nosmart-case Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.7518937587738037,629,
|
||||
subtitles_en_literal,1,3,ucg,ucg --nosmart-case Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.6610665321350098,629,
|
||||
subtitles_en_literal,1,3,grep,grep -an Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.9856901168823242,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,grep,grep -an Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.0250558853149414,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,grep,grep -an Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.0195670127868652,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,grep (no line numbers),grep -a Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5834128856658936,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,grep (no line numbers),grep -a Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5891468524932861,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,grep (no line numbers),grep -a Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5075380802154541,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,pt,pt Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.6499581336975098,629,
|
||||
subtitles_en_literal,1,3,pt,pt Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.667529821395874,629,
|
||||
subtitles_en_literal,1,3,pt,pt Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.6895508766174316,629,
|
||||
subtitles_en_literal,1,3,pt (no line numbers),pt -N Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.4941000938415527,629,
|
||||
subtitles_en_literal,1,3,pt (no line numbers),pt -N Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.670578956604004,629,
|
||||
subtitles_en_literal,1,3,pt (no line numbers),pt -N Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,1.6264257431030273,629,
|
||||
subtitles_en_literal,1,3,sift,sift -n Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.7577519416809082,629,
|
||||
subtitles_en_literal,1,3,sift,sift -n Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.7018873691558838,629,
|
||||
subtitles_en_literal,1,3,sift,sift -n Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.5913088321685791,629,
|
||||
subtitles_en_literal,1,3,sift (no line numbers),sift Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.2632462978363037,629,
|
||||
subtitles_en_literal,1,3,sift (no line numbers),sift Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.2749521732330322,629,
|
||||
subtitles_en_literal,1,3,sift (no line numbers),sift Sherlock Holmes /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.sample.en,0.27170491218566895,629,
|
||||
subtitles_ru_alternate,1,3,rg,rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.6460118293762207,691,
|
||||
subtitles_ru_alternate,1,3,rg,rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.5819060802459717,691,
|
||||
subtitles_ru_alternate,1,3,rg,rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.7640905380249023,691,
|
||||
subtitles_ru_alternate,1,3,rg (no line numbers),rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.2313611507415771,691,
|
||||
subtitles_ru_alternate,1,3,rg (no line numbers),rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3044109344482422,691,
|
||||
subtitles_ru_alternate,1,3,rg (no line numbers),rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3338491916656494,691,
|
||||
subtitles_ru_alternate,1,3,ucg,ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.3752894401550293,691,
|
||||
subtitles_ru_alternate,1,3,ucg,ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.370604991912842,691,
|
||||
subtitles_ru_alternate,1,3,ucg,ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.399735689163208,691,
|
||||
subtitles_ru_alternate,1,3,grep,grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.716331243515015,691,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,grep,grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.910337448120117,691,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,grep,grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.955447435379028,691,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,grep (no line numbers),grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.488590240478516,691,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,grep (no line numbers),grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.247926950454712,691,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,grep (no line numbers),grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.541552305221558,691,LC_ALL=C
|
||||
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.170270681381226,735,
|
||||
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.186170816421509,735,
|
||||
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.001753807067871,735,
|
||||
subtitles_ru_alternate_casei,1,3,ucg (not Unicode),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.2377853393554688,691,
|
||||
subtitles_ru_alternate_casei,1,3,ucg (not Unicode),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.361377477645874,691,
|
||||
subtitles_ru_alternate_casei,1,3,ucg (not Unicode),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.4316565990448,691,
|
||||
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.9808149337768555,735,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.773010015487671,735,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.952658414840698,735,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_alternate_casei,1,3,grep (not Unicode),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.799196481704712,691,LC_ALL=C
|
||||
subtitles_ru_alternate_casei,1,3,grep (not Unicode),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.990447282791138,691,LC_ALL=C
|
||||
subtitles_ru_alternate_casei,1,3,grep (not Unicode),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.916130781173706,691,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,rg,rg -n Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.824413537979126,583,
|
||||
subtitles_ru_literal,1,3,rg,rg -n Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8357686996459961,583,
|
||||
subtitles_ru_literal,1,3,rg,rg -n Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8958892822265625,583,
|
||||
subtitles_ru_literal,1,3,rg (no line numbers),rg Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.2959728240966797,583,
|
||||
subtitles_ru_literal,1,3,rg (no line numbers),rg Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.3027801513671875,583,
|
||||
subtitles_ru_literal,1,3,rg (no line numbers),rg Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.3133840560913086,583,
|
||||
subtitles_ru_literal,1,3,ag,ag -s Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.8583695888519287,583,
|
||||
subtitles_ru_literal,1,3,ag,ag -s Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.0803942680358887,583,
|
||||
subtitles_ru_literal,1,3,ag,ag -s Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.092284679412842,583,
|
||||
subtitles_ru_literal,1,3,ucg,ucg --nosmart-case Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.5811631679534912,583,
|
||||
subtitles_ru_literal,1,3,ucg,ucg --nosmart-case Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.5879406929016113,583,
|
||||
subtitles_ru_literal,1,3,ucg,ucg --nosmart-case Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.5010735988616943,583,
|
||||
subtitles_ru_literal,1,3,grep,grep -an Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3335914611816406,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,grep,grep -an Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3385870456695557,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,grep,grep -an Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3321411609649658,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,grep (no line numbers),grep -a Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8784911632537842,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,grep (no line numbers),grep -a Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8721048831939697,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,grep (no line numbers),grep -a Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,0.8763093948364258,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,pt,pt Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.429335355758667,583,
|
||||
subtitles_ru_literal,1,3,pt,pt Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,4.938883543014526,583,
|
||||
subtitles_ru_literal,1,3,pt,pt Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.5893049240112305,583,
|
||||
subtitles_ru_literal,1,3,pt (no line numbers),pt -N Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.522632598876953,583,
|
||||
subtitles_ru_literal,1,3,pt (no line numbers),pt -N Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.237533330917358,583,
|
||||
subtitles_ru_literal,1,3,pt (no line numbers),pt -N Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,5.215710401535034,583,
|
||||
subtitles_ru_literal,1,3,sift,sift -n Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.944578170776367,583,
|
||||
subtitles_ru_literal,1,3,sift,sift -n Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.835101127624512,583,
|
||||
subtitles_ru_literal,1,3,sift,sift -n Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.847816228866577,583,
|
||||
subtitles_ru_literal,1,3,sift (no line numbers),sift Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.25161075592041,583,
|
||||
subtitles_ru_literal,1,3,sift (no line numbers),sift Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.299700736999512,583,
|
||||
subtitles_ru_literal,1,3,sift (no line numbers),sift Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.38068151473999,583,
|
||||
subtitles_ru_literal_casei,1,3,rg,rg -n -i Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.6576766967773438,604,
|
||||
subtitles_ru_literal_casei,1,3,rg,rg -n -i Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.4723634719848633,604,
|
||||
subtitles_ru_literal_casei,1,3,rg,rg -n -i Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.775054931640625,604,
|
||||
subtitles_ru_literal_casei,1,3,ucg (not Unicode),ucg -i Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.5934054851531982,583,
|
||||
subtitles_ru_literal_casei,1,3,ucg (not Unicode),ucg -i Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.597702980041504,583,
|
||||
subtitles_ru_literal_casei,1,3,ucg (not Unicode),ucg -i Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.5229814052581787,583,
|
||||
subtitles_ru_literal_casei,1,3,grep,grep -ani Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.458112478256226,604,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_literal_casei,1,3,grep,grep -ani Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.91841197013855,604,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_literal_casei,1,3,grep,grep -ani Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,6.809293508529663,604,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_literal_casei,1,3,grep (not Unicode),grep -E -ani Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.3416473865509033,583,LC_ALL=C
|
||||
subtitles_ru_literal_casei,1,3,grep (not Unicode),grep -E -ani Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.1377508640289307,583,LC_ALL=C
|
||||
subtitles_ru_literal_casei,1,3,grep (not Unicode),grep -E -ani Шерлок Холмс /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.146819829940796,583,LC_ALL=C
|
||||
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.7402286529541016,41,
|
||||
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.872703790664673,41,
|
||||
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.8877029418945312,41,
|
||||
subtitles_ru_no_literal,1,3,rg (no line numbers),rg \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.414641857147217,41,
|
||||
subtitles_ru_no_literal,1,3,rg (no line numbers),rg \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.4537253379821777,41,
|
||||
subtitles_ru_no_literal,1,3,rg (no line numbers),rg \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,3.460618019104004,41,
|
||||
subtitles_ru_no_literal,1,3,ucg (no Unicode),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.290541648864746,,
|
||||
subtitles_ru_no_literal,1,3,ucg (no Unicode),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.311371088027954,,
|
||||
subtitles_ru_no_literal,1,3,ucg (no Unicode),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.1349129676818848,,
|
||||
subtitles_ru_no_literal,1,3,grep (no Unicode),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.8941442966461182,,LC_ALL=C
|
||||
subtitles_ru_no_literal,1,3,grep (no Unicode),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,1.8850946426391602,,LC_ALL=C
|
||||
subtitles_ru_no_literal,1,3,grep (no Unicode),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /home/andrew/tmp/benchsuite/subtitles/OpenSubtitles2016.raw.ru,2.074228525161743,,LC_ALL=C
|
|
93
benchsuite/runs/2016-09-17-ubuntu1604-ec2/README.SETUP
Normal file
93
benchsuite/runs/2016-09-17-ubuntu1604-ec2/README.SETUP
Normal file
@@ -0,0 +1,93 @@
|
||||
Ubuntu 16.04 HVM AMI
|
||||
c3.2xlarge, Xeon E5-2680, 2.8 GHz, 8 CPUs, 16 GB memory, 80 GB SSD
|
||||
|
||||
# Generic system setup
|
||||
|
||||
mkfs.ext4 /dev/xvdb
|
||||
sudo mount /dev/xvdb /mnt
|
||||
sudo chown ubuntu /mnt
|
||||
sudo apt-get update
|
||||
sudo apt-get install \ # for building Linux kernel
|
||||
make gcc bc
|
||||
sudo apt-get install \ # for the silver searcher
|
||||
automake pkg-config zlib1g-dev liblzma-dev libpcre3 libpcre3-dev
|
||||
sudo apt-get install \ # for Universal Code Grep
|
||||
libtool libpcre2-8-0 libpcre2-dev
|
||||
sudo apt-get install \ # for sift and the platinum searcher
|
||||
go
|
||||
|
||||
# Get benchmark corpora
|
||||
|
||||
cd /mnt
|
||||
mkdir /mnt/bench
|
||||
git clone git://github.com/BurntSushi/ripgrep
|
||||
cd ripgrep/benchsuite
|
||||
./benchsuite --dir /mnt/bench/ --download all # takes around 15 minutes
|
||||
|
||||
# Install search tools
|
||||
mkdir /mnt/bin/
|
||||
|
||||
## ripgrep
|
||||
|
||||
cd /mnt
|
||||
mkdir ripgrep-bin
|
||||
cd ripgrep-bin
|
||||
curl -LO 'https://github.com/BurntSushi/ripgrep/releases/download/0.1.2/ripgrep-0.1.2-x86_64-unknown-linux-musl.tar.gz'
|
||||
cp ripgrep-0.1.2-x86_64-unknown-linux-musl/rg /mnt/bin/
|
||||
|
||||
## The Silver Searcher
|
||||
|
||||
cd /mnt
|
||||
git clone git://github.com/ggreer/the_silver_searcher
|
||||
cd the_silver_searcher
|
||||
git checkout cda635
|
||||
./build.sh
|
||||
cp ag /mnt/bin/
|
||||
|
||||
## Universal Code Grep
|
||||
|
||||
cd /mnt
|
||||
git clone git://github.com/gvansickle/ucg
|
||||
cd ucg
|
||||
git checkout 487bfb
|
||||
autoreconf -i
|
||||
./configure
|
||||
make
|
||||
cp ucg /mnt/bin/
|
||||
|
||||
## The Platinum Searcher
|
||||
|
||||
export GOPATH=/mnt/go
|
||||
go get github.com/monochromegane/the_platinum_searcher
|
||||
cd /mnt/go/src/github.com/monochromegane/the_platinum_searcher
|
||||
git checkout 509368
|
||||
go install github.com/monochromegane/the_platinum_searcher/cmd/...
|
||||
cp /mnt/go/bin/pt /mnt/bin/
|
||||
|
||||
## Sift
|
||||
|
||||
export GOPATH=/mnt/go
|
||||
go get github.com/svent/sift
|
||||
cd /mnt/go/src/github.com/svent/sift
|
||||
git checkout 2d175c
|
||||
go install
|
||||
cp /mnt/go/bin/sift /mnt/bin/
|
||||
|
||||
## 'git grep' and GNU grep
|
||||
|
||||
They are part of the standard Ubuntu install, and are pretty recent (as of
|
||||
September 2016).
|
||||
|
||||
$ git --version
|
||||
git version 2.7.4
|
||||
$ grep --version
|
||||
grep (GNU grep) 2.25
|
||||
|
||||
|
||||
# Running benchmarks
|
||||
|
||||
export PATH="/mnt/bin:$PATH"
|
||||
cd /mnt/ripgrep/benchsuite
|
||||
./benchsuite --dir /mnt/bench/ --raw /mnt/bench/raw.csv \
|
||||
| tee /mnt/bench/summary
|
||||
# The above took around 30 minutes to run to completion.
|
457
benchsuite/runs/2016-09-17-ubuntu1604-ec2/raw.csv
Normal file
457
benchsuite/runs/2016-09-17-ubuntu1604-ec2/raw.csv
Normal file
@@ -0,0 +1,457 @@
|
||||
benchmark,warmup_iter,iter,name,command,duration,lines,env
|
||||
linux_alternates,1,3,rg (ignore),rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.30042552947998047,68,
|
||||
linux_alternates,1,3,rg (ignore),rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.3699159622192383,68,
|
||||
linux_alternates,1,3,rg (ignore),rg -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.2950403690338135,68,
|
||||
linux_alternates,1,3,ag (ignore),ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.7572166919708252,68,
|
||||
linux_alternates,1,3,ag (ignore),ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.7568728923797607,68,
|
||||
linux_alternates,1,3,ag (ignore),ag -s ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.7468714714050293,68,
|
||||
linux_alternates,1,3,git grep (ignore),git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5062770843505859,68,LC_ALL=C
|
||||
linux_alternates,1,3,git grep (ignore),git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.49932026863098145,68,LC_ALL=C
|
||||
linux_alternates,1,3,git grep (ignore),git grep -E -I -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5008277893066406,68,LC_ALL=C
|
||||
linux_alternates,1,3,rg (whitelist),rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.19775605201721191,68,
|
||||
linux_alternates,1,3,rg (whitelist),rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.19699668884277344,68,
|
||||
linux_alternates,1,3,rg (whitelist),rg --no-ignore -n ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.19636178016662598,68,
|
||||
linux_alternates,1,3,ucg (whitelist),ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.21344256401062012,68,
|
||||
linux_alternates,1,3,ucg (whitelist),ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.21743154525756836,68,
|
||||
linux_alternates,1,3,ucg (whitelist),ucg --nosmart-case ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.22065043449401855,68,
|
||||
linux_alternates_casei,1,3,rg (ignore),rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.31632304191589355,160,
|
||||
linux_alternates_casei,1,3,rg (ignore),rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.3168807029724121,160,
|
||||
linux_alternates_casei,1,3,rg (ignore),rg -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.4834277629852295,160,
|
||||
linux_alternates_casei,1,3,ag (ignore),ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.9558978080749512,160,
|
||||
linux_alternates_casei,1,3,ag (ignore),ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.9736671447753906,160,
|
||||
linux_alternates_casei,1,3,ag (ignore),ag -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,1.9648356437683105,160,
|
||||
linux_alternates_casei,1,3,git grep (ignore),git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,2.0229439735412598,160,LC_ALL=C
|
||||
linux_alternates_casei,1,3,git grep (ignore),git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,2.0214922428131104,160,LC_ALL=C
|
||||
linux_alternates_casei,1,3,git grep (ignore),git grep -E -I -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,2.022616147994995,160,LC_ALL=C
|
||||
linux_alternates_casei,1,3,rg (whitelist),rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.22146987915039062,160,
|
||||
linux_alternates_casei,1,3,rg (whitelist),rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.22275280952453613,160,
|
||||
linux_alternates_casei,1,3,rg (whitelist),rg --no-ignore -n -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.22226715087890625,160,
|
||||
linux_alternates_casei,1,3,ucg (whitelist),ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5290391445159912,160,
|
||||
linux_alternates_casei,1,3,ucg (whitelist),ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5196049213409424,160,
|
||||
linux_alternates_casei,1,3,ucg (whitelist),ucg -i ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,0.5219125747680664,160,
|
||||
linux_literal,1,3,rg (ignore),rg -n PM_RESUME,0.2871882915496826,16,
|
||||
linux_literal,1,3,rg (ignore),rg -n PM_RESUME,0.38920140266418457,16,
|
||||
linux_literal,1,3,rg (ignore),rg -n PM_RESUME,0.3668382167816162,16,
|
||||
linux_literal,1,3,rg (ignore) (mmap),rg -n --mmap PM_RESUME,1.6073203086853027,16,
|
||||
linux_literal,1,3,rg (ignore) (mmap),rg -n --mmap PM_RESUME,1.6012177467346191,16,
|
||||
linux_literal,1,3,rg (ignore) (mmap),rg -n --mmap PM_RESUME,1.5818352699279785,16,
|
||||
linux_literal,1,3,ag (ignore) (mmap),ag -s PM_RESUME,1.592775583267212,16,
|
||||
linux_literal,1,3,ag (ignore) (mmap),ag -s PM_RESUME,1.5901448726654053,16,
|
||||
linux_literal,1,3,ag (ignore) (mmap),ag -s PM_RESUME,1.586061716079712,16,
|
||||
linux_literal,1,3,pt (ignore),pt PM_RESUME,0.45094990730285645,16,
|
||||
linux_literal,1,3,pt (ignore),pt PM_RESUME,0.47065186500549316,16,
|
||||
linux_literal,1,3,pt (ignore),pt PM_RESUME,0.4422800540924072,16,
|
||||
linux_literal,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME,0.6293809413909912,16,
|
||||
linux_literal,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME,0.6314799785614014,16,
|
||||
linux_literal,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git PM_RESUME,0.6289358139038086,16,
|
||||
linux_literal,1,3,git grep (ignore),git grep -I -n PM_RESUME,0.347550630569458,16,LC_ALL=C
|
||||
linux_literal,1,3,git grep (ignore),git grep -I -n PM_RESUME,0.345928430557251,16,LC_ALL=C
|
||||
linux_literal,1,3,git grep (ignore),git grep -I -n PM_RESUME,0.33939385414123535,16,LC_ALL=C
|
||||
linux_literal,1,3,rg (whitelist),rg -n --no-ignore -tall PM_RESUME,0.20830345153808594,16,
|
||||
linux_literal,1,3,rg (whitelist),rg -n --no-ignore -tall PM_RESUME,0.34220385551452637,16,
|
||||
linux_literal,1,3,rg (whitelist),rg -n --no-ignore -tall PM_RESUME,0.2077772617340088,16,
|
||||
linux_literal,1,3,ucg (whitelist),ucg --nosmart-case PM_RESUME,0.21996808052062988,16,
|
||||
linux_literal,1,3,ucg (whitelist),ucg --nosmart-case PM_RESUME,0.22822093963623047,16,
|
||||
linux_literal,1,3,ucg (whitelist),ucg --nosmart-case PM_RESUME,0.21923017501831055,16,
|
||||
linux_literal_casei,1,3,rg (ignore),rg -n -i PM_RESUME,0.2988588809967041,370,
|
||||
linux_literal_casei,1,3,rg (ignore),rg -n -i PM_RESUME,0.5339267253875732,370,
|
||||
linux_literal_casei,1,3,rg (ignore),rg -n -i PM_RESUME,0.43750762939453125,370,
|
||||
linux_literal_casei,1,3,rg (ignore) (mmap),rg -n -i --mmap PM_RESUME,1.603757381439209,370,
|
||||
linux_literal_casei,1,3,rg (ignore) (mmap),rg -n -i --mmap PM_RESUME,1.618077278137207,370,
|
||||
linux_literal_casei,1,3,rg (ignore) (mmap),rg -n -i --mmap PM_RESUME,1.6234121322631836,370,
|
||||
linux_literal_casei,1,3,ag (ignore) (mmap),ag -i PM_RESUME,1.621368646621704,370,
|
||||
linux_literal_casei,1,3,ag (ignore) (mmap),ag -i PM_RESUME,1.5698626041412354,370,
|
||||
linux_literal_casei,1,3,ag (ignore) (mmap),ag -i PM_RESUME,1.6105949878692627,370,
|
||||
linux_literal_casei,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME,0.8005843162536621,370,
|
||||
linux_literal_casei,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME,0.8044955730438232,370,
|
||||
linux_literal_casei,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git PM_RESUME,0.806922197341919,370,
|
||||
linux_literal_casei,1,3,git grep (ignore),git grep -I -n -i PM_RESUME,0.34161829948425293,370,LC_ALL=C
|
||||
linux_literal_casei,1,3,git grep (ignore),git grep -I -n -i PM_RESUME,0.3455958366394043,370,LC_ALL=C
|
||||
linux_literal_casei,1,3,git grep (ignore),git grep -I -n -i PM_RESUME,0.3493361473083496,370,LC_ALL=C
|
||||
linux_literal_casei,1,3,rg (whitelist),rg -n -i --no-ignore -tall PM_RESUME,0.2149522304534912,370,
|
||||
linux_literal_casei,1,3,rg (whitelist),rg -n -i --no-ignore -tall PM_RESUME,0.21602368354797363,370,
|
||||
linux_literal_casei,1,3,rg (whitelist),rg -n -i --no-ignore -tall PM_RESUME,0.27021098136901855,370,
|
||||
linux_literal_casei,1,3,ucg (whitelist),ucg -i PM_RESUME,0.22747421264648438,370,
|
||||
linux_literal_casei,1,3,ucg (whitelist),ucg -i PM_RESUME,0.22050881385803223,370,
|
||||
linux_literal_casei,1,3,ucg (whitelist),ucg -i PM_RESUME,0.21217584609985352,370,
|
||||
linux_literal_default,1,3,rg,rg PM_RESUME,0.27482175827026367,16,
|
||||
linux_literal_default,1,3,rg,rg PM_RESUME,0.2796294689178467,16,
|
||||
linux_literal_default,1,3,rg,rg PM_RESUME,0.27638936042785645,16,
|
||||
linux_literal_default,1,3,ag,ag PM_RESUME,1.598384141921997,16,
|
||||
linux_literal_default,1,3,ag,ag PM_RESUME,1.5849597454071045,16,
|
||||
linux_literal_default,1,3,ag,ag PM_RESUME,1.6000149250030518,16,
|
||||
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.2263963222503662,16,
|
||||
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.21367835998535156,16,
|
||||
linux_literal_default,1,3,ucg,ucg PM_RESUME,0.21764111518859863,16,
|
||||
linux_literal_default,1,3,pt,pt PM_RESUME,0.42263340950012207,16,
|
||||
linux_literal_default,1,3,pt,pt PM_RESUME,0.467041015625,16,
|
||||
linux_literal_default,1,3,pt,pt PM_RESUME,0.42820048332214355,16,
|
||||
linux_literal_default,1,3,sift,sift PM_RESUME,0.33421826362609863,16,
|
||||
linux_literal_default,1,3,sift,sift PM_RESUME,0.35932135581970215,16,
|
||||
linux_literal_default,1,3,sift,sift PM_RESUME,0.3372631072998047,16,
|
||||
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.348984956741333,16,LC_ALL=en_US.UTF-8
|
||||
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.34420299530029297,16,LC_ALL=en_US.UTF-8
|
||||
linux_literal_default,1,3,git grep,git grep PM_RESUME,0.33880615234375,16,LC_ALL=en_US.UTF-8
|
||||
linux_no_literal,1,3,rg (ignore),rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.5833027362823486,490,
|
||||
linux_no_literal,1,3,rg (ignore),rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.5783836841583252,490,
|
||||
linux_no_literal,1,3,rg (ignore),rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.5806806087493896,490,
|
||||
linux_no_literal,1,3,rg (ignore) (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.4163496494293213,490,
|
||||
linux_no_literal,1,3,rg (ignore) (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.4040029048919678,490,
|
||||
linux_no_literal,1,3,rg (ignore) (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.40265560150146484,490,
|
||||
linux_no_literal,1,3,ag (ignore) (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},2.3176910877227783,766,
|
||||
linux_no_literal,1,3,ag (ignore) (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},2.3504347801208496,766,
|
||||
linux_no_literal,1,3,ag (ignore) (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},2.317542552947998,766,
|
||||
linux_no_literal,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},25.821982383728027,491,
|
||||
linux_no_literal,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},25.82067561149597,491,
|
||||
linux_no_literal,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},25.626302242279053,491,
|
||||
linux_no_literal,1,3,git grep (ignore),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},26.349210023880005,490,LC_ALL=en_US.UTF-8
|
||||
linux_no_literal,1,3,git grep (ignore),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},26.34226369857788,490,LC_ALL=en_US.UTF-8
|
||||
linux_no_literal,1,3,git grep (ignore),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},26.340656995773315,490,LC_ALL=en_US.UTF-8
|
||||
linux_no_literal,1,3,git grep (ignore) (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},4.14680290222168,490,LC_ALL=C
|
||||
linux_no_literal,1,3,git grep (ignore) (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},4.153340578079224,490,LC_ALL=C
|
||||
linux_no_literal,1,3,git grep (ignore) (ASCII),git grep -E -I -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},4.154819011688232,490,LC_ALL=C
|
||||
linux_no_literal,1,3,rg (whitelist),rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.49768829345703125,419,
|
||||
linux_no_literal,1,3,rg (whitelist),rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.5121400356292725,419,
|
||||
linux_no_literal,1,3,rg (whitelist),rg -n --no-ignore -tall \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.49718427658081055,419,
|
||||
linux_no_literal,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.38550543785095215,419,
|
||||
linux_no_literal,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.32651591300964355,419,
|
||||
linux_no_literal,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},0.3246915340423584,419,
|
||||
linux_no_literal,1,3,ucg (whitelist) (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.128183126449585,416,
|
||||
linux_no_literal,1,3,ucg (whitelist) (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.1255216598510742,416,
|
||||
linux_no_literal,1,3,ucg (whitelist) (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5},1.1268525123596191,416,
|
||||
linux_re_literal_suffix,1,3,rg (ignore),rg -n [A-Z]+_RESUME,0.36306214332580566,1652,
|
||||
linux_re_literal_suffix,1,3,rg (ignore),rg -n [A-Z]+_RESUME,0.45077037811279297,1652,
|
||||
linux_re_literal_suffix,1,3,rg (ignore),rg -n [A-Z]+_RESUME,0.3804624080657959,1652,
|
||||
linux_re_literal_suffix,1,3,ag (ignore),ag -s [A-Z]+_RESUME,1.8995850086212158,1652,
|
||||
linux_re_literal_suffix,1,3,ag (ignore),ag -s [A-Z]+_RESUME,1.8897662162780762,1652,
|
||||
linux_re_literal_suffix,1,3,ag (ignore),ag -s [A-Z]+_RESUME,1.878380537033081,1652,
|
||||
linux_re_literal_suffix,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME,10.48949646949768,1652,
|
||||
linux_re_literal_suffix,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME,10.289165735244751,1652,
|
||||
linux_re_literal_suffix,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git [A-Z]+_RESUME,10.000468254089355,1652,
|
||||
linux_re_literal_suffix,1,3,git grep (ignore),git grep -E -I -n [A-Z]+_RESUME,1.1080453395843506,1652,LC_ALL=C
|
||||
linux_re_literal_suffix,1,3,git grep (ignore),git grep -E -I -n [A-Z]+_RESUME,1.10821533203125,1652,LC_ALL=C
|
||||
linux_re_literal_suffix,1,3,git grep (ignore),git grep -E -I -n [A-Z]+_RESUME,1.105595588684082,1652,LC_ALL=C
|
||||
linux_re_literal_suffix,1,3,rg (whitelist),rg -n --no-ignore -tall [A-Z]+_RESUME,0.2073357105255127,1630,
|
||||
linux_re_literal_suffix,1,3,rg (whitelist),rg -n --no-ignore -tall [A-Z]+_RESUME,0.20552492141723633,1630,
|
||||
linux_re_literal_suffix,1,3,rg (whitelist),rg -n --no-ignore -tall [A-Z]+_RESUME,0.2061319351196289,1630,
|
||||
linux_re_literal_suffix,1,3,ucg (whitelist),ucg --nosmart-case [A-Z]+_RESUME,0.3013310432434082,1630,
|
||||
linux_re_literal_suffix,1,3,ucg (whitelist),ucg --nosmart-case [A-Z]+_RESUME,0.3005218505859375,1630,
|
||||
linux_re_literal_suffix,1,3,ucg (whitelist),ucg --nosmart-case [A-Z]+_RESUME,0.29984378814697266,1630,
|
||||
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.4162716865539551,23,
|
||||
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.47885966300964355,23,
|
||||
linux_unicode_greek,1,3,rg,rg -n \p{Greek},0.5135962963104248,23,
|
||||
linux_unicode_greek,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek},7.570494651794434,23,
|
||||
linux_unicode_greek,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek},7.790151596069336,23,
|
||||
linux_unicode_greek,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n --git \p{Greek},7.783358812332153,23,
|
||||
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.4370443820953369,103,
|
||||
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.40680766105651855,103,
|
||||
linux_unicode_greek_casei,1,3,rg,rg -n -i \p{Greek},0.4011569023132324,103,
|
||||
linux_unicode_greek_casei,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek},0.002422809600830078,,
|
||||
linux_unicode_greek_casei,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek},0.002414226531982422,,
|
||||
linux_unicode_greek_casei,1,3,sift,sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -i --git \p{Greek},0.002293109893798828,,
|
||||
linux_unicode_word,1,3,rg (ignore),rg -n \wAh,0.44771265983581543,186,
|
||||
linux_unicode_word,1,3,rg (ignore),rg -n \wAh,0.3006107807159424,186,
|
||||
linux_unicode_word,1,3,rg (ignore),rg -n \wAh,0.3026111125946045,186,
|
||||
linux_unicode_word,1,3,rg (ignore) (ASCII),rg -n (?-u)\wAh,0.43827080726623535,174,
|
||||
linux_unicode_word,1,3,rg (ignore) (ASCII),rg -n (?-u)\wAh,0.2931697368621826,174,
|
||||
linux_unicode_word,1,3,rg (ignore) (ASCII),rg -n (?-u)\wAh,0.33072638511657715,174,
|
||||
linux_unicode_word,1,3,ag (ignore) (ASCII),ag -s \wAh,1.7645132541656494,174,
|
||||
linux_unicode_word,1,3,ag (ignore) (ASCII),ag -s \wAh,1.7730333805084229,174,
|
||||
linux_unicode_word,1,3,ag (ignore) (ASCII),ag -s \wAh,1.773383378982544,174,
|
||||
linux_unicode_word,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \wAh,10.872124671936035,174,
|
||||
linux_unicode_word,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \wAh,11.147738456726074,174,
|
||||
linux_unicode_word,1,3,sift (ignore) (ASCII),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n \wAh,11.029243469238281,174,
|
||||
linux_unicode_word,1,3,git grep (ignore),git grep -E -I -n \wAh,13.047154664993286,186,LC_ALL=en_US.UTF-8
|
||||
linux_unicode_word,1,3,git grep (ignore),git grep -E -I -n \wAh,13.025037288665771,186,LC_ALL=en_US.UTF-8
|
||||
linux_unicode_word,1,3,git grep (ignore),git grep -E -I -n \wAh,13.081012487411499,186,LC_ALL=en_US.UTF-8
|
||||
linux_unicode_word,1,3,git grep (ignore) (ASCII),git grep -E -I -n \wAh,2.98722767829895,174,LC_ALL=C
|
||||
linux_unicode_word,1,3,git grep (ignore) (ASCII),git grep -E -I -n \wAh,2.987990379333496,174,LC_ALL=C
|
||||
linux_unicode_word,1,3,git grep (ignore) (ASCII),git grep -E -I -n \wAh,2.988698959350586,174,LC_ALL=C
|
||||
linux_unicode_word,1,3,rg (whitelist),rg -n --no-ignore -tall \wAh,0.21961355209350586,180,
|
||||
linux_unicode_word,1,3,rg (whitelist),rg -n --no-ignore -tall \wAh,0.2884254455566406,180,
|
||||
linux_unicode_word,1,3,rg (whitelist),rg -n --no-ignore -tall \wAh,0.21905040740966797,180,
|
||||
linux_unicode_word,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\wAh,0.23966765403747559,168,
|
||||
linux_unicode_word,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\wAh,0.21801042556762695,168,
|
||||
linux_unicode_word,1,3,rg (whitelist) (ASCII),rg -n --no-ignore -tall (?-u)\wAh,0.21909880638122559,168,
|
||||
linux_unicode_word,1,3,ucg (ASCII),ucg --nosmart-case \wAh,0.2259504795074463,168,
|
||||
linux_unicode_word,1,3,ucg (ASCII),ucg --nosmart-case \wAh,0.22269177436828613,168,
|
||||
linux_unicode_word,1,3,ucg (ASCII),ucg --nosmart-case \wAh,0.2259974479675293,168,
|
||||
linux_word,1,3,rg (ignore),rg -n -w PM_RESUME,0.34968090057373047,6,
|
||||
linux_word,1,3,rg (ignore),rg -n -w PM_RESUME,0.28850769996643066,6,
|
||||
linux_word,1,3,rg (ignore),rg -n -w PM_RESUME,0.34809160232543945,6,
|
||||
linux_word,1,3,ag (ignore),ag -s -w PM_RESUME,1.6134660243988037,6,
|
||||
linux_word,1,3,ag (ignore),ag -s -w PM_RESUME,1.59847092628479,6,
|
||||
linux_word,1,3,ag (ignore),ag -s -w PM_RESUME,1.581369161605835,6,
|
||||
linux_word,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME,7.644887208938599,6,
|
||||
linux_word,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME,7.8782219886779785,6,
|
||||
linux_word,1,3,sift (ignore),sift --binary-skip --exclude-files .* --exclude-files *.pdf -n -w --git PM_RESUME,7.754150152206421,6,
|
||||
linux_word,1,3,git grep (ignore),git grep -E -I -n -w PM_RESUME,0.34302353858947754,6,LC_ALL=C
|
||||
linux_word,1,3,git grep (ignore),git grep -E -I -n -w PM_RESUME,0.33672142028808594,6,LC_ALL=C
|
||||
linux_word,1,3,git grep (ignore),git grep -E -I -n -w PM_RESUME,0.35193610191345215,6,LC_ALL=C
|
||||
linux_word,1,3,rg (whitelist),rg -n -w --no-ignore -tall PM_RESUME,0.33329272270202637,6,
|
||||
linux_word,1,3,rg (whitelist),rg -n -w --no-ignore -tall PM_RESUME,0.25751829147338867,6,
|
||||
linux_word,1,3,rg (whitelist),rg -n -w --no-ignore -tall PM_RESUME,0.21761608123779297,6,
|
||||
linux_word,1,3,ucg (whitelist),ucg --nosmart-case -w PM_RESUME,0.22014284133911133,6,
|
||||
linux_word,1,3,ucg (whitelist),ucg --nosmart-case -w PM_RESUME,0.22314929962158203,6,
|
||||
linux_word,1,3,ucg (whitelist),ucg --nosmart-case -w PM_RESUME,0.2202434539794922,6,
|
||||
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.622809886932373,848,
|
||||
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6181182861328125,848,
|
||||
subtitles_en_alternate,1,3,rg (lines),rg -n Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6205663681030273,848,
|
||||
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.7565691471099854,848,
|
||||
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.7561769485473633,848,
|
||||
subtitles_en_alternate,1,3,ag (lines),ag -s Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.7559969425201416,848,
|
||||
subtitles_en_alternate,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.4493463039398193,848,
|
||||
subtitles_en_alternate,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.44877028465271,848,
|
||||
subtitles_en_alternate,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.4433801174163818,848,
|
||||
subtitles_en_alternate,1,3,grep (lines),grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4114174842834473,848,LC_ALL=C
|
||||
subtitles_en_alternate,1,3,grep (lines),grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.411625862121582,848,LC_ALL=C
|
||||
subtitles_en_alternate,1,3,grep (lines),grep -E -an Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.408623456954956,848,LC_ALL=C
|
||||
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.2900726795196533,848,
|
||||
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.2905848026275635,848,
|
||||
subtitles_en_alternate,1,3,rg,rg Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.2903940677642822,848,
|
||||
subtitles_en_alternate,1,3,grep,grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.9546515941619873,848,LC_ALL=C
|
||||
subtitles_en_alternate,1,3,grep,grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.955279588699341,848,LC_ALL=C
|
||||
subtitles_en_alternate,1,3,grep,grep -E -a Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.954089403152466,848,LC_ALL=C
|
||||
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.169135332107544,862,
|
||||
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.174601078033447,862,
|
||||
subtitles_en_alternate_casei,1,3,ag (ASCII),ag -s -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.1684675216674805,862,
|
||||
subtitles_en_alternate_casei,1,3,ucg (ASCII),ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4171736240386963,862,
|
||||
subtitles_en_alternate_casei,1,3,ucg (ASCII),ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4158167839050293,862,
|
||||
subtitles_en_alternate_casei,1,3,ucg (ASCII),ucg -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4186513423919678,862,
|
||||
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.531639575958252,862,LC_ALL=C
|
||||
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.526550054550171,862,LC_ALL=C
|
||||
subtitles_en_alternate_casei,1,3,grep (ASCII),grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.528509140014648,862,LC_ALL=C
|
||||
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.722398281097412,862,
|
||||
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7225935459136963,862,
|
||||
subtitles_en_alternate_casei,1,3,rg,rg -n -i Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7222185134887695,862,
|
||||
subtitles_en_alternate_casei,1,3,grep,grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.12151837348938,862,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_alternate_casei,1,3,grep,grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.119963884353638,862,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_alternate_casei,1,3,grep,grep -E -ani Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,5.121079683303833,862,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.2684764862060547,629,
|
||||
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.26811957359313965,629,
|
||||
subtitles_en_literal,1,3,rg,rg Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.2684173583984375,629,
|
||||
subtitles_en_literal,1,3,pt,pt -N Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.435128688812256,629,
|
||||
subtitles_en_literal,1,3,pt,pt -N Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4362881183624268,629,
|
||||
subtitles_en_literal,1,3,pt,pt -N Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4399220943450928,629,
|
||||
subtitles_en_literal,1,3,sift,sift Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.32662391662597656,629,
|
||||
subtitles_en_literal,1,3,sift,sift Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.3277275562286377,629,
|
||||
subtitles_en_literal,1,3,sift,sift Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.32798290252685547,629,
|
||||
subtitles_en_literal,1,3,grep,grep -a Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.520500659942627,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,grep,grep -a Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5191032886505127,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,grep,grep -a Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5171597003936768,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.595801830291748,629,
|
||||
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5954360961914062,629,
|
||||
subtitles_en_literal,1,3,rg (lines),rg -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5945618152618408,629,
|
||||
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7291676998138428,629,
|
||||
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.730966329574585,629,
|
||||
subtitles_en_literal,1,3,ag (lines),ag -s Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.728854179382324,629,
|
||||
subtitles_en_literal,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.775996208190918,629,
|
||||
subtitles_en_literal,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.7760195732116699,629,
|
||||
subtitles_en_literal,1,3,ucg (lines),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.7763564586639404,629,
|
||||
subtitles_en_literal,1,3,pt (lines),pt Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.433366060256958,629,
|
||||
subtitles_en_literal,1,3,pt (lines),pt Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.4338581562042236,629,
|
||||
subtitles_en_literal,1,3,pt (lines),pt Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,3.435924768447876,629,
|
||||
subtitles_en_literal,1,3,sift (lines),sift -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.7586827278137207,629,
|
||||
subtitles_en_literal,1,3,sift (lines),sift -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.7590317726135254,629,
|
||||
subtitles_en_literal,1,3,sift (lines),sift -n Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.754432201385498,629,
|
||||
subtitles_en_literal,1,3,grep (lines),grep -an Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9726488590240479,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,grep (lines),grep -an Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9699857234954834,629,LC_ALL=C
|
||||
subtitles_en_literal,1,3,grep (lines),grep -an Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9714112281799316,629,LC_ALL=C
|
||||
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.36658453941345215,642,
|
||||
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.3654778003692627,642,
|
||||
subtitles_en_literal_casei,1,3,rg,rg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.36565113067626953,642,
|
||||
subtitles_en_literal_casei,1,3,grep,grep -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.0890116691589355,642,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_literal_casei,1,3,grep,grep -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.08124852180481,642,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_literal_casei,1,3,grep,grep -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.0796849727630615,642,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6151647567749023,642,LC_ALL=C
|
||||
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6141552925109863,642,LC_ALL=C
|
||||
subtitles_en_literal_casei,1,3,grep (ASCII),grep -E -ai Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6132988929748535,642,LC_ALL=C
|
||||
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6962459087371826,642,
|
||||
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6945579051971436,642,
|
||||
subtitles_en_literal_casei,1,3,rg (lines),rg -n -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.693866491317749,642,
|
||||
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.771639823913574,642,
|
||||
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.772296190261841,642,
|
||||
subtitles_en_literal_casei,1,3,ag (lines) (ASCII),ag -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7712018489837646,642,
|
||||
subtitles_en_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.8068230152130127,642,
|
||||
subtitles_en_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.80411696434021,642,
|
||||
subtitles_en_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.8038516044616699,642,
|
||||
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5951778888702393,629,
|
||||
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5971941947937012,629,
|
||||
subtitles_en_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Sherlock Holmes(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5952184200286865,629,
|
||||
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7292284965515137,629,
|
||||
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.728681802749634,629,
|
||||
subtitles_en_literal_word,1,3,ag (ASCII),ag -sw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7315311431884766,629,
|
||||
subtitles_en_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.784024715423584,629,
|
||||
subtitles_en_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.780540943145752,629,
|
||||
subtitles_en_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.7772648334503174,629,
|
||||
subtitles_en_literal_word,1,3,grep (ASCII),grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9744353294372559,629,LC_ALL=C
|
||||
subtitles_en_literal_word,1,3,grep (ASCII),grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9781327247619629,629,LC_ALL=C
|
||||
subtitles_en_literal_word,1,3,grep (ASCII),grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9798097610473633,629,LC_ALL=C
|
||||
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5965189933776855,629,
|
||||
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5960156917572021,629,
|
||||
subtitles_en_literal_word,1,3,rg,rg -nw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.5975723266601562,629,
|
||||
subtitles_en_literal_word,1,3,grep,grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9818971157073975,629,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_literal_word,1,3,grep,grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.9785251617431641,629,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_literal_word,1,3,grep,grep -anw Sherlock Holmes /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.977081298828125,629,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.7750890254974365,13,
|
||||
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.774017333984375,13,
|
||||
subtitles_en_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.783200740814209,13,
|
||||
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.5396409034729004,13,
|
||||
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.5404820442199707,13,
|
||||
subtitles_en_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,2.5400590896606445,13,
|
||||
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,10.072888612747192,48,
|
||||
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,10.075153350830078,48,
|
||||
subtitles_en_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,10.0713791847229,48,
|
||||
subtitles_en_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,7.734791278839111,13,
|
||||
subtitles_en_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,7.7345263957977295,13,
|
||||
subtitles_en_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,7.73199462890625,13,
|
||||
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.411367416381836,13,LC_ALL=C
|
||||
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.41072940826416,13,LC_ALL=C
|
||||
subtitles_en_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.414730072021484,13,LC_ALL=C
|
||||
subtitles_en_surrounding_words,1,3,rg,rg -n \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6052529811859131,317,
|
||||
subtitles_en_surrounding_words,1,3,rg,rg -n \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6049232482910156,317,
|
||||
subtitles_en_surrounding_words,1,3,rg,rg -n \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6045565605163574,317,
|
||||
subtitles_en_surrounding_words,1,3,grep,grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.2849924564361572,317,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_surrounding_words,1,3,grep,grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.2837722301483154,317,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_surrounding_words,1,3,grep,grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.2847650051116943,317,LC_ALL=en_US.UTF-8
|
||||
subtitles_en_surrounding_words,1,3,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6005992889404297,317,
|
||||
subtitles_en_surrounding_words,1,3,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.600543737411499,317,
|
||||
subtitles_en_surrounding_words,1,3,rg (ASCII),rg -n (?-u)\w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,0.6009273529052734,317,
|
||||
subtitles_en_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,11.664374113082886,323,
|
||||
subtitles_en_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,11.674306869506836,323,
|
||||
subtitles_en_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,11.657484769821167,323,
|
||||
subtitles_en_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.650290012359619,317,
|
||||
subtitles_en_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.651855707168579,317,
|
||||
subtitles_en_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,4.649921417236328,317,
|
||||
subtitles_en_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.2745037078857422,317,LC_ALL=C
|
||||
subtitles_en_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.275665521621704,317,LC_ALL=C
|
||||
subtitles_en_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Holmes\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.sample.en,1.273988962173462,317,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.9031155109405518,691,
|
||||
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.9021081924438477,691,
|
||||
subtitles_ru_alternate,1,3,rg (lines),rg -n Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.9028818607330322,691,
|
||||
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.8895978927612305,691,
|
||||
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.891357660293579,691,
|
||||
subtitles_ru_alternate,1,3,ag (lines),ag -s Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.892467975616455,691,
|
||||
subtitles_ru_alternate,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.7517757415771484,691,
|
||||
subtitles_ru_alternate,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.7550888061523438,691,
|
||||
subtitles_ru_alternate,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.7555651664733887,691,
|
||||
subtitles_ru_alternate,1,3,grep (lines),grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.51417875289917,691,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,grep (lines),grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.512972116470337,691,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,grep (lines),grep -E -an Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.507266521453857,691,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.300950288772583,691,
|
||||
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.2987852096557617,691,
|
||||
subtitles_ru_alternate,1,3,rg,rg Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3024635314941406,691,
|
||||
subtitles_ru_alternate,1,3,grep,grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,7.983739137649536,691,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,grep,grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,7.988446950912476,691,LC_ALL=C
|
||||
subtitles_ru_alternate,1,3,grep,grep -E -a Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,7.979671478271484,691,LC_ALL=C
|
||||
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.889382362365723,691,
|
||||
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.902577877044678,691,
|
||||
subtitles_ru_alternate_casei,1,3,ag (ASCII),ag -s -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,5.890571355819702,691,
|
||||
subtitles_ru_alternate_casei,1,3,ucg (ASCII),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.7548162937164307,691,
|
||||
subtitles_ru_alternate_casei,1,3,ucg (ASCII),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.747791051864624,691,
|
||||
subtitles_ru_alternate_casei,1,3,ucg (ASCII),ucg -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.7396674156188965,691,
|
||||
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.58053183555603,691,LC_ALL=C
|
||||
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.594751596450806,691,LC_ALL=C
|
||||
subtitles_ru_alternate_casei,1,3,grep (ASCII),grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.561670541763306,691,LC_ALL=C
|
||||
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.833597183227539,735,
|
||||
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.831137180328369,735,
|
||||
subtitles_ru_alternate_casei,1,3,rg,rg -n -i Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.830361843109131,735,
|
||||
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.723876953125,735,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.723239183425903,735,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_alternate_casei,1,3,grep,grep -E -ani Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.722000360488892,735,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.3252851963043213,583,
|
||||
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.3270294666290283,583,
|
||||
subtitles_ru_literal,1,3,rg,rg Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.32680773735046387,583,
|
||||
subtitles_ru_literal,1,3,pt,pt -N Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.932488679885864,583,
|
||||
subtitles_ru_literal,1,3,pt,pt -N Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.91330337524414,583,
|
||||
subtitles_ru_literal,1,3,pt,pt -N Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.911381006240845,583,
|
||||
subtitles_ru_literal,1,3,sift,sift Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,16.438587427139282,583,
|
||||
subtitles_ru_literal,1,3,sift,sift Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,16.412389755249023,583,
|
||||
subtitles_ru_literal,1,3,sift,sift Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,16.412444353103638,583,
|
||||
subtitles_ru_literal,1,3,grep,grep -a Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7865939140319824,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,grep,grep -a Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7889957427978516,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,grep,grep -a Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7923679351806641,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9255633354187012,583,
|
||||
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9285938739776611,583,
|
||||
subtitles_ru_literal,1,3,rg (lines),rg -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9274048805236816,583,
|
||||
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.4811036586761475,583,
|
||||
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.4785168170928955,583,
|
||||
subtitles_ru_literal,1,3,ag (lines),ag -s Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.484618186950684,583,
|
||||
subtitles_ru_literal,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7743628025054932,583,
|
||||
subtitles_ru_literal,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7731456756591797,583,
|
||||
subtitles_ru_literal,1,3,ucg (lines),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7749128341674805,583,
|
||||
subtitles_ru_literal,1,3,pt (lines),pt Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.931540250778198,583,
|
||||
subtitles_ru_literal,1,3,pt (lines),pt Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.935162782669067,583,
|
||||
subtitles_ru_literal,1,3,pt (lines),pt Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,12.949711561203003,583,
|
||||
subtitles_ru_literal,1,3,sift (lines),sift -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,17.183809995651245,583,
|
||||
subtitles_ru_literal,1,3,sift (lines),sift -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,17.19060492515564,583,
|
||||
subtitles_ru_literal,1,3,sift (lines),sift -n Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,17.17626404762268,583,
|
||||
subtitles_ru_literal,1,3,grep (lines),grep -an Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3023960590362549,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,grep (lines),grep -an Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.2992589473724365,583,LC_ALL=C
|
||||
subtitles_ru_literal,1,3,grep (lines),grep -an Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.299330711364746,583,LC_ALL=C
|
||||
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.1320264339447021,604,
|
||||
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.1323668956756592,604,
|
||||
subtitles_ru_literal_casei,1,3,rg,rg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.1354515552520752,604,
|
||||
subtitles_ru_literal_casei,1,3,grep,grep -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.194744348526001,604,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_literal_casei,1,3,grep,grep -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.190656423568726,604,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_literal_casei,1,3,grep,grep -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,8.18506383895874,604,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7826528549194336,583,LC_ALL=C
|
||||
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7846219539642334,583,LC_ALL=C
|
||||
subtitles_ru_literal_casei,1,3,grep (ASCII),grep -E -ai Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7846999168395996,583,LC_ALL=C
|
||||
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.734788179397583,604,
|
||||
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7333040237426758,604,
|
||||
subtitles_ru_literal_casei,1,3,rg (lines),rg -n -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.731860637664795,604,
|
||||
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7297205924987793,,
|
||||
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7314808368682861,,
|
||||
subtitles_ru_literal_casei,1,3,ag (lines) (ASCII),ag -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7289514541625977,,
|
||||
subtitles_ru_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7773914337158203,583,
|
||||
subtitles_ru_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.774536371231079,583,
|
||||
subtitles_ru_literal_casei,1,3,ucg (lines) (ASCII),ucg -i Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7740859985351562,583,
|
||||
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.3252553939819336,,
|
||||
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.32543301582336426,,
|
||||
subtitles_ru_literal_word,1,3,rg (ASCII),rg -n (?-u:\b)Шерлок Холмс(?-u:\b) /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.32512736320495605,,
|
||||
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7519562244415283,,
|
||||
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.752692699432373,,
|
||||
subtitles_ru_literal_word,1,3,ag (ASCII),ag -sw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.7524521350860596,,
|
||||
subtitles_ru_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7868170738220215,583,
|
||||
subtitles_ru_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.7786612510681152,583,
|
||||
subtitles_ru_literal_word,1,3,ucg (ASCII),ucg --nosmart-case Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.776214838027954,583,
|
||||
subtitles_ru_literal_word,1,3,grep (ASCII),grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.303652286529541,583,LC_ALL=C
|
||||
subtitles_ru_literal_word,1,3,grep (ASCII),grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3012151718139648,583,LC_ALL=C
|
||||
subtitles_ru_literal_word,1,3,grep (ASCII),grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.307457685470581,583,LC_ALL=C
|
||||
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9280951023101807,579,
|
||||
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9285900592803955,579,
|
||||
subtitles_ru_literal_word,1,3,rg,rg -nw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9288535118103027,579,
|
||||
subtitles_ru_literal_word,1,3,grep,grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3026466369628906,579,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_literal_word,1,3,grep,grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3016819953918457,579,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_literal_word,1,3,grep,grep -anw Шерлок Холмс /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.3006587028503418,579,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.895586729049683,41,
|
||||
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.914353132247925,41,
|
||||
subtitles_ru_no_literal,1,3,rg,rg -n \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,4.902980327606201,41,
|
||||
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,3.972637891769409,,
|
||||
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,3.9723849296569824,,
|
||||
subtitles_ru_no_literal,1,3,rg (ASCII),rg -n (?-u)\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,3.9723057746887207,,
|
||||
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.3936586380004883,,
|
||||
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.3987748622894287,,
|
||||
subtitles_ru_no_literal,1,3,ag (ASCII),ag -s \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.393911361694336,,
|
||||
subtitles_ru_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.8932065963745117,,
|
||||
subtitles_ru_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.8977222442626953,,
|
||||
subtitles_ru_no_literal,1,3,ucg (ASCII),ucg --nosmart-case \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.893040895462036,,
|
||||
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.4844722747802734,,LC_ALL=C
|
||||
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.485093116760254,,LC_ALL=C
|
||||
subtitles_ru_no_literal,1,3,grep (ASCII),grep -E -an \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5} /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.482459306716919,,LC_ALL=C
|
||||
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9564735889434814,278,
|
||||
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9561436176300049,278,
|
||||
subtitles_ru_surrounding_words,1,3,rg,rg -n \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,0.9558789730072021,278,
|
||||
subtitles_ru_surrounding_words,1,3,grep,grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.6620113849639893,278,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_surrounding_words,1,3,grep,grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.6624438762664795,278,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_surrounding_words,1,3,grep,grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.6610260009765625,278,LC_ALL=en_US.UTF-8
|
||||
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.4094629287719727,,
|
||||
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.409822702407837,,
|
||||
subtitles_ru_surrounding_words,1,3,ag (ASCII),ag -s \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.4094691276550293,,
|
||||
subtitles_ru_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.866976261138916,,
|
||||
subtitles_ru_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.8666067123413086,,
|
||||
subtitles_ru_surrounding_words,1,3,ucg (ASCII),ucg --nosmart-case \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,2.865297317504883,,
|
||||
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.602109670639038,,LC_ALL=C
|
||||
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.598329782485962,,LC_ALL=C
|
||||
subtitles_ru_surrounding_words,1,3,grep (ASCII),grep -E -an \w+\s+Холмс\s+\w+ /mnt/bench/subtitles/OpenSubtitles2016.raw.ru,1.5975282192230225,,LC_ALL=C
|
|
226
benchsuite/runs/2016-09-17-ubuntu1604-ec2/summary
Normal file
226
benchsuite/runs/2016-09-17-ubuntu1604-ec2/summary
Normal file
@@ -0,0 +1,226 @@
|
||||
linux_alternates (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
|
||||
-------------------------------------------------------------------------
|
||||
rg (ignore) 0.322 +/- 0.042 (lines: 68)
|
||||
ag (ignore) 1.754 +/- 0.006 (lines: 68)
|
||||
git grep (ignore) 0.502 +/- 0.004 (lines: 68)
|
||||
rg (whitelist)* 0.197 +/- 0.001 (lines: 68)*
|
||||
ucg (whitelist) 0.217 +/- 0.004 (lines: 68)
|
||||
|
||||
linux_alternates_casei (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
|
||||
-------------------------------------------------------------------------------
|
||||
rg (ignore) 0.372 +/- 0.096 (lines: 160)
|
||||
ag (ignore) 1.965 +/- 0.009 (lines: 160)
|
||||
git grep (ignore) 2.022 +/- 0.001 (lines: 160)
|
||||
rg (whitelist)* 0.222 +/- 0.001 (lines: 160)*
|
||||
ucg (whitelist) 0.524 +/- 0.005 (lines: 160)
|
||||
|
||||
linux_literal (pattern: PM_RESUME)
|
||||
----------------------------------
|
||||
rg (ignore) 0.348 +/- 0.054 (lines: 16)
|
||||
rg (ignore) (mmap) 1.597 +/- 0.013 (lines: 16)
|
||||
ag (ignore) (mmap) 1.590 +/- 0.003 (lines: 16)
|
||||
pt (ignore) 0.455 +/- 0.015 (lines: 16)
|
||||
sift (ignore) 0.630 +/- 0.001 (lines: 16)
|
||||
git grep (ignore) 0.344 +/- 0.004 (lines: 16)
|
||||
rg (whitelist)* 0.253 +/- 0.077 (lines: 16)
|
||||
ucg (whitelist) 0.222 +/- 0.005 (lines: 16)*
|
||||
|
||||
linux_literal_casei (pattern: PM_RESUME)
|
||||
----------------------------------------
|
||||
rg (ignore) 0.423 +/- 0.118 (lines: 370)
|
||||
rg (ignore) (mmap) 1.615 +/- 0.010 (lines: 370)
|
||||
ag (ignore) (mmap) 1.601 +/- 0.027 (lines: 370)
|
||||
sift (ignore) 0.804 +/- 0.003 (lines: 370)
|
||||
git grep (ignore) 0.346 +/- 0.004 (lines: 370)
|
||||
rg (whitelist) 0.234 +/- 0.032 (lines: 370)
|
||||
ucg (whitelist)* 0.220 +/- 0.008 (lines: 370)*
|
||||
|
||||
linux_literal_default (pattern: PM_RESUME)
|
||||
------------------------------------------
|
||||
rg 0.277 +/- 0.002 (lines: 16)
|
||||
ag 1.594 +/- 0.008 (lines: 16)
|
||||
ucg* 0.219 +/- 0.007 (lines: 16)*
|
||||
pt 0.439 +/- 0.024 (lines: 16)
|
||||
sift 0.344 +/- 0.014 (lines: 16)
|
||||
git grep 0.344 +/- 0.005 (lines: 16)
|
||||
|
||||
linux_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||
-----------------------------------------------------------------
|
||||
rg (ignore) 0.581 +/- 0.002 (lines: 490)
|
||||
rg (ignore) (ASCII) 0.408 +/- 0.008 (lines: 490)
|
||||
ag (ignore) (ASCII) 2.329 +/- 0.019 (lines: 766)
|
||||
sift (ignore) (ASCII) 25.756 +/- 0.113 (lines: 491)
|
||||
git grep (ignore) 26.344 +/- 0.005 (lines: 490)
|
||||
git grep (ignore) (ASCII) 4.152 +/- 0.004 (lines: 490)
|
||||
rg (whitelist) 0.502 +/- 0.008 (lines: 419)
|
||||
rg (whitelist) (ASCII)* 0.346 +/- 0.035 (lines: 419)*
|
||||
ucg (whitelist) (ASCII) 1.127 +/- 0.001 (lines: 416)
|
||||
|
||||
linux_re_literal_suffix (pattern: [A-Z]+_RESUME)
|
||||
------------------------------------------------
|
||||
rg (ignore) 0.398 +/- 0.046 (lines: 1652)
|
||||
ag (ignore) 1.889 +/- 0.011 (lines: 1652)
|
||||
sift (ignore) 10.260 +/- 0.246 (lines: 1652)
|
||||
git grep (ignore) 1.107 +/- 0.001 (lines: 1652)
|
||||
rg (whitelist)* 0.206 +/- 0.001 (lines: 1630)*
|
||||
ucg (whitelist) 0.301 +/- 0.001 (lines: 1630)
|
||||
|
||||
linux_unicode_greek (pattern: \p{Greek})
|
||||
----------------------------------------
|
||||
rg* 0.470 +/- 0.049 (lines: 23)*
|
||||
sift 7.715 +/- 0.125 (lines: 23)
|
||||
|
||||
linux_unicode_greek_casei (pattern: \p{Greek})
|
||||
----------------------------------------------
|
||||
rg 0.415 +/- 0.019 (lines: 103)
|
||||
sift* 0.002 +/- 0.000 (lines: 0)*
|
||||
|
||||
linux_unicode_word (pattern: \wAh)
|
||||
----------------------------------
|
||||
rg (ignore) 0.350 +/- 0.084 (lines: 186)
|
||||
rg (ignore) (ASCII) 0.354 +/- 0.075 (lines: 174)
|
||||
ag (ignore) (ASCII) 1.770 +/- 0.005 (lines: 174)
|
||||
sift (ignore) (ASCII) 11.016 +/- 0.138 (lines: 174)
|
||||
git grep (ignore) 13.051 +/- 0.028 (lines: 186)
|
||||
git grep (ignore) (ASCII) 2.988 +/- 0.001 (lines: 174)
|
||||
rg (whitelist) 0.242 +/- 0.040 (lines: 180)
|
||||
rg (whitelist) (ASCII)* 0.226 +/- 0.012 (lines: 168)
|
||||
ucg (ASCII) 0.225 +/- 0.002 (lines: 168)*
|
||||
|
||||
linux_word (pattern: PM_RESUME)
|
||||
-------------------------------
|
||||
rg (ignore) 0.329 +/- 0.035 (lines: 6)
|
||||
ag (ignore) 1.598 +/- 0.016 (lines: 6)
|
||||
sift (ignore) 7.759 +/- 0.117 (lines: 6)
|
||||
git grep (ignore) 0.344 +/- 0.008 (lines: 6)
|
||||
rg (whitelist)* 0.269 +/- 0.059 (lines: 6)
|
||||
ucg (whitelist) 0.221 +/- 0.002 (lines: 6)*
|
||||
|
||||
subtitles_en_alternate (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
|
||||
---------------------------------------------------------------------------------------------------------------
|
||||
rg (lines) 0.620 +/- 0.002 (lines: 848)
|
||||
ag (lines) 3.756 +/- 0.000 (lines: 848)
|
||||
ucg (lines) 1.447 +/- 0.003 (lines: 848)
|
||||
grep (lines) 3.411 +/- 0.002 (lines: 848)
|
||||
rg* 0.290 +/- 0.000 (lines: 848)*
|
||||
grep 2.955 +/- 0.001 (lines: 848)
|
||||
|
||||
subtitles_en_alternate_casei (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
|
||||
---------------------------------------------------------------------------------------------------------------------
|
||||
ag (ASCII) 5.171 +/- 0.003 (lines: 862)
|
||||
ucg (ASCII) 3.417 +/- 0.001 (lines: 862)
|
||||
grep (ASCII) 4.529 +/- 0.003 (lines: 862)
|
||||
rg* 2.722 +/- 0.000 (lines: 862)*
|
||||
grep 5.121 +/- 0.001 (lines: 862)
|
||||
|
||||
subtitles_en_literal (pattern: Sherlock Holmes)
|
||||
-----------------------------------------------
|
||||
rg* 0.268 +/- 0.000 (lines: 629)*
|
||||
pt 3.437 +/- 0.003 (lines: 629)
|
||||
sift 0.327 +/- 0.001 (lines: 629)
|
||||
grep 0.519 +/- 0.002 (lines: 629)
|
||||
rg (lines) 0.595 +/- 0.001 (lines: 629)
|
||||
ag (lines) 2.730 +/- 0.001 (lines: 629)
|
||||
ucg (lines) 0.776 +/- 0.000 (lines: 629)
|
||||
pt (lines) 3.434 +/- 0.001 (lines: 629)
|
||||
sift (lines) 0.757 +/- 0.003 (lines: 629)
|
||||
grep (lines) 0.971 +/- 0.001 (lines: 629)
|
||||
|
||||
subtitles_en_literal_casei (pattern: Sherlock Holmes)
|
||||
-----------------------------------------------------
|
||||
rg* 0.366 +/- 0.001 (lines: 642)*
|
||||
grep 4.083 +/- 0.005 (lines: 642)
|
||||
grep (ASCII) 0.614 +/- 0.001 (lines: 642)
|
||||
rg (lines) 0.695 +/- 0.001 (lines: 642)
|
||||
ag (lines) (ASCII) 2.772 +/- 0.001 (lines: 642)
|
||||
ucg (lines) (ASCII) 0.805 +/- 0.002 (lines: 642)
|
||||
|
||||
subtitles_en_literal_word (pattern: Sherlock Holmes)
|
||||
----------------------------------------------------
|
||||
rg (ASCII)* 0.596 +/- 0.001 (lines: 629)*
|
||||
ag (ASCII) 2.730 +/- 0.002 (lines: 629)
|
||||
ucg (ASCII) 0.781 +/- 0.003 (lines: 629)
|
||||
grep (ASCII) 0.977 +/- 0.003 (lines: 629)
|
||||
rg 0.597 +/- 0.001 (lines: 629)
|
||||
grep 0.979 +/- 0.002 (lines: 629)
|
||||
|
||||
subtitles_en_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||
----------------------------------------------------------------------------------------
|
||||
rg 2.777 +/- 0.005 (lines: 13)
|
||||
rg (ASCII)* 2.540 +/- 0.000 (lines: 13)*
|
||||
ag (ASCII) 10.073 +/- 0.002 (lines: 48)
|
||||
ucg (ASCII) 7.734 +/- 0.002 (lines: 13)
|
||||
grep (ASCII) 4.412 +/- 0.002 (lines: 13)
|
||||
|
||||
subtitles_en_surrounding_words (pattern: \w+\s+Holmes\s+\w+)
|
||||
------------------------------------------------------------
|
||||
rg 0.605 +/- 0.000 (lines: 317)
|
||||
grep 1.285 +/- 0.001 (lines: 317)
|
||||
rg (ASCII)* 0.601 +/- 0.000 (lines: 317)*
|
||||
ag (ASCII) 11.665 +/- 0.008 (lines: 323)
|
||||
ucg (ASCII) 4.651 +/- 0.001 (lines: 317)
|
||||
grep (ASCII) 1.275 +/- 0.001 (lines: 317)
|
||||
|
||||
subtitles_ru_alternate (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
rg (lines) 1.903 +/- 0.001 (lines: 691)
|
||||
ag (lines) 5.891 +/- 0.001 (lines: 691)
|
||||
ucg (lines) 2.754 +/- 0.002 (lines: 691)
|
||||
grep (lines) 8.511 +/- 0.004 (lines: 691)
|
||||
rg* 1.301 +/- 0.002 (lines: 691)*
|
||||
grep 7.984 +/- 0.004 (lines: 691)
|
||||
|
||||
subtitles_ru_alternate_casei (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
|
||||
-----------------------------------------------------------------------------------------------------------------
|
||||
ag (ASCII) 5.894 +/- 0.007 (lines: 691)
|
||||
ucg (ASCII)* 2.747 +/- 0.008 (lines: 691)*
|
||||
grep (ASCII) 8.579 +/- 0.017 (lines: 691)
|
||||
rg 4.832 +/- 0.002 (lines: 735)
|
||||
grep 8.723 +/- 0.001 (lines: 735)
|
||||
|
||||
subtitles_ru_literal (pattern: Шерлок Холмс)
|
||||
--------------------------------------------
|
||||
rg* 0.326 +/- 0.001 (lines: 583)*
|
||||
pt 12.919 +/- 0.012 (lines: 583)
|
||||
sift 16.421 +/- 0.015 (lines: 583)
|
||||
grep 0.789 +/- 0.003 (lines: 583)
|
||||
rg (lines) 0.927 +/- 0.002 (lines: 583)
|
||||
ag (lines) 4.481 +/- 0.003 (lines: 583)
|
||||
ucg (lines) 1.774 +/- 0.001 (lines: 583)
|
||||
pt (lines) 12.939 +/- 0.010 (lines: 583)
|
||||
sift (lines) 17.184 +/- 0.007 (lines: 583)
|
||||
grep (lines) 1.300 +/- 0.002 (lines: 583)
|
||||
|
||||
subtitles_ru_literal_casei (pattern: Шерлок Холмс)
|
||||
--------------------------------------------------
|
||||
rg 1.133 +/- 0.002 (lines: 604)
|
||||
grep 8.190 +/- 0.005 (lines: 604)
|
||||
grep (ASCII) 0.784 +/- 0.001 (lines: 583)
|
||||
rg (lines) 1.733 +/- 0.001 (lines: 604)
|
||||
ag (lines) (ASCII)* 0.730 +/- 0.001 (lines: 0)*
|
||||
ucg (lines) (ASCII) 1.775 +/- 0.002 (lines: 583)
|
||||
|
||||
subtitles_ru_literal_word (pattern: Шерлок Холмс)
|
||||
-------------------------------------------------
|
||||
rg (ASCII)* 0.325 +/- 0.000 (lines: 0)*
|
||||
ag (ASCII) 0.752 +/- 0.000 (lines: 0)
|
||||
ucg (ASCII) 1.781 +/- 0.006 (lines: 583)
|
||||
grep (ASCII) 1.304 +/- 0.003 (lines: 583)
|
||||
rg 0.929 +/- 0.000 (lines: 579)
|
||||
grep 1.302 +/- 0.001 (lines: 579)
|
||||
|
||||
subtitles_ru_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||
----------------------------------------------------------------------------------------
|
||||
rg 4.904 +/- 0.009 (lines: 41)
|
||||
rg (ASCII) 3.972 +/- 0.000 (lines: 0)
|
||||
ag (ASCII)* 2.395 +/- 0.003 (lines: 0)*
|
||||
ucg (ASCII) 2.895 +/- 0.003 (lines: 0)
|
||||
grep (ASCII) 2.484 +/- 0.001 (lines: 0)
|
||||
|
||||
subtitles_ru_surrounding_words (pattern: \w+\s+Холмс\s+\w+)
|
||||
-----------------------------------------------------------
|
||||
rg* 0.956 +/- 0.000 (lines: 278)*
|
||||
grep 1.662 +/- 0.001 (lines: 278)
|
||||
ag (ASCII) 2.410 +/- 0.000 (lines: 0)
|
||||
ucg (ASCII) 2.866 +/- 0.001 (lines: 0)
|
||||
grep (ASCII) 1.599 +/- 0.002 (lines: 0)
|
93
benchsuite/runs/2016-09-20-ubuntu1604-ec2/README.SETUP
Normal file
93
benchsuite/runs/2016-09-20-ubuntu1604-ec2/README.SETUP
Normal file
@@ -0,0 +1,93 @@
|
||||
Ubuntu 16.04 HVM AMI
|
||||
c3.2xlarge, Xeon E5-2680, 2.8 GHz, 8 CPUs, 16 GB memory, 80 GB SSD
|
||||
|
||||
# Generic system setup
|
||||
|
||||
mkfs.ext4 /dev/xvdb
|
||||
sudo mount /dev/xvdb /mnt
|
||||
sudo chown ubuntu /mnt
|
||||
sudo apt-get update
|
||||
sudo apt-get install \ # for building Linux kernel
|
||||
make gcc bc
|
||||
sudo apt-get install \ # for the silver searcher
|
||||
automake pkg-config zlib1g-dev liblzma-dev libpcre3 libpcre3-dev
|
||||
sudo apt-get install \ # for Universal Code Grep
|
||||
libtool libpcre2-8-0 libpcre2-dev
|
||||
sudo apt-get install \ # for sift and the platinum searcher
|
||||
go
|
||||
|
||||
# Get benchmark corpora
|
||||
|
||||
cd /mnt
|
||||
mkdir /mnt/bench
|
||||
git clone git://github.com/BurntSushi/ripgrep
|
||||
cd ripgrep/benchsuite
|
||||
./benchsuite --dir /mnt/bench/ --download all # takes around 15 minutes
|
||||
|
||||
# Install search tools
|
||||
mkdir /mnt/bin/
|
||||
|
||||
## ripgrep
|
||||
|
||||
cd /mnt
|
||||
mkdir ripgrep-bin
|
||||
cd ripgrep-bin
|
||||
curl -LO 'https://github.com/BurntSushi/ripgrep/releases/download/0.1.2/ripgrep-0.1.2-x86_64-unknown-linux-musl.tar.gz'
|
||||
cp ripgrep-0.1.2-x86_64-unknown-linux-musl/rg /mnt/bin/
|
||||
|
||||
## The Silver Searcher
|
||||
|
||||
cd /mnt
|
||||
git clone git://github.com/ggreer/the_silver_searcher
|
||||
cd the_silver_searcher
|
||||
git checkout cda635
|
||||
./build.sh
|
||||
cp ag /mnt/bin/
|
||||
|
||||
## Universal Code Grep
|
||||
|
||||
cd /mnt
|
||||
git clone git://github.com/gvansickle/ucg
|
||||
cd ucg
|
||||
git checkout 487bfb
|
||||
autoreconf -i
|
||||
./configure
|
||||
make
|
||||
cp ucg /mnt/bin/
|
||||
|
||||
## The Platinum Searcher
|
||||
|
||||
export GOPATH=/mnt/go
|
||||
go get github.com/monochromegane/the_platinum_searcher
|
||||
cd /mnt/go/src/github.com/monochromegane/the_platinum_searcher
|
||||
git checkout 509368
|
||||
go install github.com/monochromegane/the_platinum_searcher/cmd/...
|
||||
cp /mnt/go/bin/pt /mnt/bin/
|
||||
|
||||
## Sift
|
||||
|
||||
export GOPATH=/mnt/go
|
||||
go get github.com/svent/sift
|
||||
cd /mnt/go/src/github.com/svent/sift
|
||||
git checkout 2d175c
|
||||
go install
|
||||
cp /mnt/go/bin/sift /mnt/bin/
|
||||
|
||||
## 'git grep' and GNU grep
|
||||
|
||||
They are part of the standard Ubuntu install, and are pretty recent (as of
|
||||
September 2016).
|
||||
|
||||
$ git --version
|
||||
git version 2.7.4
|
||||
$ grep --version
|
||||
grep (GNU grep) 2.25
|
||||
|
||||
|
||||
# Running benchmarks
|
||||
|
||||
export PATH="/mnt/bin:$PATH"
|
||||
cd /mnt/ripgrep/benchsuite
|
||||
./benchsuite \
|
||||
--dir /mnt/bench/ --raw /mnt/bench/raw.csv --warmup-iter 3 --bench-iter 10
|
||||
# The above took around 120 minutes to run to completion.
|
1591
benchsuite/runs/2016-09-20-ubuntu1604-ec2/raw.csv
Normal file
1591
benchsuite/runs/2016-09-20-ubuntu1604-ec2/raw.csv
Normal file
File diff suppressed because it is too large
Load Diff
233
benchsuite/runs/2016-09-20-ubuntu1604-ec2/summary
Normal file
233
benchsuite/runs/2016-09-20-ubuntu1604-ec2/summary
Normal file
@@ -0,0 +1,233 @@
|
||||
linux_alternates (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
|
||||
-------------------------------------------------------------------------
|
||||
rg (ignore) 0.351 +/- 0.074 (lines: 68)
|
||||
ag (ignore) 1.747 +/- 0.005 (lines: 68)
|
||||
git grep (ignore) 0.501 +/- 0.003 (lines: 68)
|
||||
rg (whitelist)* 0.216 +/- 0.031 (lines: 68)
|
||||
ucg (whitelist) 0.214 +/- 0.008 (lines: 68)*
|
||||
|
||||
linux_alternates_casei (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
|
||||
-------------------------------------------------------------------------------
|
||||
rg (ignore) 0.391 +/- 0.078 (lines: 160)
|
||||
ag (ignore) 1.968 +/- 0.009 (lines: 160)
|
||||
git grep (ignore) 2.018 +/- 0.006 (lines: 160)
|
||||
rg (whitelist)* 0.222 +/- 0.001 (lines: 160)*
|
||||
ucg (whitelist) 0.522 +/- 0.002 (lines: 160)
|
||||
|
||||
linux_literal (pattern: PM_RESUME)
|
||||
----------------------------------
|
||||
rg (ignore) 0.334 +/- 0.053 (lines: 16)
|
||||
rg (ignore) (mmap) 1.611 +/- 0.009 (lines: 16)
|
||||
ag (ignore) (mmap) 1.588 +/- 0.011 (lines: 16)
|
||||
pt (ignore) 0.456 +/- 0.025 (lines: 16)
|
||||
sift (ignore) 0.630 +/- 0.004 (lines: 16)
|
||||
git grep (ignore) 0.345 +/- 0.007 (lines: 16)
|
||||
rg (whitelist)* 0.228 +/- 0.042 (lines: 16)
|
||||
ucg (whitelist) 0.218 +/- 0.007 (lines: 16)*
|
||||
|
||||
linux_literal_casei (pattern: PM_RESUME)
|
||||
----------------------------------------
|
||||
rg (ignore) 0.345 +/- 0.073 (lines: 370)
|
||||
rg (ignore) (mmap) 1.612 +/- 0.011 (lines: 370)
|
||||
ag (ignore) (mmap) 1.609 +/- 0.015 (lines: 370)
|
||||
pt (ignore) 17.204 +/- 0.126 (lines: 370)
|
||||
sift (ignore) 0.805 +/- 0.005 (lines: 370)
|
||||
git grep (ignore) 0.343 +/- 0.007 (lines: 370)
|
||||
rg (whitelist)* 0.222 +/- 0.021 (lines: 370)
|
||||
ucg (whitelist) 0.217 +/- 0.006 (lines: 370)*
|
||||
|
||||
linux_literal_default (pattern: PM_RESUME)
|
||||
------------------------------------------
|
||||
rg 0.349 +/- 0.104 (lines: 16)
|
||||
ag 1.589 +/- 0.009 (lines: 16)
|
||||
ucg* 0.218 +/- 0.007 (lines: 16)*
|
||||
pt 0.462 +/- 0.012 (lines: 16)
|
||||
sift 0.352 +/- 0.018 (lines: 16)
|
||||
git grep 0.342 +/- 0.005 (lines: 16)
|
||||
|
||||
linux_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||
-----------------------------------------------------------------
|
||||
rg (ignore) 0.577 +/- 0.003 (lines: 490)
|
||||
rg (ignore) (ASCII) 0.416 +/- 0.025 (lines: 490)
|
||||
ag (ignore) (ASCII) 2.339 +/- 0.010 (lines: 766)
|
||||
pt (ignore) (ASCII) 22.066 +/- 0.057 (lines: 490)
|
||||
sift (ignore) (ASCII) 25.563 +/- 0.108 (lines: 490)
|
||||
git grep (ignore) 26.382 +/- 0.044 (lines: 490)
|
||||
git grep (ignore) (ASCII) 4.153 +/- 0.010 (lines: 490)
|
||||
rg (whitelist) 0.503 +/- 0.011 (lines: 419)
|
||||
rg (whitelist) (ASCII)* 0.343 +/- 0.038 (lines: 419)*
|
||||
ucg (whitelist) (ASCII) 1.130 +/- 0.003 (lines: 416)
|
||||
|
||||
linux_re_literal_suffix (pattern: [A-Z]+_RESUME)
|
||||
------------------------------------------------
|
||||
rg (ignore) 0.318 +/- 0.034 (lines: 1652)
|
||||
ag (ignore) 1.899 +/- 0.008 (lines: 1652)
|
||||
pt (ignore) 13.713 +/- 0.241 (lines: 1652)
|
||||
sift (ignore) 10.172 +/- 0.186 (lines: 1652)
|
||||
git grep (ignore) 1.108 +/- 0.004 (lines: 1652)
|
||||
rg (whitelist)* 0.221 +/- 0.022 (lines: 1630)*
|
||||
ucg (whitelist) 0.301 +/- 0.001 (lines: 1630)
|
||||
|
||||
linux_unicode_greek (pattern: \p{Greek})
|
||||
----------------------------------------
|
||||
rg* 0.414 +/- 0.021 (lines: 23)*
|
||||
pt 12.745 +/- 0.166 (lines: 23)
|
||||
sift 7.767 +/- 0.264 (lines: 23)
|
||||
|
||||
linux_unicode_greek_casei (pattern: \p{Greek})
|
||||
----------------------------------------------
|
||||
rg 0.425 +/- 0.027 (lines: 103)
|
||||
pt 12.612 +/- 0.217 (lines: 23)
|
||||
sift* 0.002 +/- 0.000 (lines: 0)*
|
||||
|
||||
linux_unicode_word (pattern: \wAh)
|
||||
----------------------------------
|
||||
rg (ignore) 0.355 +/- 0.073 (lines: 186)
|
||||
rg (ignore) (ASCII) 0.329 +/- 0.060 (lines: 174)
|
||||
ag (ignore) (ASCII) 1.774 +/- 0.011 (lines: 174)
|
||||
pt (ignore) (ASCII) 14.180 +/- 0.180 (lines: 174)
|
||||
sift (ignore) (ASCII) 11.087 +/- 0.108 (lines: 174)
|
||||
git grep (ignore) 13.045 +/- 0.008 (lines: 186)
|
||||
git grep (ignore) (ASCII) 2.991 +/- 0.004 (lines: 174)
|
||||
rg (whitelist) 0.235 +/- 0.031 (lines: 180)
|
||||
rg (whitelist) (ASCII)* 0.225 +/- 0.023 (lines: 168)*
|
||||
ucg (ASCII) 0.229 +/- 0.007 (lines: 168)
|
||||
|
||||
linux_word (pattern: PM_RESUME)
|
||||
-------------------------------
|
||||
rg (ignore) 0.362 +/- 0.080 (lines: 6)
|
||||
ag (ignore) 1.603 +/- 0.009 (lines: 6)
|
||||
pt (ignore) 14.417 +/- 0.144 (lines: 6)
|
||||
sift (ignore) 7.840 +/- 0.123 (lines: 6)
|
||||
git grep (ignore) 0.341 +/- 0.005 (lines: 6)
|
||||
rg (whitelist)* 0.220 +/- 0.026 (lines: 6)*
|
||||
ucg (whitelist) 0.221 +/- 0.007 (lines: 6)
|
||||
|
||||
subtitles_en_alternate (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
|
||||
---------------------------------------------------------------------------------------------------------------
|
||||
rg (lines) 0.619 +/- 0.001 (lines: 848)
|
||||
ag (lines) 3.757 +/- 0.001 (lines: 848)
|
||||
ucg (lines) 1.479 +/- 0.002 (lines: 848)
|
||||
grep (lines) 3.412 +/- 0.004 (lines: 848)
|
||||
rg* 0.294 +/- 0.001 (lines: 848)*
|
||||
grep 2.955 +/- 0.003 (lines: 848)
|
||||
|
||||
subtitles_en_alternate_casei (pattern: Sherlock Holmes|John Watson|Irene Adler|Inspector Lestrade|Professor Moriarty)
|
||||
---------------------------------------------------------------------------------------------------------------------
|
||||
ag (ASCII) 5.170 +/- 0.004 (lines: 862)
|
||||
ucg (ASCII) 3.453 +/- 0.005 (lines: 862)
|
||||
grep (ASCII) 4.537 +/- 0.025 (lines: 862)
|
||||
rg* 2.724 +/- 0.002 (lines: 862)*
|
||||
grep 5.125 +/- 0.006 (lines: 862)
|
||||
|
||||
subtitles_en_literal (pattern: Sherlock Holmes)
|
||||
-----------------------------------------------
|
||||
rg* 0.269 +/- 0.000 (lines: 629)*
|
||||
pt 3.436 +/- 0.001 (lines: 629)
|
||||
sift 0.327 +/- 0.002 (lines: 629)
|
||||
grep 0.517 +/- 0.001 (lines: 629)
|
||||
rg (lines) 0.596 +/- 0.001 (lines: 629)
|
||||
ag (lines) 2.730 +/- 0.003 (lines: 629)
|
||||
ucg (lines) 0.814 +/- 0.003 (lines: 629)
|
||||
pt (lines) 3.438 +/- 0.004 (lines: 629)
|
||||
sift (lines) 0.759 +/- 0.003 (lines: 629)
|
||||
grep (lines) 0.971 +/- 0.001 (lines: 629)
|
||||
|
||||
subtitles_en_literal_casei (pattern: Sherlock Holmes)
|
||||
-----------------------------------------------------
|
||||
rg* 0.366 +/- 0.001 (lines: 642)*
|
||||
grep 4.084 +/- 0.005 (lines: 642)
|
||||
grep (ASCII) 0.614 +/- 0.001 (lines: 642)
|
||||
rg (lines) 0.696 +/- 0.002 (lines: 642)
|
||||
ag (lines) (ASCII) 2.775 +/- 0.004 (lines: 642)
|
||||
ucg (lines) (ASCII) 0.841 +/- 0.002 (lines: 642)
|
||||
|
||||
subtitles_en_literal_word (pattern: Sherlock Holmes)
|
||||
----------------------------------------------------
|
||||
rg (ASCII) 0.596 +/- 0.001 (lines: 629)
|
||||
ag (ASCII) 2.729 +/- 0.001 (lines: 629)
|
||||
ucg (ASCII) 0.810 +/- 0.002 (lines: 629)
|
||||
grep (ASCII) 0.970 +/- 0.000 (lines: 629)
|
||||
rg* 0.596 +/- 0.001 (lines: 629)*
|
||||
grep 0.972 +/- 0.003 (lines: 629)
|
||||
|
||||
subtitles_en_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||
----------------------------------------------------------------------------------------
|
||||
rg 2.777 +/- 0.003 (lines: 13)
|
||||
rg (ASCII)* 2.541 +/- 0.005 (lines: 13)*
|
||||
ag (ASCII) 10.076 +/- 0.005 (lines: 48)
|
||||
ucg (ASCII) 7.771 +/- 0.004 (lines: 13)
|
||||
grep (ASCII) 4.411 +/- 0.004 (lines: 13)
|
||||
|
||||
subtitles_en_surrounding_words (pattern: \w+\s+Holmes\s+\w+)
|
||||
------------------------------------------------------------
|
||||
rg 0.605 +/- 0.000 (lines: 317)
|
||||
grep 1.286 +/- 0.002 (lines: 317)
|
||||
rg (ASCII)* 0.602 +/- 0.000 (lines: 317)*
|
||||
ag (ASCII) 11.663 +/- 0.008 (lines: 323)
|
||||
ucg (ASCII) 4.690 +/- 0.002 (lines: 317)
|
||||
grep (ASCII) 1.276 +/- 0.002 (lines: 317)
|
||||
|
||||
subtitles_ru_alternate (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
rg (lines) 1.902 +/- 0.002 (lines: 691)
|
||||
ag (lines) 5.892 +/- 0.003 (lines: 691)
|
||||
ucg (lines) 2.864 +/- 0.006 (lines: 691)
|
||||
grep (lines) 8.511 +/- 0.005 (lines: 691)
|
||||
rg* 1.300 +/- 0.002 (lines: 691)*
|
||||
grep 7.994 +/- 0.017 (lines: 691)
|
||||
|
||||
subtitles_ru_alternate_casei (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
|
||||
-----------------------------------------------------------------------------------------------------------------
|
||||
ag (ASCII) 5.891 +/- 0.001 (lines: 691)
|
||||
ucg (ASCII)* 2.868 +/- 0.005 (lines: 691)*
|
||||
grep (ASCII) 8.572 +/- 0.009 (lines: 691)
|
||||
rg 4.834 +/- 0.004 (lines: 735)
|
||||
grep 8.729 +/- 0.004 (lines: 735)
|
||||
|
||||
subtitles_ru_literal (pattern: Шерлок Холмс)
|
||||
--------------------------------------------
|
||||
rg* 0.326 +/- 0.001 (lines: 583)*
|
||||
pt 12.922 +/- 0.010 (lines: 583)
|
||||
sift 16.424 +/- 0.010 (lines: 583)
|
||||
grep 0.786 +/- 0.003 (lines: 583)
|
||||
rg (lines) 0.927 +/- 0.002 (lines: 583)
|
||||
ag (lines) 4.481 +/- 0.003 (lines: 583)
|
||||
ucg (lines) 1.897 +/- 0.009 (lines: 583)
|
||||
pt (lines) 12.937 +/- 0.006 (lines: 583)
|
||||
sift (lines) 17.178 +/- 0.008 (lines: 583)
|
||||
grep (lines) 1.301 +/- 0.005 (lines: 583)
|
||||
|
||||
subtitles_ru_literal_casei (pattern: Шерлок Холмс)
|
||||
--------------------------------------------------
|
||||
rg 1.131 +/- 0.001 (lines: 604)
|
||||
grep 8.187 +/- 0.006 (lines: 604)
|
||||
grep (ASCII) 0.785 +/- 0.001 (lines: 583)
|
||||
rg (lines) 1.733 +/- 0.002 (lines: 604)
|
||||
ag (lines) (ASCII)* 0.729 +/- 0.001 (lines: 0)*
|
||||
ucg (lines) (ASCII) 1.896 +/- 0.005 (lines: 583)
|
||||
|
||||
subtitles_ru_literal_word (pattern: Шерлок Холмс)
|
||||
-------------------------------------------------
|
||||
rg (ASCII)* 0.325 +/- 0.000 (lines: 0)*
|
||||
ag (ASCII) 0.753 +/- 0.001 (lines: 0)
|
||||
ucg (ASCII) 1.891 +/- 0.004 (lines: 583)
|
||||
grep (ASCII) 1.303 +/- 0.004 (lines: 583)
|
||||
rg 0.929 +/- 0.001 (lines: 579)
|
||||
grep 1.304 +/- 0.003 (lines: 579)
|
||||
|
||||
subtitles_ru_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||
----------------------------------------------------------------------------------------
|
||||
rg 4.905 +/- 0.003 (lines: 41)
|
||||
rg (ASCII) 3.973 +/- 0.002 (lines: 0)
|
||||
ag (ASCII)* 2.395 +/- 0.004 (lines: 0)*
|
||||
ucg (ASCII) 3.006 +/- 0.005 (lines: 0)
|
||||
grep (ASCII) 2.483 +/- 0.005 (lines: 0)
|
||||
|
||||
subtitles_ru_surrounding_words (pattern: \w+\s+Холмс\s+\w+)
|
||||
-----------------------------------------------------------
|
||||
rg* 0.957 +/- 0.001 (lines: 278)*
|
||||
grep 1.660 +/- 0.002 (lines: 278)
|
||||
ag (ASCII) 2.411 +/- 0.001 (lines: 0)
|
||||
ucg (ASCII) 2.980 +/- 0.002 (lines: 0)
|
||||
grep (ASCII) 1.596 +/- 0.003 (lines: 0)
|
164
benchsuite/summary
Normal file
164
benchsuite/summary
Normal file
@@ -0,0 +1,164 @@
|
||||
linux_alternates (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
|
||||
-------------------------------------------------------------------------
|
||||
rg 0.239 +/- 0.008 (lines: 68)
|
||||
rg-novcs* 0.122 +/- 0.018 (lines: 68)*
|
||||
rg-novcs-mmap 0.394 +/- 0.004 (lines: 68)
|
||||
ag 0.497 +/- 0.009 (lines: 68)
|
||||
ag-novcs 0.554 +/- 0.125 (lines: 68)
|
||||
ucg 0.153 +/- 0.004 (lines: 68)
|
||||
git grep 0.254 +/- 0.011 (lines: 68)
|
||||
|
||||
linux_alternates_casei (pattern: ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT)
|
||||
-------------------------------------------------------------------------------
|
||||
rg 0.230 +/- 0.015 (lines: 160)
|
||||
rg-novcs* 0.126 +/- 0.003 (lines: 160)*
|
||||
rg-novcs-mmap 0.397 +/- 0.004 (lines: 160)
|
||||
ag 0.826 +/- 0.377 (lines: 160)
|
||||
ag-novcs 0.592 +/- 0.047 (lines: 160)
|
||||
ucg 0.238 +/- 0.002 (lines: 160)
|
||||
git grep 0.920 +/- 0.054 (lines: 160)
|
||||
|
||||
linux_literal (pattern: PM_RESUME)
|
||||
----------------------------------
|
||||
rg 0.218 +/- 0.003 (lines: 16)
|
||||
rg-novcs* 0.109 +/- 0.011 (lines: 16)*
|
||||
rg-novcs-mmap 0.389 +/- 0.007 (lines: 16)
|
||||
ag 0.512 +/- 0.005 (lines: 16)
|
||||
ag-novcs 0.876 +/- 0.370 (lines: 16)
|
||||
ucg 0.163 +/- 0.004 (lines: 16)
|
||||
git grep 0.194 +/- 0.001 (lines: 16)
|
||||
pt 0.197 +/- 0.019 (lines: 16)
|
||||
sift 0.142 +/- 0.002 (lines: 16)
|
||||
|
||||
linux_literal_casei (pattern: PM_RESUME)
|
||||
----------------------------------------
|
||||
rg 0.267 +/- 0.054 (lines: 370)
|
||||
rg-novcs* 0.122 +/- 0.015 (lines: 399)*
|
||||
rg-novcs-mmap 0.403 +/- 0.010 (lines: 399)
|
||||
ag 0.428 +/- 0.026 (lines: 370)
|
||||
ag-novcs 0.440 +/- 0.019 (lines: 399)
|
||||
ucg 0.157 +/- 0.002 (lines: 370)
|
||||
git grep 0.183 +/- 0.005 (lines: 370)
|
||||
sift 0.203 +/- 0.005 (lines: 399)
|
||||
|
||||
linux_literal_default (pattern: PM_RESUME)
|
||||
------------------------------------------
|
||||
rg 0.232 +/- 0.024 (lines: 16)
|
||||
ag 0.460 +/- 0.056 (lines: 16)
|
||||
ucg 0.165 +/- 0.001 (lines: 16)
|
||||
git grep 0.187 +/- 0.020 (lines: 16)
|
||||
pt 0.156 +/- 0.001 (lines: 16)
|
||||
sift* 0.117 +/- 0.000 (lines: 16)*
|
||||
|
||||
linux_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||
-----------------------------------------------------------------
|
||||
rg 0.393 +/- 0.008 (lines: 490)
|
||||
rg-whitelist 0.325 +/- 0.002 (lines: 419)
|
||||
rg (no Unicode) 0.304 +/- 0.026 (lines: 490)
|
||||
rg-whitelist (no Unicode)* 0.227 +/- 0.009 (lines: 419)*
|
||||
ag (no Unicode) 0.809 +/- 0.102 (lines: 766)
|
||||
ag-novcs (no Unicode) 0.703 +/- 0.012 (lines: 767)
|
||||
ucg (no Unicode) 0.443 +/- 0.002 (lines: 416)
|
||||
git grep 9.576 +/- 0.465 (lines: 490)
|
||||
git grep (no Unicode) 2.046 +/- 0.236 (lines: 490)
|
||||
sift (no Unicode) 8.894 +/- 0.086 (lines: 491)
|
||||
|
||||
linux_re_literal_suffix (pattern: [A-Z]+_RESUME)
|
||||
------------------------------------------------
|
||||
rg 0.216 +/- 0.001 (lines: 1652)
|
||||
rg-novcs* 0.102 +/- 0.002 (lines: 1653)*
|
||||
rg-novcs-mmap 0.401 +/- 0.015 (lines: 1653)
|
||||
ag 1.399 +/- 0.556 (lines: 1652)
|
||||
ag-novcs 0.523 +/- 0.016 (lines: 1653)
|
||||
ucg 0.140 +/- 0.003 (lines: 1630)
|
||||
git grep 0.561 +/- 0.027 (lines: 1652)
|
||||
sift 4.092 +/- 0.164 (lines: 1653)
|
||||
|
||||
linux_unicode_greek (pattern: \p{Greek})
|
||||
----------------------------------------
|
||||
rg* 0.291 +/- 0.006 (lines: 23)*
|
||||
sift 2.822 +/- 0.016 (lines: 23)
|
||||
|
||||
linux_unicode_greek_casei (pattern: \p{Greek})
|
||||
----------------------------------------------
|
||||
rg* 0.324 +/- 0.037 (lines: 103)*
|
||||
sift 2.925 +/- 0.053 (lines: 23)
|
||||
|
||||
linux_unicode_word (pattern: \wAh)
|
||||
----------------------------------
|
||||
rg 0.235 +/- 0.033 (lines: 186)
|
||||
rg (no Unicode) 0.234 +/- 0.002 (lines: 174)
|
||||
rg-novcs* 0.112 +/- 0.003 (lines: 186)*
|
||||
rg-novcs-mmap 0.400 +/- 0.005 (lines: 186)
|
||||
ag (no Unicode) 0.937 +/- 0.004 (lines: 174)
|
||||
ag-novcs (no Unicode) 0.922 +/- 0.030 (lines: 174)
|
||||
ucg (no Unicode) 0.175 +/- 0.005 (lines: 168)
|
||||
git grep 4.972 +/- 0.028 (lines: 186)
|
||||
git grep (no Unicode) 1.566 +/- 0.038 (lines: 174)
|
||||
sift (no Unicode) 4.195 +/- 0.141 (lines: 174)
|
||||
|
||||
linux_word (pattern: PM_RESUME)
|
||||
-------------------------------
|
||||
rg 0.224 +/- 0.014 (lines: 6)
|
||||
rg-novcs* 0.116 +/- 0.028 (lines: 6)*
|
||||
rg-novcs-mmap 0.395 +/- 0.007 (lines: 6)
|
||||
ag 0.571 +/- 0.141 (lines: 6)
|
||||
ag-novcs 0.437 +/- 0.030 (lines: 6)
|
||||
ucg 0.163 +/- 0.002 (lines: 6)
|
||||
git grep 0.180 +/- 0.014 (lines: 6)
|
||||
sift 3.161 +/- 0.058 (lines: 6)
|
||||
|
||||
subtitles_en_literal (pattern: Sherlock Holmes)
|
||||
-----------------------------------------------
|
||||
rg 0.487 +/- 0.058 (lines: 629)
|
||||
rg (no line numbers)* 0.237 +/- 0.028 (lines: 629)*
|
||||
ag 2.002 +/- 0.003 (lines: 629)
|
||||
ucg 0.721 +/- 0.052 (lines: 629)
|
||||
grep 1.010 +/- 0.021 (lines: 629)
|
||||
grep (no line numbers) 0.560 +/- 0.046 (lines: 629)
|
||||
pt 1.669 +/- 0.020 (lines: 629)
|
||||
pt (no line numbers) 1.597 +/- 0.092 (lines: 629)
|
||||
sift 0.684 +/- 0.085 (lines: 629)
|
||||
sift (no line numbers) 0.270 +/- 0.006 (lines: 629)
|
||||
|
||||
subtitles_ru_alternate (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
rg 1.664 +/- 0.092 (lines: 691)
|
||||
rg (no line numbers)* 1.290 +/- 0.053 (lines: 691)*
|
||||
ucg 2.382 +/- 0.016 (lines: 691)
|
||||
grep 6.861 +/- 0.127 (lines: 691)
|
||||
grep (no line numbers) 6.426 +/- 0.156 (lines: 691)
|
||||
|
||||
subtitles_ru_alternate_casei (pattern: Шерлок Холмс|Джон Уотсон|Ирен Адлер|инспектор Лестрейд|профессор Мориарти)
|
||||
-----------------------------------------------------------------------------------------------------------------
|
||||
rg 4.119 +/- 0.102 (lines: 735)
|
||||
ucg (not Unicode)* 2.344 +/- 0.098 (lines: 691)*
|
||||
grep 6.902 +/- 0.113 (lines: 735)
|
||||
grep (not Unicode) 6.902 +/- 0.096 (lines: 691)
|
||||
|
||||
subtitles_ru_literal (pattern: Шерлок Холмс)
|
||||
--------------------------------------------
|
||||
rg 0.852 +/- 0.038 (lines: 583)
|
||||
rg (no line numbers)* 0.304 +/- 0.009 (lines: 583)*
|
||||
ag 3.010 +/- 0.132 (lines: 583)
|
||||
ucg 1.557 +/- 0.048 (lines: 583)
|
||||
grep 1.335 +/- 0.003 (lines: 583)
|
||||
grep (no line numbers) 0.876 +/- 0.003 (lines: 583)
|
||||
pt 5.319 +/- 0.339 (lines: 583)
|
||||
pt (no line numbers) 5.325 +/- 0.171 (lines: 583)
|
||||
sift 6.876 +/- 0.060 (lines: 583)
|
||||
sift (no line numbers) 6.311 +/- 0.065 (lines: 583)
|
||||
|
||||
subtitles_ru_literal_casei (pattern: Шерлок Холмс)
|
||||
--------------------------------------------------
|
||||
rg 1.635 +/- 0.153 (lines: 604)
|
||||
ucg (not Unicode) 1.571 +/- 0.042 (lines: 583)
|
||||
grep 6.729 +/- 0.241 (lines: 604)
|
||||
grep (not Unicode)* 1.209 +/- 0.115 (lines: 583)*
|
||||
|
||||
subtitles_ru_no_literal (pattern: \w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5}\s+\w{5})
|
||||
----------------------------------------------------------------------------------------
|
||||
rg 3.834 +/- 0.081 (lines: 41)
|
||||
rg (no line numbers) 3.443 +/- 0.025 (lines: 41)
|
||||
ucg (no Unicode) 2.246 +/- 0.096 (lines: 0)
|
||||
grep (no Unicode)* 1.951 +/- 0.107 (lines: 0)*
|
@@ -6,23 +6,22 @@ set -ex
|
||||
|
||||
# Generate artifacts for release
|
||||
mk_artifacts() {
|
||||
RUSTFLAGS="-C target-feature=+ssse3" cargo build --target $TARGET --release --features simd-accel
|
||||
RUSTFLAGS="-C target-feature=+ssse3" \
|
||||
cargo build --target $TARGET --release --features simd-accel
|
||||
}
|
||||
|
||||
mk_tarball() {
|
||||
# create a "staging" directory
|
||||
local td=$(mktempd)
|
||||
local out_dir=$(pwd)
|
||||
local name="${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}"
|
||||
mkdir "$td/$name"
|
||||
|
||||
# TODO update this part to copy the artifacts that make sense for your project
|
||||
# NOTE All Cargo build artifacts will be under the 'target/$TARGET/{debug,release}'
|
||||
cp target/$TARGET/release/xrep $td
|
||||
cp target/$TARGET/release/rg "$td/$name/"
|
||||
cp {README.md,UNLICENSE,COPYING,LICENSE-MIT} "$td/$name/"
|
||||
|
||||
pushd $td
|
||||
|
||||
# release tarball will look like 'rust-everywhere-v1.2.3-x86_64-unknown-linux-gnu.tar.gz'
|
||||
tar czf $out_dir/${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}.tar.gz *
|
||||
|
||||
tar czf "$out_dir/$name.tar.gz" *
|
||||
popd
|
||||
rm -r $td
|
||||
}
|
||||
|
28
ci/script.sh
28
ci/script.sh
@@ -11,42 +11,20 @@ disable_cross_doctests() {
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
brew install gnu-sed --default-names
|
||||
fi
|
||||
|
||||
find src -name '*.rs' -type f | xargs sed -i -e 's:\(//.\s*```\):\1 ignore,:g'
|
||||
fi
|
||||
}
|
||||
|
||||
# TODO modify this function as you see fit
|
||||
# PROTIP Always pass `--target $TARGET` to cargo commands, this makes cargo output build artifacts
|
||||
# to target/$TARGET/{debug,release} which can reduce the number of needed conditionals in the
|
||||
# `before_deploy`/packaging phase
|
||||
run_test_suite() {
|
||||
case $TARGET in
|
||||
# configure emulation for transparent execution of foreign binaries
|
||||
aarch64-unknown-linux-gnu)
|
||||
export QEMU_LD_PREFIX=/usr/aarch64-linux-gnu
|
||||
;;
|
||||
arm*-unknown-linux-gnueabihf)
|
||||
export QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -z "$QEMU_LD_PREFIX" ]; then
|
||||
# Run tests on a single thread when using QEMU user emulation
|
||||
export RUST_TEST_THREADS=1
|
||||
fi
|
||||
|
||||
cargo build --target $TARGET --verbose
|
||||
cargo test --target $TARGET
|
||||
cargo test --target $TARGET --verbose
|
||||
|
||||
# sanity check the file type
|
||||
file target/$TARGET/debug/xrep
|
||||
file target/$TARGET/debug/rg
|
||||
}
|
||||
|
||||
main() {
|
||||
disable_cross_doctests
|
||||
# disable_cross_doctests
|
||||
run_test_suite
|
||||
}
|
||||
|
||||
|
25
ci/sha256.sh
Normal file
25
ci/sha256.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo "Usage: $(basename $0) version" >&2
|
||||
exit 1
|
||||
fi
|
||||
version="$1"
|
||||
|
||||
# Linux and Darwin builds.
|
||||
for arch in i686 x86_64; do
|
||||
for target in apple-darwin unknown-linux-musl; do
|
||||
url="https://github.com/BurntSushi/ripgrep/releases/download/$version/ripgrep-$version-$arch-$target.tar.gz"
|
||||
sha=$(curl -sfSL "$url" | sha256sum)
|
||||
echo "$version-$arch-$target $sha"
|
||||
done
|
||||
done
|
||||
|
||||
# Source.
|
||||
for ext in zip tar.gz; do
|
||||
url="https://github.com/BurntSushi/ripgrep/archive/$version.$ext"
|
||||
sha=$(curl -sfSL "$url" | sha256sum)
|
||||
echo "source.$ext $sha"
|
||||
done
|
1
compile
1
compile
@@ -1,4 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
export RUSTFLAGS="-C target-feature=+ssse3"
|
||||
# export RUSTFLAGS="-C target-cpu=native"
|
||||
cargo build --release --features simd-accel
|
||||
|
11
ctags.rust
11
ctags.rust
@@ -1,11 +0,0 @@
|
||||
--langdef=Rust
|
||||
--langmap=Rust:.rs
|
||||
--regex-Rust=/^[ \t]*(#\[[^\]]\][ \t]*)*(pub[ \t]+)?(extern[ \t]+)?("[^"]+"[ \t]+)?(unsafe[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\6/f,functions,function definitions/
|
||||
--regex-Rust=/^[ \t]*(pub[ \t]+)?type[ \t]+([a-zA-Z0-9_]+)/\2/T,types,type definitions/
|
||||
--regex-Rust=/^[ \t]*(pub[ \t]+)?enum[ \t]+([a-zA-Z0-9_]+)/\2/g,enum,enumeration names/
|
||||
--regex-Rust=/^[ \t]*(pub[ \t]+)?struct[ \t]+([a-zA-Z0-9_]+)/\2/s,structure names/
|
||||
--regex-Rust=/^[ \t]*(pub[ \t]+)?mod[ \t]+([a-zA-Z0-9_]+)/\2/m,modules,module names/
|
||||
--regex-Rust=/^[ \t]*(pub[ \t]+)?static[ \t]+([a-zA-Z0-9_]+)/\2/c,consts,static constants/
|
||||
--regex-Rust=/^[ \t]*(pub[ \t]+)?trait[ \t]+([a-zA-Z0-9_]+)/\2/t,traits,traits/
|
||||
--regex-Rust=/^[ \t]*(pub[ \t]+)?impl([ \t\n]+<.*>)?[ \t]+([a-zA-Z0-9_]+)/\3/i,impls,trait implementations/
|
||||
--regex-Rust=/^[ \t]*macro_rules![ \t]+([a-zA-Z0-9_]+)/\1/d,macros,macro definitions/
|
@@ -1,20 +1,20 @@
|
||||
[package]
|
||||
publish = false
|
||||
name = "grep"
|
||||
version = "0.1.0" #:version
|
||||
version = "0.1.2" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
Fast line oriented regex searching as a library.
|
||||
"""
|
||||
documentation = "https://github.com/BurntSushi/xrep"
|
||||
homepage = "https://github.com/BurntSushi/xrep"
|
||||
repository = "https://github.com/BurntSushi/xrep"
|
||||
documentation = "http://burntsushi.net/rustdoc/grep/"
|
||||
homepage = "https://github.com/BurntSushi/ripgrep"
|
||||
repository = "https://github.com/BurntSushi/ripgrep"
|
||||
readme = "README.md"
|
||||
keywords = ["regex", "grep", "egrep", "search", "pattern"]
|
||||
license = "Unlicense/MIT"
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
memchr = "0.1"
|
||||
memmap = "0.2"
|
||||
regex = "0.1.75"
|
||||
regex = "0.1.77"
|
||||
regex-syntax = "0.3.5"
|
||||
|
4
grep/README.md
Normal file
4
grep/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
grep
|
||||
----
|
||||
This is a *library* that provides grep-style line-by-line regex searching (with
|
||||
comparable performance to `grep` itself).
|
@@ -4,6 +4,8 @@
|
||||
A fast line oriented regex searcher.
|
||||
*/
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate memchr;
|
||||
extern crate regex;
|
||||
extern crate regex_syntax as syntax;
|
||||
@@ -17,6 +19,7 @@ pub use search::{Grep, GrepBuilder, Iter, Match};
|
||||
mod literals;
|
||||
mod nonl;
|
||||
mod search;
|
||||
mod word_boundary;
|
||||
|
||||
/// Result is a convenient type alias that fixes the type of the error to
|
||||
/// the `Error` type defined in this crate.
|
||||
@@ -60,7 +63,7 @@ impl fmt::Display for Error {
|
||||
match *self {
|
||||
Error::Regex(ref err) => err.fmt(f),
|
||||
Error::LiteralNotAllowed(chr) => {
|
||||
write!(f, "Literal '{}' not allowed.", chr)
|
||||
write!(f, "Literal {:?} not allowed.", chr)
|
||||
}
|
||||
Error::__Nonexhaustive => unreachable!(),
|
||||
}
|
||||
|
@@ -1,13 +1,22 @@
|
||||
/*!
|
||||
The literals module is responsible for extracting *inner* literals out of the
|
||||
AST of a regular expression. Normally this is the job of the regex engine
|
||||
itself, but the regex engine doesn't look for inner literals. Since we're doing
|
||||
line based searching, we can use them, so we need to do it ourselves.
|
||||
|
||||
Note that this implementation is incredibly suspicious. We need something more
|
||||
principled.
|
||||
*/
|
||||
use std::cmp;
|
||||
use std::iter;
|
||||
|
||||
use regex::bytes::Regex;
|
||||
use syntax::{
|
||||
Expr, Literals, Lit,
|
||||
Repeater,
|
||||
ByteClass, ByteRange, CharClass, ClassRange, Repeater,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct LiteralSets {
|
||||
prefixes: Literals,
|
||||
suffixes: Literals,
|
||||
@@ -27,6 +36,7 @@ impl LiteralSets {
|
||||
|
||||
pub fn to_regex(&self) -> Option<Regex> {
|
||||
if self.prefixes.all_complete() && !self.prefixes.is_empty() {
|
||||
debug!("literal prefixes detected: {:?}", self.prefixes);
|
||||
// When this is true, the regex engine will do a literal scan.
|
||||
return None;
|
||||
}
|
||||
@@ -56,13 +66,27 @@ impl LiteralSets {
|
||||
if suf_lcs.len() > lit.len() {
|
||||
lit = suf_lcs;
|
||||
}
|
||||
if req.len() > lit.len() {
|
||||
if req_lits.len() == 1 && req.len() > lit.len() {
|
||||
lit = req;
|
||||
}
|
||||
if lit.is_empty() {
|
||||
|
||||
// Special case: if we detected an alternation of inner required
|
||||
// literals and its longest literal is bigger than the longest
|
||||
// prefix/suffix, then choose the alternation. In practice, this
|
||||
// helps with case insensitive matching, which can generate lots of
|
||||
// inner required literals.
|
||||
let any_empty = req_lits.iter().any(|lit| lit.is_empty());
|
||||
if req.len() > lit.len() && req_lits.len() > 1 && !any_empty {
|
||||
debug!("required literals found: {:?}", req_lits);
|
||||
let alts: Vec<String> =
|
||||
req_lits.into_iter().map(|x| bytes_to_regex(x)).collect();
|
||||
// Literals always compile.
|
||||
Some(Regex::new(&alts.join("|")).unwrap())
|
||||
} else if lit.is_empty() {
|
||||
None
|
||||
} else {
|
||||
// Literals always compile.
|
||||
debug!("required literal found: {:?}", show(lit));
|
||||
Some(Regex::new(&bytes_to_regex(lit)).unwrap())
|
||||
}
|
||||
}
|
||||
@@ -75,14 +99,30 @@ fn union_required(expr: &Expr, lits: &mut Literals) {
|
||||
let s: String = chars.iter().cloned().collect();
|
||||
lits.cross_add(s.as_bytes());
|
||||
}
|
||||
Literal { casei: true, .. } => {
|
||||
lits.cut();
|
||||
Literal { ref chars, casei: true } => {
|
||||
for &c in chars {
|
||||
let cls = CharClass::new(vec![
|
||||
ClassRange { start: c, end: c },
|
||||
]).case_fold();
|
||||
if !lits.add_char_class(&cls) {
|
||||
lits.cut();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
LiteralBytes { ref bytes, casei: false } => {
|
||||
lits.cross_add(bytes);
|
||||
}
|
||||
LiteralBytes { casei: true, .. } => {
|
||||
lits.cut();
|
||||
LiteralBytes { ref bytes, casei: true } => {
|
||||
for &b in bytes {
|
||||
let cls = ByteClass::new(vec![
|
||||
ByteRange { start: b, end: b },
|
||||
]).case_fold();
|
||||
if !lits.add_byte_class(&cls) {
|
||||
lits.cut();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Class(_) => {
|
||||
lits.cut();
|
||||
@@ -205,3 +245,18 @@ fn bytes_to_regex(bs: &[u8]) -> String {
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
/// Converts arbitrary bytes to a nice string.
|
||||
fn show(bs: &[u8]) -> String {
|
||||
// Why aren't we using this to feed to the regex? Doesn't really matter
|
||||
// I guess. ---AG
|
||||
use std::ascii::escape_default;
|
||||
use std::str;
|
||||
|
||||
let mut nice = String::new();
|
||||
for &b in bs {
|
||||
let part: Vec<u8> = escape_default(b).collect();
|
||||
nice.push_str(str::from_utf8(&part).unwrap());
|
||||
}
|
||||
nice
|
||||
}
|
||||
|
@@ -10,6 +10,10 @@ use {Error, Result};
|
||||
/// If `byte` is not an ASCII character (i.e., greater than `0x7F`), then this
|
||||
/// function panics.
|
||||
pub fn remove(expr: Expr, byte: u8) -> Result<Expr> {
|
||||
// TODO(burntsushi): There is a bug in this routine where only `\n` is
|
||||
// handled correctly. Namely, `AnyChar` and `AnyByte` need to be translated
|
||||
// to proper character classes instead of the special `AnyCharNoNL` and
|
||||
// `AnyByteNoNL` classes.
|
||||
use syntax::Expr::*;
|
||||
assert!(byte <= 0x7F);
|
||||
let chr = byte as char;
|
||||
|
@@ -4,6 +4,8 @@ use syntax;
|
||||
|
||||
use literals::LiteralSets;
|
||||
use nonl;
|
||||
use syntax::Expr;
|
||||
use word_boundary::strip_unicode_word_boundaries;
|
||||
use Result;
|
||||
|
||||
/// A matched line.
|
||||
@@ -127,22 +129,35 @@ impl GrepBuilder {
|
||||
pub fn build(self) -> Result<Grep> {
|
||||
let expr = try!(self.parse());
|
||||
let literals = LiteralSets::create(&expr);
|
||||
let re = try!(
|
||||
RegexBuilder::new(&expr.to_string())
|
||||
.case_insensitive(self.opts.case_insensitive)
|
||||
.multi_line(true)
|
||||
.unicode(true)
|
||||
.size_limit(self.opts.size_limit)
|
||||
.dfa_size_limit(self.opts.dfa_size_limit)
|
||||
.compile()
|
||||
);
|
||||
let re = try!(self.regex(&expr));
|
||||
let required = literals.to_regex().or_else(|| {
|
||||
let expr = match strip_unicode_word_boundaries(&expr) {
|
||||
None => return None,
|
||||
Some(expr) => expr,
|
||||
};
|
||||
debug!("Stripped Unicode word boundaries. New AST:\n{:?}", expr);
|
||||
self.regex(&expr).ok()
|
||||
});
|
||||
Ok(Grep {
|
||||
re: re,
|
||||
required: literals.to_regex(),
|
||||
required: required,
|
||||
opts: self.opts,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new regex from the given expression with the current
|
||||
/// configuration.
|
||||
fn regex(&self, expr: &Expr) -> Result<Regex> {
|
||||
RegexBuilder::new(&expr.to_string())
|
||||
.case_insensitive(self.opts.case_insensitive)
|
||||
.multi_line(true)
|
||||
.unicode(true)
|
||||
.size_limit(self.opts.size_limit)
|
||||
.dfa_size_limit(self.opts.dfa_size_limit)
|
||||
.compile()
|
||||
.map_err(From::from)
|
||||
}
|
||||
|
||||
/// Parses the underlying pattern and ensures the pattern can never match
|
||||
/// the line terminator.
|
||||
fn parse(&self) -> Result<syntax::Expr> {
|
||||
@@ -152,6 +167,7 @@ impl GrepBuilder {
|
||||
.unicode(true)
|
||||
.case_insensitive(self.opts.case_insensitive)
|
||||
.parse(&self.pattern));
|
||||
debug!("regex ast:\n{:#?}", expr);
|
||||
Ok(try!(nonl::remove(expr, self.opts.line_terminator)))
|
||||
}
|
||||
}
|
||||
@@ -194,7 +210,7 @@ impl Grep {
|
||||
let (prevnl, nextnl) = self.find_line(buf, e, e);
|
||||
match self.re.shortest_match(&buf[prevnl..nextnl]) {
|
||||
None => {
|
||||
start = nextnl + 1;
|
||||
start = nextnl;
|
||||
continue;
|
||||
}
|
||||
Some(_) => {
|
||||
@@ -253,7 +269,7 @@ impl<'b, 's> Iterator for Iter<'b, 's> {
|
||||
self.start = self.buf.len();
|
||||
return None;
|
||||
}
|
||||
self.start = mat.end + 1;
|
||||
self.start = mat.end;
|
||||
Some(mat)
|
||||
}
|
||||
}
|
||||
|
54
grep/src/word_boundary.rs
Normal file
54
grep/src/word_boundary.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use syntax::Expr;
|
||||
|
||||
/// Strips Unicode word boundaries from the given expression.
|
||||
///
|
||||
/// The key invariant this maintains is that the expression returned will match
|
||||
/// *at least* every where the expression given will match. Namely, a match of
|
||||
/// the returned expression can report false positives but it will never report
|
||||
/// false negatives.
|
||||
///
|
||||
/// If no word boundaries could be stripped, then None is returned.
|
||||
pub fn strip_unicode_word_boundaries(expr: &Expr) -> Option<Expr> {
|
||||
// The real reason we do this is because Unicode word boundaries are the
|
||||
// one thing that Rust's regex DFA engine can't handle. When it sees a
|
||||
// Unicode word boundary among non-ASCII text, it falls back to one of the
|
||||
// slower engines. We work around this limitation by attempting to use
|
||||
// a regex to find candidate matches without a Unicode word boundary. We'll
|
||||
// only then use the full (and slower) regex to confirm a candidate as a
|
||||
// match or not during search.
|
||||
use syntax::Expr::*;
|
||||
|
||||
match *expr {
|
||||
Concat(ref es) if !es.is_empty() => {
|
||||
let first = is_unicode_word_boundary(&es[0]);
|
||||
let last = is_unicode_word_boundary(es.last().unwrap());
|
||||
// Be careful not to strip word boundaries if there are no other
|
||||
// expressions to match.
|
||||
match (first, last) {
|
||||
(true, false) if es.len() > 1 => {
|
||||
Some(Concat(es[1..].to_vec()))
|
||||
}
|
||||
(false, true) if es.len() > 1 => {
|
||||
Some(Concat(es[..es.len() - 1].to_vec()))
|
||||
}
|
||||
(true, true) if es.len() > 2 => {
|
||||
Some(Concat(es[1..es.len() - 1].to_vec()))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the given expression is a Unicode word boundary.
|
||||
fn is_unicode_word_boundary(expr: &Expr) -> bool {
|
||||
use syntax::Expr::*;
|
||||
|
||||
match *expr {
|
||||
WordBoundary => true,
|
||||
NotWordBoundary => true,
|
||||
Group { ref e, .. } => is_unicode_word_boundary(e),
|
||||
_ => false,
|
||||
}
|
||||
}
|
35
pkg/archlinux/PKGBUILD
Normal file
35
pkg/archlinux/PKGBUILD
Normal file
@@ -0,0 +1,35 @@
|
||||
# Contributor: Andrew Gallant <jamslam@gmail.com>
|
||||
# Maintainer: Andrew Gallant
|
||||
pkgname=ripgrep
|
||||
pkgver=0.1.11
|
||||
pkgrel=1
|
||||
pkgdesc="A search tool that combines the usability of The Silver Searcher with the raw speed of grep."
|
||||
arch=('i686' 'x86_64')
|
||||
url="https://github.com/BurntSushi/ripgrep"
|
||||
license=('UNLICENSE')
|
||||
makedepends=('cargo')
|
||||
source=("https://github.com/BurntSushi/$pkgname/archive/$pkgver.tar.gz")
|
||||
sha256sums=('d29beb1a43a263d75ce4ef23a07253ed6ea306b14ffb5b37bc4972fb5d98238c')
|
||||
|
||||
build() {
|
||||
cd "$pkgname-$pkgver"
|
||||
if command -v rustup > /dev/null 2>&1; then
|
||||
RUSTFLAGS="-C target-cpu=native" rustup run nightly \
|
||||
cargo build --release --features simd-accel
|
||||
elif rustc --version | grep -q nightly; then
|
||||
RUSTFLAGS="-C target-cpu=native" \
|
||||
cargo build --release --features simd-accel
|
||||
else
|
||||
cargo build --release
|
||||
fi
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$pkgname-$pkgver"
|
||||
|
||||
install -Dm755 "target/release/rg" "$pkgdir/usr/bin/rg"
|
||||
install -Dm644 "README-NEW.md" "$pkgdir/usr/share/doc/ripgrep/README.md"
|
||||
install -Dm644 "COPYING" "$pkgdir/usr/share/doc/ripgrep/COPYING"
|
||||
install -Dm644 "LICENSE-MIT" "$pkgdir/usr/share/doc/ripgrep/LICENSE-MIT"
|
||||
install -Dm644 "UNLICENSE" "$pkgdir/usr/share/doc/ripgrep/UNLICENSE"
|
||||
}
|
18
pkg/brew/ripgrep.rb
Normal file
18
pkg/brew/ripgrep.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
require 'formula'
|
||||
class Ripgrep < Formula
|
||||
version '0.1.8'
|
||||
desc "Search tool like grep and The Silver Searcher."
|
||||
homepage "https://github.com/BurntSushi/ripgrep"
|
||||
|
||||
if Hardware::CPU.is_64_bit?
|
||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
|
||||
sha256 "893e0e7fac88ebbef024829466fafef6eae5b1060273bbfca3806090e660b06b"
|
||||
else
|
||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-i686-apple-darwin.tar.gz"
|
||||
sha256 "2296c8081a2bfe28b43dea4326a9e8ce9c2821fd628a1ca366e824aceddc5fad"
|
||||
end
|
||||
|
||||
def install
|
||||
bin.install "rg"
|
||||
end
|
||||
end
|
@@ -1 +0,0 @@
|
||||
au BufWritePost *.rs silent!make ctags > /dev/null 2>&1
|
272
src/args.rs
272
src/args.rs
@@ -9,14 +9,22 @@ use grep::{Grep, GrepBuilder};
|
||||
use log;
|
||||
use num_cpus;
|
||||
use regex;
|
||||
use term::Terminal;
|
||||
#[cfg(not(windows))]
|
||||
use term;
|
||||
#[cfg(windows)]
|
||||
use term::WinConsole;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use atty;
|
||||
use gitignore::{Gitignore, GitignoreBuilder};
|
||||
use ignore::Ignore;
|
||||
use out::Out;
|
||||
use out::{Out, ColoredTerminal};
|
||||
use printer::Printer;
|
||||
use search::{InputBuffer, Searcher};
|
||||
use sys;
|
||||
use search_buffer::BufferSearcher;
|
||||
use search_stream::{InputBuffer, Searcher};
|
||||
#[cfg(windows)]
|
||||
use terminal_win::WindowsBuffer;
|
||||
use types::{FileTypeDef, Types, TypesBuilder};
|
||||
use walk;
|
||||
|
||||
@@ -27,13 +35,14 @@ use Result;
|
||||
/// If you've never heard of Docopt before, see: http://docopt.org
|
||||
/// (TL;DR: The CLI parser is generated from the usage string below.)
|
||||
const USAGE: &'static str = "
|
||||
Usage: xrep [options] <pattern> [<path> ...]
|
||||
xrep [options] --files [<path> ...]
|
||||
xrep [options] --type-list
|
||||
xrep --help
|
||||
xrep --version
|
||||
Usage: rg [options] -e PATTERN ... [<path> ...]
|
||||
rg [options] <pattern> [<path> ...]
|
||||
rg [options] --files [<path> ...]
|
||||
rg [options] --type-list
|
||||
rg --help
|
||||
rg --version
|
||||
|
||||
xrep is like the silver searcher and grep, but faster than both.
|
||||
rg combines the usability of The Silver Searcher with the raw speed of grep.
|
||||
|
||||
Common options:
|
||||
-a, --text Search binary files as if they were text.
|
||||
@@ -41,6 +50,11 @@ Common options:
|
||||
--color WHEN Whether to use coloring in match.
|
||||
Valid values are never, always or auto.
|
||||
[default: auto]
|
||||
-e, --regexp PATTERN ... Use PATTERN to search. This option can be
|
||||
provided multiple times, where all patterns
|
||||
given are searched.
|
||||
-F, --fixed-strings Treat the pattern as a literal string instead of
|
||||
a regular expression.
|
||||
-g, --glob GLOB ... Include or exclude files for searching that
|
||||
match the given glob. This always overrides any
|
||||
other ignore logic. Multiple glob flags may be
|
||||
@@ -60,6 +74,12 @@ Common options:
|
||||
to list all available types.
|
||||
-T, --type-not TYPE ... Do not search files matching TYPE. Multiple
|
||||
not-type flags may be provided.
|
||||
-u, --unrestricted ... Reduce the level of 'smart' searching. A
|
||||
single -u doesn't respect .gitignore (etc.)
|
||||
files. Two -u flags will search hidden files
|
||||
and directories. Three -u flags will search
|
||||
binary files. -uu is equivalent to grep -r,
|
||||
and -uuu is equivalent to grep -a -r.
|
||||
-v, --invert-match Invert matching.
|
||||
-w, --word-regexp Only show matches surrounded by word boundaries.
|
||||
This is equivalent to putting \\b before and
|
||||
@@ -75,6 +95,11 @@ Less common options:
|
||||
-C, --context NUM
|
||||
Show NUM lines before and after each match.
|
||||
|
||||
--column
|
||||
Show column numbers (1 based) in output. This only shows the column
|
||||
numbers for the first match on each line. Note that this doesn't try
|
||||
to account for Unicode. One byte is equal to one column.
|
||||
|
||||
--context-separator ARG
|
||||
The string to use when separating non-continuous context lines. Escape
|
||||
sequences may be used. [default: --]
|
||||
@@ -97,17 +122,23 @@ Less common options:
|
||||
Don't show any file name heading.
|
||||
|
||||
--hidden
|
||||
Search hidden directories and files.
|
||||
Search hidden directories and files. (Hidden directories and files are
|
||||
skipped by default.)
|
||||
|
||||
-L, --follow
|
||||
Follow symlinks.
|
||||
|
||||
--line-terminator ARG
|
||||
The byte to use for a line terminator. Escape sequences may be used.
|
||||
[default: \\n]
|
||||
--mmap
|
||||
Search using memory maps when possible. This is enabled by default
|
||||
when ripgrep thinks it will be faster. (Note that mmap searching
|
||||
doesn't currently support the various context related options.)
|
||||
|
||||
--no-mmap
|
||||
Never use memory maps, even when they might be faster.
|
||||
|
||||
--no-ignore
|
||||
Don't respect ignore files (.gitignore, .xrepignore, etc.)
|
||||
Don't respect ignore files (.gitignore, .rgignore, etc.)
|
||||
This implies --no-ignore-parent.
|
||||
|
||||
--no-ignore-parent
|
||||
Don't respect ignore files in parent directories.
|
||||
@@ -115,15 +146,12 @@ Less common options:
|
||||
-p, --pretty
|
||||
Alias for --color=always --heading -n.
|
||||
|
||||
-Q, --literal
|
||||
Treat the pattern as a literal string instead of a regular expression.
|
||||
|
||||
-j, --threads ARG
|
||||
The number of threads to use. Defaults to the number of logical CPUs
|
||||
(capped at 6). [default: 0]
|
||||
|
||||
--version
|
||||
Show the version number of xrep and exit.
|
||||
Show the version number of ripgrep and exit.
|
||||
|
||||
File type management options:
|
||||
--type-list
|
||||
@@ -138,7 +166,7 @@ File type management options:
|
||||
";
|
||||
|
||||
/// RawArgs are the args as they are parsed from Docopt. They aren't used
|
||||
/// directly by the rest of xrep.
|
||||
/// directly by the rest of ripgrep.
|
||||
#[derive(Debug, RustcDecodable)]
|
||||
pub struct RawArgs {
|
||||
arg_pattern: String,
|
||||
@@ -146,6 +174,7 @@ pub struct RawArgs {
|
||||
flag_after_context: usize,
|
||||
flag_before_context: usize,
|
||||
flag_color: String,
|
||||
flag_column: bool,
|
||||
flag_context: usize,
|
||||
flag_context_separator: String,
|
||||
flag_count: bool,
|
||||
@@ -158,14 +187,16 @@ pub struct RawArgs {
|
||||
flag_ignore_case: bool,
|
||||
flag_invert_match: bool,
|
||||
flag_line_number: bool,
|
||||
flag_line_terminator: String,
|
||||
flag_literal: bool,
|
||||
flag_fixed_strings: bool,
|
||||
flag_mmap: bool,
|
||||
flag_no_heading: bool,
|
||||
flag_no_ignore: bool,
|
||||
flag_no_ignore_parent: bool,
|
||||
flag_no_line_number: bool,
|
||||
flag_no_mmap: bool,
|
||||
flag_pretty: bool,
|
||||
flag_quiet: bool,
|
||||
flag_regexp: Vec<String>,
|
||||
flag_replace: Option<String>,
|
||||
flag_text: bool,
|
||||
flag_threads: usize,
|
||||
@@ -174,6 +205,7 @@ pub struct RawArgs {
|
||||
flag_type_list: bool,
|
||||
flag_type_add: Vec<String>,
|
||||
flag_type_clear: Vec<String>,
|
||||
flag_unrestricted: u32,
|
||||
flag_with_filename: bool,
|
||||
flag_word_regexp: bool,
|
||||
}
|
||||
@@ -186,17 +218,20 @@ pub struct Args {
|
||||
after_context: usize,
|
||||
before_context: usize,
|
||||
color: bool,
|
||||
column: bool,
|
||||
context_separator: Vec<u8>,
|
||||
count: bool,
|
||||
eol: u8,
|
||||
files: bool,
|
||||
follow: bool,
|
||||
glob_overrides: Option<Gitignore>,
|
||||
grep: Grep,
|
||||
heading: bool,
|
||||
hidden: bool,
|
||||
ignore_case: bool,
|
||||
invert_match: bool,
|
||||
line_number: bool,
|
||||
mmap: bool,
|
||||
no_ignore: bool,
|
||||
no_ignore_parent: bool,
|
||||
quiet: bool,
|
||||
@@ -210,24 +245,14 @@ pub struct Args {
|
||||
}
|
||||
|
||||
impl RawArgs {
|
||||
/// Convert arguments parsed into a configuration used by xrep.
|
||||
/// Convert arguments parsed into a configuration used by ripgrep.
|
||||
fn to_args(&self) -> Result<Args> {
|
||||
let pattern = {
|
||||
let pattern =
|
||||
if self.flag_literal {
|
||||
regex::quote(&self.arg_pattern)
|
||||
} else {
|
||||
self.arg_pattern.clone()
|
||||
};
|
||||
if self.flag_word_regexp {
|
||||
format!(r"\b{}\b", pattern)
|
||||
} else {
|
||||
pattern
|
||||
}
|
||||
};
|
||||
let pattern = self.pattern();
|
||||
let paths =
|
||||
if self.arg_path.is_empty() {
|
||||
if sys::stdin_is_atty() {
|
||||
if atty::on_stdin()
|
||||
|| self.flag_files
|
||||
|| self.flag_type_list {
|
||||
vec![Path::new("./").to_path_buf()]
|
||||
} else {
|
||||
vec![Path::new("-").to_path_buf()]
|
||||
@@ -243,15 +268,22 @@ impl RawArgs {
|
||||
} else {
|
||||
(self.flag_after_context, self.flag_before_context)
|
||||
};
|
||||
let eol = {
|
||||
let eol = unescape(&self.flag_line_terminator);
|
||||
if eol.is_empty() {
|
||||
errored!("Empty line terminator is not allowed.");
|
||||
} else if eol.len() > 1 {
|
||||
errored!("Line terminators are limited to exactly 1 byte.");
|
||||
}
|
||||
eol[0]
|
||||
};
|
||||
let mmap =
|
||||
if before_context > 0 || after_context > 0 || self.flag_no_mmap {
|
||||
false
|
||||
} else if self.flag_mmap {
|
||||
true
|
||||
} else if cfg!(windows) {
|
||||
// On Windows, memory maps appear faster than read calls. Neat.
|
||||
true
|
||||
} else {
|
||||
// If we're only searching a few paths and all of them are
|
||||
// files, then memory maps are probably faster.
|
||||
paths.len() <= 10 && paths.iter().all(|p| p.is_file())
|
||||
};
|
||||
if mmap {
|
||||
debug!("will try to use memory maps");
|
||||
}
|
||||
let glob_overrides =
|
||||
if self.flag_glob.is_empty() {
|
||||
None
|
||||
@@ -265,16 +297,17 @@ impl RawArgs {
|
||||
};
|
||||
let threads =
|
||||
if self.flag_threads == 0 {
|
||||
cmp::min(6, num_cpus::get())
|
||||
cmp::min(8, num_cpus::get())
|
||||
} else {
|
||||
self.flag_threads
|
||||
};
|
||||
let color =
|
||||
if self.flag_color == "auto" {
|
||||
sys::stdout_is_atty() || self.flag_pretty
|
||||
atty::on_stdout() || self.flag_pretty
|
||||
} else {
|
||||
self.flag_color == "always"
|
||||
};
|
||||
let eol = b'\n';
|
||||
let mut with_filename = self.flag_with_filename;
|
||||
if !with_filename {
|
||||
with_filename = paths.len() > 1 || paths[0].is_dir();
|
||||
@@ -283,28 +316,42 @@ impl RawArgs {
|
||||
btypes.add_defaults();
|
||||
try!(self.add_types(&mut btypes));
|
||||
let types = try!(btypes.build());
|
||||
let grep = try!(
|
||||
GrepBuilder::new(&pattern)
|
||||
.case_insensitive(self.flag_ignore_case)
|
||||
.line_terminator(eol)
|
||||
.build()
|
||||
);
|
||||
let no_ignore = self.flag_no_ignore || self.flag_unrestricted >= 1;
|
||||
let hidden = self.flag_hidden || self.flag_unrestricted >= 2;
|
||||
let text = self.flag_text || self.flag_unrestricted >= 3;
|
||||
let mut args = Args {
|
||||
pattern: pattern,
|
||||
paths: paths,
|
||||
after_context: after_context,
|
||||
before_context: before_context,
|
||||
color: color,
|
||||
column: self.flag_column,
|
||||
context_separator: unescape(&self.flag_context_separator),
|
||||
count: self.flag_count,
|
||||
eol: eol,
|
||||
files: self.flag_files,
|
||||
follow: self.flag_follow,
|
||||
glob_overrides: glob_overrides,
|
||||
grep: grep,
|
||||
heading: !self.flag_no_heading && self.flag_heading,
|
||||
hidden: self.flag_hidden,
|
||||
hidden: hidden,
|
||||
ignore_case: self.flag_ignore_case,
|
||||
invert_match: self.flag_invert_match,
|
||||
line_number: !self.flag_no_line_number && self.flag_line_number,
|
||||
no_ignore: self.flag_no_ignore,
|
||||
no_ignore_parent: self.flag_no_ignore_parent,
|
||||
mmap: mmap,
|
||||
no_ignore: no_ignore,
|
||||
no_ignore_parent:
|
||||
// --no-ignore implies --no-ignore-parent
|
||||
self.flag_no_ignore_parent || no_ignore,
|
||||
quiet: self.flag_quiet,
|
||||
replace: self.flag_replace.clone().map(|s| s.into_bytes()),
|
||||
text: self.flag_text,
|
||||
text: text,
|
||||
threads: threads,
|
||||
type_defs: btypes.definitions(),
|
||||
type_list: self.flag_type_list,
|
||||
@@ -312,7 +359,7 @@ impl RawArgs {
|
||||
with_filename: with_filename,
|
||||
};
|
||||
// If stdout is a tty, then apply some special default options.
|
||||
if sys::stdout_is_atty() || self.flag_pretty {
|
||||
if atty::on_stdout() || self.flag_pretty {
|
||||
if !self.flag_no_line_number && !args.count {
|
||||
args.line_number = true;
|
||||
}
|
||||
@@ -334,10 +381,38 @@ impl RawArgs {
|
||||
types.select(ty);
|
||||
}
|
||||
for ty in &self.flag_type_not {
|
||||
types.select_not(ty);
|
||||
types.negate(ty);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pattern(&self) -> String {
|
||||
if !self.flag_regexp.is_empty() {
|
||||
if self.flag_fixed_strings {
|
||||
self.flag_regexp.iter().cloned().map(|lit| {
|
||||
self.word_pattern(regex::quote(&lit))
|
||||
}).collect::<Vec<String>>().join("|")
|
||||
} else {
|
||||
self.flag_regexp.iter().cloned().map(|pat| {
|
||||
self.word_pattern(pat)
|
||||
}).collect::<Vec<String>>().join("|")
|
||||
}
|
||||
} else {
|
||||
if self.flag_fixed_strings {
|
||||
self.word_pattern(regex::quote(&self.arg_pattern))
|
||||
} else {
|
||||
self.word_pattern(self.arg_pattern.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn word_pattern(&self, s: String) -> String {
|
||||
if self.flag_word_regexp {
|
||||
format!(r"\b{}\b", s)
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Args {
|
||||
@@ -345,13 +420,26 @@ impl Args {
|
||||
///
|
||||
/// If a CLI usage error occurred, then exit the process and print a usage
|
||||
/// or error message. Similarly, if the user requested the version of
|
||||
/// xrep, then print the version and exit.
|
||||
/// ripgrep, then print the version and exit.
|
||||
///
|
||||
/// Also, initialize a global logger.
|
||||
pub fn parse() -> Result<Args> {
|
||||
// Get all of the arguments, being careful to require valid UTF-8.
|
||||
let mut argv = vec![];
|
||||
for arg in env::args_os() {
|
||||
match arg.into_string() {
|
||||
Ok(s) => argv.push(s),
|
||||
Err(s) => {
|
||||
errored!("Argument '{}' is not valid UTF-8. \
|
||||
Use hex escape sequences to match arbitrary \
|
||||
bytes in a pattern (e.g., \\xFF).",
|
||||
s.to_string_lossy());
|
||||
}
|
||||
}
|
||||
}
|
||||
let raw: RawArgs =
|
||||
Docopt::new(USAGE)
|
||||
.and_then(|d| d.version(Some(version())).decode())
|
||||
.and_then(|d| d.argv(argv).version(Some(version())).decode())
|
||||
.unwrap_or_else(|e| e.exit());
|
||||
|
||||
let mut logb = env_logger::LogBuilder::new();
|
||||
@@ -367,7 +455,7 @@ impl Args {
|
||||
raw.to_args().map_err(From::from)
|
||||
}
|
||||
|
||||
/// Returns true if xrep should print the files it will search and exit
|
||||
/// Returns true if ripgrep should print the files it will search and exit
|
||||
/// (but not do any actual searching).
|
||||
pub fn files(&self) -> bool {
|
||||
self.files
|
||||
@@ -378,12 +466,8 @@ impl Args {
|
||||
/// basic searching of regular expressions in a single buffer.
|
||||
///
|
||||
/// The pattern and other flags are taken from the command line.
|
||||
pub fn grep(&self) -> Result<Grep> {
|
||||
GrepBuilder::new(&self.pattern)
|
||||
.case_insensitive(self.ignore_case)
|
||||
.line_terminator(self.eol)
|
||||
.build()
|
||||
.map_err(From::from)
|
||||
pub fn grep(&self) -> Grep {
|
||||
self.grep.clone()
|
||||
}
|
||||
|
||||
/// Creates a new input buffer that is used in searching.
|
||||
@@ -393,10 +477,16 @@ impl Args {
|
||||
inp
|
||||
}
|
||||
|
||||
/// Whether we should prefer memory maps for searching or not.
|
||||
pub fn mmap(&self) -> bool {
|
||||
self.mmap
|
||||
}
|
||||
|
||||
/// Create a new printer of individual search results that writes to the
|
||||
/// writer given.
|
||||
pub fn printer<W: Send + io::Write>(&self, wtr: W) -> Printer<W> {
|
||||
let mut p = Printer::new(wtr, self.color)
|
||||
pub fn printer<W: Terminal + Send>(&self, wtr: W) -> Printer<W> {
|
||||
let mut p = Printer::new(wtr)
|
||||
.column(self.column)
|
||||
.context_separator(self.context_separator.clone())
|
||||
.eol(self.eol)
|
||||
.heading(self.heading)
|
||||
@@ -410,8 +500,8 @@ impl Args {
|
||||
|
||||
/// Create a new printer of search results for an entire file that writes
|
||||
/// to the writer given.
|
||||
pub fn out<W: io::Write>(&self, wtr: W) -> Out<W> {
|
||||
let mut out = Out::new(wtr);
|
||||
pub fn out(&self) -> Out {
|
||||
let mut out = Out::new(self.color);
|
||||
if self.heading && !self.count {
|
||||
out = out.file_separator(b"".to_vec());
|
||||
} else if self.before_context > 0 || self.after_context > 0 {
|
||||
@@ -420,6 +510,32 @@ impl Args {
|
||||
out
|
||||
}
|
||||
|
||||
/// Create a new buffer for use with searching.
|
||||
#[cfg(not(windows))]
|
||||
pub fn outbuf(&self) -> ColoredTerminal<term::TerminfoTerminal<Vec<u8>>> {
|
||||
ColoredTerminal::new(vec![], self.color)
|
||||
}
|
||||
|
||||
/// Create a new buffer for use with searching.
|
||||
#[cfg(windows)]
|
||||
pub fn outbuf(&self) -> ColoredTerminal<WindowsBuffer> {
|
||||
ColoredTerminal::new_buffer(self.color)
|
||||
}
|
||||
|
||||
/// Create a new buffer for use with searching.
|
||||
#[cfg(not(windows))]
|
||||
pub fn stdout(
|
||||
&self,
|
||||
) -> ColoredTerminal<term::TerminfoTerminal<io::BufWriter<io::Stdout>>> {
|
||||
ColoredTerminal::new(io::BufWriter::new(io::stdout()), self.color)
|
||||
}
|
||||
|
||||
/// Create a new buffer for use with searching.
|
||||
#[cfg(windows)]
|
||||
pub fn stdout(&self) -> ColoredTerminal<WinConsole<io::Stdout>> {
|
||||
ColoredTerminal::new_stdout(self.color)
|
||||
}
|
||||
|
||||
/// Return the paths that should be searched.
|
||||
pub fn paths(&self) -> &[PathBuf] {
|
||||
&self.paths
|
||||
@@ -428,7 +544,7 @@ impl Args {
|
||||
/// Create a new line based searcher whose configuration is taken from the
|
||||
/// command line. This searcher supports a dizzying array of features:
|
||||
/// inverted matching, line counting, context control and more.
|
||||
pub fn searcher<'a, R: io::Read, W: Send + io::Write>(
|
||||
pub fn searcher<'a, R: io::Read, W: Send + Terminal>(
|
||||
&self,
|
||||
inp: &'a mut InputBuffer,
|
||||
printer: &'a mut Printer<W>,
|
||||
@@ -446,6 +562,24 @@ impl Args {
|
||||
.text(self.text)
|
||||
}
|
||||
|
||||
/// Create a new line based searcher whose configuration is taken from the
|
||||
/// command line. This search operates on an entire file all once (which
|
||||
/// may have been memory mapped).
|
||||
pub fn searcher_buffer<'a, W: Send + Terminal>(
|
||||
&self,
|
||||
printer: &'a mut Printer<W>,
|
||||
grep: &'a Grep,
|
||||
path: &'a Path,
|
||||
buf: &'a [u8],
|
||||
) -> BufferSearcher<'a, W> {
|
||||
BufferSearcher::new(printer, grep, path, buf)
|
||||
.count(self.count)
|
||||
.eol(self.eol)
|
||||
.line_number(self.line_number)
|
||||
.invert_match(self.invert_match)
|
||||
.text(self.text)
|
||||
}
|
||||
|
||||
/// Returns the number of worker search threads that should be used.
|
||||
pub fn threads(&self) -> usize {
|
||||
self.threads
|
||||
@@ -456,8 +590,8 @@ impl Args {
|
||||
&self.type_defs
|
||||
}
|
||||
|
||||
/// Returns true if xrep should print the type definitions currently loaded
|
||||
/// and then exit.
|
||||
/// Returns true if ripgrep should print the type definitions currently
|
||||
/// loaded and then exit.
|
||||
pub fn type_list(&self) -> bool {
|
||||
self.type_list
|
||||
}
|
||||
|
@@ -1,24 +1,23 @@
|
||||
/*!
|
||||
This io module contains various platform specific functions for detecting
|
||||
how xrep is being used. e.g., Is stdin being piped into it? Is stdout being
|
||||
redirected to a file? etc... We use this information to tweak various default
|
||||
configuration parameters such as colors and match formatting.
|
||||
This atty module contains functions for detecting whether ripgrep is being fed
|
||||
from (or to) a terminal. Windows and Unix do this differently, so implement
|
||||
both here.
|
||||
*/
|
||||
|
||||
use libc;
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn stdin_is_atty() -> bool {
|
||||
pub fn on_stdin() -> bool {
|
||||
use libc;
|
||||
0 < unsafe { libc::isatty(libc::STDIN_FILENO) }
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn stdout_is_atty() -> bool {
|
||||
pub fn on_stdout() -> bool {
|
||||
use libc;
|
||||
0 < unsafe { libc::isatty(libc::STDOUT_FILENO) }
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn stdin_is_atty() -> bool {
|
||||
pub fn on_stdin() -> bool {
|
||||
use kernel32;
|
||||
use winapi;
|
||||
|
||||
@@ -30,13 +29,13 @@ pub fn stdin_is_atty() -> bool {
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn stdout_is_atty() -> bool {
|
||||
pub fn on_stdout() -> bool {
|
||||
use kernel32;
|
||||
use winapi;
|
||||
|
||||
unsafe {
|
||||
let fd = winapi::winbase::STD_OUTPUT_HANDLE;
|
||||
let mut out = 0;
|
||||
kernel32::GetConsoleMode(handle, &mut out) != 0
|
||||
kernel32::GetConsoleMode(kernel32::GetStdHandle(fd), &mut out) != 0
|
||||
}
|
||||
}
|
@@ -9,7 +9,7 @@ The motivation for this submodule is performance and portability:
|
||||
2. We could shell out to a `git` sub-command like ls-files or status, but it
|
||||
seems better to not rely on the existence of external programs for a search
|
||||
tool. Besides, we need to implement this logic anyway to support things like
|
||||
an .xrepignore file.
|
||||
an .rgignore file.
|
||||
|
||||
The key implementation detail here is that a single gitignore file is compiled
|
||||
into a single RegexSet, which can be used to report which globs match a
|
||||
@@ -21,7 +21,7 @@ additional rules such as whitelists (prefix of `!`) or directory-only globs
|
||||
// TODO(burntsushi): Implement something similar, but for Mercurial. We can't
|
||||
// use this exact implementation because hgignore files are different.
|
||||
|
||||
use std::env;
|
||||
use std::cell::RefCell;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt;
|
||||
use std::fs::File;
|
||||
@@ -31,6 +31,7 @@ use std::path::{Path, PathBuf};
|
||||
use regex;
|
||||
|
||||
use glob;
|
||||
use pathutil::strip_prefix;
|
||||
|
||||
/// Represents an error that can occur when parsing a gitignore file.
|
||||
#[derive(Debug)]
|
||||
@@ -89,21 +90,10 @@ pub struct Gitignore {
|
||||
}
|
||||
|
||||
impl Gitignore {
|
||||
/// Create a new gitignore glob matcher from the gitignore file at the
|
||||
/// given path. The root of the gitignore file is the basename of path.
|
||||
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Gitignore, Error> {
|
||||
let root = match path.as_ref().parent() {
|
||||
Some(parent) => parent.to_path_buf(),
|
||||
None => env::current_dir().unwrap_or(Path::new("/").to_path_buf()),
|
||||
};
|
||||
let mut builder = GitignoreBuilder::new(root);
|
||||
try!(builder.add_path(path));
|
||||
builder.build()
|
||||
}
|
||||
|
||||
/// Create a new gitignore glob matcher from the given root directory and
|
||||
/// string containing the contents of a gitignore file.
|
||||
pub fn from_str<P: AsRef<Path>>(
|
||||
#[allow(dead_code)]
|
||||
fn from_str<P: AsRef<Path>>(
|
||||
root: P,
|
||||
gitignore: &str,
|
||||
) -> Result<Gitignore, Error> {
|
||||
@@ -122,48 +112,43 @@ impl Gitignore {
|
||||
/// same directory as this gitignore file.
|
||||
pub fn matched<P: AsRef<Path>>(&self, path: P, is_dir: bool) -> Match {
|
||||
let mut path = path.as_ref();
|
||||
if let Ok(p) = path.strip_prefix(&self.root) {
|
||||
if let Some(p) = strip_prefix("./", path) {
|
||||
path = p;
|
||||
}
|
||||
self.matched_utf8(&*path.to_string_lossy(), is_dir)
|
||||
if let Some(p) = strip_prefix(&self.root, path) {
|
||||
path = p;
|
||||
}
|
||||
self.matched_stripped(path, is_dir)
|
||||
}
|
||||
|
||||
/// Like matched, but takes a path that has already been stripped and
|
||||
/// converted to UTF-8.
|
||||
pub fn matched_utf8(&self, path: &str, is_dir: bool) -> Match {
|
||||
// A single regex with a bunch of alternations of glob patterns is
|
||||
// unfortunately typically faster than a regex, so we use it as a
|
||||
// first pass filter. We still need to run the RegexSet to get the most
|
||||
// recently defined glob that matched.
|
||||
if !self.set.is_match(path) {
|
||||
return Match::None;
|
||||
}
|
||||
// The regex set can't actually pick the right glob that matched all
|
||||
// on its own. In particular, some globs require that only directories
|
||||
// can match. Thus, only accept a match from the regex set if the given
|
||||
// path satisfies the corresponding glob's directory criteria.
|
||||
for i in self.set.matches(path).iter().rev() {
|
||||
let pat = &self.patterns[i];
|
||||
if !pat.only_dir || is_dir {
|
||||
return if pat.whitelist {
|
||||
Match::Whitelist(pat)
|
||||
} else {
|
||||
Match::Ignored(pat)
|
||||
};
|
||||
/// Like matched, but takes a path that has already been stripped.
|
||||
pub fn matched_stripped(&self, path: &Path, is_dir: bool) -> Match {
|
||||
thread_local! {
|
||||
static MATCHES: RefCell<Vec<usize>> = {
|
||||
RefCell::new(vec![])
|
||||
}
|
||||
}
|
||||
Match::None
|
||||
};
|
||||
MATCHES.with(|matches| {
|
||||
let mut matches = matches.borrow_mut();
|
||||
self.set.matches_into(path, &mut *matches);
|
||||
for &i in matches.iter().rev() {
|
||||
let pat = &self.patterns[i];
|
||||
if !pat.only_dir || is_dir {
|
||||
return if pat.whitelist {
|
||||
Match::Whitelist(pat)
|
||||
} else {
|
||||
Match::Ignored(pat)
|
||||
};
|
||||
}
|
||||
}
|
||||
Match::None
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the total number of ignore patterns.
|
||||
pub fn num_ignores(&self) -> u64 {
|
||||
self.num_ignores
|
||||
}
|
||||
|
||||
/// Returns the total number of whitelisted patterns.
|
||||
pub fn num_whitelist(&self) -> u64 {
|
||||
self.num_whitelist
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of a glob match.
|
||||
@@ -182,6 +167,7 @@ pub enum Match<'a> {
|
||||
|
||||
impl<'a> Match<'a> {
|
||||
/// Returns true if the match result implies the path should be ignored.
|
||||
#[allow(dead_code)]
|
||||
pub fn is_ignored(&self) -> bool {
|
||||
match *self {
|
||||
Match::Ignored(_) => true,
|
||||
@@ -379,7 +365,7 @@ mod tests {
|
||||
};
|
||||
}
|
||||
|
||||
const ROOT: &'static str = "/home/foobar/rust/xrep";
|
||||
const ROOT: &'static str = "/home/foobar/rust/rg";
|
||||
|
||||
ignored!(ig1, ROOT, "months", "months");
|
||||
ignored!(ig2, ROOT, "*.lock", "Cargo.lock");
|
||||
@@ -406,6 +392,7 @@ mod tests {
|
||||
ignored!(ig23, ROOT, "foo", "./foo");
|
||||
ignored!(ig24, ROOT, "target", "grep/target");
|
||||
ignored!(ig25, ROOT, "Cargo.lock", "./tabwriter-bin/Cargo.lock");
|
||||
ignored!(ig26, ROOT, "/foo/bar/baz", "./foo/bar/baz");
|
||||
|
||||
not_ignored!(ignot1, ROOT, "amonths", "months");
|
||||
not_ignored!(ignot2, ROOT, "monthsa", "months");
|
||||
|
483
src/glob.rs
483
src/glob.rs
@@ -26,14 +26,22 @@ to make its way into `glob` proper.
|
||||
// at the .gitignore for the chromium repo---just about every pattern satisfies
|
||||
// that assumption.)
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error as StdError;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fmt;
|
||||
use std::hash;
|
||||
use std::iter;
|
||||
use std::path;
|
||||
use std::path::Path;
|
||||
use std::str;
|
||||
|
||||
use fnv;
|
||||
use regex;
|
||||
use regex::bytes::{Regex, RegexSet, SetMatches};
|
||||
use regex::bytes::Regex;
|
||||
use regex::bytes::RegexSet;
|
||||
|
||||
use pathutil::file_name;
|
||||
|
||||
/// Represents an error that can occur when parsing a glob pattern.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
@@ -72,32 +80,181 @@ impl fmt::Display for Error {
|
||||
}
|
||||
}
|
||||
|
||||
/// SetYesNo represents a group of globs that can be matched together in a
|
||||
/// single pass. SetYesNo can only determine whether a particular path matched
|
||||
/// any pattern in the set.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SetYesNo {
|
||||
re: Regex,
|
||||
}
|
||||
|
||||
impl SetYesNo {
|
||||
/// Returns true if and only if the given path matches at least one glob
|
||||
/// in this set.
|
||||
pub fn is_match<T: AsRef<Path>>(&self, path: T) -> bool {
|
||||
self.re.is_match(&*path_bytes(path.as_ref()))
|
||||
}
|
||||
|
||||
fn new(
|
||||
pats: &[(Pattern, MatchOptions)],
|
||||
) -> Result<SetYesNo, regex::Error> {
|
||||
let mut joined = String::new();
|
||||
for &(ref p, ref o) in pats {
|
||||
let part = format!("(?:{})", p.to_regex_with(o));
|
||||
if !joined.is_empty() {
|
||||
joined.push('|');
|
||||
}
|
||||
joined.push_str(&part);
|
||||
}
|
||||
Ok(SetYesNo { re: try!(Regex::new(&joined)) })
|
||||
}
|
||||
}
|
||||
|
||||
type Fnv = hash::BuildHasherDefault<fnv::FnvHasher>;
|
||||
|
||||
/// Set represents a group of globs that can be matched together in a single
|
||||
/// pass.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Set {
|
||||
re: Regex,
|
||||
set: RegexSet,
|
||||
yesno: SetYesNo,
|
||||
exts: HashMap<OsString, Vec<usize>, Fnv>,
|
||||
literals: HashMap<Vec<u8>, Vec<usize>, Fnv>,
|
||||
base_literals: HashMap<Vec<u8>, Vec<usize>, Fnv>,
|
||||
base_prefixes: Vec<Vec<u8>>,
|
||||
base_prefixes_map: Vec<usize>,
|
||||
base_suffixes: Vec<Vec<u8>>,
|
||||
base_suffixes_map: Vec<usize>,
|
||||
base_regexes: RegexSet,
|
||||
base_regexes_map: Vec<usize>,
|
||||
regexes: RegexSet,
|
||||
regexes_map: Vec<usize>,
|
||||
}
|
||||
|
||||
impl Set {
|
||||
/// Returns true if and only if the given path matches at least one glob
|
||||
/// in this set.
|
||||
pub fn is_match<T: AsRef<[u8]>>(&self, path: T) -> bool {
|
||||
self.re.is_match(path.as_ref())
|
||||
/// Returns the sequence number of every glob pattern that matches the
|
||||
/// given path.
|
||||
#[allow(dead_code)]
|
||||
pub fn matches<T: AsRef<Path>>(&self, path: T) -> Vec<usize> {
|
||||
let mut into = vec![];
|
||||
self.matches_into(path, &mut into);
|
||||
into
|
||||
}
|
||||
|
||||
/// Returns every glob pattern (by sequence number) that matches the given
|
||||
/// path.
|
||||
pub fn matches<T: AsRef<[u8]>>(&self, path: T) -> SetMatches {
|
||||
// TODO(burntsushi): If we split this out into a separate crate, don't
|
||||
// expose the regex::SetMatches type in the public API.
|
||||
self.set.matches(path.as_ref())
|
||||
/// Adds the sequence number of every glob pattern that matches the given
|
||||
/// path to the vec given.
|
||||
pub fn matches_into<T: AsRef<Path>>(
|
||||
&self,
|
||||
path: T,
|
||||
into: &mut Vec<usize>,
|
||||
) {
|
||||
into.clear();
|
||||
let path = path.as_ref();
|
||||
let path_bytes = &*path_bytes(path);
|
||||
let basename = file_name(path).map(|b| os_str_bytes(b));
|
||||
if !self.yesno.is_match(path) {
|
||||
return;
|
||||
}
|
||||
if !self.exts.is_empty() {
|
||||
if let Some(ext) = path.extension() {
|
||||
if let Some(matches) = self.exts.get(ext) {
|
||||
into.extend(matches.as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
if !self.literals.is_empty() {
|
||||
if let Some(matches) = self.literals.get(path_bytes) {
|
||||
into.extend(matches.as_slice());
|
||||
}
|
||||
}
|
||||
if !self.base_literals.is_empty() {
|
||||
if let Some(ref basename) = basename {
|
||||
if let Some(matches) = self.base_literals.get(&**basename) {
|
||||
into.extend(matches.as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
if !self.base_prefixes.is_empty() {
|
||||
if let Some(ref basename) = basename {
|
||||
let basename = &**basename;
|
||||
for (i, pre) in self.base_prefixes.iter().enumerate() {
|
||||
if pre.len() <= basename.len() && &**pre == &basename[0..pre.len()] {
|
||||
into.push(self.base_prefixes_map[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !self.base_suffixes.is_empty() {
|
||||
if let Some(ref basename) = basename {
|
||||
let basename = &**basename;
|
||||
for (i, suf) in self.base_suffixes.iter().enumerate() {
|
||||
if suf.len() > basename.len() {
|
||||
continue;
|
||||
}
|
||||
let (s, e) = (basename.len() - suf.len(), basename.len());
|
||||
if &**suf == &basename[s..e] {
|
||||
into.push(self.base_suffixes_map[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(ref basename) = basename {
|
||||
for i in self.base_regexes.matches(&**basename) {
|
||||
into.push(self.base_regexes_map[i]);
|
||||
}
|
||||
}
|
||||
for i in self.regexes.matches(path_bytes) {
|
||||
into.push(self.regexes_map[i]);
|
||||
}
|
||||
into.sort();
|
||||
}
|
||||
|
||||
/// Returns the number of glob patterns in this set.
|
||||
pub fn len(&self) -> usize {
|
||||
self.set.len()
|
||||
fn new(pats: &[(Pattern, MatchOptions)]) -> Result<Set, regex::Error> {
|
||||
let fnv = Fnv::default();
|
||||
let mut exts = HashMap::with_hasher(fnv.clone());
|
||||
let mut literals = HashMap::with_hasher(fnv.clone());
|
||||
let mut base_literals = HashMap::with_hasher(fnv.clone());
|
||||
let (mut base_prefixes, mut base_prefixes_map) = (vec![], vec![]);
|
||||
let (mut base_suffixes, mut base_suffixes_map) = (vec![], vec![]);
|
||||
let (mut regexes, mut regexes_map) = (vec![], vec![]);
|
||||
let (mut base_regexes, mut base_regexes_map) = (vec![], vec![]);
|
||||
for (i, &(ref p, ref o)) in pats.iter().enumerate() {
|
||||
if let Some(ext) = p.ext() {
|
||||
exts.entry(ext).or_insert(vec![]).push(i);
|
||||
} else if let Some(literal) = p.literal() {
|
||||
literals.entry(literal.into_bytes()).or_insert(vec![]).push(i);
|
||||
} else if let Some(literal) = p.base_literal() {
|
||||
base_literals
|
||||
.entry(literal.into_bytes()).or_insert(vec![]).push(i);
|
||||
} else if let Some(literal) = p.base_literal_prefix() {
|
||||
base_prefixes.push(literal.into_bytes());
|
||||
base_prefixes_map.push(i);
|
||||
} else if let Some(literal) = p.base_literal_suffix() {
|
||||
base_suffixes.push(literal.into_bytes());
|
||||
base_suffixes_map.push(i);
|
||||
} else if p.is_only_basename() {
|
||||
let part = format!("(?:{})", p.to_regex_with(o));
|
||||
base_regexes.push(part);
|
||||
base_regexes_map.push(i);
|
||||
} else {
|
||||
let part = format!("(?:{})", p.to_regex_with(o));
|
||||
regexes.push(part);
|
||||
regexes_map.push(i);
|
||||
}
|
||||
}
|
||||
Ok(Set {
|
||||
yesno: try!(SetYesNo::new(pats)),
|
||||
exts: exts,
|
||||
literals: literals,
|
||||
base_literals: base_literals,
|
||||
base_prefixes: base_prefixes,
|
||||
base_prefixes_map: base_prefixes_map,
|
||||
base_suffixes: base_suffixes,
|
||||
base_suffixes_map: base_suffixes_map,
|
||||
base_regexes: try!(RegexSet::new(base_regexes)),
|
||||
base_regexes_map: base_regexes_map,
|
||||
regexes: try!(RegexSet::new(regexes)),
|
||||
regexes_map: regexes_map,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,25 +276,19 @@ impl SetBuilder {
|
||||
///
|
||||
/// Once a matcher is built, no new patterns can be added to it.
|
||||
pub fn build(&self) -> Result<Set, regex::Error> {
|
||||
let it = self.pats.iter().map(|&(ref p, ref o)| p.to_regex_with(o));
|
||||
let set = try!(RegexSet::new(it));
|
||||
Set::new(&self.pats)
|
||||
}
|
||||
|
||||
let mut joined = String::new();
|
||||
for &(ref p, ref o) in &self.pats {
|
||||
let part = format!("(?:{})", p.to_regex_with(o));
|
||||
if !joined.is_empty() {
|
||||
joined.push('|');
|
||||
}
|
||||
joined.push_str(&part);
|
||||
}
|
||||
let re = try!(Regex::new(&joined));
|
||||
Ok(Set { re: re, set: set })
|
||||
/// Like `build`, but returns a matcher that can only answer yes/no.
|
||||
pub fn build_yesno(&self) -> Result<SetYesNo, regex::Error> {
|
||||
SetYesNo::new(&self.pats)
|
||||
}
|
||||
|
||||
/// Add a new pattern to this set.
|
||||
///
|
||||
/// If the pattern could not be parsed as a glob, then an error is
|
||||
/// returned.
|
||||
#[allow(dead_code)]
|
||||
pub fn add(&mut self, pat: &str) -> Result<(), Error> {
|
||||
self.add_with(pat, &MatchOptions::default())
|
||||
}
|
||||
@@ -148,8 +299,21 @@ impl SetBuilder {
|
||||
pat: &str,
|
||||
opts: &MatchOptions,
|
||||
) -> Result<(), Error> {
|
||||
let pat = try!(Pattern::new(pat));
|
||||
self.pats.push((pat, opts.clone()));
|
||||
let parsed = try!(Pattern::new(pat));
|
||||
// if let Some(ext) = parsed.ext() {
|
||||
// eprintln!("ext :: {:?} :: {:?}", ext, pat);
|
||||
// } else if let Some(lit) = parsed.literal() {
|
||||
// eprintln!("literal :: {:?} :: {:?}", lit, pat);
|
||||
// } else if let Some(lit) = parsed.base_literal() {
|
||||
// eprintln!("base_literal :: {:?} :: {:?}", lit, pat);
|
||||
// } else if let Some(lit) = parsed.base_literal_prefix() {
|
||||
// eprintln!("base_literal :: {:?} :: {:?}", lit, pat);
|
||||
// } else if let Some(lit) = parsed.base_literal_suffix() {
|
||||
// eprintln!("base_literal :: {:?} :: {:?}", lit, pat);
|
||||
// } else {
|
||||
// eprintln!("regex :: {:?} :: {:?}", pat, parsed);
|
||||
// }
|
||||
self.pats.push((parsed, opts.clone()));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -203,9 +367,137 @@ impl Pattern {
|
||||
Ok(p.p)
|
||||
}
|
||||
|
||||
/// Returns an extension if this pattern exclusively matches it.
|
||||
pub fn ext(&self) -> Option<OsString> {
|
||||
if self.tokens.len() <= 3 {
|
||||
return None;
|
||||
}
|
||||
match self.tokens.get(0) {
|
||||
Some(&Token::RecursivePrefix) => {}
|
||||
_ => return None,
|
||||
}
|
||||
match self.tokens.get(1) {
|
||||
Some(&Token::ZeroOrMore) => {}
|
||||
_ => return None,
|
||||
}
|
||||
match self.tokens.get(2) {
|
||||
Some(&Token::Literal(c)) if c == '.' => {}
|
||||
_ => return None,
|
||||
}
|
||||
let mut lit = OsString::new();
|
||||
for t in self.tokens[3..].iter() {
|
||||
match *t {
|
||||
Token::Literal(c) if c == '/' || c == '\\' || c == '.' => {
|
||||
return None;
|
||||
}
|
||||
Token::Literal(c) => lit.push(c.to_string()),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
Some(lit)
|
||||
}
|
||||
|
||||
/// Returns the pattern as a literal if and only if the pattern exclusiely
|
||||
/// matches the basename of a file path *and* is a literal.
|
||||
///
|
||||
/// The basic format of these patterns is `**/{literal}`, where `{literal}`
|
||||
/// does not contain a path separator.
|
||||
pub fn base_literal(&self) -> Option<String> {
|
||||
match self.tokens.get(0) {
|
||||
Some(&Token::RecursivePrefix) => {}
|
||||
_ => return None,
|
||||
}
|
||||
let mut lit = String::new();
|
||||
for t in &self.tokens[1..] {
|
||||
match *t {
|
||||
Token::Literal(c) if c == '/' || c == '\\' => return None,
|
||||
Token::Literal(c) => lit.push(c),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
Some(lit)
|
||||
}
|
||||
|
||||
/// Returns true if and only if this pattern only inspects the basename
|
||||
/// of a path.
|
||||
pub fn is_only_basename(&self) -> bool {
|
||||
match self.tokens.get(0) {
|
||||
Some(&Token::RecursivePrefix) => {}
|
||||
_ => return false,
|
||||
}
|
||||
for t in &self.tokens[1..] {
|
||||
match *t {
|
||||
Token::Literal(c) if c == '/' || c == '\\' => return false,
|
||||
Token::RecursivePrefix
|
||||
| Token::RecursiveSuffix
|
||||
| Token::RecursiveZeroOrMore => return false,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Returns the pattern as a literal if and only if the pattern must match
|
||||
/// an entire path exactly.
|
||||
///
|
||||
/// The basic format of these patterns is `{literal}`.
|
||||
pub fn literal(&self) -> Option<String> {
|
||||
let mut lit = String::new();
|
||||
for t in &self.tokens {
|
||||
match *t {
|
||||
Token::Literal(c) => lit.push(c),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
Some(lit)
|
||||
}
|
||||
|
||||
/// Returns a basename literal prefix of this pattern.
|
||||
pub fn base_literal_prefix(&self) -> Option<String> {
|
||||
match self.tokens.get(0) {
|
||||
Some(&Token::RecursivePrefix) => {}
|
||||
_ => return None,
|
||||
}
|
||||
match self.tokens.last() {
|
||||
Some(&Token::ZeroOrMore) => {}
|
||||
_ => return None,
|
||||
}
|
||||
let mut lit = String::new();
|
||||
for t in &self.tokens[1..self.tokens.len()-1] {
|
||||
match *t {
|
||||
Token::Literal(c) if c == '/' || c == '\\' => return None,
|
||||
Token::Literal(c) => lit.push(c),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
Some(lit)
|
||||
}
|
||||
|
||||
/// Returns a basename literal suffix of this pattern.
|
||||
pub fn base_literal_suffix(&self) -> Option<String> {
|
||||
match self.tokens.get(0) {
|
||||
Some(&Token::RecursivePrefix) => {}
|
||||
_ => return None,
|
||||
}
|
||||
match self.tokens.get(1) {
|
||||
Some(&Token::ZeroOrMore) => {}
|
||||
_ => return None,
|
||||
}
|
||||
let mut lit = String::new();
|
||||
for t in &self.tokens[2..] {
|
||||
match *t {
|
||||
Token::Literal(c) if c == '/' || c == '\\' => return None,
|
||||
Token::Literal(c) => lit.push(c),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
Some(lit)
|
||||
}
|
||||
|
||||
/// Convert this pattern to a string that is guaranteed to be a valid
|
||||
/// regular expression and will represent the matching semantics of this
|
||||
/// glob pattern. This uses a default set of options.
|
||||
#[allow(dead_code)]
|
||||
pub fn to_regex(&self) -> String {
|
||||
self.to_regex_with(&MatchOptions::default())
|
||||
}
|
||||
@@ -214,7 +506,7 @@ impl Pattern {
|
||||
/// regular expression and will represent the matching semantics of this
|
||||
/// glob pattern and the options given.
|
||||
pub fn to_regex_with(&self, options: &MatchOptions) -> String {
|
||||
let sep = path::MAIN_SEPARATOR.to_string();
|
||||
let seps = regex::quote(r"/\");
|
||||
let mut re = String::new();
|
||||
re.push_str("(?-u)");
|
||||
if options.case_insensitive {
|
||||
@@ -235,26 +527,27 @@ impl Pattern {
|
||||
}
|
||||
Token::Any => {
|
||||
if options.require_literal_separator {
|
||||
re.push_str(&format!("[^{}]", regex::quote(&sep)));
|
||||
re.push_str(&format!("[^{}]", seps));
|
||||
} else {
|
||||
re.push_str(".");
|
||||
}
|
||||
}
|
||||
Token::ZeroOrMore => {
|
||||
if options.require_literal_separator {
|
||||
re.push_str(&format!("[^{}]*", regex::quote(&sep)));
|
||||
re.push_str(&format!("[^{}]*", seps));
|
||||
} else {
|
||||
re.push_str(".*");
|
||||
}
|
||||
}
|
||||
Token::RecursivePrefix => {
|
||||
re.push_str(&format!("(?:{sep}?|.*{sep})", sep=sep));
|
||||
re.push_str(&format!("(?:[{sep}]?|.*[{sep}])", sep=seps));
|
||||
}
|
||||
Token::RecursiveSuffix => {
|
||||
re.push_str(&format!("(?:{sep}?|{sep}.*)", sep=sep));
|
||||
re.push_str(&format!("(?:[{sep}]?|[{sep}].*)", sep=seps));
|
||||
}
|
||||
Token::RecursiveZeroOrMore => {
|
||||
re.push_str(&format!("(?:{sep}|{sep}.*{sep})", sep=sep));
|
||||
re.push_str(&format!("(?:[{sep}]|[{sep}].*[{sep}])",
|
||||
sep=seps));
|
||||
}
|
||||
Token::Class { negated, ref ranges } => {
|
||||
re.push('[');
|
||||
@@ -315,7 +608,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
let last = self.p.tokens.pop().unwrap();
|
||||
self.p.tokens.pop().unwrap();
|
||||
if prev != Some('/') {
|
||||
return Err(Error::InvalidRecursive);
|
||||
}
|
||||
@@ -412,11 +705,34 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn path_bytes(path: &Path) -> Cow<[u8]> {
|
||||
os_str_bytes(path.as_os_str())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn os_str_bytes(s: &OsStr) -> Cow<[u8]> {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
Cow::Borrowed(s.as_bytes())
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn os_str_bytes(s: &OsStr) -> Cow<[u8]> {
|
||||
// TODO(burntsushi): On Windows, OS strings are probably UTF-16, so even
|
||||
// if we could get at the raw bytes, they wouldn't be useful. We *must*
|
||||
// convert to UTF-8 before doing path matching. Unfortunate, but necessary.
|
||||
match s.to_string_lossy() {
|
||||
Cow::Owned(s) => Cow::Owned(s.into_bytes()),
|
||||
Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::Path;
|
||||
|
||||
use regex::bytes::Regex;
|
||||
|
||||
use super::{Error, Pattern, MatchOptions, SetBuilder, Token};
|
||||
use super::{Error, Pattern, MatchOptions, Set, SetBuilder, Token};
|
||||
use super::Token::*;
|
||||
|
||||
macro_rules! syntax {
|
||||
@@ -461,8 +777,9 @@ mod tests {
|
||||
#[test]
|
||||
fn $name() {
|
||||
let pat = Pattern::new($pat).unwrap();
|
||||
let path = &Path::new($path).to_str().unwrap();
|
||||
let re = Regex::new(&pat.to_regex_with(&$options)).unwrap();
|
||||
assert!(re.is_match($path.as_bytes()));
|
||||
assert!(re.is_match(path.as_bytes()));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -475,8 +792,40 @@ mod tests {
|
||||
#[test]
|
||||
fn $name() {
|
||||
let pat = Pattern::new($pat).unwrap();
|
||||
let path = &Path::new($path).to_str().unwrap();
|
||||
let re = Regex::new(&pat.to_regex_with(&$options)).unwrap();
|
||||
assert!(!re.is_match($path.as_bytes()));
|
||||
assert!(!re.is_match(path.as_bytes()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ext {
|
||||
($name:ident, $pat:expr, $ext:expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
let pat = Pattern::new($pat).unwrap();
|
||||
let ext = pat.ext().map(|e| e.to_string_lossy().into_owned());
|
||||
assert_eq!($ext, ext.as_ref().map(|s| &**s));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! baseliteral {
|
||||
($name:ident, $pat:expr, $yes:expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
let pat = Pattern::new($pat).unwrap();
|
||||
assert_eq!($yes, pat.base_literal().is_some());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! basesuffix {
|
||||
($name:ident, $pat:expr, $yes:expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
let pat = Pattern::new($pat).unwrap();
|
||||
assert_eq!($yes, pat.is_literal_suffix());
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -557,12 +906,11 @@ mod tests {
|
||||
case_insensitive: true,
|
||||
require_literal_separator: false,
|
||||
};
|
||||
const SEP: char = ::std::path::MAIN_SEPARATOR;
|
||||
|
||||
toregex!(re_casei, "a", "(?i)^a$", &CASEI);
|
||||
|
||||
toregex!(re_slash1, "?", format!("^[^{}]$", SEP), SLASHLIT);
|
||||
toregex!(re_slash2, "*", format!("^[^{}]*$", SEP), SLASHLIT);
|
||||
toregex!(re_slash1, "?", r"^[^/\\]$", SLASHLIT);
|
||||
toregex!(re_slash2, "*", r"^[^/\\]*$", SLASHLIT);
|
||||
|
||||
toregex!(re1, "a", "^a$");
|
||||
toregex!(re2, "?", "^.$");
|
||||
@@ -576,6 +924,26 @@ mod tests {
|
||||
toregex!(re10, "+", r"^\+$");
|
||||
toregex!(re11, "**", r"^.*$");
|
||||
|
||||
ext!(ext1, "**/*.rs", Some("rs"));
|
||||
|
||||
baseliteral!(lit1, "**", true);
|
||||
baseliteral!(lit2, "**/a", true);
|
||||
baseliteral!(lit3, "**/ab", true);
|
||||
baseliteral!(lit4, "**/a*b", false);
|
||||
baseliteral!(lit5, "z/**/a*b", false);
|
||||
baseliteral!(lit6, "[ab]", false);
|
||||
baseliteral!(lit7, "?", false);
|
||||
|
||||
/*
|
||||
issuffix!(suf1, "", false);
|
||||
issuffix!(suf2, "a", true);
|
||||
issuffix!(suf3, "ab", true);
|
||||
issuffix!(suf4, "*ab", true);
|
||||
issuffix!(suf5, "*.ab", true);
|
||||
issuffix!(suf6, "?.ab", true);
|
||||
issuffix!(suf7, "ab*", false);
|
||||
*/
|
||||
|
||||
matches!(match1, "a", "a");
|
||||
matches!(match2, "a*b", "a_b");
|
||||
matches!(match3, "a*b*c", "abc");
|
||||
@@ -638,6 +1006,7 @@ mod tests {
|
||||
|
||||
matches!(matchslash1, "abc/def", "abc/def", SLASHLIT);
|
||||
nmatches!(matchslash2, "abc?def", "abc/def", SLASHLIT);
|
||||
nmatches!(matchslash2_win, "abc?def", "abc\\def", SLASHLIT);
|
||||
nmatches!(matchslash3, "abc*def", "abc/def", SLASHLIT);
|
||||
matches!(matchslash4, "abc[/]def", "abc/def", SLASHLIT); // differs
|
||||
|
||||
@@ -671,16 +1040,22 @@ mod tests {
|
||||
builder.add("src/lib.rs").unwrap();
|
||||
let set = builder.build().unwrap();
|
||||
|
||||
assert!(set.is_match("foo.c"));
|
||||
assert!(set.is_match("src/foo.c"));
|
||||
assert!(!set.is_match("foo.rs"));
|
||||
assert!(!set.is_match("tests/foo.rs"));
|
||||
assert!(set.is_match("src/foo.rs"));
|
||||
assert!(set.is_match("src/grep/src/main.rs"));
|
||||
fn is_match(set: &Set, s: &str) -> bool {
|
||||
let mut matches = vec![];
|
||||
set.matches_into(s, &mut matches);
|
||||
!matches.is_empty()
|
||||
}
|
||||
|
||||
assert_eq!(2, set.matches("src/lib.rs").iter().count());
|
||||
assert!(set.matches("src/lib.rs").matched(0));
|
||||
assert!(!set.matches("src/lib.rs").matched(1));
|
||||
assert!(set.matches("src/lib.rs").matched(2));
|
||||
assert!(is_match(&set, "foo.c"));
|
||||
assert!(is_match(&set, "src/foo.c"));
|
||||
assert!(!is_match(&set, "foo.rs"));
|
||||
assert!(!is_match(&set, "tests/foo.rs"));
|
||||
assert!(is_match(&set, "src/foo.rs"));
|
||||
assert!(is_match(&set, "src/grep/src/main.rs"));
|
||||
|
||||
let matches = set.matches("src/lib.rs");
|
||||
assert_eq!(2, matches.len());
|
||||
assert_eq!(0, matches[0]);
|
||||
assert_eq!(2, matches[1]);
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ whether a *single* file path should be searched or not.
|
||||
In general, there are two ways to ignore a particular file:
|
||||
|
||||
1. Specify an ignore rule in some "global" configuration, such as a
|
||||
$HOME/.xrepignore or on the command line.
|
||||
$HOME/.rgignore or on the command line.
|
||||
2. A specific ignore file (like .gitignore) found during directory traversal.
|
||||
|
||||
The `IgnoreDir` type handles ignore patterns for any one particular directory
|
||||
@@ -19,12 +19,12 @@ use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use gitignore::{self, Gitignore, GitignoreBuilder, Match, Pattern};
|
||||
use pathutil::is_hidden;
|
||||
use types::Types;
|
||||
|
||||
const IGNORE_NAMES: &'static [&'static str] = &[
|
||||
".gitignore",
|
||||
".agignore",
|
||||
".xrepignore",
|
||||
".rgignore",
|
||||
];
|
||||
|
||||
/// Represents an error that can occur when parsing a gitignore file.
|
||||
@@ -83,7 +83,10 @@ pub struct Ignore {
|
||||
overrides: Overrides,
|
||||
/// A file type matcher.
|
||||
types: Types,
|
||||
/// Whether to ignore hidden files or not.
|
||||
ignore_hidden: bool,
|
||||
/// When true, don't look at .gitignore or .agignore files for ignore
|
||||
/// rules.
|
||||
no_ignore: bool,
|
||||
}
|
||||
|
||||
@@ -208,15 +211,17 @@ impl Ignore {
|
||||
debug!("{} ignored because it is hidden", path.display());
|
||||
return true;
|
||||
}
|
||||
for id in self.stack.iter().rev().filter_map(|id| id.as_ref()) {
|
||||
let mat = id.matched(path, is_dir);
|
||||
if let Some(is_ignored) = self.ignore_match(path, mat) {
|
||||
if is_ignored {
|
||||
return true;
|
||||
if !self.no_ignore {
|
||||
for id in self.stack.iter().rev().filter_map(|id| id.as_ref()) {
|
||||
let mat = id.matched(path, is_dir);
|
||||
if let Some(is_ignored) = self.ignore_match(path, mat) {
|
||||
if is_ignored {
|
||||
return true;
|
||||
}
|
||||
// If this path is whitelisted by an ignore, then
|
||||
// fallthrough and let the file type matcher have a say.
|
||||
break;
|
||||
}
|
||||
// If this path is whitelisted by an ignore, then fallthrough
|
||||
// and let the file type matcher have a say.
|
||||
break;
|
||||
}
|
||||
}
|
||||
let mat = self.types.matched(path, is_dir);
|
||||
@@ -257,8 +262,8 @@ pub struct IgnoreDir {
|
||||
/// A single accumulation of glob patterns for this directory, matched
|
||||
/// using gitignore semantics.
|
||||
///
|
||||
/// This will include patterns from xrepignore as well. The patterns are
|
||||
/// ordered so that precedence applies automatically (e.g., xrepignore
|
||||
/// This will include patterns from rgignore as well. The patterns are
|
||||
/// ordered so that precedence applies automatically (e.g., rgignore
|
||||
/// patterns procede gitignore patterns).
|
||||
gi: Option<Gitignore>,
|
||||
// TODO(burntsushi): Matching other types of glob patterns that don't
|
||||
@@ -361,8 +366,7 @@ impl Overrides {
|
||||
let path = path.as_ref();
|
||||
self.gi.as_ref()
|
||||
.map(|gi| {
|
||||
let path = &*path.to_string_lossy();
|
||||
let mat = gi.matched_utf8(path, is_dir).invert();
|
||||
let mat = gi.matched_stripped(path, is_dir).invert();
|
||||
if mat.is_none() && !is_dir {
|
||||
if gi.num_ignores() > 0 {
|
||||
return Match::Ignored(&self.unmatched_pat);
|
||||
@@ -374,14 +378,6 @@ impl Overrides {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_hidden<P: AsRef<Path>>(path: P) -> bool {
|
||||
if let Some(name) = path.as_ref().file_name() {
|
||||
name.to_str().map(|s| s.starts_with(".")).unwrap_or(false)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::Path;
|
||||
@@ -422,7 +418,7 @@ mod tests {
|
||||
};
|
||||
}
|
||||
|
||||
const ROOT: &'static str = "/home/foobar/rust/xrep";
|
||||
const ROOT: &'static str = "/home/foobar/rust/rg";
|
||||
|
||||
ignored_dir!(id1, ROOT, "src/main.rs", "", "src/main.rs");
|
||||
ignored_dir!(id2, ROOT, "", "src/main.rs", "src/main.rs");
|
||||
|
188
src/main.rs
188
src/main.rs
@@ -1,8 +1,7 @@
|
||||
#![allow(dead_code, unused_variables)]
|
||||
|
||||
extern crate crossbeam;
|
||||
extern crate deque;
|
||||
extern crate docopt;
|
||||
extern crate env_logger;
|
||||
extern crate fnv;
|
||||
extern crate grep;
|
||||
#[cfg(windows)]
|
||||
extern crate kernel32;
|
||||
@@ -15,10 +14,8 @@ extern crate memchr;
|
||||
extern crate memmap;
|
||||
extern crate num_cpus;
|
||||
extern crate regex;
|
||||
extern crate regex_syntax as syntax;
|
||||
extern crate rustc_serialize;
|
||||
extern crate term;
|
||||
extern crate thread_local;
|
||||
extern crate walkdir;
|
||||
#[cfg(windows)]
|
||||
extern crate winapi;
|
||||
@@ -26,20 +23,25 @@ extern crate winapi;
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process;
|
||||
use std::result;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
|
||||
use crossbeam::sync::chase_lev::{self, Steal, Stealer};
|
||||
use deque::{Stealer, Stolen};
|
||||
use grep::Grep;
|
||||
use memmap::{Mmap, Protection};
|
||||
use term::Terminal;
|
||||
use walkdir::DirEntry;
|
||||
|
||||
use args::Args;
|
||||
use out::Out;
|
||||
use out::{ColoredTerminal, Out};
|
||||
use pathutil::strip_prefix;
|
||||
use printer::Printer;
|
||||
use search::InputBuffer;
|
||||
use search_stream::InputBuffer;
|
||||
#[cfg(windows)]
|
||||
use terminal_win::WindowsBuffer;
|
||||
|
||||
macro_rules! errored {
|
||||
($($tt:tt)*) => {
|
||||
@@ -55,14 +57,17 @@ macro_rules! eprintln {
|
||||
}
|
||||
|
||||
mod args;
|
||||
mod atty;
|
||||
mod gitignore;
|
||||
mod glob;
|
||||
mod ignore;
|
||||
mod out;
|
||||
mod pathutil;
|
||||
mod printer;
|
||||
mod search;
|
||||
mod sys;
|
||||
mod terminal;
|
||||
mod search_buffer;
|
||||
mod search_stream;
|
||||
#[cfg(windows)]
|
||||
mod terminal_win;
|
||||
mod types;
|
||||
mod walk;
|
||||
|
||||
@@ -71,7 +76,7 @@ pub type Result<T> = result::Result<T, Box<Error + Send + Sync>>;
|
||||
fn main() {
|
||||
match Args::parse().and_then(run) {
|
||||
Ok(count) if count == 0 => process::exit(1),
|
||||
Ok(count) => process::exit(0),
|
||||
Ok(_) => process::exit(0),
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1);
|
||||
@@ -80,41 +85,56 @@ fn main() {
|
||||
}
|
||||
|
||||
fn run(args: Args) -> Result<u64> {
|
||||
let args = Arc::new(args);
|
||||
let paths = args.paths();
|
||||
if args.files() {
|
||||
return run_files(args);
|
||||
return run_files(args.clone());
|
||||
}
|
||||
if args.type_list() {
|
||||
return run_types(args);
|
||||
return run_types(args.clone());
|
||||
}
|
||||
let args = Arc::new(args);
|
||||
let out = Arc::new(Mutex::new(args.out(io::stdout())));
|
||||
if paths.len() == 1 && (paths[0] == Path::new("-") || paths[0].is_file()) {
|
||||
return run_one(args.clone(), &paths[0]);
|
||||
}
|
||||
|
||||
let out = Arc::new(Mutex::new(args.out()));
|
||||
let mut workers = vec![];
|
||||
|
||||
let mut workq = {
|
||||
let (workq, stealer) = chase_lev::deque();
|
||||
let workq = {
|
||||
let (workq, stealer) = deque::new();
|
||||
for _ in 0..args.threads() {
|
||||
let worker = Worker {
|
||||
args: args.clone(),
|
||||
out: out.clone(),
|
||||
let worker = MultiWorker {
|
||||
chan_work: stealer.clone(),
|
||||
inpbuf: args.input_buffer(),
|
||||
outbuf: Some(vec![]),
|
||||
grep: try!(args.grep()),
|
||||
match_count: 0,
|
||||
out: out.clone(),
|
||||
outbuf: Some(args.outbuf()),
|
||||
worker: Worker {
|
||||
args: args.clone(),
|
||||
inpbuf: args.input_buffer(),
|
||||
grep: args.grep(),
|
||||
match_count: 0,
|
||||
},
|
||||
};
|
||||
workers.push(thread::spawn(move || worker.run()));
|
||||
}
|
||||
workq
|
||||
};
|
||||
for p in args.paths() {
|
||||
let mut paths_searched: u64 = 0;
|
||||
for p in paths {
|
||||
if p == Path::new("-") {
|
||||
workq.push(Work::Stdin)
|
||||
paths_searched += 1;
|
||||
workq.push(Work::Stdin);
|
||||
} else {
|
||||
for ent in try!(args.walker(p)) {
|
||||
paths_searched += 1;
|
||||
workq.push(Work::File(ent));
|
||||
}
|
||||
}
|
||||
}
|
||||
if !paths.is_empty() && paths_searched == 0 {
|
||||
eprintln!("No files were searched, which means ripgrep probably \
|
||||
applied a filter you didn't expect. \
|
||||
Try running again with --debug.");
|
||||
}
|
||||
for _ in 0..workers.len() {
|
||||
workq.push(Work::Quit);
|
||||
}
|
||||
@@ -125,8 +145,28 @@ fn run(args: Args) -> Result<u64> {
|
||||
Ok(match_count)
|
||||
}
|
||||
|
||||
fn run_files(args: Args) -> Result<u64> {
|
||||
let mut printer = args.printer(io::BufWriter::new(io::stdout()));
|
||||
fn run_one(args: Arc<Args>, path: &Path) -> Result<u64> {
|
||||
let mut worker = Worker {
|
||||
args: args.clone(),
|
||||
inpbuf: args.input_buffer(),
|
||||
grep: args.grep(),
|
||||
match_count: 0,
|
||||
};
|
||||
let term = args.stdout();
|
||||
let mut printer = args.printer(term);
|
||||
let work =
|
||||
if path == Path::new("-") {
|
||||
WorkReady::Stdin
|
||||
} else {
|
||||
WorkReady::PathFile(path.to_path_buf(), try!(File::open(path)))
|
||||
};
|
||||
worker.do_work(&mut printer, work);
|
||||
Ok(worker.match_count)
|
||||
}
|
||||
|
||||
fn run_files(args: Arc<Args>) -> Result<u64> {
|
||||
let term = args.stdout();
|
||||
let mut printer = args.printer(term);
|
||||
let mut file_count = 0;
|
||||
for p in args.paths() {
|
||||
if p == Path::new("-") {
|
||||
@@ -142,8 +182,9 @@ fn run_files(args: Args) -> Result<u64> {
|
||||
Ok(file_count)
|
||||
}
|
||||
|
||||
fn run_types(args: Args) -> Result<u64> {
|
||||
let mut printer = args.printer(io::BufWriter::new(io::stdout()));
|
||||
fn run_types(args: Arc<Args>) -> Result<u64> {
|
||||
let term = args.stdout();
|
||||
let mut printer = args.printer(term);
|
||||
let mut ty_count = 0;
|
||||
for def in args.type_defs() {
|
||||
printer.type_def(def);
|
||||
@@ -160,30 +201,37 @@ enum Work {
|
||||
|
||||
enum WorkReady {
|
||||
Stdin,
|
||||
File(DirEntry, File),
|
||||
DirFile(DirEntry, File),
|
||||
PathFile(PathBuf, File),
|
||||
}
|
||||
|
||||
struct MultiWorker {
|
||||
chan_work: Stealer<Work>,
|
||||
out: Arc<Mutex<Out>>,
|
||||
#[cfg(not(windows))]
|
||||
outbuf: Option<ColoredTerminal<term::TerminfoTerminal<Vec<u8>>>>,
|
||||
#[cfg(windows)]
|
||||
outbuf: Option<ColoredTerminal<WindowsBuffer>>,
|
||||
worker: Worker,
|
||||
}
|
||||
|
||||
struct Worker {
|
||||
args: Arc<Args>,
|
||||
out: Arc<Mutex<Out<io::Stdout>>>,
|
||||
chan_work: Stealer<Work>,
|
||||
inpbuf: InputBuffer,
|
||||
outbuf: Option<Vec<u8>>,
|
||||
grep: Grep,
|
||||
match_count: u64,
|
||||
}
|
||||
|
||||
impl Worker {
|
||||
impl MultiWorker {
|
||||
fn run(mut self) -> u64 {
|
||||
self.match_count = 0;
|
||||
loop {
|
||||
let work = match self.chan_work.steal() {
|
||||
Steal::Empty | Steal::Abort => continue,
|
||||
Steal::Data(Work::Quit) => break,
|
||||
Steal::Data(Work::Stdin) => WorkReady::Stdin,
|
||||
Steal::Data(Work::File(ent)) => {
|
||||
Stolen::Empty | Stolen::Abort => continue,
|
||||
Stolen::Data(Work::Quit) => break,
|
||||
Stolen::Data(Work::Stdin) => WorkReady::Stdin,
|
||||
Stolen::Data(Work::File(ent)) => {
|
||||
match File::open(ent.path()) {
|
||||
Ok(file) => WorkReady::File(ent, file),
|
||||
Ok(file) => WorkReady::DirFile(ent, file),
|
||||
Err(err) => {
|
||||
eprintln!("{}: {}", ent.path().display(), err);
|
||||
continue;
|
||||
@@ -193,19 +241,21 @@ impl Worker {
|
||||
};
|
||||
let mut outbuf = self.outbuf.take().unwrap();
|
||||
outbuf.clear();
|
||||
let mut printer = self.args.printer(outbuf);
|
||||
self.do_work(&mut printer, work);
|
||||
let mut printer = self.worker.args.printer(outbuf);
|
||||
self.worker.do_work(&mut printer, work);
|
||||
let outbuf = printer.into_inner();
|
||||
if !outbuf.is_empty() {
|
||||
if !outbuf.get_ref().is_empty() {
|
||||
let mut out = self.out.lock().unwrap();
|
||||
out.write(&outbuf);
|
||||
}
|
||||
self.outbuf = Some(outbuf);
|
||||
}
|
||||
self.match_count
|
||||
self.worker.match_count
|
||||
}
|
||||
}
|
||||
|
||||
fn do_work<W: Send + io::Write>(
|
||||
impl Worker {
|
||||
fn do_work<W: Terminal + Send>(
|
||||
&mut self,
|
||||
printer: &mut Printer<W>,
|
||||
work: WorkReady,
|
||||
@@ -216,12 +266,27 @@ impl Worker {
|
||||
let stdin = stdin.lock();
|
||||
self.search(printer, &Path::new("<stdin>"), stdin)
|
||||
}
|
||||
WorkReady::File(ent, file) => {
|
||||
WorkReady::DirFile(ent, file) => {
|
||||
let mut path = ent.path();
|
||||
if let Ok(p) = path.strip_prefix("./") {
|
||||
if let Some(p) = strip_prefix("./", path) {
|
||||
path = p;
|
||||
}
|
||||
self.search(printer, path, file)
|
||||
if self.args.mmap() {
|
||||
self.search_mmap(printer, path, &file)
|
||||
} else {
|
||||
self.search(printer, path, file)
|
||||
}
|
||||
}
|
||||
WorkReady::PathFile(path, file) => {
|
||||
let mut path = &*path;
|
||||
if let Some(p) = strip_prefix("./", path) {
|
||||
path = p;
|
||||
}
|
||||
if self.args.mmap() {
|
||||
self.search_mmap(printer, path, &file)
|
||||
} else {
|
||||
self.search(printer, path, file)
|
||||
}
|
||||
}
|
||||
};
|
||||
match result {
|
||||
@@ -234,7 +299,7 @@ impl Worker {
|
||||
}
|
||||
}
|
||||
|
||||
fn search<R: io::Read, W: Send + io::Write>(
|
||||
fn search<R: io::Read, W: Terminal + Send>(
|
||||
&mut self,
|
||||
printer: &mut Printer<W>,
|
||||
path: &Path,
|
||||
@@ -248,4 +313,23 @@ impl Worker {
|
||||
rdr,
|
||||
).run().map_err(From::from)
|
||||
}
|
||||
|
||||
fn search_mmap<W: Terminal + Send>(
|
||||
&mut self,
|
||||
printer: &mut Printer<W>,
|
||||
path: &Path,
|
||||
file: &File,
|
||||
) -> Result<u64> {
|
||||
if try!(file.metadata()).len() == 0 {
|
||||
// Opening a memory map with an empty file results in an error.
|
||||
return Ok(0);
|
||||
}
|
||||
let mmap = try!(Mmap::open(file, Protection::Read));
|
||||
Ok(self.args.searcher_buffer(
|
||||
printer,
|
||||
&self.grep,
|
||||
path,
|
||||
unsafe { mmap.as_slice() },
|
||||
).run())
|
||||
}
|
||||
}
|
||||
|
298
src/out.rs
298
src/out.rs
@@ -1,22 +1,46 @@
|
||||
use std::io::{self, Write};
|
||||
|
||||
use term::{self, Terminal};
|
||||
#[cfg(not(windows))]
|
||||
use term::terminfo::TermInfo;
|
||||
#[cfg(windows)]
|
||||
use term::WinConsole;
|
||||
|
||||
#[cfg(windows)]
|
||||
use terminal_win::WindowsBuffer;
|
||||
|
||||
/// Out controls the actual output of all search results for a particular file
|
||||
/// to the end user.
|
||||
///
|
||||
/// (The difference between Out and Printer is that a Printer works with
|
||||
/// individual search results where as Out works with search results for each
|
||||
/// file as a whole. For example, it knows when to print a file separator.)
|
||||
pub struct Out<W: io::Write> {
|
||||
wtr: io::BufWriter<W>,
|
||||
pub struct Out {
|
||||
#[cfg(not(windows))]
|
||||
term: ColoredTerminal<term::TerminfoTerminal<io::BufWriter<io::Stdout>>>,
|
||||
#[cfg(windows)]
|
||||
term: ColoredTerminal<WinConsole<io::Stdout>>,
|
||||
printed: bool,
|
||||
file_separator: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl<W: io::Write> Out<W> {
|
||||
impl Out {
|
||||
/// Create a new Out that writes to the wtr given.
|
||||
pub fn new(wtr: W) -> Out<W> {
|
||||
#[cfg(not(windows))]
|
||||
pub fn new(color: bool) -> Out {
|
||||
let wtr = io::BufWriter::new(io::stdout());
|
||||
Out {
|
||||
wtr: io::BufWriter::new(wtr),
|
||||
term: ColoredTerminal::new(wtr, color),
|
||||
printed: false,
|
||||
file_separator: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Out that writes to the wtr given.
|
||||
#[cfg(windows)]
|
||||
pub fn new(color: bool) -> Out {
|
||||
Out {
|
||||
term: ColoredTerminal::new_stdout(color),
|
||||
printed: false,
|
||||
file_separator: None,
|
||||
}
|
||||
@@ -26,22 +50,270 @@ impl<W: io::Write> Out<W> {
|
||||
/// By default, no separator is printed.
|
||||
///
|
||||
/// If sep is empty, then no file separator is printed.
|
||||
pub fn file_separator(mut self, sep: Vec<u8>) -> Out<W> {
|
||||
pub fn file_separator(mut self, sep: Vec<u8>) -> Out {
|
||||
self.file_separator = Some(sep);
|
||||
self
|
||||
}
|
||||
|
||||
/// Write the search results of a single file to the underlying wtr and
|
||||
/// flush wtr.
|
||||
pub fn write(&mut self, buf: &[u8]) {
|
||||
if let Some(ref sep) = self.file_separator {
|
||||
if self.printed {
|
||||
let _ = self.wtr.write_all(sep);
|
||||
let _ = self.wtr.write_all(b"\n");
|
||||
#[cfg(not(windows))]
|
||||
pub fn write(
|
||||
&mut self,
|
||||
buf: &ColoredTerminal<term::TerminfoTerminal<Vec<u8>>>,
|
||||
) {
|
||||
self.write_sep();
|
||||
match *buf {
|
||||
ColoredTerminal::Colored(ref tt) => {
|
||||
let _ = self.term.write_all(tt.get_ref());
|
||||
}
|
||||
ColoredTerminal::NoColor(ref buf) => {
|
||||
let _ = self.term.write_all(buf);
|
||||
}
|
||||
}
|
||||
let _ = self.wtr.write_all(buf);
|
||||
let _ = self.wtr.flush();
|
||||
self.write_done();
|
||||
}
|
||||
/// Write the search results of a single file to the underlying wtr and
|
||||
/// flush wtr.
|
||||
#[cfg(windows)]
|
||||
pub fn write(
|
||||
&mut self,
|
||||
buf: &ColoredTerminal<WindowsBuffer>,
|
||||
) {
|
||||
self.write_sep();
|
||||
match *buf {
|
||||
ColoredTerminal::Colored(ref tt) => {
|
||||
tt.print_stdout(&mut self.term);
|
||||
}
|
||||
ColoredTerminal::NoColor(ref buf) => {
|
||||
let _ = self.term.write_all(buf);
|
||||
}
|
||||
}
|
||||
self.write_done();
|
||||
}
|
||||
|
||||
fn write_sep(&mut self) {
|
||||
if let Some(ref sep) = self.file_separator {
|
||||
if self.printed {
|
||||
let _ = self.term.write_all(sep);
|
||||
let _ = self.term.write_all(b"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_done(&mut self) {
|
||||
let _ = self.term.flush();
|
||||
self.printed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// ColoredTerminal provides optional colored output through the term::Terminal
|
||||
/// trait. In particular, it will dynamically configure itself to use coloring
|
||||
/// if it's available in the environment.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ColoredTerminal<T: Terminal + Send> {
|
||||
Colored(T),
|
||||
NoColor(T::Output),
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
impl<W: io::Write + Send> ColoredTerminal<term::TerminfoTerminal<W>> {
|
||||
/// Create a new output buffer.
|
||||
///
|
||||
/// When color is true, the buffer will attempt to support coloring.
|
||||
pub fn new(wtr: W, color: bool) -> Self {
|
||||
lazy_static! {
|
||||
// Only pay for parsing the terminfo once.
|
||||
static ref TERMINFO: Option<TermInfo> = {
|
||||
match TermInfo::from_env() {
|
||||
Ok(info) => Some(info),
|
||||
Err(err) => {
|
||||
debug!("error loading terminfo for coloring: {}", err);
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
// If we want color, build a term::TerminfoTerminal and see if the
|
||||
// current environment supports coloring. If not, bail with NoColor. To
|
||||
// avoid losing our writer (ownership), do this the long way.
|
||||
if !color {
|
||||
return ColoredTerminal::NoColor(wtr);
|
||||
}
|
||||
let terminfo = match *TERMINFO {
|
||||
None => return ColoredTerminal::NoColor(wtr),
|
||||
Some(ref ti) => {
|
||||
// Ug, this should go away with the next release of `term`.
|
||||
TermInfo {
|
||||
names: ti.names.clone(),
|
||||
bools: ti.bools.clone(),
|
||||
numbers: ti.numbers.clone(),
|
||||
strings: ti.strings.clone(),
|
||||
}
|
||||
}
|
||||
};
|
||||
let tt = term::TerminfoTerminal::new_with_terminfo(wtr, terminfo);
|
||||
if !tt.supports_color() {
|
||||
debug!("environment doesn't support coloring");
|
||||
return ColoredTerminal::NoColor(tt.into_inner());
|
||||
}
|
||||
ColoredTerminal::Colored(tt)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
impl ColoredTerminal<term::TerminfoTerminal<Vec<u8>>> {
|
||||
/// Clear the give buffer of all search results such that it is reusable
|
||||
/// in another search.
|
||||
pub fn clear(&mut self) {
|
||||
match *self {
|
||||
ColoredTerminal::Colored(ref mut tt) => {
|
||||
tt.get_mut().clear();
|
||||
}
|
||||
ColoredTerminal::NoColor(ref mut buf) => {
|
||||
buf.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl ColoredTerminal<WindowsBuffer> {
|
||||
/// Create a new output buffer.
|
||||
///
|
||||
/// When color is true, the buffer will attempt to support coloring.
|
||||
pub fn new_buffer(color: bool) -> Self {
|
||||
if !color {
|
||||
ColoredTerminal::NoColor(vec![])
|
||||
} else {
|
||||
ColoredTerminal::Colored(WindowsBuffer::new())
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear the give buffer of all search results such that it is reusable
|
||||
/// in another search.
|
||||
pub fn clear(&mut self) {
|
||||
match *self {
|
||||
ColoredTerminal::Colored(ref mut win) => win.clear(),
|
||||
ColoredTerminal::NoColor(ref mut buf) => buf.clear(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl ColoredTerminal<WinConsole<io::Stdout>> {
|
||||
/// Create a new output buffer.
|
||||
///
|
||||
/// When color is true, the buffer will attempt to support coloring.
|
||||
pub fn new_stdout(color: bool) -> Self {
|
||||
if !color {
|
||||
return ColoredTerminal::NoColor(io::stdout());
|
||||
}
|
||||
match WinConsole::new(io::stdout()) {
|
||||
Ok(win) => ColoredTerminal::Colored(win),
|
||||
Err(_) => ColoredTerminal::NoColor(io::stdout()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Terminal + Send> ColoredTerminal<T> {
|
||||
fn map_result<F>(
|
||||
&mut self,
|
||||
mut f: F,
|
||||
) -> term::Result<()>
|
||||
where F: FnMut(&mut T) -> term::Result<()> {
|
||||
match *self {
|
||||
ColoredTerminal::Colored(ref mut w) => f(w),
|
||||
ColoredTerminal::NoColor(_) => Err(term::Error::NotSupported),
|
||||
}
|
||||
}
|
||||
|
||||
fn map_bool<F>(
|
||||
&self,
|
||||
mut f: F,
|
||||
) -> bool
|
||||
where F: FnMut(&T) -> bool {
|
||||
match *self {
|
||||
ColoredTerminal::Colored(ref w) => f(w),
|
||||
ColoredTerminal::NoColor(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Terminal + Send> io::Write for ColoredTerminal<T> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
match *self {
|
||||
ColoredTerminal::Colored(ref mut w) => w.write(buf),
|
||||
ColoredTerminal::NoColor(ref mut w) => w.write(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Terminal + Send> term::Terminal for ColoredTerminal<T> {
|
||||
type Output = T::Output;
|
||||
|
||||
fn fg(&mut self, fg: term::color::Color) -> term::Result<()> {
|
||||
self.map_result(|w| w.fg(fg))
|
||||
}
|
||||
|
||||
fn bg(&mut self, bg: term::color::Color) -> term::Result<()> {
|
||||
self.map_result(|w| w.bg(bg))
|
||||
}
|
||||
|
||||
fn attr(&mut self, attr: term::Attr) -> term::Result<()> {
|
||||
self.map_result(|w| w.attr(attr))
|
||||
}
|
||||
|
||||
fn supports_attr(&self, attr: term::Attr) -> bool {
|
||||
self.map_bool(|w| w.supports_attr(attr))
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> term::Result<()> {
|
||||
self.map_result(|w| w.reset())
|
||||
}
|
||||
|
||||
fn supports_reset(&self) -> bool {
|
||||
self.map_bool(|w| w.supports_reset())
|
||||
}
|
||||
|
||||
fn supports_color(&self) -> bool {
|
||||
self.map_bool(|w| w.supports_color())
|
||||
}
|
||||
|
||||
fn cursor_up(&mut self) -> term::Result<()> {
|
||||
self.map_result(|w| w.cursor_up())
|
||||
}
|
||||
|
||||
fn delete_line(&mut self) -> term::Result<()> {
|
||||
self.map_result(|w| w.delete_line())
|
||||
}
|
||||
|
||||
fn carriage_return(&mut self) -> term::Result<()> {
|
||||
self.map_result(|w| w.carriage_return())
|
||||
}
|
||||
|
||||
fn get_ref(&self) -> &Self::Output {
|
||||
match *self {
|
||||
ColoredTerminal::Colored(ref w) => w.get_ref(),
|
||||
ColoredTerminal::NoColor(ref w) => w,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut Self::Output {
|
||||
match *self {
|
||||
ColoredTerminal::Colored(ref mut w) => w.get_mut(),
|
||||
ColoredTerminal::NoColor(ref mut w) => w,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_inner(self) -> Self::Output {
|
||||
match self {
|
||||
ColoredTerminal::Colored(w) => w.into_inner(),
|
||||
ColoredTerminal::NoColor(w) => w,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
100
src/pathutil.rs
Normal file
100
src/pathutil.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
/*!
|
||||
The pathutil module provides platform specific operations on paths that are
|
||||
typically faster than the same operations as provided in std::path. In
|
||||
particular, we really want to avoid the costly operation of parsing the path
|
||||
into its constituent components. We give up on Windows, but on Unix, we deal
|
||||
with the raw bytes directly.
|
||||
|
||||
On large repositories (like chromium), this can have a ~25% performance
|
||||
improvement on just listing the files to search (!).
|
||||
*/
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
|
||||
/// Strip `prefix` from the `path` and return the remainder.
|
||||
///
|
||||
/// If `path` doesn't have a prefix `prefix`, then return `None`.
|
||||
#[cfg(unix)]
|
||||
pub fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
|
||||
prefix: &'a P,
|
||||
path: &'a Path,
|
||||
) -> Option<&'a Path> {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
let prefix = prefix.as_ref().as_os_str().as_bytes();
|
||||
let path = path.as_os_str().as_bytes();
|
||||
if prefix.len() > path.len() || prefix != &path[0..prefix.len()] {
|
||||
None
|
||||
} else {
|
||||
Some(&Path::new(OsStr::from_bytes(&path[prefix.len()..])))
|
||||
}
|
||||
}
|
||||
|
||||
/// Strip `prefix` from the `path` and return the remainder.
|
||||
///
|
||||
/// If `path` doesn't have a prefix `prefix`, then return `None`.
|
||||
#[cfg(not(unix))]
|
||||
pub fn strip_prefix<'a, P: AsRef<Path> + ?Sized>(
|
||||
prefix: &'a P,
|
||||
path: &'a Path,
|
||||
) -> Option<&'a Path> {
|
||||
path.strip_prefix(prefix).ok()
|
||||
}
|
||||
|
||||
/// The final component of the path, if it is a normal file.
|
||||
///
|
||||
/// If the path terminates in ., .., or consists solely of a root of prefix,
|
||||
/// file_name will return None.
|
||||
#[cfg(unix)]
|
||||
pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
|
||||
path: &'a P,
|
||||
) -> Option<&'a OsStr> {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use memchr::memrchr;
|
||||
|
||||
let path = path.as_ref().as_os_str().as_bytes();
|
||||
if path.is_empty() {
|
||||
return None;
|
||||
} else if path.len() == 1 && path[0] == b'.' {
|
||||
return None;
|
||||
} else if path.last() == Some(&b'.') {
|
||||
return None;
|
||||
} else if path.len() >= 2 && &path[path.len() - 2..] == &b".."[..] {
|
||||
return None;
|
||||
}
|
||||
let last_slash = memrchr(b'/', path).map(|i| i + 1).unwrap_or(0);
|
||||
Some(OsStr::from_bytes(&path[last_slash..]))
|
||||
}
|
||||
|
||||
/// The final component of the path, if it is a normal file.
|
||||
///
|
||||
/// If the path terminates in ., .., or consists solely of a root of prefix,
|
||||
/// file_name will return None.
|
||||
#[cfg(not(unix))]
|
||||
pub fn file_name<'a, P: AsRef<Path> + ?Sized>(
|
||||
path: &'a P,
|
||||
) -> Option<&'a OsStr> {
|
||||
path.as_ref().file_name()
|
||||
}
|
||||
|
||||
/// Returns true if and only if this file path is considered to be hidden.
|
||||
#[cfg(unix)]
|
||||
pub fn is_hidden<P: AsRef<Path>>(path: P) -> bool {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
if let Some(name) = file_name(path.as_ref()) {
|
||||
name.as_bytes().get(0) == Some(&b'.')
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if and only if this file path is considered to be hidden.
|
||||
#[cfg(not(unix))]
|
||||
pub fn is_hidden<P: AsRef<Path>>(path: P) -> bool {
|
||||
if let Some(name) = file_name(path.as_ref()) {
|
||||
name.to_str().map(|s| s.starts_with(".")).unwrap_or(false)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
202
src/printer.rs
202
src/printer.rs
@@ -1,17 +1,11 @@
|
||||
use std::io::{self, Write};
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use regex::bytes::Regex;
|
||||
use term::{self, Terminal};
|
||||
use term::color::*;
|
||||
use term::terminfo::TermInfo;
|
||||
use term::{Attr, Terminal};
|
||||
use term::color;
|
||||
|
||||
use terminal::TerminfoTerminal;
|
||||
use types::FileTypeDef;
|
||||
|
||||
use self::Writer::*;
|
||||
|
||||
/// Printer encapsulates all output logic for searching.
|
||||
///
|
||||
/// Note that we currently ignore all write errors. It's probably worthwhile
|
||||
@@ -19,9 +13,11 @@ use self::Writer::*;
|
||||
/// writes to memory, neither of which commonly fail.
|
||||
pub struct Printer<W> {
|
||||
/// The underlying writer.
|
||||
wtr: Writer<W>,
|
||||
wtr: W,
|
||||
/// Whether anything has been printed to wtr yet.
|
||||
has_printed: bool,
|
||||
/// Whether to show column numbers for the first match or not.
|
||||
column: bool,
|
||||
/// The string to use to separate non-contiguous runs of context lines.
|
||||
context_separator: Vec<u8>,
|
||||
/// The end-of-line terminator used by the printer. In general, eols are
|
||||
@@ -40,14 +36,13 @@ pub struct Printer<W> {
|
||||
with_filename: bool,
|
||||
}
|
||||
|
||||
impl<W: Send + io::Write> Printer<W> {
|
||||
impl<W: Terminal + Send> Printer<W> {
|
||||
/// Create a new printer that writes to wtr.
|
||||
///
|
||||
/// `color` should be true if the printer should try to use coloring.
|
||||
pub fn new(wtr: W, color: bool) -> Printer<W> {
|
||||
pub fn new(wtr: W) -> Printer<W> {
|
||||
Printer {
|
||||
wtr: Writer::new(wtr, color),
|
||||
wtr: wtr,
|
||||
has_printed: false,
|
||||
column: false,
|
||||
context_separator: "--".to_string().into_bytes(),
|
||||
eol: b'\n',
|
||||
heading: false,
|
||||
@@ -57,6 +52,13 @@ impl<W: Send + io::Write> Printer<W> {
|
||||
}
|
||||
}
|
||||
|
||||
/// When set, column numbers will be printed for the first match on each
|
||||
/// line.
|
||||
pub fn column(mut self, yes: bool) -> Printer<W> {
|
||||
self.column = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the context separator. The default is `--`.
|
||||
pub fn context_separator(mut self, sep: Vec<u8>) -> Printer<W> {
|
||||
self.context_separator = sep;
|
||||
@@ -107,7 +109,7 @@ impl<W: Send + io::Write> Printer<W> {
|
||||
/// Flushes the underlying writer and returns it.
|
||||
pub fn into_inner(mut self) -> W {
|
||||
let _ = self.wtr.flush();
|
||||
self.wtr.into_inner()
|
||||
self.wtr
|
||||
}
|
||||
|
||||
/// Prints a type definition.
|
||||
@@ -173,6 +175,11 @@ impl<W: Send + io::Write> Printer<W> {
|
||||
if let Some(line_number) = line_number {
|
||||
self.line_number(line_number, b':');
|
||||
}
|
||||
if self.column {
|
||||
let c = re.find(&buf[start..end]).map(|(s, _)| s + 1).unwrap_or(0);
|
||||
self.write(c.to_string().as_bytes());
|
||||
self.write(b":");
|
||||
}
|
||||
if self.replace.is_some() {
|
||||
let line = re.replace_all(
|
||||
&buf[start..end], &**self.replace.as_ref().unwrap());
|
||||
@@ -186,15 +193,15 @@ impl<W: Send + io::Write> Printer<W> {
|
||||
}
|
||||
|
||||
pub fn write_match(&mut self, re: &Regex, buf: &[u8]) {
|
||||
if !self.wtr.is_color() {
|
||||
if !self.wtr.supports_color() {
|
||||
self.write(buf);
|
||||
return;
|
||||
}
|
||||
let mut last_written = 0;
|
||||
for (s, e) in re.find_iter(buf) {
|
||||
self.write(&buf[last_written..s]);
|
||||
let _ = self.wtr.fg(BRIGHT_RED);
|
||||
let _ = self.wtr.attr(term::Attr::Bold);
|
||||
let _ = self.wtr.fg(color::BRIGHT_RED);
|
||||
let _ = self.wtr.attr(Attr::Bold);
|
||||
self.write(&buf[s..e]);
|
||||
let _ = self.wtr.reset();
|
||||
last_written = e;
|
||||
@@ -226,22 +233,24 @@ impl<W: Send + io::Write> Printer<W> {
|
||||
}
|
||||
|
||||
fn write_heading<P: AsRef<Path>>(&mut self, path: P) {
|
||||
if self.wtr.is_color() {
|
||||
let _ = self.wtr.fg(GREEN);
|
||||
if self.wtr.supports_color() {
|
||||
let _ = self.wtr.fg(color::BRIGHT_GREEN);
|
||||
let _ = self.wtr.attr(Attr::Bold);
|
||||
}
|
||||
self.write(path.as_ref().to_string_lossy().as_bytes());
|
||||
self.write_eol();
|
||||
if self.wtr.is_color() {
|
||||
if self.wtr.supports_color() {
|
||||
let _ = self.wtr.reset();
|
||||
}
|
||||
}
|
||||
|
||||
fn line_number(&mut self, n: u64, sep: u8) {
|
||||
if self.wtr.is_color() {
|
||||
let _ = self.wtr.fg(YELLOW);
|
||||
if self.wtr.supports_color() {
|
||||
let _ = self.wtr.fg(color::BRIGHT_BLUE);
|
||||
let _ = self.wtr.attr(Attr::Bold);
|
||||
}
|
||||
self.write(n.to_string().as_bytes());
|
||||
if self.wtr.is_color() {
|
||||
if self.wtr.supports_color() {
|
||||
let _ = self.wtr.reset();
|
||||
}
|
||||
self.write(&[sep]);
|
||||
@@ -260,148 +269,3 @@ impl<W: Send + io::Write> Printer<W> {
|
||||
self.write(&[eol]);
|
||||
}
|
||||
}
|
||||
|
||||
enum Writer<W> {
|
||||
Colored(TerminfoTerminal<W>),
|
||||
NoColor(W),
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref TERMINFO: Option<Arc<TermInfo>> = {
|
||||
match term::terminfo::TermInfo::from_env() {
|
||||
Ok(info) => Some(Arc::new(info)),
|
||||
Err(err) => {
|
||||
debug!("error loading terminfo for coloring: {}", err);
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<W: Send + io::Write> Writer<W> {
|
||||
fn new(wtr: W, color: bool) -> Writer<W> {
|
||||
// If we want color, build a TerminfoTerminal and see if the current
|
||||
// environment supports coloring. If not, bail with NoColor. To avoid
|
||||
// losing our writer (ownership), do this the long way.
|
||||
if !color || TERMINFO.is_none() {
|
||||
return NoColor(wtr);
|
||||
}
|
||||
let info = TERMINFO.clone().unwrap();
|
||||
let tt = TerminfoTerminal::new_with_terminfo(wtr, info);
|
||||
if !tt.supports_color() {
|
||||
debug!("environment doesn't support coloring");
|
||||
return NoColor(tt.into_inner());
|
||||
}
|
||||
Colored(tt)
|
||||
}
|
||||
|
||||
fn is_color(&self) -> bool {
|
||||
match *self {
|
||||
Colored(_) => true,
|
||||
NoColor(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_result<F>(
|
||||
&mut self,
|
||||
mut f: F,
|
||||
) -> term::Result<()>
|
||||
where F: FnMut(&mut TerminfoTerminal<W>) -> term::Result<()> {
|
||||
match *self {
|
||||
Colored(ref mut w) => f(w),
|
||||
NoColor(_) => Err(term::Error::NotSupported),
|
||||
}
|
||||
}
|
||||
|
||||
fn map_bool<F>(
|
||||
&self,
|
||||
mut f: F,
|
||||
) -> bool
|
||||
where F: FnMut(&TerminfoTerminal<W>) -> bool {
|
||||
match *self {
|
||||
Colored(ref w) => f(w),
|
||||
NoColor(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Send + io::Write> io::Write for Writer<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
match *self {
|
||||
Colored(ref mut w) => w.write(buf),
|
||||
NoColor(ref mut w) => w.write(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
match *self {
|
||||
Colored(ref mut w) => w.flush(),
|
||||
NoColor(ref mut w) => w.flush(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Send + io::Write> term::Terminal for Writer<W> {
|
||||
type Output = W;
|
||||
|
||||
fn fg(&mut self, fg: term::color::Color) -> term::Result<()> {
|
||||
self.map_result(|w| w.fg(fg))
|
||||
}
|
||||
|
||||
fn bg(&mut self, bg: term::color::Color) -> term::Result<()> {
|
||||
self.map_result(|w| w.bg(bg))
|
||||
}
|
||||
|
||||
fn attr(&mut self, attr: term::Attr) -> term::Result<()> {
|
||||
self.map_result(|w| w.attr(attr))
|
||||
}
|
||||
|
||||
fn supports_attr(&self, attr: term::Attr) -> bool {
|
||||
self.map_bool(|w| w.supports_attr(attr))
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> term::Result<()> {
|
||||
self.map_result(|w| w.reset())
|
||||
}
|
||||
|
||||
fn supports_reset(&self) -> bool {
|
||||
self.map_bool(|w| w.supports_reset())
|
||||
}
|
||||
|
||||
fn supports_color(&self) -> bool {
|
||||
self.map_bool(|w| w.supports_color())
|
||||
}
|
||||
|
||||
fn cursor_up(&mut self) -> term::Result<()> {
|
||||
self.map_result(|w| w.cursor_up())
|
||||
}
|
||||
|
||||
fn delete_line(&mut self) -> term::Result<()> {
|
||||
self.map_result(|w| w.delete_line())
|
||||
}
|
||||
|
||||
fn carriage_return(&mut self) -> term::Result<()> {
|
||||
self.map_result(|w| w.carriage_return())
|
||||
}
|
||||
|
||||
fn get_ref(&self) -> &W {
|
||||
match *self {
|
||||
Colored(ref w) => w.get_ref(),
|
||||
NoColor(ref w) => w,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut W {
|
||||
match *self {
|
||||
Colored(ref mut w) => w.get_mut(),
|
||||
NoColor(ref mut w) => w,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_inner(self) -> W {
|
||||
match self {
|
||||
Colored(w) => w.into_inner(),
|
||||
NoColor(w) => w,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
275
src/search_buffer.rs
Normal file
275
src/search_buffer.rs
Normal file
@@ -0,0 +1,275 @@
|
||||
/*!
|
||||
The search_buffer module is responsible for searching a single file all in a
|
||||
single buffer. Typically, the source of the buffer is a memory map. This can
|
||||
be useful for when memory maps are faster than streaming search.
|
||||
|
||||
Note that this module doesn't quite support everything that search_stream does.
|
||||
Notably, showing contexts.
|
||||
*/
|
||||
use std::cmp;
|
||||
use std::path::Path;
|
||||
|
||||
use grep::Grep;
|
||||
use term::Terminal;
|
||||
|
||||
use printer::Printer;
|
||||
use search_stream::{IterLines, Options, count_lines, is_binary};
|
||||
|
||||
pub struct BufferSearcher<'a, W: 'a> {
|
||||
opts: Options,
|
||||
printer: &'a mut Printer<W>,
|
||||
grep: &'a Grep,
|
||||
path: &'a Path,
|
||||
buf: &'a [u8],
|
||||
match_count: u64,
|
||||
line_count: Option<u64>,
|
||||
last_line: usize,
|
||||
}
|
||||
|
||||
impl<'a, W: Send + Terminal> BufferSearcher<'a, W> {
|
||||
pub fn new(
|
||||
printer: &'a mut Printer<W>,
|
||||
grep: &'a Grep,
|
||||
path: &'a Path,
|
||||
buf: &'a [u8],
|
||||
) -> BufferSearcher<'a, W> {
|
||||
BufferSearcher {
|
||||
opts: Options::default(),
|
||||
printer: printer,
|
||||
grep: grep,
|
||||
path: path,
|
||||
buf: buf,
|
||||
match_count: 0,
|
||||
line_count: None,
|
||||
last_line: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// If enabled, searching will print a count instead of each match.
|
||||
///
|
||||
/// Disabled by default.
|
||||
pub fn count(mut self, yes: bool) -> Self {
|
||||
self.opts.count = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the end-of-line byte used by this searcher.
|
||||
pub fn eol(mut self, eol: u8) -> Self {
|
||||
self.opts.eol = eol;
|
||||
self
|
||||
}
|
||||
|
||||
/// If enabled, matching is inverted so that lines that *don't* match the
|
||||
/// given pattern are treated as matches.
|
||||
pub fn invert_match(mut self, yes: bool) -> Self {
|
||||
self.opts.invert_match = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// If enabled, compute line numbers and prefix each line of output with
|
||||
/// them.
|
||||
pub fn line_number(mut self, yes: bool) -> Self {
|
||||
self.opts.line_number = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// If enabled, search binary files as if they were text.
|
||||
pub fn text(mut self, yes: bool) -> Self {
|
||||
self.opts.text = yes;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn run(mut self) -> u64 {
|
||||
let binary_upto = cmp::min(4096, self.buf.len());
|
||||
if !self.opts.text && is_binary(&self.buf[..binary_upto]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
self.match_count = 0;
|
||||
self.line_count = if self.opts.line_number { Some(0) } else { None };
|
||||
let mut last_end = 0;
|
||||
for m in self.grep.iter(self.buf) {
|
||||
if self.opts.invert_match {
|
||||
self.print_inverted_matches(last_end, m.start());
|
||||
} else {
|
||||
self.print_match(m.start(), m.end());
|
||||
}
|
||||
last_end = m.end();
|
||||
}
|
||||
if self.opts.invert_match {
|
||||
let upto = self.buf.len();
|
||||
self.print_inverted_matches(last_end, upto);
|
||||
}
|
||||
if self.opts.count && self.match_count > 0 {
|
||||
self.printer.path_count(self.path, self.match_count);
|
||||
}
|
||||
self.match_count
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn print_match(&mut self, start: usize, end: usize) {
|
||||
self.match_count += 1;
|
||||
if self.opts.count {
|
||||
return;
|
||||
}
|
||||
self.count_lines(start);
|
||||
self.add_line(end);
|
||||
self.printer.matched(
|
||||
self.grep.regex(), self.path, self.buf,
|
||||
start, end, self.line_count);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn print_inverted_matches(&mut self, start: usize, end: usize) {
|
||||
debug_assert!(self.opts.invert_match);
|
||||
let mut it = IterLines::new(self.opts.eol, start);
|
||||
while let Some((s, e)) = it.next(&self.buf[..end]) {
|
||||
self.print_match(s, e);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn count_lines(&mut self, upto: usize) {
|
||||
if let Some(ref mut line_count) = self.line_count {
|
||||
*line_count += count_lines(
|
||||
&self.buf[self.last_line..upto], self.opts.eol);
|
||||
self.last_line = upto;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn add_line(&mut self, line_end: usize) {
|
||||
if let Some(ref mut line_count) = self.line_count {
|
||||
*line_count += 1;
|
||||
self.last_line = line_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::Path;
|
||||
|
||||
use grep::GrepBuilder;
|
||||
use term::{Terminal, TerminfoTerminal};
|
||||
|
||||
use out::ColoredTerminal;
|
||||
use printer::Printer;
|
||||
|
||||
use super::BufferSearcher;
|
||||
|
||||
const SHERLOCK: &'static str = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
Holmeses, success in the province of detective work must always
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
can extract a clew from a wisp of straw or a flake of cigar ash;
|
||||
but Doctor Watson has to have it taken out for him and dusted,
|
||||
and exhibited clearly, with a label attached.\
|
||||
";
|
||||
|
||||
fn test_path() -> &'static Path {
|
||||
&Path::new("/baz.rs")
|
||||
}
|
||||
|
||||
type TestSearcher<'a> =
|
||||
BufferSearcher<'a, ColoredTerminal<TerminfoTerminal<Vec<u8>>>>;
|
||||
|
||||
fn search<F: FnMut(TestSearcher) -> TestSearcher>(
|
||||
pat: &str,
|
||||
haystack: &str,
|
||||
mut map: F,
|
||||
) -> (u64, String) {
|
||||
let outbuf = ColoredTerminal::NoColor(vec![]);
|
||||
let mut pp = Printer::new(outbuf).with_filename(true);
|
||||
let grep = GrepBuilder::new(pat).build().unwrap();
|
||||
let count = {
|
||||
let searcher = BufferSearcher::new(
|
||||
&mut pp, &grep, test_path(), haystack.as_bytes());
|
||||
map(searcher).run()
|
||||
};
|
||||
(count, String::from_utf8(pp.into_inner().into_inner()).unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_search() {
|
||||
let (count, out) = search("Sherlock", SHERLOCK, |s|s);
|
||||
assert_eq!(2, count);
|
||||
assert_eq!(out, "\
|
||||
/baz.rs:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
/baz.rs:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn binary() {
|
||||
let text = "Sherlock\n\x00Holmes\n";
|
||||
let (count, out) = search("Sherlock|Holmes", text, |s|s);
|
||||
assert_eq!(0, count);
|
||||
assert_eq!(out, "");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn binary_text() {
|
||||
let text = "Sherlock\n\x00Holmes\n";
|
||||
let (count, out) = search("Sherlock|Holmes", text, |s| s.text(true));
|
||||
assert_eq!(2, count);
|
||||
assert_eq!(out, "/baz.rs:Sherlock\n/baz.rs:\x00Holmes\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_numbers() {
|
||||
let (count, out) = search(
|
||||
"Sherlock", SHERLOCK, |s| s.line_number(true));
|
||||
assert_eq!(2, count);
|
||||
assert_eq!(out, "\
|
||||
/baz.rs:1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
/baz.rs:3:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn count() {
|
||||
let (count, out) = search(
|
||||
"Sherlock", SHERLOCK, |s| s.count(true));
|
||||
assert_eq!(2, count);
|
||||
assert_eq!(out, "/baz.rs:2\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invert_match() {
|
||||
let (count, out) = search(
|
||||
"Sherlock", SHERLOCK, |s| s.invert_match(true));
|
||||
assert_eq!(4, count);
|
||||
assert_eq!(out, "\
|
||||
/baz.rs:Holmeses, success in the province of detective work must always
|
||||
/baz.rs:can extract a clew from a wisp of straw or a flake of cigar ash;
|
||||
/baz.rs:but Doctor Watson has to have it taken out for him and dusted,
|
||||
/baz.rs:and exhibited clearly, with a label attached.
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invert_match_line_numbers() {
|
||||
let (count, out) = search("Sherlock", SHERLOCK, |s| {
|
||||
s.invert_match(true).line_number(true)
|
||||
});
|
||||
assert_eq!(4, count);
|
||||
assert_eq!(out, "\
|
||||
/baz.rs:2:Holmeses, success in the province of detective work must always
|
||||
/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,
|
||||
/baz.rs:6:and exhibited clearly, with a label attached.
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invert_match_count() {
|
||||
let (count, out) = search("Sherlock", SHERLOCK, |s| {
|
||||
s.invert_match(true).count(true)
|
||||
});
|
||||
assert_eq!(4, count);
|
||||
assert_eq!(out, "/baz.rs:4\n");
|
||||
}
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
/*!
|
||||
The search module is responsible for searching a single file and printing
|
||||
matches.
|
||||
The search_stream module is responsible for searching a single file and
|
||||
printing matches. In particular, it searches the file in a streaming fashion
|
||||
using `read` calls and a (roughly) fixed size buffer.
|
||||
*/
|
||||
|
||||
use std::cmp;
|
||||
@@ -11,6 +12,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use grep::{Grep, Match};
|
||||
use memchr::{memchr, memrchr};
|
||||
use term::Terminal;
|
||||
|
||||
use printer::Printer;
|
||||
|
||||
@@ -74,14 +76,14 @@ pub struct Searcher<'a, R, W: 'a> {
|
||||
|
||||
/// Options for configuring search.
|
||||
#[derive(Clone)]
|
||||
struct Options {
|
||||
after_context: usize,
|
||||
before_context: usize,
|
||||
count: bool,
|
||||
eol: u8,
|
||||
invert_match: bool,
|
||||
line_number: bool,
|
||||
text: bool,
|
||||
pub struct Options {
|
||||
pub after_context: usize,
|
||||
pub before_context: usize,
|
||||
pub count: bool,
|
||||
pub eol: u8,
|
||||
pub invert_match: bool,
|
||||
pub line_number: bool,
|
||||
pub text: bool,
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
@@ -98,7 +100,7 @@ impl Default for Options {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
|
||||
impl<'a, R: io::Read, W: Terminal + Send> Searcher<'a, R, W> {
|
||||
/// Create a new searcher.
|
||||
///
|
||||
/// `inp` is a reusable input buffer that is used as scratch space by this
|
||||
@@ -219,14 +221,11 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
|
||||
self.print_inverted_matches(upto);
|
||||
}
|
||||
} else if matched {
|
||||
self.match_count += 1;
|
||||
if !self.opts.count {
|
||||
let start = self.last_match.start();
|
||||
let end = self.last_match.end();
|
||||
self.print_after_context(start);
|
||||
self.print_before_context(start);
|
||||
self.print_match(start, end);
|
||||
}
|
||||
let start = self.last_match.start();
|
||||
let end = self.last_match.end();
|
||||
self.print_after_context(start);
|
||||
self.print_before_context(start);
|
||||
self.print_match(start, end);
|
||||
}
|
||||
if matched {
|
||||
self.inp.pos = self.last_match.end();
|
||||
@@ -275,11 +274,8 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
|
||||
debug_assert!(self.opts.invert_match);
|
||||
let mut it = IterLines::new(self.opts.eol, self.inp.pos);
|
||||
while let Some((start, end)) = it.next(&self.inp.buf[..upto]) {
|
||||
if !self.opts.count {
|
||||
self.print_match(start, end);
|
||||
}
|
||||
self.print_match(start, end);
|
||||
self.inp.pos = end;
|
||||
self.match_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,11 +321,15 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> {
|
||||
|
||||
#[inline(always)]
|
||||
fn print_match(&mut self, start: usize, end: usize) {
|
||||
self.match_count += 1;
|
||||
if self.opts.count {
|
||||
return;
|
||||
}
|
||||
self.print_separator(start);
|
||||
self.count_lines(start);
|
||||
self.add_line(end);
|
||||
self.printer.matched(
|
||||
self.grep.regex(), &self.path,
|
||||
self.grep.regex(), self.path,
|
||||
&self.inp.buf, start, end, self.line_count);
|
||||
self.last_printed = end;
|
||||
self.after_context_remaining = self.opts.after_context;
|
||||
@@ -535,7 +535,7 @@ impl InputBuffer {
|
||||
///
|
||||
/// Note that this may return both false positives and false negatives.
|
||||
#[inline(always)]
|
||||
fn is_binary(buf: &[u8]) -> bool {
|
||||
pub fn is_binary(buf: &[u8]) -> bool {
|
||||
if buf.len() >= 4 && &buf[0..4] == b"%PDF" {
|
||||
return true;
|
||||
}
|
||||
@@ -543,13 +543,88 @@ fn is_binary(buf: &[u8]) -> bool {
|
||||
}
|
||||
|
||||
/// Count the number of lines in the given buffer.
|
||||
#[inline(always)]
|
||||
fn count_lines(mut buf: &[u8], eol: u8) -> u64 {
|
||||
let mut count = 0;
|
||||
while let Some(pos) = memchr(eol, buf) {
|
||||
count += 1;
|
||||
buf = &buf[pos + 1..];
|
||||
#[inline(never)]
|
||||
|
||||
#[inline(never)]
|
||||
pub fn count_lines(buf: &[u8], eol: u8) -> u64 {
|
||||
// This was adapted from code in the memchr crate. The specific benefit
|
||||
// here is that we can avoid a branch in the inner loop because all we're
|
||||
// doing is counting.
|
||||
|
||||
// The technique to count EOL bytes was adapted from:
|
||||
// http://bits.stephan-brumme.com/null.html
|
||||
const LO_U64: u64 = 0x0101010101010101;
|
||||
const HI_U64: u64 = 0x8080808080808080;
|
||||
|
||||
// use truncation
|
||||
const LO_USIZE: usize = LO_U64 as usize;
|
||||
const HI_USIZE: usize = HI_U64 as usize;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const USIZE_BYTES: usize = 4;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const USIZE_BYTES: usize = 8;
|
||||
|
||||
fn count_eol(eol: usize) -> u64 {
|
||||
// Ideally, this would compile down to a POPCNT instruction, but
|
||||
// it looks like you need to set RUSTFLAGS="-C target-cpu=native"
|
||||
// (or target-feature=+popcnt) to get that to work. Bummer.
|
||||
(eol.wrapping_sub(LO_USIZE) & !eol & HI_USIZE).count_ones() as u64
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
fn repeat_byte(b: u8) -> usize {
|
||||
let mut rep = (b as usize) << 8 | b as usize;
|
||||
rep = rep << 16 | rep;
|
||||
rep
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
fn repeat_byte(b: u8) -> usize {
|
||||
let mut rep = (b as usize) << 8 | b as usize;
|
||||
rep = rep << 16 | rep;
|
||||
rep = rep << 32 | rep;
|
||||
rep
|
||||
}
|
||||
|
||||
fn count_lines_slow(mut buf: &[u8], eol: u8) -> u64 {
|
||||
let mut count = 0;
|
||||
while let Some(pos) = memchr(eol, buf) {
|
||||
count += 1;
|
||||
buf = &buf[pos + 1..];
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
let len = buf.len();
|
||||
let ptr = buf.as_ptr();
|
||||
let mut count = 0;
|
||||
|
||||
// Search up to an aligned boundary...
|
||||
let align = (ptr as usize) & (USIZE_BYTES - 1);
|
||||
let mut i = 0;
|
||||
if align > 0 {
|
||||
i = cmp::min(USIZE_BYTES - align, len);
|
||||
count += count_lines_slow(&buf[..i], eol);
|
||||
}
|
||||
|
||||
// ... and search the rest.
|
||||
let repeated_eol = repeat_byte(eol);
|
||||
|
||||
if len >= 2 * USIZE_BYTES {
|
||||
while i <= len - (2 * USIZE_BYTES) {
|
||||
unsafe {
|
||||
let u = *(ptr.offset(i as isize) as *const usize);
|
||||
let v = *(ptr.offset((i + USIZE_BYTES) as isize)
|
||||
as *const usize);
|
||||
|
||||
count += count_eol(u ^ repeated_eol);
|
||||
count += count_eol(v ^ repeated_eol);
|
||||
}
|
||||
i += USIZE_BYTES * 2;
|
||||
}
|
||||
}
|
||||
count += count_lines_slow(&buf[i..], eol);
|
||||
count
|
||||
}
|
||||
|
||||
@@ -575,7 +650,7 @@ fn replace_buf(buf: &mut [u8], a: u8, b: u8) {
|
||||
/// advance over the positions of each line. We neglect that approach to avoid
|
||||
/// the borrow in the search code. (Because the borrow prevents composition
|
||||
/// through other mutable methods.)
|
||||
struct IterLines {
|
||||
pub struct IterLines {
|
||||
eol: u8,
|
||||
pos: usize,
|
||||
}
|
||||
@@ -585,7 +660,7 @@ impl IterLines {
|
||||
///
|
||||
/// The buffer is passed to the `next` method.
|
||||
#[inline(always)]
|
||||
fn new(eol: u8, start: usize) -> IterLines {
|
||||
pub fn new(eol: u8, start: usize) -> IterLines {
|
||||
IterLines {
|
||||
eol: eol,
|
||||
pos: start,
|
||||
@@ -597,7 +672,7 @@ impl IterLines {
|
||||
///
|
||||
/// The range returned includes the new line.
|
||||
#[inline(always)]
|
||||
fn next(&mut self, buf: &[u8]) -> Option<(usize, usize)> {
|
||||
pub fn next(&mut self, buf: &[u8]) -> Option<(usize, usize)> {
|
||||
match memchr(self.eol, &buf[self.pos..]) {
|
||||
None => {
|
||||
if self.pos < buf.len() {
|
||||
@@ -688,14 +763,15 @@ mod tests {
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
|
||||
use grep::{Grep, GrepBuilder};
|
||||
use grep::GrepBuilder;
|
||||
use term::{Terminal, TerminfoTerminal};
|
||||
|
||||
use out::ColoredTerminal;
|
||||
use printer::Printer;
|
||||
|
||||
use super::{InputBuffer, Searcher, start_of_previous_lines};
|
||||
|
||||
lazy_static! {
|
||||
static ref SHERLOCK: &'static str = "\
|
||||
const SHERLOCK: &'static str = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
Holmeses, success in the province of detective work must always
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
@@ -703,7 +779,8 @@ can extract a clew from a wisp of straw or a flake of cigar ash;
|
||||
but Doctor Watson has to have it taken out for him and dusted,
|
||||
and exhibited clearly, with a label attached.\
|
||||
";
|
||||
static ref CODE: &'static str = "\
|
||||
|
||||
const CODE: &'static str = "\
|
||||
extern crate snap;
|
||||
|
||||
use std::io;
|
||||
@@ -718,21 +795,20 @@ fn main() {
|
||||
io::copy(&mut rdr, &mut wtr).expect(\"I/O operation failed\");
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
fn hay(s: &str) -> io::Cursor<Vec<u8>> {
|
||||
io::Cursor::new(s.to_string().into_bytes())
|
||||
}
|
||||
|
||||
fn matcher(pat: &str) -> Grep {
|
||||
GrepBuilder::new(pat).build().unwrap()
|
||||
}
|
||||
|
||||
fn test_path() -> &'static Path {
|
||||
&Path::new("/baz.rs")
|
||||
}
|
||||
|
||||
type TestSearcher<'a> = Searcher<'a, io::Cursor<Vec<u8>>, Vec<u8>>;
|
||||
type TestSearcher<'a> = Searcher<
|
||||
'a,
|
||||
io::Cursor<Vec<u8>>,
|
||||
ColoredTerminal<TerminfoTerminal<Vec<u8>>>,
|
||||
>;
|
||||
|
||||
fn search_smallcap<F: FnMut(TestSearcher) -> TestSearcher>(
|
||||
pat: &str,
|
||||
@@ -740,14 +816,15 @@ fn main() {
|
||||
mut map: F,
|
||||
) -> (u64, String) {
|
||||
let mut inp = InputBuffer::with_capacity(1);
|
||||
let mut pp = Printer::new(vec![], false).with_filename(true);
|
||||
let outbuf = ColoredTerminal::NoColor(vec![]);
|
||||
let mut pp = Printer::new(outbuf).with_filename(true);
|
||||
let grep = GrepBuilder::new(pat).build().unwrap();
|
||||
let count = {
|
||||
let searcher = Searcher::new(
|
||||
&mut inp, &mut pp, &grep, test_path(), hay(haystack));
|
||||
map(searcher).run().unwrap()
|
||||
};
|
||||
(count, String::from_utf8(pp.into_inner()).unwrap())
|
||||
(count, String::from_utf8(pp.into_inner().into_inner()).unwrap())
|
||||
}
|
||||
|
||||
fn search<F: FnMut(TestSearcher) -> TestSearcher>(
|
||||
@@ -756,14 +833,15 @@ fn main() {
|
||||
mut map: F,
|
||||
) -> (u64, String) {
|
||||
let mut inp = InputBuffer::with_capacity(4096);
|
||||
let mut pp = Printer::new(vec![], false).with_filename(true);
|
||||
let outbuf = ColoredTerminal::NoColor(vec![]);
|
||||
let mut pp = Printer::new(outbuf).with_filename(true);
|
||||
let grep = GrepBuilder::new(pat).build().unwrap();
|
||||
let count = {
|
||||
let searcher = Searcher::new(
|
||||
&mut inp, &mut pp, &grep, test_path(), hay(haystack));
|
||||
map(searcher).run().unwrap()
|
||||
};
|
||||
(count, String::from_utf8(pp.into_inner()).unwrap())
|
||||
(count, String::from_utf8(pp.into_inner().into_inner()).unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -870,8 +948,8 @@ fn main() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_search() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s|s);
|
||||
fn basic_search1() {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s|s);
|
||||
assert_eq!(2, count);
|
||||
assert_eq!(out, "\
|
||||
/baz.rs:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
@@ -887,7 +965,6 @@ fn main() {
|
||||
assert_eq!(out, "");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn binary_text() {
|
||||
let text = "Sherlock\n\x00Holmes\n";
|
||||
@@ -899,7 +976,7 @@ fn main() {
|
||||
#[test]
|
||||
fn line_numbers() {
|
||||
let (count, out) = search_smallcap(
|
||||
"Sherlock", &*SHERLOCK, |s| s.line_number(true));
|
||||
"Sherlock", SHERLOCK, |s| s.line_number(true));
|
||||
assert_eq!(2, count);
|
||||
assert_eq!(out, "\
|
||||
/baz.rs:1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
@@ -910,7 +987,7 @@ fn main() {
|
||||
#[test]
|
||||
fn count() {
|
||||
let (count, out) = search_smallcap(
|
||||
"Sherlock", &*SHERLOCK, |s| s.count(true));
|
||||
"Sherlock", SHERLOCK, |s| s.count(true));
|
||||
assert_eq!(2, count);
|
||||
assert_eq!(out, "/baz.rs:2\n");
|
||||
}
|
||||
@@ -918,7 +995,7 @@ fn main() {
|
||||
#[test]
|
||||
fn invert_match() {
|
||||
let (count, out) = search_smallcap(
|
||||
"Sherlock", &*SHERLOCK, |s| s.invert_match(true));
|
||||
"Sherlock", SHERLOCK, |s| s.invert_match(true));
|
||||
assert_eq!(4, count);
|
||||
assert_eq!(out, "\
|
||||
/baz.rs:Holmeses, success in the province of detective work must always
|
||||
@@ -930,7 +1007,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn invert_match_line_numbers() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.invert_match(true).line_number(true)
|
||||
});
|
||||
assert_eq!(4, count);
|
||||
@@ -944,7 +1021,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn invert_match_count() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.invert_match(true).count(true)
|
||||
});
|
||||
assert_eq!(4, count);
|
||||
@@ -953,7 +1030,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn before_context_one1() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.line_number(true).before_context(1)
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
@@ -966,7 +1043,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn before_context_invert_one1() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.line_number(true).before_context(1).invert_match(true)
|
||||
});
|
||||
assert_eq!(4, count);
|
||||
@@ -982,7 +1059,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn before_context_invert_one2() {
|
||||
let (count, out) = search_smallcap(" a ", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap(" a ", SHERLOCK, |s| {
|
||||
s.line_number(true).before_context(1).invert_match(true)
|
||||
});
|
||||
assert_eq!(3, count);
|
||||
@@ -997,7 +1074,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn before_context_two1() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.line_number(true).before_context(2)
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
@@ -1010,7 +1087,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn before_context_two2() {
|
||||
let (count, out) = search_smallcap("dusted", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("dusted", SHERLOCK, |s| {
|
||||
s.line_number(true).before_context(2)
|
||||
});
|
||||
assert_eq!(1, count);
|
||||
@@ -1024,7 +1101,7 @@ fn main() {
|
||||
#[test]
|
||||
fn before_context_two3() {
|
||||
let (count, out) = search_smallcap(
|
||||
"success|attached", &*SHERLOCK, |s| {
|
||||
"success|attached", SHERLOCK, |s| {
|
||||
s.line_number(true).before_context(2)
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
@@ -1040,7 +1117,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn before_context_two4() {
|
||||
let (count, out) = search("stdin", &*CODE, |s| {
|
||||
let (count, out) = search("stdin", CODE, |s| {
|
||||
s.line_number(true).before_context(2)
|
||||
});
|
||||
assert_eq!(3, count);
|
||||
@@ -1057,7 +1134,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn before_context_two5() {
|
||||
let (count, out) = search("stdout", &*CODE, |s| {
|
||||
let (count, out) = search("stdout", CODE, |s| {
|
||||
s.line_number(true).before_context(2)
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
@@ -1074,7 +1151,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn before_context_three1() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.line_number(true).before_context(3)
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
@@ -1087,7 +1164,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn after_context_one1() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.line_number(true).after_context(1)
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
@@ -1101,7 +1178,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn after_context_invert_one1() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.line_number(true).after_context(1).invert_match(true)
|
||||
});
|
||||
assert_eq!(4, count);
|
||||
@@ -1116,7 +1193,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn after_context_invert_one2() {
|
||||
let (count, out) = search_smallcap(" a ", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap(" a ", SHERLOCK, |s| {
|
||||
s.line_number(true).after_context(1).invert_match(true)
|
||||
});
|
||||
assert_eq!(3, count);
|
||||
@@ -1132,7 +1209,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn after_context_two1() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.line_number(true).after_context(2)
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
@@ -1147,7 +1224,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn after_context_two2() {
|
||||
let (count, out) = search_smallcap("dusted", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("dusted", SHERLOCK, |s| {
|
||||
s.line_number(true).after_context(2)
|
||||
});
|
||||
assert_eq!(1, count);
|
||||
@@ -1160,7 +1237,7 @@ fn main() {
|
||||
#[test]
|
||||
fn after_context_two3() {
|
||||
let (count, out) = search_smallcap(
|
||||
"success|attached", &*SHERLOCK, |s| {
|
||||
"success|attached", SHERLOCK, |s| {
|
||||
s.line_number(true).after_context(2)
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
@@ -1175,7 +1252,7 @@ fn main() {
|
||||
|
||||
#[test]
|
||||
fn after_context_three1() {
|
||||
let (count, out) = search_smallcap("Sherlock", &*SHERLOCK, |s| {
|
||||
let (count, out) = search_smallcap("Sherlock", SHERLOCK, |s| {
|
||||
s.line_number(true).after_context(3)
|
||||
});
|
||||
assert_eq!(2, count);
|
||||
@@ -1192,7 +1269,7 @@ fn main() {
|
||||
#[test]
|
||||
fn before_after_context_two1() {
|
||||
let (count, out) = search(
|
||||
r"fn main|let mut rdr", &*CODE, |s| {
|
||||
r"fn main|let mut rdr", CODE, |s| {
|
||||
s.line_number(true).after_context(2).before_context(2)
|
||||
});
|
||||
assert_eq!(2, count);
|
202
src/terminal.rs
202
src/terminal.rs
@@ -1,202 +0,0 @@
|
||||
/*!
|
||||
This module contains an implementation of the `term::Terminal` trait.
|
||||
|
||||
The actual implementation is copied almost verbatim from the `term` crate, so
|
||||
this code is under the same license (MIT/Apache).
|
||||
|
||||
The specific reason why this is copied here is to wrap an Arc<TermInfo> instead
|
||||
of a TermInfo. This makes multithreaded sharing much more performant.
|
||||
|
||||
N.B. This is temporary until this issue is fixed:
|
||||
https://github.com/Stebalien/term/issues/64
|
||||
*/
|
||||
|
||||
use std::io::{self, Write};
|
||||
use std::sync::Arc;
|
||||
|
||||
use term::{Attr, Error, Result, Terminal, color};
|
||||
use term::terminfo::TermInfo;
|
||||
use term::terminfo::parm::{Param, Variables, expand};
|
||||
|
||||
/// A Terminal that knows how many colors it supports, with a reference to its
|
||||
/// parsed Terminfo database record.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TerminfoTerminal<T> {
|
||||
num_colors: u16,
|
||||
out: T,
|
||||
ti: Arc<TermInfo>,
|
||||
}
|
||||
|
||||
impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
|
||||
type Output = T;
|
||||
fn fg(&mut self, color: color::Color) -> Result<()> {
|
||||
let color = self.dim_if_necessary(color);
|
||||
if self.num_colors > color {
|
||||
return apply_cap(&self.ti, "setaf", &[Param::Number(color as i32)], &mut self.out);
|
||||
}
|
||||
Err(Error::ColorOutOfRange)
|
||||
}
|
||||
|
||||
fn bg(&mut self, color: color::Color) -> Result<()> {
|
||||
let color = self.dim_if_necessary(color);
|
||||
if self.num_colors > color {
|
||||
return apply_cap(&self.ti, "setab", &[Param::Number(color as i32)], &mut self.out);
|
||||
}
|
||||
Err(Error::ColorOutOfRange)
|
||||
}
|
||||
|
||||
fn attr(&mut self, attr: Attr) -> Result<()> {
|
||||
match attr {
|
||||
Attr::ForegroundColor(c) => self.fg(c),
|
||||
Attr::BackgroundColor(c) => self.bg(c),
|
||||
_ => apply_cap(&self.ti, cap_for_attr(attr), &[], &mut self.out),
|
||||
}
|
||||
}
|
||||
|
||||
fn supports_attr(&self, attr: Attr) -> bool {
|
||||
match attr {
|
||||
Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0,
|
||||
_ => {
|
||||
let cap = cap_for_attr(attr);
|
||||
self.ti.strings.get(cap).is_some()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> Result<()> {
|
||||
reset(&self.ti, &mut self.out)
|
||||
}
|
||||
|
||||
fn supports_reset(&self) -> bool {
|
||||
["sgr0", "sgr", "op"].iter().any(|&cap| self.ti.strings.get(cap).is_some())
|
||||
}
|
||||
|
||||
fn supports_color(&self) -> bool {
|
||||
self.num_colors > 0 && self.supports_reset()
|
||||
}
|
||||
|
||||
fn cursor_up(&mut self) -> Result<()> {
|
||||
apply_cap(&self.ti, "cuu1", &[], &mut self.out)
|
||||
}
|
||||
|
||||
fn delete_line(&mut self) -> Result<()> {
|
||||
apply_cap(&self.ti, "dl", &[], &mut self.out)
|
||||
}
|
||||
|
||||
fn carriage_return(&mut self) -> Result<()> {
|
||||
apply_cap(&self.ti, "cr", &[], &mut self.out)
|
||||
}
|
||||
|
||||
fn get_ref(&self) -> &T {
|
||||
&self.out
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut T {
|
||||
&mut self.out
|
||||
}
|
||||
|
||||
fn into_inner(self) -> T
|
||||
where Self: Sized
|
||||
{
|
||||
self.out
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Write + Send> TerminfoTerminal<T> {
|
||||
/// Create a new TerminfoTerminal with the given TermInfo and Write.
|
||||
pub fn new_with_terminfo(out: T, terminfo: Arc<TermInfo>) -> TerminfoTerminal<T> {
|
||||
let nc = if terminfo.strings.contains_key("setaf") &&
|
||||
terminfo.strings.contains_key("setab") {
|
||||
terminfo.numbers.get("colors").map_or(0, |&n| n)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
TerminfoTerminal {
|
||||
out: out,
|
||||
ti: terminfo,
|
||||
num_colors: nc,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new TerminfoTerminal for the current environment with the given Write.
|
||||
///
|
||||
/// Returns `None` when the terminfo cannot be found or parsed.
|
||||
pub fn new(out: T) -> Option<TerminfoTerminal<T>> {
|
||||
TermInfo::from_env().map(move |ti| {
|
||||
TerminfoTerminal::new_with_terminfo(out, Arc::new(ti))
|
||||
}).ok()
|
||||
}
|
||||
|
||||
fn dim_if_necessary(&self, color: color::Color) -> color::Color {
|
||||
if color >= self.num_colors && color >= 8 && color < 16 {
|
||||
color - 8
|
||||
} else {
|
||||
color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Write> Write for TerminfoTerminal<T> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.out.write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.out.flush()
|
||||
}
|
||||
}
|
||||
|
||||
fn cap_for_attr(attr: Attr) -> &'static str {
|
||||
match attr {
|
||||
Attr::Bold => "bold",
|
||||
Attr::Dim => "dim",
|
||||
Attr::Italic(true) => "sitm",
|
||||
Attr::Italic(false) => "ritm",
|
||||
Attr::Underline(true) => "smul",
|
||||
Attr::Underline(false) => "rmul",
|
||||
Attr::Blink => "blink",
|
||||
Attr::Standout(true) => "smso",
|
||||
Attr::Standout(false) => "rmso",
|
||||
Attr::Reverse => "rev",
|
||||
Attr::Secure => "invis",
|
||||
Attr::ForegroundColor(_) => "setaf",
|
||||
Attr::BackgroundColor(_) => "setab",
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_cap(ti: &TermInfo, cmd: &str, params: &[Param], out: &mut io::Write) -> Result<()> {
|
||||
match ti.strings.get(cmd) {
|
||||
Some(cmd) => {
|
||||
match expand(cmd, params, &mut Variables::new()) {
|
||||
Ok(s) => {
|
||||
try!(out.write_all(&s));
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
None => Err(Error::NotSupported),
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(ti: &TermInfo, out: &mut io::Write) -> Result<()> {
|
||||
// are there any terminals that have color/attrs and not sgr0?
|
||||
// Try falling back to sgr, then op
|
||||
let cmd = match [("sgr0", &[] as &[Param]), ("sgr", &[Param::Number(0)]), ("op", &[])]
|
||||
.iter()
|
||||
.filter_map(|&(cap, params)| {
|
||||
ti.strings.get(cap).map(|c| (c, params))
|
||||
})
|
||||
.next() {
|
||||
Some((op, params)) => {
|
||||
match expand(op, params, &mut Variables::new()) {
|
||||
Ok(cmd) => cmd,
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
None => return Err(Error::NotSupported),
|
||||
};
|
||||
try!(out.write_all(&cmd));
|
||||
Ok(())
|
||||
}
|
||||
|
176
src/terminal_win.rs
Normal file
176
src/terminal_win.rs
Normal file
@@ -0,0 +1,176 @@
|
||||
/*!
|
||||
This module contains a Windows-only *in-memory* implementation of the
|
||||
`term::Terminal` trait.
|
||||
|
||||
This particular implementation is a bit idiosyncratic, and the "in-memory"
|
||||
specification is to blame. In particular, on Windows, coloring requires
|
||||
communicating with the console synchronously as data is written to stdout.
|
||||
This is anathema to how ripgrep fundamentally works: by writing search results
|
||||
to intermediate thread local buffers in order to maximize parallelism.
|
||||
|
||||
Eliminating parallelism on Windows isn't an option, because that would negate
|
||||
a tremendous performance benefit just for coloring.
|
||||
|
||||
We've worked around this by providing an implementation of `term::Terminal`
|
||||
that records precisely where a color or a reset should be invoked, according
|
||||
to a byte offset in the in memory buffer. When the buffer is actually printed,
|
||||
we copy the bytes from the buffer to stdout incrementally while invoking the
|
||||
corresponding console APIs for coloring at the right location.
|
||||
|
||||
(Another approach would be to do ANSI coloring unconditionally, then parse that
|
||||
and translate it to console commands. The advantage of that approach is that
|
||||
it doesn't require any additional memory for storing offsets. In practice
|
||||
though, coloring is only used in the terminal, which tends to correspond to
|
||||
searches that produce very few results with respect to the corpus searched.
|
||||
Therefore, this is an acceptable trade off. Namely, we do not pay for it when
|
||||
coloring is disabled.
|
||||
*/
|
||||
use std::io;
|
||||
|
||||
use term::{self, Terminal};
|
||||
use term::color::Color;
|
||||
|
||||
/// An in-memory buffer that provides Windows console coloring.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WindowsBuffer {
|
||||
buf: Vec<u8>,
|
||||
pos: usize,
|
||||
colors: Vec<WindowsColor>,
|
||||
}
|
||||
|
||||
/// A color associated with a particular location in a buffer.
|
||||
#[derive(Clone, Debug)]
|
||||
struct WindowsColor {
|
||||
pos: usize,
|
||||
opt: WindowsOption,
|
||||
}
|
||||
|
||||
/// A color or reset directive that can be translated into an instruction to
|
||||
/// the Windows console.
|
||||
#[derive(Clone, Debug)]
|
||||
enum WindowsOption {
|
||||
Foreground(Color),
|
||||
Background(Color),
|
||||
Reset,
|
||||
}
|
||||
|
||||
impl WindowsBuffer {
|
||||
/// Create a new empty buffer for Windows console coloring.
|
||||
pub fn new() -> WindowsBuffer {
|
||||
WindowsBuffer {
|
||||
buf: vec![],
|
||||
pos: 0,
|
||||
colors: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn push(&mut self, opt: WindowsOption) {
|
||||
let pos = self.pos;
|
||||
self.colors.push(WindowsColor { pos: pos, opt: opt });
|
||||
}
|
||||
|
||||
/// Print the contents to the given terminal.
|
||||
pub fn print_stdout<T: Terminal + Send>(&self, tt: &mut T) {
|
||||
if !tt.supports_color() {
|
||||
let _ = tt.write_all(&self.buf);
|
||||
let _ = tt.flush();
|
||||
return;
|
||||
}
|
||||
let mut last = 0;
|
||||
for col in &self.colors {
|
||||
let _ = tt.write_all(&self.buf[last..col.pos]);
|
||||
match col.opt {
|
||||
WindowsOption::Foreground(c) => {
|
||||
let _ = tt.fg(c);
|
||||
}
|
||||
WindowsOption::Background(c) => {
|
||||
let _ = tt.bg(c);
|
||||
}
|
||||
WindowsOption::Reset => {
|
||||
let _ = tt.reset();
|
||||
}
|
||||
}
|
||||
last = col.pos;
|
||||
}
|
||||
let _ = tt.write_all(&self.buf[last..]);
|
||||
let _ = tt.flush();
|
||||
}
|
||||
|
||||
/// Clear the buffer.
|
||||
pub fn clear(&mut self) {
|
||||
self.buf.clear();
|
||||
self.colors.clear();
|
||||
self.pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for WindowsBuffer {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let n = try!(self.buf.write(buf));
|
||||
self.pos += n;
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Terminal for WindowsBuffer {
|
||||
type Output = Vec<u8>;
|
||||
|
||||
fn fg(&mut self, fg: Color) -> term::Result<()> {
|
||||
self.push(WindowsOption::Foreground(fg));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bg(&mut self, bg: Color) -> term::Result<()> {
|
||||
self.push(WindowsOption::Background(bg));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn attr(&mut self, _attr: term::Attr) -> term::Result<()> {
|
||||
Err(term::Error::NotSupported)
|
||||
}
|
||||
|
||||
fn supports_attr(&self, _attr: term::Attr) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> term::Result<()> {
|
||||
self.push(WindowsOption::Reset);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn supports_reset(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn supports_color(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn cursor_up(&mut self) -> term::Result<()> {
|
||||
Err(term::Error::NotSupported)
|
||||
}
|
||||
|
||||
fn delete_line(&mut self) -> term::Result<()> {
|
||||
Err(term::Error::NotSupported)
|
||||
}
|
||||
|
||||
fn carriage_return(&mut self) -> term::Result<()> {
|
||||
Err(term::Error::NotSupported)
|
||||
}
|
||||
|
||||
fn get_ref(&self) -> &Vec<u8> {
|
||||
&self.buf
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut Vec<u8> {
|
||||
&mut self.buf
|
||||
}
|
||||
|
||||
fn into_inner(self) -> Vec<u8> {
|
||||
self.buf
|
||||
}
|
||||
}
|
175
src/types.rs
175
src/types.rs
@@ -8,7 +8,10 @@ use std::error::Error as StdError;
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
|
||||
use gitignore::{self, Gitignore, GitignoreBuilder, Match, Pattern};
|
||||
use regex;
|
||||
|
||||
use gitignore::{Match, Pattern};
|
||||
use glob::{self, MatchOptions};
|
||||
|
||||
const TYPE_EXTENSIONS: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("asm", &["*.asm", "*.s", "*.S"]),
|
||||
@@ -55,6 +58,7 @@ const TYPE_EXTENSIONS: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("perl", &["*.perl", "*.pl", "*.PL", "*.plh", "*.plx", "*.pm"]),
|
||||
("php", &["*.php", "*.php3", "*.php4", "*.php5", "*.phtml"]),
|
||||
("py", &["*.py"]),
|
||||
("readme", &["README*", "*README"]),
|
||||
("rr", &["*.R"]),
|
||||
("rst", &["*.rst"]),
|
||||
("ruby", &["*.rb"]),
|
||||
@@ -81,7 +85,9 @@ pub enum Error {
|
||||
/// A user specified file type definition could not be parsed.
|
||||
InvalidDefinition,
|
||||
/// There was an error building the matcher (probably a bad glob).
|
||||
Gitignore(gitignore::Error),
|
||||
Glob(glob::Error),
|
||||
/// There was an error compiling a glob as a regex.
|
||||
Regex(regex::Error),
|
||||
}
|
||||
|
||||
impl StdError for Error {
|
||||
@@ -89,7 +95,8 @@ impl StdError for Error {
|
||||
match *self {
|
||||
Error::UnrecognizedFileType(_) => "unrecognized file type",
|
||||
Error::InvalidDefinition => "invalid definition",
|
||||
Error::Gitignore(ref err) => err.description(),
|
||||
Error::Glob(ref err) => err.description(),
|
||||
Error::Regex(ref err) => err.description(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,14 +111,21 @@ impl fmt::Display for Error {
|
||||
write!(f, "invalid definition (format is type:glob, e.g., \
|
||||
html:*.html)")
|
||||
}
|
||||
Error::Gitignore(ref err) => err.fmt(f),
|
||||
Error::Glob(ref err) => err.fmt(f),
|
||||
Error::Regex(ref err) => err.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gitignore::Error> for Error {
|
||||
fn from(err: gitignore::Error) -> Error {
|
||||
Error::Gitignore(err)
|
||||
impl From<glob::Error> for Error {
|
||||
fn from(err: glob::Error) -> Error {
|
||||
Error::Glob(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<regex::Error> for Error {
|
||||
fn from(err: regex::Error) -> Error {
|
||||
Error::Regex(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +151,8 @@ impl FileTypeDef {
|
||||
/// Types is a file type matcher.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Types {
|
||||
gi: Option<Gitignore>,
|
||||
selected: Option<glob::SetYesNo>,
|
||||
negated: Option<glob::SetYesNo>,
|
||||
has_selected: bool,
|
||||
unmatched_pat: Pattern,
|
||||
}
|
||||
@@ -149,14 +164,19 @@ impl Types {
|
||||
///
|
||||
/// If has_selected is true, then at least one file type was selected.
|
||||
/// Therefore, any non-matches should be ignored.
|
||||
fn new(gi: Option<Gitignore>, has_selected: bool) -> Types {
|
||||
fn new(
|
||||
selected: Option<glob::SetYesNo>,
|
||||
negated: Option<glob::SetYesNo>,
|
||||
has_selected: bool,
|
||||
) -> Types {
|
||||
Types {
|
||||
gi: gi,
|
||||
selected: selected,
|
||||
negated: negated,
|
||||
has_selected: has_selected,
|
||||
unmatched_pat: Pattern {
|
||||
from: Path::new("<filetype>").to_path_buf(),
|
||||
original: "<none>".to_string(),
|
||||
pat: "<none>".to_string(),
|
||||
original: "<N/A>".to_string(),
|
||||
pat: "<N/A>".to_string(),
|
||||
whitelist: false,
|
||||
only_dir: false,
|
||||
},
|
||||
@@ -165,7 +185,7 @@ impl Types {
|
||||
|
||||
/// Creates a new file type matcher that never matches.
|
||||
pub fn empty() -> Types {
|
||||
Types::new(None, false)
|
||||
Types::new(None, None, false)
|
||||
}
|
||||
|
||||
/// Returns a match for the given path against this file type matcher.
|
||||
@@ -175,22 +195,35 @@ impl Types {
|
||||
/// If at least one file type is selected and path doesn't match, then
|
||||
/// the path is also considered ignored.
|
||||
pub fn matched<P: AsRef<Path>>(&self, path: P, is_dir: bool) -> Match {
|
||||
// If we don't have any matcher, then we can't do anything.
|
||||
if self.negated.is_none() && self.selected.is_none() {
|
||||
return Match::None;
|
||||
}
|
||||
// File types don't apply to directories.
|
||||
if is_dir {
|
||||
return Match::None;
|
||||
}
|
||||
let path = path.as_ref();
|
||||
self.gi.as_ref()
|
||||
.map(|gi| {
|
||||
let path = &*path.to_string_lossy();
|
||||
let mat = gi.matched_utf8(path, is_dir).invert();
|
||||
if self.has_selected && mat.is_none() {
|
||||
Match::Ignored(&self.unmatched_pat)
|
||||
} else {
|
||||
mat
|
||||
}
|
||||
})
|
||||
.unwrap_or(Match::None)
|
||||
let name = match path.file_name() {
|
||||
Some(name) => name.to_string_lossy(),
|
||||
None if self.has_selected => {
|
||||
return Match::Ignored(&self.unmatched_pat);
|
||||
}
|
||||
None => {
|
||||
return Match::None;
|
||||
}
|
||||
};
|
||||
if self.negated.as_ref().map(|s| s.is_match(&*name)).unwrap_or(false) {
|
||||
return Match::Ignored(&self.unmatched_pat);
|
||||
}
|
||||
if self.selected.as_ref().map(|s|s.is_match(&*name)).unwrap_or(false) {
|
||||
return Match::Whitelist(&self.unmatched_pat);
|
||||
}
|
||||
if self.has_selected {
|
||||
Match::Ignored(&self.unmatched_pat)
|
||||
} else {
|
||||
Match::None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,8 +231,8 @@ impl Types {
|
||||
/// a set of file type selections.
|
||||
pub struct TypesBuilder {
|
||||
types: HashMap<String, Vec<String>>,
|
||||
select: Vec<String>,
|
||||
select_not: Vec<String>,
|
||||
selected: Vec<String>,
|
||||
negated: Vec<String>,
|
||||
}
|
||||
|
||||
impl TypesBuilder {
|
||||
@@ -207,41 +240,57 @@ impl TypesBuilder {
|
||||
pub fn new() -> TypesBuilder {
|
||||
TypesBuilder {
|
||||
types: HashMap::new(),
|
||||
select: vec![],
|
||||
select_not: vec![],
|
||||
selected: vec![],
|
||||
negated: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Build the current set of file type definitions *and* selections into
|
||||
/// a file type matcher.
|
||||
pub fn build(&self) -> Result<Types, Error> {
|
||||
if self.select.is_empty() && self.select_not.is_empty() {
|
||||
return Ok(Types::new(None, false));
|
||||
}
|
||||
let mut bgi = GitignoreBuilder::new("/");
|
||||
for name in &self.select {
|
||||
let globs = match self.types.get(name) {
|
||||
Some(globs) => globs,
|
||||
None => {
|
||||
return Err(Error::UnrecognizedFileType(name.to_string()));
|
||||
let opts = MatchOptions {
|
||||
require_literal_separator: true, ..MatchOptions::default()
|
||||
};
|
||||
let selected_globs =
|
||||
if self.selected.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let mut bset = glob::SetBuilder::new();
|
||||
for name in &self.selected {
|
||||
let globs = match self.types.get(name) {
|
||||
Some(globs) => globs,
|
||||
None => {
|
||||
let msg = name.to_string();
|
||||
return Err(Error::UnrecognizedFileType(msg));
|
||||
}
|
||||
};
|
||||
for glob in globs {
|
||||
try!(bset.add_with(glob, &opts));
|
||||
}
|
||||
}
|
||||
Some(try!(bset.build_yesno()))
|
||||
};
|
||||
for glob in globs {
|
||||
try!(bgi.add("<filetype>", glob));
|
||||
}
|
||||
}
|
||||
for name in &self.select_not {
|
||||
let globs = match self.types.get(name) {
|
||||
Some(globs) => globs,
|
||||
None => {
|
||||
return Err(Error::UnrecognizedFileType(name.to_string()));
|
||||
let negated_globs =
|
||||
if self.negated.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let mut bset = glob::SetBuilder::new();
|
||||
for name in &self.negated {
|
||||
let globs = match self.types.get(name) {
|
||||
Some(globs) => globs,
|
||||
None => {
|
||||
let msg = name.to_string();
|
||||
return Err(Error::UnrecognizedFileType(msg));
|
||||
}
|
||||
};
|
||||
for glob in globs {
|
||||
try!(bset.add_with(glob, &opts));
|
||||
}
|
||||
}
|
||||
Some(try!(bset.build_yesno()))
|
||||
};
|
||||
for glob in globs {
|
||||
try!(bgi.add("<filetype>", &format!("!{}", glob)));
|
||||
}
|
||||
}
|
||||
Ok(Types::new(Some(try!(bgi.build())), !self.select.is_empty()))
|
||||
Ok(Types::new(
|
||||
selected_globs, negated_globs, !self.selected.is_empty()))
|
||||
}
|
||||
|
||||
/// Return the set of current file type definitions.
|
||||
@@ -260,14 +309,30 @@ impl TypesBuilder {
|
||||
}
|
||||
|
||||
/// Select the file type given by `name`.
|
||||
///
|
||||
/// If `name` is `all`, then all file types are selected.
|
||||
pub fn select(&mut self, name: &str) -> &mut TypesBuilder {
|
||||
self.select.push(name.to_string());
|
||||
if name == "all" {
|
||||
for name in self.types.keys() {
|
||||
self.selected.push(name.to_string());
|
||||
}
|
||||
} else {
|
||||
self.selected.push(name.to_string());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Ignore the file type given by `name`.
|
||||
pub fn select_not(&mut self, name: &str) -> &mut TypesBuilder {
|
||||
self.select_not.push(name.to_string());
|
||||
///
|
||||
/// If `name` is `all`, then all file types are negated.
|
||||
pub fn negate(&mut self, name: &str) -> &mut TypesBuilder {
|
||||
if name == "all" {
|
||||
for name in self.types.keys() {
|
||||
self.negated.push(name.to_string());
|
||||
}
|
||||
} else {
|
||||
self.negated.push(name.to_string());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
@@ -333,7 +398,7 @@ mod tests {
|
||||
btypes.select(sel);
|
||||
}
|
||||
for selnot in $selnot {
|
||||
btypes.select_not(selnot);
|
||||
btypes.negate(selnot);
|
||||
}
|
||||
let types = btypes.build().unwrap();
|
||||
let mat = types.matched($path, false);
|
||||
|
@@ -26,6 +26,7 @@ impl Iter {
|
||||
}
|
||||
|
||||
/// Returns true if this entry should be skipped.
|
||||
#[inline(always)]
|
||||
fn skip_entry(&self, ent: &DirEntry) -> bool {
|
||||
if ent.depth() == 0 {
|
||||
// Never skip the root directory.
|
||||
@@ -41,6 +42,7 @@ impl Iter {
|
||||
impl Iterator for Iter {
|
||||
type Item = DirEntry;
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<DirEntry> {
|
||||
while let Some(ev) = self.it.next() {
|
||||
match ev {
|
||||
@@ -108,6 +110,7 @@ impl From<WalkDir> for WalkEventIter {
|
||||
impl Iterator for WalkEventIter {
|
||||
type Item = walkdir::Result<WalkEvent>;
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<walkdir::Result<WalkEvent>> {
|
||||
let dent = self.next.take().or_else(|| self.it.next());
|
||||
let depth = match dent {
|
||||
@@ -135,8 +138,3 @@ impl Iterator for WalkEventIter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_hidden(ent: &DirEntry) -> bool {
|
||||
ent.depth() > 0 &&
|
||||
ent.file_name().to_str().map(|s| s.starts_with(".")).unwrap_or(false)
|
||||
}
|
||||
|
24
tests/hay.rs
Normal file
24
tests/hay.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
pub const SHERLOCK: &'static str = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
Holmeses, success in the province of detective work must always
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
can extract a clew from a wisp of straw or a flake of cigar ash;
|
||||
but Doctor Watson has to have it taken out for him and dusted,
|
||||
and exhibited clearly, with a label attached.
|
||||
";
|
||||
|
||||
pub const CODE: &'static str = "\
|
||||
extern crate snap;
|
||||
|
||||
use std::io;
|
||||
|
||||
fn main() {
|
||||
let stdin = io::stdin();
|
||||
let stdout = io::stdout();
|
||||
|
||||
// Wrap the stdin reader in a Snappy reader.
|
||||
let mut rdr = snap::Reader::new(stdin.lock());
|
||||
let mut wtr = stdout.lock();
|
||||
io::copy(&mut rdr, &mut wtr).expect(\"I/O operation failed\");
|
||||
}
|
||||
";
|
640
tests/tests.rs
Normal file
640
tests/tests.rs
Normal file
@@ -0,0 +1,640 @@
|
||||
/*!
|
||||
This module contains *integration* tests. Their purpose is to test the CLI
|
||||
interface. Namely, that passing a flag does what it says on the tin.
|
||||
|
||||
Tests for more fine grained behavior (like the search or the globber) should be
|
||||
unit tests in their respective modules.
|
||||
*/
|
||||
|
||||
#![allow(dead_code, unused_imports)]
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
use workdir::WorkDir;
|
||||
|
||||
mod hay;
|
||||
mod workdir;
|
||||
|
||||
macro_rules! sherlock {
|
||||
($name:ident, $fun:expr) => {
|
||||
sherlock!($name, "Sherlock", $fun);
|
||||
};
|
||||
($name:ident, $query:expr, $fun:expr) => {
|
||||
sherlock!($name, $query, "sherlock", $fun);
|
||||
};
|
||||
($name:ident, $query:expr, $path:expr, $fun:expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
let wd = WorkDir::new(stringify!($name));
|
||||
wd.create("sherlock", hay::SHERLOCK);
|
||||
let mut cmd = wd.command();
|
||||
cmd.arg($query).arg($path);
|
||||
$fun(wd, cmd);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
sherlock!(single_file, |wd: WorkDir, mut cmd| {
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(dir, "Sherlock", ".", |wd: WorkDir, mut cmd| {
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(line_numbers, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-n");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
3:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(columns, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("--column");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
57:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
49:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(with_filename, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-H");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(with_heading, |wd: WorkDir, mut cmd: Command| {
|
||||
// This forces the issue since --with-filename is disabled by default
|
||||
// when searching one fil.e
|
||||
cmd.arg("--with-filename").arg("--heading");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(with_heading_default, "Sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
// Search two or more and get --with-filename enabled by default.
|
||||
// Use -j1 to get deterministic results.
|
||||
wd.create("foo", "Sherlock Holmes lives on Baker Street.");
|
||||
cmd.arg("-j1").arg("--heading");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected1 = "\
|
||||
foo
|
||||
Sherlock Holmes lives on Baker Street.
|
||||
|
||||
sherlock
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
let expected2 = "\
|
||||
sherlock
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
|
||||
foo
|
||||
Sherlock Holmes lives on Baker Street.
|
||||
";
|
||||
assert!(lines == expected1 || lines == expected2);
|
||||
});
|
||||
|
||||
sherlock!(inverted, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-v");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
Holmeses, success in the province of detective work must always
|
||||
can extract a clew from a wisp of straw or a flake of cigar ash;
|
||||
but Doctor Watson has to have it taken out for him and dusted,
|
||||
and exhibited clearly, with a label attached.
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(inverted_line_numbers, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-n").arg("-v");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
2:Holmeses, success in the province of detective work must always
|
||||
4:can extract a clew from a wisp of straw or a flake of cigar ash;
|
||||
5:but Doctor Watson has to have it taken out for him and dusted,
|
||||
6:and exhibited clearly, with a label attached.
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(case_insensitive, "sherlock", |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-i");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(word, "as", |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-w");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(literal, "()", "file", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file", "blib\n()\nblab\n");
|
||||
cmd.arg("-F");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "()\n");
|
||||
});
|
||||
|
||||
sherlock!(quiet, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-q");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert!(lines.is_empty());
|
||||
});
|
||||
|
||||
sherlock!(replace, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-r").arg("FooBar");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Doctor Watsons of this world, as opposed to the FooBar
|
||||
be, to a very large extent, the result of luck. FooBar Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(replace_groups, "([A-Z][a-z]+) ([A-Z][a-z]+)",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-r").arg("$2, $1");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Watsons, Doctor of this world, as opposed to the Sherlock
|
||||
be, to a very large extent, the result of luck. Holmes, Sherlock
|
||||
but Watson, Doctor has to have it taken out for him and dusted,
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(replace_named_groups, "(?P<first>[A-Z][a-z]+) (?P<last>[A-Z][a-z]+)",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-r").arg("$last, $first");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Watsons, Doctor of this world, as opposed to the Sherlock
|
||||
be, to a very large extent, the result of luck. Holmes, Sherlock
|
||||
but Watson, Doctor has to have it taken out for him and dusted,
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(file_types, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file.py", "Sherlock");
|
||||
wd.create("file.rs", "Sherlock");
|
||||
cmd.arg("-t").arg("rust");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "file.rs:Sherlock\n");
|
||||
});
|
||||
|
||||
sherlock!(file_types_all, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file.py", "Sherlock");
|
||||
cmd.arg("-t").arg("all");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "file.py:Sherlock\n");
|
||||
});
|
||||
|
||||
sherlock!(file_types_negate, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.remove("sherlock");
|
||||
wd.create("file.py", "Sherlock");
|
||||
wd.create("file.rs", "Sherlock");
|
||||
cmd.arg("-T").arg("rust");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "file.py:Sherlock\n");
|
||||
});
|
||||
|
||||
sherlock!(file_types_negate_all, "Sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file.py", "Sherlock");
|
||||
cmd.arg("-T").arg("all");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "\
|
||||
sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
");
|
||||
});
|
||||
|
||||
sherlock!(file_type_clear, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file.py", "Sherlock");
|
||||
wd.create("file.rs", "Sherlock");
|
||||
cmd.arg("--type-clear").arg("rust").arg("-t").arg("rust");
|
||||
wd.assert_err(&mut cmd);
|
||||
});
|
||||
|
||||
sherlock!(file_type_add, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file.py", "Sherlock");
|
||||
wd.create("file.rs", "Sherlock");
|
||||
wd.create("file.wat", "Sherlock");
|
||||
cmd.arg("--type-add").arg("wat:*.wat").arg("-t").arg("wat");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "file.wat:Sherlock\n");
|
||||
});
|
||||
|
||||
sherlock!(glob, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file.py", "Sherlock");
|
||||
wd.create("file.rs", "Sherlock");
|
||||
cmd.arg("-g").arg("*.rs");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "file.rs:Sherlock\n");
|
||||
});
|
||||
|
||||
sherlock!(glob_negate, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.remove("sherlock");
|
||||
wd.create("file.py", "Sherlock");
|
||||
wd.create("file.rs", "Sherlock");
|
||||
cmd.arg("-g").arg("!*.rs");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "file.py:Sherlock\n");
|
||||
});
|
||||
|
||||
sherlock!(after_context, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-A").arg("1");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
Holmeses, success in the province of detective work must always
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
can extract a clew from a wisp of straw or a flake of cigar ash;
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(after_context_line_numbers, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-A").arg("1").arg("-n");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
2-Holmeses, success in the province of detective work must always
|
||||
3:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
4-can extract a clew from a wisp of straw or a flake of cigar ash;
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(before_context, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-B").arg("1");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
Holmeses, success in the province of detective work must always
|
||||
be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(before_context_line_numbers, |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-B").arg("1").arg("-n");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
2-Holmeses, success in the province of detective work must always
|
||||
3:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(context, "world|attached", |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-C").arg("1");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
Holmeses, success in the province of detective work must always
|
||||
--
|
||||
but Doctor Watson has to have it taken out for him and dusted,
|
||||
and exhibited clearly, with a label attached.
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(context_line_numbers, "world|attached",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-C").arg("1").arg("-n");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
1:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
2-Holmeses, success in the province of detective work must always
|
||||
--
|
||||
5-but Doctor Watson has to have it taken out for him and dusted,
|
||||
6:and exhibited clearly, with a label attached.
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(ignore_hidden, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.remove("sherlock");
|
||||
wd.create(".sherlock", hay::SHERLOCK);
|
||||
wd.assert_err(&mut cmd);
|
||||
});
|
||||
|
||||
sherlock!(no_ignore_hidden, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.remove("sherlock");
|
||||
wd.create(".sherlock", hay::SHERLOCK);
|
||||
|
||||
cmd.arg("--hidden");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
.sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
.sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(ignore_git, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create(".gitignore", "sherlock\n");
|
||||
wd.assert_err(&mut cmd);
|
||||
});
|
||||
|
||||
sherlock!(ignore_ripgrep, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create(".rgignore", "sherlock\n");
|
||||
wd.assert_err(&mut cmd);
|
||||
});
|
||||
|
||||
sherlock!(no_ignore, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create(".gitignore", "sherlock\n");
|
||||
cmd.arg("--no-ignore");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(ignore_git_parent, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.remove("sherlock");
|
||||
wd.create(".gitignore", "sherlock\n");
|
||||
wd.create_dir(".git");
|
||||
wd.create_dir("foo");
|
||||
wd.create("foo/sherlock", hay::SHERLOCK);
|
||||
// Even though we search in foo/, which has no .gitignore, ripgrep will
|
||||
// search parent directories and respect the gitignore files found.
|
||||
cmd.current_dir(wd.path().join("foo"));
|
||||
wd.assert_err(&mut cmd);
|
||||
});
|
||||
|
||||
sherlock!(ignore_git_parent_stop, "Sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
// This tests that searching parent directories for .gitignore files stops
|
||||
// after it sees a .git directory. To test this, we create this directory
|
||||
// hierarchy:
|
||||
//
|
||||
// .gitignore (contains `sherlock`)
|
||||
// foo/
|
||||
// .git
|
||||
// bar/
|
||||
// sherlock
|
||||
//
|
||||
// And we perform the search inside `foo/bar/`. ripgrep will stop looking
|
||||
// for .gitignore files after it sees `foo/.git/`, and therefore not
|
||||
// respect the top-level `.gitignore` containing `sherlock`.
|
||||
wd.remove("sherlock");
|
||||
wd.create(".gitignore", "sherlock\n");
|
||||
wd.create_dir("foo");
|
||||
wd.create_dir("foo/.git");
|
||||
wd.create_dir("foo/bar");
|
||||
wd.create("foo/bar/sherlock", hay::SHERLOCK);
|
||||
cmd.current_dir(wd.path().join("foo").join("bar"));
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(ignore_ripgrep_parent_no_stop, "Sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
// This is like the `ignore_git_parent_stop` test, except it checks that
|
||||
// ripgrep *doesn't* stop checking for .rgignore files.
|
||||
wd.remove("sherlock");
|
||||
wd.create(".rgignore", "sherlock\n");
|
||||
wd.create_dir("foo");
|
||||
wd.create_dir("foo/.git");
|
||||
wd.create_dir("foo/bar");
|
||||
wd.create("foo/bar/sherlock", hay::SHERLOCK);
|
||||
cmd.current_dir(wd.path().join("foo").join("bar"));
|
||||
// The top-level .rgignore applies.
|
||||
wd.assert_err(&mut cmd);
|
||||
});
|
||||
|
||||
sherlock!(no_parent_ignore_git, "Sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
// Set up a directory hierarchy like this:
|
||||
//
|
||||
// .gitignore
|
||||
// foo/
|
||||
// .gitignore
|
||||
// sherlock
|
||||
// watson
|
||||
//
|
||||
// Where `.gitignore` contains `sherlock` and `foo/.gitignore` contains
|
||||
// `watson`.
|
||||
//
|
||||
// Now *do the search* from the foo directory. By default, ripgrep will
|
||||
// search parent directories for .gitignore files. The --no-ignore-parent
|
||||
// flag should prevent that. At the same time, the `foo/.gitignore` file
|
||||
// will still be respected (since the search is happening in `foo/`).
|
||||
//
|
||||
// In other words, we should only see results from `sherlock`, not from
|
||||
// `watson`.
|
||||
wd.remove("sherlock");
|
||||
wd.create(".gitignore", "sherlock\n");
|
||||
wd.create_dir("foo");
|
||||
wd.create("foo/.gitignore", "watson\n");
|
||||
wd.create("foo/sherlock", hay::SHERLOCK);
|
||||
wd.create("foo/watson", hay::SHERLOCK);
|
||||
cmd.current_dir(wd.path().join("foo"));
|
||||
cmd.arg("--no-ignore-parent");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(symlink_nofollow, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.remove("sherlock");
|
||||
wd.create_dir("foo");
|
||||
wd.create_dir("foo/bar");
|
||||
wd.link("foo/baz", "foo/bar/baz");
|
||||
wd.create_dir("foo/baz");
|
||||
wd.create("foo/baz/sherlock", hay::SHERLOCK);
|
||||
cmd.current_dir(wd.path().join("foo/bar"));
|
||||
wd.assert_err(&mut cmd);
|
||||
});
|
||||
|
||||
sherlock!(symlink_follow, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.remove("sherlock");
|
||||
wd.create_dir("foo");
|
||||
wd.create_dir("foo/bar");
|
||||
wd.create_dir("foo/baz");
|
||||
wd.create("foo/baz/sherlock", hay::SHERLOCK);
|
||||
wd.link("foo/baz", "foo/bar/baz");
|
||||
cmd.arg("-L");
|
||||
cmd.current_dir(wd.path().join("foo/bar"));
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
if cfg!(windows) {
|
||||
let expected = "\
|
||||
baz\\sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
baz\\sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
} else {
|
||||
let expected = "\
|
||||
baz/sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
baz/sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
}
|
||||
});
|
||||
|
||||
sherlock!(unrestricted1, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create(".gitignore", "sherlock\n");
|
||||
cmd.arg("-u");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
sherlock!(unrestricted2, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.remove("sherlock");
|
||||
wd.create(".sherlock", hay::SHERLOCK);
|
||||
cmd.arg("-uu");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
.sherlock:For the Doctor Watsons of this world, as opposed to the Sherlock
|
||||
.sherlock:be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
#[cfg(not(windows))]
|
||||
sherlock!(unrestricted3, "foo", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file", "foo\x00bar\nfoo\x00baz\n");
|
||||
cmd.arg("-uuu");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "file:foo\nfile:foo\n");
|
||||
});
|
||||
|
||||
// On Windows, this test uses memory maps, so the NUL bytes don't get replaced.
|
||||
#[cfg(windows)]
|
||||
sherlock!(unrestricted3, "foo", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("file", "foo\x00bar\nfoo\x00baz\n");
|
||||
cmd.arg("-uuu");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "file:foo\x00bar\nfile:foo\x00baz\n");
|
||||
});
|
||||
|
||||
#[test]
|
||||
fn binary_nosearch() {
|
||||
let wd = WorkDir::new("binary_nosearch");
|
||||
wd.create("file", "foo\x00bar\nfoo\x00baz\n");
|
||||
let mut cmd = wd.command();
|
||||
cmd.arg("foo").arg("file");
|
||||
wd.assert_err(&mut cmd);
|
||||
}
|
||||
|
||||
// The following two tests show a discrepancy in search results between
|
||||
// searching with memory mapped files and stream searching. Stream searching
|
||||
// uses a heuristic (that GNU grep also uses) where NUL bytes are replaced with
|
||||
// the EOL terminator, which tends to avoid allocating large amounts of memory
|
||||
// for really long "lines." The memory map searcher has no need to worry about
|
||||
// such things, and more than that, it would be pretty hard for it to match
|
||||
// the semantics of streaming search in this case.
|
||||
//
|
||||
// Binary files with lots of NULs aren't really part of the use case of ripgrep
|
||||
// (or any other grep-like tool for that matter), so we shouldn't feel too bad
|
||||
// about it.
|
||||
#[test]
|
||||
fn binary_search_mmap() {
|
||||
let wd = WorkDir::new("binary_search_mmap");
|
||||
wd.create("file", "foo\x00bar\nfoo\x00baz\n");
|
||||
let mut cmd = wd.command();
|
||||
cmd.arg("-a").arg("--mmap").arg("foo").arg("file");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "foo\x00bar\nfoo\x00baz\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn binary_search_no_mmap() {
|
||||
let wd = WorkDir::new("binary_search_no_mmap");
|
||||
wd.create("file", "foo\x00bar\nfoo\x00baz\n");
|
||||
let mut cmd = wd.command();
|
||||
cmd.arg("-a").arg("--no-mmap").arg("foo").arg("file");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "foo\nfoo\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn files() {
|
||||
let wd = WorkDir::new("files");
|
||||
wd.create("file", "");
|
||||
wd.create_dir("dir");
|
||||
wd.create("dir/file", "");
|
||||
|
||||
let mut cmd = wd.command();
|
||||
cmd.arg("--files");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
if cfg!(windows) {
|
||||
assert!(lines == "./dir\\file\n./file\n"
|
||||
|| lines == "./file\n./dir\\file\n");
|
||||
} else {
|
||||
assert!(lines == "./file\n./dir/file\n"
|
||||
|| lines == "./dir/file\n./file\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_list() {
|
||||
let wd = WorkDir::new("type_list");
|
||||
|
||||
let mut cmd = wd.command();
|
||||
cmd.arg("--type-list");
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
// This can change over time, so just make sure we print something.
|
||||
assert!(!lines.is_empty());
|
||||
}
|
189
tests/workdir.rs
Normal file
189
tests/workdir.rs
Normal file
@@ -0,0 +1,189 @@
|
||||
use std::env;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{self, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
static TEST_DIR: &'static str = "ripgrep-tests";
|
||||
static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
/// WorkDir represents a directory in which tests are run.
|
||||
///
|
||||
/// Directories are created from a global atomic counter to avoid duplicates.
|
||||
#[derive(Debug)]
|
||||
pub struct WorkDir {
|
||||
/// The directory in which this test executable is running.
|
||||
root: PathBuf,
|
||||
/// The directory in which the test should run. If a test needs to create
|
||||
/// files, they should go in here.
|
||||
dir: PathBuf,
|
||||
}
|
||||
|
||||
impl WorkDir {
|
||||
/// Create a new test working directory with the given name. The name
|
||||
/// does not need to be distinct for each invocation, but should correspond
|
||||
/// to a logical grouping of tests.
|
||||
pub fn new(name: &str) -> WorkDir {
|
||||
let id = NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
||||
let root = env::current_exe().unwrap()
|
||||
.parent().expect("executable's directory").to_path_buf();
|
||||
let dir = root.join(TEST_DIR).join(name).join(&format!("{}", id));
|
||||
nice_err(&dir, repeat(|| fs::create_dir_all(&dir)));
|
||||
WorkDir {
|
||||
root: root,
|
||||
dir: dir,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new file with the given name and contents in this directory.
|
||||
pub fn create<P: AsRef<Path>>(&self, name: P, contents: &str) {
|
||||
let path = self.dir.join(name);
|
||||
let mut file = nice_err(&path, File::create(&path));
|
||||
nice_err(&path, file.write_all(contents.as_bytes()));
|
||||
nice_err(&path, file.flush());
|
||||
}
|
||||
|
||||
/// Remove a file with the given name from this directory.
|
||||
pub fn remove<P: AsRef<Path>>(&self, name: P) {
|
||||
let path = self.dir.join(name);
|
||||
nice_err(&path, fs::remove_file(&path));
|
||||
}
|
||||
|
||||
/// Create a new directory with the given path (and any directories above
|
||||
/// it) inside this directory.
|
||||
pub fn create_dir<P: AsRef<Path>>(&self, path: P) {
|
||||
let path = self.dir.join(path);
|
||||
nice_err(&path, repeat(|| fs::create_dir_all(&path)));
|
||||
}
|
||||
|
||||
/// Creates a new command that is set to use the ripgrep executable in
|
||||
/// this working directory.
|
||||
pub fn command(&self) -> process::Command {
|
||||
let mut cmd = process::Command::new(&self.bin());
|
||||
cmd.current_dir(&self.dir);
|
||||
cmd
|
||||
}
|
||||
|
||||
/// Returns the path to the ripgrep executable.
|
||||
pub fn bin(&self) -> PathBuf {
|
||||
self.root.join("rg")
|
||||
}
|
||||
|
||||
/// Returns the path to this directory.
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.dir
|
||||
}
|
||||
|
||||
/// Creates a directory symlink to the src with the given target name
|
||||
/// in this directory.
|
||||
#[cfg(not(windows))]
|
||||
pub fn link<S: AsRef<Path>, T: AsRef<Path>>(&self, src: S, target: T) {
|
||||
use std::os::unix::fs::symlink;
|
||||
let src = self.dir.join(src);
|
||||
let target = self.dir.join(target);
|
||||
let _ = fs::remove_file(&target);
|
||||
nice_err(&target, symlink(&src, &target));
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn link<S: AsRef<Path>, T: AsRef<Path>>(&self, src: S, target: T) {
|
||||
use std::os::windows::fs::symlink_dir;
|
||||
let src = self.dir.join(src);
|
||||
let target = self.dir.join(target);
|
||||
let _ = fs::remove_dir(&target);
|
||||
nice_err(&target, symlink_dir(&src, &target));
|
||||
}
|
||||
|
||||
/// Runs and captures the stdout of the given command.
|
||||
///
|
||||
/// If the return type could not be created from a string, then this
|
||||
/// panics.
|
||||
pub fn stdout<E: fmt::Debug, T: FromStr<Err=E>>(
|
||||
&self,
|
||||
cmd: &mut process::Command,
|
||||
) -> T {
|
||||
let o = self.output(cmd);
|
||||
let stdout = String::from_utf8_lossy(&o.stdout);
|
||||
match stdout.parse() {
|
||||
Ok(t) => t,
|
||||
Err(err) => {
|
||||
panic!("could not convert from string: {:?}\n\n{}", err, stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the output of a command. If the command failed, then this panics.
|
||||
pub fn output(&self, cmd: &mut process::Command) -> process::Output {
|
||||
let o = cmd.output().unwrap();
|
||||
if !o.status.success() {
|
||||
let suggest =
|
||||
if o.stderr.is_empty() {
|
||||
"\n\nDid your search end up with no results?".to_string()
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
panic!("\n\n==========\n\
|
||||
command failed but expected success!\
|
||||
{}\
|
||||
\n\ncommand: {:?}\
|
||||
\ncwd: {}\
|
||||
\n\nstatus: {}\
|
||||
\n\nstdout: {}\
|
||||
\n\nstderr: {}\
|
||||
\n\n==========\n",
|
||||
suggest, cmd, self.dir.display(), o.status,
|
||||
String::from_utf8_lossy(&o.stdout),
|
||||
String::from_utf8_lossy(&o.stderr));
|
||||
}
|
||||
o
|
||||
}
|
||||
|
||||
/// Runs the given command and asserts that it resulted in an error exit
|
||||
/// code.
|
||||
pub fn assert_err(&self, cmd: &mut process::Command) {
|
||||
let o = cmd.output().unwrap();
|
||||
if o.status.success() {
|
||||
panic!("\n\n===== {:?} =====\n\
|
||||
command succeeded but expected failure!\
|
||||
\n\ncwd: {}\
|
||||
\n\nstatus: {}\
|
||||
\n\nstdout: {}\n\nstderr: {}\
|
||||
\n\n=====\n",
|
||||
cmd, self.dir.display(), o.status,
|
||||
String::from_utf8_lossy(&o.stdout),
|
||||
String::from_utf8_lossy(&o.stderr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn nice_err<P: AsRef<Path>, T, E: error::Error>(
|
||||
path: P,
|
||||
res: Result<T, E>,
|
||||
) -> T {
|
||||
match res {
|
||||
Ok(t) => t,
|
||||
Err(err) => {
|
||||
panic!("{}: {:?}", path.as_ref().display(), err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn repeat<F: FnMut() -> io::Result<()>>(mut f: F) -> io::Result<()> {
|
||||
let mut last_err = None;
|
||||
for _ in 0..10 {
|
||||
if let Err(err) = f() {
|
||||
last_err = Some(err);
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
} else {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Err(last_err.unwrap())
|
||||
}
|
Reference in New Issue
Block a user