streamProcess function

Stream<String> streamProcess(
  1. String executable,
  2. List<String> args, {
  3. String? workingDirectory,
})

Runs executable and returns a stream of its interleaved stdout/stderr.

Implementation

Stream<String> streamProcess(String executable, List<String> args, {String? workingDirectory}) {
  final controller = StreamController<String>();
  Process? process;
  StreamSubscription? sigintSub;
  StreamSubscription? sigtermSub;

  controller.onListen = () async {
    try {
      process = await Process.start(executable, args, workingDirectory: workingDirectory);

      if (!Platform.isWindows) {
        sigintSub = ProcessSignal.sigint.watch().listen((_) {
          process?.kill(ProcessSignal.sigint);
          exit(130);
        });
        sigtermSub = ProcessSignal.sigterm.watch().listen((_) {
          process?.kill(ProcessSignal.sigterm);
          exit(143);
        });
      }

      int active = 2;
      void done() {
        active--;
        if (active == 0) {
          sigintSub?.cancel();
          sigtermSub?.cancel();
          controller.close();
        }
      }

      process!.stdout.transform(utf8.decoder).transform(const LineSplitter()).listen(
        controller.add,
        onDone: done,
        onError: controller.addError,
      );
      process!.stderr.transform(utf8.decoder).transform(const LineSplitter()).listen(
        controller.add,
        onDone: done,
        onError: controller.addError,
      );
    } catch (e) {
      controller.addError(e);
      controller.close();
    }
  };

  controller.onCancel = () {
    sigintSub?.cancel();
    sigtermSub?.cancel();
    process?.kill();
  };

  return controller.stream;
}