From 674a03b43dd1aecba51b1edfdef1d64b9e7022a8 Mon Sep 17 00:00:00 2001 From: Mykhailo Chalyi Date: Fri, 22 May 2026 22:32:33 -0500 Subject: [PATCH] feat(rg): support escaped glob metacharacters --- crates/bashkit/src/builtins/rg/mod.rs | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/crates/bashkit/src/builtins/rg/mod.rs b/crates/bashkit/src/builtins/rg/mod.rs index f7eb07e09..c08ac665e 100644 --- a/crates/bashkit/src/builtins/rg/mod.rs +++ b/crates/bashkit/src/builtins/rg/mod.rs @@ -1722,6 +1722,10 @@ fn glob_to_regex(pattern: &str) -> String { i += 1; } } + '\\' if i + 1 < chars.len() => { + out.push_str(®ex::escape(&chars[i + 1].to_string())); + i += 2; + } c => { out.push_str(®ex::escape(&c.to_string())); i += 1; @@ -1741,6 +1745,12 @@ fn glob_alternation_to_regex(chars: &[char], start: usize) -> Option<(String, us while i < chars.len() { match chars[i] { + '\\' if i + 1 < chars.len() => { + current.push('\\'); + current.push(chars[i + 1]); + i += 2; + continue; + } '{' => { depth += 1; current.push('{'); @@ -4918,6 +4928,15 @@ mod tests { ("/proj/a.txt", b"needle\n"), ]; + const DIFF_GLOB_ESCAPE_FILES: &[(&str, &[u8])] = &[ + ("/proj/*.txt", b"needle\n"), + ("/proj/?.txt", b"needle\n"), + ("/proj/[x].txt", b"needle\n"), + ("/proj/{a,b}.txt", b"needle\n"), + ("/proj/a.txt", b"needle\n"), + ("/proj/x.txt", b"needle\n"), + ]; + const DIFF_COMMON_TYPE_FILES: &[(&str, &[u8])] = &[ ("/proj/data.csv", b"needle\n"), ("/proj/Dockerfile", b"needle\n"), @@ -5295,6 +5314,38 @@ mod tests { cwd: "/", output: RgDiffOutput::UnorderedLines, }, + RgDiffCase { + name: "glob escaped star", + args: &["--files", "-g", r"\*.txt", "proj"], + stdin: None, + files: DIFF_GLOB_ESCAPE_FILES, + cwd: "/", + output: RgDiffOutput::UnorderedLines, + }, + RgDiffCase { + name: "glob escaped question", + args: &["--files", "-g", r"\?.txt", "proj"], + stdin: None, + files: DIFF_GLOB_ESCAPE_FILES, + cwd: "/", + output: RgDiffOutput::UnorderedLines, + }, + RgDiffCase { + name: "glob escaped class brackets", + args: &["--files", "-g", r"\[x\].txt", "proj"], + stdin: None, + files: DIFF_GLOB_ESCAPE_FILES, + cwd: "/", + output: RgDiffOutput::UnorderedLines, + }, + RgDiffCase { + name: "glob escaped brace alternation", + args: &["--files", "-g", r"\{a,b\}.txt", "proj"], + stdin: None, + files: DIFF_GLOB_ESCAPE_FILES, + cwd: "/", + output: RgDiffOutput::UnorderedLines, + }, RgDiffCase { name: "context combined", args: &["-nC1", "needle", "proj/context.txt"],