UNPKG

5.02 kBJavaScriptView Raw
1const _Terminal = require('./terminal');
2const _BarElement = require('./generic-bar');
3const _options = require('./options');
4const _EventEmitter = require('events');
5
6// Progress-Bar constructor
7module.exports = class MultiBar extends _EventEmitter{
8
9 constructor(options, preset){
10 super();
11
12 // list of bars
13 this.bars = [];
14
15 // parse+store options
16 this.options = _options.parse(options, preset);
17
18 // disable synchronous updates
19 this.options.synchronousUpdate = false;
20
21 // store terminal instance
22 this.terminal = (this.options.terminal) ? this.options.terminal : new _Terminal(this.options.stream);
23
24 // the update timer
25 this.timer = null;
26
27 // progress bar active ?
28 this.isActive = false;
29
30 // update interval
31 this.schedulingRate = (this.terminal.isTTY() ? this.options.throttleTime : this.options.notTTYSchedule);
32 }
33
34 // add a new bar to the stack
35 create(total, startValue, payload){
36 // progress updates are only visible in TTY mode!
37 if (this.options.noTTYOutput === false && this.terminal.isTTY() === false){
38 return;
39 }
40
41 // create new bar element
42 const bar = new _BarElement(this.options);
43
44 // store bar
45 this.bars.push(bar);
46
47 // multiprogress already active ?
48 if (!this.isActive){
49 // hide the cursor ?
50 if (this.options.hideCursor === true){
51 this.terminal.cursor(false);
52 }
53
54 // disable line wrpaping ?
55 if (this.options.linewrap === false){
56 this.terminal.lineWrapping(false);
57 }
58
59 // initialize update timer
60 this.timer = setTimeout(this.update.bind(this), this.schedulingRate);
61 }
62
63 // set flag
64 this.isActive = true;
65
66 // start progress bar
67 bar.start(total, startValue, payload);
68
69 // trigger event
70 this.emit('start');
71
72 // return new instance
73 return bar;
74 }
75
76 // remove a bar from the stack
77 remove(bar){
78 // find element
79 const index = this.bars.indexOf(bar);
80
81 // element found ?
82 if (index < 0){
83 return false;
84 }
85
86 // remove element
87 this.bars.splice(index, 1);
88
89 // force update
90 this.update();
91
92 // clear bottom
93 this.terminal.newline();
94 this.terminal.clearBottom();
95
96 return true;
97 }
98
99 // internal update routine
100 update(){
101 // stop timer
102 if (this.timer){
103 clearTimeout(this.timer);
104 this.timer = null;
105 }
106
107 // trigger event
108 this.emit('update-pre');
109
110 // reset cursor
111 this.terminal.cursorRelativeReset();
112
113 // trigger event
114 this.emit('redraw-pre');
115
116 // update each bar
117 for (let i=0; i< this.bars.length; i++){
118 // add new line ?
119 if (i > 0){
120 this.terminal.newline();
121 }
122
123 // render
124 this.bars[i].render();
125 }
126
127 // trigger event
128 this.emit('redraw-post');
129
130 // add new line in notty mode!
131 if (this.options.noTTYOutput && this.terminal.isTTY() === false){
132 this.terminal.newline();
133 this.terminal.newline();
134 }
135
136 // next update
137 this.timer = setTimeout(this.update.bind(this), this.schedulingRate);
138
139 // trigger event
140 this.emit('update-post');
141
142 // stop if stopOnComplete and all bars stopped
143 if (this.options.stopOnComplete && !this.bars.find(bar => bar.isActive)) {
144 this.stop();
145 }
146 }
147
148 stop(){
149
150 // stop timer
151 clearTimeout(this.timer);
152 this.timer = null;
153
154 // set flag
155 this.isActive = false;
156
157 // cursor hidden ?
158 if (this.options.hideCursor === true){
159 this.terminal.cursor(true);
160 }
161
162 // re-enable line wrpaping ?
163 if (this.options.linewrap === false){
164 this.terminal.lineWrapping(true);
165 }
166
167 // reset cursor
168 this.terminal.cursorRelativeReset();
169
170 // trigger event
171 this.emit('stop-pre-clear');
172
173 // clear line on complete ?
174 if (this.options.clearOnComplete){
175 // clear all bars
176 this.terminal.clearBottom();
177
178 // or show final progress ?
179 }else{
180 // update each bar
181 for (let i=0; i< this.bars.length; i++){
182 // add new line ?
183 if (i > 0){
184 this.terminal.newline();
185 }
186
187 // trigger final rendering
188 this.bars[i].render();
189
190 // stop
191 this.bars[i].stop();
192 }
193
194 // new line on complete
195 this.terminal.newline();
196 }
197
198 // trigger event
199 this.emit('stop');
200 }
201}