@lonu/stc
Version:
A tool for converting OpenApi/Swagger/Apifox into code.
269 lines (268 loc) • 11.5 kB
JavaScript
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _MultiProgressBar_end, _MultiProgressBar_startIndex, _MultiProgressBar_lastRows, _MultiProgressBar_bars;
import * as dntShim from "../../../../../_dnt.shims.js";
import { bgGreen, bgWhite, stripAnsiCode } from "./deps.js";
import { writeAll } from "./deps.js";
// import type { Writer } from "./deps.ts";
import { prettyTime } from "./time.js";
const isTerminal = dntShim.Deno.stdout.isTerminal;
/**
* MultiProgressBar multiple progress bars.
*/
export class MultiProgressBar {
/**
* Title, total, complete, incomplete, can also be set or changed in the render method
*
* - title Progress bar title, default: ''
* - width the displayed width of the progress, default: 50
* - complete completion character, default: colors.bgGreen(' '), can use any string
* - incomplete incomplete character, default: colors.bgWhite(' '), can use any string
* - clear clear the bar on completion, default: false
* - interval minimum time between updates in milliseconds, default: 16
* - display What is displayed and display order, default: ':bar :text :percent :time :completed/:total'
* - prettyTime Whether to pretty print time and eta
* - output Output stream, can be Deno.stdout or Deno.stderr, default is Deno.stdout
*/
constructor({ title = "", width = 50, complete = bgGreen(" "), incomplete = bgWhite(" "), clear = false, interval, display, prettyTime = false, output = dntShim.Deno.stdout, } = {}) {
Object.defineProperty(this, "width", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "complete", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "incomplete", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "clear", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "interval", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "display", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "prettyTime", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
_MultiProgressBar_end.set(this, false);
_MultiProgressBar_startIndex.set(this, 0);
_MultiProgressBar_lastRows.set(this, 0);
_MultiProgressBar_bars.set(this, []);
Object.defineProperty(this, "lastStr", {
enumerable: true,
configurable: true,
writable: true,
value: ""
});
Object.defineProperty(this, "start", {
enumerable: true,
configurable: true,
writable: true,
value: Date.now()
});
Object.defineProperty(this, "lastRenderTime", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "encoder", {
enumerable: true,
configurable: true,
writable: true,
value: new TextEncoder()
});
// private writer: WritableStreamDefaultWriter<Uint8Array>;
// private writer: Writer;
Object.defineProperty(this, "writer", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
if (title != "") {
__classPrivateFieldGet(this, _MultiProgressBar_bars, "f").push({ str: title });
__classPrivateFieldSet(this, _MultiProgressBar_startIndex, 1, "f");
}
this.width = width;
this.complete = complete;
this.incomplete = incomplete;
this.clear = clear;
this.interval = interval ?? 16;
this.display = display ?? ":bar :text :percent :time :completed/:total";
this.prettyTime = prettyTime;
// this.writer = output.writable.getWriter();
this.writer = output;
}
/**
* "render" the progress bar
*
* - `bars` progress bars
* - `completed` completed value
* - `total` optional, total number of ticks to complete, default: 100
* - `text` optional, text displayed per ProgressBar, default: ''
* - `complete` - optional, completion character
* - `incomplete` - optional, incomplete character
* - `prettyTimeOptions` - prettyTime options
*/
async render(bars) {
if (__classPrivateFieldGet(this, _MultiProgressBar_end, "f") || !isTerminal)
return;
const now = Date.now();
const ms = now - this.lastRenderTime;
this.lastRenderTime = now;
let end = true;
let index = __classPrivateFieldGet(this, _MultiProgressBar_startIndex, "f");
for (const { completed, total = 100, text = "", ...options } of bars) {
if (completed < 0) {
throw new Error(`completed must greater than or equal to 0`);
}
if (!Number.isInteger(total))
throw new Error(`total must be 'number'`);
if (__classPrivateFieldGet(this, _MultiProgressBar_bars, "f")[index] && __classPrivateFieldGet(this, _MultiProgressBar_bars, "f")[index].end) {
index++;
continue;
}
end = false;
const percent = ((completed / total) * 100).toFixed(2) + "%";
const time = this.prettyTime
? prettyTime(now - this.start, options.prettyTimeOptions)
: ((now - this.start) / 1000).toFixed(1) + "s";
const msEta = completed >= total
? 0
: (total / completed - 1) * (now - this.start);
const eta = completed == 0
? "-"
: this.prettyTime
? prettyTime(msEta, options.prettyTimeOptions)
: (msEta / 1000).toFixed(1) + "s";
// :bar :text :percent :time :completed/:total
let str = this.display
.replace(":text", text)
.replace(":time", time)
.replace(":eta", eta)
.replace(":percent", percent)
.replace(":completed", completed + "")
.replace(":total", total + "");
// compute the available space (non-zero) for the bar
const availableSpace = Math.max(0, this.ttyColumns - stripAnsiCode(str.replace(":bar", "")).length);
const width = Math.min(this.width, availableSpace);
// :bar
const completeLength = Math.round((width * completed) / total);
const complete = new Array(completeLength)
.fill(options.complete ?? this.complete)
.join("");
const incomplete = new Array(width - completeLength)
.fill(options.incomplete ?? this.incomplete)
.join("");
str = str.replace(":bar", complete + incomplete);
const strLen = stripAnsiCode(str).length;
if (__classPrivateFieldGet(this, _MultiProgressBar_bars, "f")[index] && str != __classPrivateFieldGet(this, _MultiProgressBar_bars, "f")[index].str) {
const lastStrLen = __classPrivateFieldGet(this, _MultiProgressBar_bars, "f")[index].strLen;
if (strLen < lastStrLen) {
str += " ".repeat(lastStrLen - strLen);
}
}
__classPrivateFieldGet(this, _MultiProgressBar_bars, "f")[index++] = {
str,
strLen,
end: completed >= total,
};
}
if (ms < this.interval && !end)
return;
const str = __classPrivateFieldGet(this, _MultiProgressBar_bars, "f").map((v) => v.str).join("\n");
if (str !== this.lastStr) {
await this.resetScreen();
await this.write(str);
this.lastStr = str;
__classPrivateFieldSet(this, _MultiProgressBar_lastRows, __classPrivateFieldGet(this, _MultiProgressBar_bars, "f").length, "f");
}
if (end)
await this.end();
}
/**
* end: end a progress bar.
* No need to call in most cases, unless you want to end before 100%
*/
async end() {
if (__classPrivateFieldGet(this, _MultiProgressBar_end, "f"))
return;
__classPrivateFieldSet(this, _MultiProgressBar_end, true, "f");
if (this.clear) {
await this.resetScreen();
}
else {
await this.breakLine();
}
await this.showCursor();
// this.writer.releaseLock();
}
/**
* interrupt the progress bar and write a message above it
*
* @param message The message to write
*/
async console(message) {
await this.resetScreen();
await this.write(`${message}`);
await this.breakLine();
await this.write(this.lastStr);
}
write(msg) {
return this.stdoutWrite(`${msg}\x1b[?25l`);
}
async resetScreen() {
if (__classPrivateFieldGet(this, _MultiProgressBar_lastRows, "f") > 0) {
await this.stdoutWrite("\x1b[" + (__classPrivateFieldGet(this, _MultiProgressBar_lastRows, "f") - 1) + "A\r\x1b[?0J");
}
}
get ttyColumns() {
if (!dntShim.Deno.stdout.isTerminal())
return 100;
return dntShim.Deno.consoleSize().columns;
}
breakLine() {
return this.stdoutWrite("\n");
}
stdoutWrite(msg) {
// return this.writer.write(this.encoder.encode(msg));
return writeAll(this.writer, this.encoder.encode(msg));
}
showCursor() {
return this.stdoutWrite("\x1b[?25h");
}
}
_MultiProgressBar_end = new WeakMap(), _MultiProgressBar_startIndex = new WeakMap(), _MultiProgressBar_lastRows = new WeakMap(), _MultiProgressBar_bars = new WeakMap();