@opentui/core 0.0.0-20251031-fc297165 → 0.0.0-20251106-dd34dace

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.
@@ -1896,6 +1896,7 @@ function parseKittyKeyboard(sequence) {
1896
1896
  sequence,
1897
1897
  raw: sequence,
1898
1898
  eventType: "press",
1899
+ source: "kitty",
1899
1900
  super: false,
1900
1901
  hyper: false,
1901
1902
  capsLock: false,
@@ -2107,10 +2108,11 @@ var parseKeypress = (s = "", options = {}) => {
2107
2108
  number: false,
2108
2109
  sequence: s,
2109
2110
  raw: s,
2110
- eventType: "press"
2111
+ eventType: "press",
2112
+ source: "raw"
2111
2113
  };
2112
2114
  key.sequence = key.sequence || s || key.name;
2113
- if (options.useKittyKeyboard && /^\x1b\[.*u$/.test(s)) {
2115
+ if (options.useKittyKeyboard) {
2114
2116
  const kittyResult = parseKittyKeyboard(s);
2115
2117
  if (kittyResult) {
2116
2118
  return kittyResult;
@@ -2135,6 +2137,9 @@ var parseKeypress = (s = "", options = {}) => {
2135
2137
  } else if (s === " " || s === "\x1B ") {
2136
2138
  key.name = "space";
2137
2139
  key.meta = s.length === 2;
2140
+ } else if (s === "\x00") {
2141
+ key.name = "space";
2142
+ key.ctrl = true;
2138
2143
  } else if (s.length === 1 && s <= "\x1A") {
2139
2144
  key.name = String.fromCharCode(s.charCodeAt(0) + 97 - 1);
2140
2145
  key.ctrl = true;
@@ -2185,8 +2190,184 @@ var parseKeypress = (s = "", options = {}) => {
2185
2190
  return key;
2186
2191
  };
2187
2192
 
2188
- // src/lib/KeyHandler.ts
2193
+ // src/lib/stdin-buffer.ts
2189
2194
  import { EventEmitter } from "events";
2195
+ var ESC = "\x1B";
2196
+ function isCompleteSequence(data) {
2197
+ if (!data.startsWith(ESC)) {
2198
+ return "not-escape";
2199
+ }
2200
+ if (data.length === 1) {
2201
+ return "incomplete";
2202
+ }
2203
+ const afterEsc = data.slice(1);
2204
+ if (afterEsc.startsWith("[")) {
2205
+ if (afterEsc.startsWith("[M")) {
2206
+ return data.length >= 6 ? "complete" : "incomplete";
2207
+ }
2208
+ return isCompleteCsiSequence(data);
2209
+ }
2210
+ if (afterEsc.startsWith("]")) {
2211
+ return isCompleteOscSequence(data);
2212
+ }
2213
+ if (afterEsc.startsWith("O")) {
2214
+ return afterEsc.length >= 2 ? "complete" : "incomplete";
2215
+ }
2216
+ if (afterEsc.length === 1) {
2217
+ return "complete";
2218
+ }
2219
+ return "complete";
2220
+ }
2221
+ function isCompleteCsiSequence(data) {
2222
+ if (!data.startsWith(ESC + "[")) {
2223
+ return "complete";
2224
+ }
2225
+ if (data.length < 3) {
2226
+ return "incomplete";
2227
+ }
2228
+ const payload = data.slice(2);
2229
+ const lastChar = payload[payload.length - 1];
2230
+ const lastCharCode = lastChar.charCodeAt(0);
2231
+ if (lastCharCode >= 64 && lastCharCode <= 126) {
2232
+ if (payload.startsWith("<")) {
2233
+ const mouseMatch = /^<\d+;\d+;\d+[Mm]$/.test(payload);
2234
+ if (mouseMatch) {
2235
+ return "complete";
2236
+ }
2237
+ if (lastChar === "M" || lastChar === "m") {
2238
+ const parts = payload.slice(1, -1).split(";");
2239
+ if (parts.length === 3 && parts.every((p) => /^\d+$/.test(p))) {
2240
+ return "complete";
2241
+ }
2242
+ }
2243
+ return "incomplete";
2244
+ }
2245
+ return "complete";
2246
+ }
2247
+ return "incomplete";
2248
+ }
2249
+ function isCompleteOscSequence(data) {
2250
+ if (!data.startsWith(ESC + "]")) {
2251
+ return "complete";
2252
+ }
2253
+ if (data.endsWith(ESC + "\\") || data.endsWith("\x07")) {
2254
+ return "complete";
2255
+ }
2256
+ return "incomplete";
2257
+ }
2258
+ function extractCompleteSequences(buffer) {
2259
+ const sequences = [];
2260
+ let pos = 0;
2261
+ while (pos < buffer.length) {
2262
+ const remaining = buffer.slice(pos);
2263
+ if (remaining.startsWith(ESC)) {
2264
+ let seqEnd = 1;
2265
+ while (seqEnd <= remaining.length) {
2266
+ const candidate = remaining.slice(0, seqEnd);
2267
+ const status = isCompleteSequence(candidate);
2268
+ if (status === "complete") {
2269
+ sequences.push(candidate);
2270
+ pos += seqEnd;
2271
+ break;
2272
+ } else if (status === "incomplete") {
2273
+ seqEnd++;
2274
+ } else {
2275
+ sequences.push(candidate);
2276
+ pos += seqEnd;
2277
+ break;
2278
+ }
2279
+ }
2280
+ if (seqEnd > remaining.length) {
2281
+ return { sequences, remainder: remaining };
2282
+ }
2283
+ } else {
2284
+ sequences.push(remaining[0]);
2285
+ pos++;
2286
+ }
2287
+ }
2288
+ return { sequences, remainder: "" };
2289
+ }
2290
+
2291
+ class StdinBuffer extends EventEmitter {
2292
+ buffer = "";
2293
+ timeout = null;
2294
+ timeoutMs;
2295
+ stdin;
2296
+ stdinListener;
2297
+ constructor(stdin, options = {}) {
2298
+ super();
2299
+ this.stdin = stdin;
2300
+ this.timeoutMs = options.timeout ?? 10;
2301
+ this.stdinListener = (data) => {
2302
+ this.handleData(data);
2303
+ };
2304
+ this.stdin.on("data", this.stdinListener);
2305
+ }
2306
+ handleData(data) {
2307
+ if (this.timeout) {
2308
+ clearTimeout(this.timeout);
2309
+ this.timeout = null;
2310
+ }
2311
+ let str;
2312
+ if (Buffer.isBuffer(data)) {
2313
+ if (data.length === 1 && data[0] > 127) {
2314
+ const byte = data[0] - 128;
2315
+ str = "\x1B" + String.fromCharCode(byte);
2316
+ } else {
2317
+ str = data.toString();
2318
+ }
2319
+ } else {
2320
+ str = data;
2321
+ }
2322
+ if (str.length === 0 && this.buffer.length === 0) {
2323
+ this.emit("data", "");
2324
+ return;
2325
+ }
2326
+ this.buffer += str;
2327
+ const result = extractCompleteSequences(this.buffer);
2328
+ this.buffer = result.remainder;
2329
+ for (const sequence of result.sequences) {
2330
+ this.emit("data", sequence);
2331
+ }
2332
+ if (this.buffer.length > 0) {
2333
+ this.timeout = setTimeout(() => {
2334
+ const flushed = this.flush();
2335
+ for (const sequence of flushed) {
2336
+ this.emit("data", sequence);
2337
+ }
2338
+ }, this.timeoutMs);
2339
+ }
2340
+ }
2341
+ flush() {
2342
+ if (this.timeout) {
2343
+ clearTimeout(this.timeout);
2344
+ this.timeout = null;
2345
+ }
2346
+ if (this.buffer.length === 0) {
2347
+ return [];
2348
+ }
2349
+ const sequences = [this.buffer];
2350
+ this.buffer = "";
2351
+ return sequences;
2352
+ }
2353
+ clear() {
2354
+ if (this.timeout) {
2355
+ clearTimeout(this.timeout);
2356
+ this.timeout = null;
2357
+ }
2358
+ this.buffer = "";
2359
+ }
2360
+ getBuffer() {
2361
+ return this.buffer;
2362
+ }
2363
+ destroy() {
2364
+ this.stdin.removeListener("data", this.stdinListener);
2365
+ this.clear();
2366
+ }
2367
+ }
2368
+
2369
+ // src/lib/KeyHandler.ts
2370
+ import { EventEmitter as EventEmitter2 } from "events";
2190
2371
 
2191
2372
  // src/ansi.ts
2192
2373
  var ANSI = {
@@ -2214,6 +2395,7 @@ class KeyEvent {
2214
2395
  number;
2215
2396
  raw;
2216
2397
  eventType;
2398
+ source;
2217
2399
  code;
2218
2400
  super;
2219
2401
  hyper;
@@ -2231,6 +2413,7 @@ class KeyEvent {
2231
2413
  this.number = key.number;
2232
2414
  this.raw = key.raw;
2233
2415
  this.eventType = key.eventType;
2416
+ this.source = key.source;
2234
2417
  this.code = key.code;
2235
2418
  this.super = key.super;
2236
2419
  this.hyper = key.hyper;
@@ -2260,65 +2443,70 @@ class PasteEvent {
2260
2443
  }
2261
2444
  }
2262
2445
 
2263
- class KeyHandler extends EventEmitter {
2446
+ class KeyHandler extends EventEmitter2 {
2264
2447
  stdin;
2265
2448
  useKittyKeyboard;
2266
- listener;
2267
2449
  pasteMode = false;
2268
2450
  pasteBuffer = [];
2269
2451
  suspended = false;
2452
+ stdinBuffer;
2453
+ dataListener;
2270
2454
  constructor(stdin, useKittyKeyboard = false) {
2271
2455
  super();
2272
2456
  this.stdin = stdin || process.stdin;
2273
2457
  this.useKittyKeyboard = useKittyKeyboard;
2274
- this.listener = (key) => {
2275
- let data = key.toString();
2276
- if (data.startsWith(ANSI.bracketedPasteStart)) {
2277
- this.pasteMode = true;
2278
- }
2279
- if (this.pasteMode) {
2280
- this.pasteBuffer.push(Bun.stripANSI(data));
2281
- if (data.endsWith(ANSI.bracketedPasteEnd)) {
2282
- this.pasteMode = false;
2283
- this.emit("paste", new PasteEvent(this.pasteBuffer.join("")));
2284
- this.pasteBuffer = [];
2285
- }
2286
- return;
2287
- }
2288
- const parsedKey = parseKeypress(key, { useKittyKeyboard: this.useKittyKeyboard });
2289
- if (!parsedKey) {
2290
- return;
2291
- }
2292
- switch (parsedKey.eventType) {
2293
- case "press":
2294
- this.emit("keypress", new KeyEvent(parsedKey));
2295
- break;
2296
- case "repeat":
2297
- this.emit("keyrepeat", new KeyEvent(parsedKey));
2298
- break;
2299
- case "release":
2300
- this.emit("keyrelease", new KeyEvent(parsedKey));
2301
- break;
2302
- default:
2303
- this.emit("keypress", new KeyEvent(parsedKey));
2304
- break;
2305
- }
2458
+ this.stdinBuffer = new StdinBuffer(this.stdin, { timeout: 5 });
2459
+ this.dataListener = (sequence) => {
2460
+ this.processSequence(sequence);
2306
2461
  };
2307
- this.stdin.on("data", this.listener);
2462
+ this.stdinBuffer.on("data", this.dataListener);
2463
+ }
2464
+ processSequence(data) {
2465
+ if (data.startsWith(ANSI.bracketedPasteStart)) {
2466
+ this.pasteMode = true;
2467
+ }
2468
+ if (this.pasteMode) {
2469
+ this.pasteBuffer.push(Bun.stripANSI(data));
2470
+ if (data.endsWith(ANSI.bracketedPasteEnd)) {
2471
+ this.pasteMode = false;
2472
+ this.emit("paste", new PasteEvent(this.pasteBuffer.join("")));
2473
+ this.pasteBuffer = [];
2474
+ }
2475
+ return;
2476
+ }
2477
+ const parsedKey = parseKeypress(data, { useKittyKeyboard: this.useKittyKeyboard });
2478
+ if (!parsedKey) {
2479
+ return;
2480
+ }
2481
+ switch (parsedKey.eventType) {
2482
+ case "press":
2483
+ this.emit("keypress", new KeyEvent(parsedKey));
2484
+ break;
2485
+ case "repeat":
2486
+ this.emit("keyrepeat", new KeyEvent(parsedKey));
2487
+ break;
2488
+ case "release":
2489
+ this.emit("keyrelease", new KeyEvent(parsedKey));
2490
+ break;
2491
+ default:
2492
+ this.emit("keypress", new KeyEvent(parsedKey));
2493
+ break;
2494
+ }
2308
2495
  }
2309
2496
  destroy() {
2310
- this.stdin.removeListener("data", this.listener);
2497
+ this.stdinBuffer.removeListener("data", this.dataListener);
2498
+ this.stdinBuffer.destroy();
2311
2499
  }
2312
2500
  suspend() {
2313
2501
  if (!this.suspended) {
2314
2502
  this.suspended = true;
2315
- this.stdin.removeListener("data", this.listener);
2503
+ this.stdinBuffer.removeListener("data", this.dataListener);
2316
2504
  }
2317
2505
  }
2318
2506
  resume() {
2319
2507
  if (this.suspended) {
2320
2508
  this.suspended = false;
2321
- this.stdin.on("data", this.listener);
2509
+ this.stdinBuffer.on("data", this.dataListener);
2322
2510
  }
2323
2511
  }
2324
2512
  }
@@ -5325,7 +5513,7 @@ async function treeSitterToStyledText(content, filetype, syntaxStyle, client, op
5325
5513
  }
5326
5514
 
5327
5515
  // src/lib/tree-sitter/client.ts
5328
- import { EventEmitter as EventEmitter2 } from "events";
5516
+ import { EventEmitter as EventEmitter3 } from "events";
5329
5517
 
5330
5518
  // src/lib/debounce.ts
5331
5519
  var TIMERS_MAP = new Map;
@@ -5518,7 +5706,7 @@ function addDefaultParsers(parsers) {
5518
5706
  }
5519
5707
  var isUrl = (path) => path.startsWith("http://") || path.startsWith("https://");
5520
5708
 
5521
- class TreeSitterClient extends EventEmitter2 {
5709
+ class TreeSitterClient extends EventEmitter3 {
5522
5710
  initialized = false;
5523
5711
  worker;
5524
5712
  buffers = new Map;
@@ -5969,7 +6157,7 @@ class TreeSitterClient extends EventEmitter2 {
5969
6157
  // src/lib/data-paths.ts
5970
6158
  import os from "os";
5971
6159
  import path from "path";
5972
- import { EventEmitter as EventEmitter3 } from "events";
6160
+ import { EventEmitter as EventEmitter4 } from "events";
5973
6161
 
5974
6162
  // src/lib/validate-dir-name.ts
5975
6163
  function isValidDirectoryName(name) {
@@ -6033,7 +6221,7 @@ registerEnvVar({
6033
6221
  default: ""
6034
6222
  });
6035
6223
 
6036
- class DataPathsManager extends EventEmitter3 {
6224
+ class DataPathsManager extends EventEmitter4 {
6037
6225
  _appName;
6038
6226
  _globalConfigPath;
6039
6227
  _globalConfigFile;
@@ -7156,7 +7344,7 @@ function createExtmarksController(editBuffer, editorView) {
7156
7344
  // src/zig.ts
7157
7345
  import { dlopen, toArrayBuffer as toArrayBuffer4, JSCallback, ptr as ptr3 } from "bun:ffi";
7158
7346
  import { existsSync as existsSync2 } from "fs";
7159
- import { EventEmitter as EventEmitter4 } from "events";
7347
+ import { EventEmitter as EventEmitter5 } from "events";
7160
7348
 
7161
7349
  // src/buffer.ts
7162
7350
  import { toArrayBuffer } from "bun:ffi";
@@ -8220,6 +8408,14 @@ function getOpenTUILib(libPath) {
8220
8408
  args: ["ptr"],
8221
8409
  returns: "void"
8222
8410
  },
8411
+ setUseKittyKeyboard: {
8412
+ args: ["ptr", "bool"],
8413
+ returns: "void"
8414
+ },
8415
+ getUseKittyKeyboard: {
8416
+ args: ["ptr"],
8417
+ returns: "bool"
8418
+ },
8223
8419
  setupTerminal: {
8224
8420
  args: ["ptr", "bool"],
8225
8421
  returns: "void"
@@ -8340,6 +8536,14 @@ function getOpenTUILib(libPath) {
8340
8536
  args: ["ptr"],
8341
8537
  returns: "u32"
8342
8538
  },
8539
+ textBufferGetTextRange: {
8540
+ args: ["ptr", "u32", "u32", "ptr", "usize"],
8541
+ returns: "usize"
8542
+ },
8543
+ textBufferGetTextRangeByCoords: {
8544
+ args: ["ptr", "u32", "u32", "u32", "u32", "ptr", "usize"],
8545
+ returns: "usize"
8546
+ },
8343
8547
  createTextBufferView: {
8344
8548
  args: ["ptr"],
8345
8549
  returns: "ptr"
@@ -8604,6 +8808,14 @@ function getOpenTUILib(libPath) {
8604
8808
  args: ["ptr", "u32"],
8605
8809
  returns: "u32"
8606
8810
  },
8811
+ editBufferGetTextRange: {
8812
+ args: ["ptr", "u32", "u32", "ptr", "usize"],
8813
+ returns: "usize"
8814
+ },
8815
+ editBufferGetTextRangeByCoords: {
8816
+ args: ["ptr", "u32", "u32", "u32", "u32", "ptr", "usize"],
8817
+ returns: "usize"
8818
+ },
8607
8819
  editorViewSetSelection: {
8608
8820
  args: ["ptr", "u32", "u32", "ptr", "ptr"],
8609
8821
  returns: "void"
@@ -8724,16 +8936,28 @@ function convertToDebugSymbols(symbols) {
8724
8936
  const debugSymbols = {};
8725
8937
  const traceSymbols = {};
8726
8938
  let hasTracing = false;
8939
+ let ffiLogWriter = null;
8727
8940
  Object.entries(symbols).forEach(([key, value]) => {
8728
8941
  debugSymbols[key] = value;
8729
8942
  });
8730
8943
  if (env.OTUI_DEBUG_FFI) {
8944
+ const now = new Date;
8945
+ const timestamp = now.toISOString().replace(/[:.]/g, "-").replace(/T/, "_").split("Z")[0];
8946
+ const logFilePath = `ffi_debug_${timestamp}.log`;
8947
+ ffiLogWriter = Bun.file(logFilePath).writer();
8948
+ const writer = ffiLogWriter;
8949
+ const writeSync = (msg) => {
8950
+ const buffer = new TextEncoder().encode(msg + `
8951
+ `);
8952
+ writer.write(buffer);
8953
+ writer.flush();
8954
+ };
8731
8955
  Object.entries(symbols).forEach(([key, value]) => {
8732
8956
  if (typeof value === "function") {
8733
8957
  debugSymbols[key] = (...args) => {
8734
- console.log(`${key}(${args.map((arg) => String(arg)).join(", ")})`);
8958
+ writeSync(`${key}(${args.map((arg) => String(arg)).join(", ")})`);
8735
8959
  const result = value(...args);
8736
- console.log(`${key} returned:`, String(result));
8960
+ writeSync(`${key} returned: ${String(result)}`);
8737
8961
  return result;
8738
8962
  };
8739
8963
  }
@@ -8755,6 +8979,13 @@ function convertToDebugSymbols(symbols) {
8755
8979
  }
8756
8980
  });
8757
8981
  }
8982
+ if (env.OTUI_DEBUG_FFI && ffiLogWriter) {
8983
+ process.on("exit", () => {
8984
+ try {
8985
+ ffiLogWriter.end();
8986
+ } catch (e) {}
8987
+ });
8988
+ }
8758
8989
  if (hasTracing) {
8759
8990
  process.on("exit", () => {
8760
8991
  const allStats = [];
@@ -8837,7 +9068,7 @@ class FFIRenderLib {
8837
9068
  decoder = new TextDecoder;
8838
9069
  logCallbackWrapper;
8839
9070
  eventCallbackWrapper;
8840
- _nativeEvents = new EventEmitter4;
9071
+ _nativeEvents = new EventEmitter5;
8841
9072
  _anyEventHandlers = [];
8842
9073
  constructor(libPath) {
8843
9074
  this.opentui = getOpenTUILib(libPath);
@@ -9144,6 +9375,12 @@ class FFIRenderLib {
9144
9375
  disableKittyKeyboard(renderer) {
9145
9376
  this.opentui.symbols.disableKittyKeyboard(renderer);
9146
9377
  }
9378
+ setUseKittyKeyboard(renderer, use) {
9379
+ this.opentui.symbols.setUseKittyKeyboard(renderer, use);
9380
+ }
9381
+ getUseKittyKeyboard(renderer) {
9382
+ return this.opentui.symbols.getUseKittyKeyboard(renderer);
9383
+ }
9147
9384
  setupTerminal(renderer, useAlternateScreen) {
9148
9385
  this.opentui.symbols.setupTerminal(renderer, useAlternateScreen);
9149
9386
  }
@@ -9238,6 +9475,24 @@ class FFIRenderLib {
9238
9475
  }
9239
9476
  return outBuffer.slice(0, actualLen);
9240
9477
  }
9478
+ textBufferGetTextRange(buffer, startOffset, endOffset, maxLength) {
9479
+ const outBuffer = new Uint8Array(maxLength);
9480
+ const actualLen = this.opentui.symbols.textBufferGetTextRange(buffer, startOffset, endOffset, ptr3(outBuffer), maxLength);
9481
+ const len = typeof actualLen === "bigint" ? Number(actualLen) : actualLen;
9482
+ if (len === 0) {
9483
+ return null;
9484
+ }
9485
+ return outBuffer.slice(0, len);
9486
+ }
9487
+ textBufferGetTextRangeByCoords(buffer, startRow, startCol, endRow, endCol, maxLength) {
9488
+ const outBuffer = new Uint8Array(maxLength);
9489
+ const actualLen = this.opentui.symbols.textBufferGetTextRangeByCoords(buffer, startRow, startCol, endRow, endCol, ptr3(outBuffer), maxLength);
9490
+ const len = typeof actualLen === "bigint" ? Number(actualLen) : actualLen;
9491
+ if (len === 0) {
9492
+ return null;
9493
+ }
9494
+ return outBuffer.slice(0, len);
9495
+ }
9241
9496
  createTextBufferView(textBuffer) {
9242
9497
  const viewPtr = this.opentui.symbols.createTextBufferView(textBuffer);
9243
9498
  if (!viewPtr) {
@@ -9618,6 +9873,22 @@ class FFIRenderLib {
9618
9873
  editBufferGetLineStartOffset(buffer, row) {
9619
9874
  return this.opentui.symbols.editBufferGetLineStartOffset(buffer, row);
9620
9875
  }
9876
+ editBufferGetTextRange(buffer, startOffset, endOffset, maxLength) {
9877
+ const outBuffer = new Uint8Array(maxLength);
9878
+ const actualLen = this.opentui.symbols.editBufferGetTextRange(buffer, startOffset, endOffset, ptr3(outBuffer), maxLength);
9879
+ const len = typeof actualLen === "bigint" ? Number(actualLen) : actualLen;
9880
+ if (len === 0)
9881
+ return null;
9882
+ return outBuffer.slice(0, len);
9883
+ }
9884
+ editBufferGetTextRangeByCoords(buffer, startRow, startCol, endRow, endCol, maxLength) {
9885
+ const outBuffer = new Uint8Array(maxLength);
9886
+ const actualLen = this.opentui.symbols.editBufferGetTextRangeByCoords(buffer, startRow, startCol, endRow, endCol, ptr3(outBuffer), maxLength);
9887
+ const len = typeof actualLen === "bigint" ? Number(actualLen) : actualLen;
9888
+ if (len === 0)
9889
+ return null;
9890
+ return outBuffer.slice(0, len);
9891
+ }
9621
9892
  editorViewSetSelection(view, start, end, bgColor, fgColor) {
9622
9893
  const bg2 = bgColor ? bgColor.buffer : null;
9623
9894
  const fg2 = fgColor ? fgColor.buffer : null;
@@ -9903,6 +10174,17 @@ class TextBuffer {
9903
10174
  return "";
9904
10175
  return this.lib.decoder.decode(plainBytes);
9905
10176
  }
10177
+ getTextRange(startOffset, endOffset) {
10178
+ this.guard();
10179
+ if (startOffset >= endOffset)
10180
+ return "";
10181
+ if (this._byteSize === 0)
10182
+ return "";
10183
+ const rangeBytes = this.lib.textBufferGetTextRange(this.bufferPtr, startOffset, endOffset, this._byteSize);
10184
+ if (!rangeBytes)
10185
+ return "";
10186
+ return this.lib.decoder.decode(rangeBytes);
10187
+ }
9906
10188
  addHighlightByCharRange(highlight) {
9907
10189
  this.guard();
9908
10190
  this.lib.textBufferAddHighlightByCharRange(this.bufferPtr, highlight);
@@ -9974,7 +10256,7 @@ class TextBuffer {
9974
10256
  }
9975
10257
 
9976
10258
  // src/Renderable.ts
9977
- import { EventEmitter as EventEmitter5 } from "events";
10259
+ import { EventEmitter as EventEmitter6 } from "events";
9978
10260
 
9979
10261
  // src/lib/renderable.validations.ts
9980
10262
  function validateOptions(id, options) {
@@ -10067,7 +10349,7 @@ function isRenderable(obj) {
10067
10349
  return !!obj?.[BrandedRenderable];
10068
10350
  }
10069
10351
 
10070
- class BaseRenderable extends EventEmitter5 {
10352
+ class BaseRenderable extends EventEmitter6 {
10071
10353
  [BrandedRenderable] = true;
10072
10354
  static renderableNumber = 1;
10073
10355
  _id;
@@ -10789,7 +11071,7 @@ class Renderable extends BaseRenderable {
10789
11071
  }
10790
11072
  try {
10791
11073
  const widthMethod = this._ctx.widthMethod;
10792
- this.frameBuffer = OptimizedBuffer.create(w, h, widthMethod, { respectAlpha: true });
11074
+ this.frameBuffer = OptimizedBuffer.create(w, h, widthMethod, { respectAlpha: true, id: `framebuffer-${this.id}` });
10793
11075
  } catch (error) {
10794
11076
  console.error(`Failed to create frame buffer for ${this.id}:`, error);
10795
11077
  this.frameBuffer = null;
@@ -11388,7 +11670,7 @@ function delegate(mapping, vnode) {
11388
11670
  }
11389
11671
 
11390
11672
  // src/console.ts
11391
- import { EventEmitter as EventEmitter7 } from "events";
11673
+ import { EventEmitter as EventEmitter8 } from "events";
11392
11674
  import { Console } from "console";
11393
11675
  import fs from "fs";
11394
11676
  import path4 from "path";
@@ -11396,9 +11678,9 @@ import util2 from "util";
11396
11678
 
11397
11679
  // src/lib/output.capture.ts
11398
11680
  import { Writable } from "stream";
11399
- import { EventEmitter as EventEmitter6 } from "events";
11681
+ import { EventEmitter as EventEmitter7 } from "events";
11400
11682
 
11401
- class Capture extends EventEmitter6 {
11683
+ class Capture extends EventEmitter7 {
11402
11684
  output = [];
11403
11685
  constructor() {
11404
11686
  super();
@@ -11474,7 +11756,7 @@ registerEnvVar({
11474
11756
  default: false
11475
11757
  });
11476
11758
 
11477
- class TerminalConsoleCache extends EventEmitter7 {
11759
+ class TerminalConsoleCache extends EventEmitter8 {
11478
11760
  _cachedLogs = [];
11479
11761
  MAX_CACHE_SIZE = 1000;
11480
11762
  _collectCallerInfo = false;
@@ -11600,7 +11882,7 @@ var DEFAULT_CONSOLE_OPTIONS = {
11600
11882
  };
11601
11883
  var INDENT_WIDTH = 2;
11602
11884
 
11603
- class TerminalConsole extends EventEmitter7 {
11885
+ class TerminalConsole extends EventEmitter8 {
11604
11886
  isVisible = false;
11605
11887
  isFocused = false;
11606
11888
  renderer;
@@ -11689,34 +11971,34 @@ class TerminalConsole extends EventEmitter7 {
11689
11971
  }
11690
11972
  this.markNeedsRerender();
11691
11973
  }
11692
- _updateConsoleDimensions() {
11693
- const termWidth = this.renderer.terminalWidth;
11694
- const termHeight = this.renderer.terminalHeight;
11974
+ _updateConsoleDimensions(termWidth, termHeight) {
11975
+ const width = termWidth ?? this.renderer.terminalWidth;
11976
+ const height = termHeight ?? this.renderer.terminalHeight;
11695
11977
  const sizePercent = this.options.sizePercent / 100;
11696
11978
  switch (this.options.position) {
11697
11979
  case "top" /* TOP */:
11698
11980
  this.consoleX = 0;
11699
11981
  this.consoleY = 0;
11700
- this.consoleWidth = termWidth;
11701
- this.consoleHeight = Math.max(1, Math.floor(termHeight * sizePercent));
11982
+ this.consoleWidth = width;
11983
+ this.consoleHeight = Math.max(1, Math.floor(height * sizePercent));
11702
11984
  break;
11703
11985
  case "bottom" /* BOTTOM */:
11704
- this.consoleHeight = Math.max(1, Math.floor(termHeight * sizePercent));
11705
- this.consoleWidth = termWidth;
11986
+ this.consoleHeight = Math.max(1, Math.floor(height * sizePercent));
11987
+ this.consoleWidth = width;
11706
11988
  this.consoleX = 0;
11707
- this.consoleY = termHeight - this.consoleHeight;
11989
+ this.consoleY = height - this.consoleHeight;
11708
11990
  break;
11709
11991
  case "left" /* LEFT */:
11710
- this.consoleWidth = Math.max(1, Math.floor(termWidth * sizePercent));
11711
- this.consoleHeight = termHeight;
11992
+ this.consoleWidth = Math.max(1, Math.floor(width * sizePercent));
11993
+ this.consoleHeight = height;
11712
11994
  this.consoleX = 0;
11713
11995
  this.consoleY = 0;
11714
11996
  break;
11715
11997
  case "right" /* RIGHT */:
11716
- this.consoleWidth = Math.max(1, Math.floor(termWidth * sizePercent));
11717
- this.consoleHeight = termHeight;
11998
+ this.consoleWidth = Math.max(1, Math.floor(width * sizePercent));
11999
+ this.consoleHeight = height;
11718
12000
  this.consoleY = 0;
11719
- this.consoleX = termWidth - this.consoleWidth;
12001
+ this.consoleX = width - this.consoleWidth;
11720
12002
  break;
11721
12003
  }
11722
12004
  this.currentLineIndex = Math.max(0, Math.min(this.currentLineIndex, this.consoleHeight - 1));
@@ -11838,7 +12120,7 @@ class TerminalConsole extends EventEmitter7 {
11838
12120
  }).join(" ");
11839
12121
  }
11840
12122
  resize(width, height) {
11841
- this._updateConsoleDimensions();
12123
+ this._updateConsoleDimensions(width, height);
11842
12124
  if (this.frameBuffer) {
11843
12125
  this.frameBuffer.resize(this.consoleWidth, this.consoleHeight);
11844
12126
  const displayLineCount = this._displayLines.length;
@@ -12060,7 +12342,7 @@ class TerminalConsole extends EventEmitter7 {
12060
12342
  }
12061
12343
 
12062
12344
  // src/renderer.ts
12063
- import { EventEmitter as EventEmitter8 } from "events";
12345
+ import { EventEmitter as EventEmitter9 } from "events";
12064
12346
 
12065
12347
  // src/lib/objects-in-viewport.ts
12066
12348
  function getObjectsInViewport(viewport, objects, direction = "column", padding = 10, minTriggerSize = 16) {
@@ -12268,6 +12550,8 @@ async function createCliRenderer(config = {}) {
12268
12550
  config.useThread = false;
12269
12551
  }
12270
12552
  ziglib.setUseThread(rendererPtr, config.useThread);
12553
+ const useKittyKeyboard = config.useKittyKeyboard ?? true;
12554
+ ziglib.setUseKittyKeyboard(rendererPtr, useKittyKeyboard);
12271
12555
  const renderer = new CliRenderer(ziglib, rendererPtr, stdin, stdout, width, height, config);
12272
12556
  await renderer.setupTerminal();
12273
12557
  return renderer;
@@ -12286,7 +12570,7 @@ var RendererControlState;
12286
12570
  RendererControlState2["EXPLICIT_STOPPED"] = "explicit_stopped";
12287
12571
  })(RendererControlState ||= {});
12288
12572
 
12289
- class CliRenderer extends EventEmitter8 {
12573
+ class CliRenderer extends EventEmitter9 {
12290
12574
  static animationFrameId = 0;
12291
12575
  lib;
12292
12576
  rendererPtr;
@@ -12377,9 +12661,10 @@ class CliRenderer extends EventEmitter8 {
12377
12661
  _latestPointer = { x: 0, y: 0 };
12378
12662
  _currentFocusedRenderable = null;
12379
12663
  lifecyclePasses = new Set;
12664
+ _openConsoleOnError = true;
12380
12665
  handleError = ((error) => {
12381
12666
  console.error(error);
12382
- if (true) {
12667
+ if (this._openConsoleOnError) {
12383
12668
  this.console.show();
12384
12669
  }
12385
12670
  }).bind(this);
@@ -12464,7 +12749,16 @@ Captured output:
12464
12749
  process.on("exit", this.exitHandler);
12465
12750
  this._console = new TerminalConsole(this, config.consoleOptions);
12466
12751
  this.useConsole = config.useConsole ?? true;
12467
- this._keyHandler = new InternalKeyHandler(this.stdin, config.useKittyKeyboard ?? false);
12752
+ this._openConsoleOnError = config.openConsoleOnError ?? true;
12753
+ this._keyHandler = new InternalKeyHandler(this.stdin, config.useKittyKeyboard ?? true);
12754
+ this._keyHandler.on("keypress", (event) => {
12755
+ if (this.exitOnCtrlC && event.name === "c" && event.ctrl) {
12756
+ process.nextTick(() => {
12757
+ this.destroy();
12758
+ });
12759
+ return;
12760
+ }
12761
+ });
12468
12762
  global.requestAnimationFrame = (callback) => {
12469
12763
  const id = CliRenderer.animationFrameId++;
12470
12764
  this.animationRequest.set(id, callback);
@@ -12592,6 +12886,12 @@ Captured output:
12592
12886
  get capabilities() {
12593
12887
  return this._capabilities;
12594
12888
  }
12889
+ get useKittyKeyboard() {
12890
+ return this.lib.getUseKittyKeyboard(this.rendererPtr);
12891
+ }
12892
+ set useKittyKeyboard(use) {
12893
+ this.lib.setUseKittyKeyboard(this.rendererPtr, use);
12894
+ }
12595
12895
  set experimental_splitHeight(splitHeight) {
12596
12896
  if (splitHeight < 0)
12597
12897
  splitHeight = 0;
@@ -12724,12 +13024,6 @@ Captured output:
12724
13024
  return;
12725
13025
  }
12726
13026
  }
12727
- if (this.exitOnCtrlC && str === "\x03") {
12728
- process.nextTick(() => {
12729
- this.destroy();
12730
- });
12731
- return;
12732
- }
12733
13027
  if (this._useMouse && this.handleMouseData(data)) {
12734
13028
  return;
12735
13029
  }
@@ -13369,7 +13663,7 @@ Captured output:
13369
13663
  }
13370
13664
  }
13371
13665
 
13372
- 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, 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, ExtmarksController, createExtmarksController, 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 };
13666
+ export { __toESM, __commonJS, __export, __require, Edge, Gutter, exports_src, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, nonAlphanumericKeys, parseKeypress, ANSI, StdinBuffer, 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, 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, ExtmarksController, createExtmarksController, 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 };
13373
13667
 
13374
- //# debugId=3D6AC881EA3F1FB664756E2164756E21
13375
- //# sourceMappingURL=index-vr8t68wb.js.map
13668
+ //# debugId=A88F8272C607FC3964756E2164756E21
13669
+ //# sourceMappingURL=index-n8nbvvhk.js.map