capture<R> function

Future<Progress> capture<R>(
  1. Future<R> action(), {
  2. Progress? progress,
})

Run code in a zone which traps calls to print and printerr redirecting them to the passed progress. If no progress is passed then then both print and printerr output is surpressed.

Implementation

Future<Progress> capture<R>(Future<R> Function() action,
    {Progress? progress}) async {
  progress ??= Progress.devNull();

  /// overload printerr so we can trap it.
  final zoneValues = <String, CaptureZonePrintErr>{
    'printerr': (line) {
      if (line != null) {
        progress!.addToStderr(line);
      }
    }
  };

  final zoneCompleter = Completer<R>();
  runZonedGuarded(
    /// runZone takes a sync method but we need
    /// an async body s we can await the real [body]
    /// method in [_body]
    /// We then use the zoneCompleter to wait for the body to complete.
    () => _unawaited(_body(action, zoneCompleter)),
    (e, st) {
      if (!zoneCompleter.isCompleted) {
        zoneCompleter.complete(null);
      }
    },
    zoneValues: zoneValues,
    zoneSpecification: ZoneSpecification(
      print: (self, parent, zone, line) => progress!.addToStdout(line),
    ),
  );

  await zoneCompleter.future;

  // give the stream listeners a chance to flush.
  await _flush(progress);

  return progress;
}