From 842647e51ed3b752867fc65c7bc677b826248048 Mon Sep 17 00:00:00 2001 From: Mykhailo Chalyi Date: Mon, 25 May 2026 15:08:51 +0000 Subject: [PATCH] fix(rg): apply max-count after multiline invert Multiline --invert-match was passing opts.max_count into positive-span collection, truncating positive spans before inversion and producing too much inverted output. Match ripgrep: collect all positive spans, then apply -m/--max-count to the inverted result. Rebased on current main; original PR #1752 by chaliy. --- crates/bashkit/src/builtins/rg/mod.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/bashkit/src/builtins/rg/mod.rs b/crates/bashkit/src/builtins/rg/mod.rs index 428a4f9c..5aa61838 100644 --- a/crates/bashkit/src/builtins/rg/mod.rs +++ b/crates/bashkit/src/builtins/rg/mod.rs @@ -4915,6 +4915,8 @@ impl Builtin for Rg { && !opts.invert_match { Some(opts.max_count.unwrap_or(usize::MAX).min(1)) + } else if opts.invert_match { + None } else { opts.max_count }; @@ -4925,13 +4927,18 @@ impl Builtin for Rg { if opts.invert_match { let matched_line_set: HashSet = context_match_lines.iter().copied().collect(); - let inverted_match_lines: Vec = lines + let mut inverted_match_lines: Vec = lines .iter() .enumerate() .filter_map(|(line_idx, _)| { (!matched_line_set.contains(&line_idx)).then_some(line_idx) }) .collect(); + if let Some(limit) = opts.max_count + && inverted_match_lines.len() > limit + { + inverted_match_lines.truncate(limit); + } match_count = inverted_match_lines.len(); count_value = inverted_match_lines.len(); let inverted_matches = if opts.count_only || opts.count_matches { @@ -12413,6 +12420,18 @@ mod tests { assert_eq!(lines.len(), 1); } + #[tokio::test] + async fn test_rg_multiline_invert_max_count() { + let result = run_rg( + &["-m", "1", "-v", "-U", "foo\nbar", "/test.txt"], + None, + &[("/test.txt", b"foo\nbar\nkeep1\nfoo\nbar\nkeep2\n")], + ) + .await; + assert_eq!(result.exit_code, 0); + assert_eq!(result.stdout, "keep1\n"); + } + #[tokio::test] async fn test_rg_max_count_requires_value() { let args: Vec = vec!["hello".to_string(), "-m".to_string()];