Skip to content

Commit 94e4b8e

Browse files
committed
printer: fix --vimgrep for multi-line mode
It turned out that --vimgrep wasn't quite getting the column of each match correctly. Instead of printing column numbers relative to the current line, it was printing column numbers as byte offsets relative to where the match began. To fix this, we simply subtract the offset of the line number from the beginning of the match. If the beginning of the match came before the start of the current line, then there's really nothing sensible we can do other than to use a column number of 1, which we now document. Interestingly, existing tests were checking that the previous behavior was intended. My only defense is that I somehow tricked myself into thinking it was a byte offset instead of a column number. Kudos to @bfrg for calling this out in #1866: #1866 (comment)
1 parent 2af7724 commit 94e4b8e

File tree

4 files changed

+30
-8
lines changed

4 files changed

+30
-8
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ Bug fixes:
2121
Document cygwin path translation behavior in the FAQ.
2222
* [BUG #1741](https://github.com/BurntSushi/ripgrep/issues/1741):
2323
Fix stdin detection when using PowerShell in UNIX environments.
24+
* [BUG #1866](https://github.com/BurntSushi/ripgrep/issues/1866#issuecomment-841635553):
25+
Fix bug when computing column numbers in `--vimgrep` mode.
2426

2527

2628
12.1.1 (2020-05-29)

crates/printer/src/standard.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,9 @@ impl StandardBuilder {
222222
/// When multi-line mode is enabled, each match and its accompanying lines
223223
/// are printed. As with single line matches, if a line contains multiple
224224
/// matches (even if only partially), then that line is printed once for
225-
/// each match it participates in.
225+
/// each match it participates in. In multi-line mode, column numbers only
226+
/// indicate the start of a match. If a line only continues a match, then
227+
/// the column number printed is always `1`.
226228
pub fn per_match(&mut self, yes: bool) -> &mut StandardBuilder {
227229
self.config.per_match = yes;
228230
self
@@ -1090,7 +1092,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
10901092
self.write_prelude(
10911093
self.sunk.absolute_byte_offset() + line.start() as u64,
10921094
self.sunk.line_number().map(|n| n + count),
1093-
Some(m.start() as u64 + 1),
1095+
Some(m.start().saturating_sub(line.start()) as u64 + 1),
10941096
)?;
10951097
count += 1;
10961098
if self.exceeds_max_columns(&bytes[line]) {
@@ -2990,9 +2992,9 @@ Holmeses, success in the province of detective work must always
29902992
let got = printer_contents(&mut printer);
29912993
let expected = "\
29922994
1:16:For the Doctor Watsons of this world, as opposed to the Sherlock
2993-
2:16:Holmeses, success in the province of detective work must always
2995+
2:1:Holmeses, success in the province of detective work must always
29942996
5:12:but Doctor Watson has to have it taken out for him and dusted,
2995-
6:12:and exhibited clearly, with a label attached.
2997+
6:1:and exhibited clearly, with a label attached.
29962998
";
29972999
assert_eq_printed!(expected, got);
29983000
}
@@ -3019,9 +3021,9 @@ Holmeses, success in the province of detective work must always
30193021
let got = printer_contents(&mut printer);
30203022
let expected = "\
30213023
1:16:For the Doctor Watsons of this world, as opposed to the Sherlock
3022-
2:16:Holmeses, success in the province of detective work must always
3023-
2:123:Holmeses, success in the province of detective work must always
3024-
3:123:be, to a very large extent, the result of luck. Sherlock Holmes
3024+
2:1:Holmeses, success in the province of detective work must always
3025+
2:58:Holmeses, success in the province of detective work must always
3026+
3:1:be, to a very large extent, the result of luck. Sherlock Holmes
30253027
";
30263028
assert_eq_printed!(expected, got);
30273029
}

tests/multiline.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ rgtest!(vimgrep, |dir: Dir, mut cmd: TestCommand| {
7777
let expected = "\
7878
sherlock:1:16:For the Doctor Watsons of this world, as opposed to the Sherlock
7979
sherlock:1:57:For the Doctor Watsons of this world, as opposed to the Sherlock
80-
sherlock:2:57:Holmeses, success in the province of detective work must always
80+
sherlock:2:1:Holmeses, success in the province of detective work must always
8181
sherlock:3:49:be, to a very large extent, the result of luck. Sherlock Holmes
8282
sherlock:5:12:but Doctor Watson has to have it taken out for him and dusted,
8383
";

tests/regression.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,3 +864,21 @@ use B;
864864
]);
865865
eqnice!("2\n", cmd.stdout());
866866
});
867+
868+
rgtest!(r1866, |dir: Dir, mut cmd: TestCommand| {
869+
dir.create("test", "foobar\nfoobar\nfoo quux");
870+
cmd.args(&[
871+
"--multiline",
872+
"--vimgrep",
873+
r"foobar\nfoobar\nfoo|quux",
874+
"test",
875+
]);
876+
877+
let expected = "\
878+
test:1:1:foobar
879+
test:2:1:foobar
880+
test:3:1:foo quux
881+
test:3:5:foo quux
882+
";
883+
eqnice!(expected, cmd.stdout());
884+
});

0 commit comments

Comments
 (0)