@opentui/core 0.1.39 → 0.1.40

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.
@@ -27,7 +27,7 @@ var __export = (target, all) => {
27
27
  };
28
28
  var __require = import.meta.require;
29
29
 
30
- // ../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/index.js
30
+ // ../../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/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/binaries/yoga-wasm-base64-esm.js
54
+ // ../../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/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/generated/YGEnums.js
1359
+ // ../../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/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/wrapAssembly.js
1562
+ // ../../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/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/index.js
1664
+ // ../../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
 
@@ -2079,7 +2079,7 @@ var isShiftKey = (code) => {
2079
2079
  var isCtrlKey = (code) => {
2080
2080
  return ["Oa", "Ob", "Oc", "Od", "Oe", "[2^", "[3^", "[5^", "[6^", "[7^", "[8^"].includes(code);
2081
2081
  };
2082
- var ghosttyModifiedKeyRe = /^\x1b\[27;(\d+);(\d+)~$/;
2082
+ var modifyOtherKeysRe = /^\x1b\[27;(\d+);(\d+)~$/;
2083
2083
  var parseKeypress = (s = "", options = {}) => {
2084
2084
  let parts;
2085
2085
  if (Buffer2.isBuffer(s)) {
@@ -2100,6 +2100,27 @@ var parseKeypress = (s = "", options = {}) => {
2100
2100
  if (s.startsWith("\x1B[M") && s.length >= 6) {
2101
2101
  return null;
2102
2102
  }
2103
+ if (/^\x1b\[\d+;\d+;\d+t$/.test(s)) {
2104
+ return null;
2105
+ }
2106
+ if (/^\x1b\[\d+;\d+R$/.test(s)) {
2107
+ return null;
2108
+ }
2109
+ if (/^\x1b\[\?[\d;]+c$/.test(s)) {
2110
+ return null;
2111
+ }
2112
+ if (/^\x1b\[\?[\d;]+\$y$/.test(s)) {
2113
+ return null;
2114
+ }
2115
+ if (s === "\x1B[I" || s === "\x1B[O") {
2116
+ return null;
2117
+ }
2118
+ if (/^\x1b\][\d;].*(\x1b\\|\x07)$/.test(s)) {
2119
+ return null;
2120
+ }
2121
+ if (s === "\x1B[200~" || s === "\x1B[201~") {
2122
+ return null;
2123
+ }
2103
2124
  const key = {
2104
2125
  name: "",
2105
2126
  ctrl: false,
@@ -2119,10 +2140,10 @@ var parseKeypress = (s = "", options = {}) => {
2119
2140
  return kittyResult;
2120
2141
  }
2121
2142
  }
2122
- const ghosttyMatch = ghosttyModifiedKeyRe.exec(s);
2123
- if (ghosttyMatch) {
2124
- const modifier = parseInt(ghosttyMatch[1], 10) - 1;
2125
- const charCode = parseInt(ghosttyMatch[2], 10);
2143
+ const modifyOtherKeysMatch = modifyOtherKeysRe.exec(s);
2144
+ if (modifyOtherKeysMatch) {
2145
+ const modifier = parseInt(modifyOtherKeysMatch[1], 10) - 1;
2146
+ const charCode = parseInt(modifyOtherKeysMatch[2], 10);
2126
2147
  key.ctrl = !!(modifier & 4);
2127
2148
  key.meta = !!(modifier & 10);
2128
2149
  key.shift = !!(modifier & 1);
@@ -2214,201 +2235,8 @@ var parseKeypress = (s = "", options = {}) => {
2214
2235
  return key;
2215
2236
  };
2216
2237
 
2217
- // src/lib/stdin-buffer.ts
2218
- import { EventEmitter } from "events";
2219
- var ESC = "\x1B";
2220
- function isCompleteSequence(data) {
2221
- if (!data.startsWith(ESC)) {
2222
- return "not-escape";
2223
- }
2224
- if (data.length === 1) {
2225
- return "incomplete";
2226
- }
2227
- const afterEsc = data.slice(1);
2228
- if (afterEsc.startsWith("[")) {
2229
- if (afterEsc.startsWith("[M")) {
2230
- return data.length >= 6 ? "complete" : "incomplete";
2231
- }
2232
- return isCompleteCsiSequence(data);
2233
- }
2234
- if (afterEsc.startsWith("]")) {
2235
- return isCompleteOscSequence(data);
2236
- }
2237
- if (afterEsc.startsWith("O")) {
2238
- return afterEsc.length >= 2 ? "complete" : "incomplete";
2239
- }
2240
- if (afterEsc.length === 1) {
2241
- return "complete";
2242
- }
2243
- return "complete";
2244
- }
2245
- function isCompleteCsiSequence(data) {
2246
- if (!data.startsWith(ESC + "[")) {
2247
- return "complete";
2248
- }
2249
- if (data.length < 3) {
2250
- return "incomplete";
2251
- }
2252
- const payload = data.slice(2);
2253
- const lastChar = payload[payload.length - 1];
2254
- const lastCharCode = lastChar.charCodeAt(0);
2255
- if (lastCharCode >= 64 && lastCharCode <= 126) {
2256
- if (payload.startsWith("<")) {
2257
- const mouseMatch = /^<\d+;\d+;\d+[Mm]$/.test(payload);
2258
- if (mouseMatch) {
2259
- return "complete";
2260
- }
2261
- if (lastChar === "M" || lastChar === "m") {
2262
- const parts = payload.slice(1, -1).split(";");
2263
- if (parts.length === 3 && parts.every((p) => /^\d+$/.test(p))) {
2264
- return "complete";
2265
- }
2266
- }
2267
- return "incomplete";
2268
- }
2269
- return "complete";
2270
- }
2271
- return "incomplete";
2272
- }
2273
- function isCompleteOscSequence(data) {
2274
- if (!data.startsWith(ESC + "]")) {
2275
- return "complete";
2276
- }
2277
- if (data.endsWith(ESC + "\\") || data.endsWith("\x07")) {
2278
- return "complete";
2279
- }
2280
- return "incomplete";
2281
- }
2282
- function extractCompleteSequences(buffer) {
2283
- const sequences = [];
2284
- let pos = 0;
2285
- while (pos < buffer.length) {
2286
- const remaining = buffer.slice(pos);
2287
- if (remaining.startsWith(ESC)) {
2288
- let seqEnd = 1;
2289
- while (seqEnd <= remaining.length) {
2290
- const candidate = remaining.slice(0, seqEnd);
2291
- const status = isCompleteSequence(candidate);
2292
- if (status === "complete") {
2293
- sequences.push(candidate);
2294
- pos += seqEnd;
2295
- break;
2296
- } else if (status === "incomplete") {
2297
- seqEnd++;
2298
- } else {
2299
- sequences.push(candidate);
2300
- pos += seqEnd;
2301
- break;
2302
- }
2303
- }
2304
- if (seqEnd > remaining.length) {
2305
- return { sequences, remainder: remaining };
2306
- }
2307
- } else {
2308
- sequences.push(remaining[0]);
2309
- pos++;
2310
- }
2311
- }
2312
- return { sequences, remainder: "" };
2313
- }
2314
-
2315
- class StdinBuffer extends EventEmitter {
2316
- buffer = "";
2317
- timeout = null;
2318
- timeoutMs;
2319
- stdin;
2320
- stdinListener;
2321
- constructor(stdin, options = {}) {
2322
- super();
2323
- this.stdin = stdin;
2324
- this.timeoutMs = options.timeout ?? 10;
2325
- this.stdinListener = (data) => {
2326
- this.handleData(data);
2327
- };
2328
- this.stdin.on("data", this.stdinListener);
2329
- }
2330
- handleData(data) {
2331
- if (this.timeout) {
2332
- clearTimeout(this.timeout);
2333
- this.timeout = null;
2334
- }
2335
- let str;
2336
- if (Buffer.isBuffer(data)) {
2337
- if (data.length === 1 && data[0] > 127) {
2338
- const byte = data[0] - 128;
2339
- str = "\x1B" + String.fromCharCode(byte);
2340
- } else {
2341
- str = data.toString();
2342
- }
2343
- } else {
2344
- str = data;
2345
- }
2346
- if (str.length === 0 && this.buffer.length === 0) {
2347
- this.emit("data", "");
2348
- return;
2349
- }
2350
- this.buffer += str;
2351
- const result = extractCompleteSequences(this.buffer);
2352
- this.buffer = result.remainder;
2353
- for (const sequence of result.sequences) {
2354
- this.emit("data", sequence);
2355
- }
2356
- if (this.buffer.length > 0) {
2357
- this.timeout = setTimeout(() => {
2358
- const flushed = this.flush();
2359
- for (const sequence of flushed) {
2360
- this.emit("data", sequence);
2361
- }
2362
- }, this.timeoutMs);
2363
- }
2364
- }
2365
- flush() {
2366
- if (this.timeout) {
2367
- clearTimeout(this.timeout);
2368
- this.timeout = null;
2369
- }
2370
- if (this.buffer.length === 0) {
2371
- return [];
2372
- }
2373
- const sequences = [this.buffer];
2374
- this.buffer = "";
2375
- return sequences;
2376
- }
2377
- clear() {
2378
- if (this.timeout) {
2379
- clearTimeout(this.timeout);
2380
- this.timeout = null;
2381
- }
2382
- this.buffer = "";
2383
- }
2384
- getBuffer() {
2385
- return this.buffer;
2386
- }
2387
- destroy() {
2388
- this.stdin.removeListener("data", this.stdinListener);
2389
- this.clear();
2390
- }
2391
- }
2392
-
2393
- // src/lib/KeyHandler.ts
2394
- import { EventEmitter as EventEmitter2 } from "events";
2395
-
2396
- // src/ansi.ts
2397
- var ANSI = {
2398
- switchToAlternateScreen: "\x1B[?1049h",
2399
- switchToMainScreen: "\x1B[?1049l",
2400
- reset: "\x1B[0m",
2401
- scrollDown: (lines) => `\x1B[${lines}T`,
2402
- scrollUp: (lines) => `\x1B[${lines}S`,
2403
- moveCursor: (row, col) => `\x1B[${row};${col}H`,
2404
- moveCursorAndClear: (row, col) => `\x1B[${row};${col}H\x1B[J`,
2405
- setRgbBackground: (r, g, b) => `\x1B[48;2;${r};${g};${b}m`,
2406
- resetBackground: "\x1B[49m",
2407
- bracketedPasteStart: "\x1B[200~",
2408
- bracketedPasteEnd: "\x1B[201~"
2409
- };
2410
-
2411
2238
  // src/lib/KeyHandler.ts
2239
+ import { EventEmitter } from "events";
2412
2240
  class KeyEvent {
2413
2241
  name;
2414
2242
  ctrl;
@@ -2467,40 +2295,20 @@ class PasteEvent {
2467
2295
  }
2468
2296
  }
2469
2297
 
2470
- class KeyHandler extends EventEmitter2 {
2471
- stdin;
2298
+ class KeyHandler extends EventEmitter {
2472
2299
  useKittyKeyboard;
2473
- pasteMode = false;
2474
- pasteBuffer = [];
2475
2300
  suspended = false;
2476
- stdinBuffer;
2477
- dataListener;
2478
- constructor(stdin, useKittyKeyboard = false) {
2301
+ constructor(useKittyKeyboard = false) {
2479
2302
  super();
2480
- this.stdin = stdin || process.stdin;
2481
2303
  this.useKittyKeyboard = useKittyKeyboard;
2482
- this.stdinBuffer = new StdinBuffer(this.stdin, { timeout: 5 });
2483
- this.dataListener = (sequence) => {
2484
- this.processSequence(sequence);
2485
- };
2486
- this.stdinBuffer.on("data", this.dataListener);
2487
2304
  }
2488
- processSequence(data) {
2489
- if (data.startsWith(ANSI.bracketedPasteStart)) {
2490
- this.pasteMode = true;
2491
- }
2492
- if (this.pasteMode) {
2493
- this.pasteBuffer.push(Bun.stripANSI(data));
2494
- if (data.endsWith(ANSI.bracketedPasteEnd)) {
2495
- this.pasteMode = false;
2496
- this.emit("paste", new PasteEvent(this.pasteBuffer.join("")));
2497
- this.pasteBuffer = [];
2498
- }
2499
- return;
2305
+ processInput(data) {
2306
+ if (this.suspended) {
2307
+ return false;
2500
2308
  }
2501
2309
  const parsedKey = parseKeypress(data, { useKittyKeyboard: this.useKittyKeyboard });
2502
2310
  if (!parsedKey) {
2503
- return;
2311
+ return false;
2504
2312
  }
2505
2313
  switch (parsedKey.eventType) {
2506
2314
  case "press":
@@ -2516,29 +2324,27 @@ class KeyHandler extends EventEmitter2 {
2516
2324
  this.emit("keypress", new KeyEvent(parsedKey));
2517
2325
  break;
2518
2326
  }
2327
+ return true;
2519
2328
  }
2520
- destroy() {
2521
- this.stdinBuffer.removeListener("data", this.dataListener);
2522
- this.stdinBuffer.destroy();
2329
+ processPaste(data) {
2330
+ if (this.suspended) {
2331
+ return;
2332
+ }
2333
+ const cleanedData = Bun.stripANSI(data);
2334
+ this.emit("paste", new PasteEvent(cleanedData));
2523
2335
  }
2524
2336
  suspend() {
2525
- if (!this.suspended) {
2526
- this.suspended = true;
2527
- this.stdinBuffer.removeListener("data", this.dataListener);
2528
- }
2337
+ this.suspended = true;
2529
2338
  }
2530
2339
  resume() {
2531
- if (this.suspended) {
2532
- this.suspended = false;
2533
- this.stdinBuffer.on("data", this.dataListener);
2534
- }
2340
+ this.suspended = false;
2535
2341
  }
2536
2342
  }
2537
2343
 
2538
2344
  class InternalKeyHandler extends KeyHandler {
2539
2345
  renderableHandlers = new Map;
2540
- constructor(stdin, useKittyKeyboard = false) {
2541
- super(stdin, useKittyKeyboard);
2346
+ constructor(useKittyKeyboard = false) {
2347
+ super(useKittyKeyboard);
2542
2348
  }
2543
2349
  emit(event, ...args) {
2544
2350
  return this.emitWithPriority(event, ...args);
@@ -4524,87 +4330,327 @@ function t(strings, ...values) {
4524
4330
  });
4525
4331
  }
4526
4332
  }
4527
- return new StyledText(chunks);
4333
+ return new StyledText(chunks);
4334
+ }
4335
+
4336
+ // src/lib/hast-styled-text.ts
4337
+ function hastToTextChunks(node, syntaxStyle, parentStyles = []) {
4338
+ const chunks = [];
4339
+ if (node.type === "text") {
4340
+ const stylesToMerge = parentStyles.length > 0 ? parentStyles : ["default"];
4341
+ const mergedStyle = syntaxStyle.mergeStyles(...stylesToMerge);
4342
+ chunks.push({
4343
+ __isChunk: true,
4344
+ text: node.value,
4345
+ fg: mergedStyle.fg,
4346
+ bg: mergedStyle.bg,
4347
+ attributes: mergedStyle.attributes
4348
+ });
4349
+ } else if (node.type === "element") {
4350
+ let currentStyles = [...parentStyles];
4351
+ if (node.properties?.className) {
4352
+ const classes = node.properties.className.split(" ");
4353
+ for (const cls of classes) {
4354
+ currentStyles.push(cls);
4355
+ }
4356
+ }
4357
+ for (const child of node.children) {
4358
+ chunks.push(...hastToTextChunks(child, syntaxStyle, currentStyles));
4359
+ }
4360
+ }
4361
+ return chunks;
4362
+ }
4363
+ function hastToStyledText(hast, syntaxStyle) {
4364
+ const chunks = hastToTextChunks(hast, syntaxStyle);
4365
+ return new StyledText(chunks);
4366
+ }
4367
+
4368
+ // src/lib/scroll-acceleration.ts
4369
+ class LinearScrollAccel {
4370
+ tick(_now) {
4371
+ return 1;
4372
+ }
4373
+ reset() {}
4374
+ }
4375
+
4376
+ class MacOSScrollAccel {
4377
+ opts;
4378
+ lastTickTime = 0;
4379
+ velocityHistory = [];
4380
+ historySize = 3;
4381
+ streakTimeout = 150;
4382
+ minTickInterval = 6;
4383
+ constructor(opts = {}) {
4384
+ this.opts = opts;
4385
+ }
4386
+ tick(now = Date.now()) {
4387
+ const A = this.opts.A ?? 0.8;
4388
+ const tau = this.opts.tau ?? 3;
4389
+ const maxMultiplier = this.opts.maxMultiplier ?? 6;
4390
+ const dt = this.lastTickTime ? now - this.lastTickTime : Infinity;
4391
+ if (dt === Infinity || dt > this.streakTimeout) {
4392
+ this.lastTickTime = now;
4393
+ this.velocityHistory = [];
4394
+ return 1;
4395
+ }
4396
+ if (dt < this.minTickInterval) {
4397
+ return 1;
4398
+ }
4399
+ this.lastTickTime = now;
4400
+ this.velocityHistory.push(dt);
4401
+ if (this.velocityHistory.length > this.historySize) {
4402
+ this.velocityHistory.shift();
4403
+ }
4404
+ const avgInterval = this.velocityHistory.reduce((a, b) => a + b, 0) / this.velocityHistory.length;
4405
+ const referenceInterval = 100;
4406
+ const velocity = referenceInterval / avgInterval;
4407
+ const x = velocity / tau;
4408
+ const multiplier = 1 + A * (Math.exp(x) - 1);
4409
+ return Math.min(multiplier, maxMultiplier);
4410
+ }
4411
+ reset() {
4412
+ this.lastTickTime = 0;
4413
+ this.velocityHistory = [];
4414
+ }
4415
+ }
4416
+
4417
+ // src/lib/stdin-buffer.ts
4418
+ import { EventEmitter as EventEmitter2 } from "events";
4419
+ var ESC = "\x1B";
4420
+ var BRACKETED_PASTE_START = "\x1B[200~";
4421
+ var BRACKETED_PASTE_END = "\x1B[201~";
4422
+ function isCompleteSequence(data) {
4423
+ if (!data.startsWith(ESC)) {
4424
+ return "not-escape";
4425
+ }
4426
+ if (data.length === 1) {
4427
+ return "incomplete";
4428
+ }
4429
+ const afterEsc = data.slice(1);
4430
+ if (afterEsc.startsWith("[")) {
4431
+ if (afterEsc.startsWith("[M")) {
4432
+ return data.length >= 6 ? "complete" : "incomplete";
4433
+ }
4434
+ return isCompleteCsiSequence(data);
4435
+ }
4436
+ if (afterEsc.startsWith("]")) {
4437
+ return isCompleteOscSequence(data);
4438
+ }
4439
+ if (afterEsc.startsWith("P")) {
4440
+ return isCompleteDcsSequence(data);
4441
+ }
4442
+ if (afterEsc.startsWith("_")) {
4443
+ return isCompleteApcSequence(data);
4444
+ }
4445
+ if (afterEsc.startsWith("O")) {
4446
+ return afterEsc.length >= 2 ? "complete" : "incomplete";
4447
+ }
4448
+ if (afterEsc.length === 1) {
4449
+ return "complete";
4450
+ }
4451
+ return "complete";
4452
+ }
4453
+ function isCompleteCsiSequence(data) {
4454
+ if (!data.startsWith(ESC + "[")) {
4455
+ return "complete";
4456
+ }
4457
+ if (data.length < 3) {
4458
+ return "incomplete";
4459
+ }
4460
+ const payload = data.slice(2);
4461
+ const lastChar = payload[payload.length - 1];
4462
+ const lastCharCode = lastChar.charCodeAt(0);
4463
+ if (lastCharCode >= 64 && lastCharCode <= 126) {
4464
+ if (payload.startsWith("<")) {
4465
+ const mouseMatch = /^<\d+;\d+;\d+[Mm]$/.test(payload);
4466
+ if (mouseMatch) {
4467
+ return "complete";
4468
+ }
4469
+ if (lastChar === "M" || lastChar === "m") {
4470
+ const parts = payload.slice(1, -1).split(";");
4471
+ if (parts.length === 3 && parts.every((p) => /^\d+$/.test(p))) {
4472
+ return "complete";
4473
+ }
4474
+ }
4475
+ return "incomplete";
4476
+ }
4477
+ return "complete";
4478
+ }
4479
+ return "incomplete";
4480
+ }
4481
+ function isCompleteOscSequence(data) {
4482
+ if (!data.startsWith(ESC + "]")) {
4483
+ return "complete";
4484
+ }
4485
+ if (data.endsWith(ESC + "\\") || data.endsWith("\x07")) {
4486
+ return "complete";
4487
+ }
4488
+ return "incomplete";
4489
+ }
4490
+ function isCompleteDcsSequence(data) {
4491
+ if (!data.startsWith(ESC + "P")) {
4492
+ return "complete";
4493
+ }
4494
+ if (data.endsWith(ESC + "\\")) {
4495
+ return "complete";
4496
+ }
4497
+ return "incomplete";
4498
+ }
4499
+ function isCompleteApcSequence(data) {
4500
+ if (!data.startsWith(ESC + "_")) {
4501
+ return "complete";
4502
+ }
4503
+ if (data.endsWith(ESC + "\\")) {
4504
+ return "complete";
4505
+ }
4506
+ return "incomplete";
4507
+ }
4508
+ function extractCompleteSequences(buffer) {
4509
+ const sequences = [];
4510
+ let pos = 0;
4511
+ while (pos < buffer.length) {
4512
+ const remaining = buffer.slice(pos);
4513
+ if (remaining.startsWith(ESC)) {
4514
+ let seqEnd = 1;
4515
+ while (seqEnd <= remaining.length) {
4516
+ const candidate = remaining.slice(0, seqEnd);
4517
+ const status = isCompleteSequence(candidate);
4518
+ if (status === "complete") {
4519
+ sequences.push(candidate);
4520
+ pos += seqEnd;
4521
+ break;
4522
+ } else if (status === "incomplete") {
4523
+ seqEnd++;
4524
+ } else {
4525
+ sequences.push(candidate);
4526
+ pos += seqEnd;
4527
+ break;
4528
+ }
4529
+ }
4530
+ if (seqEnd > remaining.length) {
4531
+ return { sequences, remainder: remaining };
4532
+ }
4533
+ } else {
4534
+ sequences.push(remaining[0]);
4535
+ pos++;
4536
+ }
4537
+ }
4538
+ return { sequences, remainder: "" };
4528
4539
  }
4529
4540
 
4530
- // src/lib/hast-styled-text.ts
4531
- function hastToTextChunks(node, syntaxStyle, parentStyles = []) {
4532
- const chunks = [];
4533
- if (node.type === "text") {
4534
- const stylesToMerge = parentStyles.length > 0 ? parentStyles : ["default"];
4535
- const mergedStyle = syntaxStyle.mergeStyles(...stylesToMerge);
4536
- chunks.push({
4537
- __isChunk: true,
4538
- text: node.value,
4539
- fg: mergedStyle.fg,
4540
- bg: mergedStyle.bg,
4541
- attributes: mergedStyle.attributes
4542
- });
4543
- } else if (node.type === "element") {
4544
- let currentStyles = [...parentStyles];
4545
- if (node.properties?.className) {
4546
- const classes = node.properties.className.split(" ");
4547
- for (const cls of classes) {
4548
- currentStyles.push(cls);
4541
+ class StdinBuffer extends EventEmitter2 {
4542
+ buffer = "";
4543
+ timeout = null;
4544
+ timeoutMs;
4545
+ pasteMode = false;
4546
+ pasteBuffer = "";
4547
+ constructor(options = {}) {
4548
+ super();
4549
+ this.timeoutMs = options.timeout ?? 10;
4550
+ }
4551
+ process(data) {
4552
+ if (this.timeout) {
4553
+ clearTimeout(this.timeout);
4554
+ this.timeout = null;
4555
+ }
4556
+ let str;
4557
+ if (Buffer.isBuffer(data)) {
4558
+ if (data.length === 1 && data[0] > 127) {
4559
+ const byte = data[0] - 128;
4560
+ str = "\x1B" + String.fromCharCode(byte);
4561
+ } else {
4562
+ str = data.toString();
4549
4563
  }
4564
+ } else {
4565
+ str = data;
4550
4566
  }
4551
- for (const child of node.children) {
4552
- chunks.push(...hastToTextChunks(child, syntaxStyle, currentStyles));
4567
+ if (str.length === 0 && this.buffer.length === 0) {
4568
+ this.emit("data", "");
4569
+ return;
4570
+ }
4571
+ this.buffer += str;
4572
+ if (this.pasteMode) {
4573
+ this.pasteBuffer += this.buffer;
4574
+ this.buffer = "";
4575
+ const endIndex = this.pasteBuffer.indexOf(BRACKETED_PASTE_END);
4576
+ if (endIndex !== -1) {
4577
+ const pastedContent = this.pasteBuffer.slice(0, endIndex);
4578
+ const remaining = this.pasteBuffer.slice(endIndex + BRACKETED_PASTE_END.length);
4579
+ this.pasteMode = false;
4580
+ this.pasteBuffer = "";
4581
+ this.emit("paste", pastedContent);
4582
+ if (remaining.length > 0) {
4583
+ this.process(remaining);
4584
+ }
4585
+ }
4586
+ return;
4587
+ }
4588
+ const startIndex = this.buffer.indexOf(BRACKETED_PASTE_START);
4589
+ if (startIndex !== -1) {
4590
+ if (startIndex > 0) {
4591
+ const beforePaste = this.buffer.slice(0, startIndex);
4592
+ const result2 = extractCompleteSequences(beforePaste);
4593
+ for (const sequence of result2.sequences) {
4594
+ this.emit("data", sequence);
4595
+ }
4596
+ }
4597
+ this.buffer = this.buffer.slice(startIndex + BRACKETED_PASTE_START.length);
4598
+ this.pasteMode = true;
4599
+ this.pasteBuffer = this.buffer;
4600
+ this.buffer = "";
4601
+ const endIndex = this.pasteBuffer.indexOf(BRACKETED_PASTE_END);
4602
+ if (endIndex !== -1) {
4603
+ const pastedContent = this.pasteBuffer.slice(0, endIndex);
4604
+ const remaining = this.pasteBuffer.slice(endIndex + BRACKETED_PASTE_END.length);
4605
+ this.pasteMode = false;
4606
+ this.pasteBuffer = "";
4607
+ this.emit("paste", pastedContent);
4608
+ if (remaining.length > 0) {
4609
+ this.process(remaining);
4610
+ }
4611
+ }
4612
+ return;
4613
+ }
4614
+ const result = extractCompleteSequences(this.buffer);
4615
+ this.buffer = result.remainder;
4616
+ for (const sequence of result.sequences) {
4617
+ this.emit("data", sequence);
4618
+ }
4619
+ if (this.buffer.length > 0) {
4620
+ this.timeout = setTimeout(() => {
4621
+ const flushed = this.flush();
4622
+ for (const sequence of flushed) {
4623
+ this.emit("data", sequence);
4624
+ }
4625
+ }, this.timeoutMs);
4553
4626
  }
4554
4627
  }
4555
- return chunks;
4556
- }
4557
- function hastToStyledText(hast, syntaxStyle) {
4558
- const chunks = hastToTextChunks(hast, syntaxStyle);
4559
- return new StyledText(chunks);
4560
- }
4561
-
4562
- // src/lib/scroll-acceleration.ts
4563
- class LinearScrollAccel {
4564
- tick(_now) {
4565
- return 1;
4566
- }
4567
- reset() {}
4568
- }
4569
-
4570
- class MacOSScrollAccel {
4571
- opts;
4572
- lastTickTime = 0;
4573
- velocityHistory = [];
4574
- historySize = 3;
4575
- streakTimeout = 150;
4576
- minTickInterval = 6;
4577
- constructor(opts = {}) {
4578
- this.opts = opts;
4579
- }
4580
- tick(now = Date.now()) {
4581
- const A = this.opts.A ?? 0.8;
4582
- const tau = this.opts.tau ?? 3;
4583
- const maxMultiplier = this.opts.maxMultiplier ?? 6;
4584
- const dt = this.lastTickTime ? now - this.lastTickTime : Infinity;
4585
- if (dt === Infinity || dt > this.streakTimeout) {
4586
- this.lastTickTime = now;
4587
- this.velocityHistory = [];
4588
- return 1;
4628
+ flush() {
4629
+ if (this.timeout) {
4630
+ clearTimeout(this.timeout);
4631
+ this.timeout = null;
4589
4632
  }
4590
- if (dt < this.minTickInterval) {
4591
- return 1;
4633
+ if (this.buffer.length === 0) {
4634
+ return [];
4592
4635
  }
4593
- this.lastTickTime = now;
4594
- this.velocityHistory.push(dt);
4595
- if (this.velocityHistory.length > this.historySize) {
4596
- this.velocityHistory.shift();
4636
+ const sequences = [this.buffer];
4637
+ this.buffer = "";
4638
+ return sequences;
4639
+ }
4640
+ clear() {
4641
+ if (this.timeout) {
4642
+ clearTimeout(this.timeout);
4643
+ this.timeout = null;
4597
4644
  }
4598
- const avgInterval = this.velocityHistory.reduce((a, b) => a + b, 0) / this.velocityHistory.length;
4599
- const referenceInterval = 100;
4600
- const velocity = referenceInterval / avgInterval;
4601
- const x = velocity / tau;
4602
- const multiplier = 1 + A * (Math.exp(x) - 1);
4603
- return Math.min(multiplier, maxMultiplier);
4645
+ this.buffer = "";
4646
+ this.pasteMode = false;
4647
+ this.pasteBuffer = "";
4604
4648
  }
4605
- reset() {
4606
- this.lastTickTime = 0;
4607
- this.velocityHistory = [];
4649
+ getBuffer() {
4650
+ return this.buffer;
4651
+ }
4652
+ destroy() {
4653
+ this.clear();
4608
4654
  }
4609
4655
  }
4610
4656
 
@@ -7844,7 +7890,7 @@ class OptimizedBuffer {
7844
7890
  }
7845
7891
  }
7846
7892
 
7847
- // ../../node_modules/.bun/bun-ffi-structs@0.1.0+ca84541ac88a3075/node_modules/bun-ffi-structs/index.js
7893
+ // ../../node_modules/bun-ffi-structs/index.js
7848
7894
  import { ptr, toArrayBuffer as toArrayBuffer2 } from "bun:ffi";
7849
7895
  function fatalError(...args) {
7850
7896
  const message = args.join(" ");
@@ -7889,6 +7935,23 @@ function isObjectPointerDef(type) {
7889
7935
  function alignOffset(offset, align) {
7890
7936
  return offset + (align - 1) & ~(align - 1);
7891
7937
  }
7938
+ function enumTypeError(value) {
7939
+ throw new TypeError(`Invalid enum value: ${value}`);
7940
+ }
7941
+ function defineEnum(mapping, base = "u32") {
7942
+ const reverse2 = Object.fromEntries(Object.entries(mapping).map(([k, v]) => [v, k]));
7943
+ return {
7944
+ __type: "enum",
7945
+ type: base,
7946
+ to(value) {
7947
+ return typeof value === "number" ? value : mapping[value] ?? enumTypeError(String(value));
7948
+ },
7949
+ from(value) {
7950
+ return reverse2[value] ?? enumTypeError(String(value));
7951
+ },
7952
+ enum: mapping
7953
+ };
7954
+ }
7892
7955
  function isEnum(type) {
7893
7956
  return typeof type === "object" && type.__type === "enum";
7894
7957
  }
@@ -7965,6 +8028,7 @@ function packObjectArray(val) {
7965
8028
  return bufferView;
7966
8029
  }
7967
8030
  var encoder = new TextEncoder;
8031
+ var decoder = new TextDecoder;
7968
8032
  function defineStruct(fields, structDefOptions) {
7969
8033
  let offset = 0;
7970
8034
  let maxAlign = 1;
@@ -8007,6 +8071,7 @@ function defineStruct(fields, structDefOptions) {
8007
8071
  const ptrVal = pointerUnpacker(view, off);
8008
8072
  return ptrVal;
8009
8073
  };
8074
+ needsLengthOf = true;
8010
8075
  } else if (isEnum(typeOrStruct)) {
8011
8076
  const base = typeOrStruct.type;
8012
8077
  size = typeSizes[base];
@@ -8209,9 +8274,10 @@ function defineStruct(fields, structDefOptions) {
8209
8274
  lengthOfFields[options.lengthOf] = layoutField;
8210
8275
  }
8211
8276
  if (needsLengthOf) {
8212
- if (!lengthOfDef)
8213
- fatalError(`Internal error: needsLengthOf=true but lengthOfDef is null for ${name}`);
8214
- lengthOfRequested.push({ requester: layoutField, def: lengthOfDef });
8277
+ const def = typeof typeOrStruct === "string" && typeOrStruct === "char*" ? "char*" : lengthOfDef;
8278
+ if (!def)
8279
+ fatalError(`Internal error: needsLengthOf=true but def is null for ${name}`);
8280
+ lengthOfRequested.push({ requester: layoutField, def });
8215
8281
  }
8216
8282
  offset += size;
8217
8283
  maxAlign = Math.max(maxAlign, align);
@@ -8219,9 +8285,26 @@ function defineStruct(fields, structDefOptions) {
8219
8285
  for (const { requester, def } of lengthOfRequested) {
8220
8286
  const lengthOfField = lengthOfFields[requester.name];
8221
8287
  if (!lengthOfField) {
8288
+ if (def === "char*") {
8289
+ continue;
8290
+ }
8222
8291
  throw new Error(`lengthOf field not found for array field ${requester.name}`);
8223
8292
  }
8224
- if (isPrimitiveType(def)) {
8293
+ if (def === "char*") {
8294
+ requester.unpack = (view, off) => {
8295
+ const ptrAddress = pointerUnpacker(view, off);
8296
+ const length = lengthOfField.unpack(view, lengthOfField.offset);
8297
+ if (ptrAddress === 0) {
8298
+ return null;
8299
+ }
8300
+ const byteLength = typeof length === "bigint" ? Number(length) : length;
8301
+ if (byteLength === 0) {
8302
+ return "";
8303
+ }
8304
+ const buffer = toArrayBuffer2(ptrAddress, 0, byteLength);
8305
+ return decoder.decode(buffer);
8306
+ };
8307
+ } else if (isPrimitiveType(def)) {
8225
8308
  const elemSize = typeSizes[def];
8226
8309
  const { unpack: primitiveUnpack } = primitivePackers(def);
8227
8310
  requester.unpack = (view, off) => {
@@ -8461,6 +8544,27 @@ var VisualCursorStruct = defineStruct([
8461
8544
  ["logicalCol", "u32"],
8462
8545
  ["offset", "u32"]
8463
8546
  ]);
8547
+ var UnicodeMethodEnum = defineEnum({ wcwidth: 0, unicode: 1 }, "u8");
8548
+ var TerminalCapabilitiesStruct = defineStruct([
8549
+ ["kitty_keyboard", "bool_u8"],
8550
+ ["kitty_graphics", "bool_u8"],
8551
+ ["rgb", "bool_u8"],
8552
+ ["unicode", UnicodeMethodEnum],
8553
+ ["sgr_pixels", "bool_u8"],
8554
+ ["color_scheme_updates", "bool_u8"],
8555
+ ["explicit_width", "bool_u8"],
8556
+ ["scaled_text", "bool_u8"],
8557
+ ["sixel", "bool_u8"],
8558
+ ["focus_tracking", "bool_u8"],
8559
+ ["sync", "bool_u8"],
8560
+ ["bracketed_paste", "bool_u8"],
8561
+ ["hyperlinks", "bool_u8"],
8562
+ ["term_name", "char*"],
8563
+ ["term_name_len", "u64", { lengthOf: "term_name" }],
8564
+ ["term_version", "char*"],
8565
+ ["term_version_len", "u64", { lengthOf: "term_version" }],
8566
+ ["term_from_xtversion", "bool_u8"]
8567
+ ]);
8464
8568
 
8465
8569
  // src/zig.ts
8466
8570
  var module = await import(`@opentui/core-${process.platform}-${process.arch}/index.ts`);
@@ -8782,6 +8886,14 @@ function getOpenTUILib(libPath) {
8782
8886
  args: ["ptr", "u8"],
8783
8887
  returns: "void"
8784
8888
  },
8889
+ textBufferAppend: {
8890
+ args: ["ptr", "ptr", "usize"],
8891
+ returns: "void"
8892
+ },
8893
+ textBufferAppendFromMemId: {
8894
+ args: ["ptr", "u8"],
8895
+ returns: "void"
8896
+ },
8785
8897
  textBufferLoadFile: {
8786
8898
  args: ["ptr", "ptr", "usize"],
8787
8899
  returns: "bool"
@@ -9745,6 +9857,12 @@ class FFIRenderLib {
9745
9857
  textBufferSetTextFromMem(buffer, memId) {
9746
9858
  this.opentui.symbols.textBufferSetTextFromMem(buffer, memId);
9747
9859
  }
9860
+ textBufferAppend(buffer, bytes) {
9861
+ this.opentui.symbols.textBufferAppend(buffer, bytes, bytes.length);
9862
+ }
9863
+ textBufferAppendFromMemId(buffer, memId) {
9864
+ this.opentui.symbols.textBufferAppendFromMemId(buffer, memId);
9865
+ }
9748
9866
  textBufferLoadFile(buffer, path4) {
9749
9867
  const pathBytes = this.encoder.encode(path4);
9750
9868
  return this.opentui.symbols.textBufferLoadFile(buffer, pathBytes, pathBytes.length);
@@ -10276,25 +10394,29 @@ class FFIRenderLib {
10276
10394
  this.opentui.symbols.bufferClearScissorRects(buffer);
10277
10395
  }
10278
10396
  getTerminalCapabilities(renderer) {
10279
- const capsBuffer = new Uint8Array(64);
10280
- this.opentui.symbols.getTerminalCapabilities(renderer, capsBuffer);
10281
- let offset = 0;
10282
- const capabilities = {
10283
- kitty_keyboard: capsBuffer[offset++] !== 0,
10284
- kitty_graphics: capsBuffer[offset++] !== 0,
10285
- rgb: capsBuffer[offset++] !== 0,
10286
- unicode: capsBuffer[offset++] === 0 ? "wcwidth" : "unicode",
10287
- sgr_pixels: capsBuffer[offset++] !== 0,
10288
- color_scheme_updates: capsBuffer[offset++] !== 0,
10289
- explicit_width: capsBuffer[offset++] !== 0,
10290
- scaled_text: capsBuffer[offset++] !== 0,
10291
- sixel: capsBuffer[offset++] !== 0,
10292
- focus_tracking: capsBuffer[offset++] !== 0,
10293
- sync: capsBuffer[offset++] !== 0,
10294
- bracketed_paste: capsBuffer[offset++] !== 0,
10295
- hyperlinks: capsBuffer[offset++] !== 0
10397
+ const capsBuffer = new ArrayBuffer(TerminalCapabilitiesStruct.size);
10398
+ this.opentui.symbols.getTerminalCapabilities(renderer, ptr3(capsBuffer));
10399
+ const caps = TerminalCapabilitiesStruct.unpack(capsBuffer);
10400
+ return {
10401
+ kitty_keyboard: caps.kitty_keyboard,
10402
+ kitty_graphics: caps.kitty_graphics,
10403
+ rgb: caps.rgb,
10404
+ unicode: caps.unicode,
10405
+ sgr_pixels: caps.sgr_pixels,
10406
+ color_scheme_updates: caps.color_scheme_updates,
10407
+ explicit_width: caps.explicit_width,
10408
+ scaled_text: caps.scaled_text,
10409
+ sixel: caps.sixel,
10410
+ focus_tracking: caps.focus_tracking,
10411
+ sync: caps.sync,
10412
+ bracketed_paste: caps.bracketed_paste,
10413
+ hyperlinks: caps.hyperlinks,
10414
+ terminal: {
10415
+ name: caps.term_name ?? "",
10416
+ version: caps.term_version ?? "",
10417
+ from_xtversion: caps.term_from_xtversion
10418
+ }
10296
10419
  };
10297
- return capabilities;
10298
10420
  }
10299
10421
  processCapabilityResponse(renderer, response) {
10300
10422
  const responseBytes = this.encoder.encode(response);
@@ -10386,6 +10508,7 @@ class TextBuffer {
10386
10508
  _syntaxStyle;
10387
10509
  _textBytes;
10388
10510
  _memId;
10511
+ _appendedChunks = [];
10389
10512
  constructor(lib, ptr4) {
10390
10513
  this.lib = lib;
10391
10514
  this.bufferPtr = ptr4;
@@ -10410,6 +10533,16 @@ class TextBuffer {
10410
10533
  this._length = this.lib.textBufferGetLength(this.bufferPtr);
10411
10534
  this._byteSize = this.lib.textBufferGetByteSize(this.bufferPtr);
10412
10535
  this._lineInfo = undefined;
10536
+ this._appendedChunks = [];
10537
+ }
10538
+ append(text) {
10539
+ this.guard();
10540
+ const textBytes = this.lib.encoder.encode(text);
10541
+ this._appendedChunks.push(textBytes);
10542
+ this.lib.textBufferAppend(this.bufferPtr, textBytes);
10543
+ this._length = this.lib.textBufferGetLength(this.bufferPtr);
10544
+ this._byteSize = this.lib.textBufferGetByteSize(this.bufferPtr);
10545
+ this._lineInfo = undefined;
10413
10546
  }
10414
10547
  loadFile(path4) {
10415
10548
  this.guard();
@@ -10535,6 +10668,7 @@ class TextBuffer {
10535
10668
  this._byteSize = 0;
10536
10669
  this._lineInfo = undefined;
10537
10670
  this._textBytes = undefined;
10671
+ this._appendedChunks = [];
10538
10672
  }
10539
10673
  reset() {
10540
10674
  this.guard();
@@ -10544,6 +10678,7 @@ class TextBuffer {
10544
10678
  this._lineInfo = undefined;
10545
10679
  this._textBytes = undefined;
10546
10680
  this._memId = undefined;
10681
+ this._appendedChunks = [];
10547
10682
  }
10548
10683
  destroy() {
10549
10684
  if (this._destroyed)
@@ -12607,6 +12742,21 @@ class TerminalConsole extends EventEmitter8 {
12607
12742
  }
12608
12743
  }
12609
12744
 
12745
+ // src/ansi.ts
12746
+ var ANSI = {
12747
+ switchToAlternateScreen: "\x1B[?1049h",
12748
+ switchToMainScreen: "\x1B[?1049l",
12749
+ reset: "\x1B[0m",
12750
+ scrollDown: (lines) => `\x1B[${lines}T`,
12751
+ scrollUp: (lines) => `\x1B[${lines}S`,
12752
+ moveCursor: (row, col) => `\x1B[${row};${col}H`,
12753
+ moveCursorAndClear: (row, col) => `\x1B[${row};${col}H\x1B[J`,
12754
+ setRgbBackground: (r, g, b) => `\x1B[48;2;${r};${g};${b}m`,
12755
+ resetBackground: "\x1B[49m",
12756
+ bracketedPasteStart: "\x1B[200~",
12757
+ bracketedPasteEnd: "\x1B[201~"
12758
+ };
12759
+
12610
12760
  // src/renderer.ts
12611
12761
  import { EventEmitter as EventEmitter9 } from "events";
12612
12762
 
@@ -12700,6 +12850,42 @@ function getObjectsInViewport(viewport, objects, direction = "column", padding =
12700
12850
  return visibleChildren;
12701
12851
  }
12702
12852
 
12853
+ // src/lib/terminal-capability-detection.ts
12854
+ function isCapabilityResponse(sequence) {
12855
+ if (/\x1b\[\?\d+(?:;\d+)*\$y/.test(sequence)) {
12856
+ return true;
12857
+ }
12858
+ if (/\x1b\[1;(?!1R)\d+R/.test(sequence)) {
12859
+ return true;
12860
+ }
12861
+ if (/\x1bP>\|[\s\S]*?\x1b\\/.test(sequence)) {
12862
+ return true;
12863
+ }
12864
+ if (/\x1b_G[\s\S]*?\x1b\\/.test(sequence)) {
12865
+ return true;
12866
+ }
12867
+ if (/\x1b\[\?\d+(?:;\d+)?u/.test(sequence)) {
12868
+ return true;
12869
+ }
12870
+ if (/\x1b\[\?[0-9;]*c/.test(sequence)) {
12871
+ return true;
12872
+ }
12873
+ return false;
12874
+ }
12875
+ function isPixelResolutionResponse(sequence) {
12876
+ return /\x1b\[4;\d+;\d+t/.test(sequence);
12877
+ }
12878
+ function parsePixelResolution(sequence) {
12879
+ const match = sequence.match(/\x1b\[4;(\d+);(\d+)t/);
12880
+ if (match) {
12881
+ return {
12882
+ width: parseInt(match[2]),
12883
+ height: parseInt(match[1])
12884
+ };
12885
+ }
12886
+ return null;
12887
+ }
12888
+
12703
12889
  // src/renderer.ts
12704
12890
  registerEnvVar({
12705
12891
  name: "OTUI_DUMP_CAPTURES",
@@ -12892,6 +13078,7 @@ class CliRenderer extends EventEmitter9 {
12892
13078
  _console;
12893
13079
  _resolution = null;
12894
13080
  _keyHandler;
13081
+ _stdinBuffer;
12895
13082
  animationRequest = new Map;
12896
13083
  resizeTimeoutId = null;
12897
13084
  resizeDebounceDelay = 100;
@@ -12931,6 +13118,8 @@ class CliRenderer extends EventEmitter9 {
12931
13118
  _paletteDetector = null;
12932
13119
  _cachedPalette = null;
12933
13120
  _paletteDetectionPromise = null;
13121
+ inputHandlers = [];
13122
+ prependedInputHandlers = [];
12934
13123
  handleError = ((error) => {
12935
13124
  console.error(error);
12936
13125
  if (this._openConsoleOnError) {
@@ -13004,6 +13193,7 @@ Captured output:
13004
13193
  this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
13005
13194
  this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
13006
13195
  this.postProcessFns = config.postProcessFns || [];
13196
+ this.prependedInputHandlers = config.prependInputHandlers || [];
13007
13197
  this.root = new RootRenderable(this);
13008
13198
  if (this.memorySnapshotInterval > 0) {
13009
13199
  this.startMemorySnapshotTimer();
@@ -13016,7 +13206,7 @@ Captured output:
13016
13206
  process.on("uncaughtException", this.handleError);
13017
13207
  process.on("unhandledRejection", this.handleError);
13018
13208
  process.on("exit", this.exitHandler);
13019
- this._keyHandler = new InternalKeyHandler(this.stdin, config.useKittyKeyboard ?? true);
13209
+ this._keyHandler = new InternalKeyHandler(config.useKittyKeyboard ?? true);
13020
13210
  this._keyHandler.on("keypress", (event) => {
13021
13211
  if (this.exitOnCtrlC && event.name === "c" && event.ctrl) {
13022
13212
  process.nextTick(() => {
@@ -13025,6 +13215,7 @@ Captured output:
13025
13215
  return;
13026
13216
  }
13027
13217
  });
13218
+ this._stdinBuffer = new StdinBuffer({ timeout: 5 });
13028
13219
  this._console = new TerminalConsole(this, config.consoleOptions);
13029
13220
  this.useConsole = config.useConsole ?? true;
13030
13221
  this._openConsoleOnError = config.openConsoleOnError ?? true;
@@ -13259,52 +13450,86 @@ Captured output:
13259
13450
  if (this._terminalIsSetup)
13260
13451
  return;
13261
13452
  this._terminalIsSetup = true;
13262
- await new Promise((resolve4) => {
13263
- const timeout = setTimeout(() => {
13264
- this.stdin.off("data", capListener);
13265
- resolve4(true);
13266
- }, 100);
13267
- const capListener = (str) => {
13268
- clearTimeout(timeout);
13269
- this.lib.processCapabilityResponse(this.rendererPtr, str);
13270
- this.stdin.off("data", capListener);
13271
- resolve4(true);
13272
- };
13273
- this.stdin.on("data", capListener);
13274
- this.lib.setupTerminal(this.rendererPtr, this._useAlternateScreen);
13275
- });
13453
+ this.lib.setupTerminal(this.rendererPtr, this._useAlternateScreen);
13276
13454
  this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
13455
+ setTimeout(() => {
13456
+ this.removeInputHandler(this.capabilityHandler);
13457
+ }, 5000);
13277
13458
  if (this._useMouse) {
13278
13459
  this.enableMouse();
13279
13460
  }
13280
13461
  this.queryPixelResolution();
13281
13462
  }
13282
13463
  stdinListener = ((data) => {
13283
- const str = data.toString();
13284
- if (this.waitingForPixelResolution && /\x1b\[4;\d+;\d+t/.test(str)) {
13285
- const match = str.match(/\x1b\[4;(\d+);(\d+)t/);
13286
- if (match) {
13287
- const resolution = {
13288
- width: parseInt(match[2]),
13289
- height: parseInt(match[1])
13290
- };
13291
- this._resolution = resolution;
13292
- this.waitingForPixelResolution = false;
13293
- return;
13294
- }
13295
- }
13296
13464
  if (this._useMouse && this.handleMouseData(data)) {
13297
13465
  return;
13298
13466
  }
13299
- this.emit("key", data);
13467
+ this._stdinBuffer.process(data);
13468
+ }).bind(this);
13469
+ addInputHandler(handler) {
13470
+ this.inputHandlers.push(handler);
13471
+ }
13472
+ prependInputHandler(handler) {
13473
+ this.inputHandlers.unshift(handler);
13474
+ }
13475
+ removeInputHandler(handler) {
13476
+ this.inputHandlers = this.inputHandlers.filter((h2) => h2 !== handler);
13477
+ }
13478
+ capabilityHandler = ((sequence) => {
13479
+ if (isCapabilityResponse(sequence)) {
13480
+ this.lib.processCapabilityResponse(this.rendererPtr, sequence);
13481
+ this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
13482
+ return true;
13483
+ }
13484
+ return false;
13485
+ }).bind(this);
13486
+ focusHandler = ((sequence) => {
13487
+ if (sequence === "\x1B[I") {
13488
+ this.emit("focus");
13489
+ return true;
13490
+ }
13491
+ if (sequence === "\x1B[O") {
13492
+ this.emit("blur");
13493
+ return true;
13494
+ }
13495
+ return false;
13300
13496
  }).bind(this);
13301
13497
  setupInput() {
13498
+ for (const handler of this.prependedInputHandlers) {
13499
+ this.addInputHandler(handler);
13500
+ }
13501
+ this.addInputHandler((sequence) => {
13502
+ if (isPixelResolutionResponse(sequence) && this.waitingForPixelResolution) {
13503
+ const resolution = parsePixelResolution(sequence);
13504
+ if (resolution) {
13505
+ this._resolution = resolution;
13506
+ this.waitingForPixelResolution = false;
13507
+ }
13508
+ return true;
13509
+ }
13510
+ return false;
13511
+ });
13512
+ this.addInputHandler(this.capabilityHandler);
13513
+ this.addInputHandler(this.focusHandler);
13514
+ this.addInputHandler((sequence) => {
13515
+ return this._keyHandler.processInput(sequence);
13516
+ });
13302
13517
  if (this.stdin.setRawMode) {
13303
13518
  this.stdin.setRawMode(true);
13304
13519
  }
13305
13520
  this.stdin.resume();
13306
13521
  this.stdin.setEncoding("utf8");
13307
13522
  this.stdin.on("data", this.stdinListener);
13523
+ this._stdinBuffer.on("data", (sequence) => {
13524
+ for (const handler of this.inputHandlers) {
13525
+ if (handler(sequence)) {
13526
+ return;
13527
+ }
13528
+ }
13529
+ });
13530
+ this._stdinBuffer.on("paste", (data) => {
13531
+ this._keyHandler.processPaste(data);
13532
+ });
13308
13533
  }
13309
13534
  handleMouseData(data) {
13310
13535
  const mouseEvent = this.mouseParser.parseMouseEvent(data);
@@ -13630,6 +13855,7 @@ Captured output:
13630
13855
  this._suspendedMouseEnabled = this._useMouse;
13631
13856
  this.disableMouse();
13632
13857
  this._keyHandler.suspend();
13858
+ this._stdinBuffer.clear();
13633
13859
  if (this.stdin.setRawMode) {
13634
13860
  this.stdin.setRawMode(false);
13635
13861
  }
@@ -13699,7 +13925,7 @@ Captured output:
13699
13925
  } catch (e) {
13700
13926
  console.error("Error destroying root renderable:", e instanceof Error ? e.stack : String(e));
13701
13927
  }
13702
- this._keyHandler.destroy();
13928
+ this._stdinBuffer.destroy();
13703
13929
  this._console.deactivate();
13704
13930
  this.disableStdoutInterception();
13705
13931
  if (this._splitHeight > 0) {
@@ -13972,7 +14198,7 @@ Captured output:
13972
14198
  }
13973
14199
  }
13974
14200
 
13975
- 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, TerminalPalette, createTerminalPalette, 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 };
14201
+ export { __toESM, __commonJS, __export, __require, Edge, Gutter, exports_src, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, nonAlphanumericKeys, parseKeypress, 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, StdinBuffer, 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, TerminalPalette, createTerminalPalette, TextBuffer, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, isValidPercentage, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, ANSI, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };
13976
14202
 
13977
- //# debugId=9EF829D1358BD55D64756E2164756E21
13978
- //# sourceMappingURL=index-d4f5t33k.js.map
14203
+ //# debugId=7BD9FAB5ED52E27064756E2164756E21
14204
+ //# sourceMappingURL=index-kj9k00yt.js.map