rgs: added multiline window limit and in-file result indexing (work in progress)

This commit is contained in:
2025-12-23 04:01:55 -05:00
parent cd1f981bea
commit ad6ec1b4c5
9 changed files with 599 additions and 8 deletions

View File

@@ -97,6 +97,7 @@ pub(super) const FLAGS: &[&dyn Flag] = &[
&MaxFilesize,
&Mmap,
&Multiline,
&MultilineWindow,
&MultilineDotall,
&NoConfig,
&NoIgnore,
@@ -142,6 +143,7 @@ pub(super) const FLAGS: &[&dyn Flag] = &[
&Unrestricted,
&Version,
&Vimgrep,
&InFileIndex,
&WithFilename,
&WithFilenameNo,
&WordRegexp,
@@ -4209,6 +4211,59 @@ fn test_multiline() {
assert_eq!(false, args.multiline);
}
/// --multiline-window
#[derive(Debug)]
struct MultilineWindow;
impl Flag for MultilineWindow {
fn is_switch(&self) -> bool {
false
}
fn name_long(&self) -> &'static str {
"multiline-window"
}
fn doc_variable(&self) -> Option<&'static str> {
Some("NUM")
}
fn doc_category(&self) -> Category {
Category::Search
}
fn doc_short(&self) -> &'static str {
r"Limit multiline matches to a fixed number of lines."
}
fn doc_long(&self) -> &'static str {
r#"
Limit the maximum number of lines that a multiline match may span to
\fINUM\fP (use \fB--multiline-window=\fP\fINUM\fP).
.sp
This flag requires \flag{multiline}. Matches are found as if the file being
searched were limited to \fINUM\fP lines at a time, which can prevent
unintended long matches while still enabling multi-line searching.
.sp
The value of \fINUM\fP must be at least 1.
"#
}
fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
let lines = convert::usize(&v.unwrap_value())?;
if lines == 0 {
anyhow::bail!("--multiline-window must be at least 1");
}
args.multiline_window = Some(lines);
Ok(())
}
}
#[cfg(test)]
#[test]
fn test_multiline_window() {
let args = parse_low_raw(None::<&str>).unwrap();
assert_eq!(None, args.multiline_window);
let args = parse_low_raw(["--multiline-window=2"]).unwrap();
assert_eq!(Some(2), args.multiline_window);
}
/// --multiline-dotall
#[derive(Debug)]
struct MultilineDotall;
@@ -7401,6 +7456,53 @@ fn test_vimgrep() {
assert_eq!(true, args.vimgrep);
}
/// --in-file-index
#[derive(Debug)]
struct InFileIndex;
impl Flag for InFileIndex {
fn is_switch(&self) -> bool {
true
}
fn name_long(&self) -> &'static str {
"in-file-index"
}
fn name_negated(&self) -> Option<&'static str> {
Some("no-in-file-index")
}
fn doc_category(&self) -> Category {
Category::Output
}
fn doc_short(&self) -> &'static str {
r"Prefix matches with an index per file."
}
fn doc_long(&self) -> &'static str {
r"
When enabled, ripgrep prefixes each matching line with an index that is
incremented per file. The format is \fIFILE\fP[\fIN\fP]:\fILINE\fP:, which can
disambiguate multi-line matches that print the same line multiple times.
"
}
fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
args.in_file_index = v.unwrap_switch();
Ok(())
}
}
#[cfg(test)]
#[test]
fn test_in_file_index() {
let args = parse_low_raw(None::<&str>).unwrap();
assert_eq!(false, args.in_file_index);
let args = parse_low_raw(["--in-file-index"]).unwrap();
assert_eq!(true, args.in_file_index);
let args = parse_low_raw(["--in-file-index", "--no-in-file-index"]).unwrap();
assert_eq!(false, args.in_file_index);
}
/// --with-filename
#[derive(Debug)]
struct WithFilename;