@lonu/stc
Version:
A tool for converting OpenApi/Swagger/Apifox into code.
298 lines (297 loc) • 11.6 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 _ProgressBar_end;
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";
export { MultiProgressBar } from "./multi.js";
const isTerminal = dntShim.Deno.stdout.isTerminal;
var Direction;
(function (Direction) {
Direction[Direction["left"] = 0] = "left";
Direction[Direction["right"] = 1] = "right";
Direction[Direction["all"] = 2] = "all";
})(Direction || (Direction = {}));
/**
* ProgressBar single progress bar.
*/
class ProgressBar {
/**
* Title, total, complete, incomplete, can also be set or changed in the render method
*
* - title Progress bar title, default: ''
* - total total number of ticks to complete,
* - 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: ':title :percent :bar :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 = "", total, width = 50, complete = bgGreen(" "), preciseBar = [], incomplete = bgWhite(" "), clear = false, interval = 16, display, prettyTime = false, output = dntShim.Deno.stdout, } = {}) {
Object.defineProperty(this, "title", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "total", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
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, "preciseBar", {
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
});
_ProgressBar_end.set(this, false);
Object.defineProperty(this, "lastStr", {
enumerable: true,
configurable: true,
writable: true,
value: ""
});
Object.defineProperty(this, "lastStrLen", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
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
});
this.title = title;
this.total = total;
this.width = width;
this.complete = complete;
this.preciseBar = preciseBar.concat(complete);
this.incomplete = incomplete;
this.clear = clear;
this.interval = interval;
this.display = display ??
":title :percent :bar :time :completed/:total :text";
this.prettyTime = prettyTime;
// this.writer = output.writable.getWriter();
this.writer = output;
}
/**
* "render" the progress bar
*
* - `completed` completed value
* - `options` optional parameters
* - `title` progress bar title
* - `total` total number of ticks to complete
* - `text` optional, custom text, default: ''
* - `complete` completion character, If you want to change at a certain moment. For example, it turns red at 20%
* - `incomplete` incomplete character, If you want to change at a certain moment. For example, it turns red at 20%
* - `prettyTimeOptions` prettyTime options
*/
async render(completed, options = {}) {
if (__classPrivateFieldGet(this, _ProgressBar_end, "f") || !isTerminal)
return;
if (completed < 0) {
throw new Error(`completed must greater than or equal to 0`);
}
const total = options.total ?? this.total ?? 100;
const now = Date.now();
const ms = now - this.lastRenderTime;
const end = completed >= total;
if (ms < this.interval && !end)
return;
this.lastRenderTime = now;
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";
const percent = ((completed / total) * 100).toFixed(2) + "%";
// :title :percent :bar :time :completed/:total
let str = this.display
.replace(":title", options.title ?? this.title)
.replace(":time", time)
.replace(":text", options.text ?? "")
.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);
const preciseBar = options.preciseBar ?? this.preciseBar;
const precision = preciseBar.length > 1;
// :bar
const completeLength = (width * completed) / total;
const roundedCompleteLength = Math.floor(completeLength);
let precise = "";
if (precision) {
const preciseLength = completeLength - roundedCompleteLength;
precise = end
? ""
: preciseBar[Math.floor(preciseBar.length * preciseLength)];
}
const complete = new Array(roundedCompleteLength)
.fill(options.complete ?? this.complete)
.join("");
const incomplete = new Array(Math.max(width - roundedCompleteLength - (precision ? 1 : 0), 0))
.fill(options.incomplete ?? this.incomplete)
.join("");
str = str.replace(":bar", complete + precise + incomplete);
if (str !== this.lastStr) {
const strLen = stripAnsiCode(str).length;
if (strLen < this.lastStrLen) {
str += " ".repeat(this.lastStrLen - strLen);
}
await this.write(str);
this.lastStr = str;
this.lastStrLen = strLen;
}
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, _ProgressBar_end, "f"))
return;
__classPrivateFieldSet(this, _ProgressBar_end, true, "f");
if (this.clear) {
await this.stdoutWrite("\r");
await this.clearLine();
}
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.clearLine();
await this.write(`${message}`);
await this.breakLine();
await this.write(this.lastStr);
}
write(msg) {
return this.stdoutWrite(`\r${msg}\x1b[?25l`);
}
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));
}
clearLine(direction = Direction.all) {
switch (direction) {
case Direction.all:
return this.stdoutWrite("\x1b[2K");
case Direction.left:
return this.stdoutWrite("\x1b[1K");
case Direction.right:
return this.stdoutWrite("\x1b[0K");
}
}
showCursor() {
return this.stdoutWrite("\x1b[?25h");
}
}
_ProgressBar_end = new WeakMap();
export default ProgressBar;