diff options
Diffstat (limited to 'src/search_buffer.rs')
-rw-r--r-- | src/search_buffer.rs | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/search_buffer.rs b/src/search_buffer.rs index 59869a9b..2777a06c 100644 --- a/src/search_buffer.rs +++ b/src/search_buffer.rs @@ -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); @@ -164,8 +180,18 @@ impl<'a, W: WriteColor> BufferSearcher<'a, W> { } #[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; } @@ -318,6 +344,13 @@ and exhibited clearly, with a label attached.\ } #[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( "Sherlock", SHERLOCK, |s| s.files_with_matches(true)); |