xargs method

Script xargs(
  1. FutureOr<void> callback(
    1. List<String> args
    ), {
  2. int? maxArgs,
  3. String? name,
  4. void onSignal(
    1. ProcessSignal signal
    )?,
})

Passes the strings emitted by this stream as arguments to callback.

The callback is invoked within a Script.capture block, so any stdout or stderr it emits will be piped into the returned Script's stdout and stderr streams. If any callback throws an error or starts a Script that fails with a non-zero exit code, the returned Script will fail as well.

Waits for each callback to complete before executing the next one. While it's possible for callbacks to run in parallel by returning before the processing is complete, this is not recommended, as it will cause error and output streams from multiple callbacks to become mangled and could cause later callbacks to be executed even if earlier ones failed.

If maxArgs is passed, this invokes callback multiple times, passing at most maxArgs arguments to each invocation. Otherwise, it passes all arguments to a single invocation.

If name is passed, it's used as the name of the spawned script.

Script.kill closes the input stream. It returns true if the stream was interrupted and the script exits with Script.exitCode 143, or false if the stream was already closed.

The callback can't be interrupted by calling kill, but the onSignal callback allows capturing those signals so the callback may react appropriately. Calling kill returns true even without an onSignal callback if the stream is interrupted.

See also xargs in package:cli_script/cli_script.dart, which takes arguments from stdin rather than from this string stream.

Implementation

Script xargs(FutureOr<void> callback(List<String> args),
    {int? maxArgs, String? name, void onSignal(ProcessSignal signal)?}) {
  if (maxArgs != null && maxArgs < 1) {
    throw RangeError.range(maxArgs, 1, null, 'maxArgs');
  }

  var signalCloser = StreamCloser<String>();
  var self = transform(signalCloser);
  var chunks =
      maxArgs != null ? self.slices(maxArgs) : self.toList().asStream();

  return Script.capture(
      (_) async {
        await for (var chunk in chunks) {
          if (signalCloser.isClosed) break;
          await callback(chunk);
        }
        if (signalCloser.isClosed) {
          throw ScriptException(name ?? 'xargs', 143);
        }
      },
      name: name,
      onSignal: (signal) {
        signalCloser.close();
        if (onSignal != null) onSignal(signal);
        return true;
      });
}