(
stdout: string,
options: { matchCount?: number } = {},
)
| 16 | * @returns Formatted output with matches grouped by file |
| 17 | */ |
| 18 | export function formatCodeSearchOutput( |
| 19 | stdout: string, |
| 20 | options: { matchCount?: number } = {}, |
| 21 | ): string { |
| 22 | if (!stdout) { |
| 23 | return 'Found 0 matches' |
| 24 | } |
| 25 | const lines = stdout.split('\n') |
| 26 | const formatted: string[] = [ |
| 27 | `Found ${options.matchCount ?? countFormattedMatches(lines)} matches`, |
| 28 | ] |
| 29 | let currentFile: string | null = null |
| 30 | |
| 31 | for (const line of lines) { |
| 32 | if (!line.trim()) { |
| 33 | formatted.push(line) |
| 34 | continue |
| 35 | } |
| 36 | |
| 37 | // Skip separator lines between result groups |
| 38 | if (line === '--') { |
| 39 | continue |
| 40 | } |
| 41 | |
| 42 | // Ripgrep output format: |
| 43 | // - Match lines: filename:line_number:content |
| 44 | // - Context lines (with -A/-B/-C flags): filename-line_number-content |
| 45 | |
| 46 | // Use regex to find the pattern: separator + digits + separator |
| 47 | // This handles filenames with hyphens/colons by matching the line number pattern |
| 48 | const parsedLine = parseRipgrepLine(line) |
| 49 | |
| 50 | if (!parsedLine) { |
| 51 | formatted.push(line) |
| 52 | continue |
| 53 | } |
| 54 | const { filePath, lineNumber, content } = parsedLine |
| 55 | |
| 56 | // Check if this is a new file (file paths don't start with whitespace) |
| 57 | if (filePath && !filePath.startsWith(' ') && !filePath.startsWith('\t')) { |
| 58 | if (filePath !== currentFile) { |
| 59 | // New file - add double newline before it (except for the first file) |
| 60 | if (currentFile !== null) { |
| 61 | formatted.push('') |
| 62 | } |
| 63 | currentFile = filePath |
| 64 | // Show file path with colon on its own line |
| 65 | formatted.push(filePath + ':') |
| 66 | formatted.push(` Line ${lineNumber}: ${content}`) |
| 67 | } else { |
| 68 | formatted.push(` Line ${lineNumber}: ${content}`) |
| 69 | } |
| 70 | } else { |
| 71 | // Line doesn't match expected format, keep as-is |
| 72 | formatted.push(line) |
| 73 | } |
| 74 | } |
| 75 |
no test coverage detected