Last active
February 18, 2022 03:35
-
-
Save Kreijstal/0bc6ee2a46baa77aed5cfd2b6f3aea46 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import colors from "https://cdn.skypack.dev/[email protected]"; | |
import * as readline from "./readline.js"; | |
; | |
var global$1 = typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}; | |
var lookup = []; | |
var revLookup = []; | |
var Arr = typeof Uint8Array !== "undefined" ? Uint8Array : Array; | |
var inited = false; | |
function init() { | |
inited = true; | |
var code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
for (var i = 0, len = code.length; i < len; ++i) { | |
lookup[i] = code[i]; | |
revLookup[code.charCodeAt(i)] = i; | |
} | |
revLookup["-".charCodeAt(0)] = 62; | |
revLookup["_".charCodeAt(0)] = 63; | |
} | |
function toByteArray(b64) { | |
if (!inited) { | |
init(); | |
} | |
var i, j, l, tmp, placeHolders, arr; | |
var len = b64.length; | |
if (len % 4 > 0) { | |
throw new Error("Invalid string. Length must be a multiple of 4"); | |
} | |
placeHolders = b64[len - 2] === "=" ? 2 : b64[len - 1] === "=" ? 1 : 0; | |
arr = new Arr(len * 3 / 4 - placeHolders); | |
l = placeHolders > 0 ? len - 4 : len; | |
var L = 0; | |
for (i = 0, j = 0; i < l; i += 4, j += 3) { | |
tmp = revLookup[b64.charCodeAt(i)] << 18 | revLookup[b64.charCodeAt(i + 1)] << 12 | revLookup[b64.charCodeAt(i + 2)] << 6 | revLookup[b64.charCodeAt(i + 3)]; | |
arr[L++] = tmp >> 16 & 255; | |
arr[L++] = tmp >> 8 & 255; | |
arr[L++] = tmp & 255; | |
} | |
if (placeHolders === 2) { | |
tmp = revLookup[b64.charCodeAt(i)] << 2 | revLookup[b64.charCodeAt(i + 1)] >> 4; | |
arr[L++] = tmp & 255; | |
} else if (placeHolders === 1) { | |
tmp = revLookup[b64.charCodeAt(i)] << 10 | revLookup[b64.charCodeAt(i + 1)] << 4 | revLookup[b64.charCodeAt(i + 2)] >> 2; | |
arr[L++] = tmp >> 8 & 255; | |
arr[L++] = tmp & 255; | |
} | |
return arr; | |
} | |
function tripletToBase64(num) { | |
return lookup[num >> 18 & 63] + lookup[num >> 12 & 63] + lookup[num >> 6 & 63] + lookup[num & 63]; | |
} | |
function encodeChunk(uint8, start, end) { | |
var tmp; | |
var output = []; | |
for (var i = start; i < end; i += 3) { | |
tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + uint8[i + 2]; | |
output.push(tripletToBase64(tmp)); | |
} | |
return output.join(""); | |
} | |
function fromByteArray(uint8) { | |
if (!inited) { | |
init(); | |
} | |
var tmp; | |
var len = uint8.length; | |
var extraBytes = len % 3; | |
var output = ""; | |
var parts = []; | |
var maxChunkLength = 16383; | |
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { | |
parts.push(encodeChunk(uint8, i, i + maxChunkLength > len2 ? len2 : i + maxChunkLength)); | |
} | |
if (extraBytes === 1) { | |
tmp = uint8[len - 1]; | |
output += lookup[tmp >> 2]; | |
output += lookup[tmp << 4 & 63]; | |
output += "=="; | |
} else if (extraBytes === 2) { | |
tmp = (uint8[len - 2] << 8) + uint8[len - 1]; | |
output += lookup[tmp >> 10]; | |
output += lookup[tmp >> 4 & 63]; | |
output += lookup[tmp << 2 & 63]; | |
output += "="; | |
} | |
parts.push(output); | |
return parts.join(""); | |
} | |
function read(buffer, offset, isLE, mLen, nBytes) { | |
var e, m; | |
var eLen = nBytes * 8 - mLen - 1; | |
var eMax = (1 << eLen) - 1; | |
var eBias = eMax >> 1; | |
var nBits = -7; | |
var i = isLE ? nBytes - 1 : 0; | |
var d = isLE ? -1 : 1; | |
var s = buffer[offset + i]; | |
i += d; | |
e = s & (1 << -nBits) - 1; | |
s >>= -nBits; | |
nBits += eLen; | |
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) { | |
} | |
m = e & (1 << -nBits) - 1; | |
e >>= -nBits; | |
nBits += mLen; | |
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) { | |
} | |
if (e === 0) { | |
e = 1 - eBias; | |
} else if (e === eMax) { | |
return m ? NaN : (s ? -1 : 1) * Infinity; | |
} else { | |
m = m + Math.pow(2, mLen); | |
e = e - eBias; | |
} | |
return (s ? -1 : 1) * m * Math.pow(2, e - mLen); | |
} | |
function write(buffer, value, offset, isLE, mLen, nBytes) { | |
var e, m, c; | |
var eLen = nBytes * 8 - mLen - 1; | |
var eMax = (1 << eLen) - 1; | |
var eBias = eMax >> 1; | |
var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0; | |
var i = isLE ? 0 : nBytes - 1; | |
var d = isLE ? 1 : -1; | |
var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0; | |
value = Math.abs(value); | |
if (isNaN(value) || value === Infinity) { | |
m = isNaN(value) ? 1 : 0; | |
e = eMax; | |
} else { | |
e = Math.floor(Math.log(value) / Math.LN2); | |
if (value * (c = Math.pow(2, -e)) < 1) { | |
e--; | |
c *= 2; | |
} | |
if (e + eBias >= 1) { | |
value += rt / c; | |
} else { | |
value += rt * Math.pow(2, 1 - eBias); | |
} | |
if (value * c >= 2) { | |
e++; | |
c /= 2; | |
} | |
if (e + eBias >= eMax) { | |
m = 0; | |
e = eMax; | |
} else if (e + eBias >= 1) { | |
m = (value * c - 1) * Math.pow(2, mLen); | |
e = e + eBias; | |
} else { | |
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); | |
e = 0; | |
} | |
} | |
for (; mLen >= 8; buffer[offset + i] = m & 255, i += d, m /= 256, mLen -= 8) { | |
} | |
e = e << mLen | m; | |
eLen += mLen; | |
for (; eLen > 0; buffer[offset + i] = e & 255, i += d, e /= 256, eLen -= 8) { | |
} | |
buffer[offset + i - d] |= s * 128; | |
} | |
var toString = {}.toString; | |
var isArray = Array.isArray || function(arr) { | |
return toString.call(arr) == "[object Array]"; | |
}; | |
/*! | |
* The buffer module from node.js, for the browser. | |
* | |
* @author Feross Aboukhadijeh <[email protected]> <http://feross.org> | |
* @license MIT | |
*/ | |
var INSPECT_MAX_BYTES = 50; | |
Buffer.TYPED_ARRAY_SUPPORT = global$1.TYPED_ARRAY_SUPPORT !== void 0 ? global$1.TYPED_ARRAY_SUPPORT : true; | |
function kMaxLength() { | |
return Buffer.TYPED_ARRAY_SUPPORT ? 2147483647 : 1073741823; | |
} | |
function createBuffer(that, length) { | |
if (kMaxLength() < length) { | |
throw new RangeError("Invalid typed array length"); | |
} | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
that = new Uint8Array(length); | |
that.__proto__ = Buffer.prototype; | |
} else { | |
if (that === null) { | |
that = new Buffer(length); | |
} | |
that.length = length; | |
} | |
return that; | |
} | |
function Buffer(arg, encodingOrOffset, length) { | |
if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { | |
return new Buffer(arg, encodingOrOffset, length); | |
} | |
if (typeof arg === "number") { | |
if (typeof encodingOrOffset === "string") { | |
throw new Error("If encoding is specified then the first argument must be a string"); | |
} | |
return allocUnsafe(this, arg); | |
} | |
return from(this, arg, encodingOrOffset, length); | |
} | |
Buffer.poolSize = 8192; | |
Buffer._augment = function(arr) { | |
arr.__proto__ = Buffer.prototype; | |
return arr; | |
}; | |
function from(that, value, encodingOrOffset, length) { | |
if (typeof value === "number") { | |
throw new TypeError('"value" argument must not be a number'); | |
} | |
if (typeof ArrayBuffer !== "undefined" && value instanceof ArrayBuffer) { | |
return fromArrayBuffer(that, value, encodingOrOffset, length); | |
} | |
if (typeof value === "string") { | |
return fromString(that, value, encodingOrOffset); | |
} | |
return fromObject(that, value); | |
} | |
Buffer.from = function(value, encodingOrOffset, length) { | |
return from(null, value, encodingOrOffset, length); | |
}; | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
Buffer.prototype.__proto__ = Uint8Array.prototype; | |
Buffer.__proto__ = Uint8Array; | |
} | |
function assertSize(size) { | |
if (typeof size !== "number") { | |
throw new TypeError('"size" argument must be a number'); | |
} else if (size < 0) { | |
throw new RangeError('"size" argument must not be negative'); | |
} | |
} | |
function alloc(that, size, fill2, encoding) { | |
assertSize(size); | |
if (size <= 0) { | |
return createBuffer(that, size); | |
} | |
if (fill2 !== void 0) { | |
return typeof encoding === "string" ? createBuffer(that, size).fill(fill2, encoding) : createBuffer(that, size).fill(fill2); | |
} | |
return createBuffer(that, size); | |
} | |
Buffer.alloc = function(size, fill2, encoding) { | |
return alloc(null, size, fill2, encoding); | |
}; | |
function allocUnsafe(that, size) { | |
assertSize(size); | |
that = createBuffer(that, size < 0 ? 0 : checked(size) | 0); | |
if (!Buffer.TYPED_ARRAY_SUPPORT) { | |
for (var i = 0; i < size; ++i) { | |
that[i] = 0; | |
} | |
} | |
return that; | |
} | |
Buffer.allocUnsafe = function(size) { | |
return allocUnsafe(null, size); | |
}; | |
Buffer.allocUnsafeSlow = function(size) { | |
return allocUnsafe(null, size); | |
}; | |
function fromString(that, string2, encoding) { | |
if (typeof encoding !== "string" || encoding === "") { | |
encoding = "utf8"; | |
} | |
if (!Buffer.isEncoding(encoding)) { | |
throw new TypeError('"encoding" must be a valid string encoding'); | |
} | |
var length = byteLength(string2, encoding) | 0; | |
that = createBuffer(that, length); | |
var actual = that.write(string2, encoding); | |
if (actual !== length) { | |
that = that.slice(0, actual); | |
} | |
return that; | |
} | |
function fromArrayLike(that, array2) { | |
var length = array2.length < 0 ? 0 : checked(array2.length) | 0; | |
that = createBuffer(that, length); | |
for (var i = 0; i < length; i += 1) { | |
that[i] = array2[i] & 255; | |
} | |
return that; | |
} | |
function fromArrayBuffer(that, array2, byteOffset, length) { | |
array2.byteLength; | |
if (byteOffset < 0 || array2.byteLength < byteOffset) { | |
throw new RangeError("'offset' is out of bounds"); | |
} | |
if (array2.byteLength < byteOffset + (length || 0)) { | |
throw new RangeError("'length' is out of bounds"); | |
} | |
if (byteOffset === void 0 && length === void 0) { | |
array2 = new Uint8Array(array2); | |
} else if (length === void 0) { | |
array2 = new Uint8Array(array2, byteOffset); | |
} else { | |
array2 = new Uint8Array(array2, byteOffset, length); | |
} | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
that = array2; | |
that.__proto__ = Buffer.prototype; | |
} else { | |
that = fromArrayLike(that, array2); | |
} | |
return that; | |
} | |
function fromObject(that, obj) { | |
if (internalIsBuffer(obj)) { | |
var len = checked(obj.length) | 0; | |
that = createBuffer(that, len); | |
if (that.length === 0) { | |
return that; | |
} | |
obj.copy(that, 0, 0, len); | |
return that; | |
} | |
if (obj) { | |
if (typeof ArrayBuffer !== "undefined" && obj.buffer instanceof ArrayBuffer || "length" in obj) { | |
if (typeof obj.length !== "number" || isnan(obj.length)) { | |
return createBuffer(that, 0); | |
} | |
return fromArrayLike(that, obj); | |
} | |
if (obj.type === "Buffer" && isArray(obj.data)) { | |
return fromArrayLike(that, obj.data); | |
} | |
} | |
throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object."); | |
} | |
function checked(length) { | |
if (length >= kMaxLength()) { | |
throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x" + kMaxLength().toString(16) + " bytes"); | |
} | |
return length | 0; | |
} | |
Buffer.isBuffer = isBuffer; | |
function internalIsBuffer(b) { | |
return !!(b != null && b._isBuffer); | |
} | |
Buffer.compare = function compare(a, b) { | |
if (!internalIsBuffer(a) || !internalIsBuffer(b)) { | |
throw new TypeError("Arguments must be Buffers"); | |
} | |
if (a === b) | |
return 0; | |
var x = a.length; | |
var y = b.length; | |
for (var i = 0, len = Math.min(x, y); i < len; ++i) { | |
if (a[i] !== b[i]) { | |
x = a[i]; | |
y = b[i]; | |
break; | |
} | |
} | |
if (x < y) | |
return -1; | |
if (y < x) | |
return 1; | |
return 0; | |
}; | |
Buffer.isEncoding = function isEncoding(encoding) { | |
switch (String(encoding).toLowerCase()) { | |
case "hex": | |
case "utf8": | |
case "utf-8": | |
case "ascii": | |
case "latin1": | |
case "binary": | |
case "base64": | |
case "ucs2": | |
case "ucs-2": | |
case "utf16le": | |
case "utf-16le": | |
return true; | |
default: | |
return false; | |
} | |
}; | |
Buffer.concat = function concat(list2, length) { | |
if (!isArray(list2)) { | |
throw new TypeError('"list" argument must be an Array of Buffers'); | |
} | |
if (list2.length === 0) { | |
return Buffer.alloc(0); | |
} | |
var i; | |
if (length === void 0) { | |
length = 0; | |
for (i = 0; i < list2.length; ++i) { | |
length += list2[i].length; | |
} | |
} | |
var buffer = Buffer.allocUnsafe(length); | |
var pos = 0; | |
for (i = 0; i < list2.length; ++i) { | |
var buf = list2[i]; | |
if (!internalIsBuffer(buf)) { | |
throw new TypeError('"list" argument must be an Array of Buffers'); | |
} | |
buf.copy(buffer, pos); | |
pos += buf.length; | |
} | |
return buffer; | |
}; | |
function byteLength(string2, encoding) { | |
if (internalIsBuffer(string2)) { | |
return string2.length; | |
} | |
if (typeof ArrayBuffer !== "undefined" && typeof ArrayBuffer.isView === "function" && (ArrayBuffer.isView(string2) || string2 instanceof ArrayBuffer)) { | |
return string2.byteLength; | |
} | |
if (typeof string2 !== "string") { | |
string2 = "" + string2; | |
} | |
var len = string2.length; | |
if (len === 0) | |
return 0; | |
var loweredCase = false; | |
for (; ; ) { | |
switch (encoding) { | |
case "ascii": | |
case "latin1": | |
case "binary": | |
return len; | |
case "utf8": | |
case "utf-8": | |
case void 0: | |
return utf8ToBytes(string2).length; | |
case "ucs2": | |
case "ucs-2": | |
case "utf16le": | |
case "utf-16le": | |
return len * 2; | |
case "hex": | |
return len >>> 1; | |
case "base64": | |
return base64ToBytes(string2).length; | |
default: | |
if (loweredCase) | |
return utf8ToBytes(string2).length; | |
encoding = ("" + encoding).toLowerCase(); | |
loweredCase = true; | |
} | |
} | |
} | |
Buffer.byteLength = byteLength; | |
function slowToString(encoding, start, end) { | |
var loweredCase = false; | |
if (start === void 0 || start < 0) { | |
start = 0; | |
} | |
if (start > this.length) { | |
return ""; | |
} | |
if (end === void 0 || end > this.length) { | |
end = this.length; | |
} | |
if (end <= 0) { | |
return ""; | |
} | |
end >>>= 0; | |
start >>>= 0; | |
if (end <= start) { | |
return ""; | |
} | |
if (!encoding) | |
encoding = "utf8"; | |
while (true) { | |
switch (encoding) { | |
case "hex": | |
return hexSlice(this, start, end); | |
case "utf8": | |
case "utf-8": | |
return utf8Slice(this, start, end); | |
case "ascii": | |
return asciiSlice(this, start, end); | |
case "latin1": | |
case "binary": | |
return latin1Slice(this, start, end); | |
case "base64": | |
return base64Slice(this, start, end); | |
case "ucs2": | |
case "ucs-2": | |
case "utf16le": | |
case "utf-16le": | |
return utf16leSlice(this, start, end); | |
default: | |
if (loweredCase) | |
throw new TypeError("Unknown encoding: " + encoding); | |
encoding = (encoding + "").toLowerCase(); | |
loweredCase = true; | |
} | |
} | |
} | |
Buffer.prototype._isBuffer = true; | |
function swap(b, n, m) { | |
var i = b[n]; | |
b[n] = b[m]; | |
b[m] = i; | |
} | |
Buffer.prototype.swap16 = function swap16() { | |
var len = this.length; | |
if (len % 2 !== 0) { | |
throw new RangeError("Buffer size must be a multiple of 16-bits"); | |
} | |
for (var i = 0; i < len; i += 2) { | |
swap(this, i, i + 1); | |
} | |
return this; | |
}; | |
Buffer.prototype.swap32 = function swap32() { | |
var len = this.length; | |
if (len % 4 !== 0) { | |
throw new RangeError("Buffer size must be a multiple of 32-bits"); | |
} | |
for (var i = 0; i < len; i += 4) { | |
swap(this, i, i + 3); | |
swap(this, i + 1, i + 2); | |
} | |
return this; | |
}; | |
Buffer.prototype.swap64 = function swap64() { | |
var len = this.length; | |
if (len % 8 !== 0) { | |
throw new RangeError("Buffer size must be a multiple of 64-bits"); | |
} | |
for (var i = 0; i < len; i += 8) { | |
swap(this, i, i + 7); | |
swap(this, i + 1, i + 6); | |
swap(this, i + 2, i + 5); | |
swap(this, i + 3, i + 4); | |
} | |
return this; | |
}; | |
Buffer.prototype.toString = function toString2() { | |
var length = this.length | 0; | |
if (length === 0) | |
return ""; | |
if (arguments.length === 0) | |
return utf8Slice(this, 0, length); | |
return slowToString.apply(this, arguments); | |
}; | |
Buffer.prototype.equals = function equals(b) { | |
if (!internalIsBuffer(b)) | |
throw new TypeError("Argument must be a Buffer"); | |
if (this === b) | |
return true; | |
return Buffer.compare(this, b) === 0; | |
}; | |
Buffer.prototype.inspect = function inspect() { | |
var str = ""; | |
var max = INSPECT_MAX_BYTES; | |
if (this.length > 0) { | |
str = this.toString("hex", 0, max).match(/.{2}/g).join(" "); | |
if (this.length > max) | |
str += " ... "; | |
} | |
return "<Buffer " + str + ">"; | |
}; | |
Buffer.prototype.compare = function compare2(target, start, end, thisStart, thisEnd) { | |
if (!internalIsBuffer(target)) { | |
throw new TypeError("Argument must be a Buffer"); | |
} | |
if (start === void 0) { | |
start = 0; | |
} | |
if (end === void 0) { | |
end = target ? target.length : 0; | |
} | |
if (thisStart === void 0) { | |
thisStart = 0; | |
} | |
if (thisEnd === void 0) { | |
thisEnd = this.length; | |
} | |
if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { | |
throw new RangeError("out of range index"); | |
} | |
if (thisStart >= thisEnd && start >= end) { | |
return 0; | |
} | |
if (thisStart >= thisEnd) { | |
return -1; | |
} | |
if (start >= end) { | |
return 1; | |
} | |
start >>>= 0; | |
end >>>= 0; | |
thisStart >>>= 0; | |
thisEnd >>>= 0; | |
if (this === target) | |
return 0; | |
var x = thisEnd - thisStart; | |
var y = end - start; | |
var len = Math.min(x, y); | |
var thisCopy = this.slice(thisStart, thisEnd); | |
var targetCopy = target.slice(start, end); | |
for (var i = 0; i < len; ++i) { | |
if (thisCopy[i] !== targetCopy[i]) { | |
x = thisCopy[i]; | |
y = targetCopy[i]; | |
break; | |
} | |
} | |
if (x < y) | |
return -1; | |
if (y < x) | |
return 1; | |
return 0; | |
}; | |
function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { | |
if (buffer.length === 0) | |
return -1; | |
if (typeof byteOffset === "string") { | |
encoding = byteOffset; | |
byteOffset = 0; | |
} else if (byteOffset > 2147483647) { | |
byteOffset = 2147483647; | |
} else if (byteOffset < -2147483648) { | |
byteOffset = -2147483648; | |
} | |
byteOffset = +byteOffset; | |
if (isNaN(byteOffset)) { | |
byteOffset = dir ? 0 : buffer.length - 1; | |
} | |
if (byteOffset < 0) | |
byteOffset = buffer.length + byteOffset; | |
if (byteOffset >= buffer.length) { | |
if (dir) | |
return -1; | |
else | |
byteOffset = buffer.length - 1; | |
} else if (byteOffset < 0) { | |
if (dir) | |
byteOffset = 0; | |
else | |
return -1; | |
} | |
if (typeof val === "string") { | |
val = Buffer.from(val, encoding); | |
} | |
if (internalIsBuffer(val)) { | |
if (val.length === 0) { | |
return -1; | |
} | |
return arrayIndexOf(buffer, val, byteOffset, encoding, dir); | |
} else if (typeof val === "number") { | |
val = val & 255; | |
if (Buffer.TYPED_ARRAY_SUPPORT && typeof Uint8Array.prototype.indexOf === "function") { | |
if (dir) { | |
return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset); | |
} else { | |
return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset); | |
} | |
} | |
return arrayIndexOf(buffer, [val], byteOffset, encoding, dir); | |
} | |
throw new TypeError("val must be string, number or Buffer"); | |
} | |
function arrayIndexOf(arr, val, byteOffset, encoding, dir) { | |
var indexSize = 1; | |
var arrLength = arr.length; | |
var valLength = val.length; | |
if (encoding !== void 0) { | |
encoding = String(encoding).toLowerCase(); | |
if (encoding === "ucs2" || encoding === "ucs-2" || encoding === "utf16le" || encoding === "utf-16le") { | |
if (arr.length < 2 || val.length < 2) { | |
return -1; | |
} | |
indexSize = 2; | |
arrLength /= 2; | |
valLength /= 2; | |
byteOffset /= 2; | |
} | |
} | |
function read2(buf, i2) { | |
if (indexSize === 1) { | |
return buf[i2]; | |
} else { | |
return buf.readUInt16BE(i2 * indexSize); | |
} | |
} | |
var i; | |
if (dir) { | |
var foundIndex = -1; | |
for (i = byteOffset; i < arrLength; i++) { | |
if (read2(arr, i) === read2(val, foundIndex === -1 ? 0 : i - foundIndex)) { | |
if (foundIndex === -1) | |
foundIndex = i; | |
if (i - foundIndex + 1 === valLength) | |
return foundIndex * indexSize; | |
} else { | |
if (foundIndex !== -1) | |
i -= i - foundIndex; | |
foundIndex = -1; | |
} | |
} | |
} else { | |
if (byteOffset + valLength > arrLength) | |
byteOffset = arrLength - valLength; | |
for (i = byteOffset; i >= 0; i--) { | |
var found = true; | |
for (var j = 0; j < valLength; j++) { | |
if (read2(arr, i + j) !== read2(val, j)) { | |
found = false; | |
break; | |
} | |
} | |
if (found) | |
return i; | |
} | |
} | |
return -1; | |
} | |
Buffer.prototype.includes = function includes(val, byteOffset, encoding) { | |
return this.indexOf(val, byteOffset, encoding) !== -1; | |
}; | |
Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) { | |
return bidirectionalIndexOf(this, val, byteOffset, encoding, true); | |
}; | |
Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) { | |
return bidirectionalIndexOf(this, val, byteOffset, encoding, false); | |
}; | |
function hexWrite(buf, string2, offset, length) { | |
offset = Number(offset) || 0; | |
var remaining = buf.length - offset; | |
if (!length) { | |
length = remaining; | |
} else { | |
length = Number(length); | |
if (length > remaining) { | |
length = remaining; | |
} | |
} | |
var strLen = string2.length; | |
if (strLen % 2 !== 0) | |
throw new TypeError("Invalid hex string"); | |
if (length > strLen / 2) { | |
length = strLen / 2; | |
} | |
for (var i = 0; i < length; ++i) { | |
var parsed = parseInt(string2.substr(i * 2, 2), 16); | |
if (isNaN(parsed)) | |
return i; | |
buf[offset + i] = parsed; | |
} | |
return i; | |
} | |
function utf8Write(buf, string2, offset, length) { | |
return blitBuffer(utf8ToBytes(string2, buf.length - offset), buf, offset, length); | |
} | |
function asciiWrite(buf, string2, offset, length) { | |
return blitBuffer(asciiToBytes(string2), buf, offset, length); | |
} | |
function latin1Write(buf, string2, offset, length) { | |
return asciiWrite(buf, string2, offset, length); | |
} | |
function base64Write(buf, string2, offset, length) { | |
return blitBuffer(base64ToBytes(string2), buf, offset, length); | |
} | |
function ucs2Write(buf, string2, offset, length) { | |
return blitBuffer(utf16leToBytes(string2, buf.length - offset), buf, offset, length); | |
} | |
Buffer.prototype.write = function write2(string2, offset, length, encoding) { | |
if (offset === void 0) { | |
encoding = "utf8"; | |
length = this.length; | |
offset = 0; | |
} else if (length === void 0 && typeof offset === "string") { | |
encoding = offset; | |
length = this.length; | |
offset = 0; | |
} else if (isFinite(offset)) { | |
offset = offset | 0; | |
if (isFinite(length)) { | |
length = length | 0; | |
if (encoding === void 0) | |
encoding = "utf8"; | |
} else { | |
encoding = length; | |
length = void 0; | |
} | |
} else { | |
throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported"); | |
} | |
var remaining = this.length - offset; | |
if (length === void 0 || length > remaining) | |
length = remaining; | |
if (string2.length > 0 && (length < 0 || offset < 0) || offset > this.length) { | |
throw new RangeError("Attempt to write outside buffer bounds"); | |
} | |
if (!encoding) | |
encoding = "utf8"; | |
var loweredCase = false; | |
for (; ; ) { | |
switch (encoding) { | |
case "hex": | |
return hexWrite(this, string2, offset, length); | |
case "utf8": | |
case "utf-8": | |
return utf8Write(this, string2, offset, length); | |
case "ascii": | |
return asciiWrite(this, string2, offset, length); | |
case "latin1": | |
case "binary": | |
return latin1Write(this, string2, offset, length); | |
case "base64": | |
return base64Write(this, string2, offset, length); | |
case "ucs2": | |
case "ucs-2": | |
case "utf16le": | |
case "utf-16le": | |
return ucs2Write(this, string2, offset, length); | |
default: | |
if (loweredCase) | |
throw new TypeError("Unknown encoding: " + encoding); | |
encoding = ("" + encoding).toLowerCase(); | |
loweredCase = true; | |
} | |
} | |
}; | |
Buffer.prototype.toJSON = function toJSON() { | |
return { | |
type: "Buffer", | |
data: Array.prototype.slice.call(this._arr || this, 0) | |
}; | |
}; | |
function base64Slice(buf, start, end) { | |
if (start === 0 && end === buf.length) { | |
return fromByteArray(buf); | |
} else { | |
return fromByteArray(buf.slice(start, end)); | |
} | |
} | |
function utf8Slice(buf, start, end) { | |
end = Math.min(buf.length, end); | |
var res = []; | |
var i = start; | |
while (i < end) { | |
var firstByte = buf[i]; | |
var codePoint = null; | |
var bytesPerSequence = firstByte > 239 ? 4 : firstByte > 223 ? 3 : firstByte > 191 ? 2 : 1; | |
if (i + bytesPerSequence <= end) { | |
var secondByte, thirdByte, fourthByte, tempCodePoint; | |
switch (bytesPerSequence) { | |
case 1: | |
if (firstByte < 128) { | |
codePoint = firstByte; | |
} | |
break; | |
case 2: | |
secondByte = buf[i + 1]; | |
if ((secondByte & 192) === 128) { | |
tempCodePoint = (firstByte & 31) << 6 | secondByte & 63; | |
if (tempCodePoint > 127) { | |
codePoint = tempCodePoint; | |
} | |
} | |
break; | |
case 3: | |
secondByte = buf[i + 1]; | |
thirdByte = buf[i + 2]; | |
if ((secondByte & 192) === 128 && (thirdByte & 192) === 128) { | |
tempCodePoint = (firstByte & 15) << 12 | (secondByte & 63) << 6 | thirdByte & 63; | |
if (tempCodePoint > 2047 && (tempCodePoint < 55296 || tempCodePoint > 57343)) { | |
codePoint = tempCodePoint; | |
} | |
} | |
break; | |
case 4: | |
secondByte = buf[i + 1]; | |
thirdByte = buf[i + 2]; | |
fourthByte = buf[i + 3]; | |
if ((secondByte & 192) === 128 && (thirdByte & 192) === 128 && (fourthByte & 192) === 128) { | |
tempCodePoint = (firstByte & 15) << 18 | (secondByte & 63) << 12 | (thirdByte & 63) << 6 | fourthByte & 63; | |
if (tempCodePoint > 65535 && tempCodePoint < 1114112) { | |
codePoint = tempCodePoint; | |
} | |
} | |
} | |
} | |
if (codePoint === null) { | |
codePoint = 65533; | |
bytesPerSequence = 1; | |
} else if (codePoint > 65535) { | |
codePoint -= 65536; | |
res.push(codePoint >>> 10 & 1023 | 55296); | |
codePoint = 56320 | codePoint & 1023; | |
} | |
res.push(codePoint); | |
i += bytesPerSequence; | |
} | |
return decodeCodePointsArray(res); | |
} | |
var MAX_ARGUMENTS_LENGTH = 4096; | |
function decodeCodePointsArray(codePoints) { | |
var len = codePoints.length; | |
if (len <= MAX_ARGUMENTS_LENGTH) { | |
return String.fromCharCode.apply(String, codePoints); | |
} | |
var res = ""; | |
var i = 0; | |
while (i < len) { | |
res += String.fromCharCode.apply(String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)); | |
} | |
return res; | |
} | |
function asciiSlice(buf, start, end) { | |
var ret = ""; | |
end = Math.min(buf.length, end); | |
for (var i = start; i < end; ++i) { | |
ret += String.fromCharCode(buf[i] & 127); | |
} | |
return ret; | |
} | |
function latin1Slice(buf, start, end) { | |
var ret = ""; | |
end = Math.min(buf.length, end); | |
for (var i = start; i < end; ++i) { | |
ret += String.fromCharCode(buf[i]); | |
} | |
return ret; | |
} | |
function hexSlice(buf, start, end) { | |
var len = buf.length; | |
if (!start || start < 0) | |
start = 0; | |
if (!end || end < 0 || end > len) | |
end = len; | |
var out = ""; | |
for (var i = start; i < end; ++i) { | |
out += toHex(buf[i]); | |
} | |
return out; | |
} | |
function utf16leSlice(buf, start, end) { | |
var bytes = buf.slice(start, end); | |
var res = ""; | |
for (var i = 0; i < bytes.length; i += 2) { | |
res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256); | |
} | |
return res; | |
} | |
Buffer.prototype.slice = function slice(start, end) { | |
var len = this.length; | |
start = ~~start; | |
end = end === void 0 ? len : ~~end; | |
if (start < 0) { | |
start += len; | |
if (start < 0) | |
start = 0; | |
} else if (start > len) { | |
start = len; | |
} | |
if (end < 0) { | |
end += len; | |
if (end < 0) | |
end = 0; | |
} else if (end > len) { | |
end = len; | |
} | |
if (end < start) | |
end = start; | |
var newBuf; | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
newBuf = this.subarray(start, end); | |
newBuf.__proto__ = Buffer.prototype; | |
} else { | |
var sliceLen = end - start; | |
newBuf = new Buffer(sliceLen, void 0); | |
for (var i = 0; i < sliceLen; ++i) { | |
newBuf[i] = this[i + start]; | |
} | |
} | |
return newBuf; | |
}; | |
function checkOffset(offset, ext, length) { | |
if (offset % 1 !== 0 || offset < 0) | |
throw new RangeError("offset is not uint"); | |
if (offset + ext > length) | |
throw new RangeError("Trying to access beyond buffer length"); | |
} | |
Buffer.prototype.readUIntLE = function readUIntLE(offset, byteLength2, noAssert) { | |
offset = offset | 0; | |
byteLength2 = byteLength2 | 0; | |
if (!noAssert) | |
checkOffset(offset, byteLength2, this.length); | |
var val = this[offset]; | |
var mul = 1; | |
var i = 0; | |
while (++i < byteLength2 && (mul *= 256)) { | |
val += this[offset + i] * mul; | |
} | |
return val; | |
}; | |
Buffer.prototype.readUIntBE = function readUIntBE(offset, byteLength2, noAssert) { | |
offset = offset | 0; | |
byteLength2 = byteLength2 | 0; | |
if (!noAssert) { | |
checkOffset(offset, byteLength2, this.length); | |
} | |
var val = this[offset + --byteLength2]; | |
var mul = 1; | |
while (byteLength2 > 0 && (mul *= 256)) { | |
val += this[offset + --byteLength2] * mul; | |
} | |
return val; | |
}; | |
Buffer.prototype.readUInt8 = function readUInt8(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 1, this.length); | |
return this[offset]; | |
}; | |
Buffer.prototype.readUInt16LE = function readUInt16LE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 2, this.length); | |
return this[offset] | this[offset + 1] << 8; | |
}; | |
Buffer.prototype.readUInt16BE = function readUInt16BE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 2, this.length); | |
return this[offset] << 8 | this[offset + 1]; | |
}; | |
Buffer.prototype.readUInt32LE = function readUInt32LE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 4, this.length); | |
return (this[offset] | this[offset + 1] << 8 | this[offset + 2] << 16) + this[offset + 3] * 16777216; | |
}; | |
Buffer.prototype.readUInt32BE = function readUInt32BE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 4, this.length); | |
return this[offset] * 16777216 + (this[offset + 1] << 16 | this[offset + 2] << 8 | this[offset + 3]); | |
}; | |
Buffer.prototype.readIntLE = function readIntLE(offset, byteLength2, noAssert) { | |
offset = offset | 0; | |
byteLength2 = byteLength2 | 0; | |
if (!noAssert) | |
checkOffset(offset, byteLength2, this.length); | |
var val = this[offset]; | |
var mul = 1; | |
var i = 0; | |
while (++i < byteLength2 && (mul *= 256)) { | |
val += this[offset + i] * mul; | |
} | |
mul *= 128; | |
if (val >= mul) | |
val -= Math.pow(2, 8 * byteLength2); | |
return val; | |
}; | |
Buffer.prototype.readIntBE = function readIntBE(offset, byteLength2, noAssert) { | |
offset = offset | 0; | |
byteLength2 = byteLength2 | 0; | |
if (!noAssert) | |
checkOffset(offset, byteLength2, this.length); | |
var i = byteLength2; | |
var mul = 1; | |
var val = this[offset + --i]; | |
while (i > 0 && (mul *= 256)) { | |
val += this[offset + --i] * mul; | |
} | |
mul *= 128; | |
if (val >= mul) | |
val -= Math.pow(2, 8 * byteLength2); | |
return val; | |
}; | |
Buffer.prototype.readInt8 = function readInt8(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 1, this.length); | |
if (!(this[offset] & 128)) | |
return this[offset]; | |
return (255 - this[offset] + 1) * -1; | |
}; | |
Buffer.prototype.readInt16LE = function readInt16LE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 2, this.length); | |
var val = this[offset] | this[offset + 1] << 8; | |
return val & 32768 ? val | 4294901760 : val; | |
}; | |
Buffer.prototype.readInt16BE = function readInt16BE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 2, this.length); | |
var val = this[offset + 1] | this[offset] << 8; | |
return val & 32768 ? val | 4294901760 : val; | |
}; | |
Buffer.prototype.readInt32LE = function readInt32LE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 4, this.length); | |
return this[offset] | this[offset + 1] << 8 | this[offset + 2] << 16 | this[offset + 3] << 24; | |
}; | |
Buffer.prototype.readInt32BE = function readInt32BE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 4, this.length); | |
return this[offset] << 24 | this[offset + 1] << 16 | this[offset + 2] << 8 | this[offset + 3]; | |
}; | |
Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 4, this.length); | |
return read(this, offset, true, 23, 4); | |
}; | |
Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 4, this.length); | |
return read(this, offset, false, 23, 4); | |
}; | |
Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 8, this.length); | |
return read(this, offset, true, 52, 8); | |
}; | |
Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) { | |
if (!noAssert) | |
checkOffset(offset, 8, this.length); | |
return read(this, offset, false, 52, 8); | |
}; | |
function checkInt(buf, value, offset, ext, max, min) { | |
if (!internalIsBuffer(buf)) | |
throw new TypeError('"buffer" argument must be a Buffer instance'); | |
if (value > max || value < min) | |
throw new RangeError('"value" argument is out of bounds'); | |
if (offset + ext > buf.length) | |
throw new RangeError("Index out of range"); | |
} | |
Buffer.prototype.writeUIntLE = function writeUIntLE(value, offset, byteLength2, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
byteLength2 = byteLength2 | 0; | |
if (!noAssert) { | |
var maxBytes = Math.pow(2, 8 * byteLength2) - 1; | |
checkInt(this, value, offset, byteLength2, maxBytes, 0); | |
} | |
var mul = 1; | |
var i = 0; | |
this[offset] = value & 255; | |
while (++i < byteLength2 && (mul *= 256)) { | |
this[offset + i] = value / mul & 255; | |
} | |
return offset + byteLength2; | |
}; | |
Buffer.prototype.writeUIntBE = function writeUIntBE(value, offset, byteLength2, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
byteLength2 = byteLength2 | 0; | |
if (!noAssert) { | |
var maxBytes = Math.pow(2, 8 * byteLength2) - 1; | |
checkInt(this, value, offset, byteLength2, maxBytes, 0); | |
} | |
var i = byteLength2 - 1; | |
var mul = 1; | |
this[offset + i] = value & 255; | |
while (--i >= 0 && (mul *= 256)) { | |
this[offset + i] = value / mul & 255; | |
} | |
return offset + byteLength2; | |
}; | |
Buffer.prototype.writeUInt8 = function writeUInt8(value, offset, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) | |
checkInt(this, value, offset, 1, 255, 0); | |
if (!Buffer.TYPED_ARRAY_SUPPORT) | |
value = Math.floor(value); | |
this[offset] = value & 255; | |
return offset + 1; | |
}; | |
function objectWriteUInt16(buf, value, offset, littleEndian) { | |
if (value < 0) | |
value = 65535 + value + 1; | |
for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { | |
buf[offset + i] = (value & 255 << 8 * (littleEndian ? i : 1 - i)) >>> (littleEndian ? i : 1 - i) * 8; | |
} | |
} | |
Buffer.prototype.writeUInt16LE = function writeUInt16LE(value, offset, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) | |
checkInt(this, value, offset, 2, 65535, 0); | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = value & 255; | |
this[offset + 1] = value >>> 8; | |
} else { | |
objectWriteUInt16(this, value, offset, true); | |
} | |
return offset + 2; | |
}; | |
Buffer.prototype.writeUInt16BE = function writeUInt16BE(value, offset, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) | |
checkInt(this, value, offset, 2, 65535, 0); | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = value >>> 8; | |
this[offset + 1] = value & 255; | |
} else { | |
objectWriteUInt16(this, value, offset, false); | |
} | |
return offset + 2; | |
}; | |
function objectWriteUInt32(buf, value, offset, littleEndian) { | |
if (value < 0) | |
value = 4294967295 + value + 1; | |
for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { | |
buf[offset + i] = value >>> (littleEndian ? i : 3 - i) * 8 & 255; | |
} | |
} | |
Buffer.prototype.writeUInt32LE = function writeUInt32LE(value, offset, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) | |
checkInt(this, value, offset, 4, 4294967295, 0); | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset + 3] = value >>> 24; | |
this[offset + 2] = value >>> 16; | |
this[offset + 1] = value >>> 8; | |
this[offset] = value & 255; | |
} else { | |
objectWriteUInt32(this, value, offset, true); | |
} | |
return offset + 4; | |
}; | |
Buffer.prototype.writeUInt32BE = function writeUInt32BE(value, offset, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) | |
checkInt(this, value, offset, 4, 4294967295, 0); | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = value >>> 24; | |
this[offset + 1] = value >>> 16; | |
this[offset + 2] = value >>> 8; | |
this[offset + 3] = value & 255; | |
} else { | |
objectWriteUInt32(this, value, offset, false); | |
} | |
return offset + 4; | |
}; | |
Buffer.prototype.writeIntLE = function writeIntLE(value, offset, byteLength2, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) { | |
var limit = Math.pow(2, 8 * byteLength2 - 1); | |
checkInt(this, value, offset, byteLength2, limit - 1, -limit); | |
} | |
var i = 0; | |
var mul = 1; | |
var sub = 0; | |
this[offset] = value & 255; | |
while (++i < byteLength2 && (mul *= 256)) { | |
if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { | |
sub = 1; | |
} | |
this[offset + i] = (value / mul >> 0) - sub & 255; | |
} | |
return offset + byteLength2; | |
}; | |
Buffer.prototype.writeIntBE = function writeIntBE(value, offset, byteLength2, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) { | |
var limit = Math.pow(2, 8 * byteLength2 - 1); | |
checkInt(this, value, offset, byteLength2, limit - 1, -limit); | |
} | |
var i = byteLength2 - 1; | |
var mul = 1; | |
var sub = 0; | |
this[offset + i] = value & 255; | |
while (--i >= 0 && (mul *= 256)) { | |
if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { | |
sub = 1; | |
} | |
this[offset + i] = (value / mul >> 0) - sub & 255; | |
} | |
return offset + byteLength2; | |
}; | |
Buffer.prototype.writeInt8 = function writeInt8(value, offset, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) | |
checkInt(this, value, offset, 1, 127, -128); | |
if (!Buffer.TYPED_ARRAY_SUPPORT) | |
value = Math.floor(value); | |
if (value < 0) | |
value = 255 + value + 1; | |
this[offset] = value & 255; | |
return offset + 1; | |
}; | |
Buffer.prototype.writeInt16LE = function writeInt16LE(value, offset, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) | |
checkInt(this, value, offset, 2, 32767, -32768); | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = value & 255; | |
this[offset + 1] = value >>> 8; | |
} else { | |
objectWriteUInt16(this, value, offset, true); | |
} | |
return offset + 2; | |
}; | |
Buffer.prototype.writeInt16BE = function writeInt16BE(value, offset, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) | |
checkInt(this, value, offset, 2, 32767, -32768); | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = value >>> 8; | |
this[offset + 1] = value & 255; | |
} else { | |
objectWriteUInt16(this, value, offset, false); | |
} | |
return offset + 2; | |
}; | |
Buffer.prototype.writeInt32LE = function writeInt32LE(value, offset, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) | |
checkInt(this, value, offset, 4, 2147483647, -2147483648); | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = value & 255; | |
this[offset + 1] = value >>> 8; | |
this[offset + 2] = value >>> 16; | |
this[offset + 3] = value >>> 24; | |
} else { | |
objectWriteUInt32(this, value, offset, true); | |
} | |
return offset + 4; | |
}; | |
Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) { | |
value = +value; | |
offset = offset | 0; | |
if (!noAssert) | |
checkInt(this, value, offset, 4, 2147483647, -2147483648); | |
if (value < 0) | |
value = 4294967295 + value + 1; | |
if (Buffer.TYPED_ARRAY_SUPPORT) { | |
this[offset] = value >>> 24; | |
this[offset + 1] = value >>> 16; | |
this[offset + 2] = value >>> 8; | |
this[offset + 3] = value & 255; | |
} else { | |
objectWriteUInt32(this, value, offset, false); | |
} | |
return offset + 4; | |
}; | |
function checkIEEE754(buf, value, offset, ext, max, min) { | |
if (offset + ext > buf.length) | |
throw new RangeError("Index out of range"); | |
if (offset < 0) | |
throw new RangeError("Index out of range"); | |
} | |
function writeFloat(buf, value, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
checkIEEE754(buf, value, offset, 4); | |
} | |
write(buf, value, offset, littleEndian, 23, 4); | |
return offset + 4; | |
} | |
Buffer.prototype.writeFloatLE = function writeFloatLE(value, offset, noAssert) { | |
return writeFloat(this, value, offset, true, noAssert); | |
}; | |
Buffer.prototype.writeFloatBE = function writeFloatBE(value, offset, noAssert) { | |
return writeFloat(this, value, offset, false, noAssert); | |
}; | |
function writeDouble(buf, value, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
checkIEEE754(buf, value, offset, 8); | |
} | |
write(buf, value, offset, littleEndian, 52, 8); | |
return offset + 8; | |
} | |
Buffer.prototype.writeDoubleLE = function writeDoubleLE(value, offset, noAssert) { | |
return writeDouble(this, value, offset, true, noAssert); | |
}; | |
Buffer.prototype.writeDoubleBE = function writeDoubleBE(value, offset, noAssert) { | |
return writeDouble(this, value, offset, false, noAssert); | |
}; | |
Buffer.prototype.copy = function copy(target, targetStart, start, end) { | |
if (!start) | |
start = 0; | |
if (!end && end !== 0) | |
end = this.length; | |
if (targetStart >= target.length) | |
targetStart = target.length; | |
if (!targetStart) | |
targetStart = 0; | |
if (end > 0 && end < start) | |
end = start; | |
if (end === start) | |
return 0; | |
if (target.length === 0 || this.length === 0) | |
return 0; | |
if (targetStart < 0) { | |
throw new RangeError("targetStart out of bounds"); | |
} | |
if (start < 0 || start >= this.length) | |
throw new RangeError("sourceStart out of bounds"); | |
if (end < 0) | |
throw new RangeError("sourceEnd out of bounds"); | |
if (end > this.length) | |
end = this.length; | |
if (target.length - targetStart < end - start) { | |
end = target.length - targetStart + start; | |
} | |
var len = end - start; | |
var i; | |
if (this === target && start < targetStart && targetStart < end) { | |
for (i = len - 1; i >= 0; --i) { | |
target[i + targetStart] = this[i + start]; | |
} | |
} else if (len < 1e3 || !Buffer.TYPED_ARRAY_SUPPORT) { | |
for (i = 0; i < len; ++i) { | |
target[i + targetStart] = this[i + start]; | |
} | |
} else { | |
Uint8Array.prototype.set.call(target, this.subarray(start, start + len), targetStart); | |
} | |
return len; | |
}; | |
Buffer.prototype.fill = function fill(val, start, end, encoding) { | |
if (typeof val === "string") { | |
if (typeof start === "string") { | |
encoding = start; | |
start = 0; | |
end = this.length; | |
} else if (typeof end === "string") { | |
encoding = end; | |
end = this.length; | |
} | |
if (val.length === 1) { | |
var code = val.charCodeAt(0); | |
if (code < 256) { | |
val = code; | |
} | |
} | |
if (encoding !== void 0 && typeof encoding !== "string") { | |
throw new TypeError("encoding must be a string"); | |
} | |
if (typeof encoding === "string" && !Buffer.isEncoding(encoding)) { | |
throw new TypeError("Unknown encoding: " + encoding); | |
} | |
} else if (typeof val === "number") { | |
val = val & 255; | |
} | |
if (start < 0 || this.length < start || this.length < end) { | |
throw new RangeError("Out of range index"); | |
} | |
if (end <= start) { | |
return this; | |
} | |
start = start >>> 0; | |
end = end === void 0 ? this.length : end >>> 0; | |
if (!val) | |
val = 0; | |
var i; | |
if (typeof val === "number") { | |
for (i = start; i < end; ++i) { | |
this[i] = val; | |
} | |
} else { | |
var bytes = internalIsBuffer(val) ? val : utf8ToBytes(new Buffer(val, encoding).toString()); | |
var len = bytes.length; | |
for (i = 0; i < end - start; ++i) { | |
this[i + start] = bytes[i % len]; | |
} | |
} | |
return this; | |
}; | |
var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g; | |
function base64clean(str) { | |
str = stringtrim(str).replace(INVALID_BASE64_RE, ""); | |
if (str.length < 2) | |
return ""; | |
while (str.length % 4 !== 0) { | |
str = str + "="; | |
} | |
return str; | |
} | |
function stringtrim(str) { | |
if (str.trim) | |
return str.trim(); | |
return str.replace(/^\s+|\s+$/g, ""); | |
} | |
function toHex(n) { | |
if (n < 16) | |
return "0" + n.toString(16); | |
return n.toString(16); | |
} | |
function utf8ToBytes(string2, units) { | |
units = units || Infinity; | |
var codePoint; | |
var length = string2.length; | |
var leadSurrogate = null; | |
var bytes = []; | |
for (var i = 0; i < length; ++i) { | |
codePoint = string2.charCodeAt(i); | |
if (codePoint > 55295 && codePoint < 57344) { | |
if (!leadSurrogate) { | |
if (codePoint > 56319) { | |
if ((units -= 3) > -1) | |
bytes.push(239, 191, 189); | |
continue; | |
} else if (i + 1 === length) { | |
if ((units -= 3) > -1) | |
bytes.push(239, 191, 189); | |
continue; | |
} | |
leadSurrogate = codePoint; | |
continue; | |
} | |
if (codePoint < 56320) { | |
if ((units -= 3) > -1) | |
bytes.push(239, 191, 189); | |
leadSurrogate = codePoint; | |
continue; | |
} | |
codePoint = (leadSurrogate - 55296 << 10 | codePoint - 56320) + 65536; | |
} else if (leadSurrogate) { | |
if ((units -= 3) > -1) | |
bytes.push(239, 191, 189); | |
} | |
leadSurrogate = null; | |
if (codePoint < 128) { | |
if ((units -= 1) < 0) | |
break; | |
bytes.push(codePoint); | |
} else if (codePoint < 2048) { | |
if ((units -= 2) < 0) | |
break; | |
bytes.push(codePoint >> 6 | 192, codePoint & 63 | 128); | |
} else if (codePoint < 65536) { | |
if ((units -= 3) < 0) | |
break; | |
bytes.push(codePoint >> 12 | 224, codePoint >> 6 & 63 | 128, codePoint & 63 | 128); | |
} else if (codePoint < 1114112) { | |
if ((units -= 4) < 0) | |
break; | |
bytes.push(codePoint >> 18 | 240, codePoint >> 12 & 63 | 128, codePoint >> 6 & 63 | 128, codePoint & 63 | 128); | |
} else { | |
throw new Error("Invalid code point"); | |
} | |
} | |
return bytes; | |
} | |
function asciiToBytes(str) { | |
var byteArray = []; | |
for (var i = 0; i < str.length; ++i) { | |
byteArray.push(str.charCodeAt(i) & 255); | |
} | |
return byteArray; | |
} | |
function utf16leToBytes(str, units) { | |
var c, hi, lo; | |
var byteArray = []; | |
for (var i = 0; i < str.length; ++i) { | |
if ((units -= 2) < 0) | |
break; | |
c = str.charCodeAt(i); | |
hi = c >> 8; | |
lo = c % 256; | |
byteArray.push(lo); | |
byteArray.push(hi); | |
} | |
return byteArray; | |
} | |
function base64ToBytes(str) { | |
return toByteArray(base64clean(str)); | |
} | |
function blitBuffer(src, dst, offset, length) { | |
for (var i = 0; i < length; ++i) { | |
if (i + offset >= dst.length || i >= src.length) | |
break; | |
dst[i + offset] = src[i]; | |
} | |
return i; | |
} | |
function isnan(val) { | |
return val !== val; | |
} | |
function isBuffer(obj) { | |
return obj != null && (!!obj._isBuffer || isFastBuffer(obj) || isSlowBuffer(obj)); | |
} | |
function isFastBuffer(obj) { | |
return !!obj.constructor && typeof obj.constructor.isBuffer === "function" && obj.constructor.isBuffer(obj); | |
} | |
function isSlowBuffer(obj) { | |
return typeof obj.readFloatLE === "function" && typeof obj.slice === "function" && isFastBuffer(obj.slice(0, 0)); | |
} | |
function defaultSetTimout() { | |
throw new Error("setTimeout has not been defined"); | |
} | |
function defaultClearTimeout() { | |
throw new Error("clearTimeout has not been defined"); | |
} | |
var cachedSetTimeout = defaultSetTimout; | |
var cachedClearTimeout = defaultClearTimeout; | |
var globalContext; | |
if (typeof window !== "undefined") { | |
globalContext = window; | |
} else if (typeof self !== "undefined") { | |
globalContext = self; | |
} else { | |
globalContext = {}; | |
} | |
if (typeof globalContext.setTimeout === "function") { | |
cachedSetTimeout = setTimeout; | |
} | |
if (typeof globalContext.clearTimeout === "function") { | |
cachedClearTimeout = clearTimeout; | |
} | |
function runTimeout(fun) { | |
if (cachedSetTimeout === setTimeout) { | |
return setTimeout(fun, 0); | |
} | |
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { | |
cachedSetTimeout = setTimeout; | |
return setTimeout(fun, 0); | |
} | |
try { | |
return cachedSetTimeout(fun, 0); | |
} catch (e) { | |
try { | |
return cachedSetTimeout.call(null, fun, 0); | |
} catch (e2) { | |
return cachedSetTimeout.call(this, fun, 0); | |
} | |
} | |
} | |
function runClearTimeout(marker) { | |
if (cachedClearTimeout === clearTimeout) { | |
return clearTimeout(marker); | |
} | |
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { | |
cachedClearTimeout = clearTimeout; | |
return clearTimeout(marker); | |
} | |
try { | |
return cachedClearTimeout(marker); | |
} catch (e) { | |
try { | |
return cachedClearTimeout.call(null, marker); | |
} catch (e2) { | |
return cachedClearTimeout.call(this, marker); | |
} | |
} | |
} | |
var queue = []; | |
var draining = false; | |
var currentQueue; | |
var queueIndex = -1; | |
function cleanUpNextTick() { | |
if (!draining || !currentQueue) { | |
return; | |
} | |
draining = false; | |
if (currentQueue.length) { | |
queue = currentQueue.concat(queue); | |
} else { | |
queueIndex = -1; | |
} | |
if (queue.length) { | |
drainQueue(); | |
} | |
} | |
function drainQueue() { | |
if (draining) { | |
return; | |
} | |
var timeout = runTimeout(cleanUpNextTick); | |
draining = true; | |
var len = queue.length; | |
while (len) { | |
currentQueue = queue; | |
queue = []; | |
while (++queueIndex < len) { | |
if (currentQueue) { | |
currentQueue[queueIndex].run(); | |
} | |
} | |
queueIndex = -1; | |
len = queue.length; | |
} | |
currentQueue = null; | |
draining = false; | |
runClearTimeout(timeout); | |
} | |
function nextTick(fun) { | |
var args = new Array(arguments.length - 1); | |
if (arguments.length > 1) { | |
for (var i = 1; i < arguments.length; i++) { | |
args[i - 1] = arguments[i]; | |
} | |
} | |
queue.push(new Item(fun, args)); | |
if (queue.length === 1 && !draining) { | |
runTimeout(drainQueue); | |
} | |
} | |
function Item(fun, array2) { | |
this.fun = fun; | |
this.array = array2; | |
} | |
Item.prototype.run = function() { | |
this.fun.apply(null, this.array); | |
}; | |
var title = "browser"; | |
var platform = "browser"; | |
var browser = true; | |
var argv = []; | |
var version = ""; | |
var versions = {}; | |
var release = {}; | |
var config = {}; | |
function noop() { | |
} | |
var on = noop; | |
var addListener = noop; | |
var once = noop; | |
var off = noop; | |
var removeListener = noop; | |
var removeAllListeners = noop; | |
var emit = noop; | |
function binding(name) { | |
throw new Error("process.binding is not supported"); | |
} | |
function cwd() { | |
return "/"; | |
} | |
function chdir(dir) { | |
throw new Error("process.chdir is not supported"); | |
} | |
function umask() { | |
return 0; | |
} | |
var performance = globalContext.performance || {}; | |
var performanceNow = performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function() { | |
return new Date().getTime(); | |
}; | |
function hrtime(previousTimestamp) { | |
var clocktime = performanceNow.call(performance) * 1e-3; | |
var seconds = Math.floor(clocktime); | |
var nanoseconds = Math.floor(clocktime % 1 * 1e9); | |
if (previousTimestamp) { | |
seconds = seconds - previousTimestamp[0]; | |
nanoseconds = nanoseconds - previousTimestamp[1]; | |
if (nanoseconds < 0) { | |
seconds--; | |
nanoseconds += 1e9; | |
} | |
} | |
return [seconds, nanoseconds]; | |
} | |
var startTime = new Date(); | |
function uptime() { | |
var currentTime = new Date(); | |
var dif = currentTime - startTime; | |
return dif / 1e3; | |
} | |
var process = { | |
nextTick, | |
title, | |
browser, | |
env: {NODE_ENV: "production"}, | |
argv, | |
version, | |
versions, | |
on, | |
addListener, | |
once, | |
off, | |
removeListener, | |
removeAllListeners, | |
emit, | |
binding, | |
cwd, | |
chdir, | |
umask, | |
hrtime, | |
platform, | |
release, | |
config, | |
uptime | |
}; | |
var inherits; | |
if (typeof Object.create === "function") { | |
inherits = function inherits2(ctor, superCtor) { | |
ctor.super_ = superCtor; | |
ctor.prototype = Object.create(superCtor.prototype, { | |
constructor: { | |
value: ctor, | |
enumerable: false, | |
writable: true, | |
configurable: true | |
} | |
}); | |
}; | |
} else { | |
inherits = function inherits2(ctor, superCtor) { | |
ctor.super_ = superCtor; | |
var TempCtor = function() { | |
}; | |
TempCtor.prototype = superCtor.prototype; | |
ctor.prototype = new TempCtor(); | |
ctor.prototype.constructor = ctor; | |
}; | |
} | |
var inherits$1 = inherits; | |
function inspect2(obj, opts) { | |
var ctx = { | |
seen: [], | |
stylize: stylizeNoColor | |
}; | |
if (arguments.length >= 3) | |
ctx.depth = arguments[2]; | |
if (arguments.length >= 4) | |
ctx.colors = arguments[3]; | |
if (isBoolean(opts)) { | |
ctx.showHidden = opts; | |
} else if (opts) { | |
_extend(ctx, opts); | |
} | |
if (isUndefined(ctx.showHidden)) | |
ctx.showHidden = false; | |
if (isUndefined(ctx.depth)) | |
ctx.depth = 2; | |
if (isUndefined(ctx.colors)) | |
ctx.colors = false; | |
if (isUndefined(ctx.customInspect)) | |
ctx.customInspect = true; | |
if (ctx.colors) | |
ctx.stylize = stylizeWithColor; | |
return formatValue(ctx, obj, ctx.depth); | |
} | |
inspect2.colors = { | |
bold: [1, 22], | |
italic: [3, 23], | |
underline: [4, 24], | |
inverse: [7, 27], | |
white: [37, 39], | |
grey: [90, 39], | |
black: [30, 39], | |
blue: [34, 39], | |
cyan: [36, 39], | |
green: [32, 39], | |
magenta: [35, 39], | |
red: [31, 39], | |
yellow: [33, 39] | |
}; | |
inspect2.styles = { | |
special: "cyan", | |
number: "yellow", | |
boolean: "yellow", | |
undefined: "grey", | |
null: "bold", | |
string: "green", | |
date: "magenta", | |
regexp: "red" | |
}; | |
function stylizeWithColor(str, styleType) { | |
var style = inspect2.styles[styleType]; | |
if (style) { | |
return "[" + inspect2.colors[style][0] + "m" + str + "[" + inspect2.colors[style][1] + "m"; | |
} else { | |
return str; | |
} | |
} | |
function stylizeNoColor(str, styleType) { | |
return str; | |
} | |
function arrayToHash(array2) { | |
var hash = {}; | |
array2.forEach(function(val, idx) { | |
hash[val] = true; | |
}); | |
return hash; | |
} | |
function formatValue(ctx, value, recurseTimes) { | |
if (ctx.customInspect && value && isFunction(value.inspect) && value.inspect !== inspect2 && !(value.constructor && value.constructor.prototype === value)) { | |
var ret = value.inspect(recurseTimes, ctx); | |
if (!isString(ret)) { | |
ret = formatValue(ctx, ret, recurseTimes); | |
} | |
return ret; | |
} | |
var primitive = formatPrimitive(ctx, value); | |
if (primitive) { | |
return primitive; | |
} | |
var keys2 = Object.keys(value); | |
var visibleKeys = arrayToHash(keys2); | |
if (ctx.showHidden) { | |
keys2 = Object.getOwnPropertyNames(value); | |
} | |
if (isError(value) && (keys2.indexOf("message") >= 0 || keys2.indexOf("description") >= 0)) { | |
return formatError(value); | |
} | |
if (keys2.length === 0) { | |
if (isFunction(value)) { | |
var name = value.name ? ": " + value.name : ""; | |
return ctx.stylize("[Function" + name + "]", "special"); | |
} | |
if (isRegExp(value)) { | |
return ctx.stylize(RegExp.prototype.toString.call(value), "regexp"); | |
} | |
if (isDate(value)) { | |
return ctx.stylize(Date.prototype.toString.call(value), "date"); | |
} | |
if (isError(value)) { | |
return formatError(value); | |
} | |
} | |
var base = "", array2 = false, braces = ["{", "}"]; | |
if (isArray$1(value)) { | |
array2 = true; | |
braces = ["[", "]"]; | |
} | |
if (isFunction(value)) { | |
var n = value.name ? ": " + value.name : ""; | |
base = " [Function" + n + "]"; | |
} | |
if (isRegExp(value)) { | |
base = " " + RegExp.prototype.toString.call(value); | |
} | |
if (isDate(value)) { | |
base = " " + Date.prototype.toUTCString.call(value); | |
} | |
if (isError(value)) { | |
base = " " + formatError(value); | |
} | |
if (keys2.length === 0 && (!array2 || value.length == 0)) { | |
return braces[0] + base + braces[1]; | |
} | |
if (recurseTimes < 0) { | |
if (isRegExp(value)) { | |
return ctx.stylize(RegExp.prototype.toString.call(value), "regexp"); | |
} else { | |
return ctx.stylize("[Object]", "special"); | |
} | |
} | |
ctx.seen.push(value); | |
var output; | |
if (array2) { | |
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys2); | |
} else { | |
output = keys2.map(function(key) { | |
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array2); | |
}); | |
} | |
ctx.seen.pop(); | |
return reduceToSingleString(output, base, braces); | |
} | |
function formatPrimitive(ctx, value) { | |
if (isUndefined(value)) | |
return ctx.stylize("undefined", "undefined"); | |
if (isString(value)) { | |
var simple = "'" + JSON.stringify(value).replace(/^"|"$/g, "").replace(/'/g, "\\'").replace(/\\"/g, '"') + "'"; | |
return ctx.stylize(simple, "string"); | |
} | |
if (isNumber(value)) | |
return ctx.stylize("" + value, "number"); | |
if (isBoolean(value)) | |
return ctx.stylize("" + value, "boolean"); | |
if (isNull(value)) | |
return ctx.stylize("null", "null"); | |
} | |
function formatError(value) { | |
return "[" + Error.prototype.toString.call(value) + "]"; | |
} | |
function formatArray(ctx, value, recurseTimes, visibleKeys, keys2) { | |
var output = []; | |
for (var i = 0, l = value.length; i < l; ++i) { | |
if (hasOwnProperty(value, String(i))) { | |
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); | |
} else { | |
output.push(""); | |
} | |
} | |
keys2.forEach(function(key) { | |
if (!key.match(/^\d+$/)) { | |
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); | |
} | |
}); | |
return output; | |
} | |
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array2) { | |
var name, str, desc; | |
desc = Object.getOwnPropertyDescriptor(value, key) || {value: value[key]}; | |
if (desc.get) { | |
if (desc.set) { | |
str = ctx.stylize("[Getter/Setter]", "special"); | |
} else { | |
str = ctx.stylize("[Getter]", "special"); | |
} | |
} else { | |
if (desc.set) { | |
str = ctx.stylize("[Setter]", "special"); | |
} | |
} | |
if (!hasOwnProperty(visibleKeys, key)) { | |
name = "[" + key + "]"; | |
} | |
if (!str) { | |
if (ctx.seen.indexOf(desc.value) < 0) { | |
if (isNull(recurseTimes)) { | |
str = formatValue(ctx, desc.value, null); | |
} else { | |
str = formatValue(ctx, desc.value, recurseTimes - 1); | |
} | |
if (str.indexOf("\n") > -1) { | |
if (array2) { | |
str = str.split("\n").map(function(line) { | |
return " " + line; | |
}).join("\n").substr(2); | |
} else { | |
str = "\n" + str.split("\n").map(function(line) { | |
return " " + line; | |
}).join("\n"); | |
} | |
} | |
} else { | |
str = ctx.stylize("[Circular]", "special"); | |
} | |
} | |
if (isUndefined(name)) { | |
if (array2 && key.match(/^\d+$/)) { | |
return str; | |
} | |
name = JSON.stringify("" + key); | |
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { | |
name = name.substr(1, name.length - 2); | |
name = ctx.stylize(name, "name"); | |
} else { | |
name = name.replace(/'/g, "\\'").replace(/\\"/g, '"').replace(/(^"|"$)/g, "'"); | |
name = ctx.stylize(name, "string"); | |
} | |
} | |
return name + ": " + str; | |
} | |
function reduceToSingleString(output, base, braces) { | |
var length = output.reduce(function(prev, cur) { | |
if (cur.indexOf("\n") >= 0) | |
; | |
return prev + cur.replace(/\u001b\[\d\d?m/g, "").length + 1; | |
}, 0); | |
if (length > 60) { | |
return braces[0] + (base === "" ? "" : base + "\n ") + " " + output.join(",\n ") + " " + braces[1]; | |
} | |
return braces[0] + base + " " + output.join(", ") + " " + braces[1]; | |
} | |
function isArray$1(ar) { | |
return Array.isArray(ar); | |
} | |
function isBoolean(arg) { | |
return typeof arg === "boolean"; | |
} | |
function isNull(arg) { | |
return arg === null; | |
} | |
function isNumber(arg) { | |
return typeof arg === "number"; | |
} | |
function isString(arg) { | |
return typeof arg === "string"; | |
} | |
function isUndefined(arg) { | |
return arg === void 0; | |
} | |
function isRegExp(re) { | |
return isObject(re) && objectToString(re) === "[object RegExp]"; | |
} | |
function isObject(arg) { | |
return typeof arg === "object" && arg !== null; | |
} | |
function isDate(d) { | |
return isObject(d) && objectToString(d) === "[object Date]"; | |
} | |
function isError(e) { | |
return isObject(e) && (objectToString(e) === "[object Error]" || e instanceof Error); | |
} | |
function isFunction(arg) { | |
return typeof arg === "function"; | |
} | |
function isPrimitive(arg) { | |
return arg === null || typeof arg === "boolean" || typeof arg === "number" || typeof arg === "string" || typeof arg === "symbol" || typeof arg === "undefined"; | |
} | |
function objectToString(o) { | |
return Object.prototype.toString.call(o); | |
} | |
function _extend(origin, add) { | |
if (!add || !isObject(add)) | |
return origin; | |
var keys2 = Object.keys(add); | |
var i = keys2.length; | |
while (i--) { | |
origin[keys2[i]] = add[keys2[i]]; | |
} | |
return origin; | |
} | |
function hasOwnProperty(obj, prop) { | |
return Object.prototype.hasOwnProperty.call(obj, prop); | |
} | |
function compare3(a, b) { | |
if (a === b) { | |
return 0; | |
} | |
var x = a.length; | |
var y = b.length; | |
for (var i = 0, len = Math.min(x, y); i < len; ++i) { | |
if (a[i] !== b[i]) { | |
x = a[i]; | |
y = b[i]; | |
break; | |
} | |
} | |
if (x < y) { | |
return -1; | |
} | |
if (y < x) { | |
return 1; | |
} | |
return 0; | |
} | |
var hasOwn = Object.prototype.hasOwnProperty; | |
var objectKeys = Object.keys || function(obj) { | |
var keys2 = []; | |
for (var key in obj) { | |
if (hasOwn.call(obj, key)) | |
keys2.push(key); | |
} | |
return keys2; | |
}; | |
var pSlice = Array.prototype.slice; | |
var _functionsHaveNames; | |
function functionsHaveNames() { | |
if (typeof _functionsHaveNames !== "undefined") { | |
return _functionsHaveNames; | |
} | |
return _functionsHaveNames = function() { | |
return function foo() { | |
}.name === "foo"; | |
}(); | |
} | |
function pToString(obj) { | |
return Object.prototype.toString.call(obj); | |
} | |
function isView(arrbuf) { | |
if (isBuffer(arrbuf)) { | |
return false; | |
} | |
if (typeof global$1.ArrayBuffer !== "function") { | |
return false; | |
} | |
if (typeof ArrayBuffer.isView === "function") { | |
return ArrayBuffer.isView(arrbuf); | |
} | |
if (!arrbuf) { | |
return false; | |
} | |
if (arrbuf instanceof DataView) { | |
return true; | |
} | |
if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { | |
return true; | |
} | |
return false; | |
} | |
function assert(value, message) { | |
if (!value) | |
fail(value, true, message, "==", ok); | |
} | |
var regex = /\s*function\s+([^\(\s]*)\s*/; | |
function getName(func) { | |
if (!isFunction(func)) { | |
return; | |
} | |
if (functionsHaveNames()) { | |
return func.name; | |
} | |
var str = func.toString(); | |
var match = str.match(regex); | |
return match && match[1]; | |
} | |
assert.AssertionError = AssertionError; | |
function AssertionError(options) { | |
this.name = "AssertionError"; | |
this.actual = options.actual; | |
this.expected = options.expected; | |
this.operator = options.operator; | |
if (options.message) { | |
this.message = options.message; | |
this.generatedMessage = false; | |
} else { | |
this.message = getMessage(this); | |
this.generatedMessage = true; | |
} | |
var stackStartFunction = options.stackStartFunction || fail; | |
if (Error.captureStackTrace) { | |
Error.captureStackTrace(this, stackStartFunction); | |
} else { | |
var err = new Error(); | |
if (err.stack) { | |
var out = err.stack; | |
var fn_name = getName(stackStartFunction); | |
var idx = out.indexOf("\n" + fn_name); | |
if (idx >= 0) { | |
var next_line = out.indexOf("\n", idx + 1); | |
out = out.substring(next_line + 1); | |
} | |
this.stack = out; | |
} | |
} | |
} | |
inherits$1(AssertionError, Error); | |
function truncate(s, n) { | |
if (typeof s === "string") { | |
return s.length < n ? s : s.slice(0, n); | |
} else { | |
return s; | |
} | |
} | |
function inspect$1(something) { | |
if (functionsHaveNames() || !isFunction(something)) { | |
return inspect2(something); | |
} | |
var rawname = getName(something); | |
var name = rawname ? ": " + rawname : ""; | |
return "[Function" + name + "]"; | |
} | |
function getMessage(self2) { | |
return truncate(inspect$1(self2.actual), 128) + " " + self2.operator + " " + truncate(inspect$1(self2.expected), 128); | |
} | |
function fail(actual, expected, message, operator, stackStartFunction) { | |
throw new AssertionError({ | |
message, | |
actual, | |
expected, | |
operator, | |
stackStartFunction | |
}); | |
} | |
assert.fail = fail; | |
function ok(value, message) { | |
if (!value) | |
fail(value, true, message, "==", ok); | |
} | |
assert.ok = ok; | |
assert.equal = equal; | |
function equal(actual, expected, message) { | |
if (actual != expected) | |
fail(actual, expected, message, "==", equal); | |
} | |
assert.notEqual = notEqual; | |
function notEqual(actual, expected, message) { | |
if (actual == expected) { | |
fail(actual, expected, message, "!=", notEqual); | |
} | |
} | |
assert.deepEqual = deepEqual; | |
function deepEqual(actual, expected, message) { | |
if (!_deepEqual(actual, expected, false)) { | |
fail(actual, expected, message, "deepEqual", deepEqual); | |
} | |
} | |
assert.deepStrictEqual = deepStrictEqual; | |
function deepStrictEqual(actual, expected, message) { | |
if (!_deepEqual(actual, expected, true)) { | |
fail(actual, expected, message, "deepStrictEqual", deepStrictEqual); | |
} | |
} | |
function _deepEqual(actual, expected, strict, memos) { | |
if (actual === expected) { | |
return true; | |
} else if (isBuffer(actual) && isBuffer(expected)) { | |
return compare3(actual, expected) === 0; | |
} else if (isDate(actual) && isDate(expected)) { | |
return actual.getTime() === expected.getTime(); | |
} else if (isRegExp(actual) && isRegExp(expected)) { | |
return actual.source === expected.source && actual.global === expected.global && actual.multiline === expected.multiline && actual.lastIndex === expected.lastIndex && actual.ignoreCase === expected.ignoreCase; | |
} else if ((actual === null || typeof actual !== "object") && (expected === null || typeof expected !== "object")) { | |
return strict ? actual === expected : actual == expected; | |
} else if (isView(actual) && isView(expected) && pToString(actual) === pToString(expected) && !(actual instanceof Float32Array || actual instanceof Float64Array)) { | |
return compare3(new Uint8Array(actual.buffer), new Uint8Array(expected.buffer)) === 0; | |
} else if (isBuffer(actual) !== isBuffer(expected)) { | |
return false; | |
} else { | |
memos = memos || {actual: [], expected: []}; | |
var actualIndex = memos.actual.indexOf(actual); | |
if (actualIndex !== -1) { | |
if (actualIndex === memos.expected.indexOf(expected)) { | |
return true; | |
} | |
} | |
memos.actual.push(actual); | |
memos.expected.push(expected); | |
return objEquiv(actual, expected, strict, memos); | |
} | |
} | |
function isArguments(object) { | |
return Object.prototype.toString.call(object) == "[object Arguments]"; | |
} | |
function objEquiv(a, b, strict, actualVisitedObjects) { | |
if (a === null || a === void 0 || b === null || b === void 0) | |
return false; | |
if (isPrimitive(a) || isPrimitive(b)) | |
return a === b; | |
if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) | |
return false; | |
var aIsArgs = isArguments(a); | |
var bIsArgs = isArguments(b); | |
if (aIsArgs && !bIsArgs || !aIsArgs && bIsArgs) | |
return false; | |
if (aIsArgs) { | |
a = pSlice.call(a); | |
b = pSlice.call(b); | |
return _deepEqual(a, b, strict); | |
} | |
var ka = objectKeys(a); | |
var kb = objectKeys(b); | |
var key, i; | |
if (ka.length !== kb.length) | |
return false; | |
ka.sort(); | |
kb.sort(); | |
for (i = ka.length - 1; i >= 0; i--) { | |
if (ka[i] !== kb[i]) | |
return false; | |
} | |
for (i = ka.length - 1; i >= 0; i--) { | |
key = ka[i]; | |
if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) | |
return false; | |
} | |
return true; | |
} | |
assert.notDeepEqual = notDeepEqual; | |
function notDeepEqual(actual, expected, message) { | |
if (_deepEqual(actual, expected, false)) { | |
fail(actual, expected, message, "notDeepEqual", notDeepEqual); | |
} | |
} | |
assert.notDeepStrictEqual = notDeepStrictEqual; | |
function notDeepStrictEqual(actual, expected, message) { | |
if (_deepEqual(actual, expected, true)) { | |
fail(actual, expected, message, "notDeepStrictEqual", notDeepStrictEqual); | |
} | |
} | |
assert.strictEqual = strictEqual; | |
function strictEqual(actual, expected, message) { | |
if (actual !== expected) { | |
fail(actual, expected, message, "===", strictEqual); | |
} | |
} | |
assert.notStrictEqual = notStrictEqual; | |
function notStrictEqual(actual, expected, message) { | |
if (actual === expected) { | |
fail(actual, expected, message, "!==", notStrictEqual); | |
} | |
} | |
function expectedException(actual, expected) { | |
if (!actual || !expected) { | |
return false; | |
} | |
if (Object.prototype.toString.call(expected) == "[object RegExp]") { | |
return expected.test(actual); | |
} | |
try { | |
if (actual instanceof expected) { | |
return true; | |
} | |
} catch (e) { | |
} | |
if (Error.isPrototypeOf(expected)) { | |
return false; | |
} | |
return expected.call({}, actual) === true; | |
} | |
function _tryBlock(block) { | |
var error; | |
try { | |
block(); | |
} catch (e) { | |
error = e; | |
} | |
return error; | |
} | |
function _throws(shouldThrow, block, expected, message) { | |
var actual; | |
if (typeof block !== "function") { | |
throw new TypeError('"block" argument must be a function'); | |
} | |
if (typeof expected === "string") { | |
message = expected; | |
expected = null; | |
} | |
actual = _tryBlock(block); | |
message = (expected && expected.name ? " (" + expected.name + ")." : ".") + (message ? " " + message : "."); | |
if (shouldThrow && !actual) { | |
fail(actual, expected, "Missing expected exception" + message); | |
} | |
var userProvidedMessage = typeof message === "string"; | |
var isUnwantedException = !shouldThrow && isError(actual); | |
var isUnexpectedException = !shouldThrow && actual && !expected; | |
if (isUnwantedException && userProvidedMessage && expectedException(actual, expected) || isUnexpectedException) { | |
fail(actual, expected, "Got unwanted exception" + message); | |
} | |
if (shouldThrow && actual && expected && !expectedException(actual, expected) || !shouldThrow && actual) { | |
throw actual; | |
} | |
} | |
assert.throws = throws; | |
function throws(block, error, message) { | |
_throws(true, block, error, message); | |
} | |
assert.doesNotThrow = doesNotThrow; | |
function doesNotThrow(block, error, message) { | |
_throws(false, block, error, message); | |
} | |
assert.ifError = ifError; | |
function ifError(err) { | |
if (err) | |
throw err; | |
} | |
var assert$1 = assert; | |
var domain; | |
function EventHandlers() { | |
} | |
EventHandlers.prototype = Object.create(null); | |
function EventEmitter() { | |
EventEmitter.init.call(this); | |
} | |
EventEmitter.EventEmitter = EventEmitter; | |
EventEmitter.usingDomains = false; | |
EventEmitter.prototype.domain = void 0; | |
EventEmitter.prototype._events = void 0; | |
EventEmitter.prototype._maxListeners = void 0; | |
EventEmitter.defaultMaxListeners = 10; | |
EventEmitter.init = function() { | |
this.domain = null; | |
if (EventEmitter.usingDomains) { | |
if (domain.active) | |
; | |
} | |
if (!this._events || this._events === Object.getPrototypeOf(this)._events) { | |
this._events = new EventHandlers(); | |
this._eventsCount = 0; | |
} | |
this._maxListeners = this._maxListeners || void 0; | |
}; | |
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { | |
if (typeof n !== "number" || n < 0 || isNaN(n)) | |
throw new TypeError('"n" argument must be a positive number'); | |
this._maxListeners = n; | |
return this; | |
}; | |
function $getMaxListeners(that) { | |
if (that._maxListeners === void 0) | |
return EventEmitter.defaultMaxListeners; | |
return that._maxListeners; | |
} | |
EventEmitter.prototype.getMaxListeners = function getMaxListeners() { | |
return $getMaxListeners(this); | |
}; | |
function emitNone(handler, isFn, self2) { | |
if (isFn) | |
handler.call(self2); | |
else { | |
var len = handler.length; | |
var listeners2 = arrayClone(handler, len); | |
for (var i = 0; i < len; ++i) | |
listeners2[i].call(self2); | |
} | |
} | |
function emitOne(handler, isFn, self2, arg1) { | |
if (isFn) | |
handler.call(self2, arg1); | |
else { | |
var len = handler.length; | |
var listeners2 = arrayClone(handler, len); | |
for (var i = 0; i < len; ++i) | |
listeners2[i].call(self2, arg1); | |
} | |
} | |
function emitTwo(handler, isFn, self2, arg1, arg2) { | |
if (isFn) | |
handler.call(self2, arg1, arg2); | |
else { | |
var len = handler.length; | |
var listeners2 = arrayClone(handler, len); | |
for (var i = 0; i < len; ++i) | |
listeners2[i].call(self2, arg1, arg2); | |
} | |
} | |
function emitThree(handler, isFn, self2, arg1, arg2, arg3) { | |
if (isFn) | |
handler.call(self2, arg1, arg2, arg3); | |
else { | |
var len = handler.length; | |
var listeners2 = arrayClone(handler, len); | |
for (var i = 0; i < len; ++i) | |
listeners2[i].call(self2, arg1, arg2, arg3); | |
} | |
} | |
function emitMany(handler, isFn, self2, args) { | |
if (isFn) | |
handler.apply(self2, args); | |
else { | |
var len = handler.length; | |
var listeners2 = arrayClone(handler, len); | |
for (var i = 0; i < len; ++i) | |
listeners2[i].apply(self2, args); | |
} | |
} | |
EventEmitter.prototype.emit = function emit2(type) { | |
var er, handler, len, args, i, events2, domain2; | |
var doError = type === "error"; | |
events2 = this._events; | |
if (events2) | |
doError = doError && events2.error == null; | |
else if (!doError) | |
return false; | |
domain2 = this.domain; | |
if (doError) { | |
er = arguments[1]; | |
if (domain2) { | |
if (!er) | |
er = new Error('Uncaught, unspecified "error" event'); | |
er.domainEmitter = this; | |
er.domain = domain2; | |
er.domainThrown = false; | |
domain2.emit("error", er); | |
} else if (er instanceof Error) { | |
throw er; | |
} else { | |
var err = new Error('Uncaught, unspecified "error" event. (' + er + ")"); | |
err.context = er; | |
throw err; | |
} | |
return false; | |
} | |
handler = events2[type]; | |
if (!handler) | |
return false; | |
var isFn = typeof handler === "function"; | |
len = arguments.length; | |
switch (len) { | |
case 1: | |
emitNone(handler, isFn, this); | |
break; | |
case 2: | |
emitOne(handler, isFn, this, arguments[1]); | |
break; | |
case 3: | |
emitTwo(handler, isFn, this, arguments[1], arguments[2]); | |
break; | |
case 4: | |
emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); | |
break; | |
default: | |
args = new Array(len - 1); | |
for (i = 1; i < len; i++) | |
args[i - 1] = arguments[i]; | |
emitMany(handler, isFn, this, args); | |
} | |
return true; | |
}; | |
function _addListener(target, type, listener, prepend) { | |
var m; | |
var events2; | |
var existing; | |
if (typeof listener !== "function") | |
throw new TypeError('"listener" argument must be a function'); | |
events2 = target._events; | |
if (!events2) { | |
events2 = target._events = new EventHandlers(); | |
target._eventsCount = 0; | |
} else { | |
if (events2.newListener) { | |
target.emit("newListener", type, listener.listener ? listener.listener : listener); | |
events2 = target._events; | |
} | |
existing = events2[type]; | |
} | |
if (!existing) { | |
existing = events2[type] = listener; | |
++target._eventsCount; | |
} else { | |
if (typeof existing === "function") { | |
existing = events2[type] = prepend ? [listener, existing] : [existing, listener]; | |
} else { | |
if (prepend) { | |
existing.unshift(listener); | |
} else { | |
existing.push(listener); | |
} | |
} | |
if (!existing.warned) { | |
m = $getMaxListeners(target); | |
if (m && m > 0 && existing.length > m) { | |
existing.warned = true; | |
var w = new Error("Possible EventEmitter memory leak detected. " + existing.length + " " + type + " listeners added. Use emitter.setMaxListeners() to increase limit"); | |
w.name = "MaxListenersExceededWarning"; | |
w.emitter = target; | |
w.type = type; | |
w.count = existing.length; | |
emitWarning(w); | |
} | |
} | |
} | |
return target; | |
} | |
function emitWarning(e) { | |
typeof console.warn === "function" ? console.warn(e) : console.log(e); | |
} | |
EventEmitter.prototype.addListener = function addListener2(type, listener) { | |
return _addListener(this, type, listener, false); | |
}; | |
EventEmitter.prototype.on = EventEmitter.prototype.addListener; | |
EventEmitter.prototype.prependListener = function prependListener(type, listener) { | |
return _addListener(this, type, listener, true); | |
}; | |
function _onceWrap(target, type, listener) { | |
var fired = false; | |
function g() { | |
target.removeListener(type, g); | |
if (!fired) { | |
fired = true; | |
listener.apply(target, arguments); | |
} | |
} | |
g.listener = listener; | |
return g; | |
} | |
EventEmitter.prototype.once = function once2(type, listener) { | |
if (typeof listener !== "function") | |
throw new TypeError('"listener" argument must be a function'); | |
this.on(type, _onceWrap(this, type, listener)); | |
return this; | |
}; | |
EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) { | |
if (typeof listener !== "function") | |
throw new TypeError('"listener" argument must be a function'); | |
this.prependListener(type, _onceWrap(this, type, listener)); | |
return this; | |
}; | |
EventEmitter.prototype.removeListener = function removeListener2(type, listener) { | |
var list2, events2, position, i, originalListener; | |
if (typeof listener !== "function") | |
throw new TypeError('"listener" argument must be a function'); | |
events2 = this._events; | |
if (!events2) | |
return this; | |
list2 = events2[type]; | |
if (!list2) | |
return this; | |
if (list2 === listener || list2.listener && list2.listener === listener) { | |
if (--this._eventsCount === 0) | |
this._events = new EventHandlers(); | |
else { | |
delete events2[type]; | |
if (events2.removeListener) | |
this.emit("removeListener", type, list2.listener || listener); | |
} | |
} else if (typeof list2 !== "function") { | |
position = -1; | |
for (i = list2.length; i-- > 0; ) { | |
if (list2[i] === listener || list2[i].listener && list2[i].listener === listener) { | |
originalListener = list2[i].listener; | |
position = i; | |
break; | |
} | |
} | |
if (position < 0) | |
return this; | |
if (list2.length === 1) { | |
list2[0] = void 0; | |
if (--this._eventsCount === 0) { | |
this._events = new EventHandlers(); | |
return this; | |
} else { | |
delete events2[type]; | |
} | |
} else { | |
spliceOne(list2, position); | |
} | |
if (events2.removeListener) | |
this.emit("removeListener", type, originalListener || listener); | |
} | |
return this; | |
}; | |
EventEmitter.prototype.removeAllListeners = function removeAllListeners2(type) { | |
var listeners2, events2; | |
events2 = this._events; | |
if (!events2) | |
return this; | |
if (!events2.removeListener) { | |
if (arguments.length === 0) { | |
this._events = new EventHandlers(); | |
this._eventsCount = 0; | |
} else if (events2[type]) { | |
if (--this._eventsCount === 0) | |
this._events = new EventHandlers(); | |
else | |
delete events2[type]; | |
} | |
return this; | |
} | |
if (arguments.length === 0) { | |
var keys2 = Object.keys(events2); | |
for (var i = 0, key; i < keys2.length; ++i) { | |
key = keys2[i]; | |
if (key === "removeListener") | |
continue; | |
this.removeAllListeners(key); | |
} | |
this.removeAllListeners("removeListener"); | |
this._events = new EventHandlers(); | |
this._eventsCount = 0; | |
return this; | |
} | |
listeners2 = events2[type]; | |
if (typeof listeners2 === "function") { | |
this.removeListener(type, listeners2); | |
} else if (listeners2) { | |
do { | |
this.removeListener(type, listeners2[listeners2.length - 1]); | |
} while (listeners2[0]); | |
} | |
return this; | |
}; | |
EventEmitter.prototype.listeners = function listeners(type) { | |
var evlistener; | |
var ret; | |
var events2 = this._events; | |
if (!events2) | |
ret = []; | |
else { | |
evlistener = events2[type]; | |
if (!evlistener) | |
ret = []; | |
else if (typeof evlistener === "function") | |
ret = [evlistener.listener || evlistener]; | |
else | |
ret = unwrapListeners(evlistener); | |
} | |
return ret; | |
}; | |
EventEmitter.listenerCount = function(emitter, type) { | |
if (typeof emitter.listenerCount === "function") { | |
return emitter.listenerCount(type); | |
} else { | |
return listenerCount.call(emitter, type); | |
} | |
}; | |
EventEmitter.prototype.listenerCount = listenerCount; | |
function listenerCount(type) { | |
var events2 = this._events; | |
if (events2) { | |
var evlistener = events2[type]; | |
if (typeof evlistener === "function") { | |
return 1; | |
} else if (evlistener) { | |
return evlistener.length; | |
} | |
} | |
return 0; | |
} | |
EventEmitter.prototype.eventNames = function eventNames() { | |
return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; | |
}; | |
function spliceOne(list2, index) { | |
for (var i = index, k = i + 1, n = list2.length; k < n; i += 1, k += 1) | |
list2[i] = list2[k]; | |
list2.pop(); | |
} | |
function arrayClone(arr, i) { | |
var copy2 = new Array(i); | |
while (i--) | |
copy2[i] = arr[i]; | |
return copy2; | |
} | |
function unwrapListeners(arr) { | |
var ret = new Array(arr.length); | |
for (var i = 0; i < ret.length; ++i) { | |
ret[i] = arr[i].listener || arr[i]; | |
} | |
return ret; | |
} | |
var events = /* @__PURE__ */ //Object.freeze({ | |
// __proto__: null, | |
// default: EventEmitter, | |
EventEmitter | |
//}) | |
; | |
function createCommonjsModule(fn2, basedir, module) { | |
return module = { | |
path: basedir, | |
exports: {}, | |
require: function(path, base) { | |
return commonjsRequire(path, base === void 0 || base === null ? module.path : base); | |
} | |
}, fn2(module, module.exports), module.exports; | |
} | |
function commonjsRequire() { | |
throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs"); | |
} | |
var utils = createCommonjsModule(function(module, exports) { | |
const toString3 = Object.prototype.toString; | |
let called = false; | |
let fns = []; | |
const complements = { | |
yellow: "blue", | |
cyan: "red", | |
green: "magenta", | |
black: "white", | |
blue: "yellow", | |
red: "cyan", | |
magenta: "green", | |
white: "black" | |
}; | |
exports.longest = (arr, prop) => { | |
return arr.reduce((a, v) => Math.max(a, prop ? v[prop].length : v.length), 0); | |
}; | |
exports.hasColor = (str) => !!str && colors.hasColor(str); | |
const isObject2 = exports.isObject = (val) => { | |
return val !== null && typeof val === "object" && !Array.isArray(val); | |
}; | |
exports.nativeType = (val) => { | |
return toString3.call(val).slice(8, -1).toLowerCase().replace(/\s/g, ""); | |
}; | |
exports.isAsyncFn = (val) => { | |
return exports.nativeType(val) === "asyncfunction"; | |
}; | |
exports.isPrimitive = (val) => { | |
return val != null && typeof val !== "object" && typeof val !== "function"; | |
}; | |
exports.resolve = (context, value, ...rest) => { | |
if (typeof value === "function") { | |
return value.call(context, ...rest); | |
} | |
return value; | |
}; | |
exports.scrollDown = (choices = []) => [...choices.slice(1), choices[0]]; | |
exports.scrollUp = (choices = []) => [choices.pop(), ...choices]; | |
exports.reorder = (arr = []) => { | |
let res = arr.slice(); | |
res.sort((a, b) => { | |
if (a.index > b.index) | |
return 1; | |
if (a.index < b.index) | |
return -1; | |
return 0; | |
}); | |
return res; | |
}; | |
exports.swap = (arr, index, pos) => { | |
let len = arr.length; | |
let idx = pos === len ? 0 : pos < 0 ? len - 1 : pos; | |
let choice = arr[index]; | |
arr[index] = arr[idx]; | |
arr[idx] = choice; | |
}; | |
exports.width = (stream, fallback = 80) => { | |
let columns = stream && stream.columns ? stream.columns : fallback; | |
if (stream && typeof stream.getWindowSize === "function") { | |
columns = stream.getWindowSize()[0]; | |
} | |
if (process.platform === "win32") { | |
return columns - 1; | |
} | |
return columns; | |
}; | |
exports.height = (stream, fallback = 20) => { | |
let rows = stream && stream.rows ? stream.rows : fallback; | |
if (stream && typeof stream.getWindowSize === "function") { | |
rows = stream.getWindowSize()[1]; | |
} | |
return rows; | |
}; | |
exports.wordWrap = (str, options = {}) => { | |
if (!str) | |
return str; | |
if (typeof options === "number") { | |
options = {width: options}; | |
} | |
let {indent = "", newline = "\n" + indent, width: width2 = 80} = options; | |
let spaces = (newline + indent).match(/[^\S\n]/g) || []; | |
width2 -= spaces.length; | |
let source = `.{1,${width2}}([\\s\\u200B]+|$)|[^\\s\\u200B]+?([\\s\\u200B]+|$)`; | |
let output = str.trim(); | |
let regex2 = new RegExp(source, "g"); | |
let lines = output.match(regex2) || []; | |
lines = lines.map((line) => line.replace(/\n$/, "")); | |
if (options.padEnd) | |
lines = lines.map((line) => line.padEnd(width2, " ")); | |
if (options.padStart) | |
lines = lines.map((line) => line.padStart(width2, " ")); | |
return indent + lines.join(newline); | |
}; | |
exports.unmute = (color) => { | |
let name = color.stack.find((n) => colors.keys.color.includes(n)); | |
if (name) { | |
return colors[name]; | |
} | |
let bg = color.stack.find((n) => n.slice(2) === "bg"); | |
if (bg) { | |
return colors[name.slice(2)]; | |
} | |
return (str) => str; | |
}; | |
exports.pascal = (str) => str ? str[0].toUpperCase() + str.slice(1) : ""; | |
exports.inverse = (color) => { | |
if (!color || !color.stack) | |
return color; | |
let name = color.stack.find((n) => colors.keys.color.includes(n)); | |
if (name) { | |
let col = colors["bg" + exports.pascal(name)]; | |
return col ? col.black : color; | |
} | |
let bg = color.stack.find((n) => n.slice(0, 2) === "bg"); | |
if (bg) { | |
return colors[bg.slice(2).toLowerCase()] || color; | |
} | |
return colors.none; | |
}; | |
exports.complement = (color) => { | |
if (!color || !color.stack) | |
return color; | |
let name = color.stack.find((n) => colors.keys.color.includes(n)); | |
let bg = color.stack.find((n) => n.slice(0, 2) === "bg"); | |
if (name && !bg) { | |
return colors[complements[name] || name]; | |
} | |
if (bg) { | |
let lower = bg.slice(2).toLowerCase(); | |
let comp = complements[lower]; | |
if (!comp) | |
return color; | |
return colors["bg" + exports.pascal(comp)] || color; | |
} | |
return colors.none; | |
}; | |
exports.meridiem = (date) => { | |
let hours = date.getHours(); | |
let minutes = date.getMinutes(); | |
let ampm = hours >= 12 ? "pm" : "am"; | |
hours = hours % 12; | |
let hrs = hours === 0 ? 12 : hours; | |
let min = minutes < 10 ? "0" + minutes : minutes; | |
return hrs + ":" + min + " " + ampm; | |
}; | |
exports.set = (obj = {}, prop = "", val) => { | |
return prop.split(".").reduce((acc, k, i, arr) => { | |
let value = arr.length - 1 > i ? acc[k] || {} : val; | |
if (!exports.isObject(value) && i < arr.length - 1) | |
value = {}; | |
return acc[k] = value; | |
}, obj); | |
}; | |
exports.get = (obj = {}, prop = "", fallback) => { | |
let value = obj[prop] == null ? prop.split(".").reduce((acc, k) => acc && acc[k], obj) : obj[prop]; | |
return value == null ? fallback : value; | |
}; | |
exports.mixin = (target, b) => { | |
if (!isObject2(target)) | |
return b; | |
if (!isObject2(b)) | |
return target; | |
for (let key of Object.keys(b)) { | |
let desc = Object.getOwnPropertyDescriptor(b, key); | |
if (desc.hasOwnProperty("value")) { | |
if (target.hasOwnProperty(key) && isObject2(desc.value)) { | |
let existing = Object.getOwnPropertyDescriptor(target, key); | |
if (isObject2(existing.value)) { | |
target[key] = exports.merge({}, target[key], b[key]); | |
} else { | |
Reflect.defineProperty(target, key, desc); | |
} | |
} else { | |
Reflect.defineProperty(target, key, desc); | |
} | |
} else { | |
Reflect.defineProperty(target, key, desc); | |
} | |
} | |
return target; | |
}; | |
exports.merge = (...args) => { | |
let target = {}; | |
for (let ele of args) | |
exports.mixin(target, ele); | |
return target; | |
}; | |
exports.mixinEmitter = (obj, emitter) => { | |
let proto = emitter.constructor.prototype; | |
for (let key of Object.keys(proto)) { | |
let val = proto[key]; | |
if (typeof val === "function") { | |
exports.define(obj, key, val.bind(emitter)); | |
} else { | |
exports.define(obj, key, val); | |
} | |
} | |
}; | |
exports.onExit = (callback) => { | |
const onExit = (quit, code) => { | |
if (called) | |
return; | |
called = true; | |
fns.forEach((fn2) => fn2()); | |
if (quit === true) { | |
process.exit(128 + code); | |
} | |
}; | |
if (fns.length === 0) { | |
process.once("SIGTERM", onExit.bind(null, true, 15)); | |
process.once("SIGINT", onExit.bind(null, true, 2)); | |
process.once("exit", onExit); | |
} | |
fns.push(callback); | |
}; | |
exports.define = (obj, key, value) => { | |
Reflect.defineProperty(obj, key, {value}); | |
}; | |
exports.defineExport = (obj, key, fn2) => { | |
let custom; | |
Reflect.defineProperty(obj, key, { | |
enumerable: true, | |
configurable: true, | |
set(val) { | |
custom = val; | |
}, | |
get() { | |
return custom ? custom() : fn2(); | |
} | |
}); | |
}; | |
}); | |
var ctrl = { | |
a: "first", | |
b: "backward", | |
c: "cancel", | |
d: "deleteForward", | |
e: "last", | |
f: "forward", | |
g: "reset", | |
i: "tab", | |
k: "cutForward", | |
l: "reset", | |
n: "newItem", | |
m: "cancel", | |
j: "submit", | |
p: "search", | |
r: "remove", | |
s: "save", | |
u: "undo", | |
w: "cutLeft", | |
x: "toggleCursor", | |
v: "paste" | |
}; | |
var shift = { | |
up: "shiftUp", | |
down: "shiftDown", | |
left: "shiftLeft", | |
right: "shiftRight", | |
tab: "prev" | |
}; | |
var fn = { | |
up: "pageUp", | |
down: "pageDown", | |
left: "pageLeft", | |
right: "pageRight", | |
delete: "deleteForward" | |
}; | |
var option = { | |
b: "backward", | |
f: "forward", | |
d: "cutRight", | |
left: "cutLeft", | |
up: "altUp", | |
down: "altDown" | |
}; | |
var keys = { | |
pageup: "pageUp", | |
pagedown: "pageDown", | |
home: "home", | |
end: "end", | |
cancel: "cancel", | |
delete: "deleteForward", | |
backspace: "delete", | |
down: "down", | |
enter: "submit", | |
escape: "cancel", | |
left: "left", | |
space: "space", | |
number: "number", | |
return: "submit", | |
right: "right", | |
tab: "next", | |
up: "up" | |
}; | |
var combos = { | |
ctrl, | |
shift, | |
fn, | |
option, | |
keys | |
}; | |
const metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/; | |
const fnKeyRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/; | |
const keyName = { | |
OP: "f1", | |
OQ: "f2", | |
OR: "f3", | |
OS: "f4", | |
"[11~": "f1", | |
"[12~": "f2", | |
"[13~": "f3", | |
"[14~": "f4", | |
"[[A": "f1", | |
"[[B": "f2", | |
"[[C": "f3", | |
"[[D": "f4", | |
"[[E": "f5", | |
"[15~": "f5", | |
"[17~": "f6", | |
"[18~": "f7", | |
"[19~": "f8", | |
"[20~": "f9", | |
"[21~": "f10", | |
"[23~": "f11", | |
"[24~": "f12", | |
"[A": "up", | |
"[B": "down", | |
"[C": "right", | |
"[D": "left", | |
"[E": "clear", | |
"[F": "end", | |
"[H": "home", | |
OA: "up", | |
OB: "down", | |
OC: "right", | |
OD: "left", | |
OE: "clear", | |
OF: "end", | |
OH: "home", | |
"[1~": "home", | |
"[2~": "insert", | |
"[3~": "delete", | |
"[4~": "end", | |
"[5~": "pageup", | |
"[6~": "pagedown", | |
"[[5~": "pageup", | |
"[[6~": "pagedown", | |
"[7~": "home", | |
"[8~": "end", | |
"[a": "up", | |
"[b": "down", | |
"[c": "right", | |
"[d": "left", | |
"[e": "clear", | |
"[2$": "insert", | |
"[3$": "delete", | |
"[5$": "pageup", | |
"[6$": "pagedown", | |
"[7$": "home", | |
"[8$": "end", | |
Oa: "up", | |
Ob: "down", | |
Oc: "right", | |
Od: "left", | |
Oe: "clear", | |
"[2^": "insert", | |
"[3^": "delete", | |
"[5^": "pageup", | |
"[6^": "pagedown", | |
"[7^": "home", | |
"[8^": "end", | |
"[Z": "tab" | |
}; | |
function isShiftKey(code) { | |
return ["[a", "[b", "[c", "[d", "[e", "[2$", "[3$", "[5$", "[6$", "[7$", "[8$", "[Z"].includes(code); | |
} | |
function isCtrlKey(code) { | |
return ["Oa", "Ob", "Oc", "Od", "Oe", "[2^", "[3^", "[5^", "[6^", "[7^", "[8^"].includes(code); | |
} | |
const keypress = (s = "", event = {}) => { | |
let parts; | |
let key = { | |
name: event.name, | |
ctrl: false, | |
meta: false, | |
shift: false, | |
option: false, | |
sequence: s, | |
raw: s, | |
...event | |
}; | |
if (Buffer.isBuffer(s)) { | |
if (s[0] > 127 && s[1] === void 0) { | |
s[0] -= 128; | |
s = "" + String(s); | |
} else { | |
s = String(s); | |
} | |
} else if (s !== void 0 && typeof s !== "string") { | |
s = String(s); | |
} else if (!s) { | |
s = key.sequence || ""; | |
} | |
key.sequence = key.sequence || s || key.name; | |
if (s === "\r") { | |
key.raw = void 0; | |
key.name = "return"; | |
} else if (s === "\n") { | |
key.name = "enter"; | |
} else if (s === " ") { | |
key.name = "tab"; | |
} else if (s === "\b" || s === "\x7F" || s === "\x7F" || s === "\b") { | |
key.name = "backspace"; | |
key.meta = s.charAt(0) === ""; | |
} else if (s === "" || s === "") { | |
key.name = "escape"; | |
key.meta = s.length === 2; | |
} else if (s === " " || s === " ") { | |
key.name = "space"; | |
key.meta = s.length === 2; | |
} else if (s <= "") { | |
key.name = String.fromCharCode(s.charCodeAt(0) + "a".charCodeAt(0) - 1); | |
key.ctrl = true; | |
} else if (s.length === 1 && s >= "0" && s <= "9") { | |
key.name = "number"; | |
} else if (s.length === 1 && s >= "a" && s <= "z") { | |
key.name = s; | |
} else if (s.length === 1 && s >= "A" && s <= "Z") { | |
key.name = s.toLowerCase(); | |
key.shift = true; | |
} else if (parts = metaKeyCodeRe.exec(s)) { | |
key.meta = true; | |
key.shift = /^[A-Z]$/.test(parts[1]); | |
} else if (parts = fnKeyRe.exec(s)) { | |
let segs = [...s]; | |
if (segs[0] === "" && segs[1] === "") { | |
key.option = true; | |
} | |
let code = [parts[1], parts[2], parts[4], parts[6]].filter(Boolean).join(""); | |
let modifier = (parts[3] || parts[5] || 1) - 1; | |
key.ctrl = !!(modifier & 4); | |
key.meta = !!(modifier & 10); | |
key.shift = !!(modifier & 1); | |
key.code = code; | |
key.name = keyName[code]; | |
key.shift = isShiftKey(code) || key.shift; | |
key.ctrl = isCtrlKey(code) || key.ctrl; | |
} | |
return key; | |
}; | |
keypress.listen = (options = {}, onKeypress) => { | |
let {stdin} = options; | |
if (!stdin || stdin !== process.stdin && !stdin.isTTY) { | |
throw new Error("Invalid stream passed"); | |
} | |
let rl = readline.createInterface({terminal: true, input: stdin}); | |
readline.emitKeypressEvents(stdin, rl); | |
let on2 = (buf, key) => onKeypress(buf, keypress(buf, key), rl); | |
let isRaw = stdin.isRaw; | |
if (stdin.isTTY) | |
stdin.setRawMode(true); | |
stdin.on("keypress", on2); | |
rl.resume(); | |
let off2 = () => { | |
if (stdin.isTTY) | |
stdin.setRawMode(isRaw); | |
stdin.removeListener("keypress", on2); | |
rl.pause(); | |
rl.close(); | |
}; | |
return off2; | |
}; | |
keypress.action = (buf, key, customActions) => { | |
let obj = {...combos, ...customActions}; | |
if (key.ctrl) { | |
key.action = obj.ctrl[key.name]; | |
return key; | |
} | |
if (key.option && obj.option) { | |
key.action = obj.option[key.name]; | |
return key; | |
} | |
if (key.shift) { | |
key.action = obj.shift[key.name]; | |
return key; | |
} | |
key.action = obj.keys[key.name]; | |
return key; | |
}; | |
var keypress_1 = keypress; | |
var timer = (prompt2) => { | |
prompt2.timers = prompt2.timers || {}; | |
let timers = prompt2.options.timers; | |
if (!timers) | |
return; | |
for (let key of Object.keys(timers)) { | |
let opts = timers[key]; | |
if (typeof opts === "number") { | |
opts = {interval: opts}; | |
} | |
create(prompt2, key, opts); | |
} | |
}; | |
function create(prompt2, name, options = {}) { | |
let timer2 = prompt2.timers[name] = {name, start: Date.now(), ms: 0, tick: 0}; | |
let ms = options.interval || 120; | |
timer2.frames = options.frames || []; | |
timer2.loading = true; | |
let interval = setInterval(() => { | |
timer2.ms = Date.now() - timer2.start; | |
timer2.tick++; | |
prompt2.render(); | |
}, ms); | |
timer2.stop = () => { | |
timer2.loading = false; | |
clearInterval(interval); | |
}; | |
Reflect.defineProperty(timer2, "interval", {value: interval}); | |
prompt2.once("close", () => timer2.stop()); | |
return timer2.stop; | |
} | |
const {define, width} = utils; | |
class State { | |
constructor(prompt2) { | |
let options = prompt2.options; | |
define(this, "_prompt", prompt2); | |
this.type = prompt2.type; | |
this.name = prompt2.name; | |
this.message = ""; | |
this.header = ""; | |
this.footer = ""; | |
this.error = ""; | |
this.hint = ""; | |
this.input = ""; | |
this.cursor = 0; | |
this.index = 0; | |
this.lines = 0; | |
this.tick = 0; | |
this.prompt = ""; | |
this.buffer = ""; | |
this.width = width(options.stdout || process.stdout); | |
Object.assign(this, options); | |
this.name = this.name || this.message; | |
this.message = this.message || this.name; | |
this.symbols = prompt2.symbols; | |
this.styles = prompt2.styles; | |
this.required = new Set(); | |
this.cancelled = false; | |
this.submitted = false; | |
} | |
clone() { | |
let state2 = {...this}; | |
state2.status = this.status; | |
state2.buffer = Buffer.from(state2.buffer); | |
delete state2.clone; | |
return state2; | |
} | |
set color(val) { | |
this._color = val; | |
} | |
get color() { | |
let styles2 = this.prompt.styles; | |
if (this.cancelled) | |
return styles2.cancelled; | |
if (this.submitted) | |
return styles2.submitted; | |
let color = this._color || styles2[this.status]; | |
return typeof color === "function" ? color : styles2.pending; | |
} | |
set loading(value) { | |
this._loading = value; | |
} | |
get loading() { | |
if (typeof this._loading === "boolean") | |
return this._loading; | |
if (this.loadingChoices) | |
return "choices"; | |
return false; | |
} | |
get status() { | |
if (this.cancelled) | |
return "cancelled"; | |
if (this.submitted) | |
return "submitted"; | |
return "pending"; | |
} | |
} | |
var state = State; | |
const styles = { | |
default: colors.noop, | |
noop: colors.noop, | |
set inverse(custom) { | |
this._inverse = custom; | |
}, | |
get inverse() { | |
return this._inverse || utils.inverse(this.primary); | |
}, | |
set complement(custom) { | |
this._complement = custom; | |
}, | |
get complement() { | |
return this._complement || utils.complement(this.primary); | |
}, | |
primary: colors.cyan, | |
success: colors.green, | |
danger: colors.magenta, | |
strong: colors.bold, | |
warning: colors.yellow, | |
muted: colors.dim, | |
disabled: colors.gray, | |
dark: colors.dim.gray, | |
underline: colors.underline, | |
set info(custom) { | |
this._info = custom; | |
}, | |
get info() { | |
return this._info || this.primary; | |
}, | |
set em(custom) { | |
this._em = custom; | |
}, | |
get em() { | |
return this._em || this.primary.underline; | |
}, | |
set heading(custom) { | |
this._heading = custom; | |
}, | |
get heading() { | |
return this._heading || this.muted.underline; | |
}, | |
set pending(custom) { | |
this._pending = custom; | |
}, | |
get pending() { | |
return this._pending || this.primary; | |
}, | |
set submitted(custom) { | |
this._submitted = custom; | |
}, | |
get submitted() { | |
return this._submitted || this.success; | |
}, | |
set cancelled(custom) { | |
this._cancelled = custom; | |
}, | |
get cancelled() { | |
return this._cancelled || this.danger; | |
}, | |
set typing(custom) { | |
this._typing = custom; | |
}, | |
get typing() { | |
return this._typing || this.dim; | |
}, | |
set placeholder(custom) { | |
this._placeholder = custom; | |
}, | |
get placeholder() { | |
return this._placeholder || this.primary.dim; | |
}, | |
set highlight(custom) { | |
this._highlight = custom; | |
}, | |
get highlight() { | |
return this._highlight || this.inverse; | |
} | |
}; | |
styles.merge = (options = {}) => { | |
if (options.styles && typeof options.styles.enabled === "boolean") { | |
colors.enabled = options.styles.enabled; | |
} | |
if (options.styles && typeof options.styles.visible === "boolean") { | |
colors.visible = options.styles.visible; | |
} | |
let result = utils.merge({}, styles, options.styles); | |
delete result.merge; | |
for (let key of Object.keys(colors)) { | |
if (!result.hasOwnProperty(key)) { | |
Reflect.defineProperty(result, key, {get: () => colors[key]}); | |
} | |
} | |
for (let key of Object.keys(colors.styles)) { | |
if (!result.hasOwnProperty(key)) { | |
Reflect.defineProperty(result, key, {get: () => colors[key]}); | |
} | |
} | |
return result; | |
}; | |
var styles_1 = styles; | |
const isWindows = process.platform === "win32"; | |
const symbols = { | |
...colors.symbols, | |
upDownDoubleArrow: "\u21D5", | |
upDownDoubleArrow2: "\u2B0D", | |
upDownArrow: "\u2195", | |
asterisk: "*", | |
asterism: "\u2042", | |
bulletWhite: "\u25E6", | |
electricArrow: "\u2301", | |
ellipsisLarge: "\u22EF", | |
ellipsisSmall: "\u2026", | |
fullBlock: "\u2588", | |
identicalTo: "\u2261", | |
indicator: colors.symbols.check, | |
leftAngle: "\u2039", | |
mark: "\u203B", | |
minus: "\u2212", | |
multiplication: "\xD7", | |
obelus: "\xF7", | |
percent: "%", | |
pilcrow: "\xB6", | |
pilcrow2: "\u2761", | |
pencilUpRight: "\u2710", | |
pencilDownRight: "\u270E", | |
pencilRight: "\u270F", | |
plus: "+", | |
plusMinus: "\xB1", | |
pointRight: "\u261E", | |
rightAngle: "\u203A", | |
section: "\xA7", | |
hexagon: {off: "\u2B21", on: "\u2B22", disabled: "\u2B22"}, | |
ballot: {on: "\u2611", off: "\u2610", disabled: "\u2612"}, | |
stars: {on: "\u2605", off: "\u2606", disabled: "\u2606"}, | |
folder: {on: "\u25BC", off: "\u25B6", disabled: "\u25B6"}, | |
prefix: { | |
pending: colors.symbols.question, | |
submitted: colors.symbols.check, | |
cancelled: colors.symbols.cross | |
}, | |
separator: { | |
pending: colors.symbols.pointerSmall, | |
submitted: colors.symbols.middot, | |
cancelled: colors.symbols.middot | |
}, | |
radio: { | |
off: isWindows ? "( )" : "\u25EF", | |
on: isWindows ? "(*)" : "\u25C9", | |
disabled: isWindows ? "(|)" : "\u24BE" | |
}, | |
numbers: ["\u24EA", "\u2460", "\u2461", "\u2462", "\u2463", "\u2464", "\u2465", "\u2466", "\u2467", "\u2468", "\u2469", "\u246A", "\u246B", "\u246C", "\u246D", "\u246E", "\u246F", "\u2470", "\u2471", "\u2472", "\u2473", "\u3251", "\u3252", "\u3253", "\u3254", "\u3255", "\u3256", "\u3257", "\u3258", "\u3259", "\u325A", "\u325B", "\u325C", "\u325D", "\u325E", "\u325F", "\u32B1", "\u32B2", "\u32B3", "\u32B4", "\u32B5", "\u32B6", "\u32B7", "\u32B8", "\u32B9", "\u32BA", "\u32BB", "\u32BC", "\u32BD", "\u32BE", "\u32BF"] | |
}; | |
symbols.merge = (options) => { | |
let result = utils.merge({}, colors.symbols, symbols, options.symbols); | |
delete result.merge; | |
return result; | |
}; | |
var symbols_1 = symbols; | |
var theme = (prompt2) => { | |
prompt2.options = utils.merge({}, prompt2.options.theme, prompt2.options); | |
prompt2.symbols = symbols_1.merge(prompt2.options); | |
prompt2.styles = styles_1.merge(prompt2.options); | |
}; | |
var ansi_1 = createCommonjsModule(function(module, exports) { | |
const isTerm = process.env.TERM_PROGRAM === "Apple_Terminal"; | |
const ansi = module.exports = exports; | |
const ESC = "["; | |
const BEL = "\x07"; | |
let hidden = false; | |
const code = ansi.code = { | |
bell: BEL, | |
beep: BEL, | |
beginning: `${ESC}G`, | |
down: `${ESC}J`, | |
esc: ESC, | |
getPosition: `${ESC}6n`, | |
hide: `${ESC}?25l`, | |
line: `${ESC}2K`, | |
lineEnd: `${ESC}K`, | |
lineStart: `${ESC}1K`, | |
restorePosition: ESC + (isTerm ? "8" : "u"), | |
savePosition: ESC + (isTerm ? "7" : "s"), | |
screen: `${ESC}2J`, | |
show: `${ESC}?25h`, | |
up: `${ESC}1J` | |
}; | |
const cursor = ansi.cursor = { | |
get hidden() { | |
return hidden; | |
}, | |
hide() { | |
hidden = true; | |
return code.hide; | |
}, | |
show() { | |
hidden = false; | |
return code.show; | |
}, | |
forward: (count = 1) => `${ESC}${count}C`, | |
backward: (count = 1) => `${ESC}${count}D`, | |
nextLine: (count = 1) => `${ESC}E`.repeat(count), | |
prevLine: (count = 1) => `${ESC}F`.repeat(count), | |
up: (count = 1) => count ? `${ESC}${count}A` : "", | |
down: (count = 1) => count ? `${ESC}${count}B` : "", | |
right: (count = 1) => count ? `${ESC}${count}C` : "", | |
left: (count = 1) => count ? `${ESC}${count}D` : "", | |
to(x, y) { | |
return y ? `${ESC}${y + 1};${x + 1}H` : `${ESC}${x + 1}G`; | |
}, | |
move(x = 0, y = 0) { | |
let res = ""; | |
res += x < 0 ? cursor.left(-x) : x > 0 ? cursor.right(x) : ""; | |
res += y < 0 ? cursor.up(-y) : y > 0 ? cursor.down(y) : ""; | |
return res; | |
}, | |
restore(state2 = {}) { | |
let {after, cursor: cursor2, initial, input: input2, prompt: prompt2, size, value} = state2; | |
initial = utils.isPrimitive(initial) ? String(initial) : ""; | |
input2 = utils.isPrimitive(input2) ? String(input2) : ""; | |
value = utils.isPrimitive(value) ? String(value) : ""; | |
if (size) { | |
let codes = ansi.cursor.up(size) + ansi.cursor.to(prompt2.length); | |
let diff = input2.length - cursor2; | |
if (diff > 0) { | |
codes += ansi.cursor.left(diff); | |
} | |
return codes; | |
} | |
if (value || after) { | |
let pos = !input2 && !!initial ? -initial.length : -input2.length + cursor2; | |
if (after) | |
pos -= after.length; | |
if (input2 === "" && initial && !prompt2.includes(initial)) { | |
pos += initial.length; | |
} | |
return ansi.cursor.move(pos); | |
} | |
} | |
}; | |
const erase = ansi.erase = { | |
screen: code.screen, | |
up: code.up, | |
down: code.down, | |
line: code.line, | |
lineEnd: code.lineEnd, | |
lineStart: code.lineStart, | |
lines(n) { | |
let str = ""; | |
for (let i = 0; i < n; i++) { | |
str += ansi.erase.line + (i < n - 1 ? ansi.cursor.up(1) : ""); | |
} | |
if (n) | |
str += ansi.code.beginning; | |
return str; | |
} | |
}; | |
ansi.clear = (input2 = "", columns = process.stdout.columns) => { | |
if (!columns) | |
return erase.line + cursor.to(0); | |
let width2 = (str) => [...colors.unstyle(str)].length; | |
let lines = input2.split(/\r?\n/); | |
let rows = 0; | |
for (let line of lines) { | |
rows += 1 + Math.floor(Math.max(width2(line) - 1, 0) / columns); | |
} | |
return (erase.line + cursor.prevLine()).repeat(rows - 1) + erase.line + cursor.to(0); | |
}; | |
}); | |
class Prompt extends events { | |
constructor(options = {}) { | |
super(); | |
this.name = options.name; | |
this.type = options.type; | |
this.options = options; | |
theme(this); | |
timer(this); | |
this.state = new state(this); | |
this.initial = [options.initial, options.default].find((v) => v != null); | |
this.stdout = options.stdout || process.stdout; | |
this.stdin = options.stdin || process.stdin; | |
this.scale = options.scale || 1; | |
this.term = this.options.term || process.env.TERM_PROGRAM; | |
this.margin = margin(this.options.margin); | |
this.setMaxListeners(0); | |
setOptions(this); | |
} | |
async keypress(input2, event = {}) { | |
this.keypressed = true; | |
let key = keypress_1.action(input2, keypress_1(input2, event), this.options.actions); | |
this.state.keypress = key; | |
this.emit("keypress", input2, key); | |
this.emit("state", this.state.clone()); | |
let fn2 = this.options[key.action] || this[key.action] || this.dispatch; | |
if (typeof fn2 === "function") { | |
return await fn2.call(this, input2, key); | |
} | |
this.alert(); | |
} | |
alert() { | |
delete this.state.alert; | |
if (this.options.show === false) { | |
this.emit("alert"); | |
} else { | |
this.stdout.write(ansi_1.code.beep); | |
} | |
} | |
cursorHide() { | |
this.stdout.write(ansi_1.cursor.hide()); | |
utils.onExit(() => this.cursorShow()); | |
} | |
cursorShow() { | |
this.stdout.write(ansi_1.cursor.show()); | |
} | |
write(str) { | |
if (!str) | |
return; | |
if (this.stdout && this.state.show !== false) { | |
this.stdout.write(str); | |
} | |
this.state.buffer += str; | |
} | |
clear(lines = 0) { | |
let buffer = this.state.buffer; | |
this.state.buffer = ""; | |
if (!buffer && !lines || this.options.show === false) | |
return; | |
this.stdout.write(ansi_1.cursor.down(lines) + ansi_1.clear(buffer, this.width)); | |
} | |
restore() { | |
if (this.state.closed || this.options.show === false) | |
return; | |
let {prompt: prompt2, after, rest} = this.sections(); | |
let {cursor, initial = "", input: input2 = "", value = ""} = this; | |
let size = this.state.size = rest.length; | |
let state2 = {after, cursor, initial, input: input2, prompt: prompt2, size, value}; | |
let codes = ansi_1.cursor.restore(state2); | |
if (codes) { | |
this.stdout.write(codes); | |
} | |
} | |
sections() { | |
let {buffer, input: input2, prompt: prompt2} = this.state; | |
prompt2 = colors.unstyle(prompt2); | |
let buf = colors.unstyle(buffer); | |
let idx = buf.indexOf(prompt2); | |
let header = buf.slice(0, idx); | |
let rest = buf.slice(idx); | |
let lines = rest.split("\n"); | |
let first = lines[0]; | |
let last = lines[lines.length - 1]; | |
let promptLine = prompt2 + (input2 ? " " + input2 : ""); | |
let len = promptLine.length; | |
let after = len < first.length ? first.slice(len + 1) : ""; | |
return {header, prompt: first, after, rest: lines.slice(1), last}; | |
} | |
async submit() { | |
this.state.submitted = true; | |
this.state.validating = true; | |
if (this.options.onSubmit) { | |
await this.options.onSubmit.call(this, this.name, this.value, this); | |
} | |
let result = this.state.error || await this.validate(this.value, this.state); | |
if (result !== true) { | |
let error = "\n" + this.symbols.pointer + " "; | |
if (typeof result === "string") { | |
error += result.trim(); | |
} else { | |
error += "Invalid input"; | |
} | |
this.state.error = "\n" + this.styles.danger(error); | |
this.state.submitted = false; | |
await this.render(); | |
await this.alert(); | |
this.state.validating = false; | |
this.state.error = void 0; | |
return; | |
} | |
this.state.validating = false; | |
await this.render(); | |
await this.close(); | |
this.value = await this.result(this.value); | |
this.emit("submit", this.value); | |
} | |
async cancel(err) { | |
this.state.cancelled = this.state.submitted = true; | |
await this.render(); | |
await this.close(); | |
if (typeof this.options.onCancel === "function") { | |
await this.options.onCancel.call(this, this.name, this.value, this); | |
} | |
this.emit("cancel", await this.error(err)); | |
} | |
async close() { | |
this.state.closed = true; | |
try { | |
let sections = this.sections(); | |
let lines = Math.ceil(sections.prompt.length / this.width); | |
if (sections.rest) { | |
this.write(ansi_1.cursor.down(sections.rest.length)); | |
} | |
this.write("\n".repeat(lines)); | |
} catch (err) { | |
} | |
this.emit("close"); | |
} | |
start() { | |
if (!this.stop && this.options.show !== false) { | |
this.stop = keypress_1.listen(this, this.keypress.bind(this)); | |
this.once("close", this.stop); | |
} | |
} | |
async skip() { | |
this.skipped = this.options.skip === true; | |
if (typeof this.options.skip === "function") { | |
this.skipped = await this.options.skip.call(this, this.name, this.value); | |
} | |
return this.skipped; | |
} | |
async initialize() { | |
let {format, options, result} = this; | |
this.format = () => format.call(this, this.value); | |
this.result = () => result.call(this, this.value); | |
if (typeof options.initial === "function") { | |
this.initial = await options.initial.call(this, this); | |
} | |
if (typeof options.onRun === "function") { | |
await options.onRun.call(this, this); | |
} | |
if (typeof options.onSubmit === "function") { | |
let onSubmit = options.onSubmit.bind(this); | |
let submit = this.submit.bind(this); | |
delete this.options.onSubmit; | |
this.submit = async () => { | |
await onSubmit(this.name, this.value, this); | |
return submit(); | |
}; | |
} | |
await this.start(); | |
await this.render(); | |
} | |
render() { | |
throw new Error("expected prompt to have a custom render method"); | |
} | |
run() { | |
return new Promise(async (resolve, reject) => { | |
this.once("submit", resolve); | |
this.once("cancel", reject); | |
if (await this.skip()) { | |
this.render = () => { | |
}; | |
return this.submit(); | |
} | |
await this.initialize(); | |
this.emit("run"); | |
}); | |
} | |
async element(name, choice, i) { | |
let {options, state: state2, symbols: symbols2, timers} = this; | |
let timer2 = timers && timers[name]; | |
state2.timer = timer2; | |
let value = options[name] || state2[name] || symbols2[name]; | |
let val = choice && choice[name] != null ? choice[name] : await value; | |
if (val === "") | |
return val; | |
let res = await this.resolve(val, state2, choice, i); | |
if (!res && choice && choice[name]) { | |
return this.resolve(value, state2, choice, i); | |
} | |
return res; | |
} | |
async prefix() { | |
let element = await this.element("prefix") || this.symbols; | |
let timer2 = this.timers && this.timers.prefix; | |
let state2 = this.state; | |
state2.timer = timer2; | |
if (utils.isObject(element)) | |
element = element[state2.status] || element.pending; | |
if (!utils.hasColor(element)) { | |
let style = this.styles[state2.status] || this.styles.pending; | |
return style(element); | |
} | |
return element; | |
} | |
async message() { | |
let message = await this.element("message"); | |
if (!utils.hasColor(message)) { | |
return this.styles.strong(message); | |
} | |
return message; | |
} | |
async separator() { | |
let element = await this.element("separator") || this.symbols; | |
let timer2 = this.timers && this.timers.separator; | |
let state2 = this.state; | |
state2.timer = timer2; | |
let value = element[state2.status] || element.pending || state2.separator; | |
let ele = await this.resolve(value, state2); | |
if (utils.isObject(ele)) | |
ele = ele[state2.status] || ele.pending; | |
if (!utils.hasColor(ele)) { | |
return this.styles.muted(ele); | |
} | |
return ele; | |
} | |
async pointer(choice, i) { | |
let val = await this.element("pointer", choice, i); | |
if (typeof val === "string" && utils.hasColor(val)) { | |
return val; | |
} | |
if (val) { | |
let styles2 = this.styles; | |
let focused = this.index === i; | |
let style = focused ? styles2.primary : (val2) => val2; | |
let ele = await this.resolve(val[focused ? "on" : "off"] || val, this.state); | |
let styled = !utils.hasColor(ele) ? style(ele) : ele; | |
return focused ? styled : " ".repeat(ele.length); | |
} | |
} | |
async indicator(choice, i) { | |
let val = await this.element("indicator", choice, i); | |
if (typeof val === "string" && utils.hasColor(val)) { | |
return val; | |
} | |
if (val) { | |
let styles2 = this.styles; | |
let enabled = choice.enabled === true; | |
let style = enabled ? styles2.success : styles2.dark; | |
let ele = val[enabled ? "on" : "off"] || val; | |
return !utils.hasColor(ele) ? style(ele) : ele; | |
} | |
return ""; | |
} | |
body() { | |
return null; | |
} | |
footer() { | |
if (this.state.status === "pending") { | |
return this.element("footer"); | |
} | |
} | |
header() { | |
if (this.state.status === "pending") { | |
return this.element("header"); | |
} | |
} | |
async hint() { | |
if (this.state.status === "pending" && !this.isValue(this.state.input)) { | |
let hint2 = await this.element("hint"); | |
if (!utils.hasColor(hint2)) { | |
return this.styles.muted(hint2); | |
} | |
return hint2; | |
} | |
} | |
error(err) { | |
return !this.state.submitted ? err || this.state.error : ""; | |
} | |
format(value) { | |
return value; | |
} | |
result(value) { | |
return value; | |
} | |
validate(value) { | |
if (this.options.required === true) { | |
return this.isValue(value); | |
} | |
return true; | |
} | |
isValue(value) { | |
return value != null && value !== ""; | |
} | |
resolve(value, ...args) { | |
return utils.resolve(this, value, ...args); | |
} | |
get base() { | |
return Prompt.prototype; | |
} | |
get style() { | |
return this.styles[this.state.status]; | |
} | |
get height() { | |
return this.options.rows || utils.height(this.stdout, 25); | |
} | |
get width() { | |
return this.options.columns || utils.width(this.stdout, 80); | |
} | |
get size() { | |
return {width: this.width, height: this.height}; | |
} | |
set cursor(value) { | |
this.state.cursor = value; | |
} | |
get cursor() { | |
return this.state.cursor; | |
} | |
set input(value) { | |
this.state.input = value; | |
} | |
get input() { | |
return this.state.input; | |
} | |
set value(value) { | |
this.state.value = value; | |
} | |
get value() { | |
let {input: input2, value} = this.state; | |
let result = [value, input2].find(this.isValue.bind(this)); | |
return this.isValue(result) ? result : this.initial; | |
} | |
static get prompt() { | |
return (options) => new this(options).run(); | |
} | |
} | |
function setOptions(prompt2) { | |
let isValidKey = (key) => { | |
return prompt2[key] === void 0 || typeof prompt2[key] === "function"; | |
}; | |
let ignore = [ | |
"actions", | |
"choices", | |
"initial", | |
"margin", | |
"roles", | |
"styles", | |
"symbols", | |
"theme", | |
"timers", | |
"value" | |
]; | |
let ignoreFn = [ | |
"body", | |
"footer", | |
"error", | |
"header", | |
"hint", | |
"indicator", | |
"message", | |
"prefix", | |
"separator", | |
"skip" | |
]; | |
for (let key of Object.keys(prompt2.options)) { | |
if (ignore.includes(key)) | |
continue; | |
if (/^on[A-Z]/.test(key)) | |
continue; | |
let option2 = prompt2.options[key]; | |
if (typeof option2 === "function" && isValidKey(key)) { | |
if (!ignoreFn.includes(key)) { | |
prompt2[key] = option2.bind(prompt2); | |
} | |
} else if (typeof prompt2[key] !== "function") { | |
prompt2[key] = option2; | |
} | |
} | |
} | |
function margin(value) { | |
if (typeof value === "number") { | |
value = [value, value, value, value]; | |
} | |
let arr = [].concat(value || []); | |
let pad = (i) => i % 2 === 0 ? "\n" : " "; | |
let res = []; | |
for (let i = 0; i < 4; i++) { | |
let char = pad(i); | |
if (arr[i]) { | |
res.push(char.repeat(arr[i])); | |
} else { | |
res.push(""); | |
} | |
} | |
return res; | |
} | |
var prompt = Prompt; | |
const roles = { | |
default(prompt2, choice) { | |
return choice; | |
}, | |
checkbox(prompt2, choice) { | |
throw new Error("checkbox role is not implemented yet"); | |
}, | |
editable(prompt2, choice) { | |
throw new Error("editable role is not implemented yet"); | |
}, | |
expandable(prompt2, choice) { | |
throw new Error("expandable role is not implemented yet"); | |
}, | |
heading(prompt2, choice) { | |
choice.disabled = ""; | |
choice.indicator = [choice.indicator, " "].find((v) => v != null); | |
choice.message = choice.message || ""; | |
return choice; | |
}, | |
input(prompt2, choice) { | |
throw new Error("input role is not implemented yet"); | |
}, | |
option(prompt2, choice) { | |
return roles.default(prompt2, choice); | |
}, | |
radio(prompt2, choice) { | |
throw new Error("radio role is not implemented yet"); | |
}, | |
separator(prompt2, choice) { | |
choice.disabled = ""; | |
choice.indicator = [choice.indicator, " "].find((v) => v != null); | |
choice.message = choice.message || prompt2.symbols.line.repeat(5); | |
return choice; | |
}, | |
spacer(prompt2, choice) { | |
return choice; | |
} | |
}; | |
var roles_1 = (name, options = {}) => { | |
let role = utils.merge({}, roles, options.roles); | |
return role[name] || role.default; | |
}; | |
const {reorder, scrollUp, scrollDown, isObject: isObject$1, swap: swap$1} = utils; | |
class ArrayPrompt extends prompt { | |
constructor(options) { | |
super(options); | |
this.cursorHide(); | |
this.maxSelected = options.maxSelected || Infinity; | |
this.multiple = options.multiple || false; | |
this.initial = options.initial || 0; | |
this.delay = options.delay || 0; | |
this.longest = 0; | |
this.num = ""; | |
} | |
async initialize() { | |
if (typeof this.options.initial === "function") { | |
this.initial = await this.options.initial.call(this); | |
} | |
await this.reset(true); | |
await super.initialize(); | |
} | |
async reset() { | |
let {choices, initial, autofocus, suggest} = this.options; | |
this.state._choices = []; | |
this.state.choices = []; | |
this.choices = await Promise.all(await this.toChoices(choices)); | |
this.choices.forEach((ch) => ch.enabled = false); | |
if (typeof suggest !== "function" && this.selectable.length === 0) { | |
throw new Error("At least one choice must be selectable"); | |
} | |
if (isObject$1(initial)) | |
initial = Object.keys(initial); | |
if (Array.isArray(initial)) { | |
if (autofocus != null) | |
this.index = this.findIndex(autofocus); | |
initial.forEach((v) => this.enable(this.find(v))); | |
await this.render(); | |
} else { | |
if (autofocus != null) | |
initial = autofocus; | |
if (typeof initial === "string") | |
initial = this.findIndex(initial); | |
if (typeof initial === "number" && initial > -1) { | |
this.index = Math.max(0, Math.min(initial, this.choices.length)); | |
this.enable(this.find(this.index)); | |
} | |
} | |
if (this.isDisabled(this.focused)) { | |
await this.down(); | |
} | |
} | |
async toChoices(value, parent) { | |
this.state.loadingChoices = true; | |
let choices = []; | |
let index = 0; | |
let toChoices = async (items, parent2) => { | |
if (typeof items === "function") | |
items = await items.call(this); | |
if (items instanceof Promise) | |
items = await items; | |
for (let i = 0; i < items.length; i++) { | |
let choice = items[i] = await this.toChoice(items[i], index++, parent2); | |
choices.push(choice); | |
if (choice.choices) { | |
await toChoices(choice.choices, choice); | |
} | |
} | |
return choices; | |
}; | |
return toChoices(value, parent).then((choices2) => { | |
this.state.loadingChoices = false; | |
return choices2; | |
}); | |
} | |
async toChoice(ele, i, parent) { | |
if (typeof ele === "function") | |
ele = await ele.call(this, this); | |
if (ele instanceof Promise) | |
ele = await ele; | |
if (typeof ele === "string") | |
ele = {name: ele}; | |
if (ele.normalized) | |
return ele; | |
ele.normalized = true; | |
let origVal = ele.value; | |
let role = roles_1(ele.role, this.options); | |
ele = role(this, ele); | |
if (typeof ele.disabled === "string" && !ele.hint) { | |
ele.hint = ele.disabled; | |
ele.disabled = true; | |
} | |
if (ele.disabled === true && ele.hint == null) { | |
ele.hint = "(disabled)"; | |
} | |
if (ele.index != null) | |
return ele; | |
ele.name = ele.name || ele.key || ele.title || ele.value || ele.message; | |
ele.message = ele.message || ele.name || ""; | |
ele.value = [ele.value, ele.name].find(this.isValue.bind(this)); | |
ele.input = ""; | |
ele.index = i; | |
ele.cursor = 0; | |
utils.define(ele, "parent", parent); | |
ele.level = parent ? parent.level + 1 : 1; | |
if (ele.indent == null) { | |
ele.indent = parent ? parent.indent + " " : ele.indent || ""; | |
} | |
ele.path = parent ? parent.path + "." + ele.name : ele.name; | |
ele.enabled = !!(this.multiple && !this.isDisabled(ele) && (ele.enabled || this.isSelected(ele))); | |
if (!this.isDisabled(ele)) { | |
this.longest = Math.max(this.longest, colors.unstyle(ele.message).length); | |
} | |
let choice = {...ele}; | |
ele.reset = (input2 = choice.input, value = choice.value) => { | |
for (let key of Object.keys(choice)) | |
ele[key] = choice[key]; | |
ele.input = input2; | |
ele.value = value; | |
}; | |
if (origVal == null && typeof ele.initial === "function") { | |
ele.input = await ele.initial.call(this, this.state, ele, i); | |
} | |
return ele; | |
} | |
async onChoice(choice, i) { | |
this.emit("choice", choice, i, this); | |
if (typeof choice.onChoice === "function") { | |
await choice.onChoice.call(this, this.state, choice, i); | |
} | |
} | |
async addChoice(ele, i, parent) { | |
let choice = await this.toChoice(ele, i, parent); | |
this.choices.push(choice); | |
this.index = this.choices.length - 1; | |
this.limit = this.choices.length; | |
return choice; | |
} | |
async newItem(item, i, parent) { | |
let ele = {name: "New choice name?", editable: true, newChoice: true, ...item}; | |
let choice = await this.addChoice(ele, i, parent); | |
choice.updateChoice = () => { | |
delete choice.newChoice; | |
choice.name = choice.message = choice.input; | |
choice.input = ""; | |
choice.cursor = 0; | |
}; | |
return this.render(); | |
} | |
indent(choice) { | |
if (choice.indent == null) { | |
return choice.level > 1 ? " ".repeat(choice.level - 1) : ""; | |
} | |
return choice.indent; | |
} | |
dispatch(s, key) { | |
if (this.multiple && this[key.name]) | |
return this[key.name](); | |
this.alert(); | |
} | |
focus(choice, enabled) { | |
if (typeof enabled !== "boolean") | |
enabled = choice.enabled; | |
if (enabled && !choice.enabled && this.selected.length >= this.maxSelected) { | |
return this.alert(); | |
} | |
this.index = choice.index; | |
choice.enabled = enabled && !this.isDisabled(choice); | |
return choice; | |
} | |
space() { | |
if (!this.multiple) | |
return this.alert(); | |
this.toggle(this.focused); | |
return this.render(); | |
} | |
a() { | |
if (this.maxSelected < this.choices.length) | |
return this.alert(); | |
let enabled = this.selectable.every((ch) => ch.enabled); | |
this.choices.forEach((ch) => ch.enabled = !enabled); | |
return this.render(); | |
} | |
i() { | |
if (this.choices.length - this.selected.length > this.maxSelected) { | |
return this.alert(); | |
} | |
this.choices.forEach((ch) => ch.enabled = !ch.enabled); | |
return this.render(); | |
} | |
g(choice = this.focused) { | |
if (!this.choices.some((ch) => !!ch.parent)) | |
return this.a(); | |
this.toggle(choice.parent && !choice.choices ? choice.parent : choice); | |
return this.render(); | |
} | |
toggle(choice, enabled) { | |
if (!choice.enabled && this.selected.length >= this.maxSelected) { | |
return this.alert(); | |
} | |
if (typeof enabled !== "boolean") | |
enabled = !choice.enabled; | |
choice.enabled = enabled; | |
if (choice.choices) { | |
choice.choices.forEach((ch) => this.toggle(ch, enabled)); | |
} | |
let parent = choice.parent; | |
while (parent) { | |
let choices = parent.choices.filter((ch) => this.isDisabled(ch)); | |
parent.enabled = choices.every((ch) => ch.enabled === true); | |
parent = parent.parent; | |
} | |
reset(this, this.choices); | |
this.emit("toggle", choice, this); | |
return choice; | |
} | |
enable(choice) { | |
if (this.selected.length >= this.maxSelected) | |
return this.alert(); | |
choice.enabled = !this.isDisabled(choice); | |
choice.choices && choice.choices.forEach(this.enable.bind(this)); | |
return choice; | |
} | |
disable(choice) { | |
choice.enabled = false; | |
choice.choices && choice.choices.forEach(this.disable.bind(this)); | |
return choice; | |
} | |
number(n) { | |
this.num += n; | |
let number2 = (num) => { | |
let i = Number(num); | |
if (i > this.choices.length - 1) | |
return this.alert(); | |
let focused = this.focused; | |
let choice = this.choices.find((ch) => i === ch.index); | |
if (!choice.enabled && this.selected.length >= this.maxSelected) { | |
return this.alert(); | |
} | |
if (this.visible.indexOf(choice) === -1) { | |
let choices = reorder(this.choices); | |
let actualIdx = choices.indexOf(choice); | |
if (focused.index > actualIdx) { | |
let start = choices.slice(actualIdx, actualIdx + this.limit); | |
let end = choices.filter((ch) => !start.includes(ch)); | |
this.choices = start.concat(end); | |
} else { | |
let pos = actualIdx - this.limit + 1; | |
this.choices = choices.slice(pos).concat(choices.slice(0, pos)); | |
} | |
} | |
this.index = this.choices.indexOf(choice); | |
this.toggle(this.focused); | |
return this.render(); | |
}; | |
clearTimeout(this.numberTimeout); | |
return new Promise((resolve) => { | |
let len = this.choices.length; | |
let num = this.num; | |
let handle = (val = false, res) => { | |
clearTimeout(this.numberTimeout); | |
if (val) | |
res = number2(num); | |
this.num = ""; | |
resolve(res); | |
}; | |
if (num === "0" || num.length === 1 && Number(num + "0") > len) { | |
return handle(true); | |
} | |
if (Number(num) > len) { | |
return handle(false, this.alert()); | |
} | |
this.numberTimeout = setTimeout(() => handle(true), this.delay); | |
}); | |
} | |
home() { | |
this.choices = reorder(this.choices); | |
this.index = 0; | |
return this.render(); | |
} | |
end() { | |
let pos = this.choices.length - this.limit; | |
let choices = reorder(this.choices); | |
this.choices = choices.slice(pos).concat(choices.slice(0, pos)); | |
this.index = this.limit - 1; | |
return this.render(); | |
} | |
first() { | |
this.index = 0; | |
return this.render(); | |
} | |
last() { | |
this.index = this.visible.length - 1; | |
return this.render(); | |
} | |
prev() { | |
if (this.visible.length <= 1) | |
return this.alert(); | |
return this.up(); | |
} | |
next() { | |
if (this.visible.length <= 1) | |
return this.alert(); | |
return this.down(); | |
} | |
right() { | |
if (this.cursor >= this.input.length) | |
return this.alert(); | |
this.cursor++; | |
return this.render(); | |
} | |
left() { | |
if (this.cursor <= 0) | |
return this.alert(); | |
this.cursor--; | |
return this.render(); | |
} | |
up() { | |
let len = this.choices.length; | |
let vis = this.visible.length; | |
let idx = this.index; | |
if (this.options.scroll === false && idx === 0) { | |
return this.alert(); | |
} | |
if (len > vis && idx === 0) { | |
return this.scrollUp(); | |
} | |
this.index = (idx - 1 % len + len) % len; | |
if (this.isDisabled()) { | |
return this.up(); | |
} | |
return this.render(); | |
} | |
down() { | |
let len = this.choices.length; | |
let vis = this.visible.length; | |
let idx = this.index; | |
if (this.options.scroll === false && idx === vis - 1) { | |
return this.alert(); | |
} | |
if (len > vis && idx === vis - 1) { | |
return this.scrollDown(); | |
} | |
this.index = (idx + 1) % len; | |
if (this.isDisabled()) { | |
return this.down(); | |
} | |
return this.render(); | |
} | |
scrollUp(i = 0) { | |
this.choices = scrollUp(this.choices); | |
this.index = i; | |
if (this.isDisabled()) { | |
return this.up(); | |
} | |
return this.render(); | |
} | |
scrollDown(i = this.visible.length - 1) { | |
this.choices = scrollDown(this.choices); | |
this.index = i; | |
if (this.isDisabled()) { | |
return this.down(); | |
} | |
return this.render(); | |
} | |
async shiftUp() { | |
if (this.options.sort === true) { | |
this.sorting = true; | |
this.swap(this.index - 1); | |
await this.up(); | |
this.sorting = false; | |
return; | |
} | |
return this.scrollUp(this.index); | |
} | |
async shiftDown() { | |
if (this.options.sort === true) { | |
this.sorting = true; | |
this.swap(this.index + 1); | |
await this.down(); | |
this.sorting = false; | |
return; | |
} | |
return this.scrollDown(this.index); | |
} | |
pageUp() { | |
if (this.visible.length <= 1) | |
return this.alert(); | |
this.limit = Math.max(this.limit - 1, 0); | |
this.index = Math.min(this.limit - 1, this.index); | |
this._limit = this.limit; | |
if (this.isDisabled()) { | |
return this.up(); | |
} | |
return this.render(); | |
} | |
pageDown() { | |
if (this.visible.length >= this.choices.length) | |
return this.alert(); | |
this.index = Math.max(0, this.index); | |
this.limit = Math.min(this.limit + 1, this.choices.length); | |
this._limit = this.limit; | |
if (this.isDisabled()) { | |
return this.down(); | |
} | |
return this.render(); | |
} | |
swap(pos) { | |
swap$1(this.choices, this.index, pos); | |
} | |
isDisabled(choice = this.focused) { | |
let keys2 = ["disabled", "collapsed", "hidden", "completing", "readonly"]; | |
if (choice && keys2.some((key) => choice[key] === true)) { | |
return true; | |
} | |
return choice && choice.role === "heading"; | |
} | |
isEnabled(choice = this.focused) { | |
if (Array.isArray(choice)) | |
return choice.every((ch) => this.isEnabled(ch)); | |
if (choice.choices) { | |
let choices = choice.choices.filter((ch) => !this.isDisabled(ch)); | |
return choice.enabled && choices.every((ch) => this.isEnabled(ch)); | |
} | |
return choice.enabled && !this.isDisabled(choice); | |
} | |
isChoice(choice, value) { | |
return choice.name === value || choice.index === Number(value); | |
} | |
isSelected(choice) { | |
if (Array.isArray(this.initial)) { | |
return this.initial.some((value) => this.isChoice(choice, value)); | |
} | |
return this.isChoice(choice, this.initial); | |
} | |
map(names = [], prop = "value") { | |
return [].concat(names || []).reduce((acc, name) => { | |
acc[name] = this.find(name, prop); | |
return acc; | |
}, {}); | |
} | |
filter(value, prop) { | |
let isChoice = (ele, i) => [ele.name, i].includes(value); | |
let fn2 = typeof value === "function" ? value : isChoice; | |
let choices = this.options.multiple ? this.state._choices : this.choices; | |
let result = choices.filter(fn2); | |
if (prop) { | |
return result.map((ch) => ch[prop]); | |
} | |
return result; | |
} | |
find(value, prop) { | |
if (isObject$1(value)) | |
return prop ? value[prop] : value; | |
let isChoice = (ele, i) => [ele.name, i].includes(value); | |
let fn2 = typeof value === "function" ? value : isChoice; | |
let choice = this.choices.find(fn2); | |
if (choice) { | |
return prop ? choice[prop] : choice; | |
} | |
} | |
findIndex(value) { | |
return this.choices.indexOf(this.find(value)); | |
} | |
async submit() { | |
let choice = this.focused; | |
if (!choice) | |
return this.alert(); | |
if (choice.newChoice) { | |
if (!choice.input) | |
return this.alert(); | |
choice.updateChoice(); | |
return this.render(); | |
} | |
if (this.choices.some((ch) => ch.newChoice)) { | |
return this.alert(); | |
} | |
let {reorder: reorder2, sort: sort2} = this.options; | |
let multi = this.multiple === true; | |
let value = this.selected; | |
if (value === void 0) { | |
return this.alert(); | |
} | |
if (Array.isArray(value) && reorder2 !== false && sort2 !== true) { | |
value = utils.reorder(value); | |
} | |
this.value = multi ? value.map((ch) => ch.name) : value.name; | |
return super.submit(); | |
} | |
set choices(choices = []) { | |
this.state._choices = this.state._choices || []; | |
this.state.choices = choices; | |
for (let choice of choices) { | |
if (!this.state._choices.some((ch) => ch.name === choice.name)) { | |
this.state._choices.push(choice); | |
} | |
} | |
if (!this._initial && this.options.initial) { | |
this._initial = true; | |
let init2 = this.initial; | |
if (typeof init2 === "string" || typeof init2 === "number") { | |
let choice = this.find(init2); | |
if (choice) { | |
this.initial = choice.index; | |
this.focus(choice, true); | |
} | |
} | |
} | |
} | |
get choices() { | |
return reset(this, this.state.choices || []); | |
} | |
set visible(visible) { | |
this.state.visible = visible; | |
} | |
get visible() { | |
return (this.state.visible || this.choices).slice(0, this.limit); | |
} | |
set limit(num) { | |
this.state.limit = num; | |
} | |
get limit() { | |
let {state: state2, options, choices} = this; | |
let limit = state2.limit || this._limit || options.limit || choices.length; | |
return Math.min(limit, this.height); | |
} | |
set value(value) { | |
super.value = value; | |
} | |
get value() { | |
if (typeof super.value !== "string" && super.value === this.initial) { | |
return this.input; | |
} | |
return super.value; | |
} | |
set index(i) { | |
this.state.index = i; | |
} | |
get index() { | |
return Math.max(0, this.state ? this.state.index : 0); | |
} | |
get enabled() { | |
return this.filter(this.isEnabled.bind(this)); | |
} | |
get focused() { | |
let choice = this.choices[this.index]; | |
if (choice && this.state.submitted && this.multiple !== true) { | |
choice.enabled = true; | |
} | |
return choice; | |
} | |
get selectable() { | |
return this.choices.filter((choice) => !this.isDisabled(choice)); | |
} | |
get selected() { | |
return this.multiple ? this.enabled : this.focused; | |
} | |
} | |
function reset(prompt2, choices) { | |
if (choices instanceof Promise) | |
return choices; | |
if (typeof choices === "function") { | |
if (utils.isAsyncFn(choices)) | |
return choices; | |
choices = choices.call(prompt2, prompt2); | |
} | |
for (let choice of choices) { | |
if (Array.isArray(choice.choices)) { | |
let items = choice.choices.filter((ch) => !prompt2.isDisabled(ch)); | |
choice.enabled = items.every((ch) => ch.enabled === true); | |
} | |
if (prompt2.isDisabled(choice) === true) { | |
delete choice.enabled; | |
} | |
} | |
return choices; | |
} | |
var array = ArrayPrompt; | |
class SelectPrompt extends array { | |
constructor(options) { | |
super(options); | |
this.emptyError = this.options.emptyError || "No items were selected"; | |
} | |
async dispatch(s, key) { | |
if (this.multiple) { | |
return this[key.name] ? await this[key.name](s, key) : await super.dispatch(s, key); | |
} | |
this.alert(); | |
} | |
separator() { | |
if (this.options.separator) | |
return super.separator(); | |
let sep = this.styles.muted(this.symbols.ellipsis); | |
return this.state.submitted ? super.separator() : sep; | |
} | |
pointer(choice, i) { | |
return !this.multiple || this.options.pointer ? super.pointer(choice, i) : ""; | |
} | |
indicator(choice, i) { | |
return this.multiple ? super.indicator(choice, i) : ""; | |
} | |
choiceMessage(choice, i) { | |
let message = this.resolve(choice.message, this.state, choice, i); | |
if (choice.role === "heading" && !utils.hasColor(message)) { | |
message = this.styles.strong(message); | |
} | |
return this.resolve(message, this.state, choice, i); | |
} | |
choiceSeparator() { | |
return ":"; | |
} | |
async renderChoice(choice, i) { | |
await this.onChoice(choice, i); | |
let focused = this.index === i; | |
let pointer = await this.pointer(choice, i); | |
let check = await this.indicator(choice, i) + (choice.pad || ""); | |
let hint2 = await this.resolve(choice.hint, this.state, choice, i); | |
if (hint2 && !utils.hasColor(hint2)) { | |
hint2 = this.styles.muted(hint2); | |
} | |
let ind = this.indent(choice); | |
let msg = await this.choiceMessage(choice, i); | |
let line = () => [this.margin[3], ind + pointer + check, msg, this.margin[1], hint2].filter(Boolean).join(" "); | |
if (choice.role === "heading") { | |
return line(); | |
} | |
if (choice.disabled) { | |
if (!utils.hasColor(msg)) { | |
msg = this.styles.disabled(msg); | |
} | |
return line(); | |
} | |
if (focused) { | |
msg = this.styles.em(msg); | |
} | |
return line(); | |
} | |
async renderChoices() { | |
if (this.state.loading === "choices") { | |
return this.styles.warning("Loading choices"); | |
} | |
if (this.state.submitted) | |
return ""; | |
let choices = this.visible.map(async (ch, i) => await this.renderChoice(ch, i)); | |
let visible = await Promise.all(choices); | |
if (!visible.length) | |
visible.push(this.styles.danger("No matching choices")); | |
let result = this.margin[0] + visible.join("\n"); | |
let header; | |
if (this.options.choicesHeader) { | |
header = await this.resolve(this.options.choicesHeader, this.state); | |
} | |
return [header, result].filter(Boolean).join("\n"); | |
} | |
format() { | |
if (!this.state.submitted || this.state.cancelled) | |
return ""; | |
if (Array.isArray(this.selected)) { | |
return this.selected.map((choice) => this.styles.primary(choice.name)).join(", "); | |
} | |
return this.styles.primary(this.selected.name); | |
} | |
async render() { | |
let {submitted, size} = this.state; | |
let prompt2 = ""; | |
let header = await this.header(); | |
let prefix = await this.prefix(); | |
let separator = await this.separator(); | |
let message = await this.message(); | |
if (this.options.promptLine !== false) { | |
prompt2 = [prefix, message, separator, ""].join(" "); | |
this.state.prompt = prompt2; | |
} | |
let output = await this.format(); | |
let help = await this.error() || await this.hint(); | |
let body = await this.renderChoices(); | |
let footer = await this.footer(); | |
if (output) | |
prompt2 += output; | |
if (help && !prompt2.includes(help)) | |
prompt2 += " " + help; | |
if (submitted && !output && !body.trim() && this.multiple && this.emptyError != null) { | |
prompt2 += this.styles.danger(this.emptyError); | |
} | |
this.clear(size); | |
this.write([header, prompt2, body, footer].filter(Boolean).join("\n")); | |
this.write(this.margin[2]); | |
this.restore(); | |
} | |
} | |
var select = SelectPrompt; | |
const highlight = (input2, color) => { | |
let val = input2.toLowerCase(); | |
return (str) => { | |
let s = str.toLowerCase(); | |
let i = s.indexOf(val); | |
let colored = color(str.slice(i, i + val.length)); | |
return i >= 0 ? str.slice(0, i) + colored + str.slice(i + val.length) : str; | |
}; | |
}; | |
class AutoComplete extends select { | |
constructor(options) { | |
super(options); | |
this.cursorShow(); | |
} | |
moveCursor(n) { | |
this.state.cursor += n; | |
} | |
dispatch(ch) { | |
return this.append(ch); | |
} | |
space(ch) { | |
return this.options.multiple ? super.space(ch) : this.append(ch); | |
} | |
append(ch) { | |
let {cursor, input: input2} = this.state; | |
this.input = input2.slice(0, cursor) + ch + input2.slice(cursor); | |
this.moveCursor(1); | |
return this.complete(); | |
} | |
delete() { | |
let {cursor, input: input2} = this.state; | |
if (!input2) | |
return this.alert(); | |
this.input = input2.slice(0, cursor - 1) + input2.slice(cursor); | |
this.moveCursor(-1); | |
return this.complete(); | |
} | |
deleteForward() { | |
let {cursor, input: input2} = this.state; | |
if (input2[cursor] === void 0) | |
return this.alert(); | |
this.input = `${input2}`.slice(0, cursor) + `${input2}`.slice(cursor + 1); | |
return this.complete(); | |
} | |
number(ch) { | |
return this.append(ch); | |
} | |
async complete() { | |
this.completing = true; | |
this.choices = await this.suggest(this.input, this.state._choices); | |
this.state.limit = void 0; | |
this.index = Math.min(Math.max(this.visible.length - 1, 0), this.index); | |
await this.render(); | |
this.completing = false; | |
} | |
suggest(input2 = this.input, choices = this.state._choices) { | |
if (typeof this.options.suggest === "function") { | |
return this.options.suggest.call(this, input2, choices); | |
} | |
let str = input2.toLowerCase(); | |
return choices.filter((ch) => ch.message.toLowerCase().includes(str)); | |
} | |
pointer() { | |
return ""; | |
} | |
format() { | |
if (!this.focused) | |
return this.input; | |
if (this.options.multiple && this.state.submitted) { | |
return this.selected.map((ch) => this.styles.primary(ch.message)).join(", "); | |
} | |
if (this.state.submitted) { | |
let value = this.value = this.input = this.focused.value; | |
return this.styles.primary(value); | |
} | |
return this.input; | |
} | |
async render() { | |
if (this.state.status !== "pending") | |
return super.render(); | |
let style = this.options.highlight ? this.options.highlight.bind(this) : this.styles.placeholder; | |
let color = highlight(this.input, style); | |
let choices = this.choices; | |
this.choices = choices.map((ch) => ({...ch, message: color(ch.message)})); | |
await super.render(); | |
this.choices = choices; | |
} | |
submit() { | |
if (this.options.multiple) { | |
this.value = this.selected.map((ch) => ch.name); | |
} | |
return super.submit(); | |
} | |
} | |
var autocomplete = AutoComplete; | |
var placeholder = (prompt2, options = {}) => { | |
prompt2.cursorHide(); | |
let {input: input2 = "", initial = "", pos, showCursor = true, color} = options; | |
let style = color || prompt2.styles.placeholder; | |
let inverse = utils.inverse(prompt2.styles.primary); | |
let blinker = (str) => inverse(prompt2.styles.black(str)); | |
let output = input2; | |
let char = " "; | |
let reverse = blinker(char); | |
if (prompt2.blink && prompt2.blink.off === true) { | |
blinker = (str) => str; | |
reverse = ""; | |
} | |
if (showCursor && pos === 0 && initial === "" && input2 === "") { | |
return blinker(char); | |
} | |
if (showCursor && pos === 0 && (input2 === initial || input2 === "")) { | |
return blinker(initial[0]) + style(initial.slice(1)); | |
} | |
initial = utils.isPrimitive(initial) ? `${initial}` : ""; | |
input2 = utils.isPrimitive(input2) ? `${input2}` : ""; | |
let placeholder2 = initial && initial.startsWith(input2) && initial !== input2; | |
let cursor = placeholder2 ? blinker(initial[input2.length]) : reverse; | |
if (pos !== input2.length && showCursor === true) { | |
output = input2.slice(0, pos) + blinker(input2[pos]) + input2.slice(pos + 1); | |
cursor = ""; | |
} | |
if (showCursor === false) { | |
cursor = ""; | |
} | |
if (placeholder2) { | |
let raw = prompt2.styles.unstyle(output + cursor); | |
return output + cursor + style(initial.slice(raw.length)); | |
} | |
return output + cursor; | |
}; | |
class FormPrompt extends select { | |
constructor(options) { | |
super({...options, multiple: true}); | |
this.type = "form"; | |
this.initial = this.options.initial; | |
this.align = [this.options.align, "right"].find((v) => v != null); | |
this.emptyError = ""; | |
this.values = {}; | |
} | |
async reset(first) { | |
await super.reset(); | |
if (first === true) | |
this._index = this.index; | |
this.index = this._index; | |
this.values = {}; | |
this.choices.forEach((choice) => choice.reset && choice.reset()); | |
return this.render(); | |
} | |
dispatch(char) { | |
return !!char && this.append(char); | |
} | |
append(char) { | |
let choice = this.focused; | |
if (!choice) | |
return this.alert(); | |
let {cursor, input: input2} = choice; | |
choice.value = choice.input = input2.slice(0, cursor) + char + input2.slice(cursor); | |
choice.cursor++; | |
return this.render(); | |
} | |
delete() { | |
let choice = this.focused; | |
if (!choice || choice.cursor <= 0) | |
return this.alert(); | |
let {cursor, input: input2} = choice; | |
choice.value = choice.input = input2.slice(0, cursor - 1) + input2.slice(cursor); | |
choice.cursor--; | |
return this.render(); | |
} | |
deleteForward() { | |
let choice = this.focused; | |
if (!choice) | |
return this.alert(); | |
let {cursor, input: input2} = choice; | |
if (input2[cursor] === void 0) | |
return this.alert(); | |
let str = `${input2}`.slice(0, cursor) + `${input2}`.slice(cursor + 1); | |
choice.value = choice.input = str; | |
return this.render(); | |
} | |
right() { | |
let choice = this.focused; | |
if (!choice) | |
return this.alert(); | |
if (choice.cursor >= choice.input.length) | |
return this.alert(); | |
choice.cursor++; | |
return this.render(); | |
} | |
left() { | |
let choice = this.focused; | |
if (!choice) | |
return this.alert(); | |
if (choice.cursor <= 0) | |
return this.alert(); | |
choice.cursor--; | |
return this.render(); | |
} | |
space(ch, key) { | |
return this.dispatch(ch, key); | |
} | |
number(ch, key) { | |
return this.dispatch(ch, key); | |
} | |
next() { | |
let ch = this.focused; | |
if (!ch) | |
return this.alert(); | |
let {initial, input: input2} = ch; | |
if (initial && initial.startsWith(input2) && input2 !== initial) { | |
ch.value = ch.input = initial; | |
ch.cursor = ch.value.length; | |
return this.render(); | |
} | |
return super.next(); | |
} | |
prev() { | |
let ch = this.focused; | |
if (!ch) | |
return this.alert(); | |
if (ch.cursor === 0) | |
return super.prev(); | |
ch.value = ch.input = ""; | |
ch.cursor = 0; | |
return this.render(); | |
} | |
separator() { | |
return ""; | |
} | |
format(value) { | |
return !this.state.submitted ? super.format(value) : ""; | |
} | |
pointer() { | |
return ""; | |
} | |
indicator(choice) { | |
return choice.input ? "\u29BF" : "\u2299"; | |
} | |
async choiceSeparator(choice, i) { | |
let sep = await this.resolve(choice.separator, this.state, choice, i) || ":"; | |
return sep ? " " + this.styles.disabled(sep) : ""; | |
} | |
async renderChoice(choice, i) { | |
await this.onChoice(choice, i); | |
let {state: state2, styles: styles2} = this; | |
let {cursor, initial = "", name, hint: hint2, input: input2 = ""} = choice; | |
let {muted, submitted, primary, danger} = styles2; | |
let help = hint2; | |
let focused = this.index === i; | |
let validate = choice.validate || (() => true); | |
let sep = await this.choiceSeparator(choice, i); | |
let msg = choice.message; | |
if (this.align === "right") | |
msg = msg.padStart(this.longest + 1, " "); | |
if (this.align === "left") | |
msg = msg.padEnd(this.longest + 1, " "); | |
let value = this.values[name] = input2 || initial; | |
let color = input2 ? "success" : "dark"; | |
if (await validate.call(choice, value, this.state) !== true) { | |
color = "danger"; | |
} | |
let style = styles2[color]; | |
let indicator = style(await this.indicator(choice, i)) + (choice.pad || ""); | |
let indent = this.indent(choice); | |
let line = () => [indent, indicator, msg + sep, input2, help].filter(Boolean).join(" "); | |
if (state2.submitted) { | |
msg = colors.unstyle(msg); | |
input2 = submitted(input2); | |
help = ""; | |
return line(); | |
} | |
if (choice.format) { | |
input2 = await choice.format.call(this, input2, choice, i); | |
} else { | |
let color2 = this.styles.muted; | |
let options = {input: input2, initial, pos: cursor, showCursor: focused, color: color2}; | |
input2 = placeholder(this, options); | |
} | |
if (!this.isValue(input2)) { | |
input2 = this.styles.muted(this.symbols.ellipsis); | |
} | |
if (choice.result) { | |
this.values[name] = await choice.result.call(this, value, choice, i); | |
} | |
if (focused) { | |
msg = primary(msg); | |
} | |
if (choice.error) { | |
input2 += (input2 ? " " : "") + danger(choice.error.trim()); | |
} else if (choice.hint) { | |
input2 += (input2 ? " " : "") + muted(choice.hint.trim()); | |
} | |
return line(); | |
} | |
async submit() { | |
this.value = this.values; | |
return super.base.submit.call(this); | |
} | |
} | |
var form = FormPrompt; | |
const defaultAuthenticate = () => { | |
throw new Error("expected prompt to have a custom authenticate method"); | |
}; | |
const factory = (authenticate = defaultAuthenticate) => { | |
class AuthPrompt extends form { | |
constructor(options) { | |
super(options); | |
} | |
async submit() { | |
this.value = await authenticate.call(this, this.values, this.state); | |
super.base.submit.call(this); | |
} | |
static create(authenticate2) { | |
return factory(authenticate2); | |
} | |
} | |
return AuthPrompt; | |
}; | |
var auth = factory(); | |
function defaultAuthenticate$1(value, state2) { | |
if (value.username === this.options.username && value.password === this.options.password) { | |
return true; | |
} | |
return false; | |
} | |
const factory$1 = (authenticate = defaultAuthenticate$1) => { | |
const choices = [ | |
{name: "username", message: "username"}, | |
{ | |
name: "password", | |
message: "password", | |
format(input2) { | |
if (this.options.showPassword) { | |
return input2; | |
} | |
let color = this.state.submitted ? this.styles.primary : this.styles.muted; | |
return color(this.symbols.asterisk.repeat(input2.length)); | |
} | |
} | |
]; | |
class BasicAuthPrompt extends auth.create(authenticate) { | |
constructor(options) { | |
super({...options, choices}); | |
} | |
static create(authenticate2) { | |
return factory$1(authenticate2); | |
} | |
} | |
return BasicAuthPrompt; | |
}; | |
var basicauth = factory$1(); | |
const {isPrimitive: isPrimitive$1, hasColor} = utils; | |
class BooleanPrompt extends prompt { | |
constructor(options) { | |
super(options); | |
this.cursorHide(); | |
} | |
async initialize() { | |
let initial = await this.resolve(this.initial, this.state); | |
this.input = await this.cast(initial); | |
await super.initialize(); | |
} | |
dispatch(ch) { | |
if (!this.isValue(ch)) | |
return this.alert(); | |
this.input = ch; | |
return this.submit(); | |
} | |
format(value) { | |
let {styles: styles2, state: state2} = this; | |
return !state2.submitted ? styles2.primary(value) : styles2.success(value); | |
} | |
cast(input2) { | |
return this.isTrue(input2); | |
} | |
isTrue(input2) { | |
return /^[ty1]/i.test(input2); | |
} | |
isFalse(input2) { | |
return /^[fn0]/i.test(input2); | |
} | |
isValue(value) { | |
return isPrimitive$1(value) && (this.isTrue(value) || this.isFalse(value)); | |
} | |
async hint() { | |
if (this.state.status === "pending") { | |
let hint2 = await this.element("hint"); | |
if (!hasColor(hint2)) { | |
return this.styles.muted(hint2); | |
} | |
return hint2; | |
} | |
} | |
async render() { | |
let {input: input2, size} = this.state; | |
let prefix = await this.prefix(); | |
let sep = await this.separator(); | |
let msg = await this.message(); | |
let hint2 = this.styles.muted(this.default); | |
let promptLine = [prefix, msg, hint2, sep].filter(Boolean).join(" "); | |
this.state.prompt = promptLine; | |
let header = await this.header(); | |
let value = this.value = this.cast(input2); | |
let output = await this.format(value); | |
let help = await this.error() || await this.hint(); | |
let footer = await this.footer(); | |
if (help && !promptLine.includes(help)) | |
output += " " + help; | |
promptLine += " " + output; | |
this.clear(size); | |
this.write([header, promptLine, footer].filter(Boolean).join("\n")); | |
this.restore(); | |
} | |
set value(value) { | |
super.value = value; | |
} | |
get value() { | |
return this.cast(super.value); | |
} | |
} | |
var boolean_1 = BooleanPrompt; | |
class ConfirmPrompt extends boolean_1 { | |
constructor(options) { | |
super(options); | |
this.default = this.options.default || (this.initial ? "(Y/n)" : "(y/N)"); | |
} | |
} | |
var confirm = ConfirmPrompt; | |
const form$1 = form.prototype; | |
class Editable extends select { | |
constructor(options) { | |
super({...options, multiple: true}); | |
this.align = [this.options.align, "left"].find((v) => v != null); | |
this.emptyError = ""; | |
this.values = {}; | |
} | |
dispatch(char, key) { | |
let choice = this.focused; | |
let parent = choice.parent || {}; | |
if (!choice.editable && !parent.editable) { | |
if (char === "a" || char === "i") | |
return super[char](); | |
} | |
return form$1.dispatch.call(this, char, key); | |
} | |
append(char, key) { | |
return form$1.append.call(this, char, key); | |
} | |
delete(char, key) { | |
return form$1.delete.call(this, char, key); | |
} | |
space(char) { | |
return this.focused.editable ? this.append(char) : super.space(); | |
} | |
number(char) { | |
return this.focused.editable ? this.append(char) : super.number(char); | |
} | |
next() { | |
return this.focused.editable ? form$1.next.call(this) : super.next(); | |
} | |
prev() { | |
return this.focused.editable ? form$1.prev.call(this) : super.prev(); | |
} | |
async indicator(choice, i) { | |
let symbol = choice.indicator || ""; | |
let value = choice.editable ? symbol : super.indicator(choice, i); | |
return await this.resolve(value, this.state, choice, i) || ""; | |
} | |
indent(choice) { | |
return choice.role === "heading" ? "" : choice.editable ? " " : " "; | |
} | |
async renderChoice(choice, i) { | |
choice.indent = ""; | |
if (choice.editable) | |
return form$1.renderChoice.call(this, choice, i); | |
return super.renderChoice(choice, i); | |
} | |
error() { | |
return ""; | |
} | |
footer() { | |
return this.state.error; | |
} | |
async validate() { | |
let result = true; | |
for (let choice of this.choices) { | |
if (typeof choice.validate !== "function") { | |
continue; | |
} | |
if (choice.role === "heading") { | |
continue; | |
} | |
let val = choice.parent ? this.value[choice.parent.name] : this.value; | |
if (choice.editable) { | |
val = choice.value === choice.name ? choice.initial || "" : choice.value; | |
} else if (!this.isDisabled(choice)) { | |
val = choice.enabled === true; | |
} | |
result = await choice.validate(val, this.state); | |
if (result !== true) { | |
break; | |
} | |
} | |
if (result !== true) { | |
this.state.error = typeof result === "string" ? result : "Invalid Input"; | |
} | |
return result; | |
} | |
submit() { | |
if (this.focused.newChoice === true) | |
return super.submit(); | |
if (this.choices.some((ch) => ch.newChoice)) { | |
return this.alert(); | |
} | |
this.value = {}; | |
for (let choice of this.choices) { | |
let val = choice.parent ? this.value[choice.parent.name] : this.value; | |
if (choice.role === "heading") { | |
this.value[choice.name] = {}; | |
continue; | |
} | |
if (choice.editable) { | |
val[choice.name] = choice.value === choice.name ? choice.initial || "" : choice.value; | |
} else if (!this.isDisabled(choice)) { | |
val[choice.name] = choice.enabled === true; | |
} | |
} | |
return this.base.submit.call(this); | |
} | |
} | |
var editable = Editable; | |
const {isPrimitive: isPrimitive$2} = utils; | |
class StringPrompt extends prompt { | |
constructor(options) { | |
super(options); | |
this.initial = isPrimitive$2(this.initial) ? String(this.initial) : ""; | |
if (this.initial) | |
this.cursorHide(); | |
this.state.prevCursor = 0; | |
this.state.clipboard = []; | |
} | |
async keypress(input2, key = {}) { | |
let prev = this.state.prevKeypress; | |
this.state.prevKeypress = key; | |
if (this.options.multiline === true && key.name === "return") { | |
if (!prev || prev.name !== "return") { | |
return this.append("\n", key); | |
} | |
} | |
return super.keypress(input2, key); | |
} | |
moveCursor(n) { | |
this.cursor += n; | |
} | |
reset() { | |
this.input = this.value = ""; | |
this.cursor = 0; | |
return this.render(); | |
} | |
dispatch(ch, key) { | |
if (!ch || key.ctrl || key.code) | |
return this.alert(); | |
this.append(ch); | |
} | |
append(ch) { | |
let {cursor, input: input2} = this.state; | |
this.input = `${input2}`.slice(0, cursor) + ch + `${input2}`.slice(cursor); | |
this.moveCursor(String(ch).length); | |
this.render(); | |
} | |
insert(str) { | |
this.append(str); | |
} | |
delete() { | |
let {cursor, input: input2} = this.state; | |
if (cursor <= 0) | |
return this.alert(); | |
this.input = `${input2}`.slice(0, cursor - 1) + `${input2}`.slice(cursor); | |
this.moveCursor(-1); | |
this.render(); | |
} | |
deleteForward() { | |
let {cursor, input: input2} = this.state; | |
if (input2[cursor] === void 0) | |
return this.alert(); | |
this.input = `${input2}`.slice(0, cursor) + `${input2}`.slice(cursor + 1); | |
this.render(); | |
} | |
cutForward() { | |
let pos = this.cursor; | |
if (this.input.length <= pos) | |
return this.alert(); | |
this.state.clipboard.push(this.input.slice(pos)); | |
this.input = this.input.slice(0, pos); | |
this.render(); | |
} | |
cutLeft() { | |
let pos = this.cursor; | |
if (pos === 0) | |
return this.alert(); | |
let before = this.input.slice(0, pos); | |
let after = this.input.slice(pos); | |
let words = before.split(" "); | |
this.state.clipboard.push(words.pop()); | |
this.input = words.join(" "); | |
this.cursor = this.input.length; | |
this.input += after; | |
this.render(); | |
} | |
paste() { | |
if (!this.state.clipboard.length) | |
return this.alert(); | |
this.insert(this.state.clipboard.pop()); | |
this.render(); | |
} | |
toggleCursor() { | |
if (this.state.prevCursor) { | |
this.cursor = this.state.prevCursor; | |
this.state.prevCursor = 0; | |
} else { | |
this.state.prevCursor = this.cursor; | |
this.cursor = 0; | |
} | |
this.render(); | |
} | |
first() { | |
this.cursor = 0; | |
this.render(); | |
} | |
last() { | |
this.cursor = this.input.length - 1; | |
this.render(); | |
} | |
next() { | |
let init2 = this.initial != null ? String(this.initial) : ""; | |
if (!init2 || !init2.startsWith(this.input)) | |
return this.alert(); | |
this.input = this.initial; | |
this.cursor = this.initial.length; | |
this.render(); | |
} | |
prev() { | |
if (!this.input) | |
return this.alert(); | |
this.reset(); | |
} | |
backward() { | |
return this.left(); | |
} | |
forward() { | |
return this.right(); | |
} | |
right() { | |
if (this.cursor >= this.input.length) | |
return this.alert(); | |
this.moveCursor(1); | |
return this.render(); | |
} | |
left() { | |
if (this.cursor <= 0) | |
return this.alert(); | |
this.moveCursor(-1); | |
return this.render(); | |
} | |
isValue(value) { | |
return !!value; | |
} | |
async format(input2 = this.value) { | |
let initial = await this.resolve(this.initial, this.state); | |
if (!this.state.submitted) { | |
return placeholder(this, {input: input2, initial, pos: this.cursor}); | |
} | |
return this.styles.submitted(input2 || initial); | |
} | |
async render() { | |
let size = this.state.size; | |
let prefix = await this.prefix(); | |
let separator = await this.separator(); | |
let message = await this.message(); | |
let prompt2 = [prefix, message, separator].filter(Boolean).join(" "); | |
this.state.prompt = prompt2; | |
let header = await this.header(); | |
let output = await this.format(); | |
let help = await this.error() || await this.hint(); | |
let footer = await this.footer(); | |
if (help && !output.includes(help)) | |
output += " " + help; | |
prompt2 += " " + output; | |
this.clear(size); | |
this.write([header, prompt2, footer].filter(Boolean).join("\n")); | |
this.restore(); | |
} | |
} | |
var string = StringPrompt; | |
const unique = (arr) => arr.filter((v, i) => arr.lastIndexOf(v) === i); | |
const compact = (arr) => unique(arr).filter(Boolean); | |
var completer = (action, data = {}, value = "") => { | |
let {past = [], present = ""} = data; | |
let rest, prev; | |
switch (action) { | |
case "prev": | |
case "undo": | |
rest = past.slice(0, past.length - 1); | |
prev = past[past.length - 1] || ""; | |
return { | |
past: compact([value, ...rest]), | |
present: prev | |
}; | |
case "next": | |
case "redo": | |
rest = past.slice(1); | |
prev = past[0] || ""; | |
return { | |
past: compact([...rest, value]), | |
present: prev | |
}; | |
case "save": | |
return { | |
past: compact([...past, value]), | |
present: "" | |
}; | |
case "remove": | |
prev = compact(past.filter((v) => v !== value)); | |
present = ""; | |
if (prev.length) { | |
present = prev.pop(); | |
} | |
return { | |
past: prev, | |
present | |
}; | |
default: { | |
throw new Error(`Invalid action: "${action}"`); | |
} | |
} | |
}; | |
class Input extends string { | |
constructor(options) { | |
super(options); | |
let history = this.options.history; | |
if (history && history.store) { | |
let initial = history.values || this.initial; | |
this.autosave = !!history.autosave; | |
this.store = history.store; | |
this.data = this.store.get("values") || {past: [], present: initial}; | |
this.initial = this.data.present || this.data.past[this.data.past.length - 1]; | |
} | |
} | |
completion(action) { | |
if (!this.store) | |
return this.alert(); | |
this.data = completer(action, this.data, this.input); | |
if (!this.data.present) | |
return this.alert(); | |
this.input = this.data.present; | |
this.cursor = this.input.length; | |
return this.render(); | |
} | |
altUp() { | |
return this.completion("prev"); | |
} | |
altDown() { | |
return this.completion("next"); | |
} | |
prev() { | |
this.save(); | |
return super.prev(); | |
} | |
save() { | |
if (!this.store) | |
return; | |
this.data = completer("save", this.data, this.input); | |
this.store.set("values", this.data); | |
} | |
submit() { | |
if (this.store && this.autosave === true) { | |
this.save(); | |
} | |
return super.submit(); | |
} | |
} | |
var input = Input; | |
class InvisiblePrompt extends string { | |
format() { | |
return ""; | |
} | |
} | |
var invisible = InvisiblePrompt; | |
class ListPrompt extends string { | |
constructor(options = {}) { | |
super(options); | |
this.sep = this.options.separator || /, */; | |
this.initial = options.initial || ""; | |
} | |
split(input2 = this.value) { | |
return input2 ? String(input2).split(this.sep) : []; | |
} | |
format() { | |
let style = this.state.submitted ? this.styles.primary : (val) => val; | |
return this.list.map(style).join(", "); | |
} | |
async submit(value) { | |
let result = this.state.error || await this.validate(this.list, this.state); | |
if (result !== true) { | |
this.state.error = result; | |
return super.submit(); | |
} | |
this.value = this.list; | |
return super.submit(); | |
} | |
get list() { | |
return this.split(); | |
} | |
} | |
var list = ListPrompt; | |
class MultiSelect extends select { | |
constructor(options) { | |
super({...options, multiple: true}); | |
} | |
} | |
var multiselect = MultiSelect; | |
class NumberPrompt extends string { | |
constructor(options = {}) { | |
super({style: "number", ...options}); | |
this.min = this.isValue(options.min) ? this.toNumber(options.min) : -Infinity; | |
this.max = this.isValue(options.max) ? this.toNumber(options.max) : Infinity; | |
this.delay = options.delay != null ? options.delay : 1e3; | |
this.float = options.float !== false; | |
this.round = options.round === true || options.float === false; | |
this.major = options.major || 10; | |
this.minor = options.minor || 1; | |
this.initial = options.initial != null ? options.initial : ""; | |
this.input = String(this.initial); | |
this.cursor = this.input.length; | |
this.cursorShow(); | |
} | |
append(ch) { | |
if (!/[-+.]/.test(ch) || ch === "." && this.input.includes(".")) { | |
return this.alert("invalid number"); | |
} | |
return super.append(ch); | |
} | |
number(ch) { | |
return super.append(ch); | |
} | |
next() { | |
if (this.input && this.input !== this.initial) | |
return this.alert(); | |
if (!this.isValue(this.initial)) | |
return this.alert(); | |
this.input = this.initial; | |
this.cursor = String(this.initial).length; | |
return this.render(); | |
} | |
up(number2) { | |
let step = number2 || this.minor; | |
let num = this.toNumber(this.input); | |
if (num > this.max + step) | |
return this.alert(); | |
this.input = `${num + step}`; | |
return this.render(); | |
} | |
down(number2) { | |
let step = number2 || this.minor; | |
let num = this.toNumber(this.input); | |
if (num < this.min - step) | |
return this.alert(); | |
this.input = `${num - step}`; | |
return this.render(); | |
} | |
shiftDown() { | |
return this.down(this.major); | |
} | |
shiftUp() { | |
return this.up(this.major); | |
} | |
format(input2 = this.input) { | |
if (typeof this.options.format === "function") { | |
return this.options.format.call(this, input2); | |
} | |
return this.styles.info(input2); | |
} | |
toNumber(value = "") { | |
return this.float ? +value : Math.round(+value); | |
} | |
isValue(value) { | |
return /^[-+]?[0-9]+((\.)|(\.[0-9]+))?$/.test(value); | |
} | |
submit() { | |
let value = [this.input, this.initial].find((v) => this.isValue(v)); | |
this.value = this.toNumber(value || 0); | |
return super.submit(); | |
} | |
} | |
var number = NumberPrompt; | |
var numeral = number; | |
class PasswordPrompt extends string { | |
constructor(options) { | |
super(options); | |
this.cursorShow(); | |
} | |
format(input2 = this.input) { | |
if (!this.keypressed) | |
return ""; | |
let color = this.state.submitted ? this.styles.primary : this.styles.muted; | |
return color(this.symbols.asterisk.repeat(input2.length)); | |
} | |
} | |
var password = PasswordPrompt; | |
class LikertScale extends array { | |
constructor(options = {}) { | |
super(options); | |
this.widths = [].concat(options.messageWidth || 50); | |
this.align = [].concat(options.align || "left"); | |
this.linebreak = options.linebreak || false; | |
this.edgeLength = options.edgeLength || 3; | |
this.newline = options.newline || "\n "; | |
let start = options.startNumber || 1; | |
if (typeof this.scale === "number") { | |
this.scaleKey = false; | |
this.scale = Array(this.scale).fill(0).map((v, i) => ({name: i + start})); | |
} | |
} | |
async reset() { | |
this.tableized = false; | |
await super.reset(); | |
return this.render(); | |
} | |
tableize() { | |
if (this.tableized === true) | |
return; | |
this.tableized = true; | |
let longest = 0; | |
for (let ch of this.choices) { | |
longest = Math.max(longest, ch.message.length); | |
ch.scaleIndex = ch.initial || 2; | |
ch.scale = []; | |
for (let i = 0; i < this.scale.length; i++) { | |
ch.scale.push({index: i}); | |
} | |
} | |
this.widths[0] = Math.min(this.widths[0], longest + 3); | |
} | |
async dispatch(s, key) { | |
if (this.multiple) { | |
return this[key.name] ? await this[key.name](s, key) : await super.dispatch(s, key); | |
} | |
this.alert(); | |
} | |
heading(msg, item, i) { | |
return this.styles.strong(msg); | |
} | |
separator() { | |
return this.styles.muted(this.symbols.ellipsis); | |
} | |
right() { | |
let choice = this.focused; | |
if (choice.scaleIndex >= this.scale.length - 1) | |
return this.alert(); | |
choice.scaleIndex++; | |
return this.render(); | |
} | |
left() { | |
let choice = this.focused; | |
if (choice.scaleIndex <= 0) | |
return this.alert(); | |
choice.scaleIndex--; | |
return this.render(); | |
} | |
indent() { | |
return ""; | |
} | |
format() { | |
if (this.state.submitted) { | |
let values = this.choices.map((ch) => this.styles.info(ch.index)); | |
return values.join(", "); | |
} | |
return ""; | |
} | |
pointer() { | |
return ""; | |
} | |
renderScaleKey() { | |
if (this.scaleKey === false) | |
return ""; | |
if (this.state.submitted) | |
return ""; | |
let scale2 = this.scale.map((item) => ` ${item.name} - ${item.message}`); | |
let key = ["", ...scale2].map((item) => this.styles.muted(item)); | |
return key.join("\n"); | |
} | |
renderScaleHeading(max) { | |
let keys2 = this.scale.map((ele) => ele.name); | |
if (typeof this.options.renderScaleHeading === "function") { | |
keys2 = this.options.renderScaleHeading.call(this, max); | |
} | |
let diff = this.scaleLength - keys2.join("").length; | |
let spacing = Math.round(diff / (keys2.length - 1)); | |
let names = keys2.map((key) => this.styles.strong(key)); | |
let headings = names.join(" ".repeat(spacing)); | |
let padding = " ".repeat(this.widths[0]); | |
return this.margin[3] + padding + this.margin[1] + headings; | |
} | |
scaleIndicator(choice, item, i) { | |
if (typeof this.options.scaleIndicator === "function") { | |
return this.options.scaleIndicator.call(this, choice, item, i); | |
} | |
let enabled = choice.scaleIndex === item.index; | |
if (item.disabled) | |
return this.styles.hint(this.symbols.radio.disabled); | |
if (enabled) | |
return this.styles.success(this.symbols.radio.on); | |
return this.symbols.radio.off; | |
} | |
renderScale(choice, i) { | |
let scale2 = choice.scale.map((item) => this.scaleIndicator(choice, item, i)); | |
let padding = this.term === "Hyper" ? "" : " "; | |
return scale2.join(padding + this.symbols.line.repeat(this.edgeLength)); | |
} | |
async renderChoice(choice, i) { | |
await this.onChoice(choice, i); | |
let focused = this.index === i; | |
let pointer = await this.pointer(choice, i); | |
let hint2 = await choice.hint; | |
if (hint2 && !utils.hasColor(hint2)) { | |
hint2 = this.styles.muted(hint2); | |
} | |
let pad = (str) => this.margin[3] + str.replace(/\s+$/, "").padEnd(this.widths[0], " "); | |
let newline = this.newline; | |
let ind = this.indent(choice); | |
let message = await this.resolve(choice.message, this.state, choice, i); | |
let scale2 = await this.renderScale(choice, i); | |
let margin2 = this.margin[1] + this.margin[3]; | |
this.scaleLength = colors.unstyle(scale2).length; | |
this.widths[0] = Math.min(this.widths[0], this.width - this.scaleLength - margin2.length); | |
let msg = utils.wordWrap(message, {width: this.widths[0], newline}); | |
let lines = msg.split("\n").map((line) => pad(line) + this.margin[1]); | |
if (focused) { | |
scale2 = this.styles.info(scale2); | |
lines = lines.map((line) => this.styles.info(line)); | |
} | |
lines[0] += scale2; | |
if (this.linebreak) | |
lines.push(""); | |
return [ind + pointer, lines.join("\n")].filter(Boolean); | |
} | |
async renderChoices() { | |
if (this.state.submitted) | |
return ""; | |
this.tableize(); | |
let choices = this.visible.map(async (ch, i) => await this.renderChoice(ch, i)); | |
let visible = await Promise.all(choices); | |
let heading = await this.renderScaleHeading(); | |
return this.margin[0] + [heading, ...visible.map((v) => v.join(" "))].join("\n"); | |
} | |
async render() { | |
let {submitted, size} = this.state; | |
let prefix = await this.prefix(); | |
let separator = await this.separator(); | |
let message = await this.message(); | |
let prompt2 = ""; | |
if (this.options.promptLine !== false) { | |
prompt2 = [prefix, message, separator, ""].join(" "); | |
this.state.prompt = prompt2; | |
} | |
let header = await this.header(); | |
let output = await this.format(); | |
let key = await this.renderScaleKey(); | |
let help = await this.error() || await this.hint(); | |
let body = await this.renderChoices(); | |
let footer = await this.footer(); | |
let err = this.emptyError; | |
if (output) | |
prompt2 += output; | |
if (help && !prompt2.includes(help)) | |
prompt2 += " " + help; | |
if (submitted && !output && !body.trim() && this.multiple && err != null) { | |
prompt2 += this.styles.danger(err); | |
} | |
this.clear(size); | |
this.write([header, prompt2, key, body, footer].filter(Boolean).join("\n")); | |
if (!this.state.submitted) { | |
this.write(this.margin[2]); | |
} | |
this.restore(); | |
} | |
submit() { | |
this.value = {}; | |
for (let choice of this.choices) { | |
this.value[choice.name] = choice.scaleIndex; | |
} | |
return this.base.submit.call(this); | |
} | |
} | |
var scale = LikertScale; | |
const clean = (str = "") => { | |
return typeof str === "string" ? str.replace(/^['"]|['"]$/g, "") : ""; | |
}; | |
class Item$1 { | |
constructor(token) { | |
this.name = token.key; | |
this.field = token.field || {}; | |
this.value = clean(token.initial || this.field.initial || ""); | |
this.message = token.message || this.name; | |
this.cursor = 0; | |
this.input = ""; | |
this.lines = []; | |
} | |
} | |
const tokenize = async (options = {}, defaults = {}, fn2 = (token) => token) => { | |
let unique2 = new Set(); | |
let fields = options.fields || []; | |
let input2 = options.template; | |
let tabstops = []; | |
let items = []; | |
let keys2 = []; | |
let line = 1; | |
if (typeof input2 === "function") { | |
input2 = await input2(); | |
} | |
let i = -1; | |
let next = () => input2[++i]; | |
let peek = () => input2[i + 1]; | |
let push = (token) => { | |
token.line = line; | |
tabstops.push(token); | |
}; | |
push({type: "bos", value: ""}); | |
while (i < input2.length - 1) { | |
let value = next(); | |
if (/^[^\S\n ]$/.test(value)) { | |
push({type: "text", value}); | |
continue; | |
} | |
if (value === "\n") { | |
push({type: "newline", value}); | |
line++; | |
continue; | |
} | |
if (value === "\\") { | |
value += next(); | |
push({type: "text", value}); | |
continue; | |
} | |
if ((value === "$" || value === "#" || value === "{") && peek() === "{") { | |
let n = next(); | |
value += n; | |
let token = {type: "template", open: value, inner: "", close: "", value}; | |
let ch; | |
while (ch = next()) { | |
if (ch === "}") { | |
if (peek() === "}") | |
ch += next(); | |
token.value += ch; | |
token.close = ch; | |
break; | |
} | |
if (ch === ":") { | |
token.initial = ""; | |
token.key = token.inner; | |
} else if (token.initial !== void 0) { | |
token.initial += ch; | |
} | |
token.value += ch; | |
token.inner += ch; | |
} | |
token.template = token.open + (token.initial || token.inner) + token.close; | |
token.key = token.key || token.inner; | |
if (defaults.hasOwnProperty(token.key)) { | |
token.initial = defaults[token.key]; | |
} | |
token = fn2(token); | |
push(token); | |
keys2.push(token.key); | |
unique2.add(token.key); | |
let item = items.find((item2) => item2.name === token.key); | |
token.field = fields.find((ch2) => ch2.name === token.key); | |
if (!item) { | |
item = new Item$1(token); | |
items.push(item); | |
} | |
item.lines.push(token.line - 1); | |
continue; | |
} | |
let last = tabstops[tabstops.length - 1]; | |
if (last.type === "text" && last.line === line) { | |
last.value += value; | |
} else { | |
push({type: "text", value}); | |
} | |
} | |
push({type: "eos", value: ""}); | |
return {input: input2, tabstops, unique: unique2, keys: keys2, items}; | |
}; | |
var interpolate = async (prompt2) => { | |
let options = prompt2.options; | |
let required = new Set(options.required === true ? [] : options.required || []); | |
let defaults = {...options.values, ...options.initial}; | |
let {tabstops, items, keys: keys2} = await tokenize(options, defaults); | |
let result = createFn("result", prompt2); | |
let format = createFn("format", prompt2); | |
let isValid = createFn("validate", prompt2, options, true); | |
let isVal = prompt2.isValue.bind(prompt2); | |
return async (state2 = {}, submitted = false) => { | |
let index = 0; | |
state2.required = required; | |
state2.items = items; | |
state2.keys = keys2; | |
state2.output = ""; | |
let validate = async (value, state3, item, index2) => { | |
let error = await isValid(value, state3, item, index2); | |
if (error === false) { | |
return "Invalid field " + item.name; | |
} | |
return error; | |
}; | |
for (let token of tabstops) { | |
let value = token.value; | |
let key = token.key; | |
if (token.type !== "template") { | |
if (value) | |
state2.output += value; | |
continue; | |
} | |
if (token.type === "template") { | |
let item = items.find((ch) => ch.name === key); | |
if (options.required === true) { | |
state2.required.add(item.name); | |
} | |
let val = [item.input, state2.values[item.value], item.value, value].find(isVal); | |
let field = item.field || {}; | |
let message = field.message || token.inner; | |
if (submitted) { | |
let error = await validate(state2.values[key], state2, item, index); | |
if (error && typeof error === "string" || error === false) { | |
state2.invalid.set(key, error); | |
continue; | |
} | |
state2.invalid.delete(key); | |
let res = await result(state2.values[key], state2, item, index); | |
state2.output += colors.unstyle(res); | |
continue; | |
} | |
item.placeholder = false; | |
let before = value; | |
value = await format(value, state2, item, index); | |
if (val !== value) { | |
state2.values[key] = val; | |
value = prompt2.styles.typing(val); | |
state2.missing.delete(message); | |
} else { | |
state2.values[key] = void 0; | |
val = `<${message}>`; | |
value = prompt2.styles.primary(val); | |
item.placeholder = true; | |
if (state2.required.has(key)) { | |
state2.missing.add(message); | |
} | |
} | |
if (state2.missing.has(message) && state2.validating) { | |
value = prompt2.styles.warning(val); | |
} | |
if (state2.invalid.has(key) && state2.validating) { | |
value = prompt2.styles.danger(val); | |
} | |
if (index === state2.index) { | |
if (before !== value) { | |
value = prompt2.styles.underline(value); | |
} else { | |
value = prompt2.styles.heading(colors.unstyle(value)); | |
} | |
} | |
index++; | |
} | |
if (value) { | |
state2.output += value; | |
} | |
} | |
let lines = state2.output.split("\n").map((l) => " " + l); | |
let len = items.length; | |
let done = 0; | |
for (let item of items) { | |
if (state2.invalid.has(item.name)) { | |
item.lines.forEach((i) => { | |
if (lines[i][0] !== " ") | |
return; | |
lines[i] = state2.styles.danger(state2.symbols.bullet) + lines[i].slice(1); | |
}); | |
} | |
if (prompt2.isValue(state2.values[item.name])) { | |
done++; | |
} | |
} | |
state2.completed = (done / len * 100).toFixed(0); | |
state2.output = lines.join("\n"); | |
return state2.output; | |
}; | |
}; | |
function createFn(prop, prompt2, options, fallback) { | |
return (value, state2, item, index) => { | |
if (typeof item.field[prop] === "function") { | |
return item.field[prop].call(prompt2, value, state2, item, index); | |
} | |
return [fallback, value].find((v) => prompt2.isValue(v)); | |
}; | |
} | |
class SnippetPrompt extends prompt { | |
constructor(options) { | |
super(options); | |
this.cursorHide(); | |
this.reset(true); | |
} | |
async initialize() { | |
this.interpolate = await interpolate(this); | |
await super.initialize(); | |
} | |
async reset(first) { | |
this.state.keys = []; | |
this.state.invalid = new Map(); | |
this.state.missing = new Set(); | |
this.state.completed = 0; | |
this.state.values = {}; | |
if (first !== true) { | |
await this.initialize(); | |
await this.render(); | |
} | |
} | |
moveCursor(n) { | |
let item = this.getItem(); | |
this.cursor += n; | |
item.cursor += n; | |
} | |
dispatch(ch, key) { | |
if (!key.code && !key.ctrl && ch != null && this.getItem()) { | |
this.append(ch, key); | |
return; | |
} | |
this.alert(); | |
} | |
append(ch, key) { | |
let item = this.getItem(); | |
let prefix = item.input.slice(0, this.cursor); | |
let suffix = item.input.slice(this.cursor); | |
this.input = item.input = `${prefix}${ch}${suffix}`; | |
this.moveCursor(1); | |
this.render(); | |
} | |
delete() { | |
let item = this.getItem(); | |
if (this.cursor <= 0 || !item.input) | |
return this.alert(); | |
let suffix = item.input.slice(this.cursor); | |
let prefix = item.input.slice(0, this.cursor - 1); | |
this.input = item.input = `${prefix}${suffix}`; | |
this.moveCursor(-1); | |
this.render(); | |
} | |
increment(i) { | |
return i >= this.state.keys.length - 1 ? 0 : i + 1; | |
} | |
decrement(i) { | |
return i <= 0 ? this.state.keys.length - 1 : i - 1; | |
} | |
first() { | |
this.state.index = 0; | |
this.render(); | |
} | |
last() { | |
this.state.index = this.state.keys.length - 1; | |
this.render(); | |
} | |
right() { | |
if (this.cursor >= this.input.length) | |
return this.alert(); | |
this.moveCursor(1); | |
this.render(); | |
} | |
left() { | |
if (this.cursor <= 0) | |
return this.alert(); | |
this.moveCursor(-1); | |
this.render(); | |
} | |
prev() { | |
this.state.index = this.decrement(this.state.index); | |
this.getItem(); | |
this.render(); | |
} | |
next() { | |
this.state.index = this.increment(this.state.index); | |
this.getItem(); | |
this.render(); | |
} | |
up() { | |
this.prev(); | |
} | |
down() { | |
this.next(); | |
} | |
format(value) { | |
let color = this.state.completed < 100 ? this.styles.warning : this.styles.success; | |
if (this.state.submitted === true && this.state.completed !== 100) { | |
color = this.styles.danger; | |
} | |
return color(`${this.state.completed}% completed`); | |
} | |
async render() { | |
let {index, keys: keys2 = [], submitted, size} = this.state; | |
let newline = [this.options.newline, "\n"].find((v) => v != null); | |
let prefix = await this.prefix(); | |
let separator = await this.separator(); | |
let message = await this.message(); | |
let prompt2 = [prefix, message, separator].filter(Boolean).join(" "); | |
this.state.prompt = prompt2; | |
let header = await this.header(); | |
let error = await this.error() || ""; | |
let hint2 = await this.hint() || ""; | |
let body = submitted ? "" : await this.interpolate(this.state); | |
let key = this.state.key = keys2[index] || ""; | |
let input2 = await this.format(key); | |
let footer = await this.footer(); | |
if (input2) | |
prompt2 += " " + input2; | |
if (hint2 && !input2 && this.state.completed === 0) | |
prompt2 += " " + hint2; | |
this.clear(size); | |
let lines = [header, prompt2, body, footer, error.trim()]; | |
this.write(lines.filter(Boolean).join(newline)); | |
this.restore(); | |
} | |
getItem(name) { | |
let {items, keys: keys2, index} = this.state; | |
let item = items.find((ch) => ch.name === keys2[index]); | |
if (item && item.input != null) { | |
this.input = item.input; | |
this.cursor = item.cursor; | |
} | |
return item; | |
} | |
async submit() { | |
if (typeof this.interpolate !== "function") | |
await this.initialize(); | |
await this.interpolate(this.state, true); | |
let {invalid, missing, output, values} = this.state; | |
if (invalid.size) { | |
let err = ""; | |
for (let [key, value] of invalid) | |
err += `Invalid ${key}: ${value} | |
`; | |
this.state.error = err; | |
return super.submit(); | |
} | |
if (missing.size) { | |
this.state.error = "Required: " + [...missing.keys()].join(", "); | |
return super.submit(); | |
} | |
let lines = colors.unstyle(output).split("\n"); | |
let result = lines.map((v) => v.slice(1)).join("\n"); | |
this.value = {values, result}; | |
return super.submit(); | |
} | |
} | |
var snippet = SnippetPrompt; | |
const hint = "(Use <shift>+<up/down> to sort)"; | |
class Sort extends select { | |
constructor(options) { | |
super({...options, reorder: false, sort: true, multiple: true}); | |
this.state.hint = [this.options.hint, hint].find(this.isValue.bind(this)); | |
} | |
indicator() { | |
return ""; | |
} | |
async renderChoice(choice, i) { | |
let str = await super.renderChoice(choice, i); | |
let sym = this.symbols.identicalTo + " "; | |
let pre = this.index === i && this.sorting ? this.styles.muted(sym) : " "; | |
if (this.options.drag === false) | |
pre = ""; | |
if (this.options.numbered === true) { | |
return pre + `${i + 1} - ` + str; | |
} | |
return pre + str; | |
} | |
get selected() { | |
return this.choices; | |
} | |
submit() { | |
this.value = this.choices.map((choice) => choice.value); | |
return super.submit(); | |
} | |
} | |
var sort = Sort; | |
class Survey extends array { | |
constructor(options = {}) { | |
super(options); | |
this.emptyError = options.emptyError || "No items were selected"; | |
this.term = process.env.TERM_PROGRAM; | |
if (!this.options.header) { | |
let header = ["", "4 - Strongly Agree", "3 - Agree", "2 - Neutral", "1 - Disagree", "0 - Strongly Disagree", ""]; | |
header = header.map((ele) => this.styles.muted(ele)); | |
this.state.header = header.join("\n "); | |
} | |
} | |
async toChoices(...args) { | |
if (this.createdScales) | |
return false; | |
this.createdScales = true; | |
let choices = await super.toChoices(...args); | |
for (let choice of choices) { | |
choice.scale = createScale(5, this.options); | |
choice.scaleIdx = 2; | |
} | |
return choices; | |
} | |
dispatch() { | |
this.alert(); | |
} | |
space() { | |
let choice = this.focused; | |
let ele = choice.scale[choice.scaleIdx]; | |
let selected = ele.selected; | |
choice.scale.forEach((e) => e.selected = false); | |
ele.selected = !selected; | |
return this.render(); | |
} | |
indicator() { | |
return ""; | |
} | |
pointer() { | |
return ""; | |
} | |
separator() { | |
return this.styles.muted(this.symbols.ellipsis); | |
} | |
right() { | |
let choice = this.focused; | |
if (choice.scaleIdx >= choice.scale.length - 1) | |
return this.alert(); | |
choice.scaleIdx++; | |
return this.render(); | |
} | |
left() { | |
let choice = this.focused; | |
if (choice.scaleIdx <= 0) | |
return this.alert(); | |
choice.scaleIdx--; | |
return this.render(); | |
} | |
indent() { | |
return " "; | |
} | |
async renderChoice(item, i) { | |
await this.onChoice(item, i); | |
let focused = this.index === i; | |
let isHyper = this.term === "Hyper"; | |
let n = !isHyper ? 8 : 9; | |
let s = !isHyper ? " " : ""; | |
let ln = this.symbols.line.repeat(n); | |
let sp = " ".repeat(n + (isHyper ? 0 : 1)); | |
let dot = (enabled) => (enabled ? this.styles.success("\u25C9") : "\u25EF") + s; | |
let num = i + 1 + "."; | |
let color = focused ? this.styles.heading : this.styles.noop; | |
let msg = await this.resolve(item.message, this.state, item, i); | |
let indent = this.indent(item); | |
let scale2 = indent + item.scale.map((e, i2) => dot(i2 === item.scaleIdx)).join(ln); | |
let val = (i2) => i2 === item.scaleIdx ? color(i2) : i2; | |
let next = indent + item.scale.map((e, i2) => val(i2)).join(sp); | |
let line = () => [num, msg].filter(Boolean).join(" "); | |
let lines = () => [line(), scale2, next, " "].filter(Boolean).join("\n"); | |
if (focused) { | |
scale2 = this.styles.cyan(scale2); | |
next = this.styles.cyan(next); | |
} | |
return lines(); | |
} | |
async renderChoices() { | |
if (this.state.submitted) | |
return ""; | |
let choices = this.visible.map(async (ch, i) => await this.renderChoice(ch, i)); | |
let visible = await Promise.all(choices); | |
if (!visible.length) | |
visible.push(this.styles.danger("No matching choices")); | |
return visible.join("\n"); | |
} | |
format() { | |
if (this.state.submitted) { | |
let values = this.choices.map((ch) => this.styles.info(ch.scaleIdx)); | |
return values.join(", "); | |
} | |
return ""; | |
} | |
async render() { | |
let {submitted, size} = this.state; | |
let prefix = await this.prefix(); | |
let separator = await this.separator(); | |
let message = await this.message(); | |
let prompt2 = [prefix, message, separator].filter(Boolean).join(" "); | |
this.state.prompt = prompt2; | |
let header = await this.header(); | |
let output = await this.format(); | |
let help = await this.error() || await this.hint(); | |
let body = await this.renderChoices(); | |
let footer = await this.footer(); | |
if (output || !help) | |
prompt2 += " " + output; | |
if (help && !prompt2.includes(help)) | |
prompt2 += " " + help; | |
if (submitted && !output && !body && this.multiple && this.type !== "form") { | |
prompt2 += this.styles.danger(this.emptyError); | |
} | |
this.clear(size); | |
this.write([prompt2, header, body, footer].filter(Boolean).join("\n")); | |
this.restore(); | |
} | |
submit() { | |
this.value = {}; | |
for (let choice of this.choices) { | |
this.value[choice.name] = choice.scaleIdx; | |
} | |
return this.base.submit.call(this); | |
} | |
} | |
function createScale(n, options = {}) { | |
if (Array.isArray(options.scale)) { | |
return options.scale.map((ele) => ({...ele})); | |
} | |
let scale2 = []; | |
for (let i = 1; i < n + 1; i++) | |
scale2.push({i, selected: false}); | |
return scale2; | |
} | |
var survey = Survey; | |
var text = input; | |
class TogglePrompt extends boolean_1 { | |
async initialize() { | |
await super.initialize(); | |
this.value = this.initial = !!this.options.initial; | |
this.disabled = this.options.disabled || "no"; | |
this.enabled = this.options.enabled || "yes"; | |
await this.render(); | |
} | |
reset() { | |
this.value = this.initial; | |
this.render(); | |
} | |
delete() { | |
this.alert(); | |
} | |
toggle() { | |
this.value = !this.value; | |
this.render(); | |
} | |
enable() { | |
if (this.value === true) | |
return this.alert(); | |
this.value = true; | |
this.render(); | |
} | |
disable() { | |
if (this.value === false) | |
return this.alert(); | |
this.value = false; | |
this.render(); | |
} | |
up() { | |
this.toggle(); | |
} | |
down() { | |
this.toggle(); | |
} | |
right() { | |
this.toggle(); | |
} | |
left() { | |
this.toggle(); | |
} | |
next() { | |
this.toggle(); | |
} | |
prev() { | |
this.toggle(); | |
} | |
dispatch(ch = "", key) { | |
switch (ch.toLowerCase()) { | |
case " ": | |
return this.toggle(); | |
case "1": | |
case "y": | |
case "t": | |
return this.enable(); | |
case "0": | |
case "n": | |
case "f": | |
return this.disable(); | |
default: { | |
return this.alert(); | |
} | |
} | |
} | |
format() { | |
let active = (str) => this.styles.primary.underline(str); | |
let value = [ | |
this.value ? this.disabled : active(this.disabled), | |
this.value ? active(this.enabled) : this.enabled | |
]; | |
return value.join(this.styles.muted(" / ")); | |
} | |
async render() { | |
let {size} = this.state; | |
let header = await this.header(); | |
let prefix = await this.prefix(); | |
let separator = await this.separator(); | |
let message = await this.message(); | |
let output = await this.format(); | |
let help = await this.error() || await this.hint(); | |
let footer = await this.footer(); | |
let prompt2 = [prefix, message, separator, output].join(" "); | |
this.state.prompt = prompt2; | |
if (help && !prompt2.includes(help)) | |
prompt2 += " " + help; | |
this.clear(size); | |
this.write([header, prompt2, footer].filter(Boolean).join("\n")); | |
this.write(this.margin[2]); | |
this.restore(); | |
} | |
} | |
var toggle = TogglePrompt; | |
class Quiz extends select { | |
constructor(options) { | |
super(options); | |
if (typeof this.options.correctChoice !== "number" || this.options.correctChoice < 0) { | |
throw new Error("Please specify the index of the correct answer from the list of choices"); | |
} | |
} | |
async toChoices(value, parent) { | |
let choices = await super.toChoices(value, parent); | |
if (choices.length < 2) { | |
throw new Error("Please give at least two choices to the user"); | |
} | |
if (this.options.correctChoice > choices.length) { | |
throw new Error("Please specify the index of the correct answer from the list of choices"); | |
} | |
return choices; | |
} | |
check(state2) { | |
return state2.index === this.options.correctChoice; | |
} | |
async result(selected) { | |
return { | |
selectedAnswer: selected, | |
correctAnswer: this.options.choices[this.options.correctChoice].value, | |
correct: await this.check(this.state) | |
}; | |
} | |
} | |
var quiz = Quiz; | |
var prompts = createCommonjsModule(function(module, exports) { | |
const define2 = (key, fn2) => { | |
utils.defineExport(exports, key, fn2); | |
utils.defineExport(exports, key.toLowerCase(), fn2); | |
}; | |
define2("AutoComplete", () => autocomplete); | |
define2("BasicAuth", () => basicauth); | |
define2("Confirm", () => confirm); | |
define2("Editable", () => editable); | |
define2("Form", () => form); | |
define2("Input", () => input); | |
define2("Invisible", () => invisible); | |
define2("List", () => list); | |
define2("MultiSelect", () => multiselect); | |
define2("Numeral", () => numeral); | |
define2("Password", () => password); | |
define2("Scale", () => scale); | |
define2("Select", () => select); | |
define2("Snippet", () => snippet); | |
define2("Sort", () => sort); | |
define2("Survey", () => survey); | |
define2("Text", () => text); | |
define2("Toggle", () => toggle); | |
define2("Quiz", () => quiz); | |
}); | |
var types = { | |
ArrayPrompt: array, | |
AuthPrompt: auth, | |
BooleanPrompt: boolean_1, | |
NumberPrompt: number, | |
StringPrompt: string | |
}; | |
class Enquirer extends events { | |
constructor(options, answers) { | |
super(); | |
this.options = {...options}; | |
this.answers = {...answers}; | |
} | |
register(type, fn2) { | |
if (utils.isObject(type)) { | |
for (let key of Object.keys(type)) | |
this.register(key, type[key]); | |
return this; | |
} | |
assert$1.equal(typeof fn2, "function", "expected a function"); | |
let name = type.toLowerCase(); | |
if (fn2.prototype instanceof this.Prompt) { | |
this.prompts[name] = fn2; | |
} else { | |
this.prompts[name] = fn2(this.Prompt, this); | |
} | |
return this; | |
} | |
async prompt(questions = []) { | |
for (let question of [].concat(questions)) { | |
try { | |
if (typeof question === "function") | |
question = await question.call(this); | |
await this.ask({...this.options,...question}); | |
} catch (err) { | |
return Promise.reject(err); | |
} | |
} | |
return this.answers; | |
} | |
async ask(question) { | |
if (typeof question === "function") { | |
question = await question.call(this); | |
} | |
let opts = {...this.options, ...question}; | |
let {type, name} = question; | |
let {set, get} = utils; | |
if (typeof type === "function") { | |
type = await type.call(this, question, this.answers); | |
} | |
if (!type) | |
return this.answers[name]; | |
assert$1(this.prompts[type], `Prompt "${type}" is not registered`); | |
let prompt2 = new this.prompts[type](opts); | |
let value = get(this.answers, name); | |
prompt2.state.answers = this.answers; | |
prompt2.enquirer = this; | |
if (name) { | |
prompt2.on("submit", (value2) => { | |
this.emit("answer", name, value2, prompt2); | |
set(this.answers, name, value2); | |
}); | |
} | |
let emit3 = prompt2.emit.bind(prompt2); | |
prompt2.emit = (...args) => { | |
this.emit.call(this, ...args); | |
return emit3(...args); | |
}; | |
this.emit("prompt", prompt2, this); | |
if (opts.autofill && value != null) { | |
prompt2.value = prompt2.input = value; | |
if (opts.autofill === "show") { | |
await prompt2.submit(); | |
} | |
} else { | |
value = prompt2.value = await prompt2.run(); | |
} | |
return value; | |
} | |
use(plugin) { | |
plugin.call(this, this); | |
return this; | |
} | |
set Prompt(value) { | |
this._Prompt = value; | |
} | |
get Prompt() { | |
return this._Prompt || this.constructor.Prompt; | |
} | |
get prompts() { | |
return this.constructor.prompts; | |
} | |
static set Prompt(value) { | |
this._Prompt = value; | |
} | |
static get Prompt() { | |
return this._Prompt || prompt; | |
} | |
static get prompts() { | |
return prompts; | |
} | |
static get types() { | |
return types; | |
} | |
static get prompt() { | |
const fn2 = (questions, ...rest) => { | |
let enquirer2 = new this(...rest); | |
let emit3 = enquirer2.emit.bind(enquirer2); | |
enquirer2.emit = (...args) => { | |
fn2.emit(...args); | |
return emit3(...args); | |
}; | |
return enquirer2.prompt(questions); | |
}; | |
utils.mixinEmitter(fn2, new events()); | |
return fn2; | |
} | |
} | |
utils.mixinEmitter(Enquirer, new events()); | |
const prompts$1 = Enquirer.prompts; | |
for (let name of Object.keys(prompts$1)) { | |
let key = name.toLowerCase(); | |
let run = (options) => new prompts$1[name](options).run(); | |
Enquirer.prompt[key] = run; | |
Enquirer[key] = run; | |
if (!Enquirer[name]) { | |
Reflect.defineProperty(Enquirer, name, {get: () => prompts$1[name]}); | |
} | |
} | |
const exp = (name) => { | |
utils.defineExport(Enquirer, name, () => Enquirer.types[name]); | |
}; | |
exp("ArrayPrompt"); | |
exp("AuthPrompt"); | |
exp("BooleanPrompt"); | |
exp("NumberPrompt"); | |
exp("StringPrompt"); | |
var enquirer = Enquirer; | |
export default enquirer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var _a, _b; | |
import getStringWidth from "https://cdn.skypack.dev/string-width"; | |
import { StringDecoder } from "https://cdn.skypack.dev/string_decoder"; | |
const { default: { EventEmitter2 } } = await import("https://cdn.skypack.dev/eventemitter2"); | |
import { charLengthAt, charLengthLeft, commonPrefix, kSubstringSearch, stripVTControlCharacters, clearLine, clearScreenDown, cursorTo, moveCursor } from './utils.js'; | |
const kHistorySize = 30; | |
const kMincrlfDelay = 100; | |
// \r\n, \n, or \r followed by something other than \n | |
const lineEnding = /\r?\n|\r(?!\n)/; | |
const kLineObjectStream = Symbol('line object stream'); | |
const kQuestionCancel = Symbol('kQuestionCancel'); | |
// GNU readline library - keyseq-timeout is 500ms (default) | |
const ESCAPE_CODE_TIMEOUT = 500; | |
/** | |
* Creates a new `readline.Interface` instance. | |
* @param {Readable | { | |
* input: Readable; | |
* output: Writable; | |
* completer?: Function; | |
* terminal?: boolean; | |
* history?: string[]; | |
* historySize?: number; | |
* removeHistoryDuplicates?: boolean; | |
* prompt?: string; | |
* crlfDelay?: number; | |
* escapeCodeTimeout?: number; | |
* tabSize?: number; | |
* signal?: AbortSignal; | |
* }} input | |
* @param {Writable} [output] | |
* @param {Function} [completer] | |
* @param {boolean} [terminal] | |
* @returns {Interface} | |
*/ | |
function emitKeypressEvents(stream, aninterface) { | |
console.log("emitKeypressEvents", stream, aninterface); | |
} | |
function createInterface(input, output, completer, terminal) { | |
return new Interface(input, output, completer, terminal); | |
} | |
class Interface extends EventEmitter2 { | |
constructor(input, output, completer, terminal) { | |
super(); | |
this.input = input; | |
this.output = output; | |
this.completer = completer; | |
this._sawReturnAt = 0; | |
// TODO(BridgeAR): Document this property. The name is not ideal, so we might | |
// want to expose an alias and document that instead. | |
this.isCompletionEnabled = true; | |
this._sawKeyPress = false; | |
this.escapeCodeTimeout = ESCAPE_CODE_TIMEOUT; | |
this.tabSize = 8; | |
this.closed = false; | |
this.paused = false; | |
this.terminal = false; | |
this.history = []; | |
this.historySize = kHistorySize; | |
this.removeHistoryDuplicates = false; | |
this.crlfDelay = kMincrlfDelay; | |
this._oldPrompt = ''; | |
this._prompt = '> '; | |
this.cursor = 0; | |
this.historyIndex = 0; | |
this.line = ''; | |
this._line_buffer = ''; | |
this[_a] = this._questionCancel.bind(this); | |
this[_b] = undefined; | |
let history; | |
let historySize; | |
let removeHistoryDuplicates = false; | |
let crlfDelay; | |
let prompt = '> '; | |
let signal; | |
if (input && input.input) { | |
// An options object was given | |
output = input.output; | |
completer = input.completer; | |
terminal = input.terminal; | |
history = input.history; | |
historySize = input.historySize; | |
signal = input.signal; | |
if (input.tabSize !== undefined) { | |
this.tabSize = input.tabSize; | |
} | |
removeHistoryDuplicates = input.removeHistoryDuplicates; | |
if (input.prompt !== undefined) { | |
prompt = input.prompt; | |
} | |
if (input.escapeCodeTimeout !== undefined) { | |
if (Number.isFinite(input.escapeCodeTimeout)) { | |
this.escapeCodeTimeout = input.escapeCodeTimeout; | |
} | |
else { | |
throw new Error('input.escapeCodeTimeout'); | |
} | |
} | |
crlfDelay = input.crlfDelay; | |
input = input.input; | |
} | |
if (completer !== undefined && typeof completer !== 'function') { | |
throw new Error('completer'); | |
} | |
if (history === undefined) { | |
history = []; | |
} | |
else { | |
} | |
if (historySize === undefined) { | |
historySize = kHistorySize; | |
} | |
// Backwards compat; check the isTTY prop of the output stream | |
// when `terminal` was not specified | |
if (terminal === undefined && !(output === null || output === undefined)) { | |
terminal = !!output.isTTY; | |
} | |
this.line = ''; | |
this[kSubstringSearch] = null; | |
this.output = output; | |
this.input = input; | |
this.history = history; | |
this.historySize = historySize; | |
this.removeHistoryDuplicates = !!removeHistoryDuplicates; | |
this.crlfDelay = crlfDelay ? | |
Math.max(kMincrlfDelay, crlfDelay) : kMincrlfDelay; | |
// Check arity, 2 - for async, 1 for sync | |
if (typeof completer === 'function') { | |
this.completer = completer.length === 2 ? | |
completer : | |
function completerWrapper(v, cb) { | |
cb(null, completer(v)); | |
}; | |
} | |
this[kQuestionCancel] = this._questionCancel.bind(this); | |
this.setPrompt(prompt); | |
this.terminal = !!terminal; | |
this.input.on('error', this.onerror.bind(this)); | |
if (!this.terminal) { | |
const onSelfCloseWithoutTerminal = () => { | |
input.removeListener('data', this.ondata.bind(this)); | |
input.removeListener('error', this.onerror.bind(this)); | |
input.removeListener('end', this.onend.bind(this)); | |
}; | |
input.on('data', this.ondata.bind(this)); | |
input.on('end', this.onend.bind(this)); | |
this.once('close', onSelfCloseWithoutTerminal); | |
this._decoder = new StringDecoder('utf8'); | |
} | |
else { | |
const onSelfCloseWithTerminal = () => { | |
input.removeListener('keypress', this.onkeypress.bind(this)); | |
input.removeListener('error', this.onerror.bind(this)); | |
input.removeListener('end', this.ontermend.bind(this)); | |
if (output !== null && output !== undefined) { | |
output.removeListener('resize', this.onresize.bind(this)); | |
} | |
}; | |
// `input` usually refers to stdin | |
input.on('keypress', this.onkeypress.bind(this)); | |
input.on('end', this.ontermend.bind(this)); | |
this._setRawMode(true); | |
this.terminal = true; | |
// Cursor position on the line. | |
this.cursor = 0; | |
this.historyIndex = -1; | |
if (output !== null && output !== undefined) | |
output.on('resize', this.onresize.bind(this)); | |
this.once('close', onSelfCloseWithTerminal); | |
} | |
// Current line | |
this.line = ''; | |
input.resume(); | |
} | |
get columns() { | |
return this.output.columns; | |
} | |
onerror(err) { | |
this.emit('error', err); | |
} | |
ondata(data) { | |
this._normalWrite(data); | |
} | |
onend() { | |
if (typeof this._line_buffer === 'string' && | |
this._line_buffer.length > 0) { | |
this.emit('line', this._line_buffer); | |
} | |
this.close(); | |
} | |
ontermend() { | |
if (typeof this.line === 'string' && this.line.length > 0) { | |
this.emit('line', this.line); | |
} | |
this.close(); | |
} | |
onkeypress(s, key) { | |
this._ttyWrite(s, key); | |
if (key && key.sequence) { | |
// If the key.sequence is half of a surrogate pair | |
// (>= 0xd800 and <= 0xdfff), refresh the line so | |
// the character is displayed appropriately. | |
const ch = key.sequence.codePointAt(0); | |
if (ch >= 0xd800 && ch <= 0xdfff) | |
this._refreshLine(); | |
} | |
} | |
onresize() { | |
this._refreshLine(); | |
} | |
/** | |
* Sets the prompt written to the output. | |
* @param {string} prompt | |
* @returns {void} | |
*/ | |
setPrompt(prompt) { | |
this._prompt = prompt; | |
} | |
; | |
/** | |
* Returns the current prompt used by `rl.prompt()`. | |
* @returns {string} | |
*/ | |
getPrompt() { | |
return this._prompt; | |
} | |
; | |
_setRawMode(mode) { | |
const wasInRawMode = this.input.isRaw; | |
if (typeof this.input.setRawMode === 'function') { | |
this.input.setRawMode(mode); | |
} | |
return wasInRawMode; | |
} | |
; | |
/** | |
* Writes the configured `prompt` to a new line in `output`. | |
* @param {boolean} [preserveCursor] | |
* @returns {void} | |
*/ | |
prompt(preserveCursor) { | |
if (this.paused) | |
this.resume(); | |
if (this.terminal) { | |
if (!preserveCursor) | |
this.cursor = 0; | |
this._refreshLine(); | |
} | |
else { | |
this._writeToOutput(this._prompt); | |
} | |
} | |
; | |
/** | |
* Displays `query` by writing it to the `output`. | |
* @param {string} query | |
* @param {{ signal?: AbortSignal; }} [options] | |
* @param {Function} cb | |
* @returns {void} | |
*/ | |
question(query, options, cb) { | |
cb = typeof options === 'function' ? options : cb; | |
options = typeof options === 'object' && options !== null ? options : {}; | |
if (options.signal) { | |
if (options.signal.aborted) { | |
return; | |
} | |
options.signal.addEventListener('abort', () => { | |
this[kQuestionCancel](); | |
}, { once: true }); | |
} | |
if (typeof cb === 'function') { | |
if (this._questionCallback) { | |
this.prompt(); | |
} | |
else { | |
this._oldPrompt = this._prompt; | |
this.setPrompt(query); | |
this._questionCallback = cb; | |
this.prompt(); | |
} | |
} | |
} | |
; | |
_questionCancel() { | |
if (this._questionCallback) { | |
this._questionCallback = null; | |
this.setPrompt(this._oldPrompt); | |
this.clearLine(); | |
} | |
} | |
_onLine(line) { | |
if (this._questionCallback) { | |
const cb = this._questionCallback; | |
this._questionCallback = null; | |
this.setPrompt(this._oldPrompt); | |
cb(line); | |
} | |
else { | |
this.emit('line', line); | |
} | |
} | |
; | |
_writeToOutput(stringToWrite) { | |
if (this.output !== null && this.output !== undefined) { | |
this.output.write(stringToWrite); | |
} | |
} | |
; | |
_addHistory() { | |
if (this.line.length === 0) | |
return ''; | |
// If the history is disabled then return the line | |
if (this.historySize === 0) | |
return this.line; | |
// If the trimmed line is empty then return the line | |
if (this.line.trim().length === 0) | |
return this.line; | |
if (this.history.length === 0 || this.history[0] !== this.line) { | |
if (this.removeHistoryDuplicates) { | |
// Remove older history line if identical to new one | |
const dupIndex = this.history.indexOf(this.line); | |
if (dupIndex !== -1) | |
this.history.splice(dupIndex, 1); | |
} | |
this.history.unshift(this.line); | |
// Only store so many | |
if (this.history.length > this.historySize) | |
this.history.pop(); | |
} | |
this.historyIndex = -1; | |
// The listener could change the history object, possibly | |
// to remove the last added entry if it is sensitive and should | |
// not be persisted in the history, like a password | |
const line = this.history[0]; | |
// Emit history event to notify listeners of update | |
this.emit('history', this.history); | |
return line; | |
} | |
; | |
_refreshLine() { | |
// line length | |
const line = this._prompt + this.line; | |
const dispPos = this._getDisplayPos(line); | |
const lineCols = dispPos.cols; | |
const lineRows = dispPos.rows; | |
// cursor position | |
const cursorPos = this.getCursorPos(); | |
// First move to the bottom of the current line, based on cursor pos | |
const prevRows = this.prevRows || 0; | |
if (prevRows > 0) { | |
moveCursor(this.output, 0, -prevRows); | |
} | |
// Cursor to left edge. | |
cursorTo(this.output, 0); | |
// erase data | |
clearScreenDown(this.output); | |
// Write the prompt and the current buffer content. | |
this._writeToOutput(line); | |
// Force terminal to allocate a new line | |
if (lineCols === 0) { | |
this._writeToOutput(' '); | |
} | |
// Move cursor to original position. | |
cursorTo(this.output, cursorPos.cols); | |
const diff = lineRows - cursorPos.rows; | |
if (diff > 0) { | |
moveCursor(this.output, 0, -diff); | |
} | |
this.prevRows = cursorPos.rows; | |
} | |
; | |
/** | |
* Closes the `readline.Interface` instance. | |
* @returns {void} | |
*/ | |
close() { | |
if (this.closed) | |
return; | |
this.pause(); | |
if (this.terminal) { | |
this._setRawMode(false); | |
} | |
this.closed = true; | |
this.emit('close'); | |
} | |
; | |
/** | |
* Pauses the `input` stream. | |
* @returns {void | Interface} | |
*/ | |
pause() { | |
if (this.paused) | |
return; | |
this.input.pause(); | |
this.paused = true; | |
this.emit('pause'); | |
return this; | |
} | |
; | |
/** | |
* Resumes the `input` stream if paused. | |
* @returns {void | Interface} | |
*/ | |
resume() { | |
if (!this.paused) | |
return; | |
this.input.resume(); | |
this.paused = false; | |
this.emit('resume'); | |
return this; | |
} | |
; | |
/** | |
* Writes either `data` or a `key` sequence identified by | |
* `key` to the `output`. | |
* @param {string} d | |
* @param {{ | |
* ctrl?: boolean; | |
* meta?: boolean; | |
* shift?: boolean; | |
* name?: string; | |
* }} [key] | |
* @returns {void} | |
*/ | |
write(d, key) { | |
if (this.paused) | |
this.resume(); | |
if (this.terminal) { | |
this._ttyWrite(d, key); | |
} | |
else { | |
this._normalWrite(d); | |
} | |
} | |
; | |
_normalWrite(b) { | |
if (b === undefined) { | |
return; | |
} | |
let string = this._decoder.write(b); | |
if (this._sawReturnAt && | |
Date.now() - this._sawReturnAt <= this.crlfDelay) { | |
string = string.replace(/^\n/, ''); | |
this._sawReturnAt = 0; | |
} | |
// Run test() on the new string chunk, not on the entire line buffer. | |
const newPartContainsEnding = new RegExp(lineEnding).test(string); | |
if (this._line_buffer) { | |
string = this._line_buffer + string; | |
this._line_buffer = null; | |
} | |
if (newPartContainsEnding) { | |
this._sawReturnAt = string.endsWith('\r') ? Date.now() : 0; | |
// Got one or more newlines; process into "line" events | |
const lines = string.split(lineEnding); | |
// Either '' or (conceivably) the unfinished portion of the next line | |
string = lines.pop(); | |
this._line_buffer = string; | |
for (let n = 0; n < lines.length; n++) | |
this._onLine(lines[n]); | |
} | |
else if (string) { | |
// No newlines this time, save what we have for next time | |
this._line_buffer = string; | |
} | |
} | |
; | |
_insertString(c) { | |
if (this.cursor < this.line.length) { | |
const beg = this.line.slice(0, this.cursor); | |
const end = this.line.slice(this.cursor, this.line.length); | |
this.line = beg + c + end; | |
this.cursor += c.length; | |
this._refreshLine(); | |
} | |
else { | |
this.line += c; | |
this.cursor += c.length; | |
if (this.getCursorPos().cols === 0) { | |
this._refreshLine(); | |
} | |
else { | |
this._writeToOutput(c); | |
} | |
} | |
} | |
; | |
_tabComplete(lastKeypressWasTab) { | |
this.pause(); | |
const string = this.line.slice(0, this.cursor); | |
this.completer(string, (err, value) => { | |
this.resume(); | |
if (err) { | |
this._writeToOutput(`Tab completion error: ${err.stack}`); | |
return; | |
} | |
// Result and the text that was completed. | |
const { 0: completions, 1: completeOn } = value; | |
if (!completions || completions.length === 0) { | |
return; | |
} | |
// If there is a common prefix to all matches, then apply that portion. | |
const prefix = commonPrefix(completions.filter((e) => e !== '')); | |
if (prefix.length > completeOn.length) { | |
this._insertString(prefix.slice(completeOn.length)); | |
return; | |
} | |
if (!lastKeypressWasTab) { | |
return; | |
} | |
// Apply/show completions. | |
const completionsWidth = completions.map((e) => getStringWidth(e)); | |
const width = Math.max(...completionsWidth) + 2; // 2 space padding | |
let maxColumns = Math.floor(this.columns / width) || 1; | |
if (maxColumns === Infinity) { | |
maxColumns = 1; | |
} | |
let output = '\r\n'; | |
let lineIndex = 0; | |
let whitespace = 0; | |
for (let i = 0; i < completions.length; i++) { | |
const completion = completions[i]; | |
if (completion === '' || lineIndex === maxColumns) { | |
output += '\r\n'; | |
lineIndex = 0; | |
whitespace = 0; | |
} | |
else { | |
output += ' '.repeat(whitespace); | |
} | |
if (completion !== '') { | |
output += completion; | |
whitespace = width - completionsWidth[i]; | |
lineIndex++; | |
} | |
else { | |
output += '\r\n'; | |
} | |
} | |
if (lineIndex !== 0) { | |
output += '\r\n\r\n'; | |
} | |
this._writeToOutput(output); | |
this._refreshLine(); | |
}); | |
} | |
; | |
_wordLeft() { | |
if (this.cursor > 0) { | |
// Reverse the string and match a word near beginning | |
// to avoid quadratic time complexity | |
const leading = this.line.slice(0, this.cursor); | |
const reversed = Array.from(leading).reverse().join(''); | |
const match = reversed.match(/^\s*(?:[^\w\s]+|\w+)?/); | |
this._moveCursor(-match[0].length); | |
} | |
} | |
; | |
_wordRight() { | |
if (this.cursor < this.line.length) { | |
const trailing = this.line.slice(this.cursor); | |
const match = trailing.match(/^(?:\s+|[^\w\s]+|\w+)\s*/); | |
this._moveCursor(match[0].length); | |
} | |
} | |
; | |
_deleteLeft() { | |
if (this.cursor > 0 && this.line.length > 0) { | |
// The number of UTF-16 units comprising the character to the left | |
const charSize = charLengthLeft(this.line, this.cursor); | |
this.line = this.line.slice(0, this.cursor - charSize) + | |
this.line.slice(this.cursor, this.line.length); | |
this.cursor -= charSize; | |
this._refreshLine(); | |
} | |
} | |
; | |
_deleteRight() { | |
if (this.cursor < this.line.length) { | |
// The number of UTF-16 units comprising the character to the left | |
const charSize = charLengthAt(this.line, this.cursor); | |
this.line = this.line.slice(0, this.cursor) + | |
this.line.slice(this.cursor + charSize, this.line.length); | |
this._refreshLine(); | |
} | |
} | |
; | |
_deleteWordLeft() { | |
if (this.cursor > 0) { | |
// Reverse the string and match a word near beginning | |
// to avoid quadratic time complexity | |
let leading = this.line.slice(0, this.cursor); | |
const reversed = Array.from(leading).reverse().join(''); | |
const match = reversed.match(/^\s*(?:[^\w\s]+|\w+)?/); | |
leading = leading.slice(0, leading.length - match[0].length); | |
this.line = leading + this.line.slice(this.cursor, this.line.length); | |
this.cursor = leading.length; | |
this._refreshLine(); | |
} | |
} | |
; | |
_deleteWordRight() { | |
if (this.cursor < this.line.length) { | |
const trailing = this.line.slice(this.cursor); | |
const match = trailing.match(/^(?:\s+|\W+|\w+)\s*/); | |
this.line = this.line.slice(0, this.cursor) + | |
trailing.slice(match[0].length); | |
this._refreshLine(); | |
} | |
} | |
; | |
_deleteLineLeft() { | |
this.line = this.line.slice(this.cursor); | |
this.cursor = 0; | |
this._refreshLine(); | |
} | |
; | |
_deleteLineRight() { | |
this.line = this.line.slice(0, this.cursor); | |
this._refreshLine(); | |
} | |
; | |
clearLine() { | |
this._moveCursor(+Infinity); | |
this._writeToOutput('\r\n'); | |
this.line = ''; | |
this.cursor = 0; | |
this.prevRows = 0; | |
} | |
; | |
_line() { | |
const line = this._addHistory(); | |
this.clearLine(); | |
this._onLine(line); | |
} | |
; | |
// TODO(BridgeAR): Add underscores to the search part and a red background in | |
// case no match is found. This should only be the visual part and not the | |
// actual line content! | |
// TODO(BridgeAR): In case the substring based search is active and the end is | |
// reached, show a comment how to search the history as before. E.g., using | |
// <ctrl> + N. Only show this after two/three UPs or DOWNs, not on the first | |
// one. | |
_historyNext() { | |
if (this.historyIndex >= 0) { | |
const search = this[kSubstringSearch] || ''; | |
let index = this.historyIndex - 1; | |
while (index >= 0 && | |
(!this.history[index].startsWith(search) || | |
this.line === this.history[index])) { | |
index--; | |
} | |
if (index === -1) { | |
this.line = search; | |
} | |
else { | |
this.line = this.history[index]; | |
} | |
this.historyIndex = index; | |
this.cursor = this.line.length; // Set cursor to end of line. | |
this._refreshLine(); | |
} | |
} | |
; | |
_historyPrev() { | |
if (this.historyIndex < this.history.length && this.history.length) { | |
const search = this[kSubstringSearch] || ''; | |
let index = this.historyIndex + 1; | |
while (index < this.history.length && | |
(!this.history[index].startsWith(search) || | |
this.line === this.history[index])) { | |
index++; | |
} | |
if (index === this.history.length) { | |
this.line = search; | |
} | |
else { | |
this.line = this.history[index]; | |
} | |
this.historyIndex = index; | |
this.cursor = this.line.length; // Set cursor to end of line. | |
this._refreshLine(); | |
} | |
} | |
; | |
_getDisplayPos(str) { | |
let offset = 0; | |
const col = this.columns; | |
let rows = 0; | |
str = stripVTControlCharacters(str); | |
for (const char of str) { | |
if (char === '\n') { | |
// Rows must be incremented by 1 even if offset = 0 or col = +Infinity. | |
rows += 1; | |
offset = 0; | |
continue; | |
} | |
// Tabs must be aligned by an offset of the tab size. | |
if (char === '\t') { | |
offset += this.tabSize - (offset % this.tabSize); | |
continue; | |
} | |
const width = getStringWidth(char); | |
if (width === 0 || width === 1) { | |
offset += width; | |
} | |
else { // width === 2 | |
if ((offset + 1) % col === 0) { | |
offset++; | |
} | |
offset += 2; | |
} | |
} | |
const cols = offset % col; | |
rows += (offset - cols) / col; | |
return { cols, rows }; | |
} | |
; | |
/** | |
* Returns the real position of the cursor in relation | |
* to the input prompt + string. | |
* @returns {{ | |
* rows: number; | |
* cols: number; | |
* }} | |
*/ | |
getCursorPos() { | |
const strBeforeCursor = this._prompt + | |
this.line.slice(0, this.cursor); | |
return this._getDisplayPos(strBeforeCursor); | |
} | |
; | |
_getCursorPos() { | |
return this.getCursorPos(); | |
} | |
_moveCursor(dx) { | |
if (dx === 0) { | |
return; | |
} | |
const oldPos = this.getCursorPos(); | |
this.cursor += dx; | |
// Bounds check | |
if (this.cursor < 0) { | |
this.cursor = 0; | |
} | |
else if (this.cursor > this.line.length) { | |
this.cursor = this.line.length; | |
} | |
const newPos = this.getCursorPos(); | |
// Check if cursor stayed on the line. | |
if (oldPos.rows === newPos.rows) { | |
const diffWidth = newPos.cols - oldPos.cols; | |
moveCursor(this.output, diffWidth, 0); | |
} | |
else { | |
this._refreshLine(); | |
} | |
} | |
; | |
_ttyWriteDumb(s, key) { | |
key = key || {}; | |
if (key.name === 'escape') | |
return; | |
if (this._sawReturnAt && key.name !== 'enter') | |
this._sawReturnAt = 0; | |
if (key.ctrl) { | |
if (key.name === 'c') { | |
if (this.listenerCount('SIGINT') > 0) { | |
this.emit('SIGINT'); | |
} | |
else { | |
// This readline instance is finished | |
this.close(); | |
} | |
return; | |
} | |
else if (key.name === 'd') { | |
this.close(); | |
return; | |
} | |
} | |
switch (key.name) { | |
case 'return': // Carriage return, i.e. \r | |
this._sawReturnAt = Date.now(); | |
this._line(); | |
break; | |
case 'enter': | |
// When key interval > crlfDelay | |
if (this._sawReturnAt === 0 || | |
Date.now() - this._sawReturnAt > this.crlfDelay) { | |
this._line(); | |
} | |
this._sawReturnAt = 0; | |
break; | |
default: | |
if (typeof s === 'string' && s) { | |
this.line += s; | |
this.cursor += s.length; | |
this._writeToOutput(s); | |
} | |
} | |
} | |
_ttyWrite(s, key) { | |
const previousKey = this._previousKey; | |
key = key || {}; | |
this._previousKey = key; | |
// Activate or deactivate substring search. | |
if ((key.name === 'up' || key.name === 'down') && | |
!key.ctrl && !key.meta && !key.shift) { | |
if (this[kSubstringSearch] === null) { | |
this[kSubstringSearch] = this.line.slice(0, this.cursor); | |
} | |
} | |
else if (this[kSubstringSearch] !== null) { | |
this[kSubstringSearch] = null; | |
// Reset the index in case there's no match. | |
if (this.history.length === this.historyIndex) { | |
this.historyIndex = -1; | |
} | |
} | |
// Ignore escape key, fixes | |
// https://github.com/nodejs/node-v0.x-archive/issues/2876. | |
if (key.name === 'escape') | |
return; | |
if (key.ctrl && key.shift) { | |
/* Control and shift pressed */ | |
switch (key.name) { | |
// TODO(BridgeAR): The transmitted escape sequence is `\b` and that is | |
// identical to <ctrl>-h. It should have a unique escape sequence. | |
case 'backspace': | |
this._deleteLineLeft(); | |
break; | |
case 'delete': | |
this._deleteLineRight(); | |
break; | |
} | |
} | |
else if (key.ctrl) { | |
/* Control key pressed */ | |
switch (key.name) { | |
case 'c': | |
if (this.listenerCount('SIGINT') > 0) { | |
this.emit('SIGINT'); | |
} | |
else { | |
// This readline instance is finished | |
this.close(); | |
} | |
break; | |
case 'h': // delete left | |
this._deleteLeft(); | |
break; | |
case 'd': // delete right or EOF | |
if (this.cursor === 0 && this.line.length === 0) { | |
// This readline instance is finished | |
this.close(); | |
} | |
else if (this.cursor < this.line.length) { | |
this._deleteRight(); | |
} | |
break; | |
case 'u': // Delete from current to start of line | |
this._deleteLineLeft(); | |
break; | |
case 'k': // Delete from current to end of line | |
this._deleteLineRight(); | |
break; | |
case 'a': // Go to the start of the line | |
this._moveCursor(-Infinity); | |
break; | |
case 'e': // Go to the end of the line | |
this._moveCursor(+Infinity); | |
break; | |
case 'b': // back one character | |
this._moveCursor(-charLengthLeft(this.line, this.cursor)); | |
break; | |
case 'f': // Forward one character | |
this._moveCursor(+charLengthAt(this.line, this.cursor)); | |
break; | |
case 'l': // Clear the whole screen | |
cursorTo(this.output, 0, 0); | |
clearScreenDown(this.output); | |
this._refreshLine(); | |
break; | |
case 'n': // next history item | |
this._historyNext(); | |
break; | |
case 'p': // Previous history item | |
this._historyPrev(); | |
break; | |
case 'z': | |
break; | |
case 'w': // Delete backwards to a word boundary | |
// TODO(BridgeAR): The transmitted escape sequence is `\b` and that is | |
// identical to <ctrl>-h. It should have a unique escape sequence. | |
// Falls through | |
case 'backspace': | |
this._deleteWordLeft(); | |
break; | |
case 'delete': // Delete forward to a word boundary | |
this._deleteWordRight(); | |
break; | |
case 'left': | |
this._wordLeft(); | |
break; | |
case 'right': | |
this._wordRight(); | |
break; | |
} | |
} | |
else if (key.meta) { | |
/* Meta key pressed */ | |
switch (key.name) { | |
case 'b': // backward word | |
this._wordLeft(); | |
break; | |
case 'f': // forward word | |
this._wordRight(); | |
break; | |
case 'd': // delete forward word | |
case 'delete': | |
this._deleteWordRight(); | |
break; | |
case 'backspace': // Delete backwards to a word boundary | |
this._deleteWordLeft(); | |
break; | |
} | |
} | |
else { | |
/* No modifier keys used */ | |
// \r bookkeeping is only relevant if a \n comes right after. | |
if (this._sawReturnAt && key.name !== 'enter') | |
this._sawReturnAt = 0; | |
switch (key.name) { | |
case 'return': // Carriage return, i.e. \r | |
this._sawReturnAt = Date.now(); | |
this._line(); | |
break; | |
case 'enter': | |
// When key interval > crlfDelay | |
if (this._sawReturnAt === 0 || | |
Date.now() - this._sawReturnAt > this.crlfDelay) { | |
this._line(); | |
} | |
this._sawReturnAt = 0; | |
break; | |
case 'backspace': | |
this._deleteLeft(); | |
break; | |
case 'delete': | |
this._deleteRight(); | |
break; | |
case 'left': | |
// Obtain the code point to the left | |
this._moveCursor(-charLengthLeft(this.line, this.cursor)); | |
break; | |
case 'right': | |
this._moveCursor(+charLengthAt(this.line, this.cursor)); | |
break; | |
case 'home': | |
this._moveCursor(-Infinity); | |
break; | |
case 'end': | |
this._moveCursor(+Infinity); | |
break; | |
case 'up': | |
this._historyPrev(); | |
break; | |
case 'down': | |
this._historyNext(); | |
break; | |
case 'tab': | |
// If tab completion enabled, do that... | |
if (typeof this.completer === 'function' && this.isCompletionEnabled) { | |
const lastKeypressWasTab = previousKey && previousKey.name === 'tab'; | |
this._tabComplete(lastKeypressWasTab); | |
break; | |
} | |
// falls through | |
default: | |
if (typeof s === 'string' && s) { | |
const lines = s.split(/\r\n|\n|\r/); | |
for (let i = 0, len = lines.length; i < len; i++) { | |
if (i > 0) { | |
this._line(); | |
} | |
this._insertString(lines[i]); | |
} | |
} | |
} | |
} | |
} | |
; | |
} | |
_a = kQuestionCancel, _b = kLineObjectStream; | |
export { Interface, clearLine, createInterface, clearScreenDown, cursorTo, moveCursor, emitKeypressEvents }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const kUTF16SurrogateThreshold = 0x10000; // 2 ** 16 | |
const kEscape = '\x1b'; | |
const kSubstringSearch = Symbol('kSubstringSearch'); | |
// Regex used for ansi escape code splitting | |
// Adopted from https://github.com/chalk/ansi-regex/blob/master/index.js | |
// License: MIT, authors: @sindresorhus, Qix-, arjunmehta and LitoMore | |
// Matches all ansi escape code sequences in a string | |
const ansiPattern = '[\\u001B\\u009B][[\\]()#;?]*' + | |
'(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)' + | |
'|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'; | |
const ansi = new RegExp(ansiPattern, 'g'); | |
/** | |
* Remove all VT control characters. Use to estimate displayed string width. | |
*/ | |
function stripVTControlCharacters(str) { | |
return str.replace(ansi, ''); | |
} | |
function CSI(strings, ...args) { | |
let ret = `${kEscape}[`; | |
for (let n = 0; n < strings.length; n++) { | |
ret += strings[n]; | |
if (n < args.length) | |
ret += args[n]; | |
} | |
return ret; | |
} | |
CSI.kEscape = kEscape; | |
CSI.kClearToLineBeginning = CSI `1K`; | |
CSI.kClearToLineEnd = CSI `0K`; | |
CSI.kClearLine = CSI `2K`; | |
CSI.kClearScreenDown = CSI `0J`; | |
// TODO(BridgeAR): Treat combined characters as single character, i.e, | |
// 'a\u0301' and '\u0301a' (both have the same visual output). | |
// Check Canonical_Combining_Class in | |
// http://userguide.icu-project.org/strings/properties | |
function charLengthLeft(str, i) { | |
if (i <= 0) | |
return 0; | |
if ((i > 1 && | |
str.codePointAt(i - 2) >= kUTF16SurrogateThreshold) || | |
str.codePointAt(i - 1) >= kUTF16SurrogateThreshold) { | |
return 2; | |
} | |
return 1; | |
} | |
function charLengthAt(str, i) { | |
if (str.length <= i) { | |
// Pretend to move to the right. This is necessary to autocomplete while | |
// moving to the right. | |
return 1; | |
} | |
return str.codePointAt(i) >= kUTF16SurrogateThreshold ? 2 : 1; | |
} | |
// This runs in O(n log n). | |
function commonPrefix(strings) { | |
if (strings.length === 1) { | |
return strings[0]; | |
} | |
const sorted = strings.slice().sort(); | |
const min = sorted[0]; | |
const max = sorted[sorted.length - 1]; | |
for (let i = 0; i < min.length; i++) { | |
if (min[i] !== max[i]) { | |
return min.slice(0, i); | |
} | |
} | |
return min; | |
} | |
/** | |
* moves the cursor to the x and y coordinate on the given stream | |
*/ | |
function cursorTo(stream, x, y, callback) { | |
if (typeof y === 'function') { | |
callback = y; | |
y = undefined; | |
} | |
if (Number.isNaN(x)) | |
throw new Error(); | |
; | |
if (Number.isNaN(y)) | |
throw new Error(); | |
; | |
if (stream == null || (typeof x !== 'number' && typeof y !== 'number')) { | |
if (typeof callback === 'function') | |
setTimeout(callback, 0); | |
return true; | |
} | |
if (typeof x !== 'number') | |
throw new Error(); | |
const data = typeof y !== 'number' ? CSI `${x + 1}G` : CSI `${y + 1};${x + 1}H`; | |
return stream.write(data, callback); | |
} | |
/** | |
* moves the cursor relative to its current location | |
*/ | |
function moveCursor(stream, dx, dy, callback) { | |
if (stream == null || !(dx || dy)) { | |
if (typeof callback === 'function') | |
setTimeout(callback, 0); | |
return true; | |
} | |
let data = ''; | |
if (dx < 0) { | |
data += CSI `${-dx}D`; | |
} | |
else if (dx > 0) { | |
data += CSI `${dx}C`; | |
} | |
if (dy < 0) { | |
data += CSI `${-dy}A`; | |
} | |
else if (dy > 0) { | |
data += CSI `${dy}B`; | |
} | |
return stream.write(data, callback); | |
} | |
/** | |
* clears the current line the cursor is on: | |
* -1 for left of the cursor | |
* +1 for right of the cursor | |
* 0 for the entire line | |
*/ | |
function clearLine(stream, dir, callback) { | |
if (stream === null || stream === undefined) { | |
if (typeof callback === 'function') | |
setTimeout(callback, 0); | |
return true; | |
} | |
const type = dir < 0 ? CSI.kClearToLineBeginning : dir > 0 ? CSI.kClearToLineEnd : CSI.kClearLine; | |
return stream.write(type, callback); | |
} | |
/** | |
* clears the screen from the current position of the cursor down | |
*/ | |
function clearScreenDown(stream, callback) { | |
if (stream === null || stream === undefined) { | |
if (typeof callback === 'function') | |
setTimeout(callback, 0); | |
return true; | |
} | |
return stream.write(CSI.kClearScreenDown, callback); | |
} | |
export { clearLine, clearScreenDown, cursorTo, moveCursor, stripVTControlCharacters, charLengthAt, charLengthLeft, commonPrefix, kSubstringSearch, CSI }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment