From fde8cce9abc11d4e1f51845dd36882f7a4529c25 Mon Sep 17 00:00:00 2001 From: Sai Asish Y Date: Tue, 12 May 2026 21:03:03 -0700 Subject: [PATCH] fix: parse git grep lines for hyphenated paths without an extension --- src/handlers/grep.rs | 50 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/handlers/grep.rs b/src/handlers/grep.rs index 696c3ccfc..cbb747448 100644 --- a/src/handlers/grep.rs +++ b/src/handlers/grep.rs @@ -473,6 +473,7 @@ enum GrepLineRegex { WithFileExtensionAndLineNumber, WithFileExtension, WithFileExtensionNoSpaces, + WithoutFileExtensionColonSeparated, WithoutSeparatorCharacters, } @@ -496,6 +497,11 @@ lazy_static! { make_grep_line_regex(GrepLineRegex::WithFileExtension); } +lazy_static! { + static ref GREP_LINE_REGEX_ASSUMING_NO_FILE_EXTENSION_COLON_SEPARATED: Regex = + make_grep_line_regex(GrepLineRegex::WithoutFileExtensionColonSeparated); +} + lazy_static! { static ref GREP_LINE_REGEX_ASSUMING_NO_INTERNAL_SEPARATOR_CHARS: Regex = make_grep_line_regex(GrepLineRegex::WithoutSeparatorCharacters); @@ -553,6 +559,15 @@ fn make_grep_line_regex(regex_variant: GrepLineRegex) -> Regex { ) " } + GrepLineRegex::WithoutFileExtensionColonSeparated => { + r" + ( # 1. file name (colons not allowed) + [^:|\ ] # try to be strict about what a file path can start with + [^:]* # anything except a colon + [^:\ ] # a file name cannot end with whitespace + ) + " + } GrepLineRegex::WithoutSeparatorCharacters => { r" ( # 1. file name (colons not allowed) @@ -673,6 +688,7 @@ pub fn parse_grep_line(line: &str) -> Option> { &*GREP_LINE_REGEX_ASSUMING_FILE_EXTENSION_AND_LINE_NUMBER, &*GREP_LINE_REGEX_ASSUMING_FILE_EXTENSION_NO_SPACES, &*GREP_LINE_REGEX_ASSUMING_FILE_EXTENSION, + &*GREP_LINE_REGEX_ASSUMING_NO_FILE_EXTENSION_COLON_SEPARATED, &*GREP_LINE_REGEX_ASSUMING_NO_INTERNAL_SEPARATOR_CHARS, ] .iter() @@ -906,10 +922,8 @@ mod tests { } #[test] - #[ignore] fn test_parse_grep_n_match_file_name_with_dashes_and_no_extension() { // git grep -n - // This fails: we can't parse it currently. let fake_parent_grep_command = "/usr/local/bin/git --doesnt-matter grep --nor-this nor_this -- nor_this"; let _args = FakeParentArgs::once(fake_parent_grep_command); @@ -927,6 +941,38 @@ mod tests { ); } + #[test] + fn test_parse_grep_match_file_name_with_dashes_and_no_extension() { + // git grep (no line number); the file name contains a hyphen and has no extension + let fake_parent_grep_command = + "/usr/local/bin/git --doesnt-matter grep --nor-this nor_this -- nor_this"; + let _args = FakeParentArgs::for_scope(fake_parent_grep_command); + + assert_eq!( + parse_grep_line("foo-bar:content"), + Some(GrepLine { + grep_type: GrepType::Classic, + path: "foo-bar".into(), + line_number: None, + line_type: LineType::Match, + code: "content".into(), + submatches: None, + }) + ); + + assert_eq!( + parse_grep_line("etc/119-within-line-edits:repo=$(mktemp -d)"), + Some(GrepLine { + grep_type: GrepType::Classic, + path: "etc/119-within-line-edits".into(), + line_number: None, + line_type: LineType::Match, + code: "repo=$(mktemp -d)".into(), + submatches: None, + }) + ); + } + #[test] fn test_parse_grep_n_match_directory_name_with_dashes() { let fake_parent_grep_command =