shellquest
Version:
Terminal-based procedurally generated dungeon crawler
1,682 lines (1,660 loc) • 2.32 MB
JavaScript
#!/usr/bin/env bun
// @bun
var __create = Object.create;
var __getProtoOf = Object.getPrototypeOf;
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __toESM = (mod, isNodeMode, target) => {
target = mod != null ? __create(__getProtoOf(mod)) : {};
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
for (let key of __getOwnPropNames(mod))
if (!__hasOwnProp.call(to, key))
__defProp(to, key, {
get: () => mod[key],
enumerable: true
});
return to;
};
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, {
get: all[name],
enumerable: true,
configurable: true,
set: (newValue) => all[name] = () => newValue
});
};
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
var __promiseAll = (args) => Promise.all(args);
var __require = import.meta.require;
// node_modules/@opentui/core/assets/javascript/highlights.scm
var highlights_default = "./highlights-ghv9g403.scm";
var init_highlights = () => {};
// node_modules/@opentui/core/assets/javascript/tree-sitter-javascript.wasm
var tree_sitter_javascript_default = "./tree-sitter-javascript-nd0q4pe9.wasm";
var init_tree_sitter_javascript = () => {};
// node_modules/@opentui/core/assets/typescript/highlights.scm
var highlights_default2 = "./highlights-eq9cgrbb.scm";
var init_highlights2 = () => {};
// node_modules/@opentui/core/assets/typescript/tree-sitter-typescript.wasm
var tree_sitter_typescript_default = "./tree-sitter-typescript-zxjzwt75.wasm";
var init_tree_sitter_typescript = () => {};
// node_modules/@opentui/core/assets/markdown/highlights.scm
var highlights_default3 = "./highlights-r812a2qc.scm";
var init_highlights3 = () => {};
// node_modules/@opentui/core/assets/markdown/tree-sitter-markdown.wasm
var tree_sitter_markdown_default = "./tree-sitter-markdown-411r6y9b.wasm";
var init_tree_sitter_markdown = () => {};
// node_modules/@opentui/core/assets/markdown/injections.scm
var injections_default = "./injections-73j83es3.scm";
var init_injections = () => {};
// node_modules/@opentui/core/assets/markdown_inline/highlights.scm
var highlights_default4 = "./highlights-x6tmsnaa.scm";
var init_highlights4 = () => {};
// node_modules/@opentui/core/assets/markdown_inline/tree-sitter-markdown_inline.wasm
var tree_sitter_markdown_inline_default = "./tree-sitter-markdown_inline-j5349f42.wasm";
var init_tree_sitter_markdown_inline = () => {};
// node_modules/@opentui/core/assets/zig/highlights.scm
var highlights_default5 = "./highlights-hk7bwhj4.scm";
var init_highlights5 = () => {};
// node_modules/@opentui/core/assets/zig/tree-sitter-zig.wasm
var tree_sitter_zig_default = "./tree-sitter-zig-e78zbjpm.wasm";
var init_tree_sitter_zig = () => {};
// node_modules/@opentui/core/index-916mvx7m.js
import { Buffer as Buffer2 } from "buffer";
import { EventEmitter } from "events";
import { EventEmitter as EventEmitter2 } from "events";
import { EventEmitter as EventEmitter3 } from "events";
import { resolve, dirname } from "path";
import { fileURLToPath } from "url";
import { resolve as resolve2, isAbsolute, parse } from "path";
import { existsSync } from "fs";
import { basename, join } from "path";
import os from "os";
import path from "path";
import { EventEmitter as EventEmitter4 } from "events";
import { dlopen, toArrayBuffer as toArrayBuffer4, JSCallback, ptr as ptr3 } from "bun:ffi";
import { existsSync as existsSync2 } from "fs";
import { EventEmitter as EventEmitter5 } from "events";
import { toArrayBuffer } from "bun:ffi";
import { ptr, toArrayBuffer as toArrayBuffer2 } from "bun:ffi";
import { ptr as ptr2, toArrayBuffer as toArrayBuffer3 } from "bun:ffi";
import { EventEmitter as EventEmitter6 } from "events";
import util from "util";
import { EventEmitter as EventEmitter8 } from "events";
import { Console } from "console";
import fs from "fs";
import path4 from "path";
import util2 from "util";
import { Writable } from "stream";
import { EventEmitter as EventEmitter7 } from "events";
import { EventEmitter as EventEmitter9 } from "events";
function wrapAssembly(lib) {
function patch(prototype, name, fn) {
const original = prototype[name];
prototype[name] = function() {
for (var _len = arguments.length, args = new Array(_len), _key = 0;_key < _len; _key++) {
args[_key] = arguments[_key];
}
return fn.call(this, original, ...args);
};
}
for (const fnName of ["setPosition", "setMargin", "setFlexBasis", "setWidth", "setHeight", "setMinWidth", "setMinHeight", "setMaxWidth", "setMaxHeight", "setPadding", "setGap"]) {
const methods = {
[Unit.Point]: lib.Node.prototype[fnName],
[Unit.Percent]: lib.Node.prototype[`${fnName}Percent`],
[Unit.Auto]: lib.Node.prototype[`${fnName}Auto`]
};
patch(lib.Node.prototype, fnName, function(original) {
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1;_key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
const value = args.pop();
let unit, asNumber;
if (value === "auto") {
unit = Unit.Auto;
asNumber = undefined;
} else if (typeof value === "object") {
unit = value.unit;
asNumber = value.valueOf();
} else {
unit = typeof value === "string" && value.endsWith("%") ? Unit.Percent : Unit.Point;
asNumber = parseFloat(value);
if (value !== undefined && !Number.isNaN(value) && Number.isNaN(asNumber)) {
throw new Error(`Invalid value ${value} for ${fnName}`);
}
}
if (!methods[unit])
throw new Error(`Failed to execute "${fnName}": Unsupported unit '${value}'`);
if (asNumber !== undefined) {
return methods[unit].call(this, ...args, asNumber);
} else {
return methods[unit].call(this, ...args);
}
});
}
function wrapMeasureFunction(measureFunction) {
return lib.MeasureCallback.implement({
measure: function() {
const {
width,
height
} = measureFunction(...arguments);
return {
width: width ?? NaN,
height: height ?? NaN
};
}
});
}
patch(lib.Node.prototype, "setMeasureFunc", function(original, measureFunc) {
if (measureFunc) {
return original.call(this, wrapMeasureFunction(measureFunc));
} else {
return this.unsetMeasureFunc();
}
});
function wrapDirtiedFunc(dirtiedFunction) {
return lib.DirtiedCallback.implement({
dirtied: dirtiedFunction
});
}
patch(lib.Node.prototype, "setDirtiedFunc", function(original, dirtiedFunc) {
original.call(this, wrapDirtiedFunc(dirtiedFunc));
});
patch(lib.Config.prototype, "free", function() {
lib.Config.destroy(this);
});
patch(lib.Node, "create", (_, config) => {
return config ? lib.Node.createWithConfig(config) : lib.Node.createDefault();
});
patch(lib.Node.prototype, "free", function() {
lib.Node.destroy(this);
});
patch(lib.Node.prototype, "freeRecursive", function() {
for (let t = 0, T = this.getChildCount();t < T; ++t) {
this.getChild(0).freeRecursive();
}
this.free();
});
patch(lib.Node.prototype, "calculateLayout", function(original) {
let width = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : NaN;
let height = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : NaN;
let direction = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : Direction.LTR;
return original.call(this, width, height, direction);
});
return {
Config: lib.Config,
Node: lib.Node,
...YGEnums_default
};
}
function getBorderSides(border) {
return border === true ? { top: true, right: true, bottom: true, left: true } : Array.isArray(border) ? {
top: border.includes("top"),
right: border.includes("right"),
bottom: border.includes("bottom"),
left: border.includes("left")
} : { top: false, right: false, bottom: false, left: false };
}
function borderCharsToArray(chars) {
const array = new Uint32Array(11);
array[0] = chars.topLeft.codePointAt(0);
array[1] = chars.topRight.codePointAt(0);
array[2] = chars.bottomLeft.codePointAt(0);
array[3] = chars.bottomRight.codePointAt(0);
array[4] = chars.horizontal.codePointAt(0);
array[5] = chars.vertical.codePointAt(0);
array[6] = chars.topT.codePointAt(0);
array[7] = chars.bottomT.codePointAt(0);
array[8] = chars.leftT.codePointAt(0);
array[9] = chars.rightT.codePointAt(0);
array[10] = chars.cross.codePointAt(0);
return array;
}
function fromKittyMods(mod) {
return {
shift: !!(mod & 1),
alt: !!(mod & 2),
ctrl: !!(mod & 4),
super: !!(mod & 8),
hyper: !!(mod & 16),
meta: !!(mod & 32),
capsLock: !!(mod & 64),
numLock: !!(mod & 128)
};
}
function parseKittySpecialKey(sequence) {
const specialKeyRe = /^\x1b\[(\d+);(\d+):(\d+)([A-Z~])$/;
const match = specialKeyRe.exec(sequence);
if (!match)
return null;
const keyNumOrOne = match[1];
const modifierStr = match[2];
const eventTypeStr = match[3];
const terminator = match[4];
let keyName;
if (terminator === "~") {
keyName = tildeKeyMap[keyNumOrOne];
} else {
if (keyNumOrOne !== "1")
return null;
keyName = functionalKeyMap[terminator];
}
if (!keyName)
return null;
const key = {
name: keyName,
ctrl: false,
meta: false,
shift: false,
option: false,
number: false,
sequence,
raw: sequence,
eventType: "press",
source: "kitty",
super: false,
hyper: false,
capsLock: false,
numLock: false
};
if (modifierStr) {
const modifierMask = parseInt(modifierStr, 10);
if (!isNaN(modifierMask) && modifierMask > 1) {
const mods = fromKittyMods(modifierMask - 1);
key.shift = mods.shift;
key.ctrl = mods.ctrl;
key.meta = mods.alt || mods.meta;
key.option = mods.alt;
key.super = mods.super;
key.hyper = mods.hyper;
key.capsLock = mods.capsLock;
key.numLock = mods.numLock;
}
}
if (eventTypeStr === "1" || !eventTypeStr) {
key.eventType = "press";
} else if (eventTypeStr === "2") {
key.eventType = "press";
key.repeated = true;
} else if (eventTypeStr === "3") {
key.eventType = "release";
}
return key;
}
function parseKittyKeyboard(sequence) {
const specialResult = parseKittySpecialKey(sequence);
if (specialResult)
return specialResult;
const kittyRe = /^\x1b\[([^\x1b]+)u$/;
const match = kittyRe.exec(sequence);
if (!match)
return null;
const params = match[1];
const fields = params.split(";");
if (fields.length < 1)
return null;
const key = {
name: "",
ctrl: false,
meta: false,
shift: false,
option: false,
number: false,
sequence,
raw: sequence,
eventType: "press",
source: "kitty",
super: false,
hyper: false,
capsLock: false,
numLock: false
};
let text = "";
const field1 = fields[0]?.split(":") || [];
const codepointStr = field1[0];
if (!codepointStr)
return null;
const codepoint = parseInt(codepointStr, 10);
if (isNaN(codepoint))
return null;
let shiftedCodepoint;
let baseCodepoint;
if (field1[1]) {
const shifted = parseInt(field1[1], 10);
if (!isNaN(shifted) && shifted > 0 && shifted <= 1114111) {
shiftedCodepoint = shifted;
}
}
if (field1[2]) {
const base = parseInt(field1[2], 10);
if (!isNaN(base) && base > 0 && base <= 1114111) {
baseCodepoint = base;
}
}
const knownKey = kittyKeyMap[codepoint];
if (knownKey) {
key.name = knownKey;
key.code = `[${codepoint}u`;
} else {
if (codepoint > 0 && codepoint <= 1114111) {
const char = String.fromCodePoint(codepoint);
key.name = char;
if (baseCodepoint) {
key.baseCode = baseCodepoint;
}
} else {
return null;
}
}
if (fields[1]) {
const field2 = fields[1].split(":");
const modifierStr = field2[0];
const eventTypeStr = field2[1];
if (modifierStr) {
const modifierMask = parseInt(modifierStr, 10);
if (!isNaN(modifierMask) && modifierMask > 1) {
const mods = fromKittyMods(modifierMask - 1);
key.shift = mods.shift;
key.ctrl = mods.ctrl;
key.meta = mods.alt || mods.meta;
key.option = mods.alt;
key.super = mods.super;
key.hyper = mods.hyper;
key.capsLock = mods.capsLock;
key.numLock = mods.numLock;
}
}
if (eventTypeStr === "1" || !eventTypeStr) {
key.eventType = "press";
} else if (eventTypeStr === "2") {
key.eventType = "press";
key.repeated = true;
} else if (eventTypeStr === "3") {
key.eventType = "release";
} else {
key.eventType = "press";
}
}
if (fields[2]) {
const codepoints = fields[2].split(":");
for (const cpStr of codepoints) {
const cp = parseInt(cpStr, 10);
if (!isNaN(cp) && cp > 0 && cp <= 1114111) {
text += String.fromCodePoint(cp);
}
}
}
if (text === "") {
const isPrintable = key.name.length > 0 && !kittyKeyMap[codepoint];
if (isPrintable) {
if (key.shift && shiftedCodepoint) {
text = String.fromCodePoint(shiftedCodepoint);
} else {
text = key.name;
}
}
}
if (key.name === " " && key.shift && !key.ctrl && !key.meta) {
text = " ";
}
if (text) {
key.sequence = text;
}
return key;
}
class KeyEvent {
name;
ctrl;
meta;
shift;
option;
sequence;
number;
raw;
eventType;
source;
code;
super;
hyper;
capsLock;
numLock;
baseCode;
repeated;
_defaultPrevented = false;
constructor(key) {
this.name = key.name;
this.ctrl = key.ctrl;
this.meta = key.meta;
this.shift = key.shift;
this.option = key.option;
this.sequence = key.sequence;
this.number = key.number;
this.raw = key.raw;
this.eventType = key.eventType;
this.source = key.source;
this.code = key.code;
this.super = key.super;
this.hyper = key.hyper;
this.capsLock = key.capsLock;
this.numLock = key.numLock;
this.baseCode = key.baseCode;
this.repeated = key.repeated;
}
get defaultPrevented() {
return this._defaultPrevented;
}
preventDefault() {
this._defaultPrevented = true;
}
}
class PasteEvent {
text;
_defaultPrevented = false;
constructor(text) {
this.text = text;
}
get defaultPrevented() {
return this._defaultPrevented;
}
preventDefault() {
this._defaultPrevented = true;
}
}
class RGBA {
buffer;
constructor(buffer) {
this.buffer = buffer;
}
static fromArray(array) {
return new RGBA(array);
}
static fromValues(r, g, b, a = 1) {
return new RGBA(new Float32Array([r, g, b, a]));
}
static fromInts(r, g, b, a = 255) {
return new RGBA(new Float32Array([r / 255, g / 255, b / 255, a / 255]));
}
static fromHex(hex) {
return hexToRgb(hex);
}
toInts() {
return [Math.round(this.r * 255), Math.round(this.g * 255), Math.round(this.b * 255), Math.round(this.a * 255)];
}
get r() {
return this.buffer[0];
}
set r(value) {
this.buffer[0] = value;
}
get g() {
return this.buffer[1];
}
set g(value) {
this.buffer[1] = value;
}
get b() {
return this.buffer[2];
}
set b(value) {
this.buffer[2] = value;
}
get a() {
return this.buffer[3];
}
set a(value) {
this.buffer[3] = value;
}
map(fn) {
return [fn(this.r), fn(this.g), fn(this.b), fn(this.a)];
}
toString() {
return `rgba(${this.r.toFixed(2)}, ${this.g.toFixed(2)}, ${this.b.toFixed(2)}, ${this.a.toFixed(2)})`;
}
}
function hexToRgb(hex) {
hex = hex.replace(/^#/, "");
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
} else if (hex.length === 4) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
}
if (!/^[0-9A-Fa-f]{6}$/.test(hex) && !/^[0-9A-Fa-f]{8}$/.test(hex)) {
console.warn(`Invalid hex color: ${hex}, defaulting to magenta`);
return RGBA.fromValues(1, 0, 1, 1);
}
const r = parseInt(hex.substring(0, 2), 16) / 255;
const g = parseInt(hex.substring(2, 4), 16) / 255;
const b = parseInt(hex.substring(4, 6), 16) / 255;
const a = hex.length === 8 ? parseInt(hex.substring(6, 8), 16) / 255 : 1;
return RGBA.fromValues(r, g, b, a);
}
function parseColor(color) {
if (typeof color === "string") {
const lowerColor = color.toLowerCase();
if (lowerColor === "transparent") {
return RGBA.fromValues(0, 0, 0, 0);
}
if (CSS_COLOR_NAMES[lowerColor]) {
return hexToRgb(CSS_COLOR_NAMES[lowerColor]);
}
return hexToRgb(color);
}
return color;
}
function parseColorTags(text) {
const segments = [];
let currentIndex = 0;
const colorTagRegex = /<c(\d+)>(.*?)<\/c\d+>/g;
let lastIndex = 0;
let match;
while ((match = colorTagRegex.exec(text)) !== null) {
if (match.index > lastIndex) {
const plainText = text.slice(lastIndex, match.index);
if (plainText) {
segments.push({ text: plainText, colorIndex: 0 });
}
}
const colorIndex = parseInt(match[1]) - 1;
const taggedText = match[2];
segments.push({ text: taggedText, colorIndex: Math.max(0, colorIndex) });
lastIndex = match.index + match[0].length;
}
if (lastIndex < text.length) {
const remainingText = text.slice(lastIndex);
if (remainingText) {
segments.push({ text: remainingText, colorIndex: 0 });
}
}
return segments;
}
function getParsedFont(fontKey) {
if (!parsedFonts[fontKey]) {
const fontDef = fonts[fontKey];
const parsedChars = {};
for (const [char, lines] of Object.entries(fontDef.chars)) {
parsedChars[char] = lines.map((line) => parseColorTags(line));
}
parsedFonts[fontKey] = {
...fontDef,
colors: fontDef.colors || 1,
chars: parsedChars
};
}
return parsedFonts[fontKey];
}
function measureText({ text, font = "tiny" }) {
const fontDef = getParsedFont(font);
if (!fontDef) {
console.warn(`Font '${font}' not found`);
return { width: 0, height: 0 };
}
let currentX = 0;
for (let i = 0;i < text.length; i++) {
const char = text[i].toUpperCase();
const charDef = fontDef.chars[char];
if (!charDef) {
const spaceChar = fontDef.chars[" "];
if (spaceChar && spaceChar[0]) {
let spaceWidth = 0;
for (const segment of spaceChar[0]) {
spaceWidth += segment.text.length;
}
currentX += spaceWidth;
} else {
currentX += 1;
}
continue;
}
let charWidth = 0;
if (charDef[0]) {
for (const segment of charDef[0]) {
charWidth += segment.text.length;
}
}
currentX += charWidth;
if (i < text.length - 1) {
currentX += fontDef.letterspace_size;
}
}
return {
width: currentX,
height: fontDef.lines
};
}
function getCharacterPositions(text, font = "tiny") {
const fontDef = getParsedFont(font);
if (!fontDef) {
return [0];
}
const positions = [0];
let currentX = 0;
for (let i = 0;i < text.length; i++) {
const char = text[i].toUpperCase();
const charDef = fontDef.chars[char];
let charWidth = 0;
if (!charDef) {
const spaceChar = fontDef.chars[" "];
if (spaceChar && spaceChar[0]) {
for (const segment of spaceChar[0]) {
charWidth += segment.text.length;
}
} else {
charWidth = 1;
}
} else if (charDef[0]) {
for (const segment of charDef[0]) {
charWidth += segment.text.length;
}
}
currentX += charWidth;
if (i < text.length - 1) {
currentX += fontDef.letterspace_size;
}
positions.push(currentX);
}
return positions;
}
function coordinateToCharacterIndex(x, text, font = "tiny") {
const positions = getCharacterPositions(text, font);
if (x < 0) {
return 0;
}
for (let i = 0;i < positions.length - 1; i++) {
const currentPos = positions[i];
const nextPos = positions[i + 1];
if (x >= currentPos && x < nextPos) {
const charMidpoint = currentPos + (nextPos - currentPos) / 2;
return x < charMidpoint ? i : i + 1;
}
}
if (positions.length > 0 && x >= positions[positions.length - 1]) {
return text.length;
}
return 0;
}
function renderFontToFrameBuffer(buffer, {
text,
x = 0,
y = 0,
color = [RGBA.fromInts(255, 255, 255, 255)],
backgroundColor = RGBA.fromInts(0, 0, 0, 255),
font = "tiny"
}) {
const width = buffer.width;
const height = buffer.height;
const fontDef = getParsedFont(font);
if (!fontDef) {
console.warn(`Font '${font}' not found`);
return { width: 0, height: 0 };
}
const colors = Array.isArray(color) ? color : [color];
if (y < 0 || y + fontDef.lines > height) {
return { width: 0, height: fontDef.lines };
}
let currentX = x;
const startX = x;
for (let i = 0;i < text.length; i++) {
const char = text[i].toUpperCase();
const charDef = fontDef.chars[char];
if (!charDef) {
const spaceChar = fontDef.chars[" "];
if (spaceChar && spaceChar[0]) {
let spaceWidth = 0;
for (const segment of spaceChar[0]) {
spaceWidth += segment.text.length;
}
currentX += spaceWidth;
} else {
currentX += 1;
}
continue;
}
let charWidth = 0;
if (charDef[0]) {
for (const segment of charDef[0]) {
charWidth += segment.text.length;
}
}
if (currentX >= width)
break;
if (currentX + charWidth < 0) {
currentX += charWidth + fontDef.letterspace_size;
continue;
}
for (let lineIdx = 0;lineIdx < fontDef.lines && lineIdx < charDef.length; lineIdx++) {
const segments = charDef[lineIdx];
const renderY = y + lineIdx;
if (renderY >= 0 && renderY < height) {
let segmentX = currentX;
for (const segment of segments) {
const segmentColor = colors[segment.colorIndex] || colors[0];
for (let charIdx = 0;charIdx < segment.text.length; charIdx++) {
const renderX = segmentX + charIdx;
if (renderX >= 0 && renderX < width) {
const fontChar = segment.text[charIdx];
if (fontChar !== " ") {
buffer.setCellWithAlphaBlending(renderX, renderY, fontChar, parseColor(segmentColor), parseColor(backgroundColor));
}
}
}
segmentX += segment.text.length;
}
}
}
currentX += charWidth;
if (i < text.length - 1) {
currentX += fontDef.letterspace_size;
}
}
return {
width: currentX - startX,
height: fontDef.lines
};
}
function createTextAttributes({
bold = false,
italic = false,
underline = false,
dim = false,
blink = false,
inverse = false,
hidden = false,
strikethrough = false
} = {}) {
let attributes = TextAttributes.NONE;
if (bold)
attributes |= TextAttributes.BOLD;
if (italic)
attributes |= TextAttributes.ITALIC;
if (underline)
attributes |= TextAttributes.UNDERLINE;
if (dim)
attributes |= TextAttributes.DIM;
if (blink)
attributes |= TextAttributes.BLINK;
if (inverse)
attributes |= TextAttributes.INVERSE;
if (hidden)
attributes |= TextAttributes.HIDDEN;
if (strikethrough)
attributes |= TextAttributes.STRIKETHROUGH;
return attributes;
}
function isStyledText(obj) {
return obj && obj[BrandedStyledText];
}
function stringToStyledText(content) {
const chunk = {
__isChunk: true,
text: content
};
return new StyledText([chunk]);
}
function applyStyle(input, style) {
if (typeof input === "object" && "__isChunk" in input) {
const existingChunk = input;
const fg = style.fg ? parseColor(style.fg) : existingChunk.fg;
const bg = style.bg ? parseColor(style.bg) : existingChunk.bg;
const newAttrs = createTextAttributes(style);
const mergedAttrs = existingChunk.attributes ? existingChunk.attributes | newAttrs : newAttrs;
return {
__isChunk: true,
text: existingChunk.text,
fg,
bg,
attributes: mergedAttrs
};
} else {
const plainTextStr = String(input);
const fg = style.fg ? parseColor(style.fg) : undefined;
const bg = style.bg ? parseColor(style.bg) : undefined;
const attributes = createTextAttributes(style);
return {
__isChunk: true,
text: plainTextStr,
fg,
bg,
attributes
};
}
}
class LinearScrollAccel {
tick(_now) {
return 1;
}
reset() {}
}
function isCompleteSequence(data) {
if (!data.startsWith(ESC)) {
return "not-escape";
}
if (data.length === 1) {
return "incomplete";
}
const afterEsc = data.slice(1);
if (afterEsc.startsWith("[")) {
if (afterEsc.startsWith("[M")) {
return data.length >= 6 ? "complete" : "incomplete";
}
return isCompleteCsiSequence(data);
}
if (afterEsc.startsWith("]")) {
return isCompleteOscSequence(data);
}
if (afterEsc.startsWith("P")) {
return isCompleteDcsSequence(data);
}
if (afterEsc.startsWith("_")) {
return isCompleteApcSequence(data);
}
if (afterEsc.startsWith("O")) {
return afterEsc.length >= 2 ? "complete" : "incomplete";
}
if (afterEsc.length === 1) {
return "complete";
}
return "complete";
}
function isCompleteCsiSequence(data) {
if (!data.startsWith(ESC + "[")) {
return "complete";
}
if (data.length < 3) {
return "incomplete";
}
const payload = data.slice(2);
const lastChar = payload[payload.length - 1];
const lastCharCode = lastChar.charCodeAt(0);
if (lastCharCode >= 64 && lastCharCode <= 126) {
if (payload.startsWith("<")) {
const mouseMatch = /^<\d+;\d+;\d+[Mm]$/.test(payload);
if (mouseMatch) {
return "complete";
}
if (lastChar === "M" || lastChar === "m") {
const parts = payload.slice(1, -1).split(";");
if (parts.length === 3 && parts.every((p) => /^\d+$/.test(p))) {
return "complete";
}
}
return "incomplete";
}
return "complete";
}
return "incomplete";
}
function isCompleteOscSequence(data) {
if (!data.startsWith(ESC + "]")) {
return "complete";
}
if (data.endsWith(ESC + "\\") || data.endsWith("\x07")) {
return "complete";
}
return "incomplete";
}
function isCompleteDcsSequence(data) {
if (!data.startsWith(ESC + "P")) {
return "complete";
}
if (data.endsWith(ESC + "\\")) {
return "complete";
}
return "incomplete";
}
function isCompleteApcSequence(data) {
if (!data.startsWith(ESC + "_")) {
return "complete";
}
if (data.endsWith(ESC + "\\")) {
return "complete";
}
return "incomplete";
}
function extractCompleteSequences(buffer) {
const sequences = [];
let pos = 0;
while (pos < buffer.length) {
const remaining = buffer.slice(pos);
if (remaining.startsWith(ESC)) {
let seqEnd = 1;
while (seqEnd <= remaining.length) {
const candidate = remaining.slice(0, seqEnd);
const status = isCompleteSequence(candidate);
if (status === "complete") {
sequences.push(candidate);
pos += seqEnd;
break;
} else if (status === "incomplete") {
seqEnd++;
} else {
sequences.push(candidate);
pos += seqEnd;
break;
}
}
if (seqEnd > remaining.length) {
return { sequences, remainder: remaining };
}
} else {
sequences.push(remaining[0]);
pos++;
}
}
return { sequences, remainder: "" };
}
function parseAlign(value) {
if (value == null) {
return Align.Auto;
}
switch (value.toLowerCase()) {
case "auto":
return Align.Auto;
case "flex-start":
return Align.FlexStart;
case "center":
return Align.Center;
case "flex-end":
return Align.FlexEnd;
case "stretch":
return Align.Stretch;
case "baseline":
return Align.Baseline;
case "space-between":
return Align.SpaceBetween;
case "space-around":
return Align.SpaceAround;
case "space-evenly":
return Align.SpaceEvenly;
default:
return Align.Auto;
}
}
function parseFlexDirection(value) {
if (value == null) {
return FlexDirection.Column;
}
switch (value.toLowerCase()) {
case "column":
return FlexDirection.Column;
case "column-reverse":
return FlexDirection.ColumnReverse;
case "row":
return FlexDirection.Row;
case "row-reverse":
return FlexDirection.RowReverse;
default:
return FlexDirection.Column;
}
}
function parseJustify(value) {
if (value == null) {
return Justify.FlexStart;
}
switch (value.toLowerCase()) {
case "flex-start":
return Justify.FlexStart;
case "center":
return Justify.Center;
case "flex-end":
return Justify.FlexEnd;
case "space-between":
return Justify.SpaceBetween;
case "space-around":
return Justify.SpaceAround;
case "space-evenly":
return Justify.SpaceEvenly;
default:
return Justify.FlexStart;
}
}
function parseOverflow(value) {
if (value == null) {
return Overflow.Visible;
}
switch (value.toLowerCase()) {
case "visible":
return Overflow.Visible;
case "hidden":
return Overflow.Hidden;
case "scroll":
return Overflow.Scroll;
default:
return Overflow.Visible;
}
}
function parsePositionType(value) {
if (value == null) {
return PositionType.Relative;
}
switch (value.toLowerCase()) {
case "static":
return PositionType.Static;
case "relative":
return PositionType.Relative;
case "absolute":
return PositionType.Absolute;
default:
return PositionType.Static;
}
}
function parseWrap(value) {
if (value == null) {
return Wrap.NoWrap;
}
switch (value.toLowerCase()) {
case "no-wrap":
return Wrap.NoWrap;
case "wrap":
return Wrap.Wrap;
case "wrap-reverse":
return Wrap.WrapReverse;
default:
return Wrap.NoWrap;
}
}
class SelectionAnchor {
renderable;
relativeX;
relativeY;
constructor(renderable, absoluteX, absoluteY) {
this.renderable = renderable;
this.relativeX = absoluteX - this.renderable.x;
this.relativeY = absoluteY - this.renderable.y;
}
get x() {
return this.renderable.x + this.relativeX;
}
get y() {
return this.renderable.y + this.relativeY;
}
}
class Selection {
_anchor;
_originalFocus;
_normalizedAnchor;
_normalizedFocus;
_selectedRenderables = [];
_touchedRenderables = [];
_isActive = true;
_isSelecting = true;
constructor(anchorRenderable, anchor, focus) {
this._anchor = new SelectionAnchor(anchorRenderable, anchor.x, anchor.y);
this._originalFocus = { ...focus };
this._updateNormalizedSelection();
}
get anchor() {
return { ...this._normalizedAnchor };
}
get focus() {
return { ...this._normalizedFocus };
}
set focus(value) {
this._originalFocus = { ...value };
this._updateNormalizedSelection();
}
_updateNormalizedSelection() {
const anchorBeforeFocus = this._anchor.y < this._originalFocus.y || this._anchor.y === this._originalFocus.y && this._anchor.x <= this._originalFocus.x;
if (anchorBeforeFocus) {
this._normalizedAnchor = { x: this._anchor.x, y: this._anchor.y };
this._normalizedFocus = { ...this._originalFocus };
} else {
this._normalizedAnchor = { ...this._originalFocus };
this._normalizedFocus = { x: this._anchor.x + 1, y: this._anchor.y };
}
}
get isActive() {
return this._isActive;
}
set isActive(value) {
this._isActive = value;
}
get isSelecting() {
return this._isSelecting;
}
set isSelecting(value) {
this._isSelecting = value;
}
get bounds() {
return {
x: Math.min(this._normalizedAnchor.x, this._normalizedFocus.x),
y: Math.min(this._normalizedAnchor.y, this._normalizedFocus.y),
width: Math.max(this._normalizedAnchor.x, this._normalizedFocus.x) - Math.min(this._normalizedAnchor.x, this._normalizedFocus.x),
height: Math.max(this._normalizedAnchor.y, this._normalizedFocus.y) - Math.min(this._normalizedAnchor.y, this._normalizedFocus.y)
};
}
updateSelectedRenderables(selectedRenderables) {
this._selectedRenderables = selectedRenderables;
}
get selectedRenderables() {
return this._selectedRenderables;
}
updateTouchedRenderables(touchedRenderables) {
this._touchedRenderables = touchedRenderables;
}
get touchedRenderables() {
return this._touchedRenderables;
}
getSelectedText() {
const selectedTexts = this._selectedRenderables.sort((a, b) => {
const aY = a.y;
const bY = b.y;
if (aY !== bY) {
return aY - bY;
}
return a.x - b.x;
}).filter((renderable) => !renderable.isDestroyed).map((renderable) => renderable.getSelectedText()).filter((text) => text);
return selectedTexts.join(`
`);
}
}
function convertGlobalToLocalSelection(globalSelection, localX, localY) {
if (!globalSelection?.isActive) {
return null;
}
return {
anchorX: globalSelection.anchor.x - localX,
anchorY: globalSelection.anchor.y - localY,
focusX: globalSelection.focus.x - localX,
focusY: globalSelection.focus.y - localY,
isActive: true
};
}
class ASCIIFontSelectionHelper {
getText;
getFont;
localSelection = null;
constructor(getText, getFont) {
this.getText = getText;
this.getFont = getFont;
}
hasSelection() {
return this.localSelection !== null;
}
getSelection() {
return this.localSelection;
}
shouldStartSelection(localX, localY, width, height) {
if (localX < 0 || localX >= width || localY < 0 || localY >= height) {
return false;
}
const text = this.getText();
const font = this.getFont();
const charIndex = coordinateToCharacterIndex(localX, text, font);
return charIndex >= 0 && charIndex <= text.length;
}
onLocalSelectionChanged(localSelection, width, height) {
const previousSelection = this.localSelection;
if (!localSelection?.isActive) {
this.localSelection = null;
return previousSelection !== null;
}
const text = this.getText();
const font = this.getFont();
const selStart = { x: localSelection.anchorX, y: localSelection.anchorY };
const selEnd = { x: localSelection.focusX, y: localSelection.focusY };
if (height - 1 < selStart.y || 0 > selEnd.y) {
this.localSelection = null;
return previousSelection !== null;
}
let startCharIndex = 0;
let endCharIndex = text.length;
if (selStart.y > height - 1) {
this.localSelection = null;
return previousSelection !== null;
} else if (selStart.y >= 0 && selStart.y <= height - 1) {
if (selStart.x > 0) {
startCharIndex = coordinateToCharacterIndex(selStart.x, text, font);
}
}
if (selEnd.y < 0) {
this.localSelection = null;
return previousSelection !== null;
} else if (selEnd.y >= 0 && selEnd.y <= height - 1) {
if (selEnd.x >= 0) {
endCharIndex = coordinateToCharacterIndex(selEnd.x, text, font);
} else {
endCharIndex = 0;
}
}
if (startCharIndex < endCharIndex && startCharIndex >= 0 && endCharIndex <= text.length) {
this.localSelection = { start: startCharIndex, end: endCharIndex };
} else {
this.localSelection = null;
}
return previousSelection?.start !== this.localSelection?.start || previousSelection?.end !== this.localSelection?.end;
}
}
function singleton(key, factory) {
const bag = globalThis[singletonCacheSymbol] ??= {};
if (!(key in bag)) {
bag[key] = factory();
}
return bag[key];
}
function destroySingleton(key) {
const bag = globalThis[singletonCacheSymbol];
if (bag && key in bag) {
delete bag[key];
}
}
function hasSingleton(key) {
const bag = globalThis[singletonCacheSymbol];
return bag && key in bag;
}
function registerEnvVar(config) {
const existing = envRegistry[config.name];
if (existing) {
if (existing.description !== config.description || existing.type !== config.type || existing.default !== config.default) {
throw new Error(`Environment variable "${config.name}" is already registered with different configuration. ` + `Existing: ${JSON.stringify(existing)}, New: ${JSON.stringify(config)}`);
}
return;
}
envRegistry[config.name] = config;
}
function normalizeBoolean(value) {
const lowerValue = value.toLowerCase();
return ["true", "1", "on", "yes"].includes(lowerValue);
}
function parseEnvValue(config) {
const envValue = process.env[config.name];
if (envValue === undefined && config.default !== undefined) {
return config.default;
}
if (envValue === undefined) {
throw new Error(`Required environment variable ${config.name} is not set. ${config.description}`);
}
switch (config.type) {
case "boolean":
return typeof envValue === "boolean" ? envValue : normalizeBoolean(envValue);
case "number":
const numValue = Number(envValue);
if (isNaN(numValue)) {
throw new Error(`Environment variable ${config.name} must be a valid number, got: ${envValue}`);
}
return numValue;
case "string":
default:
return envValue;
}
}
class EnvStore {
parsedValues = new Map;
get(key) {
if (this.parsedValues.has(key)) {
return this.parsedValues.get(key);
}
if (!(key in envRegistry)) {
throw new Error(`Environment variable ${key} is not registered.`);
}
try {
const value = parseEnvValue(envRegistry[key]);
this.parsedValues.set(key, value);
return value;
} catch (error) {
throw new Error(`Failed to parse env var ${key}: ${error instanceof Error ? error.message : String(error)}`);
}
}
has(key) {
return key in envRegistry;
}
clearCache() {
this.parsedValues.clear();
}
}
function getSpecificity(group) {
return group.split(".").length;
}
function shouldSuppressInInjection(group, meta) {
if (meta?.isInjection) {
return false;
}
return group === "markup.raw.block";
}
function treeSitterToTextChunks(content, highlights, syntaxStyle, options) {
const chunks = [];
const defaultStyle = syntaxStyle.getStyle("default");
const concealEnabled = options?.enabled ?? true;
const injectionContainerRanges = [];
const boundaries = [];
for (let i = 0;i < highlights.length; i++) {
const [start, end, , meta] = highlights[i];
if (start === end)
continue;
if (meta?.containsInjection) {
injectionContainerRanges.push({ start, end });
}
boundaries.push({ offset: start, type: "start", highlightIndex: i });
boundaries.push({ offset: end, type: "end", highlightIndex: i });
}
boundaries.sort((a, b) => {
if (a.offset !== b.offset)
return a.offset - b.offset;
if (a.type === "end" && b.type === "start")
return -1;
if (a.type === "start" && b.type === "end")
return 1;
return 0;
});
const activeHighlights = new Set;
let currentOffset = 0;
for (let i = 0;i < boundaries.length; i++) {
const boundary = boundaries[i];
if (currentOffset < boundary.offset && activeHighlights.size > 0) {
const segmentText = content.slice(currentOffset, boundary.offset);
const activeGroups = [];
for (const idx of activeHighlights) {
const [, , group, meta] = highlights[idx];
activeGroups.push({ group, meta, index: idx });
}
const concealHighlight = concealEnabled ? activeGroups.find((h) => h.meta?.conceal !== undefined || h.group === "conceal" || h.group.startsWith("conceal.")) : undefined;
if (concealHighlight) {
let replacementText = "";
if (concealHighlight.meta?.conceal !== undefined) {
replacementText = concealHighlight.meta.conceal;
} else if (concealHighlight.group === "conceal.with.space") {
replacementText = " ";
}
if (replacementText) {
chunks.push({
__isChunk: true,
text: replacementText,
fg: defaultStyle?.fg,
bg: defaultStyle?.bg,
attributes: defaultStyle ? createTextAttributes({
bold: defaultStyle.bold,
italic: defaultStyle.italic,
underline: defaultStyle.underline,
dim: defaultStyle.dim
}) : 0
});
}
} else {
const insideInjectionContainer = injectionContainerRanges.some((range) => currentOffset >= range.start && currentOffset < range.end);
const validGroups = activeGroups.filter((h) => {
if (insideInjectionContainer && shouldSuppressInInjection(h.group, h.meta)) {
return false;
}
return true;
});
const sortedGroups = validGroups.sort((a, b) => {
const aSpec = getSpecificity(a.group);
const bSpec = getSpecificity(b.group);
if (aSpec !== bSpec)
return aSpec - bSpec;
return a.index - b.index;
});
const mergedStyle = {};
for (const { group } of sortedGroups) {
let styleForGroup = syntaxStyle.getStyle(group);
if (!styleForGroup && group.includes(".")) {
const baseName = group.split(".")[0];
styleForGroup = syntaxStyle.getStyle(baseName);
}
if (styleForGroup) {
if (styleForGroup.fg !== undefined)
mergedStyle.fg = styleForGroup.fg;
if (styleForGroup.bg !== undefined)
mergedStyle.bg = styleForGroup.bg;
if (styleForGroup.bold !== undefined)
mergedStyle.bold = styleForGroup.bold;
if (styleForGroup.italic !== undefined)
mergedStyle.italic = styleForGroup.italic;
if (styleForGroup.underline !== undefined)
mergedStyle.underline = styleForGroup.underline;
if (styleForGroup.dim !== undefined)
mergedStyle.dim = styleForGroup.dim;
} else {
if (group.includes(".")) {
const baseName = group.split(".")[0];
if (env.OTUI_TS_STYLE_WARN) {
console.warn(`Syntax style not found for group "${group}" or base scope "${baseName}", using default style`);
}
} else {
if (env.OTUI_TS_STYLE_WARN) {
console.warn(`Syntax style not found for group "${group}", using default style`);
}
}
}
}
const finalStyle = Object.keys(mergedStyle).length > 0 ? mergedStyle : defaultStyle;
chunks.push({
__isChunk: true,
text: segmentText,
fg: finalStyle?.fg,
bg: finalStyle?.bg,
attributes: finalStyle ? createTextAttributes({
bold: finalStyle.bold,
italic: finalStyle.italic,
underline: finalStyle.underline,
dim: finalStyle.dim
}) : 0
});
}
} else if (currentOffset < boundary.offset) {
const text = content.slice(currentOffset, boundary.offset);
chunks.push({
__isChunk: true,
text,
fg: defaultStyle?.fg,
bg: defaultStyle?.bg,
attributes: defaultStyle ? createTextAttributes({
bold: defaultStyle.bold,
italic: defaultStyle.italic,
underline: defaultStyle.underline,
dim: defaultStyle.dim
}) : 0
});
}
if (boundary.type === "start") {
activeHighlights.add(boundary.highlightIndex);
} else {
activeHighlights.delete(boundary.highlightIndex);
if (concealEnabled) {
const [, , group, meta] = highlights[boundary.highlightIndex];
if (meta?.concealLines !== undefined) {
if (boundary.offset < content.length && content[boundary.offset] === `
`) {
currentOffset = boundary.offset + 1;
continue;
}
}
if (meta?.conceal !== undefined) {
if (meta.conceal === " ") {
if (boundary.offset < content.length && content[boundary.offset] === " ") {
currentOffset = boundary.offset + 1;
continue;
}
} else if (meta.conceal === "" && group === "conceal" && !meta.isInjection) {
if (boundary.offset < content.length && content[boundary.offset] === " ") {
currentOffset = boundary.offset + 1;
continue;
}
}
}
}
}
currentOffset = boundary.offset;
}
if (currentOffset < content.length) {
const text = content.slice(currentOffset);
chunks.push({
__isChunk: true,
text,
fg: defaultStyle?.fg,
bg: defaultStyle?.bg,
attributes: defaultStyle ? createTextAttributes({
bold: defaultStyle.bold,
italic: defaultStyle.italic,
underline: defaultStyle.underline,
dim: defaultStyle.dim
}) : 0
});
}
return chunks;
}
class DebounceController {
scopeId;
constructor(scopeId) {
this.scopeId = scopeId;
if (!TIMERS_MAP.has(this.scopeId)) {
TIMERS_MAP.set(this.scopeId, new Map);
}
}
debounce(id, ms, fn) {
const scopeMap = TIMERS_MAP.get(this.scopeId);
return new Promise((resolve3, reject) => {
if (scopeMap.has(id)) {
clearTimeout(scopeMap.get(id));
}
const timerId = setTimeout(() => {
try {
resolve3(fn());
} catch (error) {
reject(error);
}
scopeMap.delete(id);
}, ms);
scopeMap.set(id, timerId);
});
}
clearDebounce(id) {
const scopeMap = TIMERS_MAP.get(this.scopeId);
if (scopeMap && scopeMap.has(id)) {
clearTimeout(scopeMap.get(id));
scopeMap.delete(id);
}
}
clear() {
const scopeMap = TIMERS_MAP.get(this.scopeId);
if (scopeMap) {
scopeMap.forEach((timerId) => clearTimeout(timerId));
scopeMap.clear();
}
}
}
function createDebounce(scopeId) {
return new DebounceController(scopeId);
}
function clearDebounceScope(scopeId) {
const scopeMap = TIMERS_MAP.get(scopeId);
if (scopeMap) {
scopeMap.forEach((timerId) => clearTimeout(timerId));
scopeMap.clear();
}
}
class ProcessQueue {
processor;
queue = [];
processing = false;
autoProcess = true;
constructor(processor, autoProcess = true) {
this.processor = processor;
this.autoProcess = autoProcess;
}
enqueue(item) {
this.queue.push(item);
if (!this.processing && this.autoProcess) {
this.processQueue();
}
}
processQueue() {
if (this.queue.length === 0) {
return;
}
this.processing = true;
queueMicrotask(async () => {
if (this.queue.length === 0) {
this.processing = false;
return;
}
const item = this.queue.shift();
try {
await this.processor(item);
} catch (error) {
console.error("Error processing queue item:", error);
}
if (this.queue.length > 0) {
this.processQueue();
} else {
this.processing = false;
}
});
}
clear() {
this.queue = [];
}
isProcessing() {
return this.processing;
}
size() {
return this.queue.length;
}
}
function getParsers() {
if (!_cachedParsers) {
_cachedParsers = [
{
filetype: "javascript",
queries: {
highlights: [resolve(dirname(fileURLToPath(import.meta.url)), highlights_default)]
},
wasm: resolve(dirname(fileURLToPath(import.meta.url)), tree_sitter_javascript_default)
},
{
filetype: "typescript",
queries: {
highlights: [resolve(dirname(fileURLToPath(import.meta.url)), highlights_default2)]
},
wasm: resolve(dirname(fileURLToPath(import.meta.url)), tree_sitter_typescript_default)
},
{
filetype: "markdown",
queries: {
highlights: [resolve(dirname(fileURLToPath(import.meta.url)), highlights_default3)],
injections: [resolve(dirname(fileURLToPath(import.meta.url)), injections_default)]
},
wasm: resolve(dirname(fileURLToPath(import.meta.url)), tree_sitter_markdown_default),
injectionMapping: {
nodeTypes: {
inline: "markdown_inline",
pipe_table_cell: "markdown_inline"
},
infoStringMap: {
javascript: "javascript",
js: "javascript",
typescript: "typescript",
ts: "typescript",
markdown: "markdown",
md: "markdown"
}
}
},
{
filetype: "markdown_inline",
queries: {
highlights: [resolve(dirname(fileURLToPath(import.meta.url)), highlights_default4)]
},
wasm: resolve(dirname(fileURLToPath(import.meta.url)), tree_sitter_markdown_inline_default)
},
{
filetype: "zig",
queries: {
highlights: [resolve(dirname(fileURLToPath(import.meta.url)), highlights_default5)]
},
wasm: resolve(dirname(fileURLToPath(import.meta.url)), tree_sitter_zig_default)
}
];
}
return _cachedParsers;
}
function isBunfsPath(path2) {
return path2.includes("$bunfs") || /^B:[\\/]~BUN/i.test(path2);
}
function getBunfsRootPath() {
return process.platform === "win32" ? "B:\\~BUN\\root" : "/$bunfs/root";
}
function normalizeBunf