UNPKG

@visulima/ansi

Version:

ANSI escape codes for some terminal swag.

337 lines (330 loc) 10.7 kB
import process$2 from 'node:process'; var __defProp$2 = Object.defineProperty; var __name$2 = (target, value) => __defProp$2(target, "name", { value, configurable: true }); const copyProperty = /* @__PURE__ */ __name$2((to, from, property, ignoreNonConfigurable) => { if (property === "length" || property === "prototype") { return; } if (property === "arguments" || property === "caller") { return; } const toDescriptor = Object.getOwnPropertyDescriptor(to, property); const fromDescriptor = Object.getOwnPropertyDescriptor(from, property); if (!canCopyProperty(toDescriptor, fromDescriptor) && ignoreNonConfigurable) { return; } Object.defineProperty(to, property, fromDescriptor); }, "copyProperty"); const canCopyProperty = /* @__PURE__ */ __name$2(function(toDescriptor, fromDescriptor) { return toDescriptor === void 0 || toDescriptor.configurable || toDescriptor.writable === fromDescriptor.writable && toDescriptor.enumerable === fromDescriptor.enumerable && toDescriptor.configurable === fromDescriptor.configurable && (toDescriptor.writable || toDescriptor.value === fromDescriptor.value); }, "canCopyProperty"); const changePrototype = /* @__PURE__ */ __name$2((to, from) => { const fromPrototype = Object.getPrototypeOf(from); if (fromPrototype === Object.getPrototypeOf(to)) { return; } Object.setPrototypeOf(to, fromPrototype); }, "changePrototype"); const wrappedToString = /* @__PURE__ */ __name$2((withName, fromBody) => `/* Wrapped ${withName}*/ ${fromBody}`, "wrappedToString"); const toStringDescriptor = Object.getOwnPropertyDescriptor(Function.prototype, "toString"); const toStringName = Object.getOwnPropertyDescriptor(Function.prototype.toString, "name"); const changeToString = /* @__PURE__ */ __name$2((to, from, name) => { const withName = name === "" ? "" : `with ${name.trim()}() `; const newToString = wrappedToString.bind(null, withName, from.toString()); Object.defineProperty(newToString, "name", toStringName); const { writable, enumerable, configurable } = toStringDescriptor; Object.defineProperty(to, "toString", { value: newToString, writable, enumerable, configurable }); }, "changeToString"); function mimicFunction(to, from, { ignoreNonConfigurable = false } = {}) { const { name } = to; for (const property of Reflect.ownKeys(from)) { copyProperty(to, from, property, ignoreNonConfigurable); } changePrototype(to, from); changeToString(to, from, name); return to; } __name$2(mimicFunction, "mimicFunction"); var __defProp$1 = Object.defineProperty; var __name$1 = (target, value) => __defProp$1(target, "name", { value, configurable: true }); const calledFunctions = /* @__PURE__ */ new WeakMap(); const onetime = /* @__PURE__ */ __name$1((function_, options = {}) => { if (typeof function_ !== "function") { throw new TypeError("Expected a function"); } let returnValue; let callCount = 0; const functionName = function_.displayName || function_.name || "<anonymous>"; const onetime2 = /* @__PURE__ */ __name$1(function(...arguments_) { calledFunctions.set(onetime2, ++callCount); if (callCount === 1) { returnValue = function_.apply(this, arguments_); function_ = void 0; } else if (options.throw === true) { throw new Error(`Function \`${functionName}\` can only be called once`); } return returnValue; }, "onetime"); mimicFunction(onetime2, function_); calledFunctions.set(onetime2, callCount); return onetime2; }, "onetime"); onetime.callCount = (function_) => { if (!calledFunctions.has(function_)) { throw new Error(`The given function \`${function_.name}\` is not wrapped by the \`onetime\` package`); } return calledFunctions.get(function_); }; const signals = []; signals.push("SIGHUP", "SIGINT", "SIGTERM"); if (process.platform !== "win32") { signals.push( "SIGALRM", "SIGABRT", "SIGVTALRM", "SIGXCPU", "SIGXFSZ", "SIGUSR2", "SIGTRAP", "SIGSYS", "SIGQUIT", "SIGIOT" // should detect profiler and enable/disable accordingly. // see #21 // 'SIGPROF' ); } if (process.platform === "linux") { signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT"); } var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); const processOk = /* @__PURE__ */ __name((process2) => !!process2 && true && typeof process2.removeListener === "function" && typeof process2.emit === "function" && typeof process2.reallyExit === "function" && typeof process2.listeners === "function" && typeof process2.kill === "function" && typeof process2.pid === "number" && typeof process2.on === "function", "processOk"); const kExitEmitter = Symbol.for("signal-exit emitter"); const global = globalThis; const ObjectDefineProperty = Object.defineProperty.bind(Object); class Emitter { static { __name(this, "Emitter"); } emitted = { afterExit: false, exit: false }; listeners = { afterExit: [], exit: [] }; count = 0; id = Math.random(); constructor() { if (global[kExitEmitter]) { return global[kExitEmitter]; } ObjectDefineProperty(global, kExitEmitter, { value: this, writable: false, enumerable: false, configurable: false }); } on(ev, fn) { this.listeners[ev].push(fn); } removeListener(ev, fn) { const list = this.listeners[ev]; const i = list.indexOf(fn); if (i === -1) { return; } if (i === 0 && list.length === 1) { list.length = 0; } else { list.splice(i, 1); } } emit(ev, code, signal) { if (this.emitted[ev]) { return false; } this.emitted[ev] = true; let ret = false; for (const fn of this.listeners[ev]) { ret = fn(code, signal) === true || ret; } if (ev === "exit") { ret = this.emit("afterExit", code, signal) || ret; } return ret; } } class SignalExitBase { static { __name(this, "SignalExitBase"); } } const signalExitWrap = /* @__PURE__ */ __name((handler) => { return { onExit(cb, opts) { return handler.onExit(cb, opts); }, load() { return handler.load(); }, unload() { return handler.unload(); } }; }, "signalExitWrap"); class SignalExitFallback extends SignalExitBase { static { __name(this, "SignalExitFallback"); } onExit() { return () => { }; } load() { } unload() { } } class SignalExit extends SignalExitBase { static { __name(this, "SignalExit"); } // "SIGHUP" throws an `ENOSYS` error on Windows, // so use a supported signal instead /* c8 ignore start */ #hupSig = process$1.platform === "win32" ? "SIGINT" : "SIGHUP"; /* c8 ignore stop */ #emitter = new Emitter(); #process; #originalProcessEmit; #originalProcessReallyExit; #sigListeners = {}; #loaded = false; constructor(process2) { super(); this.#process = process2; this.#sigListeners = {}; for (const sig of signals) { this.#sigListeners[sig] = () => { const listeners = this.#process.listeners(sig); let { count } = this.#emitter; const p = process2; if (typeof p.__signal_exit_emitter__ === "object" && typeof p.__signal_exit_emitter__.count === "number") { count += p.__signal_exit_emitter__.count; } if (listeners.length === count) { this.unload(); const ret = this.#emitter.emit("exit", null, sig); const s = sig === "SIGHUP" ? this.#hupSig : sig; if (!ret) process2.kill(process2.pid, s); } }; } this.#originalProcessReallyExit = process2.reallyExit; this.#originalProcessEmit = process2.emit; } onExit(cb, opts) { if (!processOk(this.#process)) { return () => { }; } if (this.#loaded === false) { this.load(); } const ev = opts?.alwaysLast ? "afterExit" : "exit"; this.#emitter.on(ev, cb); return () => { this.#emitter.removeListener(ev, cb); if (this.#emitter.listeners["exit"].length === 0 && this.#emitter.listeners["afterExit"].length === 0) { this.unload(); } }; } load() { if (this.#loaded) { return; } this.#loaded = true; this.#emitter.count += 1; for (const sig of signals) { try { const fn = this.#sigListeners[sig]; if (fn) this.#process.on(sig, fn); } catch (_) { } } this.#process.emit = (ev, ...a) => { return this.#processEmit(ev, ...a); }; this.#process.reallyExit = (code) => { return this.#processReallyExit(code); }; } unload() { if (!this.#loaded) { return; } this.#loaded = false; signals.forEach((sig) => { const listener = this.#sigListeners[sig]; if (!listener) { throw new Error("Listener not defined for signal: " + sig); } try { this.#process.removeListener(sig, listener); } catch (_) { } }); this.#process.emit = this.#originalProcessEmit; this.#process.reallyExit = this.#originalProcessReallyExit; this.#emitter.count -= 1; } #processReallyExit(code) { if (!processOk(this.#process)) { return 0; } this.#process.exitCode = code || 0; this.#emitter.emit("exit", this.#process.exitCode, null); return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode); } #processEmit(ev, ...args) { const og = this.#originalProcessEmit; if (ev === "exit" && processOk(this.#process)) { if (typeof args[0] === "number") { this.#process.exitCode = args[0]; } const ret = og.call(this.#process, ev, ...args); this.#emitter.emit("exit", this.#process.exitCode, null); return ret; } else { return og.call(this.#process, ev, ...args); } } } const process$1 = globalThis.process; const { /** * Called when the process is exiting, whether via signal, explicit * exit, or running out of stuff to do. * * If the global process object is not suitable for instrumentation, * then this will be a no-op. * * Returns a function that may be used to unload signal-exit. */ onExit} = signalExitWrap(processOk(process$1) ? new SignalExit(process$1) : new SignalExitFallback()); const terminal = process$2.stderr.isTTY ? process$2.stderr : process$2.stdout.isTTY ? process$2.stdout : void 0; const restoreCursor = terminal ? onetime(() => { onExit(() => { terminal.write("\x1B[?25h"); }, { alwaysLast: true }); }) : () => { }; export { restoreCursor as default };