( args: string[], target: string, abortSignal: AbortSignal, onLines: (lines: string[]) => void, )
| 345 | * timeout, stderr is ignored; interactive callers own recovery. |
| 346 | */ |
| 347 | export async function ripGrepStream( |
| 348 | args: string[], |
| 349 | target: string, |
| 350 | abortSignal: AbortSignal, |
| 351 | onLines: (lines: string[]) => void, |
| 352 | ): Promise<void> { |
| 353 | await codesignRipgrepIfNecessary() |
| 354 | const { rgPath, rgArgs, argv0 } = ripgrepCommand() |
| 355 | |
| 356 | return new Promise<void>((resolve, reject) => { |
| 357 | const child = spawn(rgPath, [...rgArgs, ...args, target], { |
| 358 | argv0, |
| 359 | signal: abortSignal, |
| 360 | windowsHide: true, |
| 361 | stdio: ['ignore', 'pipe', 'ignore'], |
| 362 | }) |
| 363 | |
| 364 | const stripCR = (l: string) => (l.endsWith('\r') ? l.slice(0, -1) : l) |
| 365 | let remainder = '' |
| 366 | child.stdout?.on('data', (chunk: Buffer) => { |
| 367 | const data = remainder + chunk.toString() |
| 368 | const lines = data.split('\n') |
| 369 | remainder = lines.pop() ?? '' |
| 370 | if (lines.length) onLines(lines.map(stripCR)) |
| 371 | }) |
| 372 | |
| 373 | // On Windows, both 'close' and 'error' can fire for the same process. |
| 374 | let settled = false |
| 375 | child.on('close', code => { |
| 376 | if (settled) return |
| 377 | // Abort races close — don't flush a torn tail from a killed process. |
| 378 | // Promise still settles: spawn's signal option fires 'error' with |
| 379 | // AbortError → reject below. |
| 380 | if (abortSignal.aborted) return |
| 381 | settled = true |
| 382 | if (code === 0 || code === 1) { |
| 383 | if (remainder) onLines([stripCR(remainder)]) |
| 384 | resolve() |
| 385 | } else { |
| 386 | reject(new Error(`ripgrep exited with code ${code}`)) |
| 387 | } |
| 388 | }) |
| 389 | child.on('error', err => { |
| 390 | if (settled) return |
| 391 | settled = true |
| 392 | reject(err) |
| 393 | }) |
| 394 | }) |
| 395 | } |
| 396 | |
| 397 | export async function ripGrep( |
| 398 | args: string[], |
no test coverage detected