runStreaming function

Future<int> runStreaming(
  1. String executable,
  2. List<String> arguments, {
  3. String? workingDirectory,
  4. Map<String, String>? environment,
  5. String transform(
    1. String line
    )?,
})

Starts a process, streams both output channels, and returns its exit code.

Implementation

Future<int> runStreaming(
  String executable,
  List<String> arguments, {
  String? workingDirectory,
  Map<String, String>? environment,
  String Function(String line)? transform,
}) async {
  final Process process;
  try {
    process = await Process.start(
      executable,
      arguments,
      workingDirectory: workingDirectory,
      environment: environment,
    );
  } on ProcessException catch (error) {
    Console.error('Could not run $executable: ${error.message}');
    return 1;
  }

  Future<void> forward(Stream<List<int>> source, IOSink sink) async {
    await for (final line in source
        .transform(utf8.decoder)
        .transform(const LineSplitter())) {
      if (line.isEmpty) continue;
      sink.writeln(transform?.call(line) ?? line);
    }
  }

  final forwards = <Future<void>>[
    forward(process.stdout, stdout),
    forward(process.stderr, stderr),
  ];
  final exitCode = await process.exitCode;
  await Future.wait(forwards);
  return exitCode;
}