* Parses the standard output of grep-like commands (git grep, system grep). * Expects format: filePath:lineNumber:lineContent * Handles colons within file paths and line content correctly. * @param {string} output The raw stdout string. * @param {string} basePath The absolute directory t
(output: string, basePath: string)
| 236 | * @returns {GrepMatch[]} Array of match objects. |
| 237 | */ |
| 238 | private parseGrepOutput(output: string, basePath: string): GrepMatch[] { |
| 239 | const results: GrepMatch[] = []; |
| 240 | if (!output) return results; |
| 241 | |
| 242 | const lines = output.split(EOL); // Use OS-specific end-of-line |
| 243 | |
| 244 | for (const line of lines) { |
| 245 | if (!line.trim()) continue; |
| 246 | |
| 247 | // Find the index of the first colon. |
| 248 | const firstColonIndex = line.indexOf(':'); |
| 249 | if (firstColonIndex === -1) continue; // Malformed |
| 250 | |
| 251 | // Find the index of the second colon, searching *after* the first one. |
| 252 | const secondColonIndex = line.indexOf(':', firstColonIndex + 1); |
| 253 | if (secondColonIndex === -1) continue; // Malformed |
| 254 | |
| 255 | // Extract parts based on the found colon indices |
| 256 | const filePathRaw = line.substring(0, firstColonIndex); |
| 257 | const lineNumberStr = line.substring( |
| 258 | firstColonIndex + 1, |
| 259 | secondColonIndex, |
| 260 | ); |
| 261 | const lineContent = line.substring(secondColonIndex + 1); |
| 262 | |
| 263 | const lineNumber = parseInt(lineNumberStr, 10); |
| 264 | |
| 265 | if (!isNaN(lineNumber)) { |
| 266 | const absoluteFilePath = path.resolve(basePath, filePathRaw); |
| 267 | const relativeFilePath = path.relative(basePath, absoluteFilePath); |
| 268 | |
| 269 | results.push({ |
| 270 | filePath: relativeFilePath || path.basename(absoluteFilePath), |
| 271 | lineNumber, |
| 272 | line: lineContent, |
| 273 | }); |
| 274 | } |
| 275 | } |
| 276 | return results; |
| 277 | } |
| 278 | |
| 279 | /** |
| 280 | * Gets a description of the grep operation |