@opentui/core 0.0.0-20251108-0c7899b1 → 0.0.0-20251112-613689c1

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.
@@ -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);
@@ -2724,86 +2530,16 @@ var CSS_COLOR_NAMES = {
2724
2530
  function parseColor(color) {
2725
2531
  if (typeof color === "string") {
2726
2532
  const lowerColor = color.toLowerCase();
2727
- if (lowerColor === "transparent") {
2728
- return RGBA.fromValues(0, 0, 0, 0);
2729
- }
2730
- if (CSS_COLOR_NAMES[lowerColor]) {
2731
- return hexToRgb(CSS_COLOR_NAMES[lowerColor]);
2732
- }
2733
- return hexToRgb(color);
2734
- }
2735
- return color;
2736
- }
2737
- // src/lib/fonts/tiny.json
2738
- var tiny_default = {
2739
- name: "tiny",
2740
- version: "0.2.0",
2741
- homepage: "https://github.com/dominikwilkowski/cfonts",
2742
- colors: 1,
2743
- lines: 2,
2744
- buffer: ["", ""],
2745
- letterspace: [" ", " "],
2746
- letterspace_size: 1,
2747
- chars: {
2748
- A: ["\u2584\u2580\u2588", "\u2588\u2580\u2588"],
2749
- B: ["\u2588\u2584\u2584", "\u2588\u2584\u2588"],
2750
- C: ["\u2588\u2580\u2580", "\u2588\u2584\u2584"],
2751
- D: ["\u2588\u2580\u2584", "\u2588\u2584\u2580"],
2752
- E: ["\u2588\u2580\u2580", "\u2588\u2588\u2584"],
2753
- F: ["\u2588\u2580\u2580", "\u2588\u2580 "],
2754
- G: ["\u2588\u2580\u2580", "\u2588\u2584\u2588"],
2755
- H: ["\u2588 \u2588", "\u2588\u2580\u2588"],
2756
- I: ["\u2588", "\u2588"],
2757
- J: [" \u2588", "\u2588\u2584\u2588"],
2758
- K: ["\u2588\u2584\u2580", "\u2588 \u2588"],
2759
- L: ["\u2588 ", "\u2588\u2584\u2584"],
2760
- M: ["\u2588\u2580\u2584\u2580\u2588", "\u2588 \u2580 \u2588"],
2761
- N: ["\u2588\u2584 \u2588", "\u2588 \u2580\u2588"],
2762
- O: ["\u2588\u2580\u2588", "\u2588\u2584\u2588"],
2763
- P: ["\u2588\u2580\u2588", "\u2588\u2580\u2580"],
2764
- Q: ["\u2588\u2580\u2588", "\u2580\u2580\u2588"],
2765
- R: ["\u2588\u2580\u2588", "\u2588\u2580\u2584"],
2766
- S: ["\u2588\u2580\u2580", "\u2584\u2584\u2588"],
2767
- T: ["\u2580\u2588\u2580", " \u2588 "],
2768
- U: ["\u2588 \u2588", "\u2588\u2584\u2588"],
2769
- V: ["\u2588 \u2588", "\u2580\u2584\u2580"],
2770
- W: ["\u2588 \u2588 \u2588", "\u2580\u2584\u2580\u2584\u2580"],
2771
- X: ["\u2580\u2584\u2580", "\u2588 \u2588"],
2772
- Y: ["\u2588\u2584\u2588", " \u2588 "],
2773
- Z: ["\u2580\u2588", "\u2588\u2584"],
2774
- "0": ["\u259E\u2588\u259A", "\u259A\u2588\u259E"],
2775
- "1": ["\u2584\u2588", " \u2588"],
2776
- "2": ["\u2580\u2588", "\u2588\u2584"],
2777
- "3": ["\u2580\u2580\u2588", "\u2584\u2588\u2588"],
2778
- "4": ["\u2588 \u2588", "\u2580\u2580\u2588"],
2779
- "5": ["\u2588\u2580", "\u2584\u2588"],
2780
- "6": ["\u2588\u2584\u2584", "\u2588\u2584\u2588"],
2781
- "7": ["\u2580\u2580\u2588", " \u2588"],
2782
- "8": ["\u2588\u2588\u2588", "\u2588\u2584\u2588"],
2783
- "9": ["\u2588\u2580\u2588", "\u2580\u2580\u2588"],
2784
- "!": ["\u2588", "\u2584"],
2785
- "?": ["\u2580\u2588", " \u2584"],
2786
- ".": [" ", "\u2584"],
2787
- "+": ["\u2584\u2588\u2584", " \u2580 "],
2788
- "-": ["\u2584\u2584", " "],
2789
- _: [" ", "\u2584\u2584"],
2790
- "=": ["\u2580\u2580", "\u2580\u2580"],
2791
- "@": ["\u259B\u2588\u259C", "\u2599\u259F\u2583"],
2792
- "#": ["\u259F\u2584\u2599", "\u259C\u2580\u259B"],
2793
- $: ["\u2596\u2588\u2597", "\u2598\u2588\u259D"],
2794
- "%": ["\u2580 \u2584\u2580", "\u2584\u2580 \u2584"],
2795
- "&": ["\u2584\u2584\u2588", "\u2588\u2584\u2588"],
2796
- "(": ["\u2584\u2580", "\u2580\u2584"],
2797
- ")": ["\u2580\u2584", "\u2584\u2580"],
2798
- "/": [" \u2584\u2580", "\u2584\u2580 "],
2799
- ":": ["\u2580", "\u2584"],
2800
- ";": [" ", "\u2584\u2580"],
2801
- ",": [" ", "\u2588"],
2802
- "'": ["\u2580", " "],
2803
- '"': ["\u259B \u259C", " "],
2804
- " ": [" ", " "]
2533
+ if (lowerColor === "transparent") {
2534
+ return RGBA.fromValues(0, 0, 0, 0);
2535
+ }
2536
+ if (CSS_COLOR_NAMES[lowerColor]) {
2537
+ return hexToRgb(CSS_COLOR_NAMES[lowerColor]);
2538
+ }
2539
+ return hexToRgb(color);
2805
2540
  }
2806
- };
2541
+ return color;
2542
+ }
2807
2543
  // src/lib/fonts/block.json
