( args: string[], target: string, abortSignal: AbortSignal, onLines: (lines: string[]) => void, )
| 293 | * timeout, stderr is ignored; interactive callers own recovery. |
| 294 | */ |
| 295 | export async function ripGrepStream( |
| 296 | args: string[], |
| 297 | target: string, |
| 298 | abortSignal: AbortSignal, |
| 299 | onLines: (lines: string[]) => void, |
| 300 | ): Promise<void> { |
| 301 | await codesignRipgrepIfNecessary() |
| 302 | const { rgPath, rgArgs, argv0 } = ripgrepCommand() |
| 303 | |
| 304 | return new Promise<void>((resolve, reject) => { |
| 305 | const child = spawn(rgPath, [...rgArgs, ...args, target], { |
| 306 | argv0, |
| 307 | signal: abortSignal, |
| 308 | windowsHide: true, |
| 309 | stdio: ['ignore', 'pipe', 'ignore'], |
| 310 | }) |
| 311 | |
| 312 | const stripCR = (l: string) => (l.endsWith('\r') ? l.slice(0, -1) : l) |
| 313 | let remainder = '' |
| 314 | child.stdout?.on('data', (chunk: Buffer) => { |
| 315 | const data = remainder + chunk.toString() |
| 316 | const lines = data.split('\n') |
| 317 | remainder = lines.pop() ?? '' |
| 318 | if (lines.length) onLines(lines.map(stripCR)) |
| 319 | }) |
| 320 | |
| 321 | // On Windows, both 'close' and 'error' can fire for the same process. |
| 322 | let settled = false |
| 323 | child.on('close', code => { |
| 324 | if (settled) return |
| 325 | // Abort races close — don't flush a torn tail from a killed process. |
| 326 | // Promise still settles: spawn's signal option fires 'error' with |
| 327 | // AbortError → reject below. |
| 328 | if (abortSignal.aborted) return |
| 329 | settled = true |
| 330 | if (code === 0 || code === 1) { |
| 331 | if (remainder) onLines([stripCR(remainder)]) |
| 332 | resolve() |
| 333 | } else { |
| 334 | reject(new Error(`ripgrep exited with code ${code}`)) |
| 335 | } |
| 336 | }) |
| 337 | child.on('error', err => { |
| 338 | if (settled) return |
| 339 | settled = true |
| 340 | reject(err) |
| 341 | }) |
| 342 | }) |
| 343 | } |
| 344 | |
| 345 | export async function ripGrep( |
| 346 | args: string[], |
no test coverage detected