Skip to content

Commit 0557b49

Browse files
committed
✨ Feat: Add filename pattern matching to search
Extend both indexed and brute-force search paths to match the regex against file paths, not just file contents. - Indexed search: collect content-hit paths into a HashSet, then run regex against all indexed file paths, appending path-only matches (no duplicates) - Brute-force search: after content search, fall back to path match if no content hits found for that entry - Output: line_number == 0 signals a path-only match; printed as bare path (rg --files style) with magenta colour support
1 parent 4d56ecf commit 0557b49

2 files changed

Lines changed: 43 additions & 2 deletions

File tree

trigrep-cli/src/cmd_search.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn search_indexed(opts: &SearchOptions, regex: &Regex, root: &Path) -> Result<Ve
9999
}
100100

101101
// Run regex on candidate files in parallel
102-
let matches: Vec<SearchMatch> = candidates
102+
let mut matches: Vec<SearchMatch> = candidates
103103
.par_iter()
104104
.flat_map(|&file_id| {
105105
let rel_path = reader.file_path(file_id).to_string();
@@ -111,6 +111,30 @@ fn search_indexed(opts: &SearchOptions, regex: &Regex, root: &Path) -> Result<Ve
111111
})
112112
.collect();
113113

114+
// Path-name matches: regex on every indexed file path. Files that already
115+
// have content matches are skipped (no duplicate path-only line).
116+
let content_hits: std::collections::HashSet<&str> =
117+
matches.iter().map(|m| m.file.as_str()).collect();
118+
let path_matches: Vec<SearchMatch> = reader
119+
.files
120+
.par_iter()
121+
.filter_map(|rel_path| {
122+
if content_hits.contains(rel_path.as_str()) {
123+
return None;
124+
}
125+
if regex.is_match(rel_path) {
126+
Some(SearchMatch {
127+
file: rel_path.clone(),
128+
line_number: 0,
129+
line_content: String::new(),
130+
})
131+
} else {
132+
None
133+
}
134+
})
135+
.collect();
136+
matches.extend(path_matches);
137+
114138
Ok(matches)
115139
}
116140

@@ -121,7 +145,15 @@ fn search_brute_force(regex: &Regex, root: &Path) -> Result<Vec<SearchMatch>> {
121145
.par_iter()
122146
.flat_map(|entry| {
123147
let content = String::from_utf8_lossy(&entry.content);
124-
search_file_content(&entry.relative_path, &content, regex)
148+
let mut hits = search_file_content(&entry.relative_path, &content, regex);
149+
if hits.is_empty() && regex.is_match(&entry.relative_path) {
150+
hits.push(SearchMatch {
151+
file: entry.relative_path.clone(),
152+
line_number: 0,
153+
line_content: String::new(),
154+
});
155+
}
156+
hits
125157
})
126158
.collect();
127159

trigrep-cli/src/output.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ fn print_grep_format(
107107
config: &OutputConfig,
108108
) -> io::Result<()> {
109109
for m in matches {
110+
// Path-name match: line_number == 0 -> print bare path (rg --files style).
111+
if m.line_number == 0 {
112+
if config.color {
113+
writeln!(out, "{}", m.file.magenta())?;
114+
} else {
115+
writeln!(out, "{}", m.file)?;
116+
}
117+
continue;
118+
}
110119
if config.color {
111120
write!(out, "{}", m.file.magenta())?;
112121
if config.line_numbers {

0 commit comments

Comments
 (0)