@opentui/core 0.1.25 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/3d.js +140 -140
  2. package/3d.js.map +2 -2
  3. package/README.md +5 -1
  4. package/Renderable.d.ts +8 -7
  5. package/animation/Timeline.d.ts +2 -1
  6. package/assets/javascript/highlights.scm +205 -0
  7. package/assets/javascript/tree-sitter-javascript.wasm +0 -0
  8. package/assets/typescript/highlights.scm +604 -0
  9. package/assets/typescript/tree-sitter-typescript.wasm +0 -0
  10. package/{index-6kvgbzah.js → index-zx1dwm33.js} +1498 -133
  11. package/index-zx1dwm33.js.map +52 -0
  12. package/index.js +2371 -2179
  13. package/index.js.map +16 -14
  14. package/lib/KeyHandler.d.ts +54 -12
  15. package/lib/data-paths.d.ts +26 -0
  16. package/lib/debounce.d.ts +42 -0
  17. package/lib/env.d.ts +2 -1
  18. package/lib/hast-styled-text.d.ts +3 -23
  19. package/lib/index.d.ts +5 -0
  20. package/lib/parse.keypress.d.ts +2 -2
  21. package/lib/queue.d.ts +15 -0
  22. package/lib/scroll-acceleration.d.ts +43 -0
  23. package/lib/singleton.d.ts +2 -0
  24. package/lib/styled-text.d.ts +0 -15
  25. package/lib/syntax-style.d.ts +36 -0
  26. package/lib/tree-sitter/assets/update.d.ts +11 -0
  27. package/lib/tree-sitter/client.d.ts +46 -0
  28. package/lib/tree-sitter/default-parsers.d.ts +2 -0
  29. package/lib/tree-sitter/download-utils.d.ts +21 -0
  30. package/lib/tree-sitter/index.d.ts +10 -0
  31. package/lib/tree-sitter/parser.worker.d.ts +1 -0
  32. package/lib/tree-sitter/resolve-ft.d.ts +2 -0
  33. package/lib/tree-sitter/types.d.ts +64 -0
  34. package/lib/tree-sitter-styled-text.d.ts +7 -0
  35. package/lib/validate-dir-name.d.ts +1 -0
  36. package/package.json +22 -8
  37. package/parser.worker.js +640 -0
  38. package/parser.worker.js.map +11 -0
  39. package/renderables/Code.d.ts +31 -0
  40. package/renderables/Input.d.ts +2 -2
  41. package/renderables/ScrollBar.d.ts +2 -2
  42. package/renderables/ScrollBox.d.ts +9 -3
  43. package/renderables/Select.d.ts +2 -2
  44. package/renderables/TabSelect.d.ts +2 -2
  45. package/renderables/Text.d.ts +10 -67
  46. package/renderables/TextBufferRenderable.d.ts +81 -0
  47. package/renderables/TextNode.d.ts +3 -1
  48. package/renderables/index.d.ts +11 -8
  49. package/renderer.d.ts +18 -3
  50. package/testing/spy.d.ts +7 -0
  51. package/testing.d.ts +1 -0
  52. package/testing.js +17 -2
  53. package/testing.js.map +5 -4
  54. package/types.d.ts +2 -1
  55. package/index-6kvgbzah.js.map +0 -39
@@ -27,7 +27,7 @@ var __export = (target, all) => {
27
27
  };
28
28
  var __require = import.meta.require;
29
29
 
30
- // ../../node_modules/yoga-layout/dist/src/index.js
30
+ // ../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/index.js
31
31
  var exports_src = {};
