mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-07-27 18:21:57 -07:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ac1c95a6d9 | ||
|
685b431d80 | ||
|
487713aa34 | ||
|
e300541701 | ||
|
e9df420d2f | ||
|
201b4fc757 | ||
|
90a11dec5e | ||
|
9456d95e8f | ||
|
0c298f60a6 | ||
|
79271fcb33 | ||
|
fc975af8e9 | ||
|
1425d6735e | ||
|
aed3ccb9c7 | ||
|
33c95d2919 | ||
|
01deac9427 | ||
|
b4bc3b6349 | ||
|
685cc6c562 | ||
|
08c017330f | ||
|
2f3a8c7f69 | ||
|
3ac1b68e54 | ||
|
0ebd5465b7 | ||
|
5cb4bb9ea0 | ||
|
c8a179b4da | ||
|
46f94826fd | ||
|
75f1855a91 |
23
CHANGELOG.md
23
CHANGELOG.md
@@ -1,3 +1,26 @@
|
||||
0.5.1 (2017-04-09)
|
||||
==================
|
||||
Feature enhancements:
|
||||
|
||||
* Added or improved file type filtering for vim.
|
||||
* [FEATURE #34](https://github.com/BurntSushi/ripgrep/issues/34):
|
||||
Add a `-o/--only-matching` flag.
|
||||
* [FEATURE #377](https://github.com/BurntSushi/ripgrep/issues/377):
|
||||
Column numbers can now be customized with a color. (The default is
|
||||
no color.)
|
||||
* [FEATURE #419](https://github.com/BurntSushi/ripgrep/issues/419):
|
||||
Added `-0` short flag option for `--null`.
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* [BUG #381](https://github.com/BurntSushi/ripgrep/issues/381):
|
||||
Include license text in all subcrates.
|
||||
* [BUG #418](https://github.com/BurntSushi/ripgrep/issues/418),
|
||||
[BUG #426](https://github.com/BurntSushi/ripgrep/issues/426),
|
||||
[BUG #439](https://github.com/BurntSushi/ripgrep/issues/439):
|
||||
Fix a few bugs with `-h/--help` output.
|
||||
|
||||
|
||||
0.5.0 (2017-03-12)
|
||||
==================
|
||||
This is a new minor version release of ripgrep that includes one minor breaking
|
||||
|
38
Cargo.lock
generated
38
Cargo.lock
generated
@@ -1,15 +1,15 @@
|
||||
[root]
|
||||
name = "ripgrep"
|
||||
version = "0.4.0"
|
||||
version = "0.5.1"
|
||||
dependencies = [
|
||||
"atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytecount 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.23.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding_rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"grep 0.1.6",
|
||||
"ignore 0.1.8",
|
||||
"lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ignore 0.1.9",
|
||||
"lazy_static 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -17,12 +17,12 @@ dependencies = [
|
||||
"num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.1",
|
||||
"termcolor 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -45,7 +45,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.8.0"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -63,12 +63,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.21.1"
|
||||
version = "2.23.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -116,7 +116,7 @@ dependencies = [
|
||||
name = "globset"
|
||||
version = "0.1.4"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -135,11 +135,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
dependencies = [
|
||||
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"globset 0.1.4",
|
||||
"lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -158,7 +158,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.2.4"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -203,7 +203,7 @@ name = "regex"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -247,7 +247,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
dependencies = [
|
||||
"wincolor 0.1.3",
|
||||
]
|
||||
@@ -332,20 +332,20 @@ dependencies = [
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"
|
||||
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
|
||||
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
|
||||
"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
|
||||
"checksum bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e1ab483fc81a8143faa7203c4a3c02888ebd1a782e37e41fa34753ba9a162"
|
||||
"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
|
||||
"checksum bytecount 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1e8f09fbc8c6726a4b616dcfbd4f54491068d6bb1b93ac03c78ac18ff9a5924a"
|
||||
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
|
||||
"checksum clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "74a80f603221c9cd9aa27a28f52af452850051598537bb6b359c38a7d61e5cda"
|
||||
"checksum clap 2.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d480c39a2e5f9b3a3798c661613e1b0e7a7ae71e005102d4aa910fc3289df484"
|
||||
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
|
||||
"checksum encoding_rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a1cca0a26f904955d80d70b9bff1019e4f4cbc06f2fcbccf8bd3d889cc1c9b7"
|
||||
"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
|
||||
"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
|
||||
"checksum fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34edaee07555859dc13ca387e6ae05686bb4d0364c95d649b6dab959511f4baf"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7291b1dd97d331f752620b02dfdbc231df7fc01bf282a00769e1cdb963c460dc"
|
||||
"checksum lazy_static 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f61b8421c7a4648c391611625d56fdd5c7567da05af1be655fd8cacc643abb3"
|
||||
"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
|
||||
"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
|
||||
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ripgrep"
|
||||
version = "0.5.0" #:version
|
||||
version = "0.5.1" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
Line oriented search tool using Rust's regex library. Combines the raw
|
||||
@@ -28,11 +28,11 @@ path = "tests/tests.rs"
|
||||
[dependencies]
|
||||
atty = "0.2.2"
|
||||
bytecount = "0.1.4"
|
||||
clap = "2.20.5"
|
||||
clap = "2.23.1"
|
||||
encoding_rs = "0.5.0"
|
||||
env_logger = { version = "0.4", default-features = false }
|
||||
grep = { version = "0.1.5", path = "grep" }
|
||||
ignore = { version = "0.1.7", path = "ignore" }
|
||||
ignore = { version = "0.1.9", path = "ignore" }
|
||||
lazy_static = "0.2"
|
||||
libc = "0.2"
|
||||
log = "0.3"
|
||||
@@ -44,7 +44,7 @@ same-file = "0.1.1"
|
||||
termcolor = { version = "0.3.0", path = "termcolor" }
|
||||
|
||||
[build-dependencies]
|
||||
clap = "2.18"
|
||||
clap = "2.23.1"
|
||||
lazy_static = "0.2"
|
||||
|
||||
[features]
|
||||
|
54
README.md
54
README.md
@@ -230,11 +230,10 @@ 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)
|
||||
One last thing before we get started: generally speaking, `ripgrep` assumes the
|
||||
input is reading is UTF-8. However, if ripgrep notices a file is encoded as
|
||||
UTF-16, then it will know how to search it. For other encodings, you'll need to
|
||||
explicitly specify them with the `-E/--encoding` flag.
|
||||
|
||||
To recursively search the current directory, while respecting all `.gitignore`
|
||||
files, ignore hidden files and directories and skip binary files:
|
||||
@@ -379,6 +378,51 @@ $ cargo test
|
||||
|
||||
from the repository root.
|
||||
|
||||
### Tips
|
||||
|
||||
#### Windows Powershell
|
||||
|
||||
##### Powershell Profile
|
||||
|
||||
To customize powershell on start-up there is a special powershell script that has to be created.
|
||||
In order to find its location run command `Get-Command $profile | Select-Object -ExpandProperty Definition`
|
||||
See [more](https://technet.microsoft.com/en-us/library/bb613488(v=vs.85).aspx) for profile details.
|
||||
|
||||
Any powershell code in this file gets evaluated at the start of console.
|
||||
This way you can have own aliases to be created at start.
|
||||
|
||||
##### Setup function alias
|
||||
|
||||
Often you can find a need to make alias for the favourite utility.
|
||||
|
||||
But powershell function aliases do not behave like your typical linux shell alias.
|
||||
|
||||
You always need to propagate arguments and **Stdin** input.
|
||||
But it cannot be done simply as `function grep() { $input | rg.exe --hidden $args }`
|
||||
|
||||
Use below example as reference to how setup alias in powershell.
|
||||
|
||||
```powershell
|
||||
function grep {
|
||||
$count = @($input).Count
|
||||
$input.Reset()
|
||||
|
||||
if ($count) {
|
||||
$input | rg.exe --hidden $args
|
||||
}
|
||||
else {
|
||||
rg.exe --hidden $args
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Powershell special variables:
|
||||
* input - is powershell **Stdin** object that allows you to access its content.
|
||||
* args - is array of arguments passed to this function.
|
||||
|
||||
This alias checks whether there is **Stdin** input and propagates only if there is some lines.
|
||||
Otherwise empty `$input` will make powershell to trigger `rg` to search empty **Stdin**
|
||||
|
||||
### Known issues
|
||||
|
||||
#### I just hit Ctrl+C in the middle of ripgrep's output and now my terminal's foreground color is wrong!
|
||||
|
@@ -40,6 +40,7 @@ before_deploy:
|
||||
- cargo build --release
|
||||
- mkdir staging
|
||||
- copy target\release\rg.exe staging
|
||||
- ps: copy target\release\build\ripgrep-*\out\_rg.ps1 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 *
|
||||
|
2
build.rs
2
build.rs
@@ -19,7 +19,7 @@ fn main() {
|
||||
};
|
||||
fs::create_dir_all(&outdir).unwrap();
|
||||
|
||||
let mut app = app::app_short();
|
||||
let mut app = app::app();
|
||||
app.gen_completions("rg", Shell::Bash, &outdir);
|
||||
app.gen_completions("rg", Shell::Fish, &outdir);
|
||||
app.gen_completions("rg", Shell::Zsh, &outdir);
|
||||
|
@@ -17,9 +17,6 @@ install_c_toolchain() {
|
||||
}
|
||||
|
||||
install_rustup() {
|
||||
# uninstall the rust toolchain installed by travis, we are going to use rustup
|
||||
sh ~/rust/lib/rustlib/uninstall.sh
|
||||
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain=$TRAVIS_RUST_VERSION
|
||||
|
||||
rustc -V
|
||||
|
17
doc/rg.1
17
doc/rg.1
@@ -181,7 +181,7 @@ Styles are limited to nobold, bold, nointense or intense.
|
||||
.RS
|
||||
.PP
|
||||
The format of the flag is {type}:{attribute}:{value}.
|
||||
{type} should be one of path, line or match.
|
||||
{type} should be one of path, line, column or match.
|
||||
{attribute} can be fg, bg or style.
|
||||
Value is either a color (for fg and bg) or a text style.
|
||||
A special format, {type}:none, will clear all color settings for {type}.
|
||||
@@ -299,6 +299,13 @@ Follow symlinks.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-M, \-\-max\-columns \f[I]NUM\f[]
|
||||
Don\[aq]t print lines longer than this limit in bytes.
|
||||
Longer lines are omitted, and only the number of matches in that line is
|
||||
printed.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-m, \-\-max\-count \f[I]NUM\f[]
|
||||
Limit the number of matching lines per file searched to NUM.
|
||||
.RS
|
||||
@@ -355,7 +362,7 @@ Note that .ignore files will continue to be respected.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-null
|
||||
.B \-0, \-\-null
|
||||
Whenever a file name is printed, follow it with a NUL byte.
|
||||
This includes printing filenames before matches, and when printing a
|
||||
list of matching files such as with \-\-count, \-\-files\-with\-matches
|
||||
@@ -363,6 +370,12 @@ and \-\-files.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-o, \-\-only\-matching
|
||||
Print only the matched (non\-empty) parts of a matching line, with each
|
||||
such part on a separate output line.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-path\-separator \f[I]SEPARATOR\f[]
|
||||
The path separator to use when printing file paths.
|
||||
This defaults to your platform\[aq]s path separator, which is / on Unix
|
||||
|
12
doc/rg.1.md
12
doc/rg.1.md
@@ -123,9 +123,9 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
||||
black. Styles are limited to nobold, bold, nointense or intense.
|
||||
|
||||
The format of the flag is {type}:{attribute}:{value}. {type} should be one
|
||||
of path, line or match. {attribute} can be fg, bg or style. Value is either
|
||||
a color (for fg and bg) or a text style. A special format, {type}:none,
|
||||
will clear all color settings for {type}.
|
||||
of path, line, column or match. {attribute} can be fg, bg or style. Value
|
||||
is either a color (for fg and bg) or a text style. A special format,
|
||||
{type}:none, will clear all color settings for {type}.
|
||||
|
||||
For example, the following command will change the match color to magenta
|
||||
and the background color for line numbers to yellow:
|
||||
@@ -243,12 +243,16 @@ Project home page: https://github.com/BurntSushi/ripgrep
|
||||
: Don't respect version control ignore files (e.g., .gitignore).
|
||||
Note that .ignore files will continue to be respected.
|
||||
|
||||
--null
|
||||
-0, --null
|
||||
: Whenever a file name is printed, follow it with a NUL byte.
|
||||
This includes printing filenames before matches, and when printing
|
||||
a list of matching files such as with --count, --files-with-matches
|
||||
and --files.
|
||||
|
||||
-o, --only-matching
|
||||
: Print only the matched (non-empty) parts of a matching line, with each such
|
||||
part on a separate output line.
|
||||
|
||||
--path-separator *SEPARATOR*
|
||||
: The path separator to use when printing file paths. This defaults to your
|
||||
platform's path separator, which is / on Unix and \\ on Windows. This flag is
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ignore"
|
||||
version = "0.1.8" #:version
|
||||
version = "0.1.9" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
A fast library for efficiently matching ignore files such as `.gitignore`
|
||||
|
@@ -191,6 +191,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("twig", &["*.twig"]),
|
||||
("vala", &["*.vala"]),
|
||||
("vb", &["*.vb"]),
|
||||
("vim", &["*.vim"]),
|
||||
("vimscript", &["*.vim"]),
|
||||
("wiki", &["*.mediawiki", "*.wiki"]),
|
||||
("xml", &["*.xml"]),
|
||||
|
@@ -3,7 +3,7 @@ class RipgrepBin < Formula
|
||||
desc "Search tool like grep and The Silver Searcher."
|
||||
homepage "https://github.com/BurntSushi/ripgrep"
|
||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
|
||||
sha256 "efdc64456fc64910c2998b25c402aac2ff17caf1507e8bcca4584b429ef7f7ae"
|
||||
sha256 "5bfa8872c4f2a5d010ddec1c213d518056e62d4dd3b3f23a0ef099b85343dbdd"
|
||||
|
||||
conflicts_with "ripgrep"
|
||||
|
||||
|
51
src/app.rs
51
src/app.rs
@@ -32,16 +32,6 @@ ARGS:
|
||||
OPTIONS:
|
||||
{unified}";
|
||||
|
||||
/// Build a clap application with short help strings.
|
||||
pub fn app_short() -> App<'static, 'static> {
|
||||
app(false, |k| USAGES[k].short)
|
||||
}
|
||||
|
||||
/// Build a clap application with long help strings.
|
||||
pub fn app_long() -> App<'static, 'static> {
|
||||
app(true, |k| USAGES[k].long)
|
||||
}
|
||||
|
||||
/// Build a clap application parameterized by usage strings.
|
||||
///
|
||||
/// The function given should take a clap argument name and return a help
|
||||
@@ -49,10 +39,9 @@ pub fn app_long() -> App<'static, 'static> {
|
||||
///
|
||||
/// This is an intentionally stand-alone module so that it can be used easily
|
||||
/// in a `build.rs` script to build shell completion files.
|
||||
fn app<F>(next_line_help: bool, doc: F) -> App<'static, 'static>
|
||||
where F: Fn(&'static str) -> &'static str {
|
||||
pub fn app() -> App<'static, 'static> {
|
||||
let arg = |name| {
|
||||
Arg::with_name(name).help(doc(name)).next_line_help(next_line_help)
|
||||
Arg::with_name(name).help(USAGES[name].short).long_help(USAGES[name].long)
|
||||
};
|
||||
let flag = |name| arg(name).long(name);
|
||||
|
||||
@@ -64,11 +53,7 @@ fn app<F>(next_line_help: bool, doc: F) -> App<'static, 'static>
|
||||
.setting(AppSettings::UnifiedHelpMessage)
|
||||
.usage(USAGE)
|
||||
.template(TEMPLATE)
|
||||
// Handle help/version manually to make their output formatting
|
||||
// consistent with short/long views.
|
||||
.arg(arg("help-short").short("h"))
|
||||
.arg(flag("help"))
|
||||
.arg(arg("ripgrep-version").long("version").short("V"))
|
||||
.help_message("Prints help information. Use --help for more details.")
|
||||
// First, set up primary positional/flag arguments.
|
||||
.arg(arg("pattern")
|
||||
.required_unless_one(&[
|
||||
@@ -158,7 +143,8 @@ fn app<F>(next_line_help: bool, doc: F) -> App<'static, 'static>
|
||||
.arg(flag("no-ignore"))
|
||||
.arg(flag("no-ignore-parent"))
|
||||
.arg(flag("no-ignore-vcs"))
|
||||
.arg(flag("null"))
|
||||
.arg(flag("null").short("0"))
|
||||
.arg(flag("only-matching").short("o").conflicts_with("replace"))
|
||||
.arg(flag("path-separator").value_name("SEPARATOR").takes_value(true))
|
||||
.arg(flag("pretty").short("p"))
|
||||
.arg(flag("replace").short("r").value_name("ARG").takes_value(true))
|
||||
@@ -249,12 +235,12 @@ lazy_static! {
|
||||
red, blue, green, cyan, magenta, yellow, white and black. \
|
||||
Styles are limited to nobold, bold, nointense or intense.\n\n\
|
||||
The format of the flag is {type}:{attribute}:{value}. {type} \
|
||||
should be one of path, line or match. {attribute} can be fg, bg \
|
||||
or style. {value} is either a color (for fg and bg) or a text \
|
||||
style. A special format, {type}:none, will clear all color \
|
||||
settings for {type}.\n\nFor example, the following command will \
|
||||
change the match color to magenta and the background color for \
|
||||
line numbers to yellow:\n\n\
|
||||
should be one of path, line, column or match. {attribute} can \
|
||||
be fg, bg or style. {value} is either a color (for fg and bg) \
|
||||
or a text style. A special format, {type}:none, will clear all \
|
||||
color settings for {type}.\n\nFor example, the following \
|
||||
command will change the match color to magenta and the \
|
||||
background color for line numbers to yellow:\n\n\
|
||||
rg --colors 'match:fg:magenta' --colors 'line:bg:yellow' foo.");
|
||||
doc!(h, "encoding",
|
||||
"Specify the text encoding of files to search.",
|
||||
@@ -388,10 +374,11 @@ lazy_static! {
|
||||
"Limit the number of matching lines per file searched to NUM.");
|
||||
doc!(h, "max-filesize",
|
||||
"Ignore files larger than NUM in size.",
|
||||
"Ignore files larger than NUM in size. Does not ignore directories. \
|
||||
"Ignore files larger than NUM in size. Does not ignore \
|
||||
directories. \
|
||||
\n\nThe input format accepts suffixes of K, M or G which \
|
||||
correspond to kilobytes, megabytes and gigabytes. If no suffix is \
|
||||
provided the input is treated as bytes. \
|
||||
correspond to kilobytes, megabytes and gigabytes. If no suffix \
|
||||
is provided the input is treated as bytes. \
|
||||
\n\nExample: --max-filesize 50K or --max-filesize 80M");
|
||||
doc!(h, "maxdepth",
|
||||
"Descend at most NUM directories.",
|
||||
@@ -435,6 +422,10 @@ lazy_static! {
|
||||
printing a list of matching files such as with --count, \
|
||||
--files-with-matches and --files. This option is useful for use \
|
||||
with xargs.");
|
||||
doc!(h, "only-matching",
|
||||
"Print only matched parts of a line.",
|
||||
"Print only the matched (non-empty) parts of a matching line, \
|
||||
with each such part on a separate output line.");
|
||||
doc!(h, "path-separator",
|
||||
"Path separator to use when printing file paths.",
|
||||
"The path separator to use when printing file paths. This \
|
||||
@@ -496,8 +487,8 @@ lazy_static! {
|
||||
permits specifying one or more other type names (separated by a \
|
||||
comma) that have been defined and its rules will automatically \
|
||||
be imported into the type specified. For example, to create a \
|
||||
type called src that matches C++, Python and Markdown files, one \
|
||||
can use:\n\n\
|
||||
type called src that matches C++, Python and Markdown files, \
|
||||
one can use:\n\n\
|
||||
--type-add 'src:include:cpp,py,md'\n\n\
|
||||
Additional glob rules can still be added to the src type by \
|
||||
using the --type-add flag again:\n\n\
|
||||
|
27
src/args.rs
27
src/args.rs
@@ -5,7 +5,6 @@ use std::fs;
|
||||
use std::io::{self, BufRead};
|
||||
use std::ops;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
@@ -66,6 +65,7 @@ pub struct Args {
|
||||
no_ignore_vcs: bool,
|
||||
no_messages: bool,
|
||||
null: bool,
|
||||
only_matching: bool,
|
||||
path_separator: Option<u8>,
|
||||
quiet: bool,
|
||||
quiet_matched: QuietMatched,
|
||||
@@ -88,26 +88,7 @@ impl Args {
|
||||
///
|
||||
/// Also, initialize a global logger.
|
||||
pub fn parse() -> Result<Args> {
|
||||
use clap::ErrorKind::*;
|
||||
|
||||
let matches = match app::app_short().get_matches_safe() {
|
||||
Ok(matches) => matches,
|
||||
Err(clap::Error { kind: HelpDisplayed, .. }) => {
|
||||
let _ = ::app::app_long().print_help();
|
||||
println!("");
|
||||
process::exit(0);
|
||||
}
|
||||
Err(err) => err.exit(),
|
||||
};
|
||||
if matches.is_present("help-short") {
|
||||
let _ = ::app::app_short().print_help();
|
||||
println!("");
|
||||
process::exit(0);
|
||||
}
|
||||
if matches.is_present("ripgrep-version") {
|
||||
println!("ripgrep {}", crate_version!());
|
||||
process::exit(0);
|
||||
}
|
||||
let matches = app::app().get_matches();
|
||||
|
||||
let mut logb = env_logger::LogBuilder::new();
|
||||
if matches.is_present("debug") {
|
||||
@@ -161,6 +142,7 @@ impl Args {
|
||||
.heading(self.heading)
|
||||
.line_per_match(self.line_per_match)
|
||||
.null(self.null)
|
||||
.only_matching(self.only_matching)
|
||||
.path_separator(self.path_separator)
|
||||
.with_filename(self.with_filename)
|
||||
.max_columns(self.max_columns);
|
||||
@@ -365,6 +347,7 @@ impl<'a> ArgMatches<'a> {
|
||||
no_ignore_vcs: self.no_ignore_vcs(),
|
||||
no_messages: self.is_present("no-messages"),
|
||||
null: self.is_present("null"),
|
||||
only_matching: self.is_present("only-matching"),
|
||||
path_separator: try!(self.path_separator()),
|
||||
quiet: quiet,
|
||||
quiet_matched: QuietMatched::new(quiet),
|
||||
@@ -837,7 +820,7 @@ impl<'a> ArgMatches<'a> {
|
||||
let caps = try!(re.captures(&max_filesize)
|
||||
.ok_or("invalid format for max-filesize argument"));
|
||||
|
||||
let value = try!(caps[1].parse::<u64>().map_err(|err| err.to_string()));
|
||||
let value = try!(caps[1].parse::<u64>().map_err(|err|err.to_string()));
|
||||
let suffix = caps.get(2).map(|x| x.as_str());
|
||||
|
||||
match suffix {
|
||||
|
@@ -1,5 +1,3 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::cmp;
|
||||
use std::io::{self, Read};
|
||||
|
||||
@@ -290,10 +288,6 @@ mod tests {
|
||||
|
||||
use super::{Bom, BomPeeker, DecodeReader};
|
||||
|
||||
fn utf8(bytes: &[u8]) -> &str {
|
||||
::std::str::from_utf8(bytes).unwrap()
|
||||
}
|
||||
|
||||
fn read_to_string<R: Read>(mut rdr: R) -> String {
|
||||
let mut s = String::new();
|
||||
rdr.read_to_string(&mut s).unwrap();
|
||||
@@ -453,7 +447,8 @@ mod tests {
|
||||
test_trans_simple!(trans_simple_utf16be, "utf-16be", b"\x04\x16", "Ж");
|
||||
test_trans_simple!(trans_simple_chinese, "chinese", b"\xA7\xA8", "Ж");
|
||||
test_trans_simple!(trans_simple_korean, "korean", b"\xAC\xA8", "Ж");
|
||||
test_trans_simple!(trans_simple_big5_hkscs, "big5-hkscs", b"\xC7\xFA", "Ж");
|
||||
test_trans_simple!(
|
||||
trans_simple_big5_hkscs, "big5-hkscs", b"\xC7\xFA", "Ж");
|
||||
test_trans_simple!(trans_simple_gbk, "gbk", b"\xA7\xA8", "Ж");
|
||||
test_trans_simple!(trans_simple_sjis, "sjis", b"\x84\x47", "Ж");
|
||||
test_trans_simple!(trans_simple_eucjp, "euc-jp", b"\xA7\xA8", "Ж");
|
||||
|
183
src/printer.rs
183
src/printer.rs
@@ -58,6 +58,8 @@ pub struct Printer<W> {
|
||||
/// Whether to print NUL bytes after a file path instead of new lines
|
||||
/// or `:`.
|
||||
null: bool,
|
||||
/// Print only the matched (non-empty) parts of a matching line
|
||||
only_matching: bool,
|
||||
/// A string to use as a replacement of each match in a matching line.
|
||||
replace: Option<Vec<u8>>,
|
||||
/// Whether to prefix each match with the corresponding file name.
|
||||
@@ -83,6 +85,7 @@ impl<W: WriteColor> Printer<W> {
|
||||
heading: false,
|
||||
line_per_match: false,
|
||||
null: false,
|
||||
only_matching: false,
|
||||
replace: None,
|
||||
with_filename: false,
|
||||
colors: ColorSpecs::default(),
|
||||
@@ -144,6 +147,12 @@ impl<W: WriteColor> Printer<W> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Print only the matched (non-empty) parts of a matching line
|
||||
pub fn only_matching(mut self, yes: bool) -> Printer<W> {
|
||||
self.only_matching = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// A separator to use when printing file paths. When empty, use the
|
||||
/// default separator for the current platform. (/ on Unix, \ on Windows.)
|
||||
pub fn path_separator(mut self, sep: Option<u8>) -> Printer<W> {
|
||||
@@ -153,9 +162,6 @@ impl<W: WriteColor> Printer<W> {
|
||||
|
||||
/// Replace every match in each matching line with the replacement string
|
||||
/// given.
|
||||
///
|
||||
/// The replacement string syntax is documented here:
|
||||
/// https://doc.rust-lang.org/regex/regex/bytes/struct.Captures.html#method.expand
|
||||
pub fn replace(mut self, replacement: Vec<u8>) -> Printer<W> {
|
||||
self.replace = Some(replacement);
|
||||
self
|
||||
@@ -204,22 +210,14 @@ impl<W: WriteColor> Printer<W> {
|
||||
pub fn path<P: AsRef<Path>>(&mut self, path: P) {
|
||||
let path = strip_prefix("./", path.as_ref()).unwrap_or(path.as_ref());
|
||||
self.write_path(path);
|
||||
if self.null {
|
||||
self.write(b"\x00");
|
||||
} else {
|
||||
self.write_eol();
|
||||
}
|
||||
self.write_path_eol();
|
||||
}
|
||||
|
||||
/// Prints the given path and a count of the number of matches found.
|
||||
pub fn path_count<P: AsRef<Path>>(&mut self, path: P, count: u64) {
|
||||
if self.with_filename {
|
||||
self.write_path(path);
|
||||
if self.null {
|
||||
self.write(b"\x00");
|
||||
} else {
|
||||
self.write(b":");
|
||||
}
|
||||
self.write_path_sep(b':');
|
||||
}
|
||||
self.write(count.to_string().as_bytes());
|
||||
self.write_eol();
|
||||
@@ -227,13 +225,11 @@ impl<W: WriteColor> Printer<W> {
|
||||
|
||||
/// Prints the context separator.
|
||||
pub fn context_separate(&mut self) {
|
||||
// N.B. We can't use `write` here because of borrowing restrictions.
|
||||
if self.context_separator.is_empty() {
|
||||
return;
|
||||
}
|
||||
self.has_printed = true;
|
||||
let _ = self.wtr.write_all(&self.context_separator);
|
||||
let _ = self.wtr.write_all(&[self.eol]);
|
||||
self.write_eol();
|
||||
}
|
||||
|
||||
pub fn matched<P: AsRef<Path>>(
|
||||
@@ -245,7 +241,7 @@ impl<W: WriteColor> Printer<W> {
|
||||
end: usize,
|
||||
line_number: Option<u64>,
|
||||
) {
|
||||
if !self.line_per_match {
|
||||
if !self.line_per_match && !self.only_matching {
|
||||
let column =
|
||||
if self.column {
|
||||
Some(re.find(&buf[start..end])
|
||||
@@ -280,16 +276,17 @@ impl<W: WriteColor> Printer<W> {
|
||||
) {
|
||||
if self.heading && self.with_filename && !self.has_printed {
|
||||
self.write_file_sep();
|
||||
self.write_heading(path.as_ref());
|
||||
self.write_path(path);
|
||||
self.write_path_eol();
|
||||
} else if !self.heading && self.with_filename {
|
||||
self.write_non_heading_path(path.as_ref());
|
||||
self.write_path(path);
|
||||
self.write_path_sep(b':');
|
||||
}
|
||||
if let Some(line_number) = line_number {
|
||||
self.line_number(line_number, b':');
|
||||
}
|
||||
if let Some(c) = column {
|
||||
self.write((c + 1).to_string().as_bytes());
|
||||
self.write(b":");
|
||||
self.column_number(c + 1, b':');
|
||||
}
|
||||
if self.replace.is_some() {
|
||||
let mut count = 0;
|
||||
@@ -299,11 +296,9 @@ impl<W: WriteColor> Printer<W> {
|
||||
re.replace_all(&buf[start..end], replacer)
|
||||
};
|
||||
if self.max_columns.map_or(false, |m| line.len() > m) {
|
||||
let _ = self.wtr.set_color(self.colors.matched());
|
||||
let msg = format!(
|
||||
"[Omitted long line with {} replacements]", count);
|
||||
self.write(msg.as_bytes());
|
||||
let _ = self.wtr.reset();
|
||||
self.write_colored(msg.as_bytes(), |colors| colors.matched());
|
||||
self.write_eol();
|
||||
return;
|
||||
}
|
||||
@@ -312,7 +307,13 @@ impl<W: WriteColor> Printer<W> {
|
||||
self.write_eol();
|
||||
}
|
||||
} else {
|
||||
self.write_matched_line(re, &buf[start..end]);
|
||||
let line_buf = if self.only_matching {
|
||||
let m = re.find(&buf[start..end]).unwrap();
|
||||
&buf[start + m.start()..start + m.end()]
|
||||
} else {
|
||||
&buf[start..end]
|
||||
};
|
||||
self.write_matched_line(re, line_buf);
|
||||
// write_matched_line guarantees to write a newline.
|
||||
}
|
||||
}
|
||||
@@ -320,10 +321,8 @@ impl<W: WriteColor> Printer<W> {
|
||||
fn write_matched_line(&mut self, re: &Regex, buf: &[u8]) {
|
||||
if self.max_columns.map_or(false, |m| buf.len() > m) {
|
||||
let count = re.find_iter(buf).count();
|
||||
let _ = self.wtr.set_color(self.colors.matched());
|
||||
let msg = format!("[Omitted long line with {} matches]", count);
|
||||
self.write(msg.as_bytes());
|
||||
let _ = self.wtr.reset();
|
||||
self.write_colored(msg.as_bytes(), |colors| colors.matched());
|
||||
self.write_eol();
|
||||
return;
|
||||
}
|
||||
@@ -333,9 +332,8 @@ impl<W: WriteColor> Printer<W> {
|
||||
let mut last_written = 0;
|
||||
for m in re.find_iter(buf) {
|
||||
self.write(&buf[last_written..m.start()]);
|
||||
let _ = self.wtr.set_color(self.colors.matched());
|
||||
self.write(&buf[m.start()..m.end()]);
|
||||
let _ = self.wtr.reset();
|
||||
self.write_colored(
|
||||
&buf[m.start()..m.end()], |colors| colors.matched());
|
||||
last_written = m.end();
|
||||
}
|
||||
self.write(&buf[last_written..]);
|
||||
@@ -355,14 +353,11 @@ impl<W: WriteColor> Printer<W> {
|
||||
) {
|
||||
if self.heading && self.with_filename && !self.has_printed {
|
||||
self.write_file_sep();
|
||||
self.write_heading(path.as_ref());
|
||||
self.write_path(path);
|
||||
self.write_path_eol();
|
||||
} else if !self.heading && self.with_filename {
|
||||
self.write_path(path.as_ref());
|
||||
if self.null {
|
||||
self.write(b"\x00");
|
||||
} else {
|
||||
self.write(b"-");
|
||||
}
|
||||
self.write_path(path);
|
||||
self.write_path_sep(b'-');
|
||||
}
|
||||
if let Some(line_number) = line_number {
|
||||
self.line_number(line_number, b'-');
|
||||
@@ -378,10 +373,19 @@ impl<W: WriteColor> Printer<W> {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_heading<P: AsRef<Path>>(&mut self, path: P) {
|
||||
let _ = self.wtr.set_color(self.colors.path());
|
||||
self.write_path(path.as_ref());
|
||||
let _ = self.wtr.reset();
|
||||
fn separator(&mut self, sep: &[u8]) {
|
||||
self.write(&sep);
|
||||
}
|
||||
|
||||
fn write_path_sep(&mut self, sep: u8) {
|
||||
if self.null {
|
||||
self.write(b"\x00");
|
||||
} else {
|
||||
self.separator(&[sep]);
|
||||
}
|
||||
}
|
||||
|
||||
fn write_path_eol(&mut self) {
|
||||
if self.null {
|
||||
self.write(b"\x00");
|
||||
} else {
|
||||
@@ -389,52 +393,43 @@ impl<W: WriteColor> Printer<W> {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_non_heading_path<P: AsRef<Path>>(&mut self, path: P) {
|
||||
let _ = self.wtr.set_color(self.colors.path());
|
||||
self.write_path(path.as_ref());
|
||||
let _ = self.wtr.reset();
|
||||
if self.null {
|
||||
self.write(b"\x00");
|
||||
} else {
|
||||
self.write(b":");
|
||||
}
|
||||
}
|
||||
|
||||
fn line_number(&mut self, n: u64, sep: u8) {
|
||||
let _ = self.wtr.set_color(self.colors.line());
|
||||
self.write(n.to_string().as_bytes());
|
||||
let _ = self.wtr.reset();
|
||||
self.write(&[sep]);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn write_path<P: AsRef<Path>>(&mut self, path: P) {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
let path = path.as_ref().as_os_str().as_bytes();
|
||||
match self.path_separator {
|
||||
None => self.write(path),
|
||||
Some(sep) => self.write_path_with_sep(path, sep),
|
||||
}
|
||||
self.write_path_replace_separator(path);
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn write_path<P: AsRef<Path>>(&mut self, path: P) {
|
||||
let path = path.as_ref().to_string_lossy();
|
||||
self.write_path_replace_separator(path.as_bytes());
|
||||
}
|
||||
|
||||
fn write_path_replace_separator(&mut self, path: &[u8]) {
|
||||
match self.path_separator {
|
||||
None => self.write(path.as_bytes()),
|
||||
Some(sep) => self.write_path_with_sep(path.as_bytes(), sep),
|
||||
None => self.write_colored(path, |colors| colors.path()),
|
||||
Some(sep) => {
|
||||
let transformed_path: Vec<_> = path.iter().map(|&b| {
|
||||
if b == b'/' || (cfg!(windows) && b == b'\\') {
|
||||
sep
|
||||
} else {
|
||||
b
|
||||
}
|
||||
}).collect();
|
||||
self.write_colored(&transformed_path, |colors| colors.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_path_with_sep(&mut self, path: &[u8], sep: u8) {
|
||||
let mut path = path.to_vec();
|
||||
for b in &mut path {
|
||||
if *b == b'/' || (cfg!(windows) && *b == b'\\') {
|
||||
*b = sep;
|
||||
}
|
||||
}
|
||||
self.write(&path);
|
||||
fn line_number(&mut self, n: u64, sep: u8) {
|
||||
self.write_colored(n.to_string().as_bytes(), |colors| colors.line());
|
||||
self.separator(&[sep]);
|
||||
}
|
||||
|
||||
fn column_number(&mut self, n: u64, sep: u8) {
|
||||
self.write_colored(n.to_string().as_bytes(), |colors| colors.column());
|
||||
self.separator(&[sep]);
|
||||
}
|
||||
|
||||
fn write(&mut self, buf: &[u8]) {
|
||||
@@ -447,6 +442,14 @@ impl<W: WriteColor> Printer<W> {
|
||||
self.write(&[eol]);
|
||||
}
|
||||
|
||||
fn write_colored<F>(&mut self, buf: &[u8], get_color: F)
|
||||
where F: Fn(&ColorSpecs) -> &ColorSpec
|
||||
{
|
||||
let _ = self.wtr.set_color( get_color(&self.colors) );
|
||||
self.write(buf);
|
||||
let _ = self.wtr.reset();
|
||||
}
|
||||
|
||||
fn write_file_sep(&mut self) {
|
||||
if let Some(ref sep) = self.file_separator {
|
||||
self.has_printed = true;
|
||||
@@ -492,7 +495,7 @@ impl fmt::Display for Error {
|
||||
match *self {
|
||||
Error::UnrecognizedOutType(ref name) => {
|
||||
write!(f, "Unrecognized output type '{}'. Choose from: \
|
||||
path, line, match.", name)
|
||||
path, line, column, match.", name)
|
||||
}
|
||||
Error::UnrecognizedSpecType(ref name) => {
|
||||
write!(f, "Unrecognized spec type '{}'. Choose from: \
|
||||
@@ -503,12 +506,14 @@ impl fmt::Display for Error {
|
||||
}
|
||||
Error::UnrecognizedStyle(ref name) => {
|
||||
write!(f, "Unrecognized style attribute '{}'. Choose from: \
|
||||
nobold, bold.", name)
|
||||
nobold, bold, nointense, intense.", name)
|
||||
}
|
||||
Error::InvalidFormat(ref original) => {
|
||||
write!(f, "Invalid color speci format: '{}'. Valid format \
|
||||
is '(path|line|match):(fg|bg|style):(value)'.",
|
||||
original)
|
||||
write!(
|
||||
f,
|
||||
"Invalid color speci format: '{}'. Valid format \
|
||||
is '(path|line|column|match):(fg|bg|style):(value)'.",
|
||||
original)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -525,6 +530,7 @@ impl From<ParseColorError> for Error {
|
||||
pub struct ColorSpecs {
|
||||
path: ColorSpec,
|
||||
line: ColorSpec,
|
||||
column: ColorSpec,
|
||||
matched: ColorSpec,
|
||||
}
|
||||
|
||||
@@ -554,7 +560,7 @@ pub struct ColorSpecs {
|
||||
/// The format of a `Spec` is a triple: `{type}:{attribute}:{value}`. Each
|
||||
/// component is defined as follows:
|
||||
///
|
||||
/// * `{type}` can be one of `path`, `line` or `match`.
|
||||
/// * `{type}` can be one of `path`, `line`, `column` or `match`.
|
||||
/// * `{attribute}` can be one of `fg`, `bg` or `style`. `{attribute}` may also
|
||||
/// be the special value `none`, in which case, `{value}` can be omitted.
|
||||
/// * `{value}` is either a color name (for `fg`/`bg`) or a style instruction.
|
||||
@@ -593,6 +599,7 @@ enum SpecValue {
|
||||
enum OutType {
|
||||
Path,
|
||||
Line,
|
||||
Column,
|
||||
Match,
|
||||
}
|
||||
|
||||
@@ -623,6 +630,7 @@ impl ColorSpecs {
|
||||
match user_spec.ty {
|
||||
OutType::Path => user_spec.merge_into(&mut specs.path),
|
||||
OutType::Line => user_spec.merge_into(&mut specs.line),
|
||||
OutType::Column => user_spec.merge_into(&mut specs.column),
|
||||
OutType::Match => user_spec.merge_into(&mut specs.matched),
|
||||
}
|
||||
}
|
||||
@@ -639,6 +647,11 @@ impl ColorSpecs {
|
||||
&self.line
|
||||
}
|
||||
|
||||
/// Return the color specification for coloring column numbers.
|
||||
fn column(&self) -> &ColorSpec {
|
||||
&self.column
|
||||
}
|
||||
|
||||
/// Return the color specification for coloring matched text.
|
||||
fn matched(&self) -> &ColorSpec {
|
||||
&self.matched
|
||||
@@ -714,6 +727,7 @@ impl FromStr for OutType {
|
||||
match &*s.to_lowercase() {
|
||||
"path" => Ok(OutType::Path),
|
||||
"line" => Ok(OutType::Line),
|
||||
"column" => Ok(OutType::Column),
|
||||
"match" => Ok(OutType::Match),
|
||||
_ => Err(Error::UnrecognizedOutType(s.to_string())),
|
||||
}
|
||||
@@ -765,6 +779,7 @@ mod tests {
|
||||
assert_eq!(ColorSpecs::new(user_specs), ColorSpecs {
|
||||
path: ColorSpec::default(),
|
||||
line: ColorSpec::default(),
|
||||
column: ColorSpec::default(),
|
||||
matched: expect_matched,
|
||||
});
|
||||
}
|
||||
@@ -800,6 +815,12 @@ mod tests {
|
||||
ty: OutType::Line,
|
||||
value: SpecValue::None,
|
||||
});
|
||||
|
||||
let spec: Spec = "column:bg:green".parse().unwrap();
|
||||
assert_eq!(spec, Spec {
|
||||
ty: OutType::Column,
|
||||
value: SpecValue::Bg(Color::Green),
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@@ -3,8 +3,8 @@ 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.
|
||||
Note that this module doesn't quite support everything that `search_stream`
|
||||
does. Notably, showing contexts.
|
||||
*/
|
||||
use std::cmp;
|
||||
use std::path::Path;
|
||||
|
3
termcolor/COPYING
Normal file
3
termcolor/COPYING
Normal file
@@ -0,0 +1,3 @@
|
||||
This project is dual-licensed under the Unlicense and MIT licenses.
|
||||
|
||||
You may use this code under the terms of either license.
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "termcolor"
|
||||
version = "0.3.1" #:version
|
||||
version = "0.3.2" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = """
|
||||
A simple cross platform library for writing colored text to a terminal.
|
||||
|
21
termcolor/LICENSE-MIT
Normal file
21
termcolor/LICENSE-MIT
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Andrew Gallant
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
24
termcolor/UNLICENSE
Normal file
24
termcolor/UNLICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
@@ -1057,6 +1057,33 @@ clean!(regression_405, "test", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
assert_eq!(lines, format!("{}:test\n", path("bar/foo/file2.txt")));
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/428
|
||||
clean!(regression_428_color_context_path, "foo", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("sherlock", "foo\nbar");
|
||||
cmd.arg("-A1").arg("-H").arg("--no-heading").arg("-N")
|
||||
.arg("--colors=match:none").arg("--color=always");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = format!("\
|
||||
{colored_path}:foo
|
||||
{colored_path}-bar
|
||||
", colored_path=format!("\x1b\x5b\x6d\x1b\x5b\x33\x35\x6d{path}\x1b\x5b\x6d", path=path("sherlock")));
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/428
|
||||
clean!(regression_428_unrecognized_style, "Sherlok", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("--colors=match:style:");
|
||||
wd.assert_err(&mut cmd);
|
||||
|
||||
let output = cmd.output().unwrap();
|
||||
let err = String::from_utf8_lossy(&output.stderr);
|
||||
let expected = "\
|
||||
Unrecognized style attribute ''. Choose from: nobold, bold, nointense, intense.
|
||||
";
|
||||
assert_eq!(err, expected);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/1
|
||||
clean!(feature_1_sjis, "Шерлок Холмс", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
let sherlock =
|
||||
@@ -1139,6 +1166,32 @@ be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/34
|
||||
sherlock!(feature_34_only_matching, "Sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("--only-matching");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock:Sherlock
|
||||
sherlock:Sherlock
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/34
|
||||
sherlock!(feature_34_only_matching_line_column, "Sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("--only-matching").arg("--column").arg("--line-number");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = "\
|
||||
sherlock:1:57:Sherlock
|
||||
sherlock:3:49:Sherlock
|
||||
";
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/45
|
||||
sherlock!(feature_45_relative_cwd, "test", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
@@ -1390,6 +1443,15 @@ clean!(feature_275_pathsep, "test", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
assert_eq!(lines, "fooZbar:test\n");
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/419
|
||||
sherlock!(feature_419_zero_as_shortcut_for_null, "Sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("-0").arg("--count");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
assert_eq!(lines, "sherlock\x002\n");
|
||||
});
|
||||
|
||||
#[test]
|
||||
fn binary_nosearch() {
|
||||
let wd = WorkDir::new("binary_nosearch");
|
||||
|
Reference in New Issue
Block a user