UNPKG

@lonu/stc

Version:

A tool for converting OpenApi/Swagger/Apifox into code.

269 lines (268 loc) 11.5 kB
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();