render method
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;
}
}