Compare commits

..

36 Commits

Author SHA1 Message Date
Andrew Gallant
9d7b6eb09a wincolor-0.1.4 2017-06-19 13:26:15 -04:00
Alex Crichton
7763c98188 wincolor: Re-fetch the console on all calls
The primary motivation for this commit was rust-lang/cargo#4189 where dropping a
`wincolor::Console` would call `CloseHandle` to close the console handle. Cargo
creates a few `Console` instances so it ended up closing stdout a little
earlier as intended!

The `GetStdHandle` function returns handles I believe aren't intended to be
closed (as there's no refcounting). I believe libstd doesn't close these
handles.

This commit also moves to calling `GetStdHandle` on demand which libstd changed
to doing so recently as well, preventing caching of stale handles that change
over time with calls to `SetStdHandle`.
2017-06-19 12:57:45 -04:00
Evan.Mattiza
06393f888c fix word boundary w/ capture group
fixes BurntSushi/ripgrep#506. Word boundary search as arg had unexpected
behavior. added capture group to regex to encapsulate 'or' option search and
prevent expansion and partial boundary finds.

Signed-off-by: Evan.Mattiza <emattiza@gmail.com>
2017-06-15 06:55:55 -04:00
Sid-Ali Teir
e0989ef13b add yocto file types 2017-06-12 19:02:21 -04:00
Gent Bajraj
45e850aff7 Add julia as file type 2017-06-12 11:39:19 -04:00
Eric Nielsen
f2d1c582a8 Use clap's overrides_with and default_value_if
to better organize options. These are the changes:
- color will have default value of "never" if --vimgrep is given,
  and only if no --color option is given
- last overrides previous: --line-number and --no-line-number, --heading
  and --no-heading, --with-filename and --no-filename, and --vimgrep and
  --count
- no heading will be show if --vimgrep is defined. This worked inside
  vim actually because heading is also only shown if tty is stdout
  (which is not the case when rg is called from vim).

Unfortunately, clap does not behave like a usual GNU/POSIX in some
cases, as reported in https://github.com/kbknapp/clap-rs/issues/970
and https://github.com/kbknapp/clap-rs/issues/976 (having all the bells
and whistles, on the other hand). So we still have issues like rg
failing when same argument is given more than once (unless for the few
ones marked with `multiple(true)`), or having unintuitive precedence
rules (and probably non-intentional, just there because of clap's
limitations) like:
- --no-filename over --vimgrep
- --no-line-number over --column, --pretty or --vimgrep
- --no-heading over --pretty
regardless of the order in which options where given, where the desired
behavior would be that the last option would override the previous ones
given.
2017-06-12 10:29:38 -04:00
Brian Gianforcaro
ab70815ea2 Add "msbuild" filetype for msbuild related files
This commit adds a "msbuild" filetype grouping, with
a few different file types being mapped to this grouping:

- MSBuild project files: .csproj, .vcxproj, .fsproj, .proj
- MSBuild shared property files: .props
- MSBuild shared targets files: .targets
2017-06-12 07:48:31 -04:00
Brian Gianforcaro
27f97db510 Add .inl as one of the c++ file typee definitions.
.inl files are often used by convention to include
both inline functions, or function templates.
2017-06-12 07:48:31 -04:00
Taryn Hill
506ad1f3cf Add a cshtml ignore type 2017-06-06 18:08:42 -04:00
Eric Nielsen
13235b596f Use uppercase for required argument names
This reverts a couple of changes introduced in 4c78ca8 and keeps the
`PATTERN` argument consistently uppercased, so error messages can look
like:

    error: The following required arguments were not provided:
        <PATTERN>
2017-06-01 20:41:04 -04:00
Fangrui Song
2628c8f38e Add Zsh completion file 2017-05-29 16:55:03 -04:00
Andrew Gallant
112b3c5e0a Fix another bug in -o/--only-matching.
The handling of the -o/--only-matching was incorrect. We cannot ever
re-run regexes on a *subset* of a matched line, because it doesn't take
into account zero width assertions on the edges of the regex. This
occurs whenever an end user uses an assertion explicity, but also occurs
when one is used implicitly, e.g., with the `-w` flag.

This instead reuses the initial matched range from the first regex
match. We also apply this fix to coloring.

Fixes #493
2017-05-29 09:51:58 -04:00
Eric Nielsen
4c78ca8b70 Update help and man pages
Formatting of rg.1.md. Remove backticks from already indented code.
Add missing italic to some arguments, Replace -n by --line-number in
--pretty for better clarity. Add explicit example of `*.foo` instead of
`<glob>` in examples. Add vim information to --vimgrep.

In src/app.rs, also changed help text for pattern and regexp. Actually,
"multiple patterns may be given" was not true for the standalone
pattern.
2017-05-26 19:17:59 -04:00
Eric Nielsen
ff898cd105 Remove vestigial color function from src/args.rs
It's usage was replaced by the `color_choice` function. Also, `color`
was outdated, as it didn't include testing for the new "ansi" option.
2017-05-26 07:00:58 -04:00
Eric Nielsen
2c98e5ce1e Update documentation for --color ansi
In `src/app.rs`, change typo "When ansi used" to "When ansi is used".
Update man pages with missing `ansi` option for `--color`.
2017-05-25 18:58:11 -04:00
Eric Nielsen
1e3fc79949 Should show filename for one file with vimgrep
With vim configured with:

    set grepprg=rg\ --vimgrep
    set grepformat^=%f:%l:%c:%m

and running the command `:grep 'vimgrep' doc/rg.1`, the output should
be:

    doc/rg.1:446:8:.B \-\-vimgrep

but the actual output was:

    446:8:.B \-\-vimgrep

Same issue would happen if results only match one file. Ag behaves as
expected.
2017-05-24 23:12:16 -04:00
Eric Nielsen
d1bbc6956b Fix typo, should be 'mode' instead of 'more'
in man pages.
2017-05-24 17:51:42 -04:00
Manuel Vives
cd6c54f5f4 Add support for QMake files 2017-05-24 16:44:22 -04:00
Andrew Gallant
44c03f58bc bump deps, redux
This only bumps the regex dependency. The new clap version causes a bump
in unicode-segmentation, which in turn requires a Rust 1.15, which is
above ripgrep's currently supported minimum Rust version of 1.12.
2017-05-21 15:56:56 -04:00
Andrew Gallant
d1a6ab922e Revert "bump deps"
This reverts commit b860fa3acd.
2017-05-21 15:52:58 -04:00
Andrew Gallant
b860fa3acd bump deps 2017-05-21 12:33:13 -04:00
Marc Tiehuis
229b8e3b33 Make --quiet flag apply when using --files option
Fixes #483.
2017-05-19 20:00:47 -04:00
Andrew Gallant
a515c4d601 update brew tap 2017-05-11 20:11:13 -04:00
Andrew Gallant
5a666b042d bump ripgrep, ignore, globset
The `ignore` and `globset` crates both got breaking changes in the
course of fixing #444, so increase 0.x to 0.(x+1).
2017-05-11 19:12:20 -04:00
Andrew Gallant
16109166fe changelog 0.5.2 2017-05-11 19:05:40 -04:00
Andrew Gallant
0b685c8429 deps: update clap to 2.24
Fixes #442
2017-05-08 19:24:11 -04:00
Eli Miller
d2c7a76a3c Add Powershell tips and autocompletion instructions 2017-05-08 19:23:41 -04:00
Chris MacNaughton
20f7d9b3a2 Add snapcraft.yaml
[Snapcraft](https://snapcraft.io/) makes Linux packaging very simple in a cross-distro
way. This adds the snapcraft.yaml file to setup a snap of ripgrep
2017-05-04 08:30:22 -04:00
Roman Proskuryakov
362abed44a Fix reiteration of the first found match with --only-mathing flag
Fixes #451
2017-04-21 08:11:55 -04:00
Andrew Gallant
c50b8b4125 Add better error messages for invalid globs.
This threads the original glob given by end users through all of the
glob parsing errors. This was slightly trickier than it might appear
because the gitignore implementation actually modifies the glob before
compiling it. So in order to get better glob error messages everywhere,
we need to track the original glob both in the glob parser and in the
higher-level abstractions in the `ignore` crate.

Fixes #444
2017-04-12 18:14:23 -04:00
Andrew Gallant
7ad23e5565 Use for_label_no_replacement.
This will cause certain unsupported legacy encodings to act as if they
don't exist, in order to avoid using an unhelpful (in the context of
file searching) "replacement" encoding.

Kudos to @hsivonen for chirping about this!
2017-04-12 18:14:23 -04:00
Marc Tiehuis
66efbad871 Add dfa-size-limit and regex-size-limit arguments
Fixes #362.
2017-04-12 18:14:23 -04:00
Bryan Richter
1f2a9b0306 Add nix 2017-04-12 18:10:59 -04:00
Andrew Gallant
a45fe94240 update brew tap 2017-04-09 10:28:22 -04:00
Andrew Gallant
ac1c95a6d9 0.5.1 2017-04-09 09:47:00 -04:00
Andrew Gallant
685b431d80 bump deps 2017-04-09 09:46:37 -04:00
27 changed files with 881 additions and 300 deletions

8
.gitignore vendored
View File

@@ -6,3 +6,11 @@ target
/ignore/Cargo.lock
/termcolor/Cargo.lock
/wincolor/Cargo.lock
# Snapcraft files
stage
prime
parts
*.snap
*.pyc
ripgrep*_source.tar.bz2

View File

