1
0
mirror of https://github.com/BurntSushi/ripgrep.git synced 2024-12-12 19:18:24 +02:00

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
This commit is contained in:
Andrew Gallant 2017-05-29 09:51:58 -04:00
parent 4c78ca8b70
commit 112b3c5e0a
No known key found for this signature in database
GPG Key ID: B2E3A4923F8B0D44
2 changed files with 35 additions and 18 deletions

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,15 +242,17 @@ impl<W: WriteColor> Printer<W> {
line_number: Option<u64>,
) {
if !self.line_per_match && !self.only_matching {
let column = re.find(&buf[start..end])
.map(|m| m.start()).unwrap_or(0);
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 = m.start();
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());
}
}
@ -262,7 +264,8 @@ impl<W: WriteColor> Printer<W> {
start: usize,
end: usize,
line_number: Option<u64>,
column: usize,
match_start: usize,
match_end: usize,
) {
if self.heading && self.with_filename && !self.has_printed {
self.write_file_sep();
@ -276,7 +279,7 @@ impl<W: WriteColor> Printer<W> {
self.line_number(line_number, b':');
}
if self.column {
self.column_number(column as u64 + 1, b':');
self.column_number(match_start as u64 + 1, b':');
}
if self.replace.is_some() {
let mut count = 0;
@ -297,19 +300,21 @@ impl<W: WriteColor> Printer<W> {
self.write_eol();
}
} else {
let line_buf = if self.only_matching {
let start_offset = start + column;
let m = re.find(&buf[start_offset..end]).unwrap();
&buf[start_offset + m.start()..start_offset + 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);
@ -319,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

@ -1079,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);
@ -1091,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 =