search: add a --count-matches flag

This commit introduces a new flag, --count-matches, which will cause
ripgrep to report a total count of all matches instead of a count of
total lines matched.

Closes #566, Closes #814
This commit is contained in:
Balaji Sivaraman
2018-02-20 21:03:07 +05:30
committed by Andrew Gallant
parent 96f73293c0
commit 27fc9f2fd3
7 changed files with 147 additions and 7 deletions

View File

@@ -22,6 +22,7 @@ pub struct BufferSearcher<'a, W: 'a> {
path: &'a Path,
buf: &'a [u8],
match_line_count: u64,
match_count: Option<u64>,
line_count: Option<u64>,
byte_offset: Option<u64>,
last_line: usize,
@@ -41,6 +42,7 @@ impl<'a, W: WriteColor> BufferSearcher<'a, W> {
path: path,
buf: buf,
match_line_count: 0,
match_count: None,
line_count: None,
byte_offset: None,
last_line: 0,
@@ -65,6 +67,15 @@ impl<'a, W: WriteColor> BufferSearcher<'a, W> {
self
}
/// If enabled, searching will print the count of individual matches
/// instead of each match.
///
/// Disabled by default.
pub fn count_matches(mut self, yes: bool) -> Self {
self.opts.count_matches = yes;
self
}
/// If enabled, searching will print the path instead of each match.
///
/// Disabled by default.
@@ -135,6 +146,7 @@ impl<'a, W: WriteColor> BufferSearcher<'a, W> {
// The memory map searcher uses one contiguous block of bytes, so the
// offsets given the printer are sufficient to compute the byte offset.
self.byte_offset = if self.opts.byte_offset { Some(0) } else { None };
self.match_count = if self.opts.count_matches { Some(0) } else { None };
let mut last_end = 0;
for m in self.grep.iter(self.buf) {
if self.opts.invert_match {
@@ -153,6 +165,10 @@ impl<'a, W: WriteColor> BufferSearcher<'a, W> {
}
if self.opts.count && self.match_line_count > 0 {
self.printer.path_count(self.path, self.match_line_count);
} else if self.opts.count_matches
&& self.match_count.map_or(false, |c| c > 0)
{
self.printer.path_count(self.path, self.match_count.unwrap());
}
if self.opts.files_with_matches && self.match_line_count > 0 {
self.printer.path(self.path);
@@ -163,9 +179,19 @@ impl<'a, W: WriteColor> BufferSearcher<'a, W> {
self.match_line_count
}
#[inline(always)]
fn count_individual_matches(&mut self, start: usize, end: usize) {
if let Some(ref mut count) = self.match_count {
for _ in self.grep.regex().find_iter(&self.buf[start..end]) {
*count += 1;
}
}
}
#[inline(always)]
pub fn print_match(&mut self, start: usize, end: usize) {
self.match_line_count += 1;
self.count_individual_matches(start, end);
if self.opts.skip_matches() {
return;
}
@@ -317,6 +343,13 @@ and exhibited clearly, with a label attached.\
assert_eq!(out, "/baz.rs:2\n");
}
#[test]
fn count_matches() {
let (_, out) = search(
"the", SHERLOCK, |s| s.count_matches(true));
assert_eq!(out, "/baz.rs:4\n");
}
#[test]
fn files_with_matches() {
let (count, out) = search(