@@ -1,3 +1,21 @@
0.5.2 (2017-05-11)
==================
Feature enhancements:
* Added or improved file type filtering for Nix.
* [FEATURE #362](https://github.com/BurntSushi/ripgrep/issues/362):
Add `--regex-size-limit` and `--dfa-size-limit` flags.
* [FEATURE #444](https://github.com/BurntSushi/ripgrep/issues/444):
Improve error messages for invalid globs.
Bug fixes:
* [BUG #442](https://github.com/BurntSushi/ripgrep/issues/442):
Fix line wrapping in `--help` output.
* [BUG #451](https://github.com/BurntSushi/ripgrep/issues/451):
Fix bug with duplicate output when using `-o/--only-matching` flag.
0.5.1 (2017-04-09)
==================
Feature enhancements:

88
Cargo.lock generated
View File

@@ -1,21 +1,21 @@
[root]
name = "ripgrep"
version = "0.5.0"
version = "0.5.2"
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.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)",
"clap 2.24.1 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding_rs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"grep 0.1.6",
"ignore 0.1.9",
"lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"ignore 0.2.0",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"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)",
"num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 0.3.2",
]
@@ -39,7 +39,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -63,14 +63,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clap"
version = "2.23.1"
version = "2.24.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.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)",
"term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -83,7 +83,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "encoding_rs"
version = "0.5.0"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -108,19 +108,19 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "globset"
version = "0.1.4"
version = "0.2.0"
dependencies = [
"aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -129,20 +129,20 @@ version = "0.1.6"
dependencies = [
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ignore"
version = "0.1.9"
version = "0.2.0"
dependencies = [
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.1.4",
"lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.2.0",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -158,12 +158,12 @@ dependencies = [
[[package]]
name = "lazy_static"
version = "0.2.5"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.21"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -176,7 +176,7 @@ name = "memchr"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -186,26 +186,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fs2 0.4.1 (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.21 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (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.3.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -213,7 +213,7 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -237,11 +237,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "term_size"
version = "0.2.3"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -254,11 +254,11 @@ dependencies = [
[[package]]
name = "thread-id"
version = "3.0.0"
version = "3.1.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.21 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -266,7 +266,7 @@ name = "thread_local"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -338,26 +338,26 @@ dependencies = [
"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.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d480c39a2e5f9b3a3798c661613e1b0e7a7ae71e005102d4aa910fc3289df484"
"checksum clap 2.24.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7541069be0b8aec41030802abe8b5cdef0490070afaa55418adea93b1e431e0"
"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 encoding_rs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e4bc519d572af08cf72c4d61e0de9b05e9fa66d1fdb5e739fb5c405860b42d43"
"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
"checksum 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.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4732c563b9a21a406565c4747daa7b46742f082911ae4753f390dc9ec7ee1a97"
"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e"
"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
"checksum memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46f3c7359028b31999287dae4e5047ddfe90a23b7dca2282ce759b491080c99b"
"checksum num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18c392466409c50b87369414a2680c93e739aedeb498eb2bff7d7eb569744e2"
"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"
"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
"checksum simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63b5847c2d766ca7ce7227672850955802fabd779ba616aeabead4c2c3877023"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a"
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773"
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"

View File

@@ -1,6 +1,6 @@
[package]
name = "ripgrep"
version = "0.5.0" #:version
version = "0.5.2" #: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.23.1"
clap = "2.24.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.9", path = "ignore" }
ignore = { version = "0.2.0", 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.23.1"
clap = "2.24.1"
lazy_static = "0.2"
[features]

View File

@@ -338,10 +338,17 @@ The syntax supported is
Shell completion files are included in the release tarball for Bash, Fish, Zsh
and PowerShell.
For **bash**, move `rg.bash-completion` to `$XDG_CONFIG_HOME/bash_completion`
For **bash**, move `complete/rg.bash-completion` to `$XDG_CONFIG_HOME/bash_completion`
or `/etc/bash_completion.d/`.
For **fish**, move `rg.fish` to `$HOME/.config/fish/completions`.
For **fish**, move `complete/rg.fish` to `$HOME/.config/fish/completions/`.
For **PowerShell**, add `. _rg.ps1` to your PowerShell
[profile](https://technet.microsoft.com/en-us/library/bb613488(v=vs.85).aspx)
(note the leading period). If the `_rg.ps1` file is not on your `PATH`, do
`. /path/to/_rg.ps1` instead.
For **zsh**, move `complete/_rg` to one of your `$fpath` directories.
### Building
@@ -423,12 +430,48 @@ Powershell special variables:
This alias checks whether there is **Stdin** input and propagates only if there is some lines.
Otherwise empty `$input` will make powershell to trigger `rg` to search empty **Stdin**
##### Piping non-ASCII content to ripgrep
When piping input into native executables in PowerShell, the encoding of the
input is controlled by the `$OutputEncoding` variable. By default, this is set
to US-ASCII, and any characters in the pipeline that don't have encodings in
US-ASCII are converted to `?` (question mark) characters.
To change this setting, set `$OutputEncoding` to a different encoding, as
represented by a .NET encoding object. Some common examples are below. The
value of this variable is reset when PowerShell restarts, so to make this
change take effect every time PowerShell is started add a line setting the
variable into your PowerShell profile.
Example `$OutputEncoding` settings:
* UTF-8 without BOM: `$OutputEncoding = [System.Text.UTF8Encoding]::new()`
* The console's output encoding:
`$OutputEncoding = [System.Console]::OutputEncoding`
If you continue to have encoding problems, you can also force the encoding
that the console will use for printing to UTF-8 with
`[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8`. This
will also reset when PowerShell is restarted, so you can add that line
to your profile as well if you want to make the setting permanent.
### Known issues
#### I just hit Ctrl+C in the middle of ripgrep's output and now my terminal's foreground color is wrong!
Type in `color` on Windows and `echo -ne "\033[0m"` on Unix to restore your
original foreground color.
Type in `color` in cmd.exe (Command Prompt) and `echo -ne "\033[0m"` on Unix
to restore your original foreground color.
In PowerShell, you can add the following code to your profile which will
restore the original foreground color when `Reset-ForegroundColor` is called.
Including the `Set-Alias` line will allow you to call it with simply `color`.
```powershell
$OrigFgColor = $Host.UI.RawUI.ForegroundColor
function Reset-ForegroundColor {
$Host.UI.RawUI.ForegroundColor = $OrigFgColor
}
Set-Alias -Name color -Value Reset-ForegroundColor
```
PR [#187](https://github.com/BurntSushi/ripgrep/pull/187) fixed this, and it
was later deprecated in

View File

@@ -22,6 +22,5 @@ fn main() {
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);
app.gen_completions("rg", Shell::PowerShell, &outdir);
}

View File

@@ -20,7 +20,8 @@ mk_tarball() {
cp target/$TARGET/release/rg "$td/$name/"
cp {doc/rg.1,README.md,UNLICENSE,COPYING,LICENSE-MIT} "$td/$name/"
cp target/$TARGET/release/build/ripgrep-*/out/{_rg,rg.bash-completion,rg.fish,_rg.ps1} "$td/$name/complete/"
cp target/$TARGET/release/build/ripgrep-*/out/{rg.bash-completion,rg.fish,_rg.ps1} "$td/$name/complete/"
cp complete/_rg "$td/$name/complete/"
pushd $td
tar czf "$out_dir/$name.tar.gz" *

142
complete/_rg Normal file
View File

@@ -0,0 +1,142 @@
#compdef rg
# ------------------------------------------------------------------------------
# Copyright (c) 2011 Github zsh-users - http://github.com/zsh-users
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the zsh-users nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL ZSH-USERS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ------------------------------------------------------------------------------
# Description
# -----------
#
# Completion script for ripgrep
#
# ------------------------------------------------------------------------------
# Authors
# -------
#
# * arcizan <ghostrevery@gmail.com>
# * MaskRay <i@maskray.me>
#
# ------------------------------------------------------------------------------
local context state state_descr line
local -A opt_args
local -i ret=1
local -a common_options
common_options=(
'(-a --text)'{-a,--text}'[search binary files as if they were text]'
'(-c, --count)'{-c,--count}'[only show count of matches for each file]'
'--color=[whether to use coloring in match]::when:( always never auto )'
'(1)*'{-e,--regexp=}'[specify pattern]:pattern'
'(-E --encoding)'{-E,--encoding=}'[specify the text encoding of files to search.]:encoding'
'(-F --fixed-strings)'{-F,--fixed-strings}'[treat the pattern as a literal string instead of a regular expression]'
'*'{-g,--glob=}'[include or exclude files for searching that match the given glob]:glob'
'(-h --help)'{-h,--help}'[prints help information]'
'(-i -s -S --ignore-case --case-sensitive --smart-case)'{-i,--ignore-case}'[case insensitive search]'
'(-n -N --line-number --no-line-number)'{-n,--line-number}'[show line numbers]'
'(-n -N --line-number --no-line-number)'{-N,--no-line-number}'[suppress line numbers]'
'(-q --quiet)'{-q,--quiet}'[do not print anything to stdout]'
'(-T --type-not)*'{-t,--type=}'[only search files matching specified type]: :->type'
'(-t --type)*'{-T,--type-not=}'[do not search files matching type]: :->type'
'*'{-u,--unrestricted}'[reduce the level of "smart" searching]'
'(-v --invert-match)'{-v,--invert-match}'[invert matching]'
'(-w --word-regexp)'{-w,--word-regexp}'[only show matches surrounded by word boundaries]'
)
local -a less_common_options
less_common_options=(
'(-A -C --after-context --context)'{-A,--after-context=}'[specify number of lines to show after each match]:number of lines'
'(-B -C --before-context --context)'{-B,--before-context=}'[specify number of lines to show before each match]:number of lines'
'(-A -B -C --after-context --before-context --context)'{-C,--context=}'[specify number of lines to show before and after each match]:number of lines'
'*--colors=[configure color settings and styles]:spec'
'--column[show column numbers in output]'
'--context-separator=[the string used to separate non-continuous context lines in the output]:separator string'
'--debug[show debug message]'
'--dfa-size-limit=[the upper size limit of the generated dfa]:size'
"--file=[search for patterns from the given file]:file:_files"
"--ignore-file=[search additional ignore files]:file:_files"
"--files[print each file that would be searched (but don't search)]"
'(-l --files-with-matches)'{-l,--files-with-matches}'[only show path of each file with matches]'
'(-H --with-filename --no-filename)'{-H,--with-filename}'[prefix each match with the file name that contains it]'
'(-H --with-filename)--no-filename[never show the file name for a match]'
'(-p --no-heading --pretty --vimgrep)--heading[show the file name above clusters of matches from each file]'
"(-p --heading --pretty --vimgrep)--no-heading[don't show any file name heading]"
'--hidden[search hidden directories and files]'
'(-L --follow)'{-L,--follow}'[follow symlinks]'
'(-M --max-columns)'{-M,--max-columns=}"[don't print lines longer than this limit in bytes]:number"
'(-m --max-count)'{-m,--max-count=}'[only show count of matches for each file]:number'
'--max-filesize=[ignore files larger than NUM in size]:size'
'--maxdepth[descend at most N directories below the command line arguments]:depth'
'(--no-mmap)--mmap[search using memory maps when possible]'
'--no-messages[suppress all error messages]'
'(--mmap)--no-mmap[never use memory maps, even when they might be faster]'
"(--no-ignore-parent)--no-ignore[don't respect ignore files]"
"--no-ignore-parent[don't respect ignore files in parent directories]"
"--no-ignore-vcs[don't respect version control ignore files]"
'(-0 --null)'{-0,--null}'[print NUL byte after file names]'
'--path-separator=[path separator to use when printing file paths]'
'(-p --heading --no-heading --pretty --vimgrep)'{-p,--pretty}'[alias for --color=always --heading -n]'
'--regex-size-limit=[the upper size limit of the compiled regex]:size'
'(-r --replace)'{-r,--replace=}'[replace matches with string given]:replace string'
'(-i -s -S --ignore-case --case-sensitive --smart-case)'{-s,--case-sensitive}'[search case sensitively]'
'(-i -s -S --ignore-case --case-sensitive --smart-case)'{-S,--smart-case}'[search case insensitively if the pattern is all lowercase]'
'(-j --threads)'{-j,--threads=}'[the approximate number of threads to use]:number of threads'
'(-v --version)'{-V,--version}'[print version information]'
'(-p --heading --no-heading --pretty)--vimgrep[show results with every match on its own line, including line numbers and column numbers]'
)
local -a file_type_management_options
file_type_management_options=(
'--type-list[show all supported file types and their associated globs]'
'*--type-add=[add a new glob for a particular file type]:type'
'*--type-clear=[clear the file type globs previously defined for specified type]: :->type'
)
_arguments -S -s : \
$common_options \
$less_common_options \
$file_type_management_options \
'(-e --regexp)1: :_guard "^--*" pattern' \
'*:file:_files' \
&& ret=0
case "$state" in
type)
local -U types
types=( ${${(f)"$(_call_program types rg --type-list)"}%%:*} )
_describe -t types "type" types && ret=0
;;
esac
return ret
# Local Variables:
# mode: shell-script
# coding: utf-8-unix
# indent-tabs-mode: nil
# sh-indentation: 2
# sh-basic-offset: 2
# End:
# vim: ft=zsh sw=2 ts=2 et

View File

@@ -7,12 +7,12 @@
rg \- recursively search current directory for lines matching a pattern
.SH SYNOPSIS
.PP
rg [\f[I]options\f[]] <\f[I]pattern\f[]> [\f[I]<\f[]path\f[I]> ...\f[]]
rg [\f[I]options\f[]] \f[I]PATTERN\f[] [\f[I]path\f[] ...]
.PP
rg [\f[I]options\f[]] (\-e PATTERN | \-f FILE) ...
[\f[I]<\f[]path\f[I]> ...\f[]]
rg [\f[I]options\f[]] [\-e \f[I]PATTERN\f[] ...] [\-f \f[I]FILE\f[] ...]
[\f[I]path\f[] ...]
.PP
rg [\f[I]options\f[]] \-\-files [\f[I]<\f[]path\f[I]> ...\f[]]
rg [\f[I]options\f[]] \-\-files [\f[I]path\f[] ...]
.PP
rg [\f[I]options\f[]] \-\-type\-list
.PP
@@ -43,8 +43,8 @@ Only show count of line matches for each file.
.RE
.TP
.B \-\-color \f[I]WHEN\f[]
Whether to use coloring in match.
Valid values are never, always or auto.
Whether to use color in the output.
Valid values are never, auto, always or ansi.
[default: auto]
.RS
.RE
@@ -71,22 +71,23 @@ Multiple glob flags may be used.
Globbing rules match .gitignore globs.
Precede a glob with a \[aq]!\[aq] to exclude it.
.RS
.RE
.PP
The \-\-glob flag subsumes the functionality of both the \-\-include and
\-\-exclude flags commonly found in other tools.
.PP
Values given to \-g must be quoted or your shell will expand them and
result in unexpected behavior.
.PP
Combine with the \-\-files flag to return matched filenames (i.e., to
replicate ack/ag\[aq]s \-g flag).
For example:
.IP
.nf
\f[C]
Values\ given\ to\ \-g\ must\ be\ quoted\ or\ your\ shell\ will\ expand\ them\ and\ result
in\ unexpected\ behavior.
Combine\ with\ the\ \-\-files\ flag\ to\ return\ matched\ filenames
(i.e.,\ to\ replicate\ ack/ag\[aq]s\ \-g\ flag).
For\ example:\ rg\ \-g\ \[aq]\\<glob\\>\[aq]\ \-\-files
rg\ \-g\ \[aq]*.foo\[aq]\ \-\-files
\f[]
.fi
.RE
.TP
.B \-h, \-\-help
Show this usage message.
@@ -134,14 +135,15 @@ Reduce the level of \[aq]smart\[aq] searching.
A single \-u doesn\[aq]t respect .gitignore (etc.) files.
Two \-u flags will search hidden files and directories.
Three \-u flags will search binary files.
\-uu is equivalent to grep \-r, and \-uuu is equivalent to grep \-a \-r.
\-uu is equivalent to \f[C]grep\ \-r\f[], and \-uuu is equivalent to
\f[C]grep\ \-a\ \-r\f[].
.RS
.PP
Note that the \-u flags are convenient aliases for other combinations of
flags.
\-u aliases \[aq]\-\-no\-ignore\[aq].
\-uu aliases \[aq]\-\-no\-ignore \-\-hidden\[aq].
\-uuu aliases \[aq]\-\-no\-ignore \-\-hidden \-\-text\[aq].
\-u aliases \-\-no\-ignore.
\-uu aliases \-\-no\-ignore \-\-hidden.
\-uuu aliases \-\-no\-ignore \-\-hidden \-\-text.
.RE
.TP
.B \-v, \-\-invert\-match
@@ -188,9 +190,12 @@ A special format, {type}:none, will clear all color settings for {type}.
.PP
For example, the following command will change the match color to
magenta and the background color for line numbers to yellow:
.PP
rg \-\-colors \[aq]match:fg:magenta\[aq] \-\-colors
\[aq]line:bg:yellow\[aq] foo.
.IP
.nf
\f[C]
rg\ \-\-colors\ \[aq]match:fg:magenta\[aq]\ \-\-colors\ \[aq]line:bg:yellow\[aq]\ foo.
\f[]
.fi
.RE
.TP
.B \-\-column
@@ -223,7 +228,7 @@ https://encoding.spec.whatwg.org/#concept\-encoding\-get
.RS
.RE
.TP
.B \-f, \-\-file FILE ...
.B \-f, \-\-file \f[I]FILE\f[] ...
Search for patterns from the given file, with one pattern per line.
When this flag is used or multiple times or in combination with the
\-e/\-\-regexp flag, then all patterns provided are searched.
@@ -237,8 +242,12 @@ Print each file that would be searched (but don\[aq]t search).
.RS
.PP
Combine with the \-g flag to return matched paths, for example:
.PP
rg \-g \[aq]<glob>\[aq] \-\-files
.IP
.nf
\f[C]
rg\ \-g\ \[aq]*.foo\[aq]\ \-\-files
\f[]
.fi
.RE
.TP
.B \-l, \-\-files\-with\-matches
@@ -274,7 +283,7 @@ This is the default mode at a tty.
Don\[aq]t group matches by each file.
If \-H/\-\-with\-filename is enabled, then file names will be shown for
every line matched.
This is the default more when not at a tty.
This is the default mode when not at a tty.
.RS
.RE
.TP
@@ -284,7 +293,7 @@ Search hidden directories and files.
.RS
.RE
.TP
.B \-\-ignore\-file FILE ...
.B \-\-ignore\-file \f[I]FILE\f[] ...
Specify additional ignore files for filtering file paths.
Ignore files should be in the gitignore format and are matched relative
to the current working directory.
@@ -387,7 +396,7 @@ A path separator is limited to a single byte.
.RE
.TP
.B \-p, \-\-pretty
Alias for \-\-color=always \-\-heading \-n.
Alias for \-\-color=always \-\-heading \-\-line\-number.
.RS
.RE
.TP
@@ -446,9 +455,21 @@ Show the version number of ripgrep and exit.
.B \-\-vimgrep
Show results with every match on its own line, including line numbers
and column numbers.
(With this option, a line with more than one match of the regex will be
printed more than once.)
With this option, a line with more than one match will be printed more
than once.
.RS
.PP
Recommended .vimrc configuration:
.IP
.nf
\f[C]
\ \ set\ grepprg=rg\\\ \-\-vimgrep
\ \ set\ grepformat^=%f:%l:%c:%m
\f[]
.fi
.PP
Use :grep to grep for something, then :cn and :cp to navigate through
the matches.
.RE
.SH FILE TYPE MANAGEMENT OPTIONS
.TP
@@ -465,11 +486,12 @@ Unless \-\-type\-clear is used, globs are added to any existing globs
inside of ripgrep.
Note that this must be passed to every invocation of rg.
Type settings are NOT persisted.
Example:
.RS
.IP
.nf
\f[C]
\ \ Example:\ `rg\ \-\-type\-add\ \[aq]foo:*.foo\[aq]\ \-tfoo\ PATTERN`
\ \ rg\ \-\-type\-add\ \[aq]foo:*.foo\[aq]\ \-tfoo\ PATTERN
\f[]
.fi
.PP
@@ -483,7 +505,7 @@ Markdown files, one can use:
.IP
.nf
\f[C]
\ \ `\-\-type\-add\ \[aq]src:include:cpp,py,md\[aq]`
\ \ \-\-type\-add\ \[aq]src:include:cpp,py,md\[aq]
\f[]
.fi
.PP
@@ -492,7 +514,7 @@ Additional glob rules can still be added to the src type by using the
.IP
.nf
\f[C]
\ \ `\-\-type\-add\ \[aq]src:include:cpp,py,md\[aq]\ \-\-type\-add\ \[aq]src:*.foo\[aq]`
\ \ \-\-type\-add\ \[aq]src:include:cpp,py,md\[aq]\ \-\-type\-add\ \[aq]src:*.foo\[aq]
\f[]
.fi
.PP

View File

@@ -4,11 +4,11 @@ rg - recursively search current directory for lines matching a pattern
# SYNOPSIS
rg [*options*] <*pattern*> [*<*path*> ...*]
rg [*options*] *PATTERN* [*path* ...]
rg [*options*] (-e PATTERN | -f FILE) ... [*<*path*> ...*]
rg [*options*] [-e *PATTERN* ...] [-f *FILE* ...] [*path* ...]
rg [*options*] --files [*<*path*> ...*]
rg [*options*] --files [*path* ...]
rg [*options*] --type-list
@@ -36,8 +36,8 @@ Project home page: https://github.com/BurntSushi/ripgrep
: Only show count of line matches for each file.
--color *WHEN*
: Whether to use coloring in match. Valid values are never, always or auto.
[default: auto]
: Whether to use color in the output. Valid values are never, auto, always or
ansi. [default: auto]
-e, --regexp *PATTERN* ...
: Use PATTERN to search. This option can be provided multiple times, where all
@@ -54,16 +54,16 @@ Project home page: https://github.com/BurntSushi/ripgrep
glob flags may be used. Globbing rules match .gitignore globs. Precede a
glob with a '!' to exclude it.
The --glob flag subsumes the functionality of both the --include and
--exclude flags commonly found in other tools.
The --glob flag subsumes the functionality of both the --include and
--exclude flags commonly found in other tools.
Values given to -g must be quoted or your shell will expand them and result
in unexpected behavior.
Combine with the --files flag to return matched filenames
(i.e., to replicate ack/ag's -g flag).
(i.e., to replicate ack/ag's -g flag). For example:
For example: rg -g '\<glob\>' --files
rg -g '*.foo' --files
-h, --help
: Show this usage message.
@@ -91,12 +91,12 @@ Project home page: https://github.com/BurntSushi/ripgrep
-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.
-u flags will search binary files. -uu is equivalent to `grep -r`, and -uuu
is equivalent to `grep -a -r`.
Note that the -u flags are convenient aliases for other combinations of
flags. -u aliases '--no-ignore'. -uu aliases '--no-ignore --hidden'.
-uuu aliases '--no-ignore --hidden --text'.
flags. -u aliases --no-ignore. -uu aliases --no-ignore --hidden.
-uuu aliases --no-ignore --hidden --text.
-v, --invert-match
: Invert matching.
@@ -130,7 +130,7 @@ Project home page: https://github.com/BurntSushi/ripgrep
For example, the following command will change the match color to magenta
and the background color for line numbers to yellow:
rg --colors 'match:fg:magenta' --colors 'line:bg:yellow' foo.
rg --colors 'match:fg:magenta' --colors 'line:bg:yellow' foo.
--column
: Show column numbers (1 based) in output. This only shows the column
@@ -152,7 +152,7 @@ Project home page: https://github.com/BurntSushi/ripgrep
Other supported values can be found in the list of labels here:
https://encoding.spec.whatwg.org/#concept-encoding-get
-f, --file FILE ...
-f, --file *FILE* ...
: Search for patterns from the given file, with one pattern per line. When this
flag is used or multiple times or in combination with the -e/--regexp flag,
then all patterns provided are searched. Empty pattern lines will match all
@@ -163,7 +163,7 @@ Project home page: https://github.com/BurntSushi/ripgrep
Combine with the -g flag to return matched paths, for example:
rg -g '\<glob\>' --files
rg -g '*.foo' --files
-l, --files-with-matches
: Only show path of each file with matches.
@@ -185,14 +185,14 @@ Project home page: https://github.com/BurntSushi/ripgrep
--no-heading
: Don't group matches by each file. If -H/--with-filename is enabled, then
file names will be shown for every line matched. This is the default more
file names will be shown for every line matched. This is the default mode
when not at a tty.
--hidden
: Search hidden directories and files. (Hidden directories and files are
skipped by default.)
--ignore-file FILE ...
--ignore-file *FILE* ...
: Specify additional ignore files for filtering file paths.
Ignore files should be in the gitignore format and are matched
relative to the current working directory. These ignore files
@@ -260,7 +260,7 @@ Project home page: https://github.com/BurntSushi/ripgrep
cygwin). A path separator is limited to a single byte.
-p, --pretty
: Alias for --color=always --heading -n.
: Alias for --color=always --heading --line-number.
-r, --replace *ARG*
: Replace every match with the string given when printing search results.
@@ -295,9 +295,17 @@ Project home page: https://github.com/BurntSushi/ripgrep
: Show the version number of ripgrep and exit.
--vimgrep
: Show results with every match on its own line, including line
numbers and column numbers. (With this option, a line with more
than one match of the regex will be printed more than once.)
: Show results with every match on its own line, including
line numbers and column numbers. With this option, a line with
more than one match will be printed more than once.
Recommended .vimrc configuration:
set grepprg=rg\ --vimgrep
set grepformat^=%f:%l:%c:%m
Use :grep to grep for something, then :cn and :cp to navigate through the
matches.
# FILE TYPE MANAGEMENT OPTIONS
@@ -309,9 +317,9 @@ Project home page: https://github.com/BurntSushi/ripgrep
at a time. Multiple --type-add flags can be provided. Unless --type-clear
is used, globs are added to any existing globs inside of ripgrep. Note that
this must be passed to every invocation of rg. Type settings are NOT
persisted.
persisted. Example:
Example: `rg --type-add 'foo:*.foo' -tfoo PATTERN`
rg --type-add 'foo:*.foo' -tfoo PATTERN
--type-add can also be used to include rules from other types
with the special include directive. The include directive
@@ -321,12 +329,12 @@ Project home page: https://github.com/BurntSushi/ripgrep
type called src that matches C++, Python and Markdown files, one
can use:
`--type-add 'src:include:cpp,py,md'`
--type-add 'src:include:cpp,py,md'
Additional glob rules can still be added to the src type by
using the --type-add flag again:
`--type-add 'src:include:cpp,py,md' --type-add 'src:*.foo'`
--type-add 'src:include:cpp,py,md' --type-add 'src:*.foo'
Note that type names must consist only of Unicode letters or
numbers. Punctuation characters are not allowed.

View File

@@ -1,6 +1,6 @@
[package]
name = "globset"
version = "0.1.4" #:version
version = "0.2.0" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
Cross platform single glob and glob set matching. Glob set matching is the

View File

@@ -9,7 +9,7 @@ use std::str;
use regex;
use regex::bytes::Regex;
use {Candidate, Error, new_regex};
use {Candidate, Error, ErrorKind, new_regex};
/// Describes a matching strategy for a particular pattern.
///
@@ -544,6 +544,7 @@ impl<'a> GlobBuilder<'a> {
/// Parses and builds the pattern.
pub fn build(&self) -> Result<Glob, Error> {
let mut p = Parser {
glob: &self.glob,
stack: vec![Tokens::default()],
chars: self.glob.chars().peekable(),
prev: None,
@@ -551,9 +552,15 @@ impl<'a> GlobBuilder<'a> {
};
try!(p.parse());
if p.stack.is_empty() {
Err(Error::UnopenedAlternates)
Err(Error {
glob: Some(self.glob.to_string()),
kind: ErrorKind::UnopenedAlternates,
})
} else if p.stack.len() > 1 {
Err(Error::UnclosedAlternates)
Err(Error {
glob: Some(self.glob.to_string()),
kind: ErrorKind::UnclosedAlternates,
})
} else {
let tokens = p.stack.pop().unwrap();
Ok(Glob {
@@ -698,6 +705,7 @@ fn bytes_to_escaped_literal(bs: &[u8]) -> String {
}
struct Parser<'a> {
glob: &'a str,
stack: Vec<Tokens>,
chars: iter::Peekable<str::Chars<'a>>,
prev: Option<char>,
@@ -705,6 +713,10 @@ struct Parser<'a> {
}
impl<'a> Parser<'a> {
fn error(&self, kind: ErrorKind) -> Error {
Error { glob: Some(self.glob.to_string()), kind: kind }
}
fn parse(&mut self) -> Result<(), Error> {
while let Some(c) = self.bump() {
match c {
@@ -729,7 +741,7 @@ impl<'a> Parser<'a> {
fn push_alternate(&mut self) -> Result<(), Error> {
if self.stack.len() > 1 {
return Err(Error::NestedAlternates);
return Err(self.error(ErrorKind::NestedAlternates));
}
Ok(self.stack.push(Tokens::default()))
}
@@ -743,22 +755,22 @@ impl<'a> Parser<'a> {
}
fn push_token(&mut self, tok: Token) -> Result<(), Error> {
match self.stack.last_mut() {
None => Err(Error::UnopenedAlternates),
Some(ref mut pat) => Ok(pat.push(tok)),
if let Some(ref mut pat) = self.stack.last_mut() {
return Ok(pat.push(tok));
}
Err(self.error(ErrorKind::UnopenedAlternates))
}
fn pop_token(&mut self) -> Result<Token, Error> {
match self.stack.last_mut() {
None => Err(Error::UnopenedAlternates),
Some(ref mut pat) => Ok(pat.pop().unwrap()),
if let Some(ref mut pat) = self.stack.last_mut() {
return Ok(pat.pop().unwrap());
}
Err(self.error(ErrorKind::UnopenedAlternates))
}
fn have_tokens(&self) -> Result<bool, Error> {
match self.stack.last() {
None => Err(Error::UnopenedAlternates),
None => Err(self.error(ErrorKind::UnopenedAlternates)),
Some(ref pat) => Ok(!pat.is_empty()),
}
}
@@ -785,7 +797,7 @@ impl<'a> Parser<'a> {
try!(self.push_token(Token::RecursivePrefix));
let next = self.bump();
if !next.map(is_separator).unwrap_or(true) {
return Err(Error::InvalidRecursive);
return Err(self.error(ErrorKind::InvalidRecursive));
}
return Ok(());
}
@@ -793,7 +805,7 @@ impl<'a> Parser<'a> {
if !prev.map(is_separator).unwrap_or(false) {
if self.stack.len() <= 1
|| (prev != Some(',') && prev != Some('{')) {
return Err(Error::InvalidRecursive);
return Err(self.error(ErrorKind::InvalidRecursive));
}
}
match self.chars.peek() {
@@ -808,18 +820,22 @@ impl<'a> Parser<'a> {
assert!(self.bump().map(is_separator).unwrap_or(false));
self.push_token(Token::RecursiveZeroOrMore)
}
_ => Err(Error::InvalidRecursive),
_ => Err(self.error(ErrorKind::InvalidRecursive)),
}
}
fn parse_class(&mut self) -> Result<(), Error> {
fn add_to_last_range(
glob: &str,
r: &mut (char, char),
add: char,
) -> Result<(), Error> {
r.1 = add;
if r.1 < r.0 {
Err(Error::InvalidRange(r.0, r.1))
Err(Error {
glob: Some(glob.to_string()),
kind: ErrorKind::InvalidRange(r.0, r.1),
})
} else {
Ok(())
}
@@ -837,7 +853,7 @@ impl<'a> Parser<'a> {
Some(c) => c,
// The only way to successfully break this loop is to observe
// a ']'.
None => return Err(Error::UnclosedClass),
None => return Err(self.error(ErrorKind::UnclosedClass)),
};
match c {
']' => {
@@ -854,7 +870,7 @@ impl<'a> Parser<'a> {
// invariant: in_range is only set when there is
// already at least one character seen.
let r = ranges.last_mut().unwrap();
try!(add_to_last_range(r, '-'));
try!(add_to_last_range(&self.glob, r, '-'));
in_range = false;
} else {
assert!(!ranges.is_empty());
@@ -865,7 +881,8 @@ impl<'a> Parser<'a> {
if in_range {
// invariant: in_range is only set when there is
// already at least one character seen.
try!(add_to_last_range(ranges.last_mut().unwrap(), c));
try!(add_to_last_range(
&self.glob, ranges.last_mut().unwrap(), c));
} else {
ranges.push((c, c));
}
@@ -909,7 +926,7 @@ fn ends_with(needle: &[u8], haystack: &[u8]) -> bool {
mod tests {
use std::ffi::{OsStr, OsString};
use {GlobSetBuilder, Error};
use {GlobSetBuilder, ErrorKind};
use super::{Glob, GlobBuilder, Token};
use super::Token::*;
@@ -934,7 +951,7 @@ mod tests {
#[test]
fn $name() {
let err = Glob::new($pat).unwrap_err();
assert_eq!($err, err);
assert_eq!(&$err, err.kind());
}
}
}
@@ -1057,19 +1074,19 @@ mod tests {
syntax!(cls18, "[!0-9a-z]", vec![rclassn(&[('0', '9'), ('a', 'z')])]);
syntax!(cls19, "[!a-z0-9]", vec![rclassn(&[('a', 'z'), ('0', '9')])]);
syntaxerr!(err_rseq1, "a**", Error::InvalidRecursive);
syntaxerr!(err_rseq2, "**a", Error::InvalidRecursive);
syntaxerr!(err_rseq3, "a**b", Error::InvalidRecursive);
syntaxerr!(err_rseq4, "***", Error::InvalidRecursive);
syntaxerr!(err_rseq5, "/a**", Error::InvalidRecursive);
syntaxerr!(err_rseq6, "/**a", Error::InvalidRecursive);
syntaxerr!(err_rseq7, "/a**b", Error::InvalidRecursive);
syntaxerr!(err_unclosed1, "[", Error::UnclosedClass);
syntaxerr!(err_unclosed2, "[]", Error::UnclosedClass);
syntaxerr!(err_unclosed3, "[!", Error::UnclosedClass);
syntaxerr!(err_unclosed4, "[!]", Error::UnclosedClass);
syntaxerr!(err_range1, "[z-a]", Error::InvalidRange('z', 'a'));
syntaxerr!(err_range2, "[z--]", Error::InvalidRange('z', '-'));
syntaxerr!(err_rseq1, "a**", ErrorKind::InvalidRecursive);
syntaxerr!(err_rseq2, "**a", ErrorKind::InvalidRecursive);
syntaxerr!(err_rseq3, "a**b", ErrorKind::InvalidRecursive);
syntaxerr!(err_rseq4, "***", ErrorKind::InvalidRecursive);
syntaxerr!(err_rseq5, "/a**", ErrorKind::InvalidRecursive);
syntaxerr!(err_rseq6, "/**a", ErrorKind::InvalidRecursive);
syntaxerr!(err_rseq7, "/a**b", ErrorKind::InvalidRecursive);
syntaxerr!(err_unclosed1, "[", ErrorKind::UnclosedClass);
syntaxerr!(err_unclosed2, "[]", ErrorKind::UnclosedClass);
syntaxerr!(err_unclosed3, "[!", ErrorKind::UnclosedClass);
syntaxerr!(err_unclosed4, "[!]", ErrorKind::UnclosedClass);
syntaxerr!(err_range1, "[z-a]", ErrorKind::InvalidRange('z', 'a'));
syntaxerr!(err_range2, "[z--]", ErrorKind::InvalidRange('z', '-'));
const CASEI: Options = Options {
casei: true,

View File

@@ -128,7 +128,16 @@ mod pathutil;
/// Represents an error that can occur when parsing a glob pattern.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Error {
pub struct Error {
/// The original glob provided by the caller.
glob: Option<String>,
/// The kind of error.
kind: ErrorKind,
}
/// The kind of error that can occur when parsing a glob pattern.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind {
/// Occurs when a use of `**` is invalid. Namely, `**` can only appear
/// adjacent to a path separator, or the beginning/end of a glob.
InvalidRecursive,
@@ -150,45 +159,74 @@ pub enum Error {
}
impl StdError for Error {
fn description(&self) -> &str {
self.kind.description()
}
}
impl Error {
/// Return the glob that caused this error, if one exists.
pub fn glob(&self) -> Option<&str> {
self.glob.as_ref().map(|s| &**s)
}
/// Return the kind of this error.
pub fn kind(&self) -> &ErrorKind {
&self.kind
}
}
impl ErrorKind {
fn description(&self) -> &str {
match *self {
Error::InvalidRecursive => {
ErrorKind::InvalidRecursive => {
"invalid use of **; must be one path component"
}
Error::UnclosedClass => {
ErrorKind::UnclosedClass => {
"unclosed character class; missing ']'"
}
Error::InvalidRange(_, _) => {
ErrorKind::InvalidRange(_, _) => {
"invalid character range"
}
Error::UnopenedAlternates => {
ErrorKind::UnopenedAlternates => {
"unopened alternate group; missing '{' \
(maybe escape '}' with '[}]'?)"
}
Error::UnclosedAlternates => {
ErrorKind::UnclosedAlternates => {
"unclosed alternate group; missing '}' \
(maybe escape '{' with '[{]'?)"
}
Error::NestedAlternates => {
ErrorKind::NestedAlternates => {
"nested alternate groups are not allowed"
}
Error::Regex(ref err) => err,
ErrorKind::Regex(ref err) => err,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.glob {
None => self.kind.fmt(f),
Some(ref glob) => {
write!(f, "error parsing glob '{}': {}", glob, self.kind)
}
}
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::InvalidRecursive
| Error::UnclosedClass
| Error::UnopenedAlternates
| Error::UnclosedAlternates
| Error::NestedAlternates
| Error::Regex(_) => {
ErrorKind::InvalidRecursive
| ErrorKind::UnclosedClass
| ErrorKind::UnopenedAlternates
| ErrorKind::UnclosedAlternates
| ErrorKind::NestedAlternates
| ErrorKind::Regex(_) => {
write!(f, "{}", self.description())
}
Error::InvalidRange(s, e) => {
ErrorKind::InvalidRange(s, e) => {
write!(f, "invalid range; '{}' > '{}'", s, e)
}
}
@@ -201,12 +239,22 @@ fn new_regex(pat: &str) -> Result<Regex, Error> {
.size_limit(10 * (1 << 20))
.dfa_size_limit(10 * (1 << 20))
.build()
.map_err(|err| Error::Regex(err.to_string()))
.map_err(|err| {
Error {
glob: Some(pat.to_string()),
kind: ErrorKind::Regex(err.to_string()),
}
})
}
fn new_regex_set<I, S>(pats: I) -> Result<RegexSet, Error>
where S: AsRef<str>, I: IntoIterator<Item=S> {
RegexSet::new(pats).map_err(|err| Error::Regex(err.to_string()))
RegexSet::new(pats).map_err(|err| {
Error {
glob: None,
kind: ErrorKind::Regex(err.to_string()),
}
})
}
type Fnv = hash::BuildHasherDefault<fnv::FnvHasher>;

View File

@@ -1,6 +1,6 @@
[package]
name = "ignore"
version = "0.1.9" #:version
version = "0.2.0" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
A fast library for efficiently matching ignore files such as `.gitignore`
@@ -19,7 +19,7 @@ bench = false
[dependencies]
crossbeam = "0.2"
globset = { version = "0.1.4", path = "../globset" }
globset = { version = "0.2.0", path = "../globset" }
lazy_static = "0.2"
log = "0.3"
memchr = "1"

View File

@@ -279,7 +279,12 @@ impl GitignoreBuilder {
let nignore = self.globs.iter().filter(|g| !g.is_whitelist()).count();
let nwhite = self.globs.iter().filter(|g| g.is_whitelist()).count();
let set = try!(
self.builder.build().map_err(|err| Error::Glob(err.to_string())));
self.builder.build().map_err(|err| {
Error::Glob {
glob: None,
err: err.to_string(),
}
}));
Ok(Gitignore {
set: set,
root: self.root.clone(),
@@ -420,7 +425,12 @@ impl GitignoreBuilder {
GlobBuilder::new(&glob.actual)
.literal_separator(literal_separator)
.build()
.map_err(|err| Error::Glob(err.to_string())));
.map_err(|err| {
Error::Glob {
glob: Some(glob.original.clone()),
err: err.kind().to_string(),
}
}));
self.builder.add(parsed);
self.globs.push(glob);
Ok(self)

View File

@@ -112,7 +112,17 @@ pub enum Error {
/// An error that occurs when doing I/O, such as reading an ignore file.
Io(io::Error),
/// An error that occurs when trying to parse a glob.
Glob(String),
Glob {
/// The original glob that caused this error. This glob, when
/// available, always corresponds to the glob provided by an end user.
/// e.g., It is the glob as writtein in a `.gitignore` file.
///
/// (This glob may be distinct from the glob that is actually
/// compiled, after accounting for `gitignore` semantics.)
glob: Option<String>,
/// The underlying glob error as a string.
err: String,
},
/// A type selection for a file type that is not defined.
UnrecognizedFileType(String),
/// A user specified file type definition could not be parsed.
@@ -144,7 +154,7 @@ impl Error {
Error::WithDepth { ref err, .. } => err.is_io(),
Error::Loop { .. } => false,
Error::Io(_) => true,
Error::Glob(_) => false,
Error::Glob { .. } => false,
Error::UnrecognizedFileType(_) => false,
Error::InvalidDefinition => false,
}
@@ -199,7 +209,7 @@ impl error::Error for Error {
Error::WithDepth { ref err, .. } => err.description(),
Error::Loop { .. } => "file system loop found",
Error::Io(ref err) => err.description(),
Error::Glob(ref msg) => msg,
Error::Glob { ref err, .. } => err,
Error::UnrecognizedFileType(_) => "unrecognized file type",
Error::InvalidDefinition => "invalid definition",
}
@@ -227,7 +237,10 @@ impl fmt::Display for Error {
child.display(), ancestor.display())
}
Error::Io(ref err) => err.fmt(f),
Error::Glob(ref msg) => write!(f, "{}", msg),
Error::Glob { glob: None, ref err } => write!(f, "{}", err),
Error::Glob { glob: Some(ref glob), ref err } => {
write!(f, "error parsing glob '{}': {}", glob, err)
}
Error::UnrecognizedFileType(ref ty) => {
write!(f, "unrecognized file type: {}", ty)
}

View File

@@ -111,11 +111,12 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
("config", &["*.config"]),
("cpp", &[
"*.C", "*.cc", "*.cpp", "*.cxx",
"*.h", "*.H", "*.hh", "*.hpp",
"*.h", "*.H", "*.hh", "*.hpp", "*.inl",
]),
("crystal", &["Projectfile", "*.cr"]),
("cs", &["*.cs"]),
("csharp", &["*.cs"]),
("cshtml", &["*.cshtml"]),
("css", &["*.css", "*.scss"]),
("cython", &["*.pyx"]),
("dart", &["*.dart"]),
@@ -142,6 +143,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
]),
("json", &["*.json"]),
("jsonl", &["*.jsonl"]),
("julia", &["*.jl"]),
("kotlin", &["*.kt", "*.kts"]),
("less", &["*.less"]),
("lisp", &["*.el", "*.jl", "*.lisp", "*.lsp", "*.sc", "*.scm"]),
@@ -154,7 +156,9 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
("matlab", &["*.m"]),
("mk", &["mkfile"]),
("ml", &["*.ml"]),
("msbuild", &["*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets"]),
("nim", &["*.nim"]),
("nix", &["*.nix"]),
("objc", &["*.h", "*.m"]),
("objcpp", &["*.h", "*.mm"]),
("ocaml", &["*.ml", "*.mli", "*.mll", "*.mly"]),
@@ -165,6 +169,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
("pod", &["*.pod"]),
("ps", &["*.cdxml", "*.ps1", "*.ps1xml", "*.psd1", "*.psm1"]),
("py", &["*.py"]),
("qmake", &["*.pro", "*.pri"]),
("readme", &["README*", "*README"]),
("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
("rdoc", &["*.rdoc"]),
@@ -197,6 +202,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
("xml", &["*.xml"]),
("yacc", &["*.y"]),
("yaml", &["*.yaml", "*.yml"]),
("yocto", &["*.bb", "*.bbappend", "*.bbclass"]),
("zsh", &["zshenv", ".zshenv", "zprofile", ".zprofile", "zshrc", ".zshrc", "zlogin", ".zlogin", "zlogout", ".zlogout", "*.zsh"]),
];
@@ -447,13 +453,18 @@ impl TypesBuilder {
GlobBuilder::new(glob)
.literal_separator(true)
.build()
.map_err(|err| Error::Glob(err.to_string()))));
.map_err(|err| {
Error::Glob {
glob: Some(glob.to_string()),
err: err.kind().to_string(),
}
})));
glob_to_selection.push((isel, iglob));
}
selections.push(selection.clone().map(move |_| def));
}
let set = try!(build_set.build().map_err(|err| {
Error::Glob(err.to_string())
Error::Glob { glob: None, err: err.to_string() }
}));
Ok(Types {
defs: defs,

View File

@@ -1,9 +1,9 @@
class RipgrepBin < Formula
version '0.5.0'
version '0.5.2'
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 "5bfa8872c4f2a5d010ddec1c213d518056e62d4dd3b3f23a0ef099b85343dbdd"
sha256 "a0326a84af8517ad707d8c7cccba6e112de27822c391cc0937e4727fbb6c48f4"
conflicts_with "ripgrep"

15
snapcraft.yaml Normal file
View File

@@ -0,0 +1,15 @@
name: ripgrep # you probably want to 'snapcraft register <name>'
version: '0.5.1' # just for humans, typically '1.2+git' or '1.3.2'
summary: Fast file searcher # 79 char long summary
description: |
ripgrep combines the usability of The Silver Searcher with the raw speed of grep.
grade: stable # must be 'stable' to release into candidate/stable channels
confinement: classic # use 'strict' once you have the right plugs and slots
parts:
ripgrep:
plugin: rust
source: .
apps:
rg:
command: env PATH=$SNAP/bin:$PATH rg
aliases: [rg]

View File

@@ -14,10 +14,10 @@ Project home page: https://github.com/BurntSushi/ripgrep
Use -h for short descriptions and --help for more details.";
const USAGE: &'static str = "
rg [OPTIONS] <pattern> [<path> ...]
rg [OPTIONS] [-e PATTERN | -f FILE ]... [<path> ...]
rg [OPTIONS] --files [<path> ...]
rg [OPTIONS] --type-list";
rg [options] PATTERN [path ...]
rg [options] [-e PATTERN ...] [-f FILE ...] [path ...]
rg [options] --files [path ...]
rg [options] --type-list";
const TEMPLATE: &'static str = "\
{bin} {version}
@@ -41,7 +41,9 @@ OPTIONS:
/// in a `build.rs` script to build shell completion files.
pub fn app() -> App<'static, 'static> {
let arg = |name| {
Arg::with_name(name).help(USAGES[name].short).long_help(USAGES[name].long)
Arg::with_name(name)
.help(USAGES[name].short)
.long_help(USAGES[name].long)
};
let flag = |name| arg(name).long(name);
@@ -53,9 +55,9 @@ pub fn app() -> App<'static, 'static> {
.setting(AppSettings::UnifiedHelpMessage)
.usage(USAGE)
.template(TEMPLATE)
.help_message("Prints help information. Use --help for more details.")
.help_message("Prints help information. Use --help for more details.")
// First, set up primary positional/flag arguments.
.arg(arg("pattern")
.arg(arg("PATTERN")
.required_unless_one(&[
"file", "files", "help-short", "help", "regexp", "type-list",
"ripgrep-version",
@@ -64,13 +66,13 @@ pub fn app() -> App<'static, 'static> {
.arg(flag("regexp").short("e")
.takes_value(true).multiple(true).number_of_values(1)
.set(ArgSettings::AllowLeadingHyphen)
.value_name("pattern"))
.value_name("PATTERN"))
.arg(flag("files")
// This should also conflict with `pattern`, but the first file
// path will actually be in `pattern`.
// This should also conflict with `PATTERN`, but the first file
// path will actually be in `PATTERN`.
.conflicts_with_all(&["file", "regexp", "type-list"]))
.arg(flag("type-list")
.conflicts_with_all(&["file", "files", "pattern", "regexp"]))
.conflicts_with_all(&["file", "files", "PATTERN", "regexp"]))
// Second, set up common flags.
.arg(flag("text").short("a"))
.arg(flag("count").short("c"))
@@ -78,7 +80,8 @@ pub fn app() -> App<'static, 'static> {
.value_name("WHEN")
.takes_value(true)
.hide_possible_values(true)
.possible_values(&["never", "auto", "always", "ansi"]))
.possible_values(&["never", "auto", "always", "ansi"])
.default_value_if("vimgrep", None, "never"))
.arg(flag("colors").value_name("SPEC")
.takes_value(true).multiple(true).number_of_values(1))
.arg(flag("encoding").short("E").value_name("ENCODING")
@@ -89,7 +92,7 @@ pub fn app() -> App<'static, 'static> {
.value_name("GLOB"))
.arg(flag("ignore-case").short("i"))
.arg(flag("line-number").short("n"))
.arg(flag("no-line-number").short("N"))
.arg(flag("no-line-number").short("N").overrides_with("line-number"))
.arg(flag("quiet").short("q"))
.arg(flag("type").short("t")
.takes_value(true).multiple(true).number_of_values(1)
@@ -114,6 +117,8 @@ pub fn app() -> App<'static, 'static> {
.arg(flag("column"))
.arg(flag("context-separator")
.value_name("SEPARATOR").takes_value(true))
.arg(flag("dfa-size-limit")
.value_name("NUM+SUFFIX?").takes_value(true))
.arg(flag("debug"))
.arg(flag("file").short("f")
.value_name("FILE").takes_value(true)
@@ -121,8 +126,8 @@ pub fn app() -> App<'static, 'static> {
.arg(flag("files-with-matches").short("l"))
.arg(flag("files-without-match"))
.arg(flag("with-filename").short("H"))
.arg(flag("no-filename"))
.arg(flag("heading").overrides_with("no-heading"))
.arg(flag("no-filename").overrides_with("with-filename"))
.arg(flag("heading"))
.arg(flag("no-heading").overrides_with("heading"))
.arg(flag("hidden"))
.arg(flag("ignore-file")
@@ -148,13 +153,15 @@ pub fn app() -> App<'static, 'static> {
.arg(flag("path-separator").value_name("SEPARATOR").takes_value(true))
.arg(flag("pretty").short("p"))
.arg(flag("replace").short("r").value_name("ARG").takes_value(true))
.arg(flag("regex-size-limit")
.value_name("NUM+SUFFIX?").takes_value(true))
.arg(flag("case-sensitive").short("s"))
.arg(flag("smart-case").short("S"))
.arg(flag("sort-files"))
.arg(flag("threads")
.short("j").value_name("ARG").takes_value(true)
.validator(validate_number))
.arg(flag("vimgrep"))
.arg(flag("vimgrep").overrides_with("count"))
.arg(flag("max-columns").short("M")
.value_name("NUM").takes_value(true)
.validator(validate_number))
@@ -195,14 +202,15 @@ lazy_static! {
doc!(h, "ripgrep-version",
"Prints version information.");
doc!(h, "pattern",
doc!(h, "PATTERN",
"A regular expression used for searching.",
"A regular expression used for searching. Multiple patterns \
may be given. To match a pattern beginning with a -, use [-].");
"A regular expression used for searching. To match a pattern \
beginning with a dash, use the -e/--regexp option.");
doc!(h, "regexp",
"A regular expression used for searching.",
"A regular expression used for searching. Multiple patterns \
may be given. To match a pattern beginning with a -, use [-].");
"Use pattern to search.",
"Use pattern to search. This option can be provided multiple \
times, where all patterns given are searched. This is also \
useful when searching for patterns that start with a dash.");
doc!(h, "path",
"A file or directory to search.",
"A file or directory to search. Directories are searched \
@@ -222,11 +230,11 @@ lazy_static! {
"Only show count of matches for each file.");
doc!(h, "color",
"When to use color. [default: auto]",
"When to use color in the output. The possible values are \
never, auto, always or ansi. The default is auto. When always \
is used, coloring is attempted based on your environment. When \
ansi used, coloring is forcefully done using ANSI escape color \
codes.");
"When to use color in the output. The possible values are never, \
auto, always or ansi. The default is auto. When always is used, \
coloring is attempted based on your environment. When ansi is \
used, coloring is forcefully done using ANSI escape color \
codes.");
doc!(h, "colors",
"Configure color settings and styles.",
"This flag specifies color settings for use in the output. \
@@ -326,6 +334,13 @@ lazy_static! {
doc!(h, "debug",
"Show debug messages.",
"Show debug messages. Please use this when filing a bug report.");
doc!(h, "dfa-size-limit",
"The upper size limit of the generated dfa.",
"The upper size limit of the generated dfa. The default limit is \
10M. This should only be changed on very large regex inputs \
where the (slower) fallback regex engine may otherwise be used. \
\n\nThe argument accepts the same size suffixes as allowed in \
the 'max-filesize' argument.");
doc!(h, "file",
"Search for patterns from the given file.",
"Search for patterns from the given file, with one pattern per \
@@ -434,7 +449,7 @@ lazy_static! {
default when the environment demands it (e.g., cygwin). A path \
separator is limited to a single byte.");
doc!(h, "pretty",
"Alias for --color always --heading -n.");
"Alias for --color always --heading --line-number.");
doc!(h, "replace",
"Replace matches with string given.",
"Replace every match with the string given when printing \
@@ -444,6 +459,11 @@ lazy_static! {
Note that the replacement by default replaces each match, and \
NOT the entire line. To replace the entire line, you should \
match the entire line.");
doc!(h, "regex-size-limit",
"The upper size limit of the compiled regex.",
"The upper size limit of the compiled regex. The default limit \
is 10M. \n\nThe argument accepts the same size suffixes as \
allowed in the 'max-filesize' argument.");
doc!(h, "case-sensitive",
"Search case sensitively.",
"Search case sensitively. This overrides -i/--ignore-case and \

View File

@@ -35,7 +35,6 @@ pub struct Args {
paths: Vec<PathBuf>,
after_context: usize,
before_context: usize,
color: bool,
color_choice: termcolor::ColorChoice,
colors: ColorSpecs,
column: bool,
@@ -317,7 +316,6 @@ impl<'a> ArgMatches<'a> {
paths: paths,
after_context: after_context,
before_context: before_context,
color: self.color(),
color_choice: self.color_choice(),
colors: try!(self.color_specs()),
column: self.column(),
@@ -377,7 +375,7 @@ impl<'a> ArgMatches<'a> {
if self.is_present("file")
|| self.is_present("files")
|| self.is_present("regexp") {
if let Some(path) = self.value_of_os("pattern") {
if let Some(path) = self.value_of_os("PATTERN") {
paths.insert(0, Path::new(path).to_path_buf());
}
}
@@ -440,7 +438,7 @@ impl<'a> ArgMatches<'a> {
match self.values_of_os("regexp") {
None => {
if self.values_of_os("file").is_none() {
if let Some(os_pat) = self.value_of_os("pattern") {
if let Some(os_pat) = self.value_of_os("PATTERN") {
pats.push(try!(self.os_str_pattern(os_pat)));
}
}
@@ -507,7 +505,7 @@ impl<'a> ArgMatches<'a> {
/// flag is set. Otherwise, the pattern is returned unchanged.
fn word_pattern(&self, pat: String) -> String {
if self.is_present("word-regexp") {
format!(r"\b{}\b", pat)
format!(r"\b(?:{})\b", pat)
} else {
pat
}
@@ -532,6 +530,7 @@ impl<'a> ArgMatches<'a> {
false
} else {
self.is_present("with-filename")
|| self.is_present("vimgrep")
|| paths.len() > 1
|| paths.get(0).map_or(false, |p| p.is_dir())
}
@@ -590,9 +589,9 @@ impl<'a> ArgMatches<'a> {
false
} else {
let only_stdin = paths == &[Path::new("-")];
self.is_present("line-number")
(atty::is(atty::Stream::Stdout) && !only_stdin)
|| self.is_present("line-number")
|| self.is_present("column")
|| (atty::is(atty::Stream::Stdout) && !only_stdin)
|| self.is_present("pretty")
|| self.is_present("vimgrep")
}
@@ -606,11 +605,11 @@ impl<'a> ArgMatches<'a> {
/// Returns true if and only if matches should be grouped with file name
/// headings.
fn heading(&self) -> bool {
if self.is_present("no-heading") {
if self.is_present("no-heading") || self.is_present("vimgrep") {
false
} else {
self.is_present("heading")
|| atty::is(atty::Stream::Stdout)
atty::is(atty::Stream::Stdout)
|| self.is_present("heading")
|| self.is_present("pretty")
}
}
@@ -664,23 +663,6 @@ impl<'a> ArgMatches<'a> {
})
}
/// Returns true if and only if ripgrep should color its output.
fn color(&self) -> bool {
let preference = match self.0.value_of_lossy("color") {
None => "auto".to_string(),
Some(v) => v.into_owned(),
};
if preference == "always" {
true
} else if self.is_present("vimgrep") {
false
} else if preference == "auto" {
atty::is(atty::Stream::Stdout) || self.is_present("pretty")
} else {
false
}
}
/// Returns the user's color choice based on command line parameters and
/// environment.
fn color_choice(&self) -> termcolor::ColorChoice {
@@ -692,8 +674,6 @@ impl<'a> ArgMatches<'a> {
termcolor::ColorChoice::Always
} else if preference == "ansi" {
termcolor::ColorChoice::AlwaysAnsi
} else if self.is_present("vimgrep") {
termcolor::ColorChoice::Never
} else if preference == "auto" {
if atty::is(atty::Stream::Stdout) || self.is_present("pretty") {
termcolor::ColorChoice::Auto
@@ -737,7 +717,7 @@ impl<'a> ArgMatches<'a> {
if label == "auto" {
return Ok(None);
}
match Encoding::for_label(label.as_bytes()) {
match Encoding::for_label_no_replacement(label.as_bytes()) {
Some(enc) => Ok(Some(enc)),
None => Err(From::from(
format!("unsupported encoding: {}", label))),
@@ -771,12 +751,18 @@ impl<'a> ArgMatches<'a> {
let casei =
self.is_present("ignore-case")
&& !self.is_present("case-sensitive");
GrepBuilder::new(&try!(self.pattern()))
let mut gb = GrepBuilder::new(&try!(self.pattern()))
.case_smart(smart)
.case_insensitive(casei)
.line_terminator(b'\n')
.build()
.map_err(From::from)
.line_terminator(b'\n');
if let Some(limit) = try!(self.dfa_size_limit()) {
gb = gb.dfa_size_limit(limit);
}
if let Some(limit) = try!(self.regex_size_limit()) {
gb = gb.size_limit(limit);
}
gb.build().map_err(From::from)
}
/// Builds the set of glob overrides from the command line flags.
@@ -807,31 +793,64 @@ impl<'a> ArgMatches<'a> {
btypes.build().map_err(From::from)
}
/// Parses the max-filesize argument option into a byte count.
fn max_filesize(&self) -> Result<Option<u64>> {
use regex::Regex;
let max_filesize = match self.value_of_lossy("max-filesize") {
/// Parses an argument of the form `[0-9]+(KMG)?`.
///
/// This always returns the result as a type `u64`. This must be converted
/// to the appropriate type by the caller.
fn parse_human_readable_size_arg(
&self,
arg_name: &str,
) -> Result<Option<u64>> {
let arg_value = match self.value_of_lossy(arg_name) {
Some(x) => x,
None => return Ok(None)
};
let re = regex::Regex::new("^([0-9]+)([KMG])?$").unwrap();
let caps = try!(
re.captures(&arg_value).ok_or_else(|| {
format!("invalid format for {}", arg_name)
}));
let re = Regex::new("^([0-9]+)([KMG])?$").unwrap();
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>());
let suffix = caps.get(2).map(|x| x.as_str());
let v_10 = value.checked_mul(1024);
let v_20 = v_10.and_then(|x| x.checked_mul(1024));
let v_30 = v_20.and_then(|x| x.checked_mul(1024));
let try_suffix = |x: Option<u64>| {
if x.is_some() {
Ok(x)
} else {
Err(From::from(format!("number too large for {}", arg_name)))
}
};
match suffix {
None => Ok(Some(value)),
Some("K") => Ok(Some(value * 1024)),
Some("M") => Ok(Some(value * 1024 * 1024)),
Some("G") => Ok(Some(value * 1024 * 1024 * 1024)),
_ => Err(From::from("invalid suffix for max-filesize argument"))
Some("K") => try_suffix(v_10),
Some("M") => try_suffix(v_20),
Some("G") => try_suffix(v_30),
_ => Err(From::from(format!("invalid suffix for {}", arg_name)))
}
}
/// Parse the dfa-size-limit argument option into a byte count.
fn dfa_size_limit(&self) -> Result<Option<usize>> {
let r = try!(self.parse_human_readable_size_arg("dfa-size-limit"));
human_readable_to_usize("dfa-size-limit", r)
}
/// Parse the regex-size-limit argument option into a byte count.
fn regex_size_limit(&self) -> Result<Option<usize>> {
let r = try!(self.parse_human_readable_size_arg("regex-size-limit"));
human_readable_to_usize("regex-size-limit", r)
}
/// Parses the max-filesize argument option into a byte count.
fn max_filesize(&self) -> Result<Option<u64>> {
self.parse_human_readable_size_arg("max-filesize")
}
/// Returns true if ignore files should be ignored.
fn no_ignore(&self) -> bool {
self.is_present("no-ignore")
@@ -926,6 +945,27 @@ impl QuietMatched {
}
}
/// Convert the result of a `parse_human_readable_size_arg` call into
/// a `usize`, failing if the type does not fit.
fn human_readable_to_usize(
arg_name: &str,
value: Option<u64>,
) -> Result<Option<usize>> {
use std::usize;
match value {
None => Ok(None),
Some(v) => {
if v <= usize::MAX as u64 {
Ok(Some(v as usize))
} else {
let msg = format!("number too large for {}", arg_name);
Err(From::from(msg))
}
}
}
}
/// Returns true if and only if stdin is deemed searchable.
#[cfg(unix)]
fn stdin_is_readable() -> bool {

View File

@@ -192,7 +192,9 @@ fn run_files_parallel(args: Arc<Args>) -> Result<u64> {
let mut printer = print_args.printer(stdout.lock());
let mut file_count = 0;
for dent in rx.iter() {
printer.path(dent.path());
if !print_args.quiet() {
printer.path(dent.path());
}
file_count += 1;
}
file_count
@@ -227,7 +229,9 @@ fn run_files_one_thread(args: Arc<Args>) -> Result<u64> {
None => continue,
Some(dent) => dent,
};
printer.path(dent.path());
if !args.quiet() {
printer.path(dent.path());
}
file_count += 1;
}
Ok(file_count)

View File

@@ -3,7 +3,7 @@ use std::fmt;
use std::path::Path;
use std::str::FromStr;
use regex::bytes::{Regex, Replacer, Captures};
use regex::bytes::{Captures, Regex, Replacer};
use termcolor::{Color, ColorSpec, ParseColorError, WriteColor};
use pathutil::strip_prefix;
@@ -242,25 +242,17 @@ impl<W: WriteColor> Printer<W> {
line_number: Option<u64>,
) {
if !self.line_per_match && !self.only_matching {
let column =
if self.column {
Some(re.find(&buf[start..end])
.map(|m| m.start()).unwrap_or(0) as u64)
} else {
None
};
let mat = re
.find(&buf[start..end])
.map(|m| (m.start(), m.end()))
.unwrap_or((0, 0));
return self.write_match(
re, path, buf, start, end, line_number, column);
re, path, buf, start, end, line_number, mat.0, mat.1);
}
for m in re.find_iter(&buf[start..end]) {
let column =
if self.column {
Some(m.start() as u64)
} else {
None
};
self.write_match(
re, path.as_ref(), buf, start, end, line_number, column);
re, path.as_ref(), buf, start, end,
line_number, m.start(), m.end());
}
}
@@ -272,7 +264,8 @@ impl<W: WriteColor> Printer<W> {
start: usize,
end: usize,
line_number: Option<u64>,
column: Option<u64>,
match_start: usize,
match_end: usize,
) {
if self.heading && self.with_filename && !self.has_printed {
self.write_file_sep();
@@ -285,8 +278,8 @@ impl<W: WriteColor> Printer<W> {
if let Some(line_number) = line_number {
self.line_number(line_number, b':');
}
if let Some(c) = column {
self.column_number(c + 1, b':');
if self.column {
self.column_number(match_start as u64 + 1, b':');
}
if self.replace.is_some() {
let mut count = 0;
@@ -307,18 +300,21 @@ impl<W: WriteColor> Printer<W> {
self.write_eol();
}
} else {
let line_buf = if self.only_matching {
let m = re.find(&buf[start..end]).unwrap();
&buf[start + m.start()..start + m.end()]
if self.only_matching {
let buf = &buf[start + match_start..start + match_end];
self.write_matched_line(re, buf, true);
} else {
&buf[start..end]
};
self.write_matched_line(re, line_buf);
// write_matched_line guarantees to write a newline.
self.write_matched_line(re, &buf[start..end], false);
}
}
}
fn write_matched_line(&mut self, re: &Regex, buf: &[u8]) {
fn write_matched_line(
&mut self,
re: &Regex,
buf: &[u8],
only_match: bool,
) {
if self.max_columns.map_or(false, |m| buf.len() > m) {
let count = re.find_iter(buf).count();
let msg = format!("[Omitted long line with {} matches]", count);
@@ -328,6 +324,8 @@ impl<W: WriteColor> Printer<W> {
}
if !self.wtr.supports_color() || self.colors.matched().is_none() {
self.write(buf);
} else if only_match {
self.write_colored(buf, |colors| colors.matched());
} else {
let mut last_written = 0;
for m in re.find_iter(buf) {

View File

@@ -455,7 +455,6 @@ sherlock!(max_filesize_parse_no_suffix, "Sherlock", ".",
let expected = "\
foo
";
assert_eq!(lines, expected);
});
@@ -470,7 +469,6 @@ sherlock!(max_filesize_parse_k_suffix, "Sherlock", ".",
let expected = "\
foo
";
assert_eq!(lines, expected);
});
@@ -485,10 +483,19 @@ sherlock!(max_filesize_parse_m_suffix, "Sherlock", ".",
let expected = "\
foo
";
assert_eq!(lines, expected);
});
sherlock!(max_filesize_suffix_overflow, "Sherlock", ".",
|wd: WorkDir, mut cmd: Command| {
wd.remove("sherlock");
wd.create_size("foo", 1000000);
// 2^35 * 2^30 would otherwise overflow
cmd.arg("--max-filesize").arg("34359738368G").arg("--files");
wd.assert_err(&mut cmd);
});
sherlock!(ignore_hidden, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
wd.remove("sherlock");
wd.create(".sherlock", hay::SHERLOCK);
@@ -1072,7 +1079,8 @@ clean!(regression_428_color_context_path, "foo", ".", |wd: WorkDir, mut cmd: Com
});
// See: https://github.com/BurntSushi/ripgrep/issues/428
clean!(regression_428_unrecognized_style, "Sherlok", ".", |wd: WorkDir, mut cmd: Command| {
clean!(regression_428_unrecognized_style, "Sherlok", ".",
|wd: WorkDir, mut cmd: Command| {
cmd.arg("--colors=match:style:");
wd.assert_err(&mut cmd);
@@ -1084,6 +1092,15 @@ Unrecognized style attribute ''. Choose from: nobold, bold, nointense, intense.
assert_eq!(err, expected);
});
// See: https://github.com/BurntSushi/ripgrep/issues/493
clean!(regression_493, " 're ", "input.txt", |wd: WorkDir, mut cmd: Command| {
wd.create("input.txt", "peshwaship 're seminomata");
cmd.arg("-o").arg("-w");
let lines: String = wd.stdout(&mut cmd);
assert_eq!(lines, " 're \n");
});
// See: https://github.com/BurntSushi/ripgrep/issues/1
clean!(feature_1_sjis, "Шерлок Холмс", ".", |wd: WorkDir, mut cmd: Command| {
let sherlock =
@@ -1130,6 +1147,21 @@ clean!(feature_1_eucjp, "Шерлок Холмс", ".",
assert_eq!(lines, "foo:Шерлок Холмс\n");
});
// See: https://github.com/BurntSushi/ripgrep/issues/1
sherlock!(feature_1_unknown_encoding, "Sherlock", ".",
|wd: WorkDir, mut cmd: Command| {
cmd.arg("-Efoobar");
wd.assert_non_empty_stderr(&mut cmd);
});
// See: https://github.com/BurntSushi/ripgrep/issues/1
// Specific: https://github.com/BurntSushi/ripgrep/pull/398/files#r111109265
sherlock!(feature_1_replacement_encoding, "Sherlock", ".",
|wd: WorkDir, mut cmd: Command| {
cmd.arg("-Ecsiso2022kr");
wd.assert_non_empty_stderr(&mut cmd);
});
// See: https://github.com/BurntSushi/ripgrep/issues/7
sherlock!(feature_7, "-fpat", "sherlock", |wd: WorkDir, mut cmd: Command| {
wd.create("pat", "Sherlock\nHolmes");
@@ -1443,6 +1475,37 @@ clean!(feature_275_pathsep, "test", ".", |wd: WorkDir, mut cmd: Command| {
assert_eq!(lines, "fooZbar:test\n");
});
// See: https://github.com/BurntSushi/ripgrep/issues/362
sherlock!(feature_362_dfa_size_limit, r"For\s",
|wd: WorkDir, mut cmd: Command| {
// This should fall back to the nfa engine but should still produce the
// expected result.
cmd.arg("--dfa-size-limit").arg("10");
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!(feature_362_exceeds_regex_size_limit, r"[0-9]\w+",
|wd: WorkDir, mut cmd: Command| {
cmd.arg("--regex-size-limit").arg("10K");
wd.assert_err(&mut cmd);
});
#[cfg(target_pointer_width = "32")]
sherlock!(feature_362_u64_to_narrow_usize_suffix_overflow, "Sherlock", ".",
|wd: WorkDir, mut cmd: Command| {
wd.remove("sherlock");
wd.create_size("foo", 1000000);
// 2^35 * 2^20 is ok for u64, but not for usize
cmd.arg("--dfa-size-limit").arg("34359738368M").arg("--files");
wd.assert_err(&mut cmd);
});
// See: https://github.com/BurntSushi/ripgrep/issues/419
sherlock!(feature_419_zero_as_shortcut_for_null, "Sherlock", ".",
|wd: WorkDir, mut cmd: Command| {
@@ -1554,6 +1617,97 @@ fn regression_391() {
assert_eq!(lines, "bar.py\n");
}
// See: https://github.com/BurntSushi/ripgrep/issues/451
#[test]
fn regression_451_only_matching_as_in_issue() {
let wd = WorkDir::new("regression_451_only_matching");
let path = "digits.txt";
wd.create(path, "1 2 3\n");
let mut cmd = wd.command();
cmd.arg("[0-9]+").arg(path).arg("--only-matching");
let lines: String = wd.stdout(&mut cmd);
let expected = "\
1
2
3
";
assert_eq!(lines, expected);
}
// See: https://github.com/BurntSushi/ripgrep/issues/451
#[test]
fn regression_451_only_matching() {
let wd = WorkDir::new("regression_451_only_matching");
let path = "digits.txt";
wd.create(path, "1 2 3\n123\n");
let mut cmd = wd.command();
cmd.arg("[0-9]").arg(path)
.arg("--only-matching")
.arg("--column");
let lines: String = wd.stdout(&mut cmd);
let expected = "\
1:1:1
1:3:2
1:5:3
2:1:1
2:2:2
2:3:3
";
assert_eq!(lines, expected);
}
// See: https://github.com/BurntSushi/ripgrep/issues/483
#[test]
fn regression_483_matching_no_stdout() {
let wd = WorkDir::new("regression_483_matching_no_stdout");
wd.create("file.py", "");
let mut cmd = wd.command();
cmd.arg("--quiet")
.arg("--files")
.arg("--glob").arg("*.py");
let lines: String = wd.stdout(&mut cmd);
assert!(lines.is_empty());
}
// See: https://github.com/BurntSushi/ripgrep/issues/483
#[test]
fn regression_483_non_matching_exit_code() {
let wd = WorkDir::new("regression_483_non_matching_exit_code");
wd.create("file.rs", "");
let mut cmd = wd.command();
cmd.arg("--quiet")
.arg("--files")
.arg("--glob").arg("*.py");
wd.assert_err(&mut cmd);
}
// See: https://github.com/BurntSushi/ripgrep/issues/506
#[test]
fn regression_506_word_boundaries_not_parenthesized() {
let wd = WorkDir::new("regression_506_word_boundaries_not_parenthesized");
let path = "wb.txt";
wd.create(path, "min minimum amin\n\
max maximum amax");
let mut cmd = wd.command();
cmd.arg("-w").arg("min|max").arg(path).arg("--only-matching");
let lines: String = wd.stdout(&mut cmd);
let expected = "min\nmax\n";
assert_eq!(lines, expected);
}
#[test]
fn type_list() {
let wd = WorkDir::new("type_list");

View File

@@ -256,6 +256,23 @@ impl WorkDir {
String::from_utf8_lossy(&o.stderr));
}
}
/// Runs the given command and asserts that something was printed to
/// stderr.
pub fn assert_non_empty_stderr(&self, cmd: &mut process::Command) {
let o = cmd.output().unwrap();
if o.status.success() || o.stderr.is_empty() {
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>(

View File

@@ -1,6 +1,6 @@
[package]
name = "wincolor"
version = "0.1.3" #:version
version = "0.1.4" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
A simple Windows specific API for controlling text color in a Windows console.

View File

@@ -2,7 +2,7 @@ use std::io;
use std::mem;
use kernel32;
use winapi::{DWORD, HANDLE, WORD};
use winapi::{DWORD, WORD};
use winapi::winbase::{STD_ERROR_HANDLE, STD_OUTPUT_HANDLE};
use winapi::wincon::{
FOREGROUND_BLUE as FG_BLUE,
@@ -30,33 +30,25 @@ const FG_WHITE: DWORD = FG_BLUE | FG_GREEN | FG_RED;
/// stdout before setting new text attributes.
#[derive(Debug)]
pub struct Console {
handle: HANDLE,
handle_id: DWORD,
start_attr: TextAttributes,
cur_attr: TextAttributes,
}
unsafe impl Send for Console {}
impl Drop for Console {
fn drop(&mut self) {
unsafe { kernel32::CloseHandle(self.handle); }
}
}
impl Console {
/// Get a console for a standard I/O stream.
fn create_for_stream(handle_id: DWORD) -> io::Result<Console> {
let mut info = unsafe { mem::zeroed() };
let (handle, res) = unsafe {
let res = unsafe {
let handle = kernel32::GetStdHandle(handle_id);
(handle, kernel32::GetConsoleScreenBufferInfo(handle, &mut info))
kernel32::GetConsoleScreenBufferInfo(handle, &mut info)
};
if res == 0 {
return Err(io::Error::last_os_error());
}
let attr = TextAttributes::from_word(info.wAttributes);
Ok(Console {
handle: handle,
handle_id: handle_id,
start_attr: attr,
cur_attr: attr,
})
@@ -80,7 +72,8 @@ impl Console {
fn set(&mut self) -> io::Result<()> {
let attr = self.cur_attr.to_word();
let res = unsafe {
kernel32::SetConsoleTextAttribute(self.handle, attr)
let handle = kernel32::GetStdHandle(self.handle_id);
kernel32::SetConsoleTextAttribute(handle, attr)
};
if res == 0 {
return Err(io::Error::last_os_error());