Compare commits

...

16 Commits

Author SHA1 Message Date
Andrew Gallant
487713aa34 bump ignore 2017-04-09 09:45:00 -04:00
Andrew Gallant
e300541701 changelog 0.5.1 2017-04-09 09:43:16 -04:00
Andrew Gallant
e9df420d2f Add ability to colorize column numbers.
Fixes #377
2017-04-09 09:08:49 -04:00
Andrew Gallant
201b4fc757 update man page 2017-04-09 08:49:19 -04:00
Roman Proskuryakov
90a11dec5e Add -o/--only-matching flag.
Currently, the `--only-matching` flag conflicts with the `--replace`
flag. In the future, this restriction may be relaxed.

Fixes #34
2017-04-09 08:47:35 -04:00
Douman
9456d95e8f Add short note on Windows Tips 2017-04-09 08:32:23 -04:00
Kevin K
0c298f60a6 updates clap and removes home rolled -h/--help distinction
This commit updates clap to v2.23.0

The update contained a bug fix in clap that results in broken code in
ripgrep. ripgrep was relying on the bug, but this commit fixes that
issue. The bug centered around not being able to override the
auto-generated help message by supplying a flag with a long of `help`.

Normally, supplying a flag with a long of `help` means whenever the user
passes `--help`, the consuming code (e.g. ripgrep) is responsible for
displaying the help message. However, due to the bug in clap this wasn't
necessary for ripgrep to do unless the user passed `-h`. With the bug
fixed, it meant the user passing `--help` and clap expected ripgrep to
display the help, yet ripgrep expected clap to display the help. This
has been fixed in this commit of ripgrep.

All well now!

v2.23.0 also brings the abilty to use `Arg::help` or `Arg::long_help`
allowing one to distinguish between `-h` and `--help`. This commit
leaves all doc strings in the `lazy_static!` hashmap however only for
aesthetic reasons.

This means all home rolled handling of `-h`/`--help` has been removed
from ripgrep, yet functionality *and* appearances are 100% the same.
2017-04-05 11:38:58 -04:00
Kosta Welke
79271fcb33 fix typo in comment 2017-04-05 07:06:58 -04:00
Andrew Gallant
fc975af8e9 Enforce 79 column limit. Grr. 2017-03-31 15:59:04 -04:00
Roman Proskuryakov
1425d6735e Bamp clap to 2.22.2
Fixes #426 , #418
2017-03-31 15:56:10 -04:00
Roman Proskuryakov
aed3ccb9c7 Improves Printer, fixes some bugs 2017-03-31 14:44:13 -04:00
Andrew Gallant
33c95d2919 bump deps 2017-03-30 12:33:31 -04:00
Roman Proskuryakov
01deac9427 Add -0 shortcut for --null
Fixes #419
2017-03-28 18:37:40 -04:00
Andrew Gallant
b4bc3b6349 remove uninstall step 2017-03-28 12:14:15 -04:00
Andrew Gallant
685cc6c562 Add vim type.
It's the same as the vimscript type, but shorter and more obvious.

Fixes #415
2017-03-21 07:56:49 -04:00
Andrew Gallant
08c017330f bump termcolor dep 2017-03-15 07:15:39 -04:00
16 changed files with 309 additions and 168 deletions

View File

@@ -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

36
Cargo.lock generated
View File

@@ -4,12 +4,12 @@ version = "0.5.0"
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.5 (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.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)",
@@ -158,7 +158,7 @@ dependencies = [
[[package]]
name = "lazy_static"
version = "0.2.4"
version = "0.2.5"
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.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 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"

View File

@@ -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]

View File

@@ -378,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!

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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`

View File

@@ -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"]),

View File

@@ -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\

View File

@@ -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 {

View File

@@ -447,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", "Ж");

View File

@@ -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]

View File

@@ -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;

View File

@@ -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");