2808
2544
  var block_default = {
2809
2545
  name: "block",
@@ -4124,6 +3860,76 @@ var slick_default = {
4124
3860
  " ": ["<c2>\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571</c2>", "<c2>\u2571\u2571\u2571</c2>"]
4125
3861
  }
4126
3862
  };
3863
+ // src/lib/fonts/tiny.json
3864
+ var tiny_default = {
3865
+ name: "tiny",
3866
+ version: "0.2.0",
3867
+ homepage: "https://github.com/dominikwilkowski/cfonts",
3868
+ colors: 1,
3869
+ lines: 2,
3870
+ buffer: ["", ""],
3871
+ letterspace: [" ", " "],
3872
+ letterspace_size: 1,
3873
+ chars: {
3874
+ A: ["\u2584\u2580\u2588", "\u2588\u2580\u2588"],
3875
+ B: ["\u2588\u2584\u2584", "\u2588\u2584\u2588"],
3876
+ C: ["\u2588\u2580\u2580", "\u2588\u2584\u2584"],
3877
+ D: ["\u2588\u2580\u2584", "\u2588\u2584\u2580"],
3878
+ E: ["\u2588\u2580\u2580", "\u2588\u2588\u2584"],
3879
+ F: ["\u2588\u2580\u2580", "\u2588\u2580 "],
3880
+ G: ["\u2588\u2580\u2580", "\u2588\u2584\u2588"],
3881
+ H: ["\u2588 \u2588", "\u2588\u2580\u2588"],
3882
+ I: ["\u2588", "\u2588"],
3883
+ J: [" \u2588", "\u2588\u2584\u2588"],
3884
+ K: ["\u2588\u2584\u2580", "\u2588 \u2588"],
3885
+ L: ["\u2588 ", "\u2588\u2584\u2584"],
3886
+ M: ["\u2588\u2580\u2584\u2580\u2588", "\u2588 \u2580 \u2588"],
3887
+ N: ["\u2588\u2584 \u2588", "\u2588 \u2580\u2588"],
3888
+ O: ["\u2588\u2580\u2588", "\u2588\u2584\u2588"],
3889
+ P: ["\u2588\u2580\u2588", "\u2588\u2580\u2580"],
3890
+ Q: ["\u2588\u2580\u2588", "\u2580\u2580\u2588"],
3891
+ R: ["\u2588\u2580\u2588", "\u2588\u2580\u2584"],
3892
+ S: ["\u2588\u2580\u2580", "\u2584\u2584\u2588"],
3893
+ T: ["\u2580\u2588\u2580", " \u2588 "],
3894
+ U: ["\u2588 \u2588", "\u2588\u2584\u2588"],
3895
+ V: ["\u2588 \u2588", "\u2580\u2584\u2580"],
3896
+ W: ["\u2588 \u2588 \u2588", "\u2580\u2584\u2580\u2584\u2580"],
3897
+ X: ["\u2580\u2584\u2580", "\u2588 \u2588"],
3898
+ Y: ["\u2588\u2584\u2588", " \u2588 "],
3899
+ Z: ["\u2580\u2588", "\u2588\u2584"],
3900
+ "0": ["\u259E\u2588\u259A", "\u259A\u2588\u259E"],
3901
+ "1": ["\u2584\u2588", " \u2588"],
3902
+ "2": ["\u2580\u2588", "\u2588\u2584"],
3903
+ "3": ["\u2580\u2580\u2588", "\u2584\u2588\u2588"],
3904
+ "4": ["\u2588 \u2588", "\u2580\u2580\u2588"],
3905
+ "5": ["\u2588\u2580", "\u2584\u2588"],
3906
+ "6": ["\u2588\u2584\u2584", "\u2588\u2584\u2588"],
3907
+ "7": ["\u2580\u2580\u2588", " \u2588"],
3908
+ "8": ["\u2588\u2588\u2588", "\u2588\u2584\u2588"],
3909
+ "9": ["\u2588\u2580\u2588", "\u2580\u2580\u2588"],
3910
+ "!": ["\u2588", "\u2584"],
3911
+ "?": ["\u2580\u2588", " \u2584"],
3912
+ ".": [" ", "\u2584"],
3913
+ "+": ["\u2584\u2588\u2584", " \u2580 "],
3914
+ "-": ["\u2584\u2584", " "],
3915
+ _: [" ", "\u2584\u2584"],
3916
+ "=": ["\u2580\u2580", "\u2580\u2580"],
3917
+ "@": ["\u259B\u2588\u259C", "\u2599\u259F\u2583"],
3918
+ "#": ["\u259F\u2584\u2599", "\u259C\u2580\u259B"],
3919
+ $: ["\u2596\u2588\u2597", "\u2598\u2588\u259D"],
3920
+ "%": ["\u2580 \u2584\u2580", "\u2584\u2580 \u2584"],
3921
+ "&": ["\u2584\u2584\u2588", "\u2588\u2584\u2588"],
3922
+ "(": ["\u2584\u2580", "\u2580\u2584"],
3923
+ ")": ["\u2580\u2584", "\u2584\u2580"],
3924
+ "/": [" \u2584\u2580", "\u2584\u2580 "],
3925
+ ":": ["\u2580", "\u2584"],
3926
+ ";": [" ", "\u2584\u2580"],
3927
+ ",": [" ", "\u2588"],
3928
+ "'": ["\u2580", " "],
3929
+ '"': ["\u259B \u259C", " "],
3930
+ " ": [" ", " "]
3931
+ }
3932
+ };
4127
3933
 
