rgs: added multiline window limit and in-file result indexing (work in progress)
This commit is contained in:
@@ -96,6 +96,8 @@ _rg() {
|
||||
+ '(file-name)' # File-name options
|
||||
{-H,--with-filename}'[show file name for matches]'
|
||||
{-I,--no-filename}"[don't show file name for matches]"
|
||||
'--in-file-index[show per-file match index in output]'
|
||||
'--no-in-file-index[hide per-file match index in output]'
|
||||
|
||||
+ '(file-system)' # File system options
|
||||
"--one-file-system[don't descend into directories on other file systems]"
|
||||
@@ -210,6 +212,7 @@ _rg() {
|
||||
|
||||
+ '(multiline)' # Multiline options
|
||||
{-U,--multiline}'[permit matching across multiple lines]'
|
||||
'--multiline-window=[limit multiline matches to NUM lines (with -U)]:number of lines'
|
||||
$no'(multiline-dotall)--no-multiline[restrict matches to at most one line each]'
|
||||
|
||||
+ '(multiline-dotall)' # Multiline DOTALL options
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -61,6 +61,7 @@ pub(crate) struct HiArgs {
|
||||
ignore_file_case_insensitive: bool,
|
||||
ignore_file: Vec<PathBuf>,
|
||||
include_zero: bool,
|
||||
in_file_index: bool,
|
||||
invert_match: bool,
|
||||
is_terminal_stdout: bool,
|
||||
line_number: bool,
|
||||
@@ -73,6 +74,7 @@ pub(crate) struct HiArgs {
|
||||
mode: Mode,
|
||||
multiline: bool,
|
||||
multiline_dotall: bool,
|
||||
multiline_window: Option<usize>,
|
||||
no_ignore_dot: bool,
|
||||
no_ignore_exclude: bool,
|
||||
no_ignore_files: bool,
|
||||
@@ -140,6 +142,9 @@ impl HiArgs {
|
||||
}
|
||||
|
||||
let mut state = State::new()?;
|
||||
if low.multiline_window.is_some() && !low.multiline {
|
||||
anyhow::bail!("--multiline-window requires --multiline");
|
||||
}
|
||||
let patterns = Patterns::from_low_args(&mut state, &mut low)?;
|
||||
let paths = Paths::from_low_args(&mut state, &patterns, &mut low)?;
|
||||
|
||||
@@ -278,6 +283,7 @@ impl HiArgs {
|
||||
ignore_file: low.ignore_file,
|
||||
ignore_file_case_insensitive: low.ignore_file_case_insensitive,
|
||||
include_zero: low.include_zero,
|
||||
in_file_index: low.in_file_index,
|
||||
invert_match: low.invert_match,
|
||||
is_terminal_stdout: state.is_terminal_stdout,
|
||||
line_number,
|
||||
@@ -289,6 +295,7 @@ impl HiArgs {
|
||||
mmap_choice,
|
||||
multiline: low.multiline,
|
||||
multiline_dotall: low.multiline_dotall,
|
||||
multiline_window: low.multiline_window,
|
||||
no_ignore_dot: low.no_ignore_dot,
|
||||
no_ignore_exclude: low.no_ignore_exclude,
|
||||
no_ignore_files: low.no_ignore_files,
|
||||
@@ -616,6 +623,7 @@ impl HiArgs {
|
||||
.column(self.column)
|
||||
.heading(self.heading)
|
||||
.hyperlink(self.hyperlink_config.clone())
|
||||
.in_file_index(self.in_file_index)
|
||||
.max_columns_preview(self.max_columns_preview)
|
||||
.max_columns(self.max_columns)
|
||||
.only_matching(self.only_matching)
|
||||
@@ -723,6 +731,7 @@ impl HiArgs {
|
||||
.invert_match(self.invert_match)
|
||||
.line_number(self.line_number)
|
||||
.multi_line(self.multiline)
|
||||
.multiline_window(self.multiline_window)
|
||||
.memory_map(self.mmap_choice.clone())
|
||||
.stop_on_nonmatch(self.stop_on_nonmatch);
|
||||
match self.context {
|
||||
|
||||
@@ -65,6 +65,7 @@ pub(crate) struct LowArgs {
|
||||
pub(crate) ignore_file: Vec<PathBuf>,
|
||||
pub(crate) ignore_file_case_insensitive: bool,
|
||||
pub(crate) include_zero: bool,
|
||||
pub(crate) in_file_index: bool,
|
||||
pub(crate) invert_match: bool,
|
||||
pub(crate) line_number: Option<bool>,
|
||||
pub(crate) logging: Option<LoggingMode>,
|
||||
@@ -76,6 +77,7 @@ pub(crate) struct LowArgs {
|
||||
pub(crate) mmap: MmapMode,
|
||||
pub(crate) multiline: bool,
|
||||
pub(crate) multiline_dotall: bool,
|
||||
pub(crate) multiline_window: Option<usize>,
|
||||
pub(crate) no_config: bool,
|
||||
pub(crate) no_ignore_dot: bool,
|
||||
pub(crate) no_ignore_exclude: bool,
|
||||
|
||||
Reference in New Issue
Block a user