Spaces:
Sleeping
Sleeping
File size: 6,852 Bytes
1070765 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | const _ETA = require('./eta');
const _Terminal = require('./terminal');
const _formatter = require('./formatter');
const _options = require('./options');
const _EventEmitter = require('events');
// Progress-Bar constructor
module.exports = class GenericBar extends _EventEmitter{
constructor(options){
super();
// store options and assign derived ones (instance specific)
this.options = _options.assignDerivedOptions(options);
// store terminal instance
this.terminal = (this.options.terminal) ? this.options.terminal : new _Terminal(this.options.stream);
// the current bar value
this.value = 0;
// bar start value (used for progress calculation)
this.startValue = 0;
// the end value of the bar
this.total = 100;
// last drawn string - only render on change!
this.lastDrawnString = null;
// start time (used for eta calculation)
this.startTime = null;
// stop time (used for duration calculation)
this.stopTime = null;
// last update time
this.lastRedraw = Date.now();
// default eta calculator (will be re-create on start)
this.eta = new _ETA(this.options.etaBufferLength, 0, 0);
// payload data
this.payload = {};
// progress bar active ?
this.isActive = false;
// use default formatter or custom one ?
this.formatter = (typeof this.options.format === 'function') ? this.options.format : _formatter;
}
// internal render function
render(forceRendering=false){
// formatter params
const params = {
progress: this.getProgress(),
eta: this.eta.getTime(),
startTime: this.startTime,
stopTime: this.stopTime,
total: this.total,
value: this.value,
maxWidth: this.terminal.getWidth()
};
// automatic eta update ? (long running processes)
if (this.options.etaAsynchronousUpdate){
this.updateETA();
}
// format string
const s = this.formatter(this.options, params, this.payload);
const forceRedraw = forceRendering || this.options.forceRedraw
// force redraw in notty-mode!
|| (this.options.noTTYOutput && !this.terminal.isTTY());
// string changed ? only trigger redraw on change!
if (forceRedraw || this.lastDrawnString != s){
// trigger event
this.emit('redraw-pre');
// set cursor to start of line
this.terminal.cursorTo(0, null);
// write output
this.terminal.write(s);
// clear to the right from cursor
this.terminal.clearRight();
// store string
this.lastDrawnString = s;
// set last redraw time
this.lastRedraw = Date.now();
// trigger event
this.emit('redraw-post');
}
}
// start the progress bar
start(total, startValue, payload){
// set initial values
this.value = startValue || 0;
this.total = (typeof total !== 'undefined' && total >= 0) ? total : 100;
// set start value for progress calculation
this.startValue = (startValue || 0);
// store payload (optional)
this.payload = payload || {};
// store start time for duration+eta calculation
this.startTime = Date.now();
// reset stop time for 're-start' scenario (used for duration calculation)
this.stopTime = null;
// reset string line buffer (redraw detection)
this.lastDrawnString = '';
// initialize eta buffer
this.eta = new _ETA(this.options.etaBufferLength, this.startTime, this.value);
// set flag
this.isActive = true;
// start event
this.emit('start', total, startValue);
}
// stop the bar
stop(){
// set flag
this.isActive = false;
// store stop timestamp to get total duration
this.stopTime = Date.now();
// stop event
this.emit('stop', this.total, this.value);
}
// update the bar value
// update(value, payload)
// update(payload)
update(arg0, arg1 = {}){
// value set ?
// update(value, [payload]);
if (typeof arg0 === 'number') {
// update value
this.value = arg0;
// add new value; recalculate eta
this.eta.update(Date.now(), arg0, this.total);
}
// extract payload
// update(value, payload)
// update(payload)
const payloadData = ((typeof arg0 === 'object') ? arg0 : arg1) || {};
// update event (before stop() is called)
this.emit('update', this.total, this.value);
// merge payload
for (const key in payloadData){
this.payload[key] = payloadData[key];
}
// limit reached ? autostop set ?
if (this.value >= this.getTotal() && this.options.stopOnComplete) {
this.stop();
}
}
// calculate the actual progress value
getProgress(){
// calculate the normalized current progress
let progress = (this.value/this.total);
// use relative progress calculation ? range between startValue and total is then used as 100%
// startValue (offset) is ignored for calculations
if (this.options.progressCalculationRelative){
progress = (this.value-this.startValue)/(this.total-this.startValue);
}
// handle NaN Errors caused by total=0. Set to complete in this case
if (isNaN(progress)){
progress = (this.options && this.options.emptyOnZero) ? 0.0 : 1.0;
}
// limiter
progress = Math.min(Math.max(progress, 0.0), 1.0);
return progress;
}
// update the bar value
// increment(delta, payload)
// increment(payload)
increment(arg0 = 1, arg1 = {}){
// increment([payload]) => step=1
// handle the use case when `step` is omitted but payload is passed
if (typeof arg0 === 'object') {
this.update(this.value + 1, arg0);
// increment([step=1], [payload={}])
}else{
this.update(this.value + arg0, arg1);
}
}
// get the total (limit) value
getTotal(){
return this.total;
}
// set the total (limit) value
setTotal(total){
if (typeof total !== 'undefined' && total >= 0){
this.total = total;
}
}
// force eta calculation update (long running processes)
updateETA(){
// add new value; recalculate eta
this.eta.update(Date.now(), this.value, this.total);
}
}
|