@opentui/core 0.1.101 → 0.1.102

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.
@@ -6867,7 +6867,8 @@ var DEFAULT_PROTOCOL_CONTEXT = {
6867
6867
  kittyKeyboardEnabled: false,
6868
6868
  privateCapabilityRepliesActive: false,
6869
6869
  pixelResolutionQueryActive: false,
6870
- explicitWidthCprActive: false
6870
+ explicitWidthCprActive: false,
6871
+ startupCursorCprActive: false
6871
6872
  };
6872
6873
  var RXVT_DOLLAR_CSI_RE = /^\x1b\[\d+\$$/;
6873
6874
  var SYSTEM_CLOCK = new SystemClock;
@@ -7056,11 +7057,14 @@ function canStillBeKittySpecial(state) {
7056
7057
  function canStillBeExplicitWidthCpr(state) {
7057
7058
  return state.firstParamValue === 1 && state.semicolons === 1;
7058
7059
  }
7060
+ function canStillBeStartupCursorCpr(state) {
7061
+ return state.semicolons === 1;
7062
+ }
7059
7063
  function canStillBePixelResolution(state) {
7060
7064
  return state.firstParamValue === 4 && state.semicolons === 2;
7061
7065
  }
7062
7066
  function canDeferParametricCsi(state, context) {
7063
- return context.kittyKeyboardEnabled && (canStillBeKittyU(state) || canStillBeKittySpecial(state)) || context.explicitWidthCprActive && canStillBeExplicitWidthCpr(state) || context.pixelResolutionQueryActive && canStillBePixelResolution(state);
7067
+ return context.kittyKeyboardEnabled && (canStillBeKittyU(state) || canStillBeKittySpecial(state)) || context.explicitWidthCprActive && canStillBeExplicitWidthCpr(state) || context.startupCursorCprActive && canStillBeStartupCursorCpr(state) || context.pixelResolutionQueryActive && canStillBePixelResolution(state);
7064
7068
  }
7065
7069
  function canCompleteDeferredParametricCsi(state, byte, context) {
7066
7070
  if (context.kittyKeyboardEnabled) {
@@ -7073,11 +7077,20 @@ function canCompleteDeferredParametricCsi(state, byte, context) {
7073
7077
  if (context.explicitWidthCprActive && state.hasDigit && state.firstParamValue === 1 && state.semicolons === 1 && byte === 82) {
7074
7078
  return true;
7075
7079
  }
7080
+ if (context.startupCursorCprActive && state.hasDigit && state.semicolons === 1 && byte === 82) {
7081
+ return true;
7082
+ }
7076
7083
  if (context.pixelResolutionQueryActive && state.hasDigit && state.firstParamValue === 4 && state.semicolons === 2 && byte === 116) {
7077
7084
  return true;
7078
7085
  }
7079
7086
  return false;
7080
7087
  }
7088
+ function classifyParametricCsiProtocol(state, finalByte) {
7089
+ if (finalByte === 82 && state.semicolons === 1 && state.segments === 1 && state.hasDigit) {
7090
+ return "cpr";
7091
+ }
7092
+ return "csi";
7093
+ }
7081
7094
  function canDeferPrivateReplyCsi(context) {
7082
7095
  return context.privateCapabilityRepliesActive;
7083
7096
  }
@@ -7184,7 +7197,8 @@ class StdinParser {
7184
7197
  kittyKeyboardEnabled: options.protocolContext?.kittyKeyboardEnabled ?? false,
7185
7198
  privateCapabilityRepliesActive: options.protocolContext?.privateCapabilityRepliesActive ?? false,
7186
7199
  pixelResolutionQueryActive: options.protocolContext?.pixelResolutionQueryActive ?? false,
7187
- explicitWidthCprActive: options.protocolContext?.explicitWidthCprActive ?? false
7200
+ explicitWidthCprActive: options.protocolContext?.explicitWidthCprActive ?? false,
7201
+ startupCursorCprActive: options.protocolContext?.startupCursorCprActive ?? false
7188
7202
  };
7189
7203
  }
7190
7204
  get bufferCapacity() {
@@ -7686,7 +7700,8 @@ class StdinParser {
7686
7700
  }
7687
7701
  if (byte >= 64 && byte <= 126) {
7688
7702
  const end = this.cursor + 1;
7689
- this.emitKeyOrResponse("csi", decodeUtf8(bytes.subarray(this.unitStart, end)));
7703
+ const protocol = classifyParametricCsiProtocol(this.state, byte);
7704
+ this.emitKeyOrResponse(protocol, decodeUtf8(bytes.subarray(this.unitStart, end)));
7690
7705
  this.state = { tag: "ground" };
7691
7706
  this.consumePrefix(end);
7692
7707
  continue;
@@ -11895,6 +11910,10 @@ function getOpenTUILib(libPath) {
11895
11910
  args: ["ptr", "bool"],
11896
11911
  returns: "void"
11897
11912
  },
11913
+ setClearOnShutdown: {
11914
+ args: ["ptr", "bool"],
11915
+ returns: "void"
11916
+ },
11898
11917
  setBackgroundColor: {
11899
11918
  args: ["ptr", "ptr"],
11900
11919
  returns: "void"
@@ -11903,6 +11922,22 @@ function getOpenTUILib(libPath) {
11903
11922
  args: ["ptr", "u32"],
11904
11923
  returns: "void"
11905
11924
  },
11925
+ resetSplitScrollback: {
11926
+ args: ["ptr", "u32", "u32"],
11927
+ returns: "u32"
11928
+ },
11929
+ syncSplitScrollback: {
11930
+ args: ["ptr", "u32"],
11931
+ returns: "u32"
11932
+ },
11933
+ setPendingSplitFooterTransition: {
11934
+ args: ["ptr", "u8", "u32", "u32", "u32", "u32"],
11935
+ returns: "void"
11936
+ },
11937
+ clearPendingSplitFooterTransition: {
11938
+ args: ["ptr"],
11939
+ returns: "void"
11940
+ },
11906
11941
  updateStats: {
11907
11942
  args: ["ptr", "f64", "u32", "f64"],
11908
11943
  returns: "void"
@@ -11915,6 +11950,14 @@ function getOpenTUILib(libPath) {
11915
11950
  args: ["ptr", "bool"],
11916
11951
  returns: "void"
11917
11952
  },
11953
+ repaintSplitFooter: {
11954
+ args: ["ptr", "u32", "bool"],
11955
+ returns: "u32"
11956
+ },
11957
+ commitSplitFooterSnapshot: {
11958
+ args: ["ptr", "ptr", "u32", "bool", "bool", "u32", "bool", "bool", "bool"],
11959
+ returns: "u32"
11960
+ },
11918
11961
  getNextBuffer: {
11919
11962
  args: ["ptr"],
11920
11963
  returns: "ptr"
@@ -12387,6 +12430,10 @@ function getOpenTUILib(libPath) {
12387
12430
  args: ["ptr", "u8"],
12388
12431
  returns: "void"
12389
12432
  },
12433
+ textBufferViewSetFirstLineOffset: {
12434
+ args: ["ptr", "u32"],
12435
+ returns: "void"
12436
+ },
12390
12437
  textBufferViewSetViewportSize: {
12391
12438
  args: ["ptr", "u32", "u32"],
12392
12439
  returns: "void"
@@ -13124,12 +13171,27 @@ class FFIRenderLib {
13124
13171
  setUseThread(renderer, useThread) {
13125
13172
  this.opentui.symbols.setUseThread(renderer, useThread);
13126
13173
  }
13174
+ setClearOnShutdown(renderer, clear) {
13175
+ this.opentui.symbols.setClearOnShutdown(renderer, clear);
13176
+ }
13127
13177
  setBackgroundColor(renderer, color) {
13128
13178
  this.opentui.symbols.setBackgroundColor(renderer, color.buffer);
13129
13179
  }
13130
13180
  setRenderOffset(renderer, offset) {
13131
13181
  this.opentui.symbols.setRenderOffset(renderer, offset);
13132
13182
  }
13183
+ resetSplitScrollback(renderer, seedRows, pinnedRenderOffset) {
13184
+ return this.opentui.symbols.resetSplitScrollback(renderer, seedRows, pinnedRenderOffset);
13185
+ }
13186
+ syncSplitScrollback(renderer, pinnedRenderOffset) {
13187
+ return this.opentui.symbols.syncSplitScrollback(renderer, pinnedRenderOffset);
13188
+ }
13189
+ setPendingSplitFooterTransition(renderer, mode, sourceTopLine, sourceHeight, targetTopLine, targetHeight) {
13190
+ this.opentui.symbols.setPendingSplitFooterTransition(renderer, mode, sourceTopLine, sourceHeight, targetTopLine, targetHeight);
13191
+ }
13192
+ clearPendingSplitFooterTransition(renderer) {
13193
+ this.opentui.symbols.clearPendingSplitFooterTransition(renderer);
13194
+ }
13133
13195
  updateStats(renderer, time, fps, frameCallbackTime) {
13134
13196
  this.opentui.symbols.updateStats(renderer, time, fps, frameCallbackTime);
13135
13197
  }
@@ -13319,6 +13381,12 @@ class FFIRenderLib {
13319
13381
  render(renderer, force) {
13320
13382
  this.opentui.symbols.render(renderer, force);
13321
13383
  }
13384
+ repaintSplitFooter(renderer, pinnedRenderOffset, force) {
13385
+ return this.opentui.symbols.repaintSplitFooter(renderer, pinnedRenderOffset, force);
13386
+ }
13387
+ commitSplitFooterSnapshot(renderer, snapshot, rowColumns, startOnNewLine, trailingNewline, pinnedRenderOffset, force, beginFrame = true, finalizeFrame = true) {
13388
+ return this.opentui.symbols.commitSplitFooterSnapshot(renderer, snapshot.ptr, rowColumns, startOnNewLine, trailingNewline, pinnedRenderOffset, force, beginFrame, finalizeFrame);
13389
+ }
13322
13390
  createOptimizedBuffer(width, height, widthMethod, respectAlpha = false, id) {
13323
13391
  if (Number.isNaN(width) || Number.isNaN(height)) {
13324
13392
  console.error(new Error(`Invalid dimensions for OptimizedBuffer: ${width}x${height}`).stack);
@@ -13598,6 +13666,9 @@ class FFIRenderLib {
13598
13666
  const modeValue = mode === "none" ? 0 : mode === "char" ? 1 : 2;
13599
13667
  this.opentui.symbols.textBufferViewSetWrapMode(view, modeValue);
13600
13668
  }
13669
+ textBufferViewSetFirstLineOffset(view, offset) {
13670
+ this.opentui.symbols.textBufferViewSetFirstLineOffset(view, offset);
13671
+ }
13601
13672
  textBufferViewSetViewportSize(view, width, height) {
13602
13673
  this.opentui.symbols.textBufferViewSetViewportSize(view, width, height);
13603
13674
  }
@@ -16051,6 +16122,139 @@ function delegate(mapping, vnode) {
16051
16122
  return vnode;
16052
16123
  }
16053
16124
 
16125
+ // src/text-buffer-view.ts
16126
+ class TextBufferView {
16127
+ lib;
16128
+ viewPtr;
16129
+ textBuffer;
16130
+ _destroyed = false;
16131
+ constructor(lib, ptr5, textBuffer) {
16132
+ this.lib = lib;
16133
+ this.viewPtr = ptr5;
16134
+ this.textBuffer = textBuffer;
16135
+ }
16136
+ static create(textBuffer) {
16137
+ const lib = resolveRenderLib();
16138
+ const viewPtr = lib.createTextBufferView(textBuffer.ptr);
16139
+ return new TextBufferView(lib, viewPtr, textBuffer);
16140
+ }
16141
+ guard() {
16142
+ if (this._destroyed)
16143
+ throw new Error("TextBufferView is destroyed");
16144
+ }
16145
+ get ptr() {
16146
+ this.guard();
16147
+ return this.viewPtr;
16148
+ }
16149
+ setSelection(start, end, bgColor, fgColor) {
16150
+ this.guard();
16151
+ this.lib.textBufferViewSetSelection(this.viewPtr, start, end, bgColor || null, fgColor || null);
16152
+ }
16153
+ updateSelection(end, bgColor, fgColor) {
16154
+ this.guard();
16155
+ this.lib.textBufferViewUpdateSelection(this.viewPtr, end, bgColor || null, fgColor || null);
16156
+ }
16157
+ resetSelection() {
16158
+ this.guard();
16159
+ this.lib.textBufferViewResetSelection(this.viewPtr);
16160
+ }
16161
+ getSelection() {
16162
+ this.guard();
16163
+ return this.lib.textBufferViewGetSelection(this.viewPtr);
16164
+ }
16165
+ hasSelection() {
16166
+ this.guard();
16167
+ return this.getSelection() !== null;
16168
+ }
16169
+ setLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor) {
16170
+ this.guard();
16171
+ return this.lib.textBufferViewSetLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null);
16172
+ }
16173
+ updateLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor) {
16174
+ this.guard();
16175
+ return this.lib.textBufferViewUpdateLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null);
16176
+ }
16177
+ resetLocalSelection() {
16178
+ this.guard();
16179
+ this.lib.textBufferViewResetLocalSelection(this.viewPtr);
16180
+ }
16181
+ setWrapWidth(width) {
16182
+ this.guard();
16183
+ this.lib.textBufferViewSetWrapWidth(this.viewPtr, width ?? 0);
16184
+ }
16185
+ setWrapMode(mode) {
16186
+ this.guard();
16187
+ this.lib.textBufferViewSetWrapMode(this.viewPtr, mode);
16188
+ }
16189
+ setFirstLineOffset(offset) {
16190
+ this.guard();
16191
+ this.lib.textBufferViewSetFirstLineOffset(this.viewPtr, offset);
16192
+ }
16193
+ setViewportSize(width, height) {
16194
+ this.guard();
16195
+ this.lib.textBufferViewSetViewportSize(this.viewPtr, width, height);
16196
+ }
16197
+ setViewport(x, y, width, height) {
16198
+ this.guard();
16199
+ this.lib.textBufferViewSetViewport(this.viewPtr, x, y, width, height);
16200
+ }
16201
+ get lineInfo() {
16202
+ this.guard();
16203
+ return this.lib.textBufferViewGetLineInfo(this.viewPtr);
16204
+ }
16205
+ get logicalLineInfo() {
16206
+ this.guard();
16207
+ return this.lib.textBufferViewGetLogicalLineInfo(this.viewPtr);
16208
+ }
16209
+ getSelectedText() {
16210
+ this.guard();
16211
+ const byteSize = this.textBuffer.byteSize;
16212
+ if (byteSize === 0)
16213
+ return "";
16214
+ const selectedBytes = this.lib.textBufferViewGetSelectedTextBytes(this.viewPtr, byteSize);
16215
+ if (!selectedBytes)
16216
+ return "";
16217
+ return this.lib.decoder.decode(selectedBytes);
16218
+ }
16219
+ getPlainText() {
16220
+ this.guard();
16221
+ const byteSize = this.textBuffer.byteSize;
16222
+ if (byteSize === 0)
16223
+ return "";
16224
+ const plainBytes = this.lib.textBufferViewGetPlainTextBytes(this.viewPtr, byteSize);
16225
+ if (!plainBytes)
16226
+ return "";
16227
+ return this.lib.decoder.decode(plainBytes);
16228
+ }
16229
+ setTabIndicator(indicator) {
16230
+ this.guard();
16231
+ const codePoint = typeof indicator === "string" ? indicator.codePointAt(0) ?? 0 : indicator;
16232
+ this.lib.textBufferViewSetTabIndicator(this.viewPtr, codePoint);
16233
+ }
16234
+ setTabIndicatorColor(color) {
16235
+ this.guard();
16236
+ this.lib.textBufferViewSetTabIndicatorColor(this.viewPtr, color);
16237
+ }
16238
+ setTruncate(truncate) {
16239
+ this.guard();
16240
+ this.lib.textBufferViewSetTruncate(this.viewPtr, truncate);
16241
+ }
16242
+ measureForDimensions(width, height) {
16243
+ this.guard();
16244
+ return this.lib.textBufferViewMeasureForDimensions(this.viewPtr, width, height);
16245
+ }
16246
+ getVirtualLineCount() {
16247
+ this.guard();
16248
+ return this.lib.textBufferViewGetVirtualLineCount(this.viewPtr);
16249
+ }
16250
+ destroy() {
16251
+ if (this._destroyed)
16252
+ return;
16253
+ this._destroyed = true;
16254
+ this.lib.destroyTextBufferView(this.viewPtr);
16255
+ }
16256
+ }
16257
+
16054
16258
  // src/edit-buffer.ts
16055
16259
  import { EventEmitter as EventEmitter6 } from "events";
16056
16260
 
@@ -16555,117 +16759,1552 @@ class EditorView {
16555
16759
  }
16556
16760
  }
16557
16761
 
16558
- // src/console.ts
16559
- import { EventEmitter as EventEmitter8 } from "events";
16560
- import { Console } from "console";
16561
- import fs from "fs";
16562
- import path5 from "path";
16563
- import util2 from "util";
16564
-
16565
- // src/lib/output.capture.ts
16566
- import { Writable } from "stream";
16567
- import { EventEmitter as EventEmitter7 } from "events";
16762
+ // src/syntax-style.ts
16763
+ function convertThemeToStyles(theme) {
16764
+ const flatStyles = {};
16765
+ for (const tokenStyle of theme) {
16766
+ const styleDefinition = {};
16767
+ if (tokenStyle.style.foreground) {
16768
+ styleDefinition.fg = parseColor(tokenStyle.style.foreground);
16769
+ }
16770
+ if (tokenStyle.style.background) {
16771
+ styleDefinition.bg = parseColor(tokenStyle.style.background);
16772
+ }
16773
+ if (tokenStyle.style.bold !== undefined) {
16774
+ styleDefinition.bold = tokenStyle.style.bold;
16775
+ }
16776
+ if (tokenStyle.style.italic !== undefined) {
16777
+ styleDefinition.italic = tokenStyle.style.italic;
16778
+ }
16779
+ if (tokenStyle.style.underline !== undefined) {
16780
+ styleDefinition.underline = tokenStyle.style.underline;
16781
+ }
16782
+ if (tokenStyle.style.dim !== undefined) {
16783
+ styleDefinition.dim = tokenStyle.style.dim;
16784
+ }
16785
+ for (const scope of tokenStyle.scope) {
16786
+ flatStyles[scope] = styleDefinition;
16787
+ }
16788
+ }
16789
+ return flatStyles;
16790
+ }
16568
16791
 
16569
- class Capture extends EventEmitter7 {
16570
- output = [];
16571
- constructor() {
16572
- super();
16792
+ class SyntaxStyle {
16793
+ lib;
16794
+ stylePtr;
16795
+ _destroyed = false;
16796
+ nameCache = new Map;
16797
+ styleDefs = new Map;
16798
+ mergedCache = new Map;
16799
+ constructor(lib, ptr5) {
16800
+ this.lib = lib;
16801
+ this.stylePtr = ptr5;
16573
16802
  }
16574
- get size() {
16575
- return this.output.length;
16803
+ static create() {
16804
+ const lib = resolveRenderLib();
16805
+ const ptr5 = lib.createSyntaxStyle();
16806
+ return new SyntaxStyle(lib, ptr5);
16576
16807
  }
16577
- write(stream, data) {
16578
- this.output.push({ stream, output: data });
16579
- this.emit("write", stream, data);
16808
+ static fromTheme(theme) {
16809
+ const style = SyntaxStyle.create();
16810
+ const flatStyles = convertThemeToStyles(theme);
16811
+ for (const [name, styleDef] of Object.entries(flatStyles)) {
16812
+ style.registerStyle(name, styleDef);
16813
+ }
16814
+ return style;
16580
16815
  }
16581
- claimOutput() {
16582
- const output = this.output.map((o) => o.output).join("");
16583
- this.clear();
16584
- return output;
16816
+ static fromStyles(styles) {
16817
+ const style = SyntaxStyle.create();
16818
+ for (const [name, styleDef] of Object.entries(styles)) {
16819
+ style.registerStyle(name, styleDef);
16820
+ }
16821
+ return style;
16585
16822
  }
16586
- clear() {
16587
- this.output = [];
16823
+ guard() {
16824
+ if (this._destroyed)
16825
+ throw new Error("NativeSyntaxStyle is destroyed");
16588
16826
  }
16589
- }
16590
-
16591
- class CapturedWritableStream extends Writable {
16592
- stream;
16593
- capture;
16594
- isTTY = true;
16595
- columns = process.stdout.columns || 80;
16596
- rows = process.stdout.rows || 24;
16597
- constructor(stream, capture) {
16598
- super();
16599
- this.stream = stream;
16600
- this.capture = capture;
16827
+ registerStyle(name, style) {
16828
+ this.guard();
16829
+ const attributes = createTextAttributes({
16830
+ bold: style.bold,
16831
+ italic: style.italic,
16832
+ underline: style.underline,
16833
+ dim: style.dim
16834
+ });
16835
+ const id = this.lib.syntaxStyleRegister(this.stylePtr, name, style.fg || null, style.bg || null, attributes);
16836
+ this.nameCache.set(name, id);
16837
+ this.styleDefs.set(name, style);
16838
+ return id;
16601
16839
  }
16602
- _write(chunk, encoding, callback) {
16603
- const data = chunk.toString();
16604
- this.capture.write(this.stream, data);
16605
- callback();
16840
+ resolveStyleId(name) {
16841
+ this.guard();
16842
+ const cached = this.nameCache.get(name);
16843
+ if (cached !== undefined)
16844
+ return cached;
16845
+ const id = this.lib.syntaxStyleResolveByName(this.stylePtr, name);
16846
+ if (id !== null) {
16847
+ this.nameCache.set(name, id);
16848
+ }
16849
+ return id;
16606
16850
  }
16607
- getColorDepth() {
16608
- return process.stdout.getColorDepth?.() || 8;
16851
+ getStyleId(name) {
16852
+ this.guard();
16853
+ const id = this.resolveStyleId(name);
16854
+ if (id !== null)
16855
+ return id;
16856
+ if (name.includes(".")) {
16857
+ const baseName = name.split(".")[0];
16858
+ return this.resolveStyleId(baseName);
16859
+ }
16860
+ return null;
16609
16861
  }
16610
- }
16611
-
16612
- // src/lib/keymapping.ts
16613
- var defaultKeyAliases = {
16614
- enter: "return",
16615
- esc: "escape",
16616
- kp0: "0",
16617
- kp1: "1",
16618
- kp2: "2",
16619
- kp3: "3",
16620
- kp4: "4",
16621
- kp5: "5",
16622
- kp6: "6",
16623
- kp7: "7",
16624
- kp8: "8",
16625
- kp9: "9",
16626
- kpdecimal: ".",
16627
- kpdivide: "/",
16628
- kpmultiply: "*",
16629
- kpminus: "-",
16630
- kpplus: "+",
16631
- kpenter: "enter",
16632
- kpequal: "=",
16633
- kpseparator: ",",
16634
- kpleft: "left",
16635
- kpright: "right",
16636
- kpup: "up",
16637
- kpdown: "down",
16638
- kppageup: "pageup",
16639
- kppagedown: "pagedown",
16640
- kphome: "home",
16641
- kpend: "end",
16642
- kpinsert: "insert",
16643
- kpdelete: "delete"
16644
- };
16645
- function mergeKeyAliases(defaults, custom) {
16646
- return { ...defaults, ...custom };
16647
- }
16648
- function mergeKeyBindings(defaults, custom) {
16649
- const map = new Map;
16650
- for (const binding of defaults) {
16651
- const key = getKeyBindingKey(binding);
16652
- map.set(key, binding);
16862
+ get ptr() {
16863
+ this.guard();
16864
+ return this.stylePtr;
16653
16865
  }
16654
- for (const binding of custom) {
16655
- const key = getKeyBindingKey(binding);
16656
- map.set(key, binding);
16866
+ getStyleCount() {
16867
+ this.guard();
16868
+ return this.lib.syntaxStyleGetStyleCount(this.stylePtr);
16657
16869
  }
16658
- return Array.from(map.values());
16659
- }
16660
- function getKeyBindingKey(binding) {
16661
- return `${binding.name}:${binding.ctrl ? 1 : 0}:${binding.shift ? 1 : 0}:${binding.meta ? 1 : 0}:${binding.super ? 1 : 0}`;
16662
- }
16663
- function getBaseCodeKeyName(baseCode) {
16664
- if (baseCode === undefined || baseCode < 32 || baseCode === 127) {
16665
- return;
16870
+ clearNameCache() {
16871
+ this.nameCache.clear();
16666
16872
  }
16667
- try {
16668
- const name = String.fromCodePoint(baseCode);
16873
+ getStyle(name) {
16874
+ this.guard();
16875
+ if (Object.prototype.hasOwnProperty.call(this.styleDefs, name)) {
16876
+ return;
16877
+ }
16878
+ const style = this.styleDefs.get(name);
16879
+ if (style)
16880
+ return style;
16881
+ if (name.includes(".")) {
16882
+ const baseName = name.split(".")[0];
16883
+ if (Object.prototype.hasOwnProperty.call(this.styleDefs, baseName)) {
16884
+ return;
16885
+ }
16886
+ return this.styleDefs.get(baseName);
16887
+ }
16888
+ return;
16889
+ }
16890
+ mergeStyles(...styleNames) {
16891
+ this.guard();
16892
+ const cacheKey = styleNames.join(":");
16893
+ const cached = this.mergedCache.get(cacheKey);
16894
+ if (cached)
16895
+ return cached;
16896
+ const styleDefinition = {};
16897
+ for (const name of styleNames) {
16898
+ const style = this.getStyle(name);
16899
+ if (!style)
16900
+ continue;
16901
+ if (style.fg)
16902
+ styleDefinition.fg = style.fg;
16903
+ if (style.bg)
16904
+ styleDefinition.bg = style.bg;
16905
+ if (style.bold !== undefined)
16906
+ styleDefinition.bold = style.bold;
16907
+ if (style.italic !== undefined)
16908
+ styleDefinition.italic = style.italic;
16909
+ if (style.underline !== undefined)
16910
+ styleDefinition.underline = style.underline;
16911
+ if (style.dim !== undefined)
16912
+ styleDefinition.dim = style.dim;
16913
+ }
16914
+ const attributes = createTextAttributes({
16915
+ bold: styleDefinition.bold,
16916
+ italic: styleDefinition.italic,
16917
+ underline: styleDefinition.underline,
16918
+ dim: styleDefinition.dim
16919
+ });
16920
+ const merged = {
16921
+ fg: styleDefinition.fg,
16922
+ bg: styleDefinition.bg,
16923
+ attributes
16924
+ };
16925
+ this.mergedCache.set(cacheKey, merged);
16926
+ return merged;
16927
+ }
16928
+ clearCache() {
16929
+ this.guard();
16930
+ this.mergedCache.clear();
16931
+ }
16932
+ getCacheSize() {
16933
+ this.guard();
16934
+ return this.mergedCache.size;
16935
+ }
16936
+ getAllStyles() {
16937
+ this.guard();
16938
+ return new Map(this.styleDefs);
16939
+ }
16940
+ getRegisteredNames() {
16941
+ this.guard();
16942
+ return Array.from(this.styleDefs.keys());
16943
+ }
16944
+ destroy() {
16945
+ if (this._destroyed)
16946
+ return;
16947
+ this._destroyed = true;
16948
+ this.nameCache.clear();
16949
+ this.styleDefs.clear();
16950
+ this.mergedCache.clear();
16951
+ this.lib.destroySyntaxStyle(this.stylePtr);
16952
+ }
16953
+ }
16954
+
16955
+ // src/renderables/Box.ts
16956
+ function isGapType(value) {
16957
+ if (value === undefined) {
16958
+ return true;
16959
+ }
16960
+ if (typeof value === "number" && !Number.isNaN(value)) {
16961
+ return true;
16962
+ }
16963
+ return isValidPercentage(value);
16964
+ }
16965
+
16966
+ class BoxRenderable extends Renderable {
16967
+ _backgroundColor;
16968
+ _border;
16969
+ _borderStyle;
16970
+ _borderColor;
16971
+ _focusedBorderColor;
16972
+ _customBorderCharsObj;
16973
+ _customBorderChars;
16974
+ borderSides;
16975
+ shouldFill;
16976
+ _title;
16977
+ _titleAlignment;
16978
+ _bottomTitle;
16979
+ _bottomTitleAlignment;
16980
+ _defaultOptions = {
16981
+ backgroundColor: "transparent",
16982
+ borderStyle: "single",
16983
+ border: false,
16984
+ borderColor: "#FFFFFF",
16985
+ shouldFill: true,
16986
+ titleAlignment: "left",
16987
+ bottomTitleAlignment: "left",
16988
+ focusedBorderColor: "#00AAFF"
16989
+ };
16990
+ constructor(ctx, options) {
16991
+ super(ctx, options);
16992
+ if (options.focusable === true) {
16993
+ this._focusable = true;
16994
+ }
16995
+ this._backgroundColor = parseColor(options.backgroundColor || this._defaultOptions.backgroundColor);
16996
+ this._border = options.border ?? this._defaultOptions.border;
16997
+ if (!options.border && (options.borderStyle || options.borderColor || options.focusedBorderColor || options.customBorderChars)) {
16998
+ this._border = true;
16999
+ }
17000
+ this._borderStyle = parseBorderStyle(options.borderStyle, this._defaultOptions.borderStyle);
17001
+ this._borderColor = parseColor(options.borderColor || this._defaultOptions.borderColor);
17002
+ this._focusedBorderColor = parseColor(options.focusedBorderColor || this._defaultOptions.focusedBorderColor);
17003
+ this._customBorderCharsObj = options.customBorderChars;
17004
+ this._customBorderChars = this._customBorderCharsObj ? borderCharsToArray(this._customBorderCharsObj) : undefined;
17005
+ this.borderSides = getBorderSides(this._border);
17006
+ this.shouldFill = options.shouldFill ?? this._defaultOptions.shouldFill;
17007
+ this._title = options.title;
17008
+ this._titleAlignment = options.titleAlignment || this._defaultOptions.titleAlignment;
17009
+ this._bottomTitle = options.bottomTitle;
17010
+ this._bottomTitleAlignment = options.bottomTitleAlignment || this._defaultOptions.bottomTitleAlignment;
17011
+ this.applyYogaBorders();
17012
+ const hasInitialGapProps = options.gap !== undefined || options.rowGap !== undefined || options.columnGap !== undefined;
17013
+ if (hasInitialGapProps) {
17014
+ this.applyYogaGap(options);
17015
+ }
17016
+ }
17017
+ initializeBorder() {
17018
+ if (this._border === false) {
17019
+ this._border = true;
17020
+ this.borderSides = getBorderSides(this._border);
17021
+ this.applyYogaBorders();
17022
+ }
17023
+ }
17024
+ get customBorderChars() {
17025
+ return this._customBorderCharsObj;
17026
+ }
17027
+ set customBorderChars(value) {
17028
+ this._customBorderCharsObj = value;
17029
+ this._customBorderChars = value ? borderCharsToArray(value) : undefined;
17030
+ this.requestRender();
17031
+ }
17032
+ get backgroundColor() {
17033
+ return this._backgroundColor;
17034
+ }
17035
+ set backgroundColor(value) {
17036
+ const newColor = parseColor(value ?? this._defaultOptions.backgroundColor);
17037
+ if (this._backgroundColor !== newColor) {
17038
+ this._backgroundColor = newColor;
17039
+ this.requestRender();
17040
+ }
17041
+ }
17042
+ get border() {
17043
+ return this._border;
17044
+ }
17045
+ set border(value) {
17046
+ if (this._border !== value) {
17047
+ this._border = value;
17048
+ this.borderSides = getBorderSides(value);
17049
+ this.applyYogaBorders();
17050
+ this.requestRender();
17051
+ }
17052
+ }
17053
+ get borderStyle() {
17054
+ return this._borderStyle;
17055
+ }
17056
+ set borderStyle(value) {
17057
+ const _value = parseBorderStyle(value, this._defaultOptions.borderStyle);
17058
+ if (this._borderStyle !== _value || !this._border) {
17059
+ this._borderStyle = _value;
17060
+ this._customBorderChars = undefined;
17061
+ this.initializeBorder();
17062
+ this.requestRender();
17063
+ }
17064
+ }
17065
+ get borderColor() {
17066
+ return this._borderColor;
17067
+ }
17068
+ set borderColor(value) {
17069
+ const newColor = parseColor(value ?? this._defaultOptions.borderColor);
17070
+ if (this._borderColor !== newColor) {
17071
+ this._borderColor = newColor;
17072
+ this.initializeBorder();
17073
+ this.requestRender();
17074
+ }
17075
+ }
17076
+ get focusedBorderColor() {
17077
+ return this._focusedBorderColor;
17078
+ }
17079
+ set focusedBorderColor(value) {
17080
+ const newColor = parseColor(value ?? this._defaultOptions.focusedBorderColor);
17081
+ if (this._focusedBorderColor !== newColor) {
17082
+ this._focusedBorderColor = newColor;
17083
+ this.initializeBorder();
17084
+ if (this._focused) {
17085
+ this.requestRender();
17086
+ }
17087
+ }
17088
+ }
17089
+ get title() {
17090
+ return this._title;
17091
+ }
17092
+ set title(value) {
17093
+ if (this._title !== value) {
17094
+ this._title = value;
17095
+ this.requestRender();
17096
+ }
17097
+ }
17098
+ get titleAlignment() {
17099
+ return this._titleAlignment;
17100
+ }
17101
+ set titleAlignment(value) {
17102
+ if (this._titleAlignment !== value) {
17103
+ this._titleAlignment = value;
17104
+ this.requestRender();
17105
+ }
17106
+ }
17107
+ get bottomTitle() {
17108
+ return this._bottomTitle;
17109
+ }
17110
+ set bottomTitle(value) {
17111
+ if (this._bottomTitle !== value) {
17112
+ this._bottomTitle = value;
17113
+ this.requestRender();
17114
+ }
17115
+ }
17116
+ get bottomTitleAlignment() {
17117
+ return this._bottomTitleAlignment;
17118
+ }
17119
+ set bottomTitleAlignment(value) {
17120
+ if (this._bottomTitleAlignment !== value) {
17121
+ this._bottomTitleAlignment = value;
17122
+ this.requestRender();
17123
+ }
17124
+ }
17125
+ renderSelf(buffer) {
17126
+ const hasBorder = this.borderSides.top || this.borderSides.right || this.borderSides.bottom || this.borderSides.left;
17127
+ const hasVisibleFill = this.shouldFill && this._backgroundColor.a > 0;
17128
+ if (!hasBorder && !hasVisibleFill) {
17129
+ return;
17130
+ }
17131
+ const hasFocusWithin = this._focusable && (this._focused || this._hasFocusedDescendant);
17132
+ const currentBorderColor = hasFocusWithin ? this._focusedBorderColor : this._borderColor;
17133
+ const screenX = this._screenX;
17134
+ const screenY = this._screenY;
17135
+ buffer.drawBox({
17136
+ x: screenX,
17137
+ y: screenY,
17138
+ width: this.width,
17139
+ height: this.height,
17140
+ borderStyle: this._borderStyle,
17141
+ customBorderChars: this._customBorderChars,
17142
+ border: this._border,
17143
+ borderColor: currentBorderColor,
17144
+ backgroundColor: this._backgroundColor,
17145
+ shouldFill: this.shouldFill,
17146
+ title: this._title,
17147
+ titleAlignment: this._titleAlignment,
17148
+ bottomTitle: this._bottomTitle,
17149
+ bottomTitleAlignment: this._bottomTitleAlignment
17150
+ });
17151
+ }
17152
+ getScissorRect() {
17153
+ const baseRect = super.getScissorRect();
17154
+ if (!this.borderSides.top && !this.borderSides.right && !this.borderSides.bottom && !this.borderSides.left) {
17155
+ return baseRect;
17156
+ }
17157
+ const leftInset = this.borderSides.left ? 1 : 0;
17158
+ const rightInset = this.borderSides.right ? 1 : 0;
17159
+ const topInset = this.borderSides.top ? 1 : 0;
17160
+ const bottomInset = this.borderSides.bottom ? 1 : 0;
17161
+ return {
17162
+ x: baseRect.x + leftInset,
17163
+ y: baseRect.y + topInset,
17164
+ width: Math.max(0, baseRect.width - leftInset - rightInset),
17165
+ height: Math.max(0, baseRect.height - topInset - bottomInset)
17166
+ };
17167
+ }
17168
+ applyYogaBorders() {
17169
+ const node = this.yogaNode;
17170
+ node.setBorder(Edge.Left, this.borderSides.left ? 1 : 0);
17171
+ node.setBorder(Edge.Right, this.borderSides.right ? 1 : 0);
17172
+ node.setBorder(Edge.Top, this.borderSides.top ? 1 : 0);
17173
+ node.setBorder(Edge.Bottom, this.borderSides.bottom ? 1 : 0);
17174
+ this.requestRender();
17175
+ }
17176
+ applyYogaGap(options) {
17177
+ const node = this.yogaNode;
17178
+ if (isGapType(options.gap)) {
17179
+ node.setGap(Gutter.All, options.gap);
17180
+ }
17181
+ if (isGapType(options.rowGap)) {
17182
+ node.setGap(Gutter.Row, options.rowGap);
17183
+ }
17184
+ if (isGapType(options.columnGap)) {
17185
+ node.setGap(Gutter.Column, options.columnGap);
17186
+ }
17187
+ }
17188
+ set gap(gap) {
17189
+ if (isGapType(gap)) {
17190
+ this.yogaNode.setGap(Gutter.All, gap);
17191
+ this.requestRender();
17192
+ }
17193
+ }
17194
+ set rowGap(rowGap) {
17195
+ if (isGapType(rowGap)) {
17196
+ this.yogaNode.setGap(Gutter.Row, rowGap);
17197
+ this.requestRender();
17198
+ }
17199
+ }
17200
+ set columnGap(columnGap) {
17201
+ if (isGapType(columnGap)) {
17202
+ this.yogaNode.setGap(Gutter.Column, columnGap);
17203
+ this.requestRender();
17204
+ }
17205
+ }
17206
+ }
17207
+
17208
+ // src/renderables/TextBufferRenderable.ts
17209
+ class TextBufferRenderable extends Renderable {
17210
+ selectable = true;
17211
+ _defaultFg;
17212
+ _defaultBg;
17213
+ _defaultAttributes;
17214
+ _selectionBg;
17215
+ _selectionFg;
17216
+ _wrapMode = "word";
17217
+ lastLocalSelection = null;
17218
+ _tabIndicator;
17219
+ _tabIndicatorColor;
17220
+ _scrollX = 0;
17221
+ _scrollY = 0;
17222
+ _truncate = false;
17223
+ _firstLineOffset = 0;
17224
+ textBuffer;
17225
+ textBufferView;
17226
+ _textBufferSyntaxStyle;
17227
+ _defaultOptions = {
17228
+ fg: RGBA.fromValues(1, 1, 1, 1),
17229
+ bg: RGBA.fromValues(0, 0, 0, 0),
17230
+ selectionBg: undefined,
17231
+ selectionFg: undefined,
17232
+ selectable: true,
17233
+ attributes: 0,
17234
+ wrapMode: "word",
17235
+ tabIndicator: undefined,
17236
+ tabIndicatorColor: undefined,
17237
+ truncate: false
17238
+ };
17239
+ constructor(ctx, options) {
17240
+ super(ctx, options);
17241
+ this._defaultFg = parseColor(options.fg ?? this._defaultOptions.fg);
17242
+ this._defaultBg = parseColor(options.bg ?? this._defaultOptions.bg);
17243
+ this._defaultAttributes = options.attributes ?? this._defaultOptions.attributes;
17244
+ this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : this._defaultOptions.selectionBg;
17245
+ this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : this._defaultOptions.selectionFg;
17246
+ this.selectable = options.selectable ?? this._defaultOptions.selectable;
17247
+ this._wrapMode = options.wrapMode ?? this._defaultOptions.wrapMode;
17248
+ this._tabIndicator = options.tabIndicator ?? this._defaultOptions.tabIndicator;
17249
+ this._tabIndicatorColor = options.tabIndicatorColor ? parseColor(options.tabIndicatorColor) : this._defaultOptions.tabIndicatorColor;
17250
+ this._truncate = options.truncate ?? this._defaultOptions.truncate;
17251
+ this.textBuffer = TextBuffer.create(this._ctx.widthMethod);
17252
+ this.textBufferView = TextBufferView.create(this.textBuffer);
17253
+ this._firstLineOffset = ctx.claimFirstLineOffset?.(this) ?? 0;
17254
+ this._textBufferSyntaxStyle = SyntaxStyle.create();
17255
+ this.textBuffer.setSyntaxStyle(this._textBufferSyntaxStyle);
17256
+ this.textBufferView.setWrapMode(this._wrapMode);
17257
+ this.textBufferView.setFirstLineOffset(this._firstLineOffset);
17258
+ this.setupMeasureFunc();
17259
+ this.textBuffer.setDefaultFg(this._defaultFg);
17260
+ this.textBuffer.setDefaultBg(this._defaultBg);
17261
+ this.textBuffer.setDefaultAttributes(this._defaultAttributes);
17262
+ if (this._tabIndicator !== undefined) {
17263
+ this.textBufferView.setTabIndicator(this._tabIndicator);
17264
+ }
17265
+ if (this._tabIndicatorColor !== undefined) {
17266
+ this.textBufferView.setTabIndicatorColor(this._tabIndicatorColor);
17267
+ }
17268
+ if (this._wrapMode !== "none" && this.width > 0) {
17269
+ this.textBufferView.setWrapWidth(this.width);
17270
+ }
17271
+ if (this.width > 0 && this.height > 0) {
17272
+ this.textBufferView.setViewport(this._scrollX, this._scrollY, this.width, this.height);
17273
+ }
17274
+ this.textBufferView.setTruncate(this._truncate);
17275
+ this.updateTextInfo();
17276
+ }
17277
+ onMouseEvent(event) {
17278
+ if (event.type === "scroll") {
17279
+ this.handleScroll(event);
17280
+ }
17281
+ }
17282
+ handleScroll(event) {
17283
+ if (!event.scroll)
17284
+ return;
17285
+ const { direction, delta } = event.scroll;
17286
+ if (direction === "up") {
17287
+ this.scrollY -= delta;
17288
+ } else if (direction === "down") {
17289
+ this.scrollY += delta;
17290
+ }
17291
+ if (this._wrapMode === "none") {
17292
+ if (direction === "left") {
17293
+ this.scrollX -= delta;
17294
+ } else if (direction === "right") {
17295
+ this.scrollX += delta;
17296
+ }
17297
+ }
17298
+ }
17299
+ get lineInfo() {
17300
+ return this.textBufferView.logicalLineInfo;
17301
+ }
17302
+ get lineCount() {
17303
+ return this.textBuffer.getLineCount();
17304
+ }
17305
+ get virtualLineCount() {
17306
+ return this.textBufferView.getVirtualLineCount();
17307
+ }
17308
+ get scrollY() {
17309
+ return this._scrollY;
17310
+ }
17311
+ set scrollY(value) {
17312
+ const maxScrollY = Math.max(0, this.scrollHeight - this.height);
17313
+ const clamped = Math.max(0, Math.min(value, maxScrollY));
17314
+ if (this._scrollY !== clamped) {
17315
+ this._scrollY = clamped;
17316
+ this.updateViewportOffset();
17317
+ this.requestRender();
17318
+ }
17319
+ }
17320
+ get scrollX() {
17321
+ return this._scrollX;
17322
+ }
17323
+ set scrollX(value) {
17324
+ const maxScrollX = Math.max(0, this.scrollWidth - this.width);
17325
+ const clamped = Math.max(0, Math.min(value, maxScrollX));
17326
+ if (this._scrollX !== clamped) {
17327
+ this._scrollX = clamped;
17328
+ this.updateViewportOffset();
17329
+ this.requestRender();
17330
+ }
17331
+ }
17332
+ get scrollWidth() {
17333
+ return this.lineInfo.lineWidthColsMax;
17334
+ }
17335
+ get scrollHeight() {
17336
+ return this.lineInfo.lineStartCols.length;
17337
+ }
17338
+ get maxScrollY() {
17339
+ return Math.max(0, this.scrollHeight - this.height);
17340
+ }
17341
+ get maxScrollX() {
17342
+ return Math.max(0, this.scrollWidth - this.width);
17343
+ }
17344
+ updateViewportOffset() {
17345
+ if (this.width > 0 && this.height > 0) {
17346
+ this.textBufferView.setViewport(this._scrollX, this._scrollY, this.width, this.height);
17347
+ }
17348
+ }
17349
+ get plainText() {
17350
+ return this.textBuffer.getPlainText();
17351
+ }
17352
+ get textLength() {
17353
+ return this.textBuffer.length;
17354
+ }
17355
+ get fg() {
17356
+ return this._defaultFg;
17357
+ }
17358
+ set fg(value) {
17359
+ const newColor = parseColor(value ?? this._defaultOptions.fg);
17360
+ if (this._defaultFg !== newColor) {
17361
+ this._defaultFg = newColor;
17362
+ this.textBuffer.setDefaultFg(this._defaultFg);
17363
+ this.onFgChanged(newColor);
17364
+ this.requestRender();
17365
+ }
17366
+ }
17367
+ get selectionBg() {
17368
+ return this._selectionBg;
17369
+ }
17370
+ set selectionBg(value) {
17371
+ const newColor = value ? parseColor(value) : this._defaultOptions.selectionBg;
17372
+ if (this._selectionBg !== newColor) {
17373
+ this._selectionBg = newColor;
17374
+ if (this.lastLocalSelection) {
17375
+ this.updateLocalSelection(this.lastLocalSelection);
17376
+ }
17377
+ this.requestRender();
17378
+ }
17379
+ }
17380
+ get selectionFg() {
17381
+ return this._selectionFg;
17382
+ }
17383
+ set selectionFg(value) {
17384
+ const newColor = value ? parseColor(value) : this._defaultOptions.selectionFg;
17385
+ if (this._selectionFg !== newColor) {
17386
+ this._selectionFg = newColor;
17387
+ if (this.lastLocalSelection) {
17388
+ this.updateLocalSelection(this.lastLocalSelection);
17389
+ }
17390
+ this.requestRender();
17391
+ }
17392
+ }
17393
+ get bg() {
17394
+ return this._defaultBg;
17395
+ }
17396
+ set bg(value) {
17397
+ const newColor = parseColor(value ?? this._defaultOptions.bg);
17398
+ if (this._defaultBg !== newColor) {
17399
+ this._defaultBg = newColor;
17400
+ this.textBuffer.setDefaultBg(this._defaultBg);
17401
+ this.onBgChanged(newColor);
17402
+ this.requestRender();
17403
+ }
17404
+ }
17405
+ get attributes() {
17406
+ return this._defaultAttributes;
17407
+ }
17408
+ set attributes(value) {
17409
+ if (this._defaultAttributes !== value) {
17410
+ this._defaultAttributes = value;
17411
+ this.textBuffer.setDefaultAttributes(this._defaultAttributes);
17412
+ this.onAttributesChanged(value);
17413
+ this.requestRender();
17414
+ }
17415
+ }
17416
+ get wrapMode() {
17417
+ return this._wrapMode;
17418
+ }
17419
+ set wrapMode(value) {
17420
+ if (this._wrapMode !== value) {
17421
+ this._wrapMode = value;
17422
+ this.textBufferView.setWrapMode(this._wrapMode);
17423
+ if (value !== "none" && this.width > 0) {
17424
+ this.textBufferView.setWrapWidth(this.width);
17425
+ }
17426
+ this.yogaNode.markDirty();
17427
+ this.requestRender();
17428
+ }
17429
+ }
17430
+ get tabIndicator() {
17431
+ return this._tabIndicator;
17432
+ }
17433
+ set tabIndicator(value) {
17434
+ if (this._tabIndicator !== value) {
17435
+ this._tabIndicator = value;
17436
+ if (value !== undefined) {
17437
+ this.textBufferView.setTabIndicator(value);
17438
+ }
17439
+ this.requestRender();
17440
+ }
17441
+ }
17442
+ get tabIndicatorColor() {
17443
+ return this._tabIndicatorColor;
17444
+ }
17445
+ set tabIndicatorColor(value) {
17446
+ const newColor = value ? parseColor(value) : undefined;
17447
+ if (this._tabIndicatorColor !== newColor) {
17448
+ this._tabIndicatorColor = newColor;
17449
+ if (newColor !== undefined) {
17450
+ this.textBufferView.setTabIndicatorColor(newColor);
17451
+ }
17452
+ this.requestRender();
17453
+ }
17454
+ }
17455
+ get truncate() {
17456
+ return this._truncate;
17457
+ }
17458
+ set truncate(value) {
17459
+ if (this._truncate !== value) {
17460
+ this._truncate = value;
17461
+ this.textBufferView.setTruncate(value);
17462
+ this.requestRender();
17463
+ }
17464
+ }
17465
+ onResize(width, height) {
17466
+ this.textBufferView.setViewport(this._scrollX, this._scrollY, width, height);
17467
+ this.yogaNode.markDirty();
17468
+ this.requestRender();
17469
+ this.emit("line-info-change");
17470
+ }
17471
+ refreshLocalSelection() {
17472
+ if (this.lastLocalSelection) {
17473
+ return this.updateLocalSelection(this.lastLocalSelection);
17474
+ }
17475
+ return false;
17476
+ }
17477
+ updateLocalSelection(localSelection) {
17478
+ if (!localSelection?.isActive) {
17479
+ this.textBufferView.resetLocalSelection();
17480
+ return true;
17481
+ }
17482
+ return this.textBufferView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
17483
+ }
17484
+ updateTextInfo() {
17485
+ if (this.lastLocalSelection) {
17486
+ this.updateLocalSelection(this.lastLocalSelection);
17487
+ }
17488
+ this.yogaNode.markDirty();
17489
+ this.requestRender();
17490
+ this.emit("line-info-change");
17491
+ }
17492
+ setupMeasureFunc() {
17493
+ const measureFunc = (width, widthMode, height, heightMode) => {
17494
+ let effectiveWidth;
17495
+ if (widthMode === MeasureMode.Undefined || isNaN(width)) {
17496
+ effectiveWidth = 0;
17497
+ } else {
17498
+ effectiveWidth = width;
17499
+ }
17500
+ const effectiveHeight = isNaN(height) ? 1 : height;
17501
+ const measureResult = this.textBufferView.measureForDimensions(Math.floor(effectiveWidth), Math.floor(effectiveHeight));
17502
+ const measuredWidth = measureResult ? Math.max(1, measureResult.widthColsMax) : 1;
17503
+ const measuredHeight = measureResult ? Math.max(1, measureResult.lineCount) : 1;
17504
+ if (widthMode === MeasureMode.AtMost && this._positionType !== "absolute") {
17505
+ return {
17506
+ width: Math.min(effectiveWidth, measuredWidth),
17507
+ height: Math.min(effectiveHeight, measuredHeight)
17508
+ };
17509
+ }
17510
+ return {
17511
+ width: measuredWidth,
17512
+ height: measuredHeight
17513
+ };
17514
+ };
17515
+ this.yogaNode.setMeasureFunc(measureFunc);
17516
+ }
17517
+ shouldStartSelection(x, y) {
17518
+ if (!this.selectable)
17519
+ return false;
17520
+ const localX = x - this.x;
17521
+ const localY = y - this.y;
17522
+ return localX >= 0 && localX < this.width && localY >= 0 && localY < this.height;
17523
+ }
17524
+ onSelectionChanged(selection2) {
17525
+ const localSelection = convertGlobalToLocalSelection(selection2, this.x, this.y);
17526
+ this.lastLocalSelection = localSelection;
17527
+ let changed;
17528
+ if (!localSelection?.isActive) {
17529
+ this.textBufferView.resetLocalSelection();
17530
+ changed = true;
17531
+ } else if (selection2?.isStart) {
17532
+ changed = this.textBufferView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
17533
+ } else {
17534
+ changed = this.textBufferView.updateLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
17535
+ }
17536
+ if (changed) {
17537
+ this.requestRender();
17538
+ }
17539
+ return this.hasSelection();
17540
+ }
17541
+ getSelectedText() {
17542
+ return this.textBufferView.getSelectedText();
17543
+ }
17544
+ hasSelection() {
17545
+ return this.textBufferView.hasSelection();
17546
+ }
17547
+ getSelection() {
17548
+ return this.textBufferView.getSelection();
17549
+ }
17550
+ render(buffer, deltaTime) {
17551
+ if (!this.visible)
17552
+ return;
17553
+ const screenX = this._screenX;
17554
+ const screenY = this._screenY;
17555
+ this.markClean();
17556
+ this._ctx.addToHitGrid(screenX, screenY, this.width, this.height, this.num);
17557
+ this.renderSelf(buffer);
17558
+ if (this.buffered && this.frameBuffer) {
17559
+ buffer.drawFrameBuffer(screenX, screenY, this.frameBuffer);
17560
+ }
17561
+ }
17562
+ renderSelf(buffer) {
17563
+ if (this.textBuffer.ptr) {
17564
+ buffer.drawTextBuffer(this.textBufferView, this._screenX, this._screenY);
17565
+ }
17566
+ }
17567
+ destroy() {
17568
+ if (this.isDestroyed)
17569
+ return;
17570
+ this.textBuffer.setSyntaxStyle(null);
17571
+ this._textBufferSyntaxStyle.destroy();
17572
+ this.textBufferView.destroy();
17573
+ this.textBuffer.destroy();
17574
+ super.destroy();
17575
+ }
17576
+ onFgChanged(newColor) {}
17577
+ onBgChanged(newColor) {}
17578
+ onAttributesChanged(newAttributes) {}
17579
+ }
17580
+
17581
+ // src/renderables/Code.ts
17582
+ class CodeRenderable extends TextBufferRenderable {
17583
+ _content;
17584
+ _filetype;
17585
+ _syntaxStyle;
17586
+ _isHighlighting = false;
17587
+ _treeSitterClient;
17588
+ _highlightsDirty = false;
17589
+ _highlightSnapshotId = 0;
17590
+ _conceal;
17591
+ _drawUnstyledText;
17592
+ _shouldRenderTextBuffer = true;
17593
+ _streaming;
17594
+ _hadInitialContent = false;
17595
+ _lastHighlights = [];
17596
+ _onHighlight;
17597
+ _onChunks;
17598
+ _highlightingPromise = Promise.resolve();
17599
+ _contentDefaultOptions = {
17600
+ content: "",
17601
+ conceal: true,
17602
+ drawUnstyledText: true,
17603
+ streaming: false
17604
+ };
17605
+ constructor(ctx, options) {
17606
+ super(ctx, options);
17607
+ this._content = options.content ?? this._contentDefaultOptions.content;
17608
+ this._filetype = options.filetype;
17609
+ this._syntaxStyle = options.syntaxStyle;
17610
+ this._treeSitterClient = options.treeSitterClient ?? getTreeSitterClient();
17611
+ this._conceal = options.conceal ?? this._contentDefaultOptions.conceal;
17612
+ this._drawUnstyledText = options.drawUnstyledText ?? this._contentDefaultOptions.drawUnstyledText;
17613
+ this._streaming = options.streaming ?? this._contentDefaultOptions.streaming;
17614
+ this._onHighlight = options.onHighlight;
17615
+ this._onChunks = options.onChunks;
17616
+ if (this._content.length > 0) {
17617
+ this.textBuffer.setText(this._content);
17618
+ this.updateTextInfo();
17619
+ this._shouldRenderTextBuffer = this._drawUnstyledText || !this._filetype;
17620
+ }
17621
+ this._highlightsDirty = this._content.length > 0;
17622
+ }
17623
+ get content() {
17624
+ return this._content;
17625
+ }
17626
+ set content(value) {
17627
+ if (this._content !== value) {
17628
+ this._content = value;
17629
+ this._highlightsDirty = true;
17630
+ this._highlightSnapshotId++;
17631
+ if (this._streaming && !this._drawUnstyledText && this._filetype) {
17632
+ return;
17633
+ }
17634
+ this.textBuffer.setText(value);
17635
+ this.updateTextInfo();
17636
+ }
17637
+ }
17638
+ get filetype() {
17639
+ return this._filetype;
17640
+ }
17641
+ set filetype(value) {
17642
+ if (this._filetype !== value) {
17643
+ this._filetype = value;
17644
+ this._highlightsDirty = true;
17645
+ }
17646
+ }
17647
+ get syntaxStyle() {
17648
+ return this._syntaxStyle;
17649
+ }
17650
+ set syntaxStyle(value) {
17651
+ if (this._syntaxStyle !== value) {
17652
+ this._syntaxStyle = value;
17653
+ this._highlightsDirty = true;
17654
+ }
17655
+ }
17656
+ get conceal() {
17657
+ return this._conceal;
17658
+ }
17659
+ set conceal(value) {
17660
+ if (this._conceal !== value) {
17661
+ this._conceal = value;
17662
+ this._highlightsDirty = true;
17663
+ }
17664
+ }
17665
+ get drawUnstyledText() {
17666
+ return this._drawUnstyledText;
17667
+ }
17668
+ set drawUnstyledText(value) {
17669
+ if (this._drawUnstyledText !== value) {
17670
+ this._drawUnstyledText = value;
17671
+ this._highlightsDirty = true;
17672
+ }
17673
+ }
17674
+ get streaming() {
17675
+ return this._streaming;
17676
+ }
17677
+ set streaming(value) {
17678
+ if (this._streaming !== value) {
17679
+ this._streaming = value;
17680
+ this._hadInitialContent = false;
17681
+ this._lastHighlights = [];
17682
+ this._highlightsDirty = true;
17683
+ }
17684
+ }
17685
+ get treeSitterClient() {
17686
+ return this._treeSitterClient;
17687
+ }
17688
+ set treeSitterClient(value) {
17689
+ if (this._treeSitterClient !== value) {
17690
+ this._treeSitterClient = value;
17691
+ this._highlightsDirty = true;
17692
+ }
17693
+ }
17694
+ get onHighlight() {
17695
+ return this._onHighlight;
17696
+ }
17697
+ set onHighlight(value) {
17698
+ if (this._onHighlight !== value) {
17699
+ this._onHighlight = value;
17700
+ this._highlightsDirty = true;
17701
+ }
17702
+ }
17703
+ get onChunks() {
17704
+ return this._onChunks;
17705
+ }
17706
+ set onChunks(value) {
17707
+ if (this._onChunks !== value) {
17708
+ this._onChunks = value;
17709
+ this._highlightsDirty = true;
17710
+ }
17711
+ }
17712
+ get isHighlighting() {
17713
+ return this._isHighlighting;
17714
+ }
17715
+ get highlightingDone() {
17716
+ return this._highlightingPromise;
17717
+ }
17718
+ async transformChunks(chunks, context) {
17719
+ if (!this._onChunks)
17720
+ return chunks;
17721
+ const modified = await this._onChunks(chunks, context);
17722
+ return modified ?? chunks;
17723
+ }
17724
+ ensureVisibleTextBeforeHighlight() {
17725
+ if (this.isDestroyed)
17726
+ return;
17727
+ const content = this._content;
17728
+ if (!this._filetype) {
17729
+ this._shouldRenderTextBuffer = true;
17730
+ return;
17731
+ }
17732
+ const isInitialContent = this._streaming && !this._hadInitialContent;
17733
+ const shouldDrawUnstyledNow = this._streaming ? isInitialContent && this._drawUnstyledText : this._drawUnstyledText;
17734
+ if (this._streaming && !isInitialContent) {
17735
+ this._shouldRenderTextBuffer = true;
17736
+ } else if (shouldDrawUnstyledNow) {
17737
+ this.textBuffer.setText(content);
17738
+ this._shouldRenderTextBuffer = true;
17739
+ } else {
17740
+ this._shouldRenderTextBuffer = false;
17741
+ }
17742
+ }
17743
+ async startHighlight() {
17744
+ const content = this._content;
17745
+ const filetype = this._filetype;
17746
+ const snapshotId = ++this._highlightSnapshotId;
17747
+ if (!filetype)
17748
+ return;
17749
+ const isInitialContent = this._streaming && !this._hadInitialContent;
17750
+ if (isInitialContent) {
17751
+ this._hadInitialContent = true;
17752
+ }
17753
+ this._isHighlighting = true;
17754
+ try {
17755
+ const result = await this._treeSitterClient.highlightOnce(content, filetype);
17756
+ if (snapshotId !== this._highlightSnapshotId) {
17757
+ return;
17758
+ }
17759
+ if (this.isDestroyed)
17760
+ return;
17761
+ let highlights = result.highlights ?? [];
17762
+ if (this._onHighlight && highlights.length >= 0) {
17763
+ const context = {
17764
+ content,
17765
+ filetype,
17766
+ syntaxStyle: this._syntaxStyle
17767
+ };
17768
+ const modified = await this._onHighlight(highlights, context);
17769
+ if (modified !== undefined) {
17770
+ highlights = modified;
17771
+ }
17772
+ }
17773
+ if (snapshotId !== this._highlightSnapshotId) {
17774
+ return;
17775
+ }
17776
+ if (this.isDestroyed)
17777
+ return;
17778
+ if (highlights.length > 0) {
17779
+ if (this._streaming) {
17780
+ this._lastHighlights = highlights;
17781
+ }
17782
+ }
17783
+ if (highlights.length > 0 || this._onChunks) {
17784
+ const context = {
17785
+ content,
17786
+ filetype,
17787
+ syntaxStyle: this._syntaxStyle,
17788
+ highlights
17789
+ };
17790
+ let chunks = treeSitterToTextChunks(content, highlights, this._syntaxStyle, {
17791
+ enabled: this._conceal
17792
+ });
17793
+ chunks = await this.transformChunks(chunks, context);
17794
+ if (snapshotId !== this._highlightSnapshotId) {
17795
+ return;
17796
+ }
17797
+ if (this.isDestroyed)
17798
+ return;
17799
+ const styledText = new StyledText(chunks);
17800
+ this.textBuffer.setStyledText(styledText);
17801
+ } else {
17802
+ this.textBuffer.setText(content);
17803
+ }
17804
+ this._shouldRenderTextBuffer = true;
17805
+ this._isHighlighting = false;
17806
+ this._highlightsDirty = false;
17807
+ this.updateTextInfo();
17808
+ this.requestRender();
17809
+ } catch (error) {
17810
+ if (snapshotId !== this._highlightSnapshotId) {
17811
+ return;
17812
+ }
17813
+ console.warn("Code highlighting failed, falling back to plain text:", error);
17814
+ if (this.isDestroyed)
17815
+ return;
17816
+ this.textBuffer.setText(content);
17817
+ this._shouldRenderTextBuffer = true;
17818
+ this._isHighlighting = false;
17819
+ this._highlightsDirty = false;
17820
+ this.updateTextInfo();
17821
+ this.requestRender();
17822
+ }
17823
+ }
17824
+ getLineHighlights(lineIdx) {
17825
+ return this.textBuffer.getLineHighlights(lineIdx);
17826
+ }
17827
+ renderSelf(buffer) {
17828
+ if (this._highlightsDirty) {
17829
+ if (this.isDestroyed)
17830
+ return;
17831
+ if (this._content.length === 0) {
17832
+ this._shouldRenderTextBuffer = false;
17833
+ this._highlightsDirty = false;
17834
+ } else if (!this._filetype) {
17835
+ this._shouldRenderTextBuffer = true;
17836
+ this._highlightsDirty = false;
17837
+ } else {
17838
+ this.ensureVisibleTextBeforeHighlight();
17839
+ this._highlightsDirty = false;
17840
+ this._highlightingPromise = this.startHighlight();
17841
+ }
17842
+ }
17843
+ if (!this._shouldRenderTextBuffer)
17844
+ return;
17845
+ super.renderSelf(buffer);
17846
+ }
17847
+ }
17848
+
17849
+ // src/renderables/TextNode.ts
17850
+ var BrandedTextNodeRenderable = Symbol.for("@opentui/core/TextNodeRenderable");
17851
+ function isTextNodeRenderable(obj) {
17852
+ return !!obj?.[BrandedTextNodeRenderable];
17853
+ }
17854
+ function styledTextToTextNodes(styledText) {
17855
+ return styledText.chunks.map((chunk) => {
17856
+ const node = new TextNodeRenderable({
17857
+ fg: chunk.fg,
17858
+ bg: chunk.bg,
17859
+ attributes: chunk.attributes,
17860
+ link: chunk.link
17861
+ });
17862
+ node.add(chunk.text);
17863
+ return node;
17864
+ });
17865
+ }
17866
+
17867
+ class TextNodeRenderable extends BaseRenderable {
17868
+ [BrandedTextNodeRenderable] = true;
17869
+ _fg;
17870
+ _bg;
17871
+ _attributes;
17872
+ _link;
17873
+ _children = [];
17874
+ parent = null;
17875
+ constructor(options) {
17876
+ super(options);
17877
+ this._fg = options.fg ? parseColor(options.fg) : undefined;
17878
+ this._bg = options.bg ? parseColor(options.bg) : undefined;
17879
+ this._attributes = options.attributes ?? 0;
17880
+ this._link = options.link;
17881
+ }
17882
+ get children() {
17883
+ return this._children;
17884
+ }
17885
+ set children(children) {
17886
+ this._children = children;
17887
+ this.requestRender();
17888
+ }
17889
+ requestRender() {
17890
+ this.markDirty();
17891
+ this.parent?.requestRender();
17892
+ }
17893
+ add(obj, index) {
17894
+ if (typeof obj === "string") {
17895
+ if (index !== undefined) {
17896
+ this._children.splice(index, 0, obj);
17897
+ this.requestRender();
17898
+ return index;
17899
+ }
17900
+ const insertIndex = this._children.length;
17901
+ this._children.push(obj);
17902
+ this.requestRender();
17903
+ return insertIndex;
17904
+ }
17905
+ if (isTextNodeRenderable(obj)) {
17906
+ if (index !== undefined) {
17907
+ this._children.splice(index, 0, obj);
17908
+ obj.parent = this;
17909
+ this.requestRender();
17910
+ return index;
17911
+ }
17912
+ const insertIndex = this._children.length;
17913
+ this._children.push(obj);
17914
+ obj.parent = this;
17915
+ this.requestRender();
17916
+ return insertIndex;
17917
+ }
17918
+ if (isStyledText(obj)) {
17919
+ const textNodes = styledTextToTextNodes(obj);
17920
+ if (index !== undefined) {
17921
+ this._children.splice(index, 0, ...textNodes);
17922
+ textNodes.forEach((node) => node.parent = this);
17923
+ this.requestRender();
17924
+ return index;
17925
+ }
17926
+ const insertIndex = this._children.length;
17927
+ this._children.push(...textNodes);
17928
+ textNodes.forEach((node) => node.parent = this);
17929
+ this.requestRender();
17930
+ return insertIndex;
17931
+ }
17932
+ throw new Error("TextNodeRenderable only accepts strings, TextNodeRenderable instances, or StyledText instances");
17933
+ }
17934
+ replace(obj, index) {
17935
+ this._children[index] = obj;
17936
+ if (typeof obj !== "string") {
17937
+ obj.parent = this;
17938
+ }
17939
+ this.requestRender();
17940
+ }
17941
+ insertBefore(child, anchorNode) {
17942
+ if (!anchorNode || !isTextNodeRenderable(anchorNode)) {
17943
+ throw new Error("Anchor must be a TextNodeRenderable");
17944
+ }
17945
+ const anchorIndex = this._children.indexOf(anchorNode);
17946
+ if (anchorIndex === -1) {
17947
+ throw new Error("Anchor node not found in children");
17948
+ }
17949
+ if (typeof child === "string") {
17950
+ this._children.splice(anchorIndex, 0, child);
17951
+ } else if (isTextNodeRenderable(child)) {
17952
+ this._children.splice(anchorIndex, 0, child);
17953
+ child.parent = this;
17954
+ } else if (child instanceof StyledText) {
17955
+ const textNodes = styledTextToTextNodes(child);
17956
+ this._children.splice(anchorIndex, 0, ...textNodes);
17957
+ textNodes.forEach((node) => node.parent = this);
17958
+ } else {
17959
+ throw new Error("Child must be a string, TextNodeRenderable, or StyledText instance");
17960
+ }
17961
+ this.requestRender();
17962
+ return this;
17963
+ }
17964
+ remove(id) {
17965
+ const childIndex = this.getRenderableIndex(id);
17966
+ if (childIndex === -1) {
17967
+ throw new Error("Child not found in children");
17968
+ }
17969
+ const child = this._children[childIndex];
17970
+ this._children.splice(childIndex, 1);
17971
+ child.parent = null;
17972
+ this.requestRender();
17973
+ return this;
17974
+ }
17975
+ clear() {
17976
+ this._children = [];
17977
+ this.requestRender();
17978
+ }
17979
+ mergeStyles(parentStyle) {
17980
+ return {
17981
+ fg: this._fg ?? parentStyle.fg,
17982
+ bg: this._bg ?? parentStyle.bg,
17983
+ attributes: this._attributes | parentStyle.attributes,
17984
+ link: this._link ?? parentStyle.link
17985
+ };
17986
+ }
17987
+ gatherWithInheritedStyle(parentStyle = {
17988
+ fg: undefined,
17989
+ bg: undefined,
17990
+ attributes: 0
17991
+ }) {
17992
+ const currentStyle = this.mergeStyles(parentStyle);
17993
+ const chunks = [];
17994
+ for (const child of this._children) {
17995
+ if (typeof child === "string") {
17996
+ chunks.push({
17997
+ __isChunk: true,
17998
+ text: child,
17999
+ fg: currentStyle.fg,
18000
+ bg: currentStyle.bg,
18001
+ attributes: currentStyle.attributes,
18002
+ link: currentStyle.link
18003
+ });
18004
+ } else {
18005
+ const childChunks = child.gatherWithInheritedStyle(currentStyle);
18006
+ chunks.push(...childChunks);
18007
+ }
18008
+ }
18009
+ this.markClean();
18010
+ return chunks;
18011
+ }
18012
+ static fromString(text, options = {}) {
18013
+ const node = new TextNodeRenderable(options);
18014
+ node.add(text);
18015
+ return node;
18016
+ }
18017
+ static fromNodes(nodes, options = {}) {
18018
+ const node = new TextNodeRenderable(options);
18019
+ for (const childNode of nodes) {
18020
+ node.add(childNode);
18021
+ }
18022
+ return node;
18023
+ }
18024
+ toChunks(parentStyle = {
18025
+ fg: undefined,
18026
+ bg: undefined,
18027
+ attributes: 0
18028
+ }) {
18029
+ return this.gatherWithInheritedStyle(parentStyle);
18030
+ }
18031
+ getChildren() {
18032
+ return this._children.filter((child) => typeof child !== "string");
18033
+ }
18034
+ getChildrenCount() {
18035
+ return this._children.length;
18036
+ }
18037
+ getRenderable(id) {
18038
+ return this._children.find((child) => typeof child !== "string" && child.id === id);
18039
+ }
18040
+ getRenderableIndex(id) {
18041
+ return this._children.findIndex((child) => isTextNodeRenderable(child) && child.id === id);
18042
+ }
18043
+ get fg() {
18044
+ return this._fg;
18045
+ }
18046
+ set fg(fg2) {
18047
+ if (!fg2) {
18048
+ this._fg = undefined;
18049
+ this.requestRender();
18050
+ return;
18051
+ }
18052
+ this._fg = parseColor(fg2);
18053
+ this.requestRender();
18054
+ }
18055
+ set bg(bg2) {
18056
+ if (!bg2) {
18057
+ this._bg = undefined;
18058
+ this.requestRender();
18059
+ return;
18060
+ }
18061
+ this._bg = parseColor(bg2);
18062
+ this.requestRender();
18063
+ }
18064
+ get bg() {
18065
+ return this._bg;
18066
+ }
18067
+ set attributes(attributes) {
18068
+ this._attributes = attributes;
18069
+ this.requestRender();
18070
+ }
18071
+ get attributes() {
18072
+ return this._attributes;
18073
+ }
18074
+ set link(link2) {
18075
+ this._link = link2;
18076
+ this.requestRender();
18077
+ }
18078
+ get link() {
18079
+ return this._link;
18080
+ }
18081
+ findDescendantById(id) {
18082
+ return;
18083
+ }
18084
+ }
18085
+
18086
+ class RootTextNodeRenderable extends TextNodeRenderable {
18087
+ ctx;
18088
+ textParent;
18089
+ constructor(ctx, options, textParent) {
18090
+ super(options);
18091
+ this.ctx = ctx;
18092
+ this.textParent = textParent;
18093
+ }
18094
+ requestRender() {
18095
+ this.markDirty();
18096
+ this.ctx.requestRender();
18097
+ }
18098
+ }
18099
+
18100
+ // src/renderables/Text.ts
18101
+ class TextRenderable extends TextBufferRenderable {
18102
+ _text;
18103
+ _hasManualStyledText = false;
18104
+ rootTextNode;
18105
+ _contentDefaultOptions = {
18106
+ content: ""
18107
+ };
18108
+ constructor(ctx, options) {
18109
+ super(ctx, options);
18110
+ const content = options.content ?? this._contentDefaultOptions.content;
18111
+ const styledText = typeof content === "string" ? stringToStyledText(content) : content;
18112
+ this._text = styledText;
18113
+ this._hasManualStyledText = options.content !== undefined && content !== "";
18114
+ this.rootTextNode = new RootTextNodeRenderable(ctx, {
18115
+ id: `${this.id}-root`,
18116
+ fg: this._defaultFg,
18117
+ bg: this._defaultBg,
18118
+ attributes: this._defaultAttributes
18119
+ }, this);
18120
+ this.updateTextBuffer(styledText);
18121
+ }
18122
+ updateTextBuffer(styledText) {
18123
+ this.textBuffer.setStyledText(styledText);
18124
+ this.clearChunks(styledText);
18125
+ }
18126
+ clearChunks(styledText) {}
18127
+ get content() {
18128
+ return this._text;
18129
+ }
18130
+ get chunks() {
18131
+ return this._text.chunks;
18132
+ }
18133
+ get textNode() {
18134
+ return this.rootTextNode;
18135
+ }
18136
+ set content(value) {
18137
+ this._hasManualStyledText = true;
18138
+ const styledText = typeof value === "string" ? stringToStyledText(value) : value;
18139
+ if (this._text !== styledText) {
18140
+ this._text = styledText;
18141
+ this.updateTextBuffer(styledText);
18142
+ this.updateTextInfo();
18143
+ }
18144
+ }
18145
+ updateTextFromNodes() {
18146
+ if (this.rootTextNode.isDirty && !this._hasManualStyledText) {
18147
+ const chunks = this.rootTextNode.gatherWithInheritedStyle({
18148
+ fg: this._defaultFg,
18149
+ bg: this._defaultBg,
18150
+ attributes: this._defaultAttributes,
18151
+ link: undefined
18152
+ });
18153
+ this.textBuffer.setStyledText(new StyledText(chunks));
18154
+ this.refreshLocalSelection();
18155
+ this.yogaNode.markDirty();
18156
+ }
18157
+ }
18158
+ add(obj, index) {
18159
+ return this.rootTextNode.add(obj, index);
18160
+ }
18161
+ remove(id) {
18162
+ this.rootTextNode.remove(id);
18163
+ }
18164
+ insertBefore(obj, anchor) {
18165
+ this.rootTextNode.insertBefore(obj, anchor);
18166
+ return this.rootTextNode.children.indexOf(obj);
18167
+ }
18168
+ getTextChildren() {
18169
+ return this.rootTextNode.getChildren();
18170
+ }
18171
+ clear() {
18172
+ this.rootTextNode.clear();
18173
+ const emptyStyledText = stringToStyledText("");
18174
+ this._text = emptyStyledText;
18175
+ this.updateTextBuffer(emptyStyledText);
18176
+ this.updateTextInfo();
18177
+ this.requestRender();
18178
+ }
18179
+ onLifecyclePass = () => {
18180
+ this.updateTextFromNodes();
18181
+ };
18182
+ onFgChanged(newColor) {
18183
+ this.rootTextNode.fg = newColor;
18184
+ }
18185
+ onBgChanged(newColor) {
18186
+ this.rootTextNode.bg = newColor;
18187
+ }
18188
+ onAttributesChanged(newAttributes) {
18189
+ this.rootTextNode.attributes = newAttributes;
18190
+ }
18191
+ destroy() {
18192
+ this.rootTextNode.children.length = 0;
18193
+ super.destroy();
18194
+ }
18195
+ }
18196
+
18197
+ // src/console.ts
18198
+ import { EventEmitter as EventEmitter8 } from "events";
18199
+ import { Console } from "console";
18200
+ import fs from "fs";
18201
+ import path5 from "path";
18202
+ import util2 from "util";
18203
+
18204
+ // src/lib/output.capture.ts
18205
+ import { Writable } from "stream";
18206
+ import { EventEmitter as EventEmitter7 } from "events";
18207
+
18208
+ class Capture extends EventEmitter7 {
18209
+ output = [];
18210
+ constructor() {
18211
+ super();
18212
+ }
18213
+ get size() {
18214
+ return this.output.length;
18215
+ }
18216
+ write(stream, data) {
18217
+ this.output.push({ stream, output: data });
18218
+ this.emit("write", stream, data);
18219
+ }
18220
+ claimOutput() {
18221
+ const output = this.output.map((o) => o.output).join("");
18222
+ this.clear();
18223
+ return output;
18224
+ }
18225
+ clear() {
18226
+ this.output = [];
18227
+ }
18228
+ }
18229
+
18230
+ class CapturedWritableStream extends Writable {
18231
+ stream;
18232
+ capture;
18233
+ isTTY = true;
18234
+ columns = process.stdout.columns || 80;
18235
+ rows = process.stdout.rows || 24;
18236
+ constructor(stream, capture) {
18237
+ super();
18238
+ this.stream = stream;
18239
+ this.capture = capture;
18240
+ }
18241
+ _write(chunk, encoding, callback) {
18242
+ const data = chunk.toString();
18243
+ this.capture.write(this.stream, data);
18244
+ callback();
18245
+ }
18246
+ getColorDepth() {
18247
+ return process.stdout.getColorDepth?.() || 8;
18248
+ }
18249
+ }
18250
+
18251
+ // src/lib/keymapping.ts
18252
+ var defaultKeyAliases = {
18253
+ enter: "return",
18254
+ esc: "escape",
18255
+ kp0: "0",
18256
+ kp1: "1",
18257
+ kp2: "2",
18258
+ kp3: "3",
18259
+ kp4: "4",
18260
+ kp5: "5",
18261
+ kp6: "6",
18262
+ kp7: "7",
18263
+ kp8: "8",
18264
+ kp9: "9",
18265
+ kpdecimal: ".",
18266
+ kpdivide: "/",
18267
+ kpmultiply: "*",
18268
+ kpminus: "-",
18269
+ kpplus: "+",
18270
+ kpenter: "enter",
18271
+ kpequal: "=",
18272
+ kpseparator: ",",
18273
+ kpleft: "left",
18274
+ kpright: "right",
18275
+ kpup: "up",
18276
+ kpdown: "down",
18277
+ kppageup: "pageup",
18278
+ kppagedown: "pagedown",
18279
+ kphome: "home",
18280
+ kpend: "end",
18281
+ kpinsert: "insert",
18282
+ kpdelete: "delete"
18283
+ };
18284
+ function mergeKeyAliases(defaults, custom) {
18285
+ return { ...defaults, ...custom };
18286
+ }
18287
+ function mergeKeyBindings(defaults, custom) {
18288
+ const map = new Map;
18289
+ for (const binding of defaults) {
18290
+ const key = getKeyBindingKey(binding);
18291
+ map.set(key, binding);
18292
+ }
18293
+ for (const binding of custom) {
18294
+ const key = getKeyBindingKey(binding);
18295
+ map.set(key, binding);
18296
+ }
18297
+ return Array.from(map.values());
18298
+ }
18299
+ function getKeyBindingKey(binding) {
18300
+ return `${binding.name}:${binding.ctrl ? 1 : 0}:${binding.shift ? 1 : 0}:${binding.meta ? 1 : 0}:${binding.super ? 1 : 0}`;
18301
+ }
18302
+ function getBaseCodeKeyName(baseCode) {
18303
+ if (baseCode === undefined || baseCode < 32 || baseCode === 127) {
18304
+ return;
18305
+ }
18306
+ try {
18307
+ const name = String.fromCodePoint(baseCode);
16669
18308
  if (name.length === 1 && name >= "A" && name <= "Z") {
16670
18309
  return name.toLowerCase();
16671
18310
  }
@@ -18734,6 +20373,27 @@ function getObjectsInViewport(viewport, objects, direction = "column", padding =
18734
20373
  return visibleChildren;
18735
20374
  }
18736
20375
 
20376
+ // src/lib/render-geometry.ts
20377
+ function calculateRenderGeometry(screenMode, terminalWidth, terminalHeight, footerHeight) {
20378
+ const safeTerminalWidth = Math.max(terminalWidth, 0);
20379
+ const safeTerminalHeight = Math.max(terminalHeight, 0);
20380
+ if (screenMode !== "split-footer") {
20381
+ return {
20382
+ effectiveFooterHeight: 0,
20383
+ renderOffset: 0,
20384
+ renderWidth: safeTerminalWidth,
20385
+ renderHeight: safeTerminalHeight
20386
+ };
20387
+ }
20388
+ const effectiveFooterHeight = Math.min(footerHeight, safeTerminalHeight);
20389
+ return {
20390
+ effectiveFooterHeight,
20391
+ renderOffset: safeTerminalHeight - effectiveFooterHeight,
20392
+ renderWidth: safeTerminalWidth,
20393
+ renderHeight: effectiveFooterHeight
20394
+ };
20395
+ }
20396
+
18737
20397
  // src/lib/terminal-capability-detection.ts
18738
20398
  function isCapabilityResponse(sequence) {
18739
20399
  if (/\x1b\[\?\d+(?:;\d+)*\$y/.test(sequence)) {
@@ -18828,6 +20488,9 @@ registerEnvVar({
18828
20488
  default: false
18829
20489
  });
18830
20490
  var DEFAULT_FOOTER_HEIGHT = 12;
20491
+ var MAX_SCROLLBACK_SURFACE_HEIGHT_PASSES = 4;
20492
+ var TRANSPARENT_RGBA = RGBA.fromValues(0, 0, 0, 0);
20493
+ var scrollbackSurfaceCounter = 0;
18831
20494
  function normalizeFooterHeight(footerHeight) {
18832
20495
  if (footerHeight === undefined) {
18833
20496
  return DEFAULT_FOOTER_HEIGHT;
@@ -18854,11 +20517,106 @@ function resolveModes(config) {
18854
20517
  if (externalOutputMode === "capture-stdout" && screenMode !== "split-footer") {
18855
20518
  throw new Error('externalOutputMode "capture-stdout" requires screenMode "split-footer"');
18856
20519
  }
18857
- return {
18858
- screenMode,
18859
- footerHeight,
18860
- externalOutputMode
18861
- };
20520
+ return {
20521
+ screenMode,
20522
+ footerHeight,
20523
+ externalOutputMode
20524
+ };
20525
+ }
20526
+
20527
+ class ExternalOutputQueue {
20528
+ commits = [];
20529
+ get size() {
20530
+ return this.commits.length;
20531
+ }
20532
+ writeSnapshot(commit) {
20533
+ this.commits.push(commit);
20534
+ }
20535
+ claim(limit = Number.POSITIVE_INFINITY) {
20536
+ if (this.commits.length === 0) {
20537
+ return [];
20538
+ }
20539
+ const clampedLimit = Number.isFinite(limit) ? Math.max(1, Math.trunc(limit)) : this.commits.length;
20540
+ if (clampedLimit >= this.commits.length) {
20541
+ const output2 = this.commits;
20542
+ this.commits = [];
20543
+ return output2;
20544
+ }
20545
+ const output = this.commits.slice(0, clampedLimit);
20546
+ this.commits = this.commits.slice(clampedLimit);
20547
+ return output;
20548
+ }
20549
+ clear() {
20550
+ for (const commit of this.commits) {
20551
+ commit.snapshot.destroy();
20552
+ }
20553
+ this.commits = [];
20554
+ }
20555
+ }
20556
+ var CHAR_FLAG_CONTINUATION = 3221225472 >>> 0;
20557
+ var CHAR_FLAG_MASK = 3221225472 >>> 0;
20558
+
20559
+ class ScrollbackSnapshotRenderContext extends EventEmitter9 {
20560
+ width;
20561
+ height;
20562
+ frameId = 0;
20563
+ widthMethod;
20564
+ capabilities = null;
20565
+ hasSelection = false;
20566
+ currentFocusedRenderable = null;
20567
+ keyInput;
20568
+ _internalKeyInput;
20569
+ lifecyclePasses = new Set;
20570
+ constructor(width, height, widthMethod) {
20571
+ super();
20572
+ this.width = width;
20573
+ this.height = height;
20574
+ this.widthMethod = widthMethod;
20575
+ this.keyInput = new KeyHandler;
20576
+ this._internalKeyInput = new InternalKeyHandler;
20577
+ }
20578
+ addToHitGrid(_x, _y, _width, _height, _id) {}
20579
+ pushHitGridScissorRect(_x, _y, _width, _height) {}
20580
+ popHitGridScissorRect() {}
20581
+ clearHitGridScissorRects() {}
20582
+ requestRender() {}
20583
+ setCursorPosition(_x, _y, _visible) {}
20584
+ setCursorStyle(_options) {}
20585
+ setCursorColor(_color) {}
20586
+ setMousePointer(_shape) {}
20587
+ requestLive() {}
20588
+ dropLive() {}
20589
+ getSelection() {
20590
+ return null;
20591
+ }
20592
+ get currentFocusedEditor() {
20593
+ if (!this.currentFocusedRenderable)
20594
+ return null;
20595
+ if (!isEditBufferRenderable(this.currentFocusedRenderable))
20596
+ return null;
20597
+ return this.currentFocusedRenderable;
20598
+ }
20599
+ requestSelectionUpdate() {}
20600
+ focusRenderable(renderable) {
20601
+ this.currentFocusedRenderable = renderable;
20602
+ }
20603
+ blurRenderable(renderable) {
20604
+ if (this.currentFocusedRenderable === renderable) {
20605
+ this.currentFocusedRenderable = null;
20606
+ }
20607
+ }
20608
+ registerLifecyclePass(renderable) {
20609
+ this.lifecyclePasses.add(renderable);
20610
+ }
20611
+ unregisterLifecyclePass(renderable) {
20612
+ this.lifecyclePasses.delete(renderable);
20613
+ }
20614
+ getLifecyclePasses() {
20615
+ return this.lifecyclePasses;
20616
+ }
20617
+ clearSelection() {}
20618
+ startSelection(_renderable, _x, _y) {}
20619
+ updateSelection(_currentRenderable, _x, _y, _options) {}
18862
20620
  }
18863
20621
  var DEFAULT_FORWARDED_ENV_KEYS = [
18864
20622
  "TMUX",
@@ -18980,9 +20738,9 @@ async function createCliRenderer(config = {}) {
18980
20738
  const { screenMode, footerHeight } = resolveModes(config);
18981
20739
  const width = stdout.columns || 80;
18982
20740
  const height = stdout.rows || 24;
18983
- const renderHeight = screenMode === "split-footer" ? footerHeight : height;
20741
+ const geometry = calculateRenderGeometry(screenMode, width, height, footerHeight);
18984
20742
  const ziglib = resolveRenderLib();
18985
- const rendererPtr = ziglib.createRenderer(width, renderHeight, {
20743
+ const rendererPtr = ziglib.createRenderer(geometry.renderWidth, geometry.renderHeight, {
18986
20744
  remote: config.remote ?? false,
18987
20745
  testing: config.testing ?? false
18988
20746
  });
@@ -19099,6 +20857,8 @@ class CliRenderer extends EventEmitter9 {
19099
20857
  animationRequest = new Map;
19100
20858
  resizeTimeoutId = null;
19101
20859
  capabilityTimeoutId = null;
20860
+ splitStartupSeedTimeoutId = null;
20861
+ pendingSplitStartupCursorSeed = false;
19102
20862
  resizeDebounceDelay = 100;
19103
20863
  enableMouseMovement = false;
19104
20864
  _useMouse = true;
@@ -19106,6 +20866,7 @@ class CliRenderer extends EventEmitter9 {
19106
20866
  _screenMode = "alternate-screen";
19107
20867
  _footerHeight = DEFAULT_FOOTER_HEIGHT;
19108
20868
  _externalOutputMode = "passthrough";
20869
+ clearOnShutdown = true;
19109
20870
  _suspendedMouseEnabled = false;
19110
20871
  _previousControlState = "idle" /* IDLE */;
19111
20872
  capturedRenderable;
@@ -19116,15 +20877,15 @@ class CliRenderer extends EventEmitter9 {
19116
20877
  clipboard;
19117
20878
  _splitHeight = 0;
19118
20879
  renderOffset = 0;
20880
+ splitTailColumn = 0;
20881
+ pendingSplitFooterTransition = null;
20882
+ forceFullRepaintRequested = false;
20883
+ maxSplitCommitsPerFrame = 8;
19119
20884
  _terminalWidth = 0;
19120
20885
  _terminalHeight = 0;
19121
20886
  _terminalIsSetup = false;
20887
+ externalOutputQueue = new ExternalOutputQueue;
19122
20888
  realStdoutWrite;
19123
- captureCallback = () => {
19124
- if (this._splitHeight > 0) {
19125
- this.requestRender();
19126
- }
19127
- };
19128
20889
  _useConsole = true;
19129
20890
  sigwinchHandler = (() => {
19130
20891
  const width = this.stdout.columns || 80;
@@ -19167,8 +20928,15 @@ class CliRenderer extends EventEmitter9 {
19167
20928
  }).bind(this);
19168
20929
  dumpOutputCache(optionalMessage = "") {
19169
20930
  const cachedLogs = this.console.getCachedLogs();
19170
- const capturedOutput = capture.claimOutput();
19171
- if (capturedOutput.length > 0 || cachedLogs.length > 0) {
20931
+ const capturedConsoleOutput = capture.claimOutput();
20932
+ const capturedExternalOutputCommits = this.externalOutputQueue.claim();
20933
+ let capturedExternalOutput = "";
20934
+ for (const commit of capturedExternalOutputCommits) {
20935
+ capturedExternalOutput += `[snapshot ${commit.snapshot.width}x${commit.snapshot.height}]
20936
+ `;
20937
+ commit.snapshot.destroy();
20938
+ }
20939
+ if (capturedConsoleOutput.length > 0 || capturedExternalOutput.length > 0 || cachedLogs.length > 0) {
19172
20940
  this.realStdoutWrite.call(this.stdout, optionalMessage);
19173
20941
  }
19174
20942
  if (cachedLogs.length > 0) {
@@ -19176,11 +20944,18 @@ class CliRenderer extends EventEmitter9 {
19176
20944
  `);
19177
20945
  this.realStdoutWrite.call(this.stdout, cachedLogs);
19178
20946
  }
19179
- if (capturedOutput.length > 0) {
20947
+ if (capturedConsoleOutput.length > 0) {
20948
+ this.realStdoutWrite.call(this.stdout, `
20949
+ Captured console output:
20950
+ `);
20951
+ this.realStdoutWrite.call(this.stdout, capturedConsoleOutput + `
20952
+ `);
20953
+ }
20954
+ if (capturedExternalOutput.length > 0) {
19180
20955
  this.realStdoutWrite.call(this.stdout, `
19181
- Captured output:
20956
+ Captured external output:
19182
20957
  `);
19183
- this.realStdoutWrite.call(this.stdout, capturedOutput + `
20958
+ this.realStdoutWrite.call(this.stdout, capturedExternalOutput + `
19184
20959
  `);
19185
20960
  }
19186
20961
  this.realStdoutWrite.call(this.stdout, ANSI.reset);
@@ -19209,13 +20984,18 @@ Captured output:
19209
20984
  this.lib = lib;
19210
20985
  this._terminalWidth = stdout.columns ?? width;
19211
20986
  this._terminalHeight = stdout.rows ?? height;
19212
- this.width = width;
19213
- this.height = height;
19214
20987
  this._useThread = config.useThread === undefined ? false : config.useThread;
19215
20988
  const { screenMode, footerHeight, externalOutputMode } = resolveModes(config);
20989
+ this._externalOutputMode = externalOutputMode;
20990
+ const initialGeometry = calculateRenderGeometry(screenMode, this._terminalWidth, this._terminalHeight, footerHeight);
20991
+ this.width = initialGeometry.renderWidth;
20992
+ this.height = initialGeometry.renderHeight;
20993
+ this._splitHeight = initialGeometry.effectiveFooterHeight;
20994
+ this.renderOffset = screenMode === "split-footer" ? 0 : initialGeometry.renderOffset;
19216
20995
  this._footerHeight = footerHeight;
19217
- this._screenMode = screenMode;
19218
20996
  this.rendererPtr = rendererPtr;
20997
+ this.clearOnShutdown = config.clearOnShutdown ?? true;
20998
+ this.lib.setClearOnShutdown(this.rendererPtr, this.clearOnShutdown);
19219
20999
  const forwardEnvKeys = config.forwardEnvKeys ?? [...DEFAULT_FORWARDED_ENV_KEYS];
19220
21000
  for (const key of forwardEnvKeys) {
19221
21001
  const value = process.env[key];
@@ -19283,7 +21063,8 @@ Captured output:
19283
21063
  kittyKeyboardEnabled: useKittyForParsing,
19284
21064
  privateCapabilityRepliesActive: false,
19285
21065
  pixelResolutionQueryActive: false,
19286
- explicitWidthCprActive: false
21066
+ explicitWidthCprActive: false,
21067
+ startupCursorCprActive: false
19287
21068
  },
19288
21069
  clock: this.clock
19289
21070
  });
@@ -19293,7 +21074,7 @@ Captured output:
19293
21074
  });
19294
21075
  this.consoleMode = config.consoleMode ?? "console-overlay";
19295
21076
  this.applyScreenMode(screenMode, false, false);
19296
- this.externalOutputMode = externalOutputMode;
21077
+ this.stdout.write = externalOutputMode === "capture-stdout" ? this.interceptStdoutWrite : this.realStdoutWrite;
19297
21078
  this._openConsoleOnError = config.openConsoleOnError ?? true;
19298
21079
  this._onDestroy = config.onDestroy;
19299
21080
  global.requestAnimationFrame = (callback) => {
@@ -19569,8 +21350,25 @@ Captured output:
19569
21350
  if (mode === "capture-stdout" && this.screenMode !== "split-footer") {
19570
21351
  throw new Error('externalOutputMode "capture-stdout" requires screenMode "split-footer"');
19571
21352
  }
21353
+ const previousMode = this._externalOutputMode;
21354
+ if (previousMode === mode) {
21355
+ return;
21356
+ }
21357
+ if (previousMode === "capture-stdout" && mode === "passthrough" && this._splitHeight > 0) {
21358
+ this.flushPendingSplitOutputBeforeTransition();
21359
+ }
19572
21360
  this._externalOutputMode = mode;
19573
21361
  this.stdout.write = mode === "capture-stdout" ? this.interceptStdoutWrite : this.realStdoutWrite;
21362
+ if (this._screenMode === "split-footer" && this._splitHeight > 0 && mode === "capture-stdout") {
21363
+ this.clearPendingSplitFooterTransition();
21364
+ this.resetSplitScrollback(this.getSplitCursorSeedRows());
21365
+ return;
21366
+ }
21367
+ if (this._screenMode === "split-footer" && this._splitHeight > 0 && previousMode === "capture-stdout" && mode === "passthrough") {
21368
+ this.clearPendingSplitFooterTransition();
21369
+ return;
21370
+ }
21371
+ this.syncSplitFooterState();
19574
21372
  }
19575
21373
  get liveRequestCount() {
19576
21374
  return this.liveRequestCounter;
@@ -19626,21 +21424,604 @@ Captured output:
19626
21424
  const flags = use ? KITTY_FLAG_DISAMBIGUATE | KITTY_FLAG_ALTERNATE_KEYS : 0;
19627
21425
  this.lib.setKittyKeyboardFlags(this.rendererPtr, flags);
19628
21426
  }
19629
- interceptStdoutWrite = (chunk, encoding, callback) => {
19630
- const text = chunk.toString();
19631
- capture.write("stdout", text);
19632
- if (this._splitHeight > 0) {
21427
+ createScrollbackSurface(options = {}) {
21428
+ if (this._screenMode !== "split-footer" || this._externalOutputMode !== "capture-stdout") {
21429
+ throw new Error('createScrollbackSurface requires screenMode "split-footer" and externalOutputMode "capture-stdout"');
21430
+ }
21431
+ const renderer = this;
21432
+ const surfaceId = scrollbackSurfaceCounter++;
21433
+ const startOnNewLine = options.startOnNewLine ?? true;
21434
+ const firstLineOffset = !startOnNewLine && renderer.splitTailColumn > 0 && renderer.splitTailColumn < renderer.width ? renderer.splitTailColumn : 0;
21435
+ const snapshotContext = new ScrollbackSnapshotRenderContext(renderer.width, 1, renderer.widthMethod);
21436
+ let firstLineOffsetOwner = null;
21437
+ const renderContext = Object.create(snapshotContext);
21438
+ Object.defineProperty(renderContext, "claimFirstLineOffset", {
21439
+ value: (renderable) => {
21440
+ if (firstLineOffsetOwner?.isDestroyed) {
21441
+ firstLineOffsetOwner = null;
21442
+ }
21443
+ if (firstLineOffsetOwner) {
21444
+ return 0;
21445
+ }
21446
+ firstLineOffsetOwner = renderable ?? null;
21447
+ return firstLineOffset;
21448
+ },
21449
+ enumerable: true,
21450
+ configurable: true
21451
+ });
21452
+ const internalRoot = new RootRenderable(renderContext);
21453
+ const publicRoot = new BoxRenderable(renderContext, {
21454
+ id: `scrollback-surface-root-${surfaceId}`,
21455
+ position: "absolute",
21456
+ left: 0,
21457
+ top: 0,
21458
+ width: renderer.width,
21459
+ height: "auto",
21460
+ border: false,
21461
+ backgroundColor: "transparent",
21462
+ shouldFill: false,
21463
+ flexDirection: "column"
21464
+ });
21465
+ internalRoot.add(publicRoot);
21466
+ let surfaceWidth = renderer.width;
21467
+ let surfaceHeight = 1;
21468
+ let surfaceWidthMethod = renderer.widthMethod;
21469
+ let surfaceDestroyed = false;
21470
+ let hasRendered = false;
21471
+ let nextCommitStartOnNewLine = startOnNewLine;
21472
+ let backingBuffer = OptimizedBuffer.create(surfaceWidth, surfaceHeight, surfaceWidthMethod, {
21473
+ id: `scrollback-surface-buffer-${surfaceId}`
21474
+ });
21475
+ const destroyListener = () => {
21476
+ destroySurface();
21477
+ };
21478
+ const assertNotDestroyed = () => {
21479
+ if (surfaceDestroyed) {
21480
+ throw new Error("ScrollbackSurface is destroyed");
21481
+ }
21482
+ };
21483
+ const assertRendered = () => {
21484
+ if (!hasRendered) {
21485
+ throw new Error("ScrollbackSurface.commitRows requires render() before commitRows()");
21486
+ }
21487
+ };
21488
+ const assertGeometryStillCurrent = () => {
21489
+ if (renderer.width !== surfaceWidth || renderer.widthMethod !== surfaceWidthMethod) {
21490
+ throw new Error("ScrollbackSurface.commitRows requires render() after renderer geometry changes");
21491
+ }
21492
+ };
21493
+ const assertRowRange = (startRow, endRowExclusive) => {
21494
+ if (!Number.isInteger(startRow) || !Number.isInteger(endRowExclusive)) {
21495
+ throw new Error("ScrollbackSurface.commitRows requires finite integer row bounds");
21496
+ }
21497
+ if (startRow < 0) {
21498
+ throw new Error("ScrollbackSurface.commitRows requires startRow >= 0");
21499
+ }
21500
+ if (endRowExclusive < startRow) {
21501
+ throw new Error("ScrollbackSurface.commitRows requires endRowExclusive >= startRow");
21502
+ }
21503
+ if (endRowExclusive > surfaceHeight) {
21504
+ throw new Error("ScrollbackSurface.commitRows row range exceeds rendered surface height");
21505
+ }
21506
+ };
21507
+ const collectPendingCodeRenderables = (node) => {
21508
+ const pending = [];
21509
+ if (node instanceof CodeRenderable && node.isHighlighting) {
21510
+ pending.push(node);
21511
+ }
21512
+ for (const child of node.getChildren()) {
21513
+ pending.push(...collectPendingCodeRenderables(child));
21514
+ }
21515
+ return pending;
21516
+ };
21517
+ const waitForPendingHighlights = async (pending, timeoutMs) => {
21518
+ await new Promise((resolve4, reject) => {
21519
+ let settled = false;
21520
+ const timeoutHandle = renderer.clock.setTimeout(() => {
21521
+ if (settled) {
21522
+ return;
21523
+ }
21524
+ settled = true;
21525
+ reject(new Error("ScrollbackSurface.settle timed out waiting for CodeRenderable highlighting"));
21526
+ }, timeoutMs);
21527
+ Promise.all(pending.map((renderable) => renderable.highlightingDone)).then(() => {
21528
+ if (settled) {
21529
+ return;
21530
+ }
21531
+ settled = true;
21532
+ renderer.clock.clearTimeout(timeoutHandle);
21533
+ resolve4();
21534
+ }, (error) => {
21535
+ if (settled) {
21536
+ return;
21537
+ }
21538
+ settled = true;
21539
+ renderer.clock.clearTimeout(timeoutHandle);
21540
+ reject(error);
21541
+ });
21542
+ });
21543
+ };
21544
+ const renderSurface = () => {
21545
+ assertNotDestroyed();
21546
+ const width = renderer.width;
21547
+ const widthMethod = renderer.widthMethod;
21548
+ snapshotContext.width = width;
21549
+ snapshotContext.widthMethod = widthMethod;
21550
+ publicRoot.width = width;
21551
+ const renderPass = (height) => {
21552
+ snapshotContext.height = height;
21553
+ internalRoot.resize(width, height);
21554
+ backingBuffer.resize(width, height);
21555
+ backingBuffer.clear(TRANSPARENT_RGBA);
21556
+ snapshotContext.frameId += 1;
21557
+ internalRoot.render(backingBuffer, 0);
21558
+ };
21559
+ let targetHeight = Math.max(1, surfaceHeight);
21560
+ if (surfaceWidthMethod !== widthMethod) {
21561
+ backingBuffer.destroy();
21562
+ backingBuffer = OptimizedBuffer.create(width, targetHeight, widthMethod, {
21563
+ id: `scrollback-surface-buffer-${surfaceId}`
21564
+ });
21565
+ } else {
21566
+ backingBuffer.resize(width, targetHeight);
21567
+ }
21568
+ for (let pass = 0;pass < MAX_SCROLLBACK_SURFACE_HEIGHT_PASSES; pass += 1) {
21569
+ renderPass(targetHeight);
21570
+ const measuredHeight = Math.max(1, publicRoot.height);
21571
+ if (measuredHeight === targetHeight) {
21572
+ surfaceWidth = width;
21573
+ surfaceHeight = measuredHeight;
21574
+ surfaceWidthMethod = widthMethod;
21575
+ hasRendered = true;
21576
+ return;
21577
+ }
21578
+ targetHeight = measuredHeight;
21579
+ }
21580
+ renderPass(targetHeight);
21581
+ surfaceWidth = width;
21582
+ surfaceHeight = targetHeight;
21583
+ surfaceWidthMethod = widthMethod;
21584
+ hasRendered = true;
21585
+ };
21586
+ const settleSurface = async (timeoutMs = 2000) => {
21587
+ assertNotDestroyed();
21588
+ const startedAt = renderer.clock.now();
21589
+ renderSurface();
21590
+ while (true) {
21591
+ assertNotDestroyed();
21592
+ const pending = collectPendingCodeRenderables(publicRoot);
21593
+ if (pending.length === 0) {
21594
+ return;
21595
+ }
21596
+ const remainingMs = timeoutMs - (renderer.clock.now() - startedAt);
21597
+ if (remainingMs <= 0) {
21598
+ throw new Error("ScrollbackSurface.settle timed out waiting for CodeRenderable highlighting");
21599
+ }
21600
+ await waitForPendingHighlights(pending, remainingMs);
21601
+ assertNotDestroyed();
21602
+ renderSurface();
21603
+ }
21604
+ };
21605
+ const commitRows = (startRow, endRowExclusive, commitOptions = {}) => {
21606
+ assertNotDestroyed();
21607
+ assertRendered();
21608
+ assertGeometryStillCurrent();
21609
+ assertRowRange(startRow, endRowExclusive);
21610
+ if (startRow === endRowExclusive) {
21611
+ return;
21612
+ }
21613
+ const rowCount = endRowExclusive - startRow;
21614
+ const commitBuffer = OptimizedBuffer.create(surfaceWidth, rowCount, surfaceWidthMethod, {
21615
+ id: `scrollback-surface-commit-${surfaceId}`
21616
+ });
21617
+ try {
21618
+ commitBuffer.drawFrameBuffer(0, 0, backingBuffer, 0, startRow, surfaceWidth, rowCount);
21619
+ renderer.enqueueRenderedScrollbackCommit({
21620
+ snapshot: commitBuffer,
21621
+ rowColumns: commitOptions.rowColumns,
21622
+ startOnNewLine: nextCommitStartOnNewLine,
21623
+ trailingNewline: commitOptions.trailingNewline ?? false
21624
+ });
21625
+ nextCommitStartOnNewLine = false;
21626
+ } catch (error) {
21627
+ commitBuffer.destroy();
21628
+ throw error;
21629
+ }
21630
+ };
21631
+ const destroySurface = () => {
21632
+ if (surfaceDestroyed) {
21633
+ return;
21634
+ }
21635
+ surfaceDestroyed = true;
21636
+ renderer.off("destroy" /* DESTROY */, destroyListener);
21637
+ let destroyError = null;
21638
+ try {
21639
+ internalRoot.destroyRecursively();
21640
+ } catch (error) {
21641
+ destroyError = error;
21642
+ }
21643
+ try {
21644
+ backingBuffer.destroy();
21645
+ } catch (error) {
21646
+ if (destroyError === null) {
21647
+ destroyError = error;
21648
+ }
21649
+ }
21650
+ renderContext.removeAllListeners();
21651
+ snapshotContext.removeAllListeners();
21652
+ if (destroyError !== null) {
21653
+ throw destroyError;
21654
+ }
21655
+ };
21656
+ renderer.on("destroy" /* DESTROY */, destroyListener);
21657
+ return {
21658
+ get renderContext() {
21659
+ return renderContext;
21660
+ },
21661
+ get root() {
21662
+ return publicRoot;
21663
+ },
21664
+ get width() {
21665
+ return surfaceWidth;
21666
+ },
21667
+ get height() {
21668
+ return surfaceHeight;
21669
+ },
21670
+ get isDestroyed() {
21671
+ return surfaceDestroyed;
21672
+ },
21673
+ render: renderSurface,
21674
+ settle: settleSurface,
21675
+ commitRows,
21676
+ destroy: destroySurface
21677
+ };
21678
+ }
21679
+ writeToScrollback(write) {
21680
+ if (this._screenMode !== "split-footer" || this._externalOutputMode !== "capture-stdout") {
21681
+ throw new Error('writeToScrollback requires screenMode "split-footer" and externalOutputMode "capture-stdout"');
21682
+ }
21683
+ const snapshotContext = new ScrollbackSnapshotRenderContext(this.width, this.height, this.widthMethod);
21684
+ const snapshot = write({
21685
+ width: this.width,
21686
+ widthMethod: this.widthMethod,
21687
+ tailColumn: this.splitTailColumn,
21688
+ renderContext: snapshotContext
21689
+ });
21690
+ if (!snapshot || !snapshot.root) {
21691
+ throw new Error("writeToScrollback must return a snapshot root renderable");
21692
+ }
21693
+ let renderFailed = false;
21694
+ let snapshotRoot = null;
21695
+ let snapshotBuffer = null;
21696
+ try {
21697
+ const rootRenderable = snapshot.root;
21698
+ const snapshotWidth = this.getSnapshotWidth(snapshot.width, rootRenderable.width);
21699
+ const snapshotHeight = this.getSnapshotHeight(snapshot.height, rootRenderable.height);
21700
+ snapshotContext.width = snapshotWidth;
21701
+ snapshotContext.height = snapshotHeight;
21702
+ snapshotContext.widthMethod = this.widthMethod;
21703
+ snapshotRoot = new RootRenderable(snapshotContext);
21704
+ snapshotBuffer = OptimizedBuffer.create(snapshotWidth, snapshotHeight, this.widthMethod, {
21705
+ id: "scrollback-snapshot-commit"
21706
+ });
21707
+ snapshotRoot.add(rootRenderable);
21708
+ snapshotRoot.render(snapshotBuffer, 0);
21709
+ this.enqueueRenderedScrollbackCommit({
21710
+ snapshot: snapshotBuffer,
21711
+ rowColumns: snapshot.rowColumns,
21712
+ startOnNewLine: snapshot.startOnNewLine,
21713
+ trailingNewline: snapshot.trailingNewline
21714
+ });
21715
+ } catch (error) {
21716
+ renderFailed = true;
21717
+ snapshotBuffer?.destroy();
21718
+ throw error;
21719
+ } finally {
21720
+ let cleanupError = null;
21721
+ try {
21722
+ if (snapshotRoot) {
21723
+ snapshotRoot.destroyRecursively();
21724
+ } else {
21725
+ snapshot.root.destroyRecursively();
21726
+ }
21727
+ } catch (error) {
21728
+ cleanupError = error;
21729
+ }
21730
+ try {
21731
+ snapshot.teardown?.();
21732
+ } catch (error) {
21733
+ if (cleanupError === null) {
21734
+ cleanupError = error;
21735
+ }
21736
+ }
21737
+ if (!renderFailed && cleanupError) {
21738
+ throw cleanupError;
21739
+ }
21740
+ }
21741
+ }
21742
+ getSnapshotWidth(value, fallback) {
21743
+ const rawValue = value ?? fallback;
21744
+ if (!Number.isFinite(rawValue)) {
21745
+ throw new Error("writeToScrollback produced a non-finite width");
21746
+ }
21747
+ return Math.min(Math.max(Math.trunc(rawValue), 1), Math.max(this.width, 1));
21748
+ }
21749
+ getSnapshotHeight(value, fallback) {
21750
+ const rawValue = value ?? fallback;
21751
+ if (!Number.isFinite(rawValue)) {
21752
+ throw new Error("writeToScrollback produced a non-finite height");
21753
+ }
21754
+ return Math.max(Math.trunc(rawValue), 1);
21755
+ }
21756
+ getSnapshotRowWidths(snapshot, rowColumns) {
21757
+ const widths = [];
21758
+ const limit = Math.min(Math.max(Math.trunc(rowColumns), 0), snapshot.width);
21759
+ const chars = snapshot.buffers.char;
21760
+ for (let y = 0;y < snapshot.height; y += 1) {
21761
+ let x = limit;
21762
+ while (x > 0) {
21763
+ const cp = chars[y * snapshot.width + x - 1];
21764
+ if (cp === 0 || (cp & CHAR_FLAG_MASK) === CHAR_FLAG_CONTINUATION) {
21765
+ x -= 1;
21766
+ continue;
21767
+ }
21768
+ break;
21769
+ }
21770
+ widths.push(x);
21771
+ }
21772
+ return widths;
21773
+ }
21774
+ publishSplitTailColumns(columns) {
21775
+ if (columns <= 0) {
21776
+ return;
21777
+ }
21778
+ const width = Math.max(this.width, 1);
21779
+ let tail = this.splitTailColumn;
21780
+ let remaining = columns;
21781
+ while (remaining > 0) {
21782
+ if (tail >= width) {
21783
+ tail = 0;
21784
+ }
21785
+ const step = Math.min(remaining, width - tail);
21786
+ tail += step;
21787
+ remaining -= step;
21788
+ if (remaining > 0 && tail >= width) {
21789
+ tail = 0;
21790
+ }
21791
+ }
21792
+ this.splitTailColumn = tail;
21793
+ }
21794
+ recordSplitCommit(commit) {
21795
+ if (commit.startOnNewLine && this.splitTailColumn > 0) {
21796
+ this.splitTailColumn = 0;
21797
+ }
21798
+ const rowWidths = this.getSnapshotRowWidths(commit.snapshot, commit.rowColumns);
21799
+ for (const [index, rowWidth] of rowWidths.entries()) {
21800
+ this.publishSplitTailColumns(rowWidth);
21801
+ if (index < rowWidths.length - 1 || commit.trailingNewline) {
21802
+ this.splitTailColumn = 0;
21803
+ }
21804
+ }
21805
+ }
21806
+ enqueueRenderedScrollbackCommit(options) {
21807
+ if (this._screenMode !== "split-footer" || this._externalOutputMode !== "capture-stdout") {
21808
+ throw new Error('scrollback commit requires screenMode "split-footer" and externalOutputMode "capture-stdout"');
21809
+ }
21810
+ const rowColumns = Math.min(Math.max(Math.trunc(options.rowColumns ?? options.snapshot.width), 0), options.snapshot.width);
21811
+ this.enqueueSplitCommit({
21812
+ snapshot: options.snapshot,
21813
+ rowColumns,
21814
+ startOnNewLine: options.startOnNewLine ?? true,
21815
+ trailingNewline: options.trailingNewline ?? true
21816
+ });
21817
+ this.requestRender();
21818
+ }
21819
+ enqueueSplitCommit(commit) {
21820
+ this.recordSplitCommit(commit);
21821
+ this.externalOutputQueue.writeSnapshot(commit);
21822
+ }
21823
+ createStdoutSnapshotCommit(line, trailingNewline) {
21824
+ const snapshotContext = new ScrollbackSnapshotRenderContext(this.width, 1, this.widthMethod);
21825
+ const maxWidth = Math.max(1, this.width);
21826
+ const lineCells = [...line];
21827
+ const rowColumns = Math.min(lineCells.length, maxWidth);
21828
+ const renderedLine = lineCells.slice(0, maxWidth).join("");
21829
+ const snapshotRoot = new RootRenderable(snapshotContext);
21830
+ const snapshotRenderable = new TextRenderable(snapshotContext, {
21831
+ id: "captured-stdout-snapshot",
21832
+ position: "absolute",
21833
+ left: 0,
21834
+ top: 0,
21835
+ width: Math.max(1, rowColumns),
21836
+ height: 1,
21837
+ content: renderedLine
21838
+ });
21839
+ const snapshotBuffer = OptimizedBuffer.create(Math.max(1, rowColumns), 1, this.widthMethod, {
21840
+ id: "captured-stdout-snapshot"
21841
+ });
21842
+ try {
21843
+ snapshotRoot.add(snapshotRenderable);
21844
+ snapshotRoot.render(snapshotBuffer, 0);
21845
+ return {
21846
+ snapshot: snapshotBuffer,
21847
+ rowColumns,
21848
+ startOnNewLine: false,
21849
+ trailingNewline
21850
+ };
21851
+ } catch (error) {
21852
+ snapshotBuffer.destroy();
21853
+ throw error;
21854
+ } finally {
21855
+ snapshotRoot.destroyRecursively();
21856
+ }
21857
+ }
21858
+ splitStdoutRows(text) {
21859
+ const rows = [];
21860
+ let current = "";
21861
+ for (const char of text) {
21862
+ if (char === "\r") {
21863
+ current = "";
21864
+ continue;
21865
+ }
21866
+ if (char === `
21867
+ `) {
21868
+ rows.push({ line: current, trailingNewline: true });
21869
+ current = "";
21870
+ continue;
21871
+ }
21872
+ current += char;
21873
+ }
21874
+ if (current.length > 0) {
21875
+ rows.push({ line: current, trailingNewline: false });
21876
+ }
21877
+ return rows;
21878
+ }
21879
+ createStdoutSnapshotCommits(text) {
21880
+ if (text.length === 0) {
21881
+ return [];
21882
+ }
21883
+ const commits = [];
21884
+ const chunkWidth = Math.max(1, this.width);
21885
+ for (const row of this.splitStdoutRows(text)) {
21886
+ const rowCells = [...row.line];
21887
+ if (rowCells.length === 0) {
21888
+ commits.push(this.createStdoutSnapshotCommit("", row.trailingNewline));
21889
+ continue;
21890
+ }
21891
+ let offset = 0;
21892
+ while (offset < rowCells.length) {
21893
+ const chunk = rowCells.slice(offset, offset + chunkWidth).join("");
21894
+ offset += chunkWidth;
21895
+ const isLastChunk = offset >= rowCells.length;
21896
+ commits.push(this.createStdoutSnapshotCommit(chunk, isLastChunk ? row.trailingNewline : false));
21897
+ }
21898
+ }
21899
+ return commits;
21900
+ }
21901
+ flushPendingSplitCommits(forceFooterRepaint = false) {
21902
+ const commits = this.externalOutputQueue.claim(this.maxSplitCommitsPerFrame);
21903
+ let hasCommittedOutput = false;
21904
+ const lastCommitIndex = commits.length - 1;
21905
+ for (const [index, commit] of commits.entries()) {
21906
+ const forceCommit = forceFooterRepaint && index === lastCommitIndex;
21907
+ const beginFrame = index === 0;
21908
+ const finalizeFrame = index === lastCommitIndex;
21909
+ try {
21910
+ this.renderOffset = this.lib.commitSplitFooterSnapshot(this.rendererPtr, commit.snapshot, commit.rowColumns, commit.startOnNewLine, commit.trailingNewline, this.getSplitPinnedRenderOffset(), forceCommit, beginFrame, finalizeFrame);
21911
+ hasCommittedOutput = true;
21912
+ } finally {
21913
+ commit.snapshot.destroy();
21914
+ }
21915
+ }
21916
+ if (!hasCommittedOutput) {
21917
+ this.renderOffset = this.lib.repaintSplitFooter(this.rendererPtr, this.getSplitPinnedRenderOffset(), forceFooterRepaint);
21918
+ }
21919
+ this.pendingSplitFooterTransition = null;
21920
+ if (this.externalOutputQueue.size > 0) {
19633
21921
  this.requestRender();
19634
21922
  }
19635
- if (typeof callback === "function") {
19636
- process.nextTick(callback);
21923
+ }
21924
+ interceptStdoutWrite = (chunk, encoding, callback) => {
21925
+ const resolvedCallback = typeof encoding === "function" ? encoding : callback;
21926
+ const resolvedEncoding = typeof encoding === "string" ? encoding : undefined;
21927
+ const text = typeof chunk === "string" ? chunk : chunk?.toString(resolvedEncoding) ?? "";
21928
+ if (this._externalOutputMode === "capture-stdout" && this._screenMode === "split-footer" && this._splitHeight > 0) {
21929
+ const commits = this.createStdoutSnapshotCommits(text);
21930
+ for (const commit of commits) {
21931
+ this.enqueueSplitCommit(commit);
21932
+ }
21933
+ if (commits.length > 0) {
21934
+ this.requestRender();
21935
+ }
21936
+ }
21937
+ if (typeof resolvedCallback === "function") {
21938
+ process.nextTick(resolvedCallback);
19637
21939
  }
19638
21940
  return true;
19639
21941
  };
21942
+ getSplitPinnedRenderOffset() {
21943
+ return this._screenMode === "split-footer" ? Math.max(this._terminalHeight - this._splitHeight, 0) : 0;
21944
+ }
21945
+ getSplitCursorSeedRows() {
21946
+ const cursorState = this.lib.getCursorState(this.rendererPtr);
21947
+ const cursorRow = Number.isFinite(cursorState.y) ? Math.max(Math.trunc(cursorState.y), 1) : 1;
21948
+ return Math.min(cursorRow, Math.max(this._terminalHeight, 1));
21949
+ }
21950
+ flushPendingSplitOutputBeforeTransition(forceFooterRepaint = false) {
21951
+ if (this._screenMode !== "split-footer" || this._splitHeight <= 0 || this._externalOutputMode !== "capture-stdout") {
21952
+ return;
21953
+ }
21954
+ if (this.externalOutputQueue.size === 0 && !forceFooterRepaint) {
21955
+ return;
21956
+ }
21957
+ this.flushPendingSplitCommits(forceFooterRepaint);
21958
+ }
21959
+ resetSplitScrollback(seedRows = 0) {
21960
+ this.splitTailColumn = 0;
21961
+ this.renderOffset = this.lib.resetSplitScrollback(this.rendererPtr, seedRows, this.getSplitPinnedRenderOffset());
21962
+ }
21963
+ syncSplitScrollback() {
21964
+ this.renderOffset = this.lib.syncSplitScrollback(this.rendererPtr, this.getSplitPinnedRenderOffset());
21965
+ }
21966
+ clearPendingSplitFooterTransition() {
21967
+ if (this.pendingSplitFooterTransition === null) {
21968
+ return;
21969
+ }
21970
+ this.pendingSplitFooterTransition = null;
21971
+ this.lib.clearPendingSplitFooterTransition(this.rendererPtr);
21972
+ }
21973
+ setPendingSplitFooterTransition(transition) {
21974
+ this.pendingSplitFooterTransition = transition;
21975
+ this.lib.setPendingSplitFooterTransition(this.rendererPtr, transition.mode === "viewport-scroll" ? 1 : 2, transition.sourceTopLine, transition.sourceHeight, transition.targetTopLine, transition.targetHeight);
21976
+ }
21977
+ syncSplitFooterState() {
21978
+ const splitActive = this._screenMode === "split-footer" && this._splitHeight > 0;
21979
+ if (!splitActive) {
21980
+ this.clearPendingSplitFooterTransition();
21981
+ this.splitTailColumn = 0;
21982
+ this.lib.resetSplitScrollback(this.rendererPtr, 0, 0);
21983
+ this.renderOffset = 0;
21984
+ this.lib.setRenderOffset(this.rendererPtr, this.renderOffset);
21985
+ return;
21986
+ }
21987
+ if (this._externalOutputMode === "capture-stdout") {
21988
+ this.syncSplitScrollback();
21989
+ } else {
21990
+ this.clearPendingSplitFooterTransition();
21991
+ this.splitTailColumn = 0;
21992
+ this.lib.resetSplitScrollback(this.rendererPtr, 0, 0);
21993
+ this.renderOffset = this.getSplitPinnedRenderOffset();
21994
+ this.lib.setRenderOffset(this.rendererPtr, this.renderOffset);
21995
+ }
21996
+ }
21997
+ clearStaleSplitSurfaceRows(previousTopLine, previousHeight, nextTopLine, nextHeight) {
21998
+ if (!this._terminalIsSetup || previousHeight <= 0 || this._terminalHeight <= 0) {
21999
+ return;
22000
+ }
22001
+ const terminalBottom = this._terminalHeight;
22002
+ const previousStart = Math.max(1, previousTopLine);
22003
+ const previousEnd = Math.min(terminalBottom, previousTopLine + previousHeight - 1);
22004
+ if (previousEnd < previousStart) {
22005
+ return;
22006
+ }
22007
+ const nextStart = Math.max(1, nextTopLine);
22008
+ const nextEnd = Math.min(terminalBottom, nextTopLine + Math.max(nextHeight, 0) - 1);
22009
+ let clear = "";
22010
+ for (let line = previousStart;line <= previousEnd; line += 1) {
22011
+ if (line >= nextStart && line <= nextEnd) {
22012
+ continue;
22013
+ }
22014
+ clear += `${ANSI.moveCursor(line, 1)}\x1B[2K`;
22015
+ }
22016
+ if (clear.length > 0) {
22017
+ this.writeOut(clear);
22018
+ }
22019
+ }
19640
22020
  applyScreenMode(screenMode, emitResize = true, requestRender = true) {
19641
22021
  const prevScreenMode = this._screenMode;
19642
22022
  const prevSplitHeight = this._splitHeight;
19643
- const nextSplitHeight = screenMode === "split-footer" ? this._footerHeight : 0;
22023
+ const nextGeometry = calculateRenderGeometry(screenMode, this._terminalWidth, this._terminalHeight, this._footerHeight);
22024
+ const nextSplitHeight = nextGeometry.effectiveFooterHeight;
19644
22025
  if (prevScreenMode === screenMode && prevSplitHeight === nextSplitHeight) {
19645
22026
  return;
19646
22027
  }
@@ -19648,10 +22029,24 @@ Captured output:
19648
22029
  const nextUseAlternateScreen = screenMode === "alternate-screen";
19649
22030
  const terminalScreenModeChanged = this._terminalIsSetup && prevUseAlternateScreen !== nextUseAlternateScreen;
19650
22031
  const leavingSplitFooter = prevSplitHeight > 0 && nextSplitHeight === 0;
22032
+ if (this._terminalIsSetup && prevSplitHeight > 0) {
22033
+ this.flushPendingSplitOutputBeforeTransition();
22034
+ }
22035
+ const previousSurfaceTopLine = this.renderOffset + 1;
22036
+ const previousPinnedRenderOffset = Math.max(this._terminalHeight - prevSplitHeight, 0);
22037
+ const splitWasSettled = prevSplitHeight === 0 || this.renderOffset >= previousPinnedRenderOffset;
22038
+ const shouldUseViewportScrollTransitions = this._externalOutputMode !== "capture-stdout" || splitWasSettled;
22039
+ const shouldDeferSplitFooterResizeTransition = this._terminalIsSetup && prevScreenMode === "split-footer" && screenMode === "split-footer" && this._externalOutputMode === "capture-stdout" && prevSplitHeight > 0 && nextSplitHeight > 0 && !terminalScreenModeChanged;
22040
+ const splitStartupSeedBlocksFirstNativeFrame = this.pendingSplitStartupCursorSeed && this.splitStartupSeedTimeoutId !== null;
22041
+ const splitTransitionSourceTopLine = this.pendingSplitFooterTransition?.sourceTopLine ?? previousSurfaceTopLine;
22042
+ const splitTransitionSourceHeight = this.pendingSplitFooterTransition?.sourceHeight ?? prevSplitHeight;
22043
+ const splitTransitionMode = this.pendingSplitFooterTransition?.mode ?? (splitWasSettled ? "viewport-scroll" : "clear-stale-rows");
19651
22044
  if (this._terminalIsSetup && leavingSplitFooter) {
19652
- this.flushStdoutCache(this._terminalHeight, true);
22045
+ this.clearPendingSplitFooterTransition();
22046
+ this.renderOffset = 0;
22047
+ this.lib.setRenderOffset(this.rendererPtr, 0);
19653
22048
  }
19654
- if (this._terminalIsSetup && !terminalScreenModeChanged) {
22049
+ if (this._terminalIsSetup && !terminalScreenModeChanged && shouldUseViewportScrollTransitions && !shouldDeferSplitFooterResizeTransition) {
19655
22050
  if (prevSplitHeight === 0 && nextSplitHeight > 0) {
19656
22051
  const freedLines = this._terminalHeight - nextSplitHeight;
19657
22052
  const scrollDown = ANSI.scrollDown(freedLines);
@@ -19666,18 +22061,39 @@ Captured output:
19666
22061
  this.writeOut(scrollUp);
19667
22062
  }
19668
22063
  }
19669
- if (prevSplitHeight === 0 && nextSplitHeight > 0) {
19670
- capture.on("write", this.captureCallback);
19671
- } else if (prevSplitHeight > 0 && nextSplitHeight === 0) {
19672
- capture.off("write", this.captureCallback);
19673
- }
19674
22064
  this._screenMode = screenMode;
19675
22065
  this._splitHeight = nextSplitHeight;
19676
- this.renderOffset = nextSplitHeight > 0 ? this._terminalHeight - nextSplitHeight : 0;
19677
- this.width = this._terminalWidth;
19678
- this.height = nextSplitHeight > 0 ? nextSplitHeight : this._terminalHeight;
19679
- this.lib.setRenderOffset(this.rendererPtr, this.renderOffset);
22066
+ this.width = nextGeometry.renderWidth;
22067
+ this.height = nextGeometry.renderHeight;
19680
22068
  this.lib.resizeRenderer(this.rendererPtr, this.width, this.height);
22069
+ if (this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
22070
+ if (prevScreenMode !== "split-footer") {
22071
+ this.resetSplitScrollback(this.getSplitCursorSeedRows());
22072
+ } else {
22073
+ this.syncSplitScrollback();
22074
+ }
22075
+ if (shouldDeferSplitFooterResizeTransition) {
22076
+ if (splitStartupSeedBlocksFirstNativeFrame) {
22077
+ this.clearPendingSplitFooterTransition();
22078
+ } else {
22079
+ this.setPendingSplitFooterTransition({
22080
+ mode: splitTransitionMode,
22081
+ sourceTopLine: splitTransitionSourceTopLine,
22082
+ sourceHeight: splitTransitionSourceHeight,
22083
+ targetTopLine: this.renderOffset + 1,
22084
+ targetHeight: nextSplitHeight
22085
+ });
22086
+ }
22087
+ this.forceFullRepaintRequested = true;
22088
+ } else if (!shouldUseViewportScrollTransitions && prevSplitHeight > 0 && nextSplitHeight > 0) {
22089
+ this.clearPendingSplitFooterTransition();
22090
+ this.clearStaleSplitSurfaceRows(previousSurfaceTopLine, prevSplitHeight, this.renderOffset + 1, nextSplitHeight);
22091
+ } else {
22092
+ this.clearPendingSplitFooterTransition();
22093
+ }
22094
+ } else {
22095
+ this.syncSplitFooterState();
22096
+ }
19681
22097
  this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
19682
22098
  this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
19683
22099
  this._console.resize(this.width, this.height);
@@ -19697,12 +22113,18 @@ Captured output:
19697
22113
  }
19698
22114
  }
19699
22115
  flushStdoutCache(space, force = false) {
19700
- if (capture.size === 0 && !force)
22116
+ if (this.externalOutputQueue.size === 0 && !force)
19701
22117
  return false;
19702
- const output = capture.claimOutput();
19703
- const rendererStartLine = this._terminalHeight - this._splitHeight;
22118
+ const outputCommits = this.externalOutputQueue.claim();
22119
+ let output = "";
22120
+ for (const commit of outputCommits) {
22121
+ output += `[snapshot ${commit.snapshot.width}x${commit.snapshot.height}]
22122
+ `;
22123
+ commit.snapshot.destroy();
22124
+ }
22125
+ const rendererStartLine = this.renderOffset + 1;
19704
22126
  const flush = ANSI.moveCursorAndClear(rendererStartLine, 1);
19705
- const outputLine = this._terminalHeight - this._splitHeight;
22127
+ const outputLine = this.renderOffset + 1;
19706
22128
  const move = ANSI.moveCursor(outputLine, 1);
19707
22129
  let clear = "";
19708
22130
  if (space > 0) {
@@ -19744,9 +22166,11 @@ Captured output:
19744
22166
  if (this._terminalIsSetup)
19745
22167
  return;
19746
22168
  this._terminalIsSetup = true;
22169
+ const startupCursorCprActive = this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout";
19747
22170
  this.updateStdinParserProtocolContext({
19748
22171
  privateCapabilityRepliesActive: true,
19749
- explicitWidthCprActive: true
22172
+ explicitWidthCprActive: true,
22173
+ startupCursorCprActive
19750
22174
  });
19751
22175
  this.lib.setupTerminal(this.rendererPtr, this._screenMode === "alternate-screen");
19752
22176
  this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
@@ -19760,15 +22184,40 @@ Captured output:
19760
22184
  }
19761
22185
  this.capabilityTimeoutId = this.clock.setTimeout(() => {
19762
22186
  this.capabilityTimeoutId = null;
22187
+ this.pendingSplitStartupCursorSeed = false;
22188
+ if (this.splitStartupSeedTimeoutId !== null) {
22189
+ this.clock.clearTimeout(this.splitStartupSeedTimeoutId);
22190
+ this.splitStartupSeedTimeoutId = null;
22191
+ }
22192
+ if (this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
22193
+ this.requestRender();
22194
+ }
19763
22195
  this.removeInputHandler(this.capabilityHandler);
19764
22196
  this.updateStdinParserProtocolContext({
19765
22197
  privateCapabilityRepliesActive: false,
19766
- explicitWidthCprActive: false
22198
+ explicitWidthCprActive: false,
22199
+ startupCursorCprActive: false
19767
22200
  }, true);
19768
22201
  }, 5000);
19769
22202
  if (this._useMouse) {
19770
22203
  this.enableMouse();
19771
22204
  }
22205
+ if (this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
22206
+ this.pendingSplitStartupCursorSeed = true;
22207
+ if (this.splitStartupSeedTimeoutId !== null) {
22208
+ this.clock.clearTimeout(this.splitStartupSeedTimeoutId);
22209
+ }
22210
+ this.splitStartupSeedTimeoutId = this.clock.setTimeout(() => {
22211
+ this.splitStartupSeedTimeoutId = null;
22212
+ if (!this.pendingSplitStartupCursorSeed) {
22213
+ return;
22214
+ }
22215
+ this.updateStdinParserProtocolContext({ startupCursorCprActive: false });
22216
+ if (this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
22217
+ this.requestRender();
22218
+ }
22219
+ }, 120);
22220
+ }
19772
22221
  this.queryPixelResolution();
19773
22222
  }
19774
22223
  stdinListener = ((chunk) => {
@@ -19804,14 +22253,32 @@ Captured output:
19804
22253
  this.oscSubscribers.delete(handler);
19805
22254
  };
19806
22255
  }
19807
- capabilityHandler = ((sequence) => {
19808
- if (isCapabilityResponse(sequence)) {
19809
- this.lib.processCapabilityResponse(this.rendererPtr, sequence);
19810
- this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
19811
- this.emit("capabilities" /* CAPABILITIES */, this._capabilities);
19812
- return true;
22256
+ processCapabilitySequence(sequence, hasCursorReport) {
22257
+ const hasStandardCapabilitySignature = isCapabilityResponse(sequence);
22258
+ const shouldProcessAsCapability = hasStandardCapabilitySignature || hasCursorReport && this.capabilityTimeoutId !== null;
22259
+ if (!shouldProcessAsCapability) {
22260
+ return false;
19813
22261
  }
19814
- return false;
22262
+ this.lib.processCapabilityResponse(this.rendererPtr, sequence);
22263
+ this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
22264
+ this.emit("capabilities" /* CAPABILITIES */, this._capabilities);
22265
+ const hadPendingSplitStartupCursorSeed = this.pendingSplitStartupCursorSeed;
22266
+ if (hadPendingSplitStartupCursorSeed && hasCursorReport && this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
22267
+ this.resetSplitScrollback(this.getSplitCursorSeedRows());
22268
+ this.clearPendingSplitFooterTransition();
22269
+ this.pendingSplitStartupCursorSeed = false;
22270
+ this.updateStdinParserProtocolContext({ startupCursorCprActive: false });
22271
+ if (this.splitStartupSeedTimeoutId !== null) {
22272
+ this.clock.clearTimeout(this.splitStartupSeedTimeoutId);
22273
+ this.splitStartupSeedTimeoutId = null;
22274
+ }
22275
+ this.requestRender();
22276
+ }
22277
+ const consumeStartupCursorReport = hadPendingSplitStartupCursorSeed && hasCursorReport && this.splitStartupSeedTimeoutId !== null;
22278
+ return hasStandardCapabilitySignature || consumeStartupCursorReport;
22279
+ }
22280
+ capabilityHandler = ((sequence) => {
22281
+ return this.processCapabilitySequence(sequence, false);
19815
22282
  }).bind(this);
19816
22283
  focusHandler = ((sequence) => {
19817
22284
  if (sequence === "\x1B[I") {
@@ -19925,6 +22392,9 @@ Captured output:
19925
22392
  subscriber(event.sequence);
19926
22393
  }
19927
22394
  }
22395
+ if (event.protocol === "cpr" && this.processCapabilitySequence(event.sequence, true)) {
22396
+ return;
22397
+ }
19928
22398
  this.dispatchSequenceHandlers(event.sequence);
19929
22399
  return;
19930
22400
  }
@@ -20211,28 +22681,45 @@ Captured output:
20211
22681
  processResize(width, height) {
20212
22682
  if (width === this._terminalWidth && height === this._terminalHeight)
20213
22683
  return;
22684
+ if (this._terminalIsSetup && this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
22685
+ this.flushPendingSplitOutputBeforeTransition();
22686
+ }
22687
+ const pendingSplitFooterTransition = this.pendingSplitFooterTransition;
22688
+ const previousGeometry = calculateRenderGeometry(this._screenMode, this._terminalWidth, this._terminalHeight, this._footerHeight);
20214
22689
  const prevWidth = this._terminalWidth;
22690
+ const previousTerminalHeight = this._terminalHeight;
22691
+ const visiblePreviousSplitHeight = pendingSplitFooterTransition?.sourceHeight ?? previousGeometry.effectiveFooterHeight;
20215
22692
  this._terminalWidth = width;
20216
22693
  this._terminalHeight = height;
20217
22694
  this.queryPixelResolution();
20218
22695
  this.setCapturedRenderable(undefined);
20219
22696
  this.stdinParser?.resetMouseState();
20220
- if (this._splitHeight > 0) {
20221
- if (width < prevWidth) {
20222
- const start = this._terminalHeight - this._splitHeight * 2;
20223
- const flush = ANSI.moveCursorAndClear(start, 1);
22697
+ const nextGeometry = calculateRenderGeometry(this._screenMode, this._terminalWidth, this._terminalHeight, this._footerHeight);
22698
+ const splitFooterActive = this._screenMode === "split-footer";
22699
+ if (splitFooterActive) {
22700
+ let clearStart = null;
22701
+ if (width < prevWidth && visiblePreviousSplitHeight > 0) {
22702
+ clearStart = Math.max(previousTerminalHeight - visiblePreviousSplitHeight * 2, 1);
22703
+ }
22704
+ if (pendingSplitFooterTransition !== null) {
22705
+ clearStart = clearStart === null ? pendingSplitFooterTransition.sourceTopLine : Math.min(clearStart, pendingSplitFooterTransition.sourceTopLine);
22706
+ }
22707
+ if (clearStart !== null) {
22708
+ const flush = ANSI.moveCursorAndClear(clearStart, 1);
20224
22709
  this.writeOut(flush);
20225
22710
  }
20226
- this.renderOffset = height - this._splitHeight;
20227
- this.width = width;
20228
- this.height = this._splitHeight;
20229
22711
  this.currentRenderBuffer.clear(this.backgroundColor);
20230
- this.lib.setRenderOffset(this.rendererPtr, this.renderOffset);
20231
- } else {
20232
- this.width = width;
20233
- this.height = height;
20234
22712
  }
22713
+ this.clearPendingSplitFooterTransition();
22714
+ this._splitHeight = nextGeometry.effectiveFooterHeight;
22715
+ this.width = nextGeometry.renderWidth;
22716
+ this.height = nextGeometry.renderHeight;
20235
22717
  this.lib.resizeRenderer(this.rendererPtr, this.width, this.height);
22718
+ if (this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout") {
22719
+ this.syncSplitScrollback();
22720
+ } else {
22721
+ this.syncSplitFooterState();
22722
+ }
20236
22723
  this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
20237
22724
  this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
20238
22725
  this._console.resize(this.width, this.height);
@@ -20380,6 +22867,9 @@ Captured output:
20380
22867
  this._previousControlState = this._controlState;
20381
22868
  this._controlState = "explicit_suspended" /* EXPLICIT_SUSPENDED */;
20382
22869
  this.internalPause();
22870
+ if (this._terminalIsSetup) {
22871
+ this.flushPendingSplitOutputBeforeTransition(true);
22872
+ }
20383
22873
  this._suspendedMouseEnabled = this._useMouse;
20384
22874
  this.disableMouse();
20385
22875
  this.removeExitListeners();
@@ -20387,7 +22877,8 @@ Captured output:
20387
22877
  this.updateStdinParserProtocolContext({
20388
22878
  privateCapabilityRepliesActive: false,
20389
22879
  pixelResolutionQueryActive: false,
20390
- explicitWidthCprActive: false
22880
+ explicitWidthCprActive: false,
22881
+ startupCursorCprActive: false
20391
22882
  });
20392
22883
  this.stdinParser?.reset();
20393
22884
  this.stdin.removeListener("data", this.stdinListener);
@@ -20406,6 +22897,9 @@ Captured output:
20406
22897
  this.stdin.resume();
20407
22898
  this.addExitListeners();
20408
22899
  this.lib.resumeRenderer(this.rendererPtr);
22900
+ if (this._screenMode === "split-footer" && this._splitHeight > 0) {
22901
+ this.syncSplitFooterState();
22902
+ }
20409
22903
  if (this._suspendedMouseEnabled) {
20410
22904
  this.enableMouse();
20411
22905
  }
@@ -20467,7 +22961,6 @@ Captured output:
20467
22961
  process.removeListener("unhandledRejection", this.handleError);
20468
22962
  process.removeListener("warning", this.warningHandler);
20469
22963
  process.removeListener("beforeExit", this.exitHandler);
20470
- capture.removeListener("write", this.captureCallback);
20471
22964
  this.removeExitListeners();
20472
22965
  if (this.resizeTimeoutId !== null) {
20473
22966
  this.clock.clearTimeout(this.resizeTimeoutId);
@@ -20477,6 +22970,10 @@ Captured output:
20477
22970
  this.clock.clearTimeout(this.capabilityTimeoutId);
20478
22971
  this.capabilityTimeoutId = null;
20479
22972
  }
22973
+ if (this.splitStartupSeedTimeoutId !== null) {
22974
+ this.clock.clearTimeout(this.splitStartupSeedTimeoutId);
22975
+ this.splitStartupSeedTimeoutId = null;
22976
+ }
20480
22977
  if (this.memorySnapshotTimer) {
20481
22978
  this.clock.clearInterval(this.memorySnapshotTimer);
20482
22979
  this.memorySnapshotTimer = null;
@@ -20490,7 +22987,8 @@ Captured output:
20490
22987
  this.updateStdinParserProtocolContext({
20491
22988
  privateCapabilityRepliesActive: false,
20492
22989
  pixelResolutionQueryActive: false,
20493
- explicitWidthCprActive: false
22990
+ explicitWidthCprActive: false,
22991
+ startupCursorCprActive: false
20494
22992
  }, true);
20495
22993
  this._useMouse = false;
20496
22994
  this.setCapturedRenderable(undefined);
@@ -20529,6 +23027,16 @@ Captured output:
20529
23027
  this.stdinParser = null;
20530
23028
  this.oscSubscribers.clear();
20531
23029
  this._console.destroy();
23030
+ if (this._splitHeight > 0 && this._terminalIsSetup && this._controlState !== "explicit_suspended" /* EXPLICIT_SUSPENDED */) {
23031
+ this.flushPendingSplitOutputBeforeTransition(true);
23032
+ this.renderOffset = 0;
23033
+ if (this.clearOnShutdown) {
23034
+ this.lib.setRenderOffset(this.rendererPtr, 0);
23035
+ }
23036
+ }
23037
+ this._externalOutputMode = "passthrough";
23038
+ this.stdout.write = this.realStdoutWrite;
23039
+ this.externalOutputQueue.clear();
20532
23040
  this.lib.destroyRenderer(this.rendererPtr);
20533
23041
  rendererTracker.removeRenderer(this);
20534
23042
  if (this._onDestroy) {
@@ -20637,12 +23145,21 @@ Captured output:
20637
23145
  console.error("Rendering called concurrently");
20638
23146
  throw new Error("Rendering called concurrently");
20639
23147
  }
20640
- let force = false;
20641
- if (this._splitHeight > 0) {
20642
- force = this.flushStdoutCache(this._splitHeight);
20643
- }
20644
23148
  this.renderingNative = true;
20645
- this.lib.render(this.rendererPtr, force);
23149
+ if (this.pendingSplitStartupCursorSeed && this.splitStartupSeedTimeoutId !== null && this._splitHeight > 0 && this._externalOutputMode === "capture-stdout") {
23150
+ this.renderingNative = false;
23151
+ return;
23152
+ }
23153
+ if (this._splitHeight > 0 && this._externalOutputMode === "capture-stdout") {
23154
+ const forceSplitRepaint = this.forceFullRepaintRequested;
23155
+ this.forceFullRepaintRequested = false;
23156
+ this.flushPendingSplitCommits(forceSplitRepaint);
23157
+ this.pendingSplitFooterTransition = null;
23158
+ } else {
23159
+ this.forceFullRepaintRequested = false;
23160
+ this.pendingSplitFooterTransition = null;
23161
+ this.lib.render(this.rendererPtr, false);
23162
+ }
20646
23163
  this.renderingNative = false;
20647
23164
  }
20648
23165
  collectStatSample(frameTime) {
@@ -20824,7 +23341,7 @@ Captured output:
20824
23341
  }
20825
23342
  }
20826
23343
 
20827
- export { __toESM, __commonJS, __export, __require, Edge, Gutter, MeasureMode, exports_src, isValidBorderStyle, parseBorderStyle, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, KeyEvent, PasteEvent, KeyHandler, InternalKeyHandler, RGBA, hexToRgb, rgbToHex, hsvToRgb, parseColor, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, ATTRIBUTE_BASE_BITS, ATTRIBUTE_BASE_MASK, getBaseAttributes, DebugOverlayCorner, TargetChannel, createTextAttributes, attributesWithLink, getLinkId, 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, link, t, hastToStyledText, SystemClock, nonAlphanumericKeys, parseKeypress, LinearScrollAccel, MacOSScrollAccel, parseAlign, parseAlignItems, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, envRegistry, registerEnvVar, clearEnvCache, generateEnvMarkdown, generateEnvColored, env, StdinParser, treeSitterToTextChunks, treeSitterToStyledText, addDefaultParsers, TreeSitterClient, DataPathsManager, getDataPaths, extensionToFiletype, basenameToFiletype, extToFiletype, pathToFiletype, infoStringToFiletype, main, getTreeSitterClient, ExtmarksController, createExtmarksController, TerminalPalette, createTerminalPalette, decodePasteBytes, stripAnsiSequences, detectLinks, TextBuffer, SpanInfoStruct, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, isValidPercentage, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, EditBuffer, EditorView, ANSI, defaultKeyAliases, mergeKeyAliases, mergeKeyBindings, getKeyBindingAction, buildKeyBindingsMap, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, EditBufferRenderableEvents, isEditBufferRenderable, EditBufferRenderable, buildKittyKeyboardFlags, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };
23344
+ export { __toESM, __commonJS, __export, __require, MeasureMode, exports_src, isValidBorderStyle, parseBorderStyle, BorderChars, getBorderFromSides, getBorderSides, borderCharsToArray, BorderCharArrays, KeyEvent, PasteEvent, KeyHandler, InternalKeyHandler, RGBA, hexToRgb, rgbToHex, hsvToRgb, parseColor, fonts, measureText, getCharacterPositions, coordinateToCharacterIndex, renderFontToFrameBuffer, TextAttributes, ATTRIBUTE_BASE_BITS, ATTRIBUTE_BASE_MASK, getBaseAttributes, DebugOverlayCorner, TargetChannel, createTextAttributes, attributesWithLink, getLinkId, 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, link, t, hastToStyledText, SystemClock, nonAlphanumericKeys, parseKeypress, LinearScrollAccel, MacOSScrollAccel, parseAlign, parseAlignItems, parseBoxSizing, parseDimension, parseDirection, parseDisplay, parseEdge, parseFlexDirection, parseGutter, parseJustify, parseLogLevel, parseMeasureMode, parseOverflow, parsePositionType, parseUnit, parseWrap, MouseParser, Selection, convertGlobalToLocalSelection, ASCIIFontSelectionHelper, envRegistry, registerEnvVar, clearEnvCache, generateEnvMarkdown, generateEnvColored, env, StdinParser, treeSitterToTextChunks, treeSitterToStyledText, addDefaultParsers, TreeSitterClient, DataPathsManager, getDataPaths, extensionToFiletype, basenameToFiletype, extToFiletype, pathToFiletype, infoStringToFiletype, main, getTreeSitterClient, ExtmarksController, createExtmarksController, TerminalPalette, createTerminalPalette, decodePasteBytes, stripAnsiSequences, detectLinks, TextBuffer, SpanInfoStruct, LogLevel2 as LogLevel, setRenderLibPath, resolveRenderLib, OptimizedBuffer, h, isVNode, maybeMakeRenderable, wrapWithDelegates, instantiate, delegate, LayoutEvents, RenderableEvents, isRenderable, BaseRenderable, Renderable, RootRenderable, TextBufferView, EditBuffer, EditorView, convertThemeToStyles, SyntaxStyle, ANSI, BoxRenderable, TextBufferRenderable, CodeRenderable, isTextNodeRenderable, TextNodeRenderable, RootTextNodeRenderable, TextRenderable, defaultKeyAliases, mergeKeyAliases, mergeKeyBindings, getKeyBindingAction, buildKeyBindingsMap, capture, ConsolePosition, TerminalConsole, getObjectsInViewport, EditBufferRenderableEvents, isEditBufferRenderable, EditBufferRenderable, calculateRenderGeometry, buildKittyKeyboardFlags, MouseEvent, MouseButton, createCliRenderer, CliRenderEvents, RendererControlState, CliRenderer };
20828
23345
 
20829
- //# debugId=9682C54D228A139264756E2164756E21
20830
- //# sourceMappingURL=index-xsfpee0k.js.map
23346
+ //# debugId=F970487203C0DBFC64756E2164756E21
23347
+ //# sourceMappingURL=index-qpcsqve6.js.map