4128
3934
  // src/lib/ascii.font.ts
4129
3935
  var fonts = {
@@ -4268,8 +4074,8 @@ function renderFontToFrameBuffer(buffer, {
4268
4074
  text,
4269
4075
  x = 0,
4270
4076
  y = 0,
4271
- fg = [RGBA.fromInts(255, 255, 255, 255)],
4272
- bg = RGBA.fromInts(0, 0, 0, 255),
4077
+ color = [RGBA.fromInts(255, 255, 255, 255)],
4078
+ backgroundColor = RGBA.fromInts(0, 0, 0, 255),
4273
4079
  font = "tiny"
4274
4080
  }) {
4275
4081
  const width = buffer.width;
@@ -4279,7 +4085,7 @@ function renderFontToFrameBuffer(buffer, {
4279
4085
  console.warn(`Font '${font}' not found`);
4280
4086
  return { width: 0, height: 0 };
4281
4087
  }
4282
- const colors = Array.isArray(fg) ? fg : [fg];
4088
+ const colors = Array.isArray(color) ? color : [color];
4283
4089
  if (y < 0 || y + fontDef.lines > height) {
4284
4090
  return { width: 0, height: fontDef.lines };
4285
4091
  }
@@ -4325,7 +4131,7 @@ function renderFontToFrameBuffer(buffer, {
4325
4131
  if (renderX >= 0 && renderX < width) {
4326
4132
  const fontChar = segment.text[charIdx];
4327
4133
  if (fontChar !== " ") {
4328
- buffer.setCellWithAlphaBlending(renderX, renderY, fontChar, segmentColor, bg);
4134
+ buffer.setCellWithAlphaBlending(renderX, renderY, fontChar, parseColor(segmentColor), parseColor(backgroundColor));
4329
4135
  }
4330
4136
  }
4331
4137
  }
@@ -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
 
@@ -7175,8 +7221,8 @@ class ExtmarksController {
7175
7221
  this.editBuffer.clearAllHighlights();
7176
7222
  for (const extmark of this.extmarks.values()) {
7177
7223
  if (extmark.styleId !== undefined) {
7178
- const startWithoutNewlines = this.offsetToCharOffset(extmark.start);
7179
- const endWithoutNewlines = this.offsetToCharOffset(extmark.end);
7224
+ const startWithoutNewlines = this.offsetExcludingNewlines(extmark.start);
7225
+ const endWithoutNewlines = this.offsetExcludingNewlines(extmark.end);
7180
7226
  this.editBuffer.addHighlightByCharRange({
7181
7227
  start: startWithoutNewlines,
7182
7228
  end: endWithoutNewlines,
@@ -7187,16 +7233,38 @@ class ExtmarksController {
7187
7233
  }
7188
7234
  }
7189
7235
  }
7190
- offsetToCharOffset(offset) {
7236
+ offsetExcludingNewlines(offset) {
7191
7237
  const text = this.editBuffer.getText();
7192
- let charOffset = 0;
7193
- for (let i = 0;i < offset && i < text.length; i++) {
7194
- if (text[i] !== `
7238
+ let displayWidthSoFar = 0;
7239
+ let newlineCount = 0;
7240
+ let i = 0;
7241
+ while (i < text.length && displayWidthSoFar < offset) {
7242
+ if (text[i] === `
7243
+ `) {
7244
+ displayWidthSoFar++;
7245
+ newlineCount++;
7246
+ i++;
7247
+ } else {
7248
+ let j = i;
7249
+ while (j < text.length && text[j] !== `
7195
7250
  `) {
7196
- charOffset++;
7251
+ j++;
7252
+ }
7253
+ const chunk = text.substring(i, j);
7254
+ const chunkWidth = Bun.stringWidth(chunk);
7255
+ if (displayWidthSoFar + chunkWidth < offset) {
7256
+ displayWidthSoFar += chunkWidth;
7257
+ i = j;
7258
+ } else {
7259
+ for (let k = i;k < j && displayWidthSoFar < offset; k++) {
7260
+ const charWidth = Bun.stringWidth(text[k]);
7261
+ displayWidthSoFar += charWidth;
7262
+ }
7263
+ break;
7264
+ }
7197
7265
  }
7198
7266
  }
7199
- return charOffset;
7267
+ return offset - newlineCount;
7200
7268
  }
7201
7269
  create(options) {
7202
7270
  if (this.destroyed) {
@@ -7889,6 +7957,23 @@ function isObjectPointerDef(type) {
7889
7957
  function alignOffset(offset, align) {
7890
7958
  return offset + (align - 1) & ~(align - 1);
7891
7959
  }
7960
+ function enumTypeError(value) {
7961
+ throw new TypeError(`Invalid enum value: ${value}`);
7962
+ }
7963
+ function defineEnum(mapping, base = "u32") {
7964
+ const reverse2 = Object.fromEntries(Object.entries(mapping).map(([k, v]) => [v, k]));
7965
+ return {
7966
+ __type: "enum",
7967
+ type: base,
7968
+ to(value) {
7969
+ return typeof value === "number" ? value : mapping[value] ?? enumTypeError(String(value));
7970
+ },
7971
+ from(value) {
7972
+ return reverse2[value] ?? enumTypeError(String(value));
7973
+ },
7974
+ enum: mapping
7975
+ };
7976
+ }
7892
7977
  function isEnum(type) {
7893
7978
  return typeof type === "object" && type.__type === "enum";
7894
7979
  }
@@ -7965,6 +8050,7 @@ function packObjectArray(val) {
7965
8050
  return bufferView;
7966
8051
  }
7967
8052
  var encoder = new TextEncoder;
8053
+ var decoder = new TextDecoder;
7968
8054
  function defineStruct(fields, structDefOptions) {
7969
8055
  let offset = 0;
7970
8056
  let maxAlign = 1;
@@ -8007,6 +8093,7 @@ function defineStruct(fields, structDefOptions) {
8007
8093
  const ptrVal = pointerUnpacker(view, off);
8008
8094
  return ptrVal;
8009
8095
  };
8096
+ needsLengthOf = true;
8010
8097
  } else if (isEnum(typeOrStruct)) {
8011
8098
  const base = typeOrStruct.type;
8012
8099
  size = typeSizes[base];
@@ -8209,9 +8296,10 @@ function defineStruct(fields, structDefOptions) {
8209
8296
  lengthOfFields[options.lengthOf] = layoutField;
8210
8297
  }
8211
8298
  if (needsLengthOf) {
8212
- if (!lengthOfDef)
8213
- fatalError(`Internal error: needsLengthOf=true but lengthOfDef is null for ${name}`);
8214
- lengthOfRequested.push({ requester: layoutField, def: lengthOfDef });
8299
+ const def = typeof typeOrStruct === "string" && typeOrStruct === "char*" ? "char*" : lengthOfDef;
8300
+ if (!def)
8301
+ fatalError(`Internal error: needsLengthOf=true but def is null for ${name}`);
8302
+ lengthOfRequested.push({ requester: layoutField, def });
8215
8303
  }
8216
8304
  offset += size;
8217
8305
  maxAlign = Math.max(maxAlign, align);
@@ -8219,9 +8307,26 @@ function defineStruct(fields, structDefOptions) {
8219
8307
  for (const { requester, def } of lengthOfRequested) {
8220
8308
  const lengthOfField = lengthOfFields[requester.name];
8221
8309
  if (!lengthOfField) {
8310
+ if (def === "char*") {
8311
+ continue;
8312
+ }
8222
8313
  throw new Error(`lengthOf field not found for array field ${requester.name}`);
8223
8314
  }
8224
- if (isPrimitiveType(def)) {
8315
+ if (def === "char*") {
8316
+ requester.unpack = (view, off) => {
8317
+ const ptrAddress = pointerUnpacker(view, off);
8318
+ const length = lengthOfField.unpack(view, lengthOfField.offset);
8319
+ if (ptrAddress === 0) {
8320
+ return null;
8321
+ }
8322
+ const byteLength = typeof length === "bigint" ? Number(length) : length;
8323
+ if (byteLength === 0) {
8324
+ return "";
8325
+ }
8326
+ const buffer = toArrayBuffer2(ptrAddress, 0, byteLength);
8327
+ return decoder.decode(buffer);
8328
+ };
8329
+ } else if (isPrimitiveType(def)) {
8225
8330
  const elemSize = typeSizes[def];
8226
8331
  const { unpack: primitiveUnpack } = primitivePackers(def);
8227
8332
  requester.unpack = (view, off) => {
@@ -8461,6 +8566,27 @@ var VisualCursorStruct = defineStruct([
8461
8566
  ["logicalCol", "u32"],
8462
8567
  ["offset", "u32"]
8463
8568
  ]);
8569
+ var UnicodeMethodEnum = defineEnum({ wcwidth: 0, unicode: 1 }, "u8");
8570
+ var TerminalCapabilitiesStruct = defineStruct([
8571
+ ["kitty_keyboard", "bool_u8"],
8572
+ ["kitty_graphics", "bool_u8"],
8573
+ ["rgb", "bool_u8"],
8574
+ ["unicode", UnicodeMethodEnum],
8575
+ ["sgr_pixels", "bool_u8"],
8576
+ ["color_scheme_updates", "bool_u8"],
8577
+ ["explicit_width", "bool_u8"],
8578
+ ["scaled_text", "bool_u8"],
8579
+ ["sixel", "bool_u8"],
8580
+ ["focus_tracking", "bool_u8"],
8581
+ ["sync", "bool_u8"],
8582
+ ["bracketed_paste", "bool_u8"],
8583
+ ["hyperlinks", "bool_u8"],
8584
+ ["term_name", "char*"],
8585
+ ["term_name_len", "u64", { lengthOf: "term_name" }],
8586
+ ["term_version", "char*"],
8587
+ ["term_version_len", "u64", { lengthOf: "term_version" }],
8588
+ ["term_from_xtversion", "bool_u8"]
8589
+ ]);
8464
8590
 
8465
8591
  // src/zig.ts
8466
8592
  var module = await import(`@opentui/core-${process.platform}-${process.arch}/index.ts`);
@@ -10290,25 +10416,29 @@ class FFIRenderLib {
10290
10416
  this.opentui.symbols.bufferClearScissorRects(buffer);
10291
10417
  }
10292
10418
  getTerminalCapabilities(renderer) {
10293
- const capsBuffer = new Uint8Array(64);
10294
- this.opentui.symbols.getTerminalCapabilities(renderer, capsBuffer);
10295
- let offset = 0;
10296
- const capabilities = {
10297
- kitty_keyboard: capsBuffer[offset++] !== 0,
10298
- kitty_graphics: capsBuffer[offset++] !== 0,
10299
- rgb: capsBuffer[offset++] !== 0,
10300
- unicode: capsBuffer[offset++] === 0 ? "wcwidth" : "unicode",
10301
- sgr_pixels: capsBuffer[offset++] !== 0,
10302
- color_scheme_updates: capsBuffer[offset++] !== 0,
10303
- explicit_width: capsBuffer[offset++] !== 0,
10304
- scaled_text: capsBuffer[offset++] !== 0,
10305
- sixel: capsBuffer[offset++] !== 0,
10306
- focus_tracking: capsBuffer[offset++] !== 0,
10307
- sync: capsBuffer[offset++] !== 0,
10308
- bracketed_paste: capsBuffer[offset++] !== 0,
10309
- hyperlinks: capsBuffer[offset++] !== 0
10419
+ const capsBuffer = new ArrayBuffer(TerminalCapabilitiesStruct.size);
10420
+ this.opentui.symbols.getTerminalCapabilities(renderer, ptr3(capsBuffer));
10421
+ const caps = TerminalCapabilitiesStruct.unpack(capsBuffer);
10422
+ return {
10423
+ kitty_keyboard: caps.kitty_keyboard,
10424
+ kitty_graphics: caps.kitty_graphics,
10425
+ rgb: caps.rgb,
10426
+ unicode: caps.unicode,
10427
+ sgr_pixels: caps.sgr_pixels,
10428
+ color_scheme_updates: caps.color_scheme_updates,
10429
+ explicit_width: caps.explicit_width,
10430
+ scaled_text: caps.scaled_text,
10431
+ sixel: caps.sixel,
10432
+ focus_tracking: caps.focus_tracking,
10433
+ sync: caps.sync,
10434
+ bracketed_paste: caps.bracketed_paste,
10435
+ hyperlinks: caps.hyperlinks,
10436
+ terminal: {
10437
+ name: caps.term_name ?? "",
10438
+ version: caps.term_version ?? "",
10439
+ from_xtversion: caps.term_from_xtversion
10440
+ }
10310
10441
  };
10311
- return capabilities;
10312
10442
  }
10313
10443
  processCapabilityResponse(renderer, response) {
10314
10444
  const responseBytes = this.encoder.encode(response);
@@ -12634,6 +12764,21 @@ class TerminalConsole extends EventEmitter8 {
12634
12764
  }
12635
12765
  }
12636
12766
 
12767
+ // src/ansi.ts
12768
+ var ANSI = {
12769
+ switchToAlternateScreen: "\x1B[?1049h",
12770
+ switchToMainScreen: "\x1B[?1049l",
12771
+ reset: "\x1B[0m",
12772
+ scrollDown: (lines) => `\x1B[${lines}T`,
12773
+ scrollUp: (lines) => `\x1B[${lines}S`,
12774
+ moveCursor: (row, col) => `\x1B[${row};${col}H`,
12775
+ moveCursorAndClear: (row, col) => `\x1B[${row};${col}H\x1B[J`,
12776
+ setRgbBackground: (r, g, b) => `\x1B[48;2;${r};${g};${b}m`,
12777
+ resetBackground: "\x1B[49m",
12778
+ bracketedPasteStart: "\x1B[200~",
12779
+ bracketedPasteEnd: "\x1B[201~"
12780
+ };
12781
+
12637
12782
  // src/renderer.ts
12638
12783
  import { EventEmitter as EventEmitter9 } from "events";
12639
12784
 
@@ -12727,6 +12872,42 @@ function getObjectsInViewport(viewport, objects, direction = "column", padding =
12727
12872
  return visibleChildren;
12728
12873
  }
12729
12874
 
12875
+ // src/lib/terminal-capability-detection.ts
12876
+ function isCapabilityResponse(sequence) {
12877
+ if (/\x1b\[\?\d+(?:;\d+)*\$y/.test(sequence)) {
12878
+ return true;
12879
+ }
12880
+ if (/\x1b\[1;(?!1R)\d+R/.test(sequence)) {
12881
+ return true;
12882
+ }
12883
+ if (/\x1bP>\|[\s\S]*?\x1b\\/.test(sequence)) {
12884
+ return true;
12885
+ }
12886
+ if (/\x1b_G[\s\S]*?\x1b\\/.test(sequence)) {
12887
+ return true;
12888
+ }
12889
+ if (/\x1b\[\?\d+(?:;\d+)?u/.test(sequence)) {
12890
+ return true;
12891
+ }
12892
+ if (/\x1b\[\?[0-9;]*c/.test(sequence)) {
12893
+ return true;
12894
+ }
12895
+ return false;
12896
+ }
12897
+ function isPixelResolutionResponse(sequence) {
12898
+ return /\x1b\[4;\d+;\d+t/.test(sequence);
12899
+ }
12900
+ function parsePixelResolution(sequence) {
12901
+ const match = sequence.match(/\x1b\[4;(\d+);(\d+)t/);
12902
+ if (match) {
12903
+ return {
12904
+ width: parseInt(match[2]),
12905
+ height: parseInt(match[1])
12906
+ };
12907
+ }
12908
+ return null;
12909
+ }
12910
+
12730
12911
  // src/renderer.ts
12731
12912
  registerEnvVar({
12732
12913
  name: "OTUI_DUMP_CAPTURES",
@@ -12919,6 +13100,7 @@ class CliRenderer extends EventEmitter9 {
12919
13100
  _console;
12920
13101
  _resolution = null;
12921
13102
  _keyHandler;
13103
+ _stdinBuffer;
12922
13104
  animationRequest = new Map;
12923
13105
  resizeTimeoutId = null;
12924
13106
  resizeDebounceDelay = 100;
@@ -12958,6 +13140,9 @@ class CliRenderer extends EventEmitter9 {
12958
13140
  _paletteDetector = null;
12959
13141
  _cachedPalette = null;
12960
13142
  _paletteDetectionPromise = null;
13143
+ _onDestroy;
13144
+ inputHandlers = [];
13145
+ prependedInputHandlers = [];
12961
13146
  handleError = ((error) => {
12962
13147
  console.error(error);
12963
13148
  if (this._openConsoleOnError) {
@@ -13031,6 +13216,7 @@ Captured output:
13031
13216
  this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
13032
13217
  this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
13033
13218
  this.postProcessFns = config.postProcessFns || [];
13219
+ this.prependedInputHandlers = config.prependInputHandlers || [];
13034
13220
  this.root = new RootRenderable(this);
13035
13221
  if (this.memorySnapshotInterval > 0) {
13036
13222
  this.startMemorySnapshotTimer();
@@ -13043,7 +13229,7 @@ Captured output:
13043
13229
  process.on("uncaughtException", this.handleError);
13044
13230
  process.on("unhandledRejection", this.handleError);
13045
13231
  process.on("exit", this.exitHandler);
13046
- this._keyHandler = new InternalKeyHandler(this.stdin, config.useKittyKeyboard ?? true);
13232
+ this._keyHandler = new InternalKeyHandler(config.useKittyKeyboard ?? true);
13047
13233
  this._keyHandler.on("keypress", (event) => {
13048
13234
  if (this.exitOnCtrlC && event.name === "c" && event.ctrl) {
13049
13235
  process.nextTick(() => {
@@ -13052,9 +13238,11 @@ Captured output:
13052
13238
  return;
13053
13239
  }
13054
13240
  });
13241
+ this._stdinBuffer = new StdinBuffer({ timeout: 5 });
13055
13242
  this._console = new TerminalConsole(this, config.consoleOptions);
13056
13243
  this.useConsole = config.useConsole ?? true;
13057
13244
  this._openConsoleOnError = config.openConsoleOnError ?? true;
13245
+ this._onDestroy = config.onDestroy;
13058
13246
  global.requestAnimationFrame = (callback) => {
13059
13247
  const id = CliRenderer.animationFrameId++;
13060
13248
  this.animationRequest.set(id, callback);
@@ -13286,52 +13474,86 @@ Captured output:
13286
13474
  if (this._terminalIsSetup)
13287
13475
  return;
13288
13476
  this._terminalIsSetup = true;
13289
- await new Promise((resolve4) => {
13290
- const timeout = setTimeout(() => {
13291
- this.stdin.off("data", capListener);
13292
- resolve4(true);
13293
- }, 100);
13294
- const capListener = (str) => {
13295
- clearTimeout(timeout);
13296
- this.lib.processCapabilityResponse(this.rendererPtr, str);
13297
- this.stdin.off("data", capListener);
13298
- resolve4(true);
13299
- };
13300
- this.stdin.on("data", capListener);
13301
- this.lib.setupTerminal(this.rendererPtr, this._useAlternateScreen);
13302
- });
13477
+ this.lib.setupTerminal(this.rendererPtr, this._useAlternateScreen);
13303
13478
  this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
13479
+ setTimeout(() => {
13480
+ this.removeInputHandler(this.capabilityHandler);
13481
+ }, 5000);
13304
13482
  if (this._useMouse) {
13305
13483
  this.enableMouse();
13306
13484
  }
13307
13485
  this.queryPixelResolution();
13308
13486
  }
13309
13487
  stdinListener = ((data) => {
13310
- const str = data.toString();
13311
- if (this.waitingForPixelResolution && /\x1b\[4;\d+;\d+t/.test(str)) {
13312
- const match = str.match(/\x1b\[4;(\d+);(\d+)t/);
13313
- if (match) {
13314
- const resolution = {
13315
- width: parseInt(match[2]),
13316
- height: parseInt(match[1])
13317
- };
13318
- this._resolution = resolution;
13319
- this.waitingForPixelResolution = false;
13320
- return;
13321
- }
13322
- }
13323
13488
  if (this._useMouse && this.handleMouseData(data)) {
13324
13489
  return;
13325
13490
  }
13326
- this.emit("key", data);
13491
+ this._stdinBuffer.process(data);
13492
+ }).bind(this);
13493
+ addInputHandler(handler) {
13494
+ this.inputHandlers.push(handler);
13495
+ }
13496
+ prependInputHandler(handler) {
13497
+ this.inputHandlers.unshift(handler);
13498
+ }
13499
+ removeInputHandler(handler) {
13500
+ this.inputHandlers = this.inputHandlers.filter((h2) => h2 !== handler);
13501
+ }
13502
+ capabilityHandler = ((sequence) => {
13503
+ if (isCapabilityResponse(sequence)) {
13504
+ this.lib.processCapabilityResponse(this.rendererPtr, sequence);
13505
+ this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
13506
+ return true;
13507
+ }
13508
+ return false;
13509
+ }).bind(this);
13510
+ focusHandler = ((sequence) => {
13511
+ if (sequence === "\x1B[I") {
13512
+ this.emit("focus");
13513
+ return true;
13514
+ }
13515
+ if (sequence === "\x1B[O") {
13516
+ this.emit("blur");
13517
+ return true;
13518
+ }
13519
+ return false;
13327
13520
  }).bind(this);
13328
13521
  setupInput() {
13522
+ for (const handler of this.prependedInputHandlers) {
13523
+ this.addInputHandler(handler);
13524
+ }
13525
+ this.addInputHandler((sequence) => {
13526
+ if (isPixelResolutionResponse(sequence) && this.waitingForPixelResolution) {
13527
+ const resolution = parsePixelResolution(sequence);
13528
+ if (resolution) {
13529
+ this._resolution = resolution;
13530
+ this.waitingForPixelResolution = false;
13531
+ }
13532
+ return true;
13533
+ }
13534
+ return false;
13535
+ });
13536
+ this.addInputHandler(this.capabilityHandler);
13537
+ this.addInputHandler(this.focusHandler);
13538
+ this.addInputHandler((sequence) => {
13539
+ return this._keyHandler.processInput(sequence);
13540
+ });
13329
13541
  if (this.stdin.setRawMode) {
13330
13542
  this.stdin.setRawMode(true);
13331
13543
  }
13332
13544
  this.stdin.resume();
13333
13545
  this.stdin.setEncoding("utf8");
13334
13546
  this.stdin.on("data", this.stdinListener);
13547
+ this._stdinBuffer.on("data", (sequence) => {
13548
+ for (const handler of this.inputHandlers) {
13549
+ if (handler(sequence)) {
13550
+ return;
13551
+ }
13552
+ }
13553
+ });
13554
+ this._stdinBuffer.on("paste", (data) => {
13555
+ this._keyHandler.processPaste(data);
13556
+ });
13335
13557
  }
13336
13558
  handleMouseData(data) {
13337
13559
  const mouseEvent = this.mouseParser.parseMouseEvent(data);
@@ -13657,6 +13879,7 @@ Captured output:
13657
13879
  this._suspendedMouseEnabled = this._useMouse;
13658
13880
  this.disableMouse();
13659
13881
  this._keyHandler.suspend();
13882
+ this._stdinBuffer.clear();
13660
13883
  if (this.stdin.setRawMode) {
13661
13884
  this.stdin.setRawMode(false);
13662
13885
  }
@@ -13726,7 +13949,7 @@ Captured output:
13726
13949
  } catch (e) {
13727
13950
  console.error("Error destroying root renderable:", e instanceof Error ? e.stack : String(e));
13728
13951
  }
13729
- this._keyHandler.destroy();
13952
+ this._stdinBuffer.destroy();
13730
13953
  this._console.deactivate();
13731
13954
  this.disableStdoutInterception();
13732
13955
  if (this._splitHeight > 0) {
@@ -13738,6 +13961,13 @@ Captured output:
13738
13961
  this.stdin.removeListener("data", this.stdinListener);
13739
13962
  this.lib.destroyRenderer(this.rendererPtr);
13740
13963
  rendererTracker.removeRenderer(this);
13964
+ if (this._onDestroy) {
13965
+ try {
13966
+ this._onDestroy();
13967
+ } catch (e) {
13968
+ console.error("Error in onDestroy callback:", e instanceof Error ? e.stack : String(e));
13969
+ }
13970
+ }
13741
13971
  }
13742
13972
  startRenderLoop() {
13743
13973
  if (!this._isRunning)
@@ -13999,7 +14229,7 @@ Captured output:
13999
14229
  }
14000
14230
  }
14001
14231
 
14002
- 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 };
14232
+ 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 };
14003
14233
 
14004
- //# debugId=FE3334220FB993E564756E2164756E21
14005
- //# sourceMappingURL=index-z5bb2h2z.js.map
14234
+ //# debugId=3DCC34290CF7528A64756E2164756E21
14235
+ //# sourceMappingURL=index-y49e47t2.js.map