rgs: added multiline window limit and in-file result indexing (work in progress)
This commit is contained in:
@@ -39,6 +39,7 @@ struct Config {
|
||||
stats: bool,
|
||||
heading: bool,
|
||||
path: bool,
|
||||
in_file_index: bool,
|
||||
only_matching: bool,
|
||||
per_match: bool,
|
||||
per_match_one_line: bool,
|
||||
@@ -64,6 +65,7 @@ impl Default for Config {
|
||||
stats: false,
|
||||
heading: false,
|
||||
path: true,
|
||||
in_file_index: false,
|
||||
only_matching: false,
|
||||
per_match: false,
|
||||
per_match_one_line: false,
|
||||
@@ -231,6 +233,12 @@ impl StandardBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// When enabled, prefix matching lines with a per-file match index.
|
||||
pub fn in_file_index(&mut self, yes: bool) -> &mut StandardBuilder {
|
||||
self.config.in_file_index = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Only print the specific matches instead of the entire line containing
|
||||
/// each match. Each match is printed on its own line. When multi line
|
||||
/// search is enabled, then matches spanning multiple lines are printed
|
||||
@@ -528,6 +536,7 @@ impl<W: WriteColor> Standard<W> {
|
||||
path: None,
|
||||
start_time: Instant::now(),
|
||||
match_count: 0,
|
||||
in_file_index: 0,
|
||||
binary_byte_offset: None,
|
||||
stats,
|
||||
needs_match_granularity,
|
||||
@@ -564,6 +573,7 @@ impl<W: WriteColor> Standard<W> {
|
||||
path: Some(ppath),
|
||||
start_time: Instant::now(),
|
||||
match_count: 0,
|
||||
in_file_index: 0,
|
||||
binary_byte_offset: None,
|
||||
stats,
|
||||
needs_match_granularity,
|
||||
@@ -644,6 +654,7 @@ pub struct StandardSink<'p, 's, M: Matcher, W> {
|
||||
path: Option<PrinterPath<'p>>,
|
||||
start_time: Instant,
|
||||
match_count: u64,
|
||||
in_file_index: u64,
|
||||
binary_byte_offset: Option<u64>,
|
||||
stats: Option<Stats>,
|
||||
needs_match_granularity: bool,
|
||||
@@ -769,6 +780,7 @@ impl<'p, 's, M: Matcher, W: WriteColor> Sink for StandardSink<'p, 's, M, W> {
|
||||
mat: &SinkMatch<'_>,
|
||||
) -> Result<bool, io::Error> {
|
||||
self.match_count += 1;
|
||||
self.in_file_index += 1;
|
||||
|
||||
self.record_matches(
|
||||
searcher,
|
||||
@@ -842,6 +854,7 @@ impl<'p, 's, M: Matcher, W: WriteColor> Sink for StandardSink<'p, 's, M, W> {
|
||||
self.standard.wtr.borrow_mut().reset_count();
|
||||
self.start_time = Instant::now();
|
||||
self.match_count = 0;
|
||||
self.in_file_index = 0;
|
||||
self.binary_byte_offset = None;
|
||||
Ok(true)
|
||||
}
|
||||
@@ -956,6 +969,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
||||
self.sunk.absolute_byte_offset(),
|
||||
self.sunk.line_number(),
|
||||
None,
|
||||
self.in_file_index(),
|
||||
)?;
|
||||
self.write_line(self.sunk.bytes())
|
||||
}
|
||||
@@ -981,6 +995,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
||||
absolute_byte_offset,
|
||||
self.sunk.line_number().map(|n| n + i as u64),
|
||||
None,
|
||||
self.in_file_index(),
|
||||
)?;
|
||||
absolute_byte_offset += line.len() as u64;
|
||||
|
||||
@@ -1001,6 +1016,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
||||
self.sunk.absolute_byte_offset() + m.start() as u64,
|
||||
self.sunk.line_number(),
|
||||
Some(m.start() as u64 + 1),
|
||||
self.in_file_index(),
|
||||
)?;
|
||||
|
||||
let buf = &self.sunk.bytes()[m];
|
||||
@@ -1012,6 +1028,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
||||
self.sunk.absolute_byte_offset() + m.start() as u64,
|
||||
self.sunk.line_number(),
|
||||
Some(m.start() as u64 + 1),
|
||||
self.in_file_index(),
|
||||
)?;
|
||||
self.write_colored_line(&[m], self.sunk.bytes())?;
|
||||
}
|
||||
@@ -1020,6 +1037,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
||||
self.sunk.absolute_byte_offset(),
|
||||
self.sunk.line_number(),
|
||||
Some(self.sunk.matches()[0].start() as u64 + 1),
|
||||
self.in_file_index(),
|
||||
)?;
|
||||
self.write_colored_line(self.sunk.matches(), self.sunk.bytes())?;
|
||||
}
|
||||
@@ -1048,6 +1066,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
||||
self.sunk.absolute_byte_offset() + line.start() as u64,
|
||||
self.sunk.line_number().map(|n| n + count),
|
||||
Some(matches[0].start() as u64 + 1),
|
||||
self.in_file_index(),
|
||||
)?;
|
||||
count += 1;
|
||||
self.trim_ascii_prefix(bytes, &mut line);
|
||||
@@ -1093,6 +1112,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
||||
self.sunk.absolute_byte_offset() + m.start() as u64,
|
||||
self.sunk.line_number().map(|n| n + count),
|
||||
Some(m.start() as u64 + 1),
|
||||
self.in_file_index(),
|
||||
)?;
|
||||
|
||||
let this_line = line.with_end(upto);
|
||||
@@ -1131,6 +1151,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
||||
self.sunk.absolute_byte_offset() + line.start() as u64,
|
||||
self.sunk.line_number().map(|n| n + count),
|
||||
Some(m.start().saturating_sub(line.start()) as u64 + 1),
|
||||
self.in_file_index(),
|
||||
)?;
|
||||
count += 1;
|
||||
self.trim_line_terminator(bytes, &mut line);
|
||||
@@ -1178,10 +1199,11 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
||||
absolute_byte_offset: u64,
|
||||
line_number: Option<u64>,
|
||||
column: Option<u64>,
|
||||
in_file_index: Option<u64>,
|
||||
) -> io::Result<()> {
|
||||
let mut prelude = PreludeWriter::new(self);
|
||||
prelude.start(line_number, column)?;
|
||||
prelude.write_path()?;
|
||||
prelude.write_path(in_file_index)?;
|
||||
prelude.write_line_number(line_number)?;
|
||||
prelude.write_column_number(column)?;
|
||||
prelude.write_byte_offset(absolute_byte_offset)?;
|
||||
@@ -1532,6 +1554,14 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
||||
self.sunk.context_kind().is_some()
|
||||
}
|
||||
|
||||
fn in_file_index(&self) -> Option<u64> {
|
||||
if self.is_context() || !self.config().in_file_index {
|
||||
None
|
||||
} else {
|
||||
Some(self.sink.in_file_index)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the underlying configuration for this printer.
|
||||
fn config(&self) -> &'a Config {
|
||||
&self.sink.standard.config
|
||||
@@ -1657,16 +1687,27 @@ impl<'a, M: Matcher, W: WriteColor> PreludeWriter<'a, M, W> {
|
||||
/// separator. (If a path terminator is set, then that is used instead of
|
||||
/// the field separator.)
|
||||
#[inline(always)]
|
||||
fn write_path(&mut self) -> io::Result<()> {
|
||||
fn write_path(&mut self, in_file_index: Option<u64>) -> io::Result<()> {
|
||||
// The prelude doesn't handle headings, only what comes before a match
|
||||
// on the same line. So if we are emitting paths in headings, we should
|
||||
// not do it here on each line.
|
||||
if self.config().heading {
|
||||
if self.config().heading && in_file_index.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
let path = self.std.path();
|
||||
if path.is_none() && in_file_index.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
let Some(path) = self.std.path() else { return Ok(()) };
|
||||
self.write_separator()?;
|
||||
self.std.write_path(path)?;
|
||||
if let Some(path) = path {
|
||||
self.std.write_path(path)?;
|
||||
}
|
||||
if let Some(index) = in_file_index {
|
||||
self.std.write_spec(self.config().colors.path(), b"[")?;
|
||||
let n = DecimalFormatter::new(index);
|
||||
self.std.write_spec(self.config().colors.path(), n.as_bytes())?;
|
||||
self.std.write_spec(self.config().colors.path(), b"]")?;
|
||||
}
|
||||
|
||||
self.next_separator = if self.config().path_terminator.is_some() {
|
||||
PreludeSeparator::PathTerminator
|
||||
|
||||
Reference in New Issue
Block a user