render method

dynamic render(
  1. Map<String, String>? tokens
)

Method to render the progress bar with optional tokens to place in the progress bar's format field.

Implementation

render(Map<String, String>? tokens) {
  if (!stdout.hasTerminal) return;

  var ratio = this.curr / this.total;
  ratio = min(max(ratio, 0.0), 1.0);

  var percent = ratio * 100;
  var elapsed = new DateTime.now().difference(this.start).inMilliseconds;
  var eta = (percent == 100) ? 0 : elapsed * (this.total / this.curr - 1);

  /* populate the bar template with percentages and timestamps */
  var str = this
      .format
      .replaceAll(':current', this.curr.toString())
      .replaceAll(':total', this.total.toString())
      .replaceAll(':elapsed',
          elapsed.isNaN ? '0.0' : (elapsed / 1000).toStringAsFixed(1))
      .replaceAll(
          ':eta',
          (eta.isNaN || !eta.isFinite)
              ? '0.0'
              : (eta / 1000).toStringAsFixed(1))
      .replaceAll(':percent', percent.toStringAsFixed(0) + '%');

  /* compute the available space (non-zero) for the bar */
  var availableSpace =
      max(0, stdout.terminalColumns - str.replaceAll(':bar', '').length);
  var width = min(this.width, availableSpace);

  /* the following assumes the user has one ':bar' token */
  var completeLength = (width * ratio).round();
  var completeStr =
      new List<String>.filled(completeLength, this.completeChar).join();
  var incompleteStr =
      new List<String>.filled(width - completeLength, this.incompleteChar)
          .join();

  /* fill in the actual progress bar */
  str = str.replaceAll(':bar', completeStr + incompleteStr);

  /* replace the extra tokens */
  if (tokens != null && tokens.isNotEmpty) {
    tokens.forEach((key, val) {
      str = str.replaceAll(':' + key, val);
    });
  }

  if (this.lastDraw != str) {
    stdout.writeCharCode(13); // output carriage return
    stdout.write(str);
    this.lastDraw = str;
  }
}