32
32
  __export(exports_src, {
33
33
  default: () => src_default,
@@ -51,7 +51,7 @@ __export(exports_src, {
51
51
  Align: () => Align
52
52
  });
53
53
 
54
- // ../../node_modules/yoga-layout/dist/binaries/yoga-wasm-base64-esm.js
54
+ // ../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/binaries/yoga-wasm-base64-esm.js
55
55
  var loadYoga = (() => {
56
56
  var _scriptDir = import.meta.url;
57
57
  return function(loadYoga2) {
@@ -1356,7 +1356,7 @@ var loadYoga = (() => {
1356
1356
  })();
1357
1357
  var yoga_wasm_base64_esm_default = loadYoga;
1358
1358
 
1359
- // ../../node_modules/yoga-layout/dist/src/generated/YGEnums.js
1359
+ // ../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/generated/YGEnums.js
1360
1360
  var Align = /* @__PURE__ */ function(Align2) {
1361
1361
  Align2[Align2["Auto"] = 0] = "Auto";
1362
1362
  Align2[Align2["FlexStart"] = 1] = "FlexStart";
@@ -1559,7 +1559,7 @@ var constants = {
1559
1559
  };
1560
1560
  var YGEnums_default = constants;
1561
1561
 
1562
- // ../../node_modules/yoga-layout/dist/src/wrapAssembly.js
1562
+ // ../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/wrapAssembly.js
1563
1563
  function wrapAssembly(lib) {
1564
1564
  function patch(prototype, name, fn) {
1565
1565
  const original = prototype[name];
@@ -1661,7 +1661,7 @@ function wrapAssembly(lib) {
1661
1661
  };
1662
1662
  }
1663
1663
 
1664
- // ../../node_modules/yoga-layout/dist/src/index.js
1664
+ // ../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/index.js
1665
1665
  var Yoga = wrapAssembly(await yoga_wasm_base64_esm_default());
1666
1666
  var src_default = Yoga;
1667
1667
 
@@ -1763,7 +1763,7 @@ var BorderCharArrays = {
1763
1763
  };
1764
1764
 
1765
1765
  // src/lib/parse.keypress.ts
1766
- import { Buffer } from "buffer";
1766
+ import { Buffer as Buffer2 } from "buffer";
1767
1767
 
1768
1768
  // src/lib/parse.keypress-kitty.ts
1769
1769
  var kittyKeyMap = {
@@ -2080,7 +2080,7 @@ var isCtrlKey = (code) => {
2080
2080
  };
2081
2081
  var parseKeypress = (s = "", options = {}) => {
2082
2082
  let parts;
2083
- if (Buffer.isBuffer(s)) {
2083
+ if (Buffer2.isBuffer(s)) {
2084
2084
  if (s[0] > 127 && s[1] === undefined) {
2085
2085
  s[0] -= 128;
2086
2086
  s = "\x1B" + String(s);
@@ -2143,6 +2143,10 @@ var parseKeypress = (s = "", options = {}) => {
2143
2143
  key.meta = true;
2144
2144
  key.shift = /^[A-Z]$/.test(parts[1]);
2145
2145
  key.name = parts[1];
2146
+ } else if (s.length === 2 && s[0] === "\x1B" && s[1] <= "\x1A") {
2147
+ key.meta = true;
2148
+ key.ctrl = true;
2149
+ key.name = String.fromCharCode(s.charCodeAt(1) + 97 - 1);
2146
2150
  } else if (parts = fnKeyRe.exec(s)) {
2147
2151
  const segs = [...s];
2148
2152
  if (segs[0] === "\x1B" && segs[1] === "\x1B") {
@@ -2191,12 +2195,69 @@ var ANSI = {
2191
2195
  };
2192
2196
 
2193
2197
  // src/lib/KeyHandler.ts
2198
+ class KeyEvent {
2199
+ name;
2200
+ ctrl;
2201
+ meta;
2202
+ shift;
2203
+ option;
2204
+ sequence;
2205
+ number;
2206
+ raw;
2207
+ eventType;
2208
+ code;
2209
+ super;
2210
+ hyper;
2211
+ capsLock;
2212
+ numLock;
2213
+ baseCode;
2214
+ _defaultPrevented = false;
2215
+ constructor(key) {
2216
+ this.name = key.name;
2217
+ this.ctrl = key.ctrl;
2218
+ this.meta = key.meta;
2219
+ this.shift = key.shift;
2220
+ this.option = key.option;
2221
+ this.sequence = key.sequence;
2222
+ this.number = key.number;
2223
+ this.raw = key.raw;
2224
+ this.eventType = key.eventType;
2225
+ this.code = key.code;
2226
+ this.super = key.super;
2227
+ this.hyper = key.hyper;
2228
+ this.capsLock = key.capsLock;
2229
+ this.numLock = key.numLock;
2230
+ this.baseCode = key.baseCode;
2231
+ }
2232
+ get defaultPrevented() {
2233
+ return this._defaultPrevented;
2234
+ }
2235
+ preventDefault() {
2236
+ this._defaultPrevented = true;
2237
+ }
2238
+ }
2239
+
2240
+ class PasteEvent {
2241
+ text;
2242
+ _defaultPrevented = false;
2243
+ constructor(text) {
2244
+ this.text = text;
2245
+ }
2246
+ get defaultPrevented() {
2247
+ return this._defaultPrevented;
2248
+ }
2249
+ preventDefault() {
2250
+ this._defaultPrevented = true;
2251
+ }
2252
+ }
2253
+
2194
2254
  class KeyHandler extends EventEmitter {
2195
2255
  stdin;
2196
2256
  useKittyKeyboard;
2197
2257
  listener;
2198
2258
  pasteMode = false;
2199
2259
  pasteBuffer = [];
2260
+ suspended = false;
2200
2261
  constructor(stdin, useKittyKeyboard = false) {
2201
2262
  super();
2202
2263
  this.stdin = stdin || process.stdin;
@@ -2210,7 +2271,7 @@ class KeyHandler extends EventEmitter {
2210
2271
  this.pasteBuffer.push(Bun.stripANSI(data));
2211
2272
  if (data.endsWith(ANSI.bracketedPasteEnd)) {
2212
2273
  this.pasteMode = false;
2213
- this.emit("paste", this.pasteBuffer.join(""));
2274
+ this.emit("paste", new PasteEvent(this.pasteBuffer.join("")));
2214
2275
  this.pasteBuffer = [];
2215
2276
  }
2216
2277
  return;
@@ -2218,16 +2279,16 @@ class KeyHandler extends EventEmitter {
2218
2279
  const parsedKey = parseKeypress(key, { useKittyKeyboard: this.useKittyKeyboard });
2219
2280
  switch (parsedKey.eventType) {
2220
2281
  case "press":
2221
- this.emit("keypress", parsedKey);
2282
+ this.emit("keypress", new KeyEvent(parsedKey));
2222
2283
  break;
2223
2284
  case "repeat":
2224
- this.emit("keyrepeat", parsedKey);
2285
+ this.emit("keyrepeat", new KeyEvent(parsedKey));
2225
2286
  break;
2226
2287
  case "release":
2227
- this.emit("keyrelease", parsedKey);
2288
+ this.emit("keyrelease", new KeyEvent(parsedKey));
2228
2289
  break;
2229
2290
  default:
2230
- this.emit("keypress", parsedKey);
2291
+ this.emit("keypress", new KeyEvent(parsedKey));
2231
2292
  break;
2232
2293
  }
2233
2294
  };
@@ -2236,6 +2297,57 @@ class KeyHandler extends EventEmitter {
2236
2297
  destroy() {
2237
2298
  this.stdin.removeListener("data", this.listener);
2238
2299
  }
2300
+ suspend() {
2301
+ if (!this.suspended) {
2302
+ this.suspended = true;
2303
+ this.stdin.removeListener("data", this.listener);
2304
+ }
2305
+ }
2306
+ resume() {
2307
+ if (this.suspended) {
2308
+ this.suspended = false;
2309
+ this.stdin.on("data", this.listener);
2310
+ }
2311
+ }
2312
+ }
2313
+
2314
+ class InternalKeyHandler extends KeyHandler {
2315
+ renderableHandlers = new Map;
2316
+ constructor(stdin, useKittyKeyboard = false) {
2317
+ super(stdin, useKittyKeyboard);
2318
+ }
2319
+ emit(event, ...args) {
2320
+ return this.emitWithPriority(event, ...args);
2321
+ }
2322
+ emitWithPriority(event, ...args) {
2323
+ const hasGlobalListeners = super.emit(event, ...args);
2324
+ const renderableSet = this.renderableHandlers.get(event);
2325
+ let hasRenderableListeners = false;
2326
+ if (renderableSet && renderableSet.size > 0) {
2327
+ hasRenderableListeners = true;
2328
+ if (event === "keypress" || event === "keyrepeat" || event === "keyrelease" || event === "paste") {
2329
+ const keyEvent = args[0];
2330
+ if (keyEvent.defaultPrevented)
2331
+ return hasGlobalListeners || hasRenderableListeners;
2332
+ }
2333
+ for (const handler of renderableSet) {
2334
+ handler(...args);
2335
+ }
2336
+ }
2337
+ return hasGlobalListeners || hasRenderableListeners;
2338
+ }
2339
+ onInternal(event, handler) {
2340
+ if (!this.renderableHandlers.has(event)) {
2341
+ this.renderableHandlers.set(event, new Set);
2342
+ }
2343
+ this.renderableHandlers.get(event).add(handler);
2344
+ }
2345
+ offInternal(event, handler) {
2346
+ const handlers = this.renderableHandlers.get(event);
2347
+ if (handlers) {
2348
+ handlers.delete(handler);
2349
+ }
2350
+ }
2239
2351
  }
2240
2352
 
2241
2353
  // src/lib/RGBA.ts
@@ -4089,60 +4201,9 @@ function isStyledText(obj) {
4089
4201
  class StyledText {
4090
4202
  [BrandedStyledText] = true;
4091
4203
  chunks;
4092
- textRenderable;
4093
4204
  constructor(chunks) {
4094
4205
  this.chunks = chunks;
4095
4206
  }
4096
- mount(textRenderable) {
4097
- this.textRenderable = textRenderable;
4098
- }
4099
- insert(chunk, index) {
4100
- const originalLength = this.chunks.length;
4101
- if (this.textRenderable) {
4102
- this.textRenderable.insertChunk(chunk, index ?? originalLength);
4103
- let newChunks;
4104
- if (index === undefined || index === originalLength) {
4105
- newChunks = [...this.chunks, chunk];
4106
- } else {
4107
- newChunks = [...this.chunks.slice(0, index), chunk, ...this.chunks.slice(index)];
4108
- }
4109
- this.chunks = newChunks;
4110
- }
4111
- return this;
4112
- }
4113
- remove(chunk) {
4114
- if (this.textRenderable) {
4115
- this.textRenderable.removeChunk(chunk);
4116
- const originalLength = this.chunks.length;
4117
- const index = this.chunks.indexOf(chunk);
4118
- if (index === -1)
4119
- return this;
4120
- let newChunks;
4121
- if (index === originalLength - 1) {
4122
- newChunks = this.chunks.slice(0, -1);
4123
- } else {
4124
- newChunks = [...this.chunks.slice(0, index), ...this.chunks.slice(index + 1)];
4125
- }
4126
- this.chunks = newChunks;
4127
- }
4128
- return this;
4129
- }
4130
- replace(chunk, oldChunk) {
4131
- if (this.textRenderable) {
4132
- this.textRenderable.replaceChunk(chunk, oldChunk);
4133
- const index = this.chunks.indexOf(oldChunk);
4134
- if (index === -1)
4135
- return this;
4136
- let newChunks;
4137
- if (index === this.chunks.length - 1) {
4138
- newChunks = [...this.chunks.slice(0, -1), chunk];
4139
- } else {
4140
- newChunks = [...this.chunks.slice(0, index), chunk, ...this.chunks.slice(index + 1)];
4141
- }
4142
- this.chunks = newChunks;
4143
- }
4144
- return this;
4145
- }
4146
4207
  }
4147
4208
  function stringToStyledText(content) {
4148
4209
  const chunk = {
@@ -4238,7 +4299,36 @@ function t(strings, ...values) {
4238
4299
  return new StyledText(chunks);
4239
4300
  }
4240
4301
 
4241
- // src/lib/hast-styled-text.ts
4302
+ // src/lib/syntax-style.ts
4303
+ function convertThemeToStyles(theme) {
4304
+ const flatStyles = {};
4305
+ for (const tokenStyle of theme) {
4306
+ const styleDefinition = {};
4307
+ if (tokenStyle.style.foreground) {
4308
+ styleDefinition.fg = parseColor(tokenStyle.style.foreground);
4309
+ }
4310
+ if (tokenStyle.style.background) {
4311
+ styleDefinition.bg = parseColor(tokenStyle.style.background);
4312
+ }
4313
+ if (tokenStyle.style.bold !== undefined) {
4314
+ styleDefinition.bold = tokenStyle.style.bold;
4315
+ }
4316
+ if (tokenStyle.style.italic !== undefined) {
4317
+ styleDefinition.italic = tokenStyle.style.italic;
4318
+ }
4319
+ if (tokenStyle.style.underline !== undefined) {
4320
+ styleDefinition.underline = tokenStyle.style.underline;
4321
+ }
4322
+ if (tokenStyle.style.dim !== undefined) {
4323
+ styleDefinition.dim = tokenStyle.style.dim;
4324
+ }
4325
+ for (const scope of tokenStyle.scope) {
4326
+ flatStyles[scope] = styleDefinition;
4327
+ }
4328
+ }
4329
+ return flatStyles;
4330
+ }
4331
+
4242
4332
  class SyntaxStyle {
4243
4333
  styles;
4244
4334
  mergedStyleCache;
@@ -4246,6 +4336,10 @@ class SyntaxStyle {
4246
4336
  this.styles = styles;
4247
4337
  this.mergedStyleCache = new Map;
4248
4338
  }
4339
+ static fromTheme(theme) {
4340
+ const flatStyles = convertThemeToStyles(theme);
4341
+ return new SyntaxStyle(flatStyles);
4342
+ }
4249
4343
  mergeStyles(...styleNames) {
4250
4344
  const cacheKey = styleNames.join(":");
4251
4345
  const cached = this.mergedStyleCache.get(cacheKey);
@@ -4253,7 +4347,7 @@ class SyntaxStyle {
4253
4347
  return cached;
4254
4348
  const styleDefinition = {};
4255
4349
  for (const name of styleNames) {
4256
- const style = this.styles[name];
4350
+ const style = this.getStyle(name);
4257
4351
  if (!style)
4258
4352
  continue;
4259
4353
  if (style.fg)
@@ -4283,6 +4377,18 @@ class SyntaxStyle {
4283
4377
  this.mergedStyleCache.set(cacheKey, merged);
4284
4378
  return merged;
4285
4379
  }
4380
+ getStyle(name) {
4381
+ if (Object.prototype.hasOwnProperty.call(this.styles, name)) {
4382
+ return this.styles[name];
4383
+ }
4384
+ if (name.includes(".")) {
4385
+ const baseName = name.split(".")[0];
4386
+ if (Object.prototype.hasOwnProperty.call(this.styles, baseName)) {
4387
+ return this.styles[baseName];
4388
+ }
4389
+ }
4390
+ return;
4391
+ }
4286
4392
  clearCache() {
4287
4393
  this.mergedStyleCache.clear();
4288
4394
  }
@@ -4290,6 +4396,8 @@ class SyntaxStyle {
4290
4396
  return this.mergedStyleCache.size;
4291
4397
  }
4292
4398
  }
4399
+
4400
+ // src/lib/hast-styled-text.ts
4293
4401
  function hastToTextChunks(node, syntaxStyle, parentStyles = []) {
4294
4402
  const chunks = [];
4295
4403
  if (node.type === "text") {
@@ -4321,6 +4429,55 @@ function hastToStyledText(hast, syntaxStyle) {
4321
4429
  return new StyledText(chunks);
4322
4430
  }
4323
4431
 
4432
+ // src/lib/scroll-acceleration.ts
4433
+ class LinearScrollAccel {
4434
+ tick(_now) {
4435
+ return 1;
4436
+ }
4437
+ reset() {}
4438
+ }
4439
+
4440
+ class MacOSScrollAccel {
4441
+ opts;
4442
+ lastTickTime = 0;
4443
+ velocityHistory = [];
4444
+ historySize = 3;
4445
+ streakTimeout = 150;
4446
+ minTickInterval = 6;
4447
+ constructor(opts = {}) {
4448
+ this.opts = opts;
4449
+ }
4450
+ tick(now = Date.now()) {
4451
+ const A = this.opts.A ?? 0.8;
4452
+ const tau = this.opts.tau ?? 3;
4453
+ const maxMultiplier = this.opts.maxMultiplier ?? 6;
4454
+ const dt = this.lastTickTime ? now - this.lastTickTime : Infinity;
4455
+ if (dt === Infinity || dt > this.streakTimeout) {
4456
+ this.lastTickTime = now;
4457
+ this.velocityHistory = [];
4458
+ return 1;
4459
+ }
4460
+ if (dt < this.minTickInterval) {
4461
+ return 1;
4462
+ }
4463
+ this.lastTickTime = now;
4464
+ this.velocityHistory.push(dt);
4465
+ if (this.velocityHistory.length > this.historySize) {
4466
+ this.velocityHistory.shift();
4467
+ }
4468
+ const avgInterval = this.velocityHistory.reduce((a, b) => a + b, 0) / this.velocityHistory.length;
4469
+ const referenceInterval = 100;
4470
+ const velocity = referenceInterval / avgInterval;
4471
+ const x = velocity / tau;
4472
+ const multiplier = 1 + A * (Math.exp(x) - 1);
4473
+ return Math.min(multiplier, maxMultiplier);
4474
+ }
4475
+ reset() {
4476
+ this.lastTickTime = 0;
4477
+ this.velocityHistory = [];
4478
+ }
4479
+ }
4480
+
4324
4481
  // src/lib/yoga.options.ts
4325
4482
  function parseAlign(value) {
4326
4483
  switch (value.toLowerCase()) {
@@ -4824,9 +4981,19 @@ function singleton(key, factory) {
4824
4981
  }
4825
4982
  return bag[key];
4826
4983
  }
4984
+ function destroySingleton(key) {
4985
+ const bag = globalThis[singletonCacheSymbol];
4986
+ if (bag && key in bag) {
4987
+ delete bag[key];
4988
+ }
4989
+ }
4990
+ function hasSingleton(key) {
4991
+ const bag = globalThis[singletonCacheSymbol];
4992
+ return bag && key in bag;
4993
+ }
4827
4994
 
4828
4995
  // src/lib/env.ts
4829
- var envRegistry = {};
4996
+ var envRegistry = singleton("env-registry", () => ({}));
4830
4997
  function registerEnvVar(config) {
4831
4998
  const existing = envRegistry[config.name];
4832
4999
  if (existing) {
@@ -4884,8 +5051,14 @@ class EnvStore {
4884
5051
  has(key) {
4885
5052
  return key in envRegistry;
4886
5053
  }
5054
+ clearCache() {
5055
+ this.parsedValues.clear();
5056
+ }
4887
5057
  }
4888
5058
  var envStore = singleton("env-store", () => new EnvStore);
5059
+ function clearEnvCache() {
5060
+ envStore.clearCache();
5061
+ }
4889
5062
  function generateEnvMarkdown() {
4890
5063
  const configs = Object.values(envRegistry);
4891
5064
  if (configs.length === 0) {
@@ -4974,9 +5147,1115 @@ var env = new Proxy({}, {
4974
5147
  return;
4975
5148
  }
4976
5149
  });
5150
+
5151
+ // src/lib/tree-sitter-styled-text.ts
5152
+ function treeSitterToTextChunks(content, highlights, syntaxStyle) {
5153
+ const chunks = [];
5154
+ const defaultStyle = syntaxStyle.getStyle("default");
5155
+ let currentIndex = 0;
5156
+ for (let i = 0;i < highlights.length; i++) {
5157
+ const [startIndex, endIndex, group] = highlights[i];
5158
+ if (startIndex < currentIndex)
5159
+ continue;
5160
+ if (currentIndex < startIndex) {
5161
+ const text2 = content.slice(currentIndex, startIndex);
5162
+ chunks.push({
5163
+ __isChunk: true,
5164
+ text: text2,
5165
+ fg: defaultStyle?.fg,
5166
+ bg: defaultStyle?.bg,
5167
+ attributes: defaultStyle ? createTextAttributes({
5168
+ bold: defaultStyle.bold,
5169
+ italic: defaultStyle.italic,
5170
+ underline: defaultStyle.underline,
5171
+ dim: defaultStyle.dim
5172
+ }) : 0
5173
+ });
5174
+ currentIndex = startIndex;
5175
+ }
5176
+ let resolvedStyle = syntaxStyle.getStyle(group);
5177
+ let j = i + 1;
5178
+ while (j < highlights.length && highlights[j][0] === startIndex) {
5179
+ const [, , nextGroup] = highlights[j];
5180
+ const nextStyle = syntaxStyle.getStyle(nextGroup);
5181
+ if (nextStyle) {
5182
+ resolvedStyle = nextStyle;
5183
+ }
5184
+ j++;
5185
+ }
5186
+ i = j - 1;
5187
+ const text = content.slice(startIndex, endIndex);
5188
+ const styleToUse = resolvedStyle || defaultStyle;
5189
+ chunks.push({
5190
+ __isChunk: true,
5191
+ text,
5192
+ fg: styleToUse?.fg,
5193
+ bg: styleToUse?.bg,
5194
+ attributes: styleToUse ? createTextAttributes({
5195
+ bold: styleToUse.bold,
5196
+ italic: styleToUse.italic,
5197
+ underline: styleToUse.underline,
5198
+ dim: styleToUse.dim
5199
+ }) : 0
5200
+ });
5201
+ currentIndex = endIndex;
5202
+ }
5203
+ if (currentIndex < content.length) {
5204
+ const text = content.slice(currentIndex);
5205
+ chunks.push({
5206
+ __isChunk: true,
5207
+ text,
5208
+ fg: defaultStyle?.fg,
5209
+ bg: defaultStyle?.bg,
5210
+ attributes: defaultStyle ? createTextAttributes({
5211
+ bold: defaultStyle.bold,
5212
+ italic: defaultStyle.italic,
5213
+ underline: defaultStyle.underline,
5214
+ dim: defaultStyle.dim
5215
+ }) : 0
5216
+ });
5217
+ }
5218
+ return chunks;
5219
+ }
5220
+ async function treeSitterToStyledText(content, filetype, syntaxStyle, client) {
5221
+ const result = await client.highlightOnce(content, filetype);
5222
+ if (result.highlights && result.highlights.length > 0) {
5223
+ const chunks = treeSitterToTextChunks(content, result.highlights, syntaxStyle);
5224
+ return new StyledText(chunks);
5225
+ } else {
5226
+ const defaultStyle = syntaxStyle.mergeStyles("default");
5227
+ const chunks = [
5228
+ {
5229
+ __isChunk: true,
5230
+ text: content,
5231
+ fg: defaultStyle.fg,
5232
+ bg: defaultStyle.bg,
5233
+ attributes: defaultStyle.attributes
5234
+ }
5235
+ ];
5236
+ return new StyledText(chunks);
5237
+ }
5238
+ }
5239
+
5240
+ // src/lib/tree-sitter/client.ts
5241
+ import { EventEmitter as EventEmitter2 } from "events";
5242
+
5243
+ // src/lib/debounce.ts
5244
+ var TIMERS_MAP = new Map;
5245
+
5246
+ class DebounceController {
5247
+ scopeId;
5248
+ constructor(scopeId) {
5249
+ this.scopeId = scopeId;
5250
+ if (!TIMERS_MAP.has(this.scopeId)) {
5251
+ TIMERS_MAP.set(this.scopeId, new Map);
5252
+ }
5253
+ }
5254
+ debounce(id, ms, fn) {
5255
+ const scopeMap = TIMERS_MAP.get(this.scopeId);
5256
+ return new Promise((resolve, reject) => {
5257
+ if (scopeMap.has(id)) {
5258
+ clearTimeout(scopeMap.get(id));
5259
+ }
5260
+ const timerId = setTimeout(() => {
5261
+ try {
5262
+ resolve(fn());
5263
+ } catch (error) {
5264
+ reject(error);
5265
+ }
5266
+ scopeMap.delete(id);
5267
+ }, ms);
5268
+ scopeMap.set(id, timerId);
5269
+ });
5270
+ }
5271
+ clearDebounce(id) {
5272
+ const scopeMap = TIMERS_MAP.get(this.scopeId);
5273
+ if (scopeMap && scopeMap.has(id)) {
5274
+ clearTimeout(scopeMap.get(id));
5275
+ scopeMap.delete(id);
5276
+ }
5277
+ }
5278
+ clear() {
5279
+ const scopeMap = TIMERS_MAP.get(this.scopeId);
5280
+ if (scopeMap) {
5281
+ scopeMap.forEach((timerId) => clearTimeout(timerId));
5282
+ scopeMap.clear();
5283
+ }
5284
+ }
5285
+ }
5286
+ function createDebounce(scopeId) {
5287
+ return new DebounceController(scopeId);
5288
+ }
5289
+ function clearDebounceScope(scopeId) {
5290
+ const scopeMap = TIMERS_MAP.get(scopeId);
5291
+ if (scopeMap) {
5292
+ scopeMap.forEach((timerId) => clearTimeout(timerId));
5293
+ scopeMap.clear();
5294
+ }
5295
+ }
5296
+
5297
+ // src/lib/queue.ts
5298
+ class ProcessQueue {
5299
+ processor;
5300
+ queue = [];
5301
+ processing = false;
5302
+ autoProcess = true;
5303
+ constructor(processor, autoProcess = true) {
5304
+ this.processor = processor;
5305
+ this.autoProcess = autoProcess;
5306
+ }
5307
+ enqueue(item) {
5308
+ this.queue.push(item);
5309
+ if (!this.processing && this.autoProcess) {
5310
+ this.processQueue();
5311
+ }
5312
+ }
5313
+ processQueue() {
5314
+ if (this.queue.length === 0) {
5315
+ return;
5316
+ }
5317
+ this.processing = true;
5318
+ queueMicrotask(async () => {
5319
+ if (this.queue.length === 0) {
5320
+ this.processing = false;
5321
+ return;
5322
+ }
5323
+ const item = this.queue.shift();
5324
+ try {
5325
+ await this.processor(item);
5326
+ } catch (error) {
5327
+ console.error("Error processing queue item:", error);
5328
+ }
5329
+ if (this.queue.length > 0) {
5330
+ this.processQueue();
5331
+ } else {
5332
+ this.processing = false;
5333
+ }
5334
+ });
5335
+ }
5336
+ clear() {
5337
+ this.queue = [];
5338
+ }
5339
+ isProcessing() {
5340
+ return this.processing;
5341
+ }
5342
+ size() {
5343
+ return this.queue.length;
5344
+ }
5345
+ }
5346
+
5347
+ // src/lib/tree-sitter/default-parsers.ts
5348
+ import { resolve, dirname } from "path";
5349
+ import { fileURLToPath } from "url";
5350
+ import javascript_highlights from "./assets/javascript/highlights.scm" with { type: "file" };
5351
+ import javascript_language from "./assets/javascript/tree-sitter-javascript.wasm" with { type: "file" };
5352
+ import typescript_highlights from "./assets/typescript/highlights.scm" with { type: "file" };
5353
+ import typescript_language from "./assets/typescript/tree-sitter-typescript.wasm" with { type: "file" };
5354
+ var _cachedParsers;
5355
+ function getParsers() {
5356
+ if (!_cachedParsers) {
5357
+ _cachedParsers = [
5358
+ {
5359
+ filetype: "javascript",
5360
+ queries: {
5361
+ highlights: [resolve(dirname(fileURLToPath(import.meta.url)), javascript_highlights)]
5362
+ },
5363
+ wasm: resolve(dirname(fileURLToPath(import.meta.url)), javascript_language)
5364
+ },
5365
+ {
5366
+ filetype: "typescript",
5367
+ queries: {
5368
+ highlights: [resolve(dirname(fileURLToPath(import.meta.url)), typescript_highlights)]
5369
+ },
5370
+ wasm: resolve(dirname(fileURLToPath(import.meta.url)), typescript_language)
5371
+ }
5372
+ ];
5373
+ }
5374
+ return _cachedParsers;
5375
+ }
5376
+
5377
+ // src/lib/tree-sitter/client.ts
5378
+ import { resolve as resolve2, isAbsolute } from "path";
5379
+ import { existsSync } from "fs";
5380
+ import { parse } from "path";
5381
+ registerEnvVar({
5382
+ name: "OTUI_TREE_SITTER_WORKER_PATH",
5383
+ description: "Path to the TreeSitter worker",
5384
+ type: "string",
5385
+ default: ""
5386
+ });
5387
+ var DEFAULT_PARSERS = getParsers();
5388
+ function addDefaultParsers(parsers) {
5389
+ for (const parser of parsers) {
5390
+ const existingIndex = DEFAULT_PARSERS.findIndex((p) => p.filetype === parser.filetype);
5391
+ if (existingIndex >= 0) {
5392
+ DEFAULT_PARSERS[existingIndex] = parser;
5393
+ } else {
5394
+ DEFAULT_PARSERS.push(parser);
5395
+ }
5396
+ }
5397
+ }
5398
+ var isUrl = (path) => path.startsWith("http://") || path.startsWith("https://");
5399
+
5400
+ class TreeSitterClient extends EventEmitter2 {
5401
+ initialized = false;
5402
+ worker;
5403
+ buffers = new Map;
5404
+ initializePromise;
5405
+ initializeResolvers;
5406
+ messageCallbacks = new Map;
5407
+ messageIdCounter = 0;
5408
+ editQueues = new Map;
5409
+ debouncer;
5410
+ options;
5411
+ constructor(options) {
5412
+ super();
5413
+ this.options = options;
5414
+ this.debouncer = createDebounce("tree-sitter-client");
5415
+ this.startWorker();
5416
+ }
5417
+ emitError(error, bufferId) {
5418
+ if (this.listenerCount("error") > 0) {
5419
+ this.emit("error", error, bufferId);
5420
+ }
5421
+ }
5422
+ emitWarning(warning, bufferId) {
5423
+ if (this.listenerCount("warning") > 0) {
5424
+ this.emit("warning", warning, bufferId);
5425
+ }
5426
+ }
5427
+ startWorker() {
5428
+ if (this.worker) {
5429
+ return;
5430
+ }
5431
+ let worker_path;
5432
+ if (env.OTUI_TREE_SITTER_WORKER_PATH) {
5433
+ worker_path = env.OTUI_TREE_SITTER_WORKER_PATH;
5434
+ } else if (typeof OTUI_TREE_SITTER_WORKER_PATH !== "undefined") {
5435
+ worker_path = OTUI_TREE_SITTER_WORKER_PATH;
5436
+ } else if (this.options.workerPath) {
5437
+ worker_path = this.options.workerPath;
5438
+ } else {
5439
+ worker_path = new URL("./parser.worker.js", import.meta.url).href;
5440
+ if (!existsSync(resolve2(import.meta.dirname, "parser.worker.js"))) {
5441
+ worker_path = new URL("./parser.worker.ts", import.meta.url).href;
5442
+ }
5443
+ }
5444
+ this.worker = new Worker(worker_path);
5445
+ this.worker.onmessage = this.handleWorkerMessage.bind(this);
5446
+ this.worker.onerror = (error) => {
5447
+ console.error("TreeSitter worker error:", error.message);
5448
+ if (this.initializeResolvers) {
5449
+ clearTimeout(this.initializeResolvers.timeoutId);
5450
+ this.initializeResolvers.reject(new Error(`Worker error: ${error.message}`));
5451
+ this.initializeResolvers = undefined;
5452
+ }
5453
+ this.emitError(`Worker error: ${error.message}`);
5454
+ };
5455
+ }
5456
+ stopWorker() {
5457
+ if (!this.worker) {
5458
+ return;
5459
+ }
5460
+ this.worker.terminate();
5461
+ this.worker = undefined;
5462
+ }
5463
+ handleReset() {
5464
+ this.buffers.clear();
5465
+ this.stopWorker();
5466
+ this.startWorker();
5467
+ this.initializePromise = undefined;
5468
+ this.initializeResolvers = undefined;
5469
+ return this.initialize();
5470
+ }
5471
+ async initialize() {
5472
+ if (this.initializePromise) {
5473
+ return this.initializePromise;
5474
+ }
5475
+ this.initializePromise = new Promise((resolve3, reject) => {
5476
+ const timeoutMs = this.options.initTimeout ?? 1e4;
5477
+ const timeoutId = setTimeout(() => {
5478
+ const error = new Error("Worker initialization timed out");
5479
+ console.error("TreeSitter client:", error.message);
5480
+ this.initializeResolvers = undefined;
5481
+ reject(error);
5482
+ }, timeoutMs);
5483
+ this.initializeResolvers = { resolve: resolve3, reject, timeoutId };
5484
+ this.worker?.postMessage({
5485
+ type: "INIT",
5486
+ dataPath: this.options.dataPath
5487
+ });
5488
+ });
5489
+ await this.initializePromise;
5490
+ await this.registerDefaultParsers();
5491
+ return this.initializePromise;
5492
+ }
5493
+ async registerDefaultParsers() {
5494
+ for (const parser of DEFAULT_PARSERS) {
5495
+ this.addFiletypeParser(parser);
5496
+ }
5497
+ }
5498
+ resolvePath(path) {
5499
+ if (isUrl(path)) {
5500
+ return path;
5501
+ }
5502
+ if (/\$bunfs/.test(path)) {
5503
+ return "/$bunfs/root/" + parse(path).base;
5504
+ }
5505
+ if (!isAbsolute(path)) {
5506
+ return resolve2(path);
5507
+ }
5508
+ return path;
5509
+ }
5510
+ addFiletypeParser(filetypeParser) {
5511
+ const resolvedParser = {
5512
+ ...filetypeParser,
5513
+ wasm: this.resolvePath(filetypeParser.wasm),
5514
+ queries: {
5515
+ highlights: filetypeParser.queries.highlights.map((path) => this.resolvePath(path))
5516
+ }
5517
+ };
5518
+ this.worker?.postMessage({ type: "ADD_FILETYPE_PARSER", filetypeParser: resolvedParser });
5519
+ }
5520
+ async getPerformance() {
5521
+ const messageId = `performance_${this.messageIdCounter++}`;
5522
+ return new Promise((resolve3) => {
5523
+ this.messageCallbacks.set(messageId, resolve3);
5524
+ this.worker?.postMessage({ type: "GET_PERFORMANCE", messageId });
5525
+ });
5526
+ }
5527
+ async highlightOnce(content, filetype) {
5528
+ if (!this.initialized) {
5529
+ try {
5530
+ await this.initialize();
5531
+ } catch (error) {
5532
+ return { error: "Could not highlight because of initialization error" };
5533
+ }
5534
+ }
5535
+ const messageId = `oneshot_${this.messageIdCounter++}`;
5536
+ return new Promise((resolve3) => {
5537
+ this.messageCallbacks.set(messageId, resolve3);
5538
+ this.worker?.postMessage({
5539
+ type: "ONESHOT_HIGHLIGHT",
5540
+ content,
5541
+ filetype,
5542
+ messageId
5543
+ });
5544
+ });
5545
+ }
5546
+ handleWorkerMessage(event) {
5547
+ const { type, bufferId, error, highlights, warning, messageId, hasParser, performance: performance2, version } = event.data;
5548
+ if (type === "HIGHLIGHT_RESPONSE") {
5549
+ const buffer = this.buffers.get(bufferId);
5550
+ if (!buffer || !buffer.hasParser)
5551
+ return;
5552
+ if (buffer.version !== version) {
5553
+ this.resetBuffer(bufferId, buffer.version, buffer.content);
5554
+ return;
5555
+ }
5556
+ this.emit("highlights:response", bufferId, version, highlights);
5557
+ }
5558
+ if (type === "INIT_RESPONSE") {
5559
+ if (this.initializeResolvers) {
5560
+ clearTimeout(this.initializeResolvers.timeoutId);
5561
+ if (error) {
5562
+ console.error("TreeSitter client initialization failed:", error);
5563
+ this.initializeResolvers.reject(new Error(error));
5564
+ } else {
5565
+ this.initialized = true;
5566
+ this.initializeResolvers.resolve();
5567
+ }
5568
+ this.initializeResolvers = undefined;
5569
+ return;
5570
+ }
5571
+ }
5572
+ if (type === "PARSER_INIT_RESPONSE") {
5573
+ const callback = this.messageCallbacks.get(messageId);
5574
+ if (callback) {
5575
+ this.messageCallbacks.delete(messageId);
5576
+ callback({ hasParser, warning, error });
5577
+ }
5578
+ return;
5579
+ }
5580
+ if (type === "PRELOAD_PARSER_RESPONSE") {
5581
+ const callback = this.messageCallbacks.get(messageId);
5582
+ if (callback) {
5583
+ this.messageCallbacks.delete(messageId);
5584
+ callback({ hasParser });
5585
+ }
5586
+ return;
5587
+ }
5588
+ if (type === "BUFFER_DISPOSED") {
5589
+ const callback = this.messageCallbacks.get(`dispose_${bufferId}`);
5590
+ if (callback) {
5591
+ this.messageCallbacks.delete(`dispose_${bufferId}`);
5592
+ callback(true);
5593
+ }
5594
+ this.emit("buffer:disposed", bufferId);
5595
+ return;
5596
+ }
5597
+ if (type === "PERFORMANCE_RESPONSE") {
5598
+ const callback = this.messageCallbacks.get(messageId);
5599
+ if (callback) {
5600
+ this.messageCallbacks.delete(messageId);
5601
+ callback(performance2);
5602
+ }
5603
+ return;
5604
+ }
5605
+ if (type === "ONESHOT_HIGHLIGHT_RESPONSE") {
5606
+ const callback = this.messageCallbacks.get(messageId);
5607
+ if (callback) {
5608
+ this.messageCallbacks.delete(messageId);
5609
+ callback({ highlights, warning, error });
5610
+ }
5611
+ return;
5612
+ }
5613
+ if (type === "UPDATE_DATA_PATH_RESPONSE") {
5614
+ const callback = this.messageCallbacks.get(messageId);
5615
+ if (callback) {
5616
+ this.messageCallbacks.delete(messageId);
5617
+ callback({ error });
5618
+ }
5619
+ return;
5620
+ }
5621
+ if (warning) {
5622
+ this.emitWarning(warning, bufferId);
5623
+ return;
5624
+ }
5625
+ if (error) {
5626
+ this.emitError(error, bufferId);
5627
+ return;
5628
+ }
5629
+ if (type === "WORKER_LOG") {
5630
+ const { logType, data } = event.data;
5631
+ const message = data.join(" ");
5632
+ this.emit("worker:log", logType, message);
5633
+ if (logType === "log") {
5634
+ console.log("Worker stdout:", ...data);
5635
+ } else if (logType === "error") {
5636
+ console.error("Worker stderr:", ...data);
5637
+ }
5638
+ return;
5639
+ }
5640
+ }
5641
+ async preloadParser(filetype) {
5642
+ const messageId = `has_parser_${this.messageIdCounter++}`;
5643
+ const response = await new Promise((resolve3) => {
5644
+ this.messageCallbacks.set(messageId, resolve3);
5645
+ this.worker?.postMessage({
5646
+ type: "PRELOAD_PARSER",
5647
+ filetype,
5648
+ messageId
5649
+ });
5650
+ });
5651
+ return response.hasParser;
5652
+ }
5653
+ async createBuffer(id, content, filetype, version = 1, autoInitialize = true) {
5654
+ if (!this.initialized) {
5655
+ if (!autoInitialize) {
5656
+ this.emitError("Could not create buffer because client is not initialized");
5657
+ return false;
5658
+ }
5659
+ try {
5660
+ await this.initialize();
5661
+ } catch (error) {
5662
+ this.emitError("Could not create buffer because of initialization error");
5663
+ return false;
5664
+ }
5665
+ }
5666
+ if (this.buffers.has(id)) {
5667
+ throw new Error(`Buffer with id ${id} already exists`);
5668
+ }
5669
+ this.buffers.set(id, { id, content, filetype, version, hasParser: false });
5670
+ const messageId = `init_${this.messageIdCounter++}`;
5671
+ const response = await new Promise((resolve3) => {
5672
+ this.messageCallbacks.set(messageId, resolve3);
5673
+ this.worker?.postMessage({
5674
+ type: "INITIALIZE_PARSER",
5675
+ bufferId: id,
5676
+ version,
5677
+ content,
5678
+ filetype,
5679
+ messageId
5680
+ });
5681
+ });
5682
+ if (!response.hasParser) {
5683
+ this.emit("buffer:initialized", id, false);
5684
+ if (filetype !== "plaintext") {
5685
+ this.emitWarning(response.warning || response.error || "Buffer has no parser", id);
5686
+ }
5687
+ return false;
5688
+ }
5689
+ const bufferState = { id, content, filetype, version, hasParser: true };
5690
+ this.buffers.set(id, bufferState);
5691
+ this.emit("buffer:initialized", id, true);
5692
+ return true;
5693
+ }
5694
+ async updateBuffer(id, edits, newContent, version) {
5695
+ if (!this.initialized) {
5696
+ return;
5697
+ }
5698
+ const buffer = this.buffers.get(id);
5699
+ if (!buffer || !buffer.hasParser) {
5700
+ return;
5701
+ }
5702
+ this.buffers.set(id, { ...buffer, content: newContent, version });
5703
+ if (!this.editQueues.has(id)) {
5704
+ this.editQueues.set(id, new ProcessQueue((item) => this.processEdit(id, item.edits, item.newContent, item.version, item.isReset)));
5705
+ }
5706
+ const bufferQueue = this.editQueues.get(id);
5707
+ bufferQueue.enqueue({ edits, newContent, version });
5708
+ }
5709
+ async processEdit(bufferId, edits, newContent, version, isReset = false) {
5710
+ this.worker?.postMessage({
5711
+ type: isReset ? "RESET_BUFFER" : "HANDLE_EDITS",
5712
+ bufferId,
5713
+ version,
5714
+ content: newContent,
5715
+ edits
5716
+ });
5717
+ }
5718
+ async removeBuffer(bufferId) {
5719
+ if (!this.initialized) {
5720
+ return;
5721
+ }
5722
+ this.buffers.delete(bufferId);
5723
+ if (this.editQueues.has(bufferId)) {
5724
+ this.editQueues.get(bufferId)?.clear();
5725
+ this.editQueues.delete(bufferId);
5726
+ }
5727
+ if (this.worker) {
5728
+ await new Promise((resolve3) => {
5729
+ const messageId = `dispose_${bufferId}`;
5730
+ this.messageCallbacks.set(messageId, resolve3);
5731
+ try {
5732
+ this.worker.postMessage({
5733
+ type: "DISPOSE_BUFFER",
5734
+ bufferId
5735
+ });
5736
+ } catch (error) {
5737
+ console.error("Error disposing buffer", error);
5738
+ resolve3(false);
5739
+ }
5740
+ setTimeout(() => {
5741
+ if (this.messageCallbacks.has(messageId)) {
5742
+ this.messageCallbacks.delete(messageId);
5743
+ console.warn({ bufferId }, "Timed out waiting for buffer to be disposed");
5744
+ resolve3(false);
5745
+ }
5746
+ }, 3000);
5747
+ });
5748
+ }
5749
+ this.debouncer.clearDebounce(`reset-${bufferId}`);
5750
+ }
5751
+ async destroy() {
5752
+ if (this.initializeResolvers) {
5753
+ clearTimeout(this.initializeResolvers.timeoutId);
5754
+ this.initializeResolvers = undefined;
5755
+ }
5756
+ for (const [messageId, callback] of this.messageCallbacks.entries()) {
5757
+ if (typeof callback === "function") {
5758
+ try {
5759
+ callback({ error: "Client destroyed" });
5760
+ } catch (e) {}
5761
+ }
5762
+ }
5763
+ this.messageCallbacks.clear();
5764
+ clearDebounceScope("tree-sitter-client");
5765
+ this.debouncer.clear();
5766
+ this.editQueues.clear();
5767
+ this.buffers.clear();
5768
+ this.stopWorker();
5769
+ this.initialized = false;
5770
+ this.initializePromise = undefined;
5771
+ }
5772
+ async resetBuffer(bufferId, version, content) {
5773
+ if (!this.initialized) {
5774
+ return;
5775
+ }
5776
+ const buffer = this.buffers.get(bufferId);
5777
+ if (!buffer || !buffer.hasParser) {
5778
+ this.emitError("Cannot reset buffer with no parser", bufferId);
5779
+ return;
5780
+ }
5781
+ this.buffers.set(bufferId, { ...buffer, content, version });
5782
+ this.debouncer.debounce(`reset-${bufferId}`, 10, () => this.processEdit(bufferId, [], content, version, true));
5783
+ }
5784
+ getBuffer(bufferId) {
5785
+ return this.buffers.get(bufferId);
5786
+ }
5787
+ getAllBuffers() {
5788
+ return Array.from(this.buffers.values());
5789
+ }
5790
+ isInitialized() {
5791
+ return this.initialized;
5792
+ }
5793
+ async setDataPath(dataPath) {
5794
+ if (this.options.dataPath === dataPath) {
5795
+ return;
5796
+ }
5797
+ this.options.dataPath = dataPath;
5798
+ if (this.initialized && this.worker) {
5799
+ const messageId = `update_datapath_${this.messageIdCounter++}`;
5800
+ return new Promise((resolve3, reject) => {
5801
+ this.messageCallbacks.set(messageId, (response) => {
5802
+ if (response.error) {
5803
+ reject(new Error(response.error));
5804
+ } else {
5805
+ resolve3();
5806
+ }
5807
+ });
5808
+ this.worker.postMessage({
5809
+ type: "UPDATE_DATA_PATH",
5810
+ dataPath,
5811
+ messageId
5812
+ });
5813
+ });
5814
+ }
5815
+ }
5816
+ }
5817
+
5818
+ // src/lib/data-paths.ts
5819
+ import os from "os";
5820
+ import path from "path";
5821
+ import { EventEmitter as EventEmitter3 } from "events";
5822
+
5823
+ // src/lib/validate-dir-name.ts
5824
+ function isValidDirectoryName(name) {
5825
+ if (!name || typeof name !== "string") {
5826
+ return false;
5827
+ }
5828
+ if (name.trim().length === 0) {
5829
+ return false;
5830
+ }
5831
+ const reservedNames = [
5832
+ "CON",
5833
+ "PRN",
5834
+ "AUX",
5835
+ "NUL",
5836
+ "COM1",
5837
+ "COM2",
5838
+ "COM3",
5839
+ "COM4",
5840
+ "COM5",
5841
+ "COM6",
5842
+ "COM7",
5843
+ "COM8",
5844
+ "COM9",
5845
+ "LPT1",
5846
+ "LPT2",
5847
+ "LPT3",
5848
+ "LPT4",
5849
+ "LPT5",
5850
+ "LPT6",
5851
+ "LPT7",
5852
+ "LPT8",
5853
+ "LPT9"
5854
+ ];
5855
+ if (reservedNames.includes(name.toUpperCase())) {
5856
+ return false;
5857
+ }
5858
+ const invalidChars = /[<>:"|?*\/\\\x00-\x1f]/;
5859
+ if (invalidChars.test(name)) {
5860
+ return false;
5861
+ }
5862
+ if (name.endsWith(".") || name.endsWith(" ")) {
5863
+ return false;
5864
+ }
5865
+ if (name === "." || name === "..") {
5866
+ return false;
5867
+ }
5868
+ return true;
5869
+ }
5870
+
5871
+ // src/lib/data-paths.ts
5872
+ registerEnvVar({
5873
+ name: "XDG_CONFIG_HOME",
5874
+ description: "Base directory for user-specific configuration files",
5875
+ type: "string",
5876
+ default: ""
5877
+ });
5878
+ registerEnvVar({
5879
+ name: "XDG_DATA_HOME",
5880
+ description: "Base directory for user-specific data files",
5881
+ type: "string",
5882
+ default: ""
5883
+ });
5884
+
5885
+ class DataPathsManager extends EventEmitter3 {
5886
+ _appName;
5887
+ _globalConfigPath;
5888
+ _globalConfigFile;
5889
+ _localConfigFile;
5890
+ _globalDataPath;
5891
+ constructor() {
5892
+ super();
5893
+ this._appName = "opentui";
5894
+ }
5895
+ get appName() {
5896
+ return this._appName;
5897
+ }
5898
+ set appName(value) {
5899
+ if (!isValidDirectoryName(value)) {
5900
+ throw new Error(`Invalid app name "${value}": must be a valid directory name`);
5901
+ }
5902
+ if (this._appName !== value) {
5903
+ this._appName = value;
5904
+ this._globalConfigPath = undefined;
5905
+ this._globalConfigFile = undefined;
5906
+ this._localConfigFile = undefined;
5907
+ this._globalDataPath = undefined;
5908
+ this.emit("paths:changed", this.toObject());
5909
+ }
5910
+ }
5911
+ get globalConfigPath() {
5912
+ if (this._globalConfigPath === undefined) {
5913
+ const homeDir = os.homedir();
5914
+ const xdgConfigHome = env.XDG_CONFIG_HOME;
5915
+ const baseConfigDir = xdgConfigHome || path.join(homeDir, ".config");
5916
+ this._globalConfigPath = path.join(baseConfigDir, this._appName);
5917
+ }
5918
+ return this._globalConfigPath;
5919
+ }
5920
+ get globalConfigFile() {
5921
+ if (this._globalConfigFile === undefined) {
5922
+ this._globalConfigFile = path.join(this.globalConfigPath, "init.ts");
5923
+ }
5924
+ return this._globalConfigFile;
5925
+ }
5926
+ get localConfigFile() {
5927
+ if (this._localConfigFile === undefined) {
5928
+ this._localConfigFile = path.join(process.cwd(), `.${this._appName}.ts`);
5929
+ }
5930
+ return this._localConfigFile;
5931
+ }
5932
+ get globalDataPath() {
5933
+ if (this._globalDataPath === undefined) {
5934
+ const homeDir = os.homedir();
5935
+ const xdgDataHome = env.XDG_DATA_HOME;
5936
+ const baseDataDir = xdgDataHome || path.join(homeDir, ".local/share");
5937
+ this._globalDataPath = path.join(baseDataDir, this._appName);
5938
+ }
5939
+ return this._globalDataPath;
5940
+ }
5941
+ toObject() {
5942
+ return {
5943
+ globalConfigPath: this.globalConfigPath,
5944
+ globalConfigFile: this.globalConfigFile,
5945
+ localConfigFile: this.localConfigFile,
5946
+ globalDataPath: this.globalDataPath
5947
+ };
5948
+ }
5949
+ }
5950
+ function getDataPaths() {
5951
+ return singleton("data-paths-opentui", () => new DataPathsManager);
5952
+ }
5953
+
5954
+ // src/lib/tree-sitter/resolve-ft.ts
5955
+ function extToFiletype(extension) {
5956
+ const extensionToFiletype = new Map([
5957
+ ["js", "javascript"],
5958
+ ["jsx", "javascriptreact"],
5959
+ ["ts", "typescript"],
5960
+ ["tsx", "typescriptreact"],
5961
+ ["md", "markdown"],
5962
+ ["json", "json"],
5963
+ ["py", "python"],
5964
+ ["rb", "ruby"],
5965
+ ["go", "go"],
5966
+ ["rs", "rust"],
5967
+ ["c", "c"],
5968
+ ["cpp", "cpp"],
5969
+ ["h", "c"],
5970
+ ["hpp", "cpp"],
5971
+ ["html", "html"],
5972
+ ["css", "css"],
5973
+ ["scss", "scss"],
5974
+ ["less", "less"],
5975
+ ["sh", "shell"],
5976
+ ["bash", "shell"],
5977
+ ["zsh", "shell"],
5978
+ ["vim", "vim"],
5979
+ ["yaml", "yaml"],
5980
+ ["yml", "yaml"],
5981
+ ["toml", "toml"],
5982
+ ["xml", "xml"],
5983
+ ["zig", "zig"]
5984
+ ]);
5985
+ return extensionToFiletype.get(extension);
5986
+ }
5987
+ function pathToFiletype(path2) {
5988
+ if (typeof path2 !== "string")
5989
+ return;
5990
+ const lastDot = path2.lastIndexOf(".");
5991
+ if (lastDot === -1 || lastDot === path2.length - 1) {
5992
+ return;
5993
+ }
5994
+ const extension = path2.substring(lastDot + 1);
5995
+ return extToFiletype(extension);
5996
+ }
5997
+
5998
+ // src/lib/tree-sitter/assets/update.ts
5999
+ import { readFile, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
6000
+ import * as path3 from "path";
6001
+
6002
+ // src/lib/tree-sitter/download-utils.ts
6003
+ import { mkdir, writeFile } from "fs/promises";
6004
+ import * as path2 from "path";
6005
+
6006
+ class DownloadUtils {
6007
+ static hashUrl(url) {
6008
+ let hash = 0;
6009
+ for (let i = 0;i < url.length; i++) {
6010
+ const char = url.charCodeAt(i);
6011
+ hash = (hash << 5) - hash + char;
6012
+ hash = hash & hash;
6013
+ }
6014
+ return Math.abs(hash).toString(16);
6015
+ }
6016
+ static async downloadOrLoad(source, cacheDir, cacheSubdir, fileExtension, useHashForCache = true, filetype) {
6017
+ const isUrl2 = source.startsWith("http://") || source.startsWith("https://");
6018
+ if (isUrl2) {
6019
+ let cacheFileName;
6020
+ if (useHashForCache) {
6021
+ const hash = this.hashUrl(source);
6022
+ cacheFileName = filetype ? `${filetype}-${hash}${fileExtension}` : `${hash}${fileExtension}`;
6023
+ } else {
6024
+ cacheFileName = path2.basename(source);
6025
+ }
6026
+ const cacheFile = path2.join(cacheDir, cacheSubdir, cacheFileName);
6027
+ await mkdir(path2.dirname(cacheFile), { recursive: true });
6028
+ try {
6029
+ const cachedContent = await Bun.file(cacheFile).arrayBuffer();
6030
+ if (cachedContent.byteLength > 0) {
6031
+ console.log(`Loaded from cache: ${cacheFile} (${source})`);
6032
+ return { content: cachedContent, filePath: cacheFile };
6033
+ }
6034
+ } catch (error) {}
6035
+ try {
6036
+ console.log(`Downloading from URL: ${source}`);
6037
+ const response = await fetch(source);
6038
+ if (!response.ok) {
6039
+ return { error: `Failed to fetch from ${source}: ${response.statusText}` };
6040
+ }
6041
+ const content = await response.arrayBuffer();
6042
+ try {
6043
+ await writeFile(cacheFile, Buffer.from(content));
6044
+ console.log(`Cached: ${source}`);
6045
+ } catch (cacheError) {
6046
+ console.warn(`Failed to cache: ${cacheError}`);
6047
+ }
6048
+ return { content, filePath: cacheFile };
6049
+ } catch (error) {
6050
+ return { error: `Error downloading from ${source}: ${error}` };
6051
+ }
6052
+ } else {
6053
+ try {
6054
+ console.log(`Loading from local path: ${source}`);
6055
+ const content = await Bun.file(source).arrayBuffer();
6056
+ return { content, filePath: source };
6057
+ } catch (error) {
6058
+ return { error: `Error loading from local path ${source}: ${error}` };
6059
+ }
6060
+ }
6061
+ }
6062
+ static async downloadToPath(source, targetPath) {
6063
+ const isUrl2 = source.startsWith("http://") || source.startsWith("https://");
6064
+ await mkdir(path2.dirname(targetPath), { recursive: true });
6065
+ if (isUrl2) {
6066
+ try {
6067
+ console.log(`Downloading from URL: ${source}`);
6068
+ const response = await fetch(source);
6069
+ if (!response.ok) {
6070
+ return { error: `Failed to fetch from ${source}: ${response.statusText}` };
6071
+ }
6072
+ const content = await response.arrayBuffer();
6073
+ await writeFile(targetPath, Buffer.from(content));
6074
+ console.log(`Downloaded: ${source} -> ${targetPath}`);
6075
+ return { content, filePath: targetPath };
6076
+ } catch (error) {
6077
+ return { error: `Error downloading from ${source}: ${error}` };
6078
+ }
6079
+ } else {
6080
+ try {
6081
+ console.log(`Copying from local path: ${source}`);
6082
+ const content = await Bun.file(source).arrayBuffer();
6083
+ await writeFile(targetPath, Buffer.from(content));
6084
+ return { content, filePath: targetPath };
6085
+ } catch (error) {
6086
+ return { error: `Error copying from local path ${source}: ${error}` };
6087
+ }
6088
+ }
6089
+ }
6090
+ static async fetchHighlightQueries(sources, cacheDir, filetype) {
6091
+ const queryPromises = sources.map((source) => this.fetchHighlightQuery(source, cacheDir, filetype));
6092
+ const queryResults = await Promise.all(queryPromises);
6093
+ const validQueries = queryResults.filter((query) => query.trim().length > 0);
6094
+ return validQueries.join(`
6095
+ `);
6096
+ }
6097
+ static async fetchHighlightQuery(source, cacheDir, filetype) {
6098
+ const result = await this.downloadOrLoad(source, cacheDir, "queries", ".scm", true, filetype);
6099
+ if (result.error) {
6100
+ console.error(`Error fetching highlight query from ${source}:`, result.error);
6101
+ return "";
6102
+ }
6103
+ if (result.content) {
6104
+ return new TextDecoder().decode(result.content);
6105
+ }
6106
+ return "";
6107
+ }
6108
+ }
6109
+
6110
+ // src/lib/tree-sitter/assets/update.ts
6111
+ var __dirname = "/Users/runner/work/opentui/opentui/packages/core/src/lib/tree-sitter/assets";
6112
+ function getDefaultOptions() {
6113
+ return {
6114
+ configPath: path3.resolve(__dirname, "../parsers-config.json"),
6115
+ assetsDir: path3.resolve(__dirname),
6116
+ outputPath: path3.resolve(__dirname, "../default-parsers.ts")
6117
+ };
6118
+ }
6119
+ async function loadConfig(configPath) {
6120
+ const configContent = await readFile(configPath, "utf-8");
6121
+ return JSON.parse(configContent);
6122
+ }
6123
+ async function downloadLanguage(filetype, languageUrl, assetsDir, outputPath) {
6124
+ const languageDir = path3.join(assetsDir, filetype);
6125
+ const languageFilename = path3.basename(languageUrl);
6126
+ const languagePath = path3.join(languageDir, languageFilename);
6127
+ const result = await DownloadUtils.downloadToPath(languageUrl, languagePath);
6128
+ if (result.error) {
6129
+ throw new Error(`Failed to download language for ${filetype}: ${result.error}`);
6130
+ }
6131
+ return "./" + path3.relative(path3.dirname(outputPath), languagePath);
6132
+ }
6133
+ async function downloadAndCombineQueries(filetype, queryUrls, assetsDir, outputPath) {
6134
+ const queriesDir = path3.join(assetsDir, filetype);
6135
+ const highlightsPath = path3.join(queriesDir, "highlights.scm");
6136
+ const queryContents = [];
6137
+ for (let i = 0;i < queryUrls.length; i++) {
6138
+ const queryUrl = queryUrls[i];
6139
+ console.log(` Downloading query ${i + 1}/${queryUrls.length}: ${queryUrl}`);
6140
+ try {
6141
+ const response = await fetch(queryUrl);
6142
+ if (!response.ok) {
6143
+ console.warn(`Failed to download query from ${queryUrl}: ${response.statusText}`);
6144
+ continue;
6145
+ }
6146
+ const content = await response.text();
6147
+ if (content.trim()) {
6148
+ queryContents.push(`; Query from: ${queryUrl}
6149
+ ${content}`);
6150
+ console.log(` \u2713 Downloaded ${content.split(`
6151
+ `).length} lines`);
6152
+ }
6153
+ } catch (error) {
6154
+ console.warn(`Failed to download query from ${queryUrl}: ${error}`);
6155
+ continue;
6156
+ }
6157
+ }
6158
+ const combinedContent = queryContents.join(`
6159
+
6160
+ `);
6161
+ await writeFile2(highlightsPath, combinedContent, "utf-8");
6162
+ console.log(` Combined ${queryContents.length} queries into ${highlightsPath}`);
6163
+ return "./" + path3.relative(path3.dirname(outputPath), highlightsPath);
6164
+ }
6165
+ async function generateDefaultParsersFile(parsers, outputPath) {
6166
+ const imports = parsers.map((parser) => {
6167
+ const safeFiletype = parser.filetype.replace(/[^a-zA-Z0-9]/g, "_");
6168
+ return `import ${safeFiletype}_highlights from "${parser.highlightsPath}" with { type: "file" }
6169
+ import ${safeFiletype}_language from "${parser.languagePath}" with { type: "file" }`;
6170
+ }).join(`
6171
+ `);
6172
+ const parserDefinitions = parsers.map((parser) => {
6173
+ const safeFiletype = parser.filetype.replace(/[^a-zA-Z0-9]/g, "_");
6174
+ return ` {
6175
+ filetype: "${parser.filetype}",
6176
+ queries: {
6177
+ highlights: [resolve(dirname(fileURLToPath(import.meta.url)), ${safeFiletype}_highlights)],
6178
+ },
6179
+ wasm: resolve(dirname(fileURLToPath(import.meta.url)), ${safeFiletype}_language),
6180
+ }`;
6181
+ }).join(`,
6182
+ `);
6183
+ const fileContent = `// This file is generated by assets/update.ts - DO NOT EDIT MANUALLY
6184
+ // Run 'bun assets/update.ts' to regenerate this file
6185
+ // Last generated: ${new Date().toISOString()}
6186
+
6187
+ import type { FiletypeParserOptions } from "./types"
6188
+ import { resolve, dirname } from "path"
6189
+ import { fileURLToPath } from "url"
6190
+
6191
+ ${imports}
6192
+
6193
+ // Cached parsers to avoid re-resolving paths on every call
6194
+ let _cachedParsers: FiletypeParserOptions[] | undefined
6195
+
6196
+ export function getParsers(): FiletypeParserOptions[] {
6197
+ if (!_cachedParsers) {
6198
+ _cachedParsers = [
6199
+ ${parserDefinitions},
6200
+ ]
6201
+ }
6202
+ return _cachedParsers
6203
+ }
6204
+ `;
6205
+ await mkdir2(path3.dirname(outputPath), { recursive: true });
6206
+ await writeFile2(outputPath, fileContent, "utf-8");
6207
+ console.log(`Generated ${path3.basename(outputPath)} with ${parsers.length} parsers`);
6208
+ }
6209
+ async function main(options) {
6210
+ const opts = { ...getDefaultOptions(), ...options };
6211
+ try {
6212
+ console.log("Loading parsers configuration...");
6213
+ console.log(` Config: ${opts.configPath}`);
6214
+ console.log(` Assets Dir: ${opts.assetsDir}`);
6215
+ console.log(` Output: ${opts.outputPath}`);
6216
+ const config = await loadConfig(opts.configPath);
6217
+ console.log(`Found ${config.parsers.length} parsers to process`);
6218
+ const generatedParsers = [];
6219
+ for (const parser of config.parsers) {
6220
+ console.log(`Processing ${parser.filetype}...`);
6221
+ console.log(` Downloading language...`);
6222
+ const languagePath = await downloadLanguage(parser.filetype, parser.wasm, opts.assetsDir, opts.outputPath);
6223
+ console.log(` Downloading ${parser.queries.highlights.length} highlight queries...`);
6224
+ const highlightsPath = await downloadAndCombineQueries(parser.filetype, parser.queries.highlights, opts.assetsDir, opts.outputPath);
6225
+ generatedParsers.push({
6226
+ filetype: parser.filetype,
6227
+ languagePath,
6228
+ highlightsPath
6229
+ });
6230
+ console.log(` \u2713 Completed ${parser.filetype}`);
6231
+ }
6232
+ console.log("Generating output file...");
6233
+ await generateDefaultParsersFile(generatedParsers, opts.outputPath);
6234
+ console.log("\u2705 Update completed successfully!");
6235
+ } catch (error) {
6236
+ console.error("\u274C Update failed:", error);
6237
+ process.exit(1);
6238
+ }
6239
+ }
6240
+ if (false) {}
6241
+
6242
+ // src/lib/tree-sitter/index.ts
6243
+ function getTreeSitterClient() {
6244
+ const dataPathsManager = getDataPaths();
6245
+ const defaultOptions = {
6246
+ dataPath: dataPathsManager.globalDataPath
6247
+ };
6248
+ return singleton("tree-sitter-client", () => {
6249
+ const client2 = new TreeSitterClient(defaultOptions);
6250
+ dataPathsManager.on("paths:changed", (paths) => {
6251
+ client2.setDataPath(paths.globalDataPath);
6252
+ });
6253
+ return client2;
6254
+ });
6255
+ }
4977
6256
  // src/zig.ts
4978
6257
  import { dlopen, toArrayBuffer as toArrayBuffer2, JSCallback, ptr } from "bun:ffi";
4979
- import { existsSync } from "fs";
6258
+ import { existsSync as existsSync2 } from "fs";
4980
6259
 
4981
6260
  // src/buffer.ts
4982
6261
  import { toArrayBuffer } from "bun:ffi";
@@ -5177,7 +6456,10 @@ class OptimizedBuffer {
5177
6456
  // src/zig.ts
5178
6457
  var module = await import(`@opentui/core-${process.platform}-${process.arch}/index.ts`);
5179
6458
  var targetLibPath = module.default;
5180
- if (!existsSync(targetLibPath)) {
6459
+ if (/\$bunfs/.test(targetLibPath)) {
6460
+ targetLibPath = targetLibPath.replace("../", "");
6461
+ }
6462
+ if (!existsSync2(targetLibPath)) {
5181
6463
  throw new Error(`opentui is not supported on the current platform: ${process.platform}-${process.arch}`);
5182
6464
  }
5183
6465
  registerEnvVar({
@@ -6281,7 +7563,7 @@ class TextBuffer {
6281
7563
  }
6282
7564
 
6283
7565
  // src/Renderable.ts
6284
- import { EventEmitter as EventEmitter2 } from "events";
7566
+ import { EventEmitter as EventEmitter4 } from "events";
6285
7567
 
6286
7568
  // src/lib/renderable.validations.ts
6287
7569
  function validateOptions(id, options) {
@@ -6374,7 +7656,7 @@ function isRenderable(obj) {
6374
7656
  return !!obj?.[BrandedRenderable];
6375
7657
  }
6376
7658
 
6377
- class BaseRenderable extends EventEmitter2 {
7659
+ class BaseRenderable extends EventEmitter4 {
6378
7660
  [BrandedRenderable] = true;
6379
7661
  static renderableNumber = 1;
6380
7662
  _id;
@@ -6546,18 +7828,18 @@ class Renderable extends BaseRenderable {
6546
7828
  this.requestRender();
6547
7829
  this.keypressHandler = (key) => {
6548
7830
  this._keyListeners["down"]?.(key);
6549
- if (this.handleKeyPress) {
7831
+ if (!key.defaultPrevented && this.handleKeyPress) {
6550
7832
  this.handleKeyPress(key);
6551
7833
  }
6552
7834
  };
6553
- this.pasteHandler = (text) => {
6554
- this._pasteListener?.call(this, text);
6555
- if (this.handlePaste) {
6556
- this.handlePaste(text);
7835
+ this.pasteHandler = (event) => {
7836
+ this._pasteListener?.call(this, event.text);
7837
+ if (!event.defaultPrevented && this.handlePaste) {
7838
+ this.handlePaste(event.text);
6557
7839
  }
6558
7840
  };
6559
- this.ctx.keyInput.on("keypress", this.keypressHandler);
6560
- this.ctx.keyInput.on("paste", this.pasteHandler);
7841
+ this.ctx._internalKeyInput.onInternal("keypress", this.keypressHandler);
7842
+ this.ctx._internalKeyInput.onInternal("paste", this.pasteHandler);
6561
7843
  this.emit("focused" /* FOCUSED */);
6562
7844
  }
6563
7845
  blur() {
@@ -6566,11 +7848,11 @@ class Renderable extends BaseRenderable {
6566
7848
  this._focused = false;
6567
7849
  this.requestRender();
6568
7850
  if (this.keypressHandler) {
6569
- this.ctx.keyInput.off("keypress", this.keypressHandler);
7851
+ this.ctx._internalKeyInput.offInternal("keypress", this.keypressHandler);
6570
7852
  this.keypressHandler = null;
6571
7853
  }
6572
7854
  if (this.pasteHandler) {
6573
- this.ctx.keyInput.off("paste", this.pasteHandler);
7855
+ this.ctx._internalKeyInput.offInternal("paste", this.pasteHandler);
6574
7856
  this.pasteHandler = null;
6575
7857
  }
6576
7858
  this.emit("blurred" /* BLURRED */);
@@ -7171,10 +8453,11 @@ class Renderable extends BaseRenderable {
7171
8453
  if (renderable.parent === this) {
7172
8454
  this.yogaNode.removeChild(renderable.getLayoutNode());
7173
8455
  this._childrenInLayoutOrder.splice(this._childrenInLayoutOrder.indexOf(renderable), 1);
7174
- } else if (renderable.parent) {
8456
+ } else {
7175
8457
  this.replaceParent(renderable);
7176
8458
  this.needsZIndexSort = true;
7177
8459
  this.renderableMapById.set(renderable.id, renderable);
8460
+ this._childrenInZIndexOrder.push(renderable);
7178
8461
  if (typeof renderable.onLifecyclePass === "function") {
7179
8462
  this._ctx.registerLifecyclePass(renderable);
7180
8463
  }
@@ -7219,6 +8502,16 @@ class Renderable extends BaseRenderable {
7219
8502
  if (zIndexIndex !== -1) {
7220
8503
  this._childrenInZIndexOrder.splice(zIndexIndex, 1);
7221
8504
  }
8505
+ if (this._forceLayoutUpdateFor) {
8506
+ const forceIndex = this._forceLayoutUpdateFor.findIndex((obj2) => obj2.id === id);
8507
+ if (forceIndex !== -1) {
8508
+ this._forceLayoutUpdateFor?.splice(forceIndex, 1);
8509
+ }
8510
+ }
8511
+ const newChildIndex = this._newChildren.findIndex((obj2) => obj2.id === id);
8512
+ if (newChildIndex !== -1) {
8513
+ this._newChildren?.splice(newChildIndex, 1);
8514
+ }
7222
8515
  this.childrenPrimarySortDirty = true;
7223
8516
  }
7224
8517
  }
@@ -7327,7 +8620,8 @@ class Renderable extends BaseRenderable {
7327
8620
  } catch (e) {}
7328
8621
  }
7329
8622
  destroyRecursively() {
7330
- for (const child of this._childrenInLayoutOrder) {
8623
+ const children = [...this._childrenInLayoutOrder];
8624
+ for (const child of children) {
7331
8625
  child.destroyRecursively();
7332
8626
  }
7333
8627
  this.destroy();
@@ -7666,17 +8960,17 @@ function delegate(mapping, vnode) {
7666
8960
  }
7667
8961
 
7668
8962
  // src/console.ts
7669
- import { EventEmitter as EventEmitter4 } from "events";
8963
+ import { EventEmitter as EventEmitter6 } from "events";
7670
8964
  import { Console } from "console";
7671
8965
  import fs from "fs";
7672
- import path from "path";
8966
+ import path4 from "path";
7673
8967
  import util2 from "util";
7674
8968
 
7675
8969
  // src/lib/output.capture.ts
7676
8970
  import { Writable } from "stream";
7677
- import { EventEmitter as EventEmitter3 } from "events";
8971
+ import { EventEmitter as EventEmitter5 } from "events";
7678
8972
 
7679
- class Capture extends EventEmitter3 {
8973
+ class Capture extends EventEmitter5 {
7680
8974
  output = [];
7681
8975
  constructor() {
7682
8976
  super();
@@ -7752,7 +9046,7 @@ registerEnvVar({
7752
9046
  default: false
7753
9047
  });
7754
9048
 
7755
- class TerminalConsoleCache extends EventEmitter4 {
9049
+ class TerminalConsoleCache extends EventEmitter6 {
7756
9050
  _cachedLogs = [];
7757
9051
  MAX_CACHE_SIZE = 1000;
7758
9052
  _collectCallerInfo = false;
@@ -7873,7 +9167,7 @@ var DEFAULT_CONSOLE_OPTIONS = {
7873
9167
  };
7874
9168
  var INDENT_WIDTH = 2;
7875
9169
 
7876
- class TerminalConsole extends EventEmitter4 {
9170
+ class TerminalConsole extends EventEmitter6 {
7877
9171
  isVisible = false;
7878
9172
  isFocused = false;
7879
9173
  renderer;
@@ -8312,7 +9606,7 @@ class TerminalConsole extends EventEmitter4 {
8312
9606
  try {
8313
9607
  const timestamp = Date.now();
8314
9608
  const filename = `_console_${timestamp}.log`;
8315
- const filepath = path.join(process.cwd(), filename);
9609
+ const filepath = path4.join(process.cwd(), filename);
8316
9610
  const allLogEntries = [...this._allLogEntries, ...terminalConsoleCache.cachedLogs];
8317
9611
  const logLines = [];
8318
9612
  for (const [date, level, args, callerInfo] of allLogEntries) {
@@ -8333,7 +9627,7 @@ class TerminalConsole extends EventEmitter4 {
8333
9627
  }
8334
9628
 
8335
9629
  // src/renderer.ts
8336
- import { EventEmitter as EventEmitter5 } from "events";
9630
+ import { EventEmitter as EventEmitter7 } from "events";
8337
9631
 
8338
9632
  // src/lib/objects-in-viewport.ts
8339
9633
  function getObjectsInViewport(viewport, objects, direction = "column", padding = 10, minTriggerSize = 16) {
@@ -8423,6 +9717,18 @@ registerEnvVar({
8423
9717
  type: "boolean",
8424
9718
  default: false
8425
9719
  });
9720
+ registerEnvVar({
9721
+ name: "OTUI_USE_ALTERNATE_SCREEN",
9722
+ description: "Whether to use the console. Will not capture console output if set to false.",
9723
+ type: "boolean",
9724
+ default: true
9725
+ });
9726
+ registerEnvVar({
9727
+ name: "OTUI_OVERRIDE_STDOUT",
9728
+ description: "Override the stdout stream. This is useful for debugging.",
9729
+ type: "boolean",
9730
+ default: true
9731
+ });
8426
9732
 
8427
9733
  class MouseEvent {
8428
9734
  type;
@@ -8485,13 +9791,17 @@ var rendererTracker = singleton("RendererTracker", () => {
8485
9791
  renderers.delete(renderer);
8486
9792
  if (renderers.size === 0) {
8487
9793
  process.stdin.pause();
9794
+ if (hasSingleton("tree-sitter-client")) {
9795
+ getTreeSitterClient().destroy();
9796
+ destroySingleton("tree-sitter-client");
9797
+ }
8488
9798
  }
8489
9799
  }
8490
9800
  };
8491
9801
  });
8492
9802
  async function createCliRenderer(config = {}) {
8493
9803
  if (process.argv.includes("--delay-start")) {
8494
- await new Promise((resolve) => setTimeout(resolve, 5000));
9804
+ await new Promise((resolve4) => setTimeout(resolve4, 5000));
8495
9805
  }
8496
9806
  const stdin = config.stdin || process.stdin;
8497
9807
  const stdout = config.stdout || process.stdout;
@@ -8518,14 +9828,24 @@ var CliRenderEvents;
8518
9828
  ((CliRenderEvents2) => {
8519
9829
  CliRenderEvents2["DEBUG_OVERLAY_TOGGLE"] = "debugOverlay:toggle";
8520
9830
  })(CliRenderEvents ||= {});
8521
- class CliRenderer extends EventEmitter5 {
9831
+ var RendererControlState;
9832
+ ((RendererControlState2) => {
9833
+ RendererControlState2["IDLE"] = "idle";
9834
+ RendererControlState2["AUTO_STARTED"] = "auto_started";
9835
+ RendererControlState2["EXPLICIT_STARTED"] = "explicit_started";
9836
+ RendererControlState2["EXPLICIT_PAUSED"] = "explicit_paused";
9837
+ RendererControlState2["EXPLICIT_SUSPENDED"] = "explicit_suspended";
9838
+ RendererControlState2["EXPLICIT_STOPPED"] = "explicit_stopped";
9839
+ })(RendererControlState ||= {});
9840
+
9841
+ class CliRenderer extends EventEmitter7 {
8522
9842
  static animationFrameId = 0;
8523
9843
  lib;
8524
9844
  rendererPtr;
8525
9845
  stdin;
8526
9846
  stdout;
8527
9847
  exitOnCtrlC;
8528
- isDestroyed = false;
9848
+ _isDestroyed = false;
8529
9849
  nextRenderBuffer;
8530
9850
  currentRenderBuffer;
8531
9851
  _isRunning = false;
@@ -8559,7 +9879,7 @@ class CliRenderer extends EventEmitter5 {
8559
9879
  immediateRerenderRequested = false;
8560
9880
  updateScheduled = false;
8561
9881
  liveRequestCounter = 0;
8562
- controlState = "idle" /* IDLE */;
9882
+ _controlState = "idle" /* IDLE */;
8563
9883
  frameCallbacks = [];
8564
9884
  renderStats = {
8565
9885
  frameCount: 0,
@@ -8579,7 +9899,9 @@ class CliRenderer extends EventEmitter5 {
8579
9899
  resizeDebounceDelay = 100;
8580
9900
  enableMouseMovement = false;
8581
9901
  _useMouse = true;
8582
- _useAlternateScreen = true;
9902
+ _useAlternateScreen = env.OTUI_USE_ALTERNATE_SCREEN;
9903
+ _suspendedMouseEnabled = false;
9904
+ _previousControlState = "idle" /* IDLE */;
8583
9905
  capturedRenderable;
8584
9906
  lastOverRenderableNum = 0;
8585
9907
  lastOverRenderable;
@@ -8610,9 +9932,9 @@ class CliRenderer extends EventEmitter5 {
8610
9932
  handleError = ((error) => {
8611
9933
  this.stop();
8612
9934
  this.destroy();
8613
- new Promise((resolve) => {
9935
+ new Promise((resolve4) => {
8614
9936
  setTimeout(() => {
8615
- resolve(true);
9937
+ resolve4(true);
8616
9938
  }, 100);
8617
9939
  }).then(() => {
8618
9940
  this.realStdoutWrite.call(this.stdout, `
@@ -8663,6 +9985,9 @@ Captured output:
8663
9985
  warningHandler = ((warning) => {
8664
9986
  console.warn(JSON.stringify(warning.message, null, 2));
8665
9987
  }).bind(this);
9988
+ get controlState() {
9989
+ return this._controlState;
9990
+ }
8666
9991
  constructor(lib, rendererPtr, stdin, stdout, width, height, config = {}) {
8667
9992
  super();
8668
9993
  rendererTracker.addRenderer(this);
@@ -8691,7 +10016,7 @@ Captured output:
8691
10016
  this.maxStatSamples = config.maxStatSamples || 300;
8692
10017
  this.enableMouseMovement = config.enableMouseMovement || true;
8693
10018
  this._useMouse = config.useMouse ?? true;
8694
- this._useAlternateScreen = config.useAlternateScreen ?? true;
10019
+ this._useAlternateScreen = config.useAlternateScreen ?? env.OTUI_USE_ALTERNATE_SCREEN;
8695
10020
  this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
8696
10021
  this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
8697
10022
  this.postProcessFns = config.postProcessFns || [];
@@ -8699,7 +10024,9 @@ Captured output:
8699
10024
  if (this.memorySnapshotInterval > 0) {
8700
10025
  this.startMemorySnapshotTimer();
8701
10026
  }
8702
- this.stdout.write = this.interceptStdoutWrite.bind(this);
10027
+ if (env.OTUI_OVERRIDE_STDOUT) {
10028
+ this.stdout.write = this.interceptStdoutWrite.bind(this);
10029
+ }
8703
10030
  process.on("SIGWINCH", this.sigwinchHandler);
8704
10031
  process.on("warning", this.warningHandler);
8705
10032
  process.on("uncaughtException", this.handleError);
@@ -8707,7 +10034,7 @@ Captured output:
8707
10034
  process.on("exit", this.exitHandler);
8708
10035
  this._console = new TerminalConsole(this, config.consoleOptions);
8709
10036
  this.useConsole = config.useConsole ?? true;
8710
- this._keyHandler = new KeyHandler(this.stdin, config.useKittyKeyboard ?? false);
10037
+ this._keyHandler = new InternalKeyHandler(this.stdin, config.useKittyKeyboard ?? false);
8711
10038
  global.requestAnimationFrame = (callback) => {
8712
10039
  const id = CliRenderer.animationFrameId++;
8713
10040
  this.animationRequest.set(id, callback);
@@ -8731,6 +10058,9 @@ Captured output:
8731
10058
  }
8732
10059
  this.setupInput();
8733
10060
  }
10061
+ get isDestroyed() {
10062
+ return this._isDestroyed;
10063
+ }
8734
10064
  registerLifecyclePass(renderable) {
8735
10065
  this.lifecyclePasses.add(renderable);
8736
10066
  }
@@ -8764,7 +10094,7 @@ Captured output:
8764
10094
  return this.realStdoutWrite.call(this.stdout, chunk, encoding, callback);
8765
10095
  }
8766
10096
  requestRender() {
8767
- if (!this.rendering && !this.updateScheduled && !this._isRunning) {
10097
+ if (!this.rendering && !this.updateScheduled && !this._isRunning && this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
8768
10098
  this.updateScheduled = true;
8769
10099
  process.nextTick(() => {
8770
10100
  this.loop();
@@ -8795,6 +10125,9 @@ Captured output:
8795
10125
  get keyInput() {
8796
10126
  return this._keyHandler;
8797
10127
  }
10128
+ get _internalKeyInput() {
10129
+ return this._keyHandler;
10130
+ }
8798
10131
  get terminalWidth() {
8799
10132
  return this._terminalWidth;
8800
10133
  }
@@ -8824,7 +10157,7 @@ Captured output:
8824
10157
  return this.liveRequestCounter;
8825
10158
  }
8826
10159
  get currentControlState() {
8827
- return this.controlState;
10160
+ return this._controlState;
8828
10161
  }
8829
10162
  get capabilities() {
8830
10163
  return this._capabilities;
@@ -8904,9 +10237,11 @@ Captured output:
8904
10237
  return true;
8905
10238
  }
8906
10239
  enableMouse() {
10240
+ this._useMouse = true;
8907
10241
  this.lib.enableMouse(this.rendererPtr, this.enableMouseMovement);
8908
10242
  }
8909
10243
  disableMouse() {
10244
+ this._useMouse = false;
8910
10245
  this.capturedRenderable = undefined;
8911
10246
  this.mouseParser.reset();
8912
10247
  this.lib.disableMouse(this.rendererPtr);
@@ -8925,16 +10260,16 @@ Captured output:
8925
10260
  if (this._terminalIsSetup)
8926
10261
  return;
8927
10262
  this._terminalIsSetup = true;
8928
- await new Promise((resolve) => {
10263
+ await new Promise((resolve4) => {
8929
10264
  const timeout = setTimeout(() => {
8930
10265
  this.stdin.off("data", capListener);
8931
- resolve(true);
10266
+ resolve4(true);
8932
10267
  }, 100);
8933
10268
  const capListener = (str) => {
8934
10269
  clearTimeout(timeout);
8935
10270
  this.lib.processCapabilityResponse(this.rendererPtr, str);
8936
10271
  this.stdin.off("data", capListener);
8937
- resolve(true);
10272
+ resolve4(true);
8938
10273
  };
8939
10274
  this.stdin.on("data", capListener);
8940
10275
  this.lib.setupTerminal(this.rendererPtr, this._useAlternateScreen);
@@ -9091,7 +10426,7 @@ Captured output:
9091
10426
  return false;
9092
10427
  }
9093
10428
  takeMemorySnapshot() {
9094
- if (this.isDestroyed)
10429
+ if (this._isDestroyed)
9095
10430
  return;
9096
10431
  const memoryUsage = process.memoryUsage();
9097
10432
  this.lastMemorySnapshot = {
@@ -9124,7 +10459,7 @@ Captured output:
9124
10459
  }
9125
10460
  }
9126
10461
  handleResize(width, height) {
9127
- if (this.isDestroyed)
10462
+ if (this._isDestroyed)
9128
10463
  return;
9129
10464
  if (this._splitHeight > 0) {
9130
10465
  this.processResize(width, height);
@@ -9263,27 +10598,27 @@ Captured output:
9263
10598
  }
9264
10599
  requestLive() {
9265
10600
  this.liveRequestCounter++;
9266
- if (this.controlState === "idle" /* IDLE */ && this.liveRequestCounter > 0) {
9267
- this.controlState = "auto_started" /* AUTO_STARTED */;
10601
+ if (this._controlState === "idle" /* IDLE */ && this.liveRequestCounter > 0) {
10602
+ this._controlState = "auto_started" /* AUTO_STARTED */;
9268
10603
  this.internalStart();
9269
10604
  }
9270
10605
  }
9271
10606
  dropLive() {
9272
10607
  this.liveRequestCounter = Math.max(0, this.liveRequestCounter - 1);
9273
- if (this.controlState === "auto_started" /* AUTO_STARTED */ && this.liveRequestCounter === 0) {
9274
- this.controlState = "idle" /* IDLE */;
10608
+ if (this._controlState === "auto_started" /* AUTO_STARTED */ && this.liveRequestCounter === 0) {
10609
+ this._controlState = "idle" /* IDLE */;
9275
10610
  this.internalPause();
9276
10611
  }
9277
10612
  }
9278
10613
  start() {
9279
- this.controlState = "explicit_started" /* EXPLICIT_STARTED */;
10614
+ this._controlState = "explicit_started" /* EXPLICIT_STARTED */;
9280
10615
  this.internalStart();
9281
10616
  }
9282
10617
  auto() {
9283
- this.controlState = this._isRunning ? "auto_started" /* AUTO_STARTED */ : "idle" /* IDLE */;
10618
+ this._controlState = this._isRunning ? "auto_started" /* AUTO_STARTED */ : "idle" /* IDLE */;
9284
10619
  }
9285
10620
  internalStart() {
9286
- if (!this._isRunning && !this.isDestroyed) {
10621
+ if (!this._isRunning && !this._isDestroyed) {
9287
10622
  this._isRunning = true;
9288
10623
  if (this.memorySnapshotInterval > 0) {
9289
10624
  this.startMemorySnapshotTimer();
@@ -9292,18 +10627,44 @@ Captured output:
9292
10627
  }
9293
10628
  }
9294
10629
  pause() {
9295
- this.controlState = "explicit_paused" /* EXPLICIT_PAUSED */;
10630
+ this._controlState = "explicit_paused" /* EXPLICIT_PAUSED */;
9296
10631
  this.internalPause();
9297
10632
  }
10633
+ suspend() {
10634
+ this._previousControlState = this._controlState;
10635
+ this._controlState = "explicit_suspended" /* EXPLICIT_SUSPENDED */;
10636
+ this.internalPause();
10637
+ this._suspendedMouseEnabled = this._useMouse;
10638
+ this.disableMouse();
10639
+ this._keyHandler.suspend();
10640
+ if (this.stdin.setRawMode) {
10641
+ this.stdin.setRawMode(false);
10642
+ }
10643
+ this.stdin.pause();
10644
+ }
10645
+ resume() {
10646
+ if (this.stdin.setRawMode) {
10647
+ this.stdin.setRawMode(true);
10648
+ }
10649
+ this.stdin.resume();
10650
+ this._keyHandler.resume();
10651
+ if (this._suspendedMouseEnabled) {
10652
+ this.enableMouse();
10653
+ }
10654
+ this._controlState = this._previousControlState;
10655
+ if (this._previousControlState === "auto_started" /* AUTO_STARTED */ || this._previousControlState === "explicit_started" /* EXPLICIT_STARTED */) {
10656
+ this.internalStart();
10657
+ }
10658
+ }
9298
10659
  internalPause() {
9299
10660
  this._isRunning = false;
9300
10661
  }
9301
10662
  stop() {
9302
- this.controlState = "explicit_stopped" /* EXPLICIT_STOPPED */;
10663
+ this._controlState = "explicit_stopped" /* EXPLICIT_STOPPED */;
9303
10664
  this.internalStop();
9304
10665
  }
9305
10666
  internalStop() {
9306
- if (this.isRunning && !this.isDestroyed) {
10667
+ if (this.isRunning && !this._isDestroyed) {
9307
10668
  this._isRunning = false;
9308
10669
  if (this.memorySnapshotTimer) {
9309
10670
  clearInterval(this.memorySnapshotTimer);
@@ -9324,9 +10685,9 @@ Captured output:
9324
10685
  if (this.memorySnapshotTimer) {
9325
10686
  clearInterval(this.memorySnapshotTimer);
9326
10687
  }
9327
- if (this.isDestroyed)
10688
+ if (this._isDestroyed)
9328
10689
  return;
9329
- this.isDestroyed = true;
10690
+ this._isDestroyed = true;
9330
10691
  if (this.renderTimeout) {
9331
10692
  clearTimeout(this.renderTimeout);
9332
10693
  this.renderTimeout = null;
@@ -9334,7 +10695,11 @@ Captured output:
9334
10695
  this._isRunning = false;
9335
10696
  this.waitingForPixelResolution = false;
9336
10697
  this.capturedRenderable = undefined;
9337
- this.root.destroyRecursively();
10698
+ try {
10699
+ this.root.destroyRecursively();
10700
+ } catch (e) {
10701
+ console.error("Error destroying root renderable:", e instanceof Error ? e.stack : String(e));
10702
+ }
9338
10703
  this._keyHandler.destroy();
9339
10704
  this._console.deactivate();
9340
10705
  this.disableStdoutInterception();
@@ -9359,7 +10724,7 @@ Captured output:
9359
10724
  this.loop();
9360
10725
  }
9361
10726
  async loop() {
9362
- if (this.rendering || this.isDestroyed)
10727
+ if (this.rendering || this._isDestroyed)
9363
10728
  return;
9364
10729
  this.rendering = true;
9365
10730
  if (this.renderTimeout) {
@@ -9403,17 +10768,17 @@ Captured output:
9403
10768
  postProcessFn(this.nextRenderBuffer, deltaTime);
9404
10769
  }
9405
10770
  this._console.renderToBuffer(this.nextRenderBuffer);
9406
- if (!this.isDestroyed) {
10771
+ if (!this._isDestroyed) {
9407
10772
  this.renderNative();
9408
- }
9409
- const overallFrameTime = performance.now() - overallStart;
9410
- this.lib.updateStats(this.rendererPtr, overallFrameTime, this.renderStats.fps, this.renderStats.frameCallbackTime);
9411
- if (this.gatherStats) {
9412
- this.collectStatSample(overallFrameTime);
9413
- }
9414
- if (this._isRunning) {
9415
- const delay = Math.max(1, this.targetFrameTime - Math.floor(overallFrameTime));
9416
- this.renderTimeout = setTimeout(() => this.loop(), delay);
10773
+ const overallFrameTime = performance.now() - overallStart;
10774
+ this.lib.updateStats(this.rendererPtr, overallFrameTime, this.renderStats.fps, this.renderStats.frameCallbackTime);
10775
+ if (this.gatherStats) {
10776
+ this.collectStatSample(overallFrameTime);
10777
+ }
10778
+ if (this._isRunning) {
10779
+ const delay = Math.max(1, this.targetFrameTime - Math.floor(overallFrameTime));
10780
+ this.renderTimeout = setTimeout(() => this.loop(), delay);
10781
+ }
9417
10782
  }
9418
10783
  this.rendering = false;
9419
10784
  if (this.immediateRerenderRequested) {
@@ -9572,7 +10937,7 @@ Captured output:
9572
10937
  }
9573
10938
  }
9574
10939
 
9575
- export { __toESM, __commonJS, __export, __require, Edge, Gutter, exports_src, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, nonAlphanumericKeys, parseKeypress, ANSI, KeyHandler, RGBA, hexToRgb, rgbToHex, hsvToRgb, parseColor, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, DebugOverlayCorner, createTextAttributes, visualizeRenderableTree, isStyledText, StyledText, stringToStyledText, black, red, green, yellow, blue, magenta, cyan, white, brightBlack, brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite, bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite, bold, italic, underline, strikethrough, dim, reverse, blink, fg, bg, t, SyntaxStyle, hastToStyledText, parseAlign, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, envRegistry, registerEnvVar, generateEnvMarkdown, generateEnvColored, env, TextBuffer, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, isValidPercentage, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, CliRenderer };
10940
+ export { __toESM, __commonJS, __export, __require, Edge, Gutter, exports_src, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, nonAlphanumericKeys, parseKeypress, ANSI, KeyEvent, PasteEvent, KeyHandler, InternalKeyHandler, RGBA, hexToRgb, rgbToHex, hsvToRgb, parseColor, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, DebugOverlayCorner, createTextAttributes, visualizeRenderableTree, isStyledText, StyledText, stringToStyledText, black, red, green, yellow, blue, magenta, cyan, white, brightBlack, brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite, bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite, bold, italic, underline, strikethrough, dim, reverse, blink, fg, bg, t, convertThemeToStyles, SyntaxStyle, hastToStyledText, LinearScrollAccel, MacOSScrollAccel, parseAlign, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, envRegistry, registerEnvVar, clearEnvCache, generateEnvMarkdown, generateEnvColored, env, treeSitterToTextChunks, treeSitterToStyledText, addDefaultParsers, TreeSitterClient, DataPathsManager, getDataPaths, extToFiletype, pathToFiletype, main, getTreeSitterClient, TextBuffer, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, isValidPercentage, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };
9576
10941
 
9577
- //# debugId=FA47EE78BCA83E8664756E2164756E21
9578
- //# sourceMappingURL=index-6kvgbzah.js.map
10942
+ //# debugId=4CAC9B07B4894E3E64756E2164756E21
10943
+ //# sourceMappingURL=index-zx1dwm33.js.map