xprogress 0.19.2 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +100 -35
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -44,6 +44,7 @@ const globOpts = {
|
|
|
44
44
|
'color:bar:separator': '',
|
|
45
45
|
},
|
|
46
46
|
forceFirst: !1,
|
|
47
|
+
keepHeader: !1,
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
const defaultOptions = {
|
|
@@ -54,7 +55,7 @@ const defaultOptions = {
|
|
|
54
55
|
const streamOpts = {
|
|
55
56
|
...globOpts,
|
|
56
57
|
pulsate: false,
|
|
57
|
-
progress: {time:
|
|
58
|
+
progress: {time: 200, pulsate: false, infinite: !1, pulsateSkip: 15, pulsateLength: 15},
|
|
58
59
|
template: [
|
|
59
60
|
':{label}',
|
|
60
61
|
' |:{slot:bar}| [:3{slot:percentage}%] (:{slot:eta}) [:{speed}] [:{slot:size}/:{slot:size:total}]',
|
|
@@ -123,7 +124,8 @@ function parseBar(opts, fillable, percentage, headers = !opts.pulsate) {
|
|
|
123
124
|
let empty = fillable - filled;
|
|
124
125
|
let {filler, blank, header} = opts.bar;
|
|
125
126
|
[filled, empty] = [filled, empty].map(Math.floor);
|
|
126
|
-
[filler, blank] = [filler, blank].map(content => (
|
|
127
|
+
[filler, blank] = [filler, blank].map(content => (typeof content === 'string' ? content : '?'));
|
|
128
|
+
if (!opts.keepHeader && headers && empty === 0) (filled += header.length), (headers = null);
|
|
127
129
|
return stringd(
|
|
128
130
|
[
|
|
129
131
|
`:{color:bar:filled}${filler.repeat(filled)}`,
|
|
@@ -165,6 +167,28 @@ function pulsateBar(bar, slots, skip, sep = '') {
|
|
|
165
167
|
return stack.map(({fillable, percentage}) => parseBar(bar.opts, fillable, percentage, false));
|
|
166
168
|
}
|
|
167
169
|
|
|
170
|
+
// eslint-disable-next-line no-control-regex
|
|
171
|
+
const ANSI_RE = /\x1b\[[^m]*m/g;
|
|
172
|
+
function trimLine(line, cols) {
|
|
173
|
+
let visible = 0;
|
|
174
|
+
let i = 0;
|
|
175
|
+
let result = '';
|
|
176
|
+
while (i < line.length) {
|
|
177
|
+
ANSI_RE.lastIndex = i;
|
|
178
|
+
const ansi = ANSI_RE.exec(line);
|
|
179
|
+
if (ansi && ansi.index === i) {
|
|
180
|
+
result += ansi[0];
|
|
181
|
+
i += ansi[0].length;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (visible >= cols) break;
|
|
185
|
+
result += line[i];
|
|
186
|
+
visible++;
|
|
187
|
+
i++;
|
|
188
|
+
}
|
|
189
|
+
return visible < line.replace(ANSI_RE, '').length ? `${result}\x1b[0m` : result;
|
|
190
|
+
}
|
|
191
|
+
|
|
168
192
|
class ProgressGen extends EventEmitter {}
|
|
169
193
|
|
|
170
194
|
export default class ProgressBar {
|
|
@@ -213,6 +237,20 @@ export default class ProgressBar {
|
|
|
213
237
|
delete this.opts.label;
|
|
214
238
|
delete this.opts.append;
|
|
215
239
|
delete this.opts.length;
|
|
240
|
+
this.#resizeHandler = () => {
|
|
241
|
+
if (!this.hasBarredOnce || this.isEnded) return;
|
|
242
|
+
const stdout = this.cores.stdout;
|
|
243
|
+
this.#resizing = true;
|
|
244
|
+
stdout.moveCursor(0, -(this.oldBar.length - 1));
|
|
245
|
+
stdout.cursorTo(0);
|
|
246
|
+
stdout.clearScreenDown();
|
|
247
|
+
clearTimeout(this.#resizeTimer);
|
|
248
|
+
this.#resizeTimer = setTimeout(() => {
|
|
249
|
+
this.#resizing = false;
|
|
250
|
+
this.draw(this.oldBar);
|
|
251
|
+
}, 100);
|
|
252
|
+
};
|
|
253
|
+
this.cores.stdout?.on('resize', this.#resizeHandler);
|
|
216
254
|
}
|
|
217
255
|
|
|
218
256
|
/**
|
|
@@ -384,19 +422,28 @@ export default class ProgressBar {
|
|
|
384
422
|
* @param {String|Object} [template] The template to use on the drawn progress bar or an array of predrawn progressbar from `this.constructBar` like `this.oldBar`
|
|
385
423
|
*/
|
|
386
424
|
draw(template) {
|
|
425
|
+
if (!Array.isArray(template))
|
|
426
|
+
this.cores.append = this.cores.append.filter(block => !(block.bar.opts.clean && block.bar.isComplete()));
|
|
387
427
|
const result = Array.isArray(template)
|
|
388
428
|
? template
|
|
389
429
|
: [
|
|
390
430
|
...this.constructBar(template).split('\n'),
|
|
391
431
|
...this.cores.append.map(block => block.bar.constructBar(block.inherit ? template : null)),
|
|
392
432
|
];
|
|
433
|
+
const prevLength = this.hasBarredOnce ? this.oldBar.length : 0;
|
|
393
434
|
this.oldBar = result;
|
|
394
|
-
this
|
|
435
|
+
if (!this.#resizing) {
|
|
436
|
+
this.#printLines(result, this.justLogged, prevLength ? prevLength - 1 : 0);
|
|
437
|
+
this.justLogged = false;
|
|
438
|
+
}
|
|
395
439
|
this.hasBarredOnce = !0;
|
|
396
440
|
return this;
|
|
397
441
|
}
|
|
398
442
|
|
|
399
443
|
#flipperCount = 0;
|
|
444
|
+
#resizeHandler = null;
|
|
445
|
+
#resizeTimer = null;
|
|
446
|
+
#resizing = false;
|
|
400
447
|
|
|
401
448
|
constructBar(template) {
|
|
402
449
|
const forcedFirst = [
|
|
@@ -446,45 +493,40 @@ export default class ProgressBar {
|
|
|
446
493
|
return stringd(stringd(str, template), variables);
|
|
447
494
|
}
|
|
448
495
|
|
|
496
|
+
#printLines(lines, dontClean, addons = 0, ending = false) {
|
|
497
|
+
const stdout = this.cores.stdout;
|
|
498
|
+
if (!dontClean) {
|
|
499
|
+
// check https://github.com/freeall/single-line-log/blob/515b3b99b699396c2ad5f937e4b490b6f9fbff0e/index.js#L1-L3
|
|
500
|
+
stdout.moveCursor(0, -addons);
|
|
501
|
+
stdout.cursorTo(0);
|
|
502
|
+
stdout.clearScreenDown();
|
|
503
|
+
}
|
|
504
|
+
const cols = stdout.columns;
|
|
505
|
+
// eslint-disable-next-line no-control-regex
|
|
506
|
+
const strip = this.opts.bar.colorize ? l => l : l => l.replace(/\x1b\[\d+m/g, '');
|
|
507
|
+
stdout.write(
|
|
508
|
+
`${dontClean && ending && (addons || this.hasBarredOnce) ? '\n' : ''}${lines
|
|
509
|
+
.map(line => trimLine(strip(line), cols))
|
|
510
|
+
.join('\n')}`,
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
|
|
449
514
|
/**
|
|
450
515
|
* Print a message after a bar `draw` interrupt
|
|
451
|
-
* @param {'bar'|'end'} type Type of bar print or the first part of the printer
|
|
452
516
|
* @param {any[]} content The contents to be formatted
|
|
453
517
|
*/
|
|
454
518
|
print(type, ...content) {
|
|
455
|
-
|
|
519
|
+
if (this.isChild) return this.cores.parent.print(type, ...content);
|
|
456
520
|
type = format(type);
|
|
457
|
-
if (!
|
|
458
|
-
const cleanWrite = function cleanWrite(arr, dontClean, addons = 0, ending = false, normie = false) {
|
|
459
|
-
if (!dontClean) {
|
|
460
|
-
// check https://github.com/freeall/single-line-log/blob/515b3b99b699396c2ad5f937e4b490b6f9fbff0e/index.js#L1-L3
|
|
461
|
-
self.cores.stdout.moveCursor(0, -addons);
|
|
462
|
-
self.cores.stdout.cursorTo(0);
|
|
463
|
-
self.cores.stdout.clearScreenDown();
|
|
464
|
-
}
|
|
465
|
-
(normie ? process.stdout : self.cores.stdout).write(
|
|
466
|
-
`${dontClean && ending && addons ? '\n' : ''}${self
|
|
467
|
-
.parseString(format(...arr))
|
|
468
|
-
// eslint-disable-next-line no-control-regex
|
|
469
|
-
.replace(self.opts.bar.colorize ? '' : /\x1b\[\d+m/g, '')}`,
|
|
470
|
-
);
|
|
471
|
-
};
|
|
472
|
-
let addonPack;
|
|
521
|
+
if (!this.cores.stdout.isTTY) throw Error("Can't draw or print progressBar interrupts with piped output");
|
|
473
522
|
const addons = this.hasBarredOnce && !this.justLogged ? this.oldBar.length - 1 : 0;
|
|
523
|
+
const lines = this.parseString(
|
|
524
|
+
type === 'end' ? format(...content) : format((type.startsWith(':') && type.slice(1)) || type, ...content, '\n'),
|
|
525
|
+
).split('\n');
|
|
474
526
|
this.justLogged =
|
|
475
|
-
type === '
|
|
476
|
-
? !!
|
|
477
|
-
: (
|
|
478
|
-
? !!cleanWrite(content, this.justLogged, this.hasBarredOnce ? addonPack[1] : addons)
|
|
479
|
-
: type === 'end'
|
|
480
|
-
? !!cleanWrite(content, !this.opts.clean, addons, true, true)
|
|
481
|
-
: !cleanWrite(
|
|
482
|
-
[(type.startsWith(':') && `${type.slice(1)}`) || type, ...content, '\n'],
|
|
483
|
-
this.justLogged,
|
|
484
|
-
addons,
|
|
485
|
-
false,
|
|
486
|
-
true,
|
|
487
|
-
);
|
|
527
|
+
type === 'end'
|
|
528
|
+
? !!this.#printLines(lines, !this.opts.clean, addons, true)
|
|
529
|
+
: !this.#printLines(lines, this.justLogged, addons);
|
|
488
530
|
if (this.justLogged && this.hasBarredOnce) this.draw(this.oldBar);
|
|
489
531
|
return this;
|
|
490
532
|
}
|
|
@@ -495,8 +537,14 @@ export default class ProgressBar {
|
|
|
495
537
|
*/
|
|
496
538
|
end(...message) {
|
|
497
539
|
if (!this.isEnded) {
|
|
498
|
-
if (message.length)
|
|
540
|
+
if (message.length) {
|
|
541
|
+
if (this.isChild) this.cores.parent.print(...message);
|
|
542
|
+
else this.print('end', ...message);
|
|
543
|
+
}
|
|
499
544
|
this.isEnded = !0;
|
|
545
|
+
this.#resizing = false;
|
|
546
|
+
clearTimeout(this.#resizeTimer);
|
|
547
|
+
this.cores.stdout?.off('resize', this.#resizeHandler);
|
|
500
548
|
}
|
|
501
549
|
return this;
|
|
502
550
|
}
|
|
@@ -515,6 +563,21 @@ export default class ProgressBar {
|
|
|
515
563
|
*/
|
|
516
564
|
drop() {}
|
|
517
565
|
|
|
566
|
+
/**
|
|
567
|
+
* Insert a bar immediately after an existing appended bar
|
|
568
|
+
* @param {ProgressBar} anchor The bar after which to insert
|
|
569
|
+
* @param {ProgressBar} bar The bar to insert
|
|
570
|
+
* @param {Boolean} inherit Whether or not to inherit bar templates from `this`
|
|
571
|
+
*/
|
|
572
|
+
insertAfter(anchor, bar, inherit = !1) {
|
|
573
|
+
const idx = this.cores.append.findIndex(a => a.bar === anchor);
|
|
574
|
+
if (idx === -1) throw Error('Anchor bar not found');
|
|
575
|
+
const tail = this.cores.append.splice(idx + 1);
|
|
576
|
+
this.append(bar, inherit);
|
|
577
|
+
this.cores.append.push(...tail);
|
|
578
|
+
return this;
|
|
579
|
+
}
|
|
580
|
+
|
|
518
581
|
/**
|
|
519
582
|
* Append the specified bar after `this`
|
|
520
583
|
* @param {ProgressBar} bar The bar to be appended
|
|
@@ -524,6 +587,8 @@ export default class ProgressBar {
|
|
|
524
587
|
if (!ProgressBar.isBar(bar) && !bar.opts.template) throw Error('The Parameter <bar> is not a progressbar or a hanger');
|
|
525
588
|
this.cores.append.push({bar, inherit});
|
|
526
589
|
bar.cores.isKid = !0;
|
|
590
|
+
bar.cores.parent = this;
|
|
591
|
+
bar.cores.stdout?.off('resize', bar.#resizeHandler);
|
|
527
592
|
return this;
|
|
528
593
|
}
|
|
529
594
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xprogress",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Dynamic, Flexible, extensible progressive CLI bar for the terminal built with NodeJS",
|
|
5
5
|
"exports": "./index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"progress-stream": "^2.0.0",
|
|
51
51
|
"speedometer": "^1.1.0",
|
|
52
52
|
"stringd": "^2.2.0",
|
|
53
|
-
"stringd-colors": "^1.
|
|
53
|
+
"stringd-colors": "^1.11.0",
|
|
54
54
|
"xbytes": "^1.6.1"
|
|
55
55
|
}
|
|
56
56
|
}
|