botbook/node_modules/cli-progress/lib/multi-bar.js

251 lines
6.4 KiB
JavaScript
Raw Normal View History

2024-09-04 13:13:15 -03:00
const _Terminal = require('./terminal');
const _BarElement = require('./generic-bar');
const _options = require('./options');
const _EventEmitter = require('events');
// Progress-Bar constructor
module.exports = class MultiBar extends _EventEmitter{
constructor(options, preset){
super();
// list of bars
this.bars = [];
// parse+store options
this.options = _options.parse(options, preset);
// disable synchronous updates
this.options.synchronousUpdate = false;
// store terminal instance
this.terminal = (this.options.terminal) ? this.options.terminal : new _Terminal(this.options.stream);
// the update timer
this.timer = null;
// progress bar active ?
this.isActive = false;
// update interval
this.schedulingRate = (this.terminal.isTTY() ? this.options.throttleTime : this.options.notTTYSchedule);
// logging output buffer
this.loggingBuffer = [];
// callback used for gracefulExit
this.sigintCallback = null;
}
// add a new bar to the stack
create(total, startValue, payload, barOptions={}){
// create new bar element and merge global options + overrides
// use the same global terminal instance for all instances
const bar = new _BarElement(Object.assign(
{},
// global options
this.options,
// terminal instance
{
terminal: this.terminal
},
// overrides
barOptions,
));
// store bar
this.bars.push(bar);
// progress updates are only visible in TTY mode!
if (this.options.noTTYOutput === false && this.terminal.isTTY() === false){
return bar;
}
// add handler to restore cursor settings (stop the bar) on SIGINT/SIGTERM ?
if (this.sigintCallback === null && this.options.gracefulExit){
this.sigintCallback = this.stop.bind(this);
process.once('SIGINT', this.sigintCallback);
process.once('SIGTERM', this.sigintCallback);
}
// multiprogress already active ?
if (!this.isActive){
// hide the cursor ?
if (this.options.hideCursor === true){
this.terminal.cursor(false);
}
// disable line wrapping ?
if (this.options.linewrap === false){
this.terminal.lineWrapping(false);
}
// initialize update timer
this.timer = setTimeout(this.update.bind(this), this.schedulingRate);
}
// set flag
this.isActive = true;
// start progress bar
bar.start(total, startValue, payload);
// trigger event
this.emit('start');
// return new instance
return bar;
}
// remove a bar from the stack
remove(bar){
// find element
const index = this.bars.indexOf(bar);
// element found ?
if (index < 0){
return false;
}
// remove element
this.bars.splice(index, 1);
// force update
this.update();
// clear bottom
this.terminal.newline();
this.terminal.clearBottom();
return true;
}
// internal update routine
update(){
// stop timer
if (this.timer){
clearTimeout(this.timer);
this.timer = null;
}
// trigger event
this.emit('update-pre');
// reset cursor
this.terminal.cursorRelativeReset();
// trigger event
this.emit('redraw-pre');
// content within logging buffer ?
if (this.loggingBuffer.length > 0){
this.terminal.clearLine();
// flush logging buffer and write content to terminal
while (this.loggingBuffer.length > 0){
this.terminal.write(this.loggingBuffer.shift(), true);
}
}
// update each bar
for (let i=0; i< this.bars.length; i++){
// add new line ?
if (i > 0){
this.terminal.newline();
}
// render
this.bars[i].render();
}
// trigger event
this.emit('redraw-post');
// add new line in notty mode!
if (this.options.noTTYOutput && this.terminal.isTTY() === false){
this.terminal.newline();
this.terminal.newline();
}
// next update
this.timer = setTimeout(this.update.bind(this), this.schedulingRate);
// trigger event
this.emit('update-post');
// stop if stopOnComplete and all bars stopped
if (this.options.stopOnComplete && !this.bars.find(bar => bar.isActive)) {
this.stop();
}
}
stop(){
// stop timer
clearTimeout(this.timer);
this.timer = null;
// remove sigint listener
if (this.sigintCallback){
process.removeListener('SIGINT', this.sigintCallback);
process.removeListener('SIGTERM', this.sigintCallback);
this.sigintCallback = null;
}
// set flag
this.isActive = false;
// cursor hidden ?
if (this.options.hideCursor === true){
this.terminal.cursor(true);
}
// re-enable line wrpaping ?
if (this.options.linewrap === false){
this.terminal.lineWrapping(true);
}
// reset cursor
this.terminal.cursorRelativeReset();
// trigger event
this.emit('stop-pre-clear');
// clear line on complete ?
if (this.options.clearOnComplete){
// clear all bars
this.terminal.clearBottom();
// or show final progress ?
}else{
// update each bar
for (let i=0; i< this.bars.length; i++){
// add new line ?
if (i > 0){
this.terminal.newline();
}
// trigger final rendering
this.bars[i].render();
// stop
this.bars[i].stop();
}
// new line on complete
this.terminal.newline();
}
// trigger event
this.emit('stop');
}
log(s){
// push content into logging buffer
this.loggingBuffer.push(s);
}
}