@opentui/core 0.1.100 → 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.
- package/3d.js +1 -1
- package/{index-zkcykvp8.js → index-qpcsqve6.js} +2905 -301
- package/{index-zkcykvp8.js.map → index-qpcsqve6.js.map} +15 -7
- package/{index-86ppjrgv.js → index-r3mexem1.js} +337 -1671
- package/index-r3mexem1.js.map +35 -0
- package/{index-nr5q8nyn.js → index-zhsxkp8y.js} +3 -3
- package/index.js +13 -13
- package/index.js.map +1 -1
- package/lib/render-geometry.d.ts +8 -0
- package/lib/stdin-parser.d.ts +2 -1
- package/package.json +7 -7
- package/renderables/Markdown.d.ts +30 -0
- package/renderables/TextBufferRenderable.d.ts +1 -0
- package/renderables/TextTable.d.ts +7 -0
- package/renderables/markdown-parser.d.ts +1 -0
- package/renderer.d.ts +72 -1
- package/runtime-plugin-support.js +3 -3
- package/runtime-plugin.js +3 -3
- package/testing.js +7 -4
- package/testing.js.map +3 -3
- package/text-buffer-view.d.ts +1 -0
- package/types.d.ts +1 -0
- package/zig.d.ts +8 -0
- package/index-86ppjrgv.js.map +0 -42
- /package/{index-nr5q8nyn.js.map → index-zhsxkp8y.js.map} +0 -0
|
@@ -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
|
}
|
|
@@ -7088,6 +7101,8 @@ function canCompleteDeferredPrivateReplyCsi(state, byte, context) {
|
|
|
7088
7101
|
return state.hasDigit && byte === 121;
|
|
7089
7102
|
if (byte === 99)
|
|
7090
7103
|
return state.hasDigit || state.semicolons > 0;
|
|
7104
|
+
if (byte === 110)
|
|
7105
|
+
return state.hasDigit;
|
|
7091
7106
|
return state.hasDigit && byte === 117;
|
|
7092
7107
|
}
|
|
7093
7108
|
function concatBytes(left, right) {
|
|
@@ -7182,7 +7197,8 @@ class StdinParser {
|
|
|
7182
7197
|
kittyKeyboardEnabled: options.protocolContext?.kittyKeyboardEnabled ?? false,
|
|
7183
7198
|
privateCapabilityRepliesActive: options.protocolContext?.privateCapabilityRepliesActive ?? false,
|
|
7184
7199
|
pixelResolutionQueryActive: options.protocolContext?.pixelResolutionQueryActive ?? false,
|
|
7185
|
-
explicitWidthCprActive: options.protocolContext?.explicitWidthCprActive ?? false
|
|
7200
|
+
explicitWidthCprActive: options.protocolContext?.explicitWidthCprActive ?? false,
|
|
7201
|
+
startupCursorCprActive: options.protocolContext?.startupCursorCprActive ?? false
|
|
7186
7202
|
};
|
|
7187
7203
|
}
|
|
7188
7204
|
get bufferCapacity() {
|
|
@@ -7684,7 +7700,8 @@ class StdinParser {
|
|
|
7684
7700
|
}
|
|
7685
7701
|
if (byte >= 64 && byte <= 126) {
|
|
7686
7702
|
const end = this.cursor + 1;
|
|
7687
|
-
|
|
7703
|
+
const protocol = classifyParametricCsiProtocol(this.state, byte);
|
|
7704
|
+
this.emitKeyOrResponse(protocol, decodeUtf8(bytes.subarray(this.unitStart, end)));
|
|
7688
7705
|
this.state = { tag: "ground" };
|
|
7689
7706
|
this.consumePrefix(end);
|
|
7690
7707
|
continue;
|
|
@@ -7789,7 +7806,7 @@ class StdinParser {
|
|
|
7789
7806
|
}
|
|
7790
7807
|
if (byte >= 64 && byte <= 126) {
|
|
7791
7808
|
const end = this.cursor + 1;
|
|
7792
|
-
this.
|
|
7809
|
+
this.emitOpaqueResponse("csi", bytes.subarray(this.unitStart, end));
|
|
7793
7810
|
this.state = { tag: "ground" };
|
|
7794
7811
|
this.consumePrefix(end);
|
|
7795
7812
|
continue;
|
|
@@ -11893,6 +11910,10 @@ function getOpenTUILib(libPath) {
|
|
|
11893
11910
|
args: ["ptr", "bool"],
|
|
11894
11911
|
returns: "void"
|
|
11895
11912
|
},
|
|
11913
|
+
setClearOnShutdown: {
|
|
11914
|
+
args: ["ptr", "bool"],
|
|
11915
|
+
returns: "void"
|
|
11916
|
+
},
|
|
11896
11917
|
setBackgroundColor: {
|
|
11897
11918
|
args: ["ptr", "ptr"],
|
|
11898
11919
|
returns: "void"
|
|
@@ -11901,6 +11922,22 @@ function getOpenTUILib(libPath) {
|
|
|
11901
11922
|
args: ["ptr", "u32"],
|
|
11902
11923
|
returns: "void"
|
|
11903
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
|
+
},
|
|
11904
11941
|
updateStats: {
|
|
11905
11942
|
args: ["ptr", "f64", "u32", "f64"],
|
|
11906
11943
|
returns: "void"
|
|
@@ -11913,6 +11950,14 @@ function getOpenTUILib(libPath) {
|
|
|
11913
11950
|
args: ["ptr", "bool"],
|
|
11914
11951
|
returns: "void"
|
|
11915
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
|
+
},
|
|
11916
11961
|
getNextBuffer: {
|
|
11917
11962
|
args: ["ptr"],
|
|
11918
11963
|
returns: "ptr"
|
|
@@ -12385,6 +12430,10 @@ function getOpenTUILib(libPath) {
|
|
|
12385
12430
|
args: ["ptr", "u8"],
|
|
12386
12431
|
returns: "void"
|
|
12387
12432
|
},
|
|
12433
|
+
textBufferViewSetFirstLineOffset: {
|
|
12434
|
+
args: ["ptr", "u32"],
|
|
12435
|
+
returns: "void"
|
|
12436
|
+
},
|
|
12388
12437
|
textBufferViewSetViewportSize: {
|
|
12389
12438
|
args: ["ptr", "u32", "u32"],
|
|
12390
12439
|
returns: "void"
|
|
@@ -13122,12 +13171,27 @@ class FFIRenderLib {
|
|
|
13122
13171
|
setUseThread(renderer, useThread) {
|
|
13123
13172
|
this.opentui.symbols.setUseThread(renderer, useThread);
|
|
13124
13173
|
}
|
|
13174
|
+
setClearOnShutdown(renderer, clear) {
|
|
13175
|
+
this.opentui.symbols.setClearOnShutdown(renderer, clear);
|
|
13176
|
+
}
|
|
13125
13177
|
setBackgroundColor(renderer, color) {
|
|
13126
13178
|
this.opentui.symbols.setBackgroundColor(renderer, color.buffer);
|
|
13127
13179
|
}
|
|
13128
13180
|
setRenderOffset(renderer, offset) {
|
|
13129
13181
|
this.opentui.symbols.setRenderOffset(renderer, offset);
|
|
13130
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
|
+
}
|
|
13131
13195
|
updateStats(renderer, time, fps, frameCallbackTime) {
|
|
13132
13196
|
this.opentui.symbols.updateStats(renderer, time, fps, frameCallbackTime);
|
|
13133
13197
|
}
|
|
@@ -13317,6 +13381,12 @@ class FFIRenderLib {
|
|
|
13317
13381
|
render(renderer, force) {
|
|
13318
13382
|
this.opentui.symbols.render(renderer, force);
|
|
13319
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
|
+
}
|
|
13320
13390
|
createOptimizedBuffer(width, height, widthMethod, respectAlpha = false, id) {
|
|
13321
13391
|
if (Number.isNaN(width) || Number.isNaN(height)) {
|
|
13322
13392
|
console.error(new Error(`Invalid dimensions for OptimizedBuffer: ${width}x${height}`).stack);
|
|
@@ -13596,6 +13666,9 @@ class FFIRenderLib {
|
|
|
13596
13666
|
const modeValue = mode === "none" ? 0 : mode === "char" ? 1 : 2;
|
|
13597
13667
|
this.opentui.symbols.textBufferViewSetWrapMode(view, modeValue);
|
|
13598
13668
|
}
|
|
13669
|
+
textBufferViewSetFirstLineOffset(view, offset) {
|
|
13670
|
+
this.opentui.symbols.textBufferViewSetFirstLineOffset(view, offset);
|
|
13671
|
+
}
|
|
13599
13672
|
textBufferViewSetViewportSize(view, width, height) {
|
|
13600
13673
|
this.opentui.symbols.textBufferViewSetViewportSize(view, width, height);
|
|
13601
13674
|
}
|
|
@@ -16049,6 +16122,139 @@ function delegate(mapping, vnode) {
|
|
|
16049
16122
|
return vnode;
|
|
16050
16123
|
}
|
|
16051
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
|
+
|
|
16052
16258
|
// src/edit-buffer.ts
|
|
16053
16259
|
import { EventEmitter as EventEmitter6 } from "events";
|
|
16054
16260
|
|
|
@@ -16553,117 +16759,1552 @@ class EditorView {
|
|
|
16553
16759
|
}
|
|
16554
16760
|
}
|
|
16555
16761
|
|
|
16556
|
-
// src/
|
|
16557
|
-
|
|
16558
|
-
|
|
16559
|
-
|
|
16560
|
-
|
|
16561
|
-
|
|
16562
|
-
|
|
16563
|
-
|
|
16564
|
-
|
|
16565
|
-
|
|
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
|
+
}
|
|
16566
16791
|
|
|
16567
|
-
class
|
|
16568
|
-
|
|
16569
|
-
|
|
16570
|
-
|
|
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;
|
|
16571
16802
|
}
|
|
16572
|
-
|
|
16573
|
-
|
|
16803
|
+
static create() {
|
|
16804
|
+
const lib = resolveRenderLib();
|
|
16805
|
+
const ptr5 = lib.createSyntaxStyle();
|
|
16806
|
+
return new SyntaxStyle(lib, ptr5);
|
|
16574
16807
|
}
|
|
16575
|
-
|
|
16576
|
-
|
|
16577
|
-
|
|
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;
|
|
16578
16815
|
}
|
|
16579
|
-
|
|
16580
|
-
const
|
|
16581
|
-
|
|
16582
|
-
|
|
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;
|
|
16583
16822
|
}
|
|
16584
|
-
|
|
16585
|
-
this.
|
|
16823
|
+
guard() {
|
|
16824
|
+
if (this._destroyed)
|
|
16825
|
+
throw new Error("NativeSyntaxStyle is destroyed");
|
|
16586
16826
|
}
|
|
16587
|
-
|
|
16588
|
-
|
|
16589
|
-
|
|
16590
|
-
|
|
16591
|
-
|
|
16592
|
-
|
|
16593
|
-
|
|
16594
|
-
|
|
16595
|
-
|
|
16596
|
-
|
|
16597
|
-
this.
|
|
16598
|
-
|
|
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;
|
|
16599
16839
|
}
|
|
16600
|
-
|
|
16601
|
-
|
|
16602
|
-
this.
|
|
16603
|
-
|
|
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;
|
|
16604
16850
|
}
|
|
16605
|
-
|
|
16606
|
-
|
|
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;
|
|
16607
16861
|
}
|
|
16608
|
-
|
|
16609
|
-
|
|
16610
|
-
|
|
16611
|
-
var defaultKeyAliases = {
|
|
16612
|
-
enter: "return",
|
|
16613
|
-
esc: "escape",
|
|
16614
|
-
kp0: "0",
|
|
16615
|
-
kp1: "1",
|
|
16616
|
-
kp2: "2",
|
|
16617
|
-
kp3: "3",
|
|
16618
|
-
kp4: "4",
|
|
16619
|
-
kp5: "5",
|
|
16620
|
-
kp6: "6",
|
|
16621
|
-
kp7: "7",
|
|
16622
|
-
kp8: "8",
|
|
16623
|
-
kp9: "9",
|
|
16624
|
-
kpdecimal: ".",
|
|
16625
|
-
kpdivide: "/",
|
|
16626
|
-
kpmultiply: "*",
|
|
16627
|
-
kpminus: "-",
|
|
16628
|
-
kpplus: "+",
|
|
16629
|
-
kpenter: "enter",
|
|
16630
|
-
kpequal: "=",
|
|
16631
|
-
kpseparator: ",",
|
|
16632
|
-
kpleft: "left",
|
|
16633
|
-
kpright: "right",
|
|
16634
|
-
kpup: "up",
|
|
16635
|
-
kpdown: "down",
|
|
16636
|
-
kppageup: "pageup",
|
|
16637
|
-
kppagedown: "pagedown",
|
|
16638
|
-
kphome: "home",
|
|
16639
|
-
kpend: "end",
|
|
16640
|
-
kpinsert: "insert",
|
|
16641
|
-
kpdelete: "delete"
|
|
16642
|
-
};
|
|
16643
|
-
function mergeKeyAliases(defaults, custom) {
|
|
16644
|
-
return { ...defaults, ...custom };
|
|
16645
|
-
}
|
|
16646
|
-
function mergeKeyBindings(defaults, custom) {
|
|
16647
|
-
const map = new Map;
|
|
16648
|
-
for (const binding of defaults) {
|
|
16649
|
-
const key = getKeyBindingKey(binding);
|
|
16650
|
-
map.set(key, binding);
|
|
16862
|
+
get ptr() {
|
|
16863
|
+
this.guard();
|
|
16864
|
+
return this.stylePtr;
|
|
16651
16865
|
}
|
|
16652
|
-
|
|
16653
|
-
|
|
16654
|
-
|
|
16866
|
+
getStyleCount() {
|
|
16867
|
+
this.guard();
|
|
16868
|
+
return this.lib.syntaxStyleGetStyleCount(this.stylePtr);
|
|
16655
16869
|
}
|
|
16656
|
-
|
|
16657
|
-
|
|
16658
|
-
function getKeyBindingKey(binding) {
|
|
16659
|
-
return `${binding.name}:${binding.ctrl ? 1 : 0}:${binding.shift ? 1 : 0}:${binding.meta ? 1 : 0}:${binding.super ? 1 : 0}`;
|
|
16660
|
-
}
|
|
16661
|
-
function getBaseCodeKeyName(baseCode) {
|
|
16662
|
-
if (baseCode === undefined || baseCode < 32 || baseCode === 127) {
|
|
16663
|
-
return;
|
|
16870
|
+
clearNameCache() {
|
|
16871
|
+
this.nameCache.clear();
|
|
16664
16872
|
}
|
|
16665
|
-
|
|
16666
|
-
|
|
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);
|
|
16667
18308
|
if (name.length === 1 && name >= "A" && name <= "Z") {
|
|
16668
18309
|
return name.toLowerCase();
|
|
16669
18310
|
}
|
|
@@ -18732,6 +20373,27 @@ function getObjectsInViewport(viewport, objects, direction = "column", padding =
|
|
|
18732
20373
|
return visibleChildren;
|
|
18733
20374
|
}
|
|
18734
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
|
+
|
|
18735
20397
|
// src/lib/terminal-capability-detection.ts
|
|
18736
20398
|
function isCapabilityResponse(sequence) {
|
|
18737
20399
|
if (/\x1b\[\?\d+(?:;\d+)*\$y/.test(sequence)) {
|
|
@@ -18769,6 +20431,26 @@ function parsePixelResolution(sequence) {
|
|
|
18769
20431
|
}
|
|
18770
20432
|
|
|
18771
20433
|
// src/renderer.ts
|
|
20434
|
+
var OSC_THEME_RESPONSE = /\x1b](10|11);(?:(?:rgb:)([0-9a-fA-F]+)\/([0-9a-fA-F]+)\/([0-9a-fA-F]+)|#([0-9a-fA-F]{6}))(?:\x07|\x1b\\)/g;
|
|
20435
|
+
function scaleOscThemeComponent(component) {
|
|
20436
|
+
const value = parseInt(component, 16);
|
|
20437
|
+
const maxValue = (1 << 4 * component.length) - 1;
|
|
20438
|
+
return Math.round(value / maxValue * 255).toString(16).padStart(2, "0");
|
|
20439
|
+
}
|
|
20440
|
+
function oscThemeColorToHex(r, g, b, hex6) {
|
|
20441
|
+
if (hex6) {
|
|
20442
|
+
return `#${hex6.toLowerCase()}`;
|
|
20443
|
+
}
|
|
20444
|
+
if (r && g && b) {
|
|
20445
|
+
return `#${scaleOscThemeComponent(r)}${scaleOscThemeComponent(g)}${scaleOscThemeComponent(b)}`;
|
|
20446
|
+
}
|
|
20447
|
+
return "#000000";
|
|
20448
|
+
}
|
|
20449
|
+
function inferThemeModeFromBackgroundColor(color) {
|
|
20450
|
+
const [r, g, b] = parseColor(color).toInts();
|
|
20451
|
+
const brightness = (r * 299 + g * 587 + b * 114) / 1000;
|
|
20452
|
+
return brightness > 128 ? "light" : "dark";
|
|
20453
|
+
}
|
|
18772
20454
|
registerEnvVar({
|
|
18773
20455
|
name: "OTUI_DUMP_CAPTURES",
|
|
18774
20456
|
description: "Dump captured stdout and console caches when the renderer exit handler runs.",
|
|
@@ -18806,6 +20488,9 @@ registerEnvVar({
|
|
|
18806
20488
|
default: false
|
|
18807
20489
|
});
|
|
18808
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;
|
|
18809
20494
|
function normalizeFooterHeight(footerHeight) {
|
|
18810
20495
|
if (footerHeight === undefined) {
|
|
18811
20496
|
return DEFAULT_FOOTER_HEIGHT;
|
|
@@ -18832,11 +20517,106 @@ function resolveModes(config) {
|
|
|
18832
20517
|
if (externalOutputMode === "capture-stdout" && screenMode !== "split-footer") {
|
|
18833
20518
|
throw new Error('externalOutputMode "capture-stdout" requires screenMode "split-footer"');
|
|
18834
20519
|
}
|
|
18835
|
-
return {
|
|
18836
|
-
screenMode,
|
|
18837
|
-
footerHeight,
|
|
18838
|
-
externalOutputMode
|
|
18839
|
-
};
|
|
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) {}
|
|
18840
20620
|
}
|
|
18841
20621
|
var DEFAULT_FORWARDED_ENV_KEYS = [
|
|
18842
20622
|
"TMUX",
|
|
@@ -18958,9 +20738,9 @@ async function createCliRenderer(config = {}) {
|
|
|
18958
20738
|
const { screenMode, footerHeight } = resolveModes(config);
|
|
18959
20739
|
const width = stdout.columns || 80;
|
|
18960
20740
|
const height = stdout.rows || 24;
|
|
18961
|
-
const
|
|
20741
|
+
const geometry = calculateRenderGeometry(screenMode, width, height, footerHeight);
|
|
18962
20742
|
const ziglib = resolveRenderLib();
|
|
18963
|
-
const rendererPtr = ziglib.createRenderer(
|
|
20743
|
+
const rendererPtr = ziglib.createRenderer(geometry.renderWidth, geometry.renderHeight, {
|
|
18964
20744
|
remote: config.remote ?? false,
|
|
18965
20745
|
testing: config.testing ?? false
|
|
18966
20746
|
});
|
|
@@ -19077,6 +20857,8 @@ class CliRenderer extends EventEmitter9 {
|
|
|
19077
20857
|
animationRequest = new Map;
|
|
19078
20858
|
resizeTimeoutId = null;
|
|
19079
20859
|
capabilityTimeoutId = null;
|
|
20860
|
+
splitStartupSeedTimeoutId = null;
|
|
20861
|
+
pendingSplitStartupCursorSeed = false;
|
|
19080
20862
|
resizeDebounceDelay = 100;
|
|
19081
20863
|
enableMouseMovement = false;
|
|
19082
20864
|
_useMouse = true;
|
|
@@ -19084,6 +20866,7 @@ class CliRenderer extends EventEmitter9 {
|
|
|
19084
20866
|
_screenMode = "alternate-screen";
|
|
19085
20867
|
_footerHeight = DEFAULT_FOOTER_HEIGHT;
|
|
19086
20868
|
_externalOutputMode = "passthrough";
|
|
20869
|
+
clearOnShutdown = true;
|
|
19087
20870
|
_suspendedMouseEnabled = false;
|
|
19088
20871
|
_previousControlState = "idle" /* IDLE */;
|
|
19089
20872
|
capturedRenderable;
|
|
@@ -19094,15 +20877,15 @@ class CliRenderer extends EventEmitter9 {
|
|
|
19094
20877
|
clipboard;
|
|
19095
20878
|
_splitHeight = 0;
|
|
19096
20879
|
renderOffset = 0;
|
|
20880
|
+
splitTailColumn = 0;
|
|
20881
|
+
pendingSplitFooterTransition = null;
|
|
20882
|
+
forceFullRepaintRequested = false;
|
|
20883
|
+
maxSplitCommitsPerFrame = 8;
|
|
19097
20884
|
_terminalWidth = 0;
|
|
19098
20885
|
_terminalHeight = 0;
|
|
19099
20886
|
_terminalIsSetup = false;
|
|
20887
|
+
externalOutputQueue = new ExternalOutputQueue;
|
|
19100
20888
|
realStdoutWrite;
|
|
19101
|
-
captureCallback = () => {
|
|
19102
|
-
if (this._splitHeight > 0) {
|
|
19103
|
-
this.requestRender();
|
|
19104
|
-
}
|
|
19105
|
-
};
|
|
19106
20889
|
_useConsole = true;
|
|
19107
20890
|
sigwinchHandler = (() => {
|
|
19108
20891
|
const width = this.stdout.columns || 80;
|
|
@@ -19126,6 +20909,10 @@ class CliRenderer extends EventEmitter9 {
|
|
|
19126
20909
|
_paletteDetectionPromise = null;
|
|
19127
20910
|
_onDestroy;
|
|
19128
20911
|
_themeMode = null;
|
|
20912
|
+
_themeModeSource = "none";
|
|
20913
|
+
_themeFallbackPending = true;
|
|
20914
|
+
_themeOscForeground = null;
|
|
20915
|
+
_themeOscBackground = null;
|
|
19129
20916
|
_terminalFocusState = null;
|
|
19130
20917
|
sequenceHandlers = [];
|
|
19131
20918
|
prependedInputHandlers = [];
|
|
@@ -19141,8 +20928,15 @@ class CliRenderer extends EventEmitter9 {
|
|
|
19141
20928
|
}).bind(this);
|
|
19142
20929
|
dumpOutputCache(optionalMessage = "") {
|
|
19143
20930
|
const cachedLogs = this.console.getCachedLogs();
|
|
19144
|
-
const
|
|
19145
|
-
|
|
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) {
|
|
19146
20940
|
this.realStdoutWrite.call(this.stdout, optionalMessage);
|
|
19147
20941
|
}
|
|
19148
20942
|
if (cachedLogs.length > 0) {
|
|
@@ -19150,11 +20944,18 @@ class CliRenderer extends EventEmitter9 {
|
|
|
19150
20944
|
`);
|
|
19151
20945
|
this.realStdoutWrite.call(this.stdout, cachedLogs);
|
|
19152
20946
|
}
|
|
19153
|
-
if (
|
|
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) {
|
|
19154
20955
|
this.realStdoutWrite.call(this.stdout, `
|
|
19155
|
-
Captured output:
|
|
20956
|
+
Captured external output:
|
|
19156
20957
|
`);
|
|
19157
|
-
this.realStdoutWrite.call(this.stdout,
|
|
20958
|
+
this.realStdoutWrite.call(this.stdout, capturedExternalOutput + `
|
|
19158
20959
|
`);
|
|
19159
20960
|
}
|
|
19160
20961
|
this.realStdoutWrite.call(this.stdout, ANSI.reset);
|
|
@@ -19183,13 +20984,18 @@ Captured output:
|
|
|
19183
20984
|
this.lib = lib;
|
|
19184
20985
|
this._terminalWidth = stdout.columns ?? width;
|
|
19185
20986
|
this._terminalHeight = stdout.rows ?? height;
|
|
19186
|
-
this.width = width;
|
|
19187
|
-
this.height = height;
|
|
19188
20987
|
this._useThread = config.useThread === undefined ? false : config.useThread;
|
|
19189
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;
|
|
19190
20995
|
this._footerHeight = footerHeight;
|
|
19191
|
-
this._screenMode = screenMode;
|
|
19192
20996
|
this.rendererPtr = rendererPtr;
|
|
20997
|
+
this.clearOnShutdown = config.clearOnShutdown ?? true;
|
|
20998
|
+
this.lib.setClearOnShutdown(this.rendererPtr, this.clearOnShutdown);
|
|
19193
20999
|
const forwardEnvKeys = config.forwardEnvKeys ?? [...DEFAULT_FORWARDED_ENV_KEYS];
|
|
19194
21000
|
for (const key of forwardEnvKeys) {
|
|
19195
21001
|
const value = process.env[key];
|
|
@@ -19257,7 +21063,8 @@ Captured output:
|
|
|
19257
21063
|
kittyKeyboardEnabled: useKittyForParsing,
|
|
19258
21064
|
privateCapabilityRepliesActive: false,
|
|
19259
21065
|
pixelResolutionQueryActive: false,
|
|
19260
|
-
explicitWidthCprActive: false
|
|
21066
|
+
explicitWidthCprActive: false,
|
|
21067
|
+
startupCursorCprActive: false
|
|
19261
21068
|
},
|
|
19262
21069
|
clock: this.clock
|
|
19263
21070
|
});
|
|
@@ -19267,7 +21074,7 @@ Captured output:
|
|
|
19267
21074
|
});
|
|
19268
21075
|
this.consoleMode = config.consoleMode ?? "console-overlay";
|
|
19269
21076
|
this.applyScreenMode(screenMode, false, false);
|
|
19270
|
-
this.
|
|
21077
|
+
this.stdout.write = externalOutputMode === "capture-stdout" ? this.interceptStdoutWrite : this.realStdoutWrite;
|
|
19271
21078
|
this._openConsoleOnError = config.openConsoleOnError ?? true;
|
|
19272
21079
|
this._onDestroy = config.onDestroy;
|
|
19273
21080
|
global.requestAnimationFrame = (callback) => {
|
|
@@ -19426,163 +21233,795 @@ Captured output:
|
|
|
19426
21233
|
return;
|
|
19427
21234
|
}
|
|
19428
21235
|
try {
|
|
19429
|
-
await this.loop();
|
|
21236
|
+
await this.loop();
|
|
21237
|
+
} finally {
|
|
21238
|
+
this.updateScheduled = false;
|
|
21239
|
+
this.resolveIdleIfNeeded();
|
|
21240
|
+
}
|
|
21241
|
+
}
|
|
21242
|
+
get consoleMode() {
|
|
21243
|
+
return this._useConsole ? "console-overlay" : "disabled";
|
|
21244
|
+
}
|
|
21245
|
+
set consoleMode(mode) {
|
|
21246
|
+
this._useConsole = mode === "console-overlay";
|
|
21247
|
+
if (this._useConsole) {
|
|
21248
|
+
this.console.activate();
|
|
21249
|
+
} else {
|
|
21250
|
+
this.console.deactivate();
|
|
21251
|
+
}
|
|
21252
|
+
}
|
|
21253
|
+
get isRunning() {
|
|
21254
|
+
return this._isRunning;
|
|
21255
|
+
}
|
|
21256
|
+
isIdleNow() {
|
|
21257
|
+
return !this._isRunning && !this.rendering && !this.renderTimeout && !this.updateScheduled && !this.immediateRerenderRequested;
|
|
21258
|
+
}
|
|
21259
|
+
resolveIdleIfNeeded() {
|
|
21260
|
+
if (!this.isIdleNow())
|
|
21261
|
+
return;
|
|
21262
|
+
const resolvers = this.idleResolvers.splice(0);
|
|
21263
|
+
for (const resolve4 of resolvers) {
|
|
21264
|
+
resolve4();
|
|
21265
|
+
}
|
|
21266
|
+
}
|
|
21267
|
+
idle() {
|
|
21268
|
+
if (this._isDestroyed)
|
|
21269
|
+
return Promise.resolve();
|
|
21270
|
+
if (this.isIdleNow())
|
|
21271
|
+
return Promise.resolve();
|
|
21272
|
+
return new Promise((resolve4) => {
|
|
21273
|
+
this.idleResolvers.push(resolve4);
|
|
21274
|
+
});
|
|
21275
|
+
}
|
|
21276
|
+
get resolution() {
|
|
21277
|
+
return this._resolution;
|
|
21278
|
+
}
|
|
21279
|
+
get console() {
|
|
21280
|
+
return this._console;
|
|
21281
|
+
}
|
|
21282
|
+
get keyInput() {
|
|
21283
|
+
return this._keyHandler;
|
|
21284
|
+
}
|
|
21285
|
+
get _internalKeyInput() {
|
|
21286
|
+
return this._keyHandler;
|
|
21287
|
+
}
|
|
21288
|
+
get terminalWidth() {
|
|
21289
|
+
return this._terminalWidth;
|
|
21290
|
+
}
|
|
21291
|
+
get terminalHeight() {
|
|
21292
|
+
return this._terminalHeight;
|
|
21293
|
+
}
|
|
21294
|
+
get useThread() {
|
|
21295
|
+
return this._useThread;
|
|
21296
|
+
}
|
|
21297
|
+
get targetFps() {
|
|
21298
|
+
return this._targetFps;
|
|
21299
|
+
}
|
|
21300
|
+
set targetFps(targetFps) {
|
|
21301
|
+
this._targetFps = targetFps;
|
|
21302
|
+
this.targetFrameTime = 1000 / this._targetFps;
|
|
21303
|
+
}
|
|
21304
|
+
get maxFps() {
|
|
21305
|
+
return this._maxFps;
|
|
21306
|
+
}
|
|
21307
|
+
set maxFps(maxFps) {
|
|
21308
|
+
this._maxFps = maxFps;
|
|
21309
|
+
this.minTargetFrameTime = 1000 / this._maxFps;
|
|
21310
|
+
}
|
|
21311
|
+
get useMouse() {
|
|
21312
|
+
return this._useMouse;
|
|
21313
|
+
}
|
|
21314
|
+
set useMouse(useMouse) {
|
|
21315
|
+
if (this._useMouse === useMouse)
|
|
21316
|
+
return;
|
|
21317
|
+
this._useMouse = useMouse;
|
|
21318
|
+
if (useMouse) {
|
|
21319
|
+
this.enableMouse();
|
|
21320
|
+
} else {
|
|
21321
|
+
this.disableMouse();
|
|
21322
|
+
}
|
|
21323
|
+
}
|
|
21324
|
+
get screenMode() {
|
|
21325
|
+
return this._screenMode;
|
|
21326
|
+
}
|
|
21327
|
+
set screenMode(mode) {
|
|
21328
|
+
if (this.externalOutputMode === "capture-stdout" && mode !== "split-footer") {
|
|
21329
|
+
throw new Error('externalOutputMode "capture-stdout" requires screenMode "split-footer"');
|
|
21330
|
+
}
|
|
21331
|
+
this.applyScreenMode(mode);
|
|
21332
|
+
}
|
|
21333
|
+
get footerHeight() {
|
|
21334
|
+
return this._footerHeight;
|
|
21335
|
+
}
|
|
21336
|
+
set footerHeight(footerHeight) {
|
|
21337
|
+
const normalizedFooterHeight = normalizeFooterHeight(footerHeight);
|
|
21338
|
+
if (normalizedFooterHeight === this._footerHeight) {
|
|
21339
|
+
return;
|
|
21340
|
+
}
|
|
21341
|
+
this._footerHeight = normalizedFooterHeight;
|
|
21342
|
+
if (this.screenMode === "split-footer") {
|
|
21343
|
+
this.applyScreenMode("split-footer");
|
|
21344
|
+
}
|
|
21345
|
+
}
|
|
21346
|
+
get externalOutputMode() {
|
|
21347
|
+
return this._externalOutputMode;
|
|
21348
|
+
}
|
|
21349
|
+
set externalOutputMode(mode) {
|
|
21350
|
+
if (mode === "capture-stdout" && this.screenMode !== "split-footer") {
|
|
21351
|
+
throw new Error('externalOutputMode "capture-stdout" requires screenMode "split-footer"');
|
|
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
|
+
}
|
|
21360
|
+
this._externalOutputMode = mode;
|
|
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();
|
|
21372
|
+
}
|
|
21373
|
+
get liveRequestCount() {
|
|
21374
|
+
return this.liveRequestCounter;
|
|
21375
|
+
}
|
|
21376
|
+
get currentControlState() {
|
|
21377
|
+
return this._controlState;
|
|
21378
|
+
}
|
|
21379
|
+
get capabilities() {
|
|
21380
|
+
return this._capabilities;
|
|
21381
|
+
}
|
|
21382
|
+
get themeMode() {
|
|
21383
|
+
return this._themeMode;
|
|
21384
|
+
}
|
|
21385
|
+
waitForThemeMode(timeoutMs = 1000) {
|
|
21386
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
|
|
21387
|
+
throw new Error("timeoutMs must be a non-negative finite number");
|
|
21388
|
+
}
|
|
21389
|
+
if (this._themeMode !== null || this._isDestroyed || timeoutMs === 0) {
|
|
21390
|
+
return Promise.resolve(this._themeMode);
|
|
21391
|
+
}
|
|
21392
|
+
return new Promise((resolve4) => {
|
|
21393
|
+
let timeoutHandle = null;
|
|
21394
|
+
const cleanup = () => {
|
|
21395
|
+
if (timeoutHandle !== null) {
|
|
21396
|
+
this.clock.clearTimeout(timeoutHandle);
|
|
21397
|
+
timeoutHandle = null;
|
|
21398
|
+
}
|
|
21399
|
+
this.off("theme_mode" /* THEME_MODE */, handleThemeMode);
|
|
21400
|
+
this.off("destroy" /* DESTROY */, handleDestroy);
|
|
21401
|
+
};
|
|
21402
|
+
const finish = () => {
|
|
21403
|
+
cleanup();
|
|
21404
|
+
resolve4(this._themeMode);
|
|
21405
|
+
};
|
|
21406
|
+
const handleThemeMode = () => {
|
|
21407
|
+
finish();
|
|
21408
|
+
};
|
|
21409
|
+
const handleDestroy = () => {
|
|
21410
|
+
finish();
|
|
21411
|
+
};
|
|
21412
|
+
this.on("theme_mode" /* THEME_MODE */, handleThemeMode);
|
|
21413
|
+
this.on("destroy" /* DESTROY */, handleDestroy);
|
|
21414
|
+
timeoutHandle = this.clock.setTimeout(finish, timeoutMs);
|
|
21415
|
+
});
|
|
21416
|
+
}
|
|
21417
|
+
getDebugInputs() {
|
|
21418
|
+
return [...this._debugInputs];
|
|
21419
|
+
}
|
|
21420
|
+
get useKittyKeyboard() {
|
|
21421
|
+
return this.lib.getKittyKeyboardFlags(this.rendererPtr) > 0;
|
|
21422
|
+
}
|
|
21423
|
+
set useKittyKeyboard(use) {
|
|
21424
|
+
const flags = use ? KITTY_FLAG_DISAMBIGUATE | KITTY_FLAG_ALTERNATE_KEYS : 0;
|
|
21425
|
+
this.lib.setKittyKeyboardFlags(this.rendererPtr, flags);
|
|
21426
|
+
}
|
|
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;
|
|
19430
21719
|
} finally {
|
|
19431
|
-
|
|
19432
|
-
|
|
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
|
+
}
|
|
19433
21740
|
}
|
|
19434
21741
|
}
|
|
19435
|
-
|
|
19436
|
-
|
|
19437
|
-
|
|
19438
|
-
|
|
19439
|
-
this._useConsole = mode === "console-overlay";
|
|
19440
|
-
if (this._useConsole) {
|
|
19441
|
-
this.console.activate();
|
|
19442
|
-
} else {
|
|
19443
|
-
this.console.deactivate();
|
|
21742
|
+
getSnapshotWidth(value, fallback) {
|
|
21743
|
+
const rawValue = value ?? fallback;
|
|
21744
|
+
if (!Number.isFinite(rawValue)) {
|
|
21745
|
+
throw new Error("writeToScrollback produced a non-finite width");
|
|
19444
21746
|
}
|
|
21747
|
+
return Math.min(Math.max(Math.trunc(rawValue), 1), Math.max(this.width, 1));
|
|
19445
21748
|
}
|
|
19446
|
-
|
|
19447
|
-
|
|
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);
|
|
19448
21755
|
}
|
|
19449
|
-
|
|
19450
|
-
|
|
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;
|
|
19451
21773
|
}
|
|
19452
|
-
|
|
19453
|
-
if (
|
|
21774
|
+
publishSplitTailColumns(columns) {
|
|
21775
|
+
if (columns <= 0) {
|
|
19454
21776
|
return;
|
|
19455
|
-
const resolvers = this.idleResolvers.splice(0);
|
|
19456
|
-
for (const resolve4 of resolvers) {
|
|
19457
|
-
resolve4();
|
|
19458
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;
|
|
19459
21793
|
}
|
|
19460
|
-
|
|
19461
|
-
if (this.
|
|
19462
|
-
|
|
19463
|
-
|
|
19464
|
-
|
|
19465
|
-
|
|
19466
|
-
this.
|
|
19467
|
-
|
|
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
|
+
}
|
|
19468
21805
|
}
|
|
19469
|
-
|
|
19470
|
-
|
|
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();
|
|
19471
21818
|
}
|
|
19472
|
-
|
|
19473
|
-
|
|
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
|
+
}
|
|
19474
21857
|
}
|
|
19475
|
-
|
|
19476
|
-
|
|
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;
|
|
19477
21878
|
}
|
|
19478
|
-
|
|
19479
|
-
|
|
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;
|
|
19480
21900
|
}
|
|
19481
|
-
|
|
19482
|
-
|
|
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) {
|
|
21921
|
+
this.requestRender();
|
|
21922
|
+
}
|
|
19483
21923
|
}
|
|
19484
|
-
|
|
19485
|
-
|
|
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);
|
|
21939
|
+
}
|
|
21940
|
+
return true;
|
|
21941
|
+
};
|
|
21942
|
+
getSplitPinnedRenderOffset() {
|
|
21943
|
+
return this._screenMode === "split-footer" ? Math.max(this._terminalHeight - this._splitHeight, 0) : 0;
|
|
19486
21944
|
}
|
|
19487
|
-
|
|
19488
|
-
|
|
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));
|
|
19489
21949
|
}
|
|
19490
|
-
|
|
19491
|
-
|
|
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);
|
|
19492
21958
|
}
|
|
19493
|
-
|
|
19494
|
-
this.
|
|
19495
|
-
this.
|
|
21959
|
+
resetSplitScrollback(seedRows = 0) {
|
|
21960
|
+
this.splitTailColumn = 0;
|
|
21961
|
+
this.renderOffset = this.lib.resetSplitScrollback(this.rendererPtr, seedRows, this.getSplitPinnedRenderOffset());
|
|
19496
21962
|
}
|
|
19497
|
-
|
|
19498
|
-
|
|
21963
|
+
syncSplitScrollback() {
|
|
21964
|
+
this.renderOffset = this.lib.syncSplitScrollback(this.rendererPtr, this.getSplitPinnedRenderOffset());
|
|
19499
21965
|
}
|
|
19500
|
-
|
|
19501
|
-
this.
|
|
19502
|
-
|
|
21966
|
+
clearPendingSplitFooterTransition() {
|
|
21967
|
+
if (this.pendingSplitFooterTransition === null) {
|
|
21968
|
+
return;
|
|
21969
|
+
}
|
|
21970
|
+
this.pendingSplitFooterTransition = null;
|
|
21971
|
+
this.lib.clearPendingSplitFooterTransition(this.rendererPtr);
|
|
19503
21972
|
}
|
|
19504
|
-
|
|
19505
|
-
|
|
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);
|
|
19506
21976
|
}
|
|
19507
|
-
|
|
19508
|
-
|
|
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);
|
|
19509
21985
|
return;
|
|
19510
|
-
|
|
19511
|
-
if (
|
|
19512
|
-
this.
|
|
21986
|
+
}
|
|
21987
|
+
if (this._externalOutputMode === "capture-stdout") {
|
|
21988
|
+
this.syncSplitScrollback();
|
|
19513
21989
|
} else {
|
|
19514
|
-
this.
|
|
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);
|
|
19515
21995
|
}
|
|
19516
21996
|
}
|
|
19517
|
-
|
|
19518
|
-
|
|
19519
|
-
|
|
19520
|
-
set screenMode(mode) {
|
|
19521
|
-
if (this.externalOutputMode === "capture-stdout" && mode !== "split-footer") {
|
|
19522
|
-
throw new Error('externalOutputMode "capture-stdout" requires screenMode "split-footer"');
|
|
21997
|
+
clearStaleSplitSurfaceRows(previousTopLine, previousHeight, nextTopLine, nextHeight) {
|
|
21998
|
+
if (!this._terminalIsSetup || previousHeight <= 0 || this._terminalHeight <= 0) {
|
|
21999
|
+
return;
|
|
19523
22000
|
}
|
|
19524
|
-
this.
|
|
19525
|
-
|
|
19526
|
-
|
|
19527
|
-
|
|
19528
|
-
}
|
|
19529
|
-
set footerHeight(footerHeight) {
|
|
19530
|
-
const normalizedFooterHeight = normalizeFooterHeight(footerHeight);
|
|
19531
|
-
if (normalizedFooterHeight === this._footerHeight) {
|
|
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) {
|
|
19532
22005
|
return;
|
|
19533
22006
|
}
|
|
19534
|
-
|
|
19535
|
-
|
|
19536
|
-
|
|
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`;
|
|
19537
22015
|
}
|
|
19538
|
-
|
|
19539
|
-
|
|
19540
|
-
return this._externalOutputMode;
|
|
19541
|
-
}
|
|
19542
|
-
set externalOutputMode(mode) {
|
|
19543
|
-
if (mode === "capture-stdout" && this.screenMode !== "split-footer") {
|
|
19544
|
-
throw new Error('externalOutputMode "capture-stdout" requires screenMode "split-footer"');
|
|
22016
|
+
if (clear.length > 0) {
|
|
22017
|
+
this.writeOut(clear);
|
|
19545
22018
|
}
|
|
19546
|
-
this._externalOutputMode = mode;
|
|
19547
|
-
this.stdout.write = mode === "capture-stdout" ? this.interceptStdoutWrite : this.realStdoutWrite;
|
|
19548
|
-
}
|
|
19549
|
-
get liveRequestCount() {
|
|
19550
|
-
return this.liveRequestCounter;
|
|
19551
|
-
}
|
|
19552
|
-
get currentControlState() {
|
|
19553
|
-
return this._controlState;
|
|
19554
|
-
}
|
|
19555
|
-
get capabilities() {
|
|
19556
|
-
return this._capabilities;
|
|
19557
|
-
}
|
|
19558
|
-
get themeMode() {
|
|
19559
|
-
return this._themeMode;
|
|
19560
|
-
}
|
|
19561
|
-
getDebugInputs() {
|
|
19562
|
-
return [...this._debugInputs];
|
|
19563
|
-
}
|
|
19564
|
-
get useKittyKeyboard() {
|
|
19565
|
-
return this.lib.getKittyKeyboardFlags(this.rendererPtr) > 0;
|
|
19566
|
-
}
|
|
19567
|
-
set useKittyKeyboard(use) {
|
|
19568
|
-
const flags = use ? KITTY_FLAG_DISAMBIGUATE | KITTY_FLAG_ALTERNATE_KEYS : 0;
|
|
19569
|
-
this.lib.setKittyKeyboardFlags(this.rendererPtr, flags);
|
|
19570
22019
|
}
|
|
19571
|
-
interceptStdoutWrite = (chunk, encoding, callback) => {
|
|
19572
|
-
const text = chunk.toString();
|
|
19573
|
-
capture.write("stdout", text);
|
|
19574
|
-
if (this._splitHeight > 0) {
|
|
19575
|
-
this.requestRender();
|
|
19576
|
-
}
|
|
19577
|
-
if (typeof callback === "function") {
|
|
19578
|
-
process.nextTick(callback);
|
|
19579
|
-
}
|
|
19580
|
-
return true;
|
|
19581
|
-
};
|
|
19582
22020
|
applyScreenMode(screenMode, emitResize = true, requestRender = true) {
|
|
19583
22021
|
const prevScreenMode = this._screenMode;
|
|
19584
22022
|
const prevSplitHeight = this._splitHeight;
|
|
19585
|
-
const
|
|
22023
|
+
const nextGeometry = calculateRenderGeometry(screenMode, this._terminalWidth, this._terminalHeight, this._footerHeight);
|
|
22024
|
+
const nextSplitHeight = nextGeometry.effectiveFooterHeight;
|
|
19586
22025
|
if (prevScreenMode === screenMode && prevSplitHeight === nextSplitHeight) {
|
|
19587
22026
|
return;
|
|
19588
22027
|
}
|
|
@@ -19590,10 +22029,24 @@ Captured output:
|
|
|
19590
22029
|
const nextUseAlternateScreen = screenMode === "alternate-screen";
|
|
19591
22030
|
const terminalScreenModeChanged = this._terminalIsSetup && prevUseAlternateScreen !== nextUseAlternateScreen;
|
|
19592
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");
|
|
19593
22044
|
if (this._terminalIsSetup && leavingSplitFooter) {
|
|
19594
|
-
this.
|
|
22045
|
+
this.clearPendingSplitFooterTransition();
|
|
22046
|
+
this.renderOffset = 0;
|
|
22047
|
+
this.lib.setRenderOffset(this.rendererPtr, 0);
|
|
19595
22048
|
}
|
|
19596
|
-
if (this._terminalIsSetup && !terminalScreenModeChanged) {
|
|
22049
|
+
if (this._terminalIsSetup && !terminalScreenModeChanged && shouldUseViewportScrollTransitions && !shouldDeferSplitFooterResizeTransition) {
|
|
19597
22050
|
if (prevSplitHeight === 0 && nextSplitHeight > 0) {
|
|
19598
22051
|
const freedLines = this._terminalHeight - nextSplitHeight;
|
|
19599
22052
|
const scrollDown = ANSI.scrollDown(freedLines);
|
|
@@ -19608,18 +22061,39 @@ Captured output:
|
|
|
19608
22061
|
this.writeOut(scrollUp);
|
|
19609
22062
|
}
|
|
19610
22063
|
}
|
|
19611
|
-
if (prevSplitHeight === 0 && nextSplitHeight > 0) {
|
|
19612
|
-
capture.on("write", this.captureCallback);
|
|
19613
|
-
} else if (prevSplitHeight > 0 && nextSplitHeight === 0) {
|
|
19614
|
-
capture.off("write", this.captureCallback);
|
|
19615
|
-
}
|
|
19616
22064
|
this._screenMode = screenMode;
|
|
19617
22065
|
this._splitHeight = nextSplitHeight;
|
|
19618
|
-
this.
|
|
19619
|
-
this.
|
|
19620
|
-
this.height = nextSplitHeight > 0 ? nextSplitHeight : this._terminalHeight;
|
|
19621
|
-
this.lib.setRenderOffset(this.rendererPtr, this.renderOffset);
|
|
22066
|
+
this.width = nextGeometry.renderWidth;
|
|
22067
|
+
this.height = nextGeometry.renderHeight;
|
|
19622
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
|
+
}
|
|
19623
22097
|
this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
|
|
19624
22098
|
this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
|
|
19625
22099
|
this._console.resize(this.width, this.height);
|
|
@@ -19639,12 +22113,18 @@ Captured output:
|
|
|
19639
22113
|
}
|
|
19640
22114
|
}
|
|
19641
22115
|
flushStdoutCache(space, force = false) {
|
|
19642
|
-
if (
|
|
22116
|
+
if (this.externalOutputQueue.size === 0 && !force)
|
|
19643
22117
|
return false;
|
|
19644
|
-
const
|
|
19645
|
-
|
|
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;
|
|
19646
22126
|
const flush = ANSI.moveCursorAndClear(rendererStartLine, 1);
|
|
19647
|
-
const outputLine = this.
|
|
22127
|
+
const outputLine = this.renderOffset + 1;
|
|
19648
22128
|
const move = ANSI.moveCursor(outputLine, 1);
|
|
19649
22129
|
let clear = "";
|
|
19650
22130
|
if (space > 0) {
|
|
@@ -19686,9 +22166,11 @@ Captured output:
|
|
|
19686
22166
|
if (this._terminalIsSetup)
|
|
19687
22167
|
return;
|
|
19688
22168
|
this._terminalIsSetup = true;
|
|
22169
|
+
const startupCursorCprActive = this._screenMode === "split-footer" && this._externalOutputMode === "capture-stdout";
|
|
19689
22170
|
this.updateStdinParserProtocolContext({
|
|
19690
22171
|
privateCapabilityRepliesActive: true,
|
|
19691
|
-
explicitWidthCprActive: true
|
|
22172
|
+
explicitWidthCprActive: true,
|
|
22173
|
+
startupCursorCprActive
|
|
19692
22174
|
});
|
|
19693
22175
|
this.lib.setupTerminal(this.rendererPtr, this._screenMode === "alternate-screen");
|
|
19694
22176
|
this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
|
|
@@ -19702,15 +22184,40 @@ Captured output:
|
|
|
19702
22184
|
}
|
|
19703
22185
|
this.capabilityTimeoutId = this.clock.setTimeout(() => {
|
|
19704
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
|
+
}
|
|
19705
22195
|
this.removeInputHandler(this.capabilityHandler);
|
|
19706
22196
|
this.updateStdinParserProtocolContext({
|
|
19707
22197
|
privateCapabilityRepliesActive: false,
|
|
19708
|
-
explicitWidthCprActive: false
|
|
22198
|
+
explicitWidthCprActive: false,
|
|
22199
|
+
startupCursorCprActive: false
|
|
19709
22200
|
}, true);
|
|
19710
22201
|
}, 5000);
|
|
19711
22202
|
if (this._useMouse) {
|
|
19712
22203
|
this.enableMouse();
|
|
19713
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
|
+
}
|
|
19714
22221
|
this.queryPixelResolution();
|
|
19715
22222
|
}
|
|
19716
22223
|
stdinListener = ((chunk) => {
|
|
@@ -19746,14 +22253,32 @@ Captured output:
|
|
|
19746
22253
|
this.oscSubscribers.delete(handler);
|
|
19747
22254
|
};
|
|
19748
22255
|
}
|
|
19749
|
-
|
|
19750
|
-
|
|
19751
|
-
|
|
19752
|
-
|
|
19753
|
-
|
|
19754
|
-
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;
|
|
19755
22261
|
}
|
|
19756
|
-
|
|
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);
|
|
19757
22282
|
}).bind(this);
|
|
19758
22283
|
focusHandler = ((sequence) => {
|
|
19759
22284
|
if (sequence === "\x1B[I") {
|
|
@@ -19779,21 +22304,50 @@ Captured output:
|
|
|
19779
22304
|
}).bind(this);
|
|
19780
22305
|
themeModeHandler = ((sequence) => {
|
|
19781
22306
|
if (sequence === "\x1B[?997;1n") {
|
|
19782
|
-
|
|
19783
|
-
|
|
19784
|
-
this.emit("theme_mode" /* THEME_MODE */, "dark");
|
|
19785
|
-
}
|
|
22307
|
+
this.applyThemeMode("dark", "csi");
|
|
22308
|
+
this._themeFallbackPending = false;
|
|
19786
22309
|
return true;
|
|
19787
22310
|
}
|
|
19788
22311
|
if (sequence === "\x1B[?997;2n") {
|
|
19789
|
-
|
|
19790
|
-
|
|
19791
|
-
|
|
22312
|
+
this.applyThemeMode("light", "csi");
|
|
22313
|
+
this._themeFallbackPending = false;
|
|
22314
|
+
return true;
|
|
22315
|
+
}
|
|
22316
|
+
let handledOscThemeResponse = false;
|
|
22317
|
+
let match;
|
|
22318
|
+
OSC_THEME_RESPONSE.lastIndex = 0;
|
|
22319
|
+
while (match = OSC_THEME_RESPONSE.exec(sequence)) {
|
|
22320
|
+
handledOscThemeResponse = true;
|
|
22321
|
+
const color = oscThemeColorToHex(match[2], match[3], match[4], match[5]);
|
|
22322
|
+
if (match[1] === "10") {
|
|
22323
|
+
this._themeOscForeground = color;
|
|
22324
|
+
} else {
|
|
22325
|
+
this._themeOscBackground = color;
|
|
19792
22326
|
}
|
|
22327
|
+
}
|
|
22328
|
+
if (!handledOscThemeResponse) {
|
|
22329
|
+
return false;
|
|
22330
|
+
}
|
|
22331
|
+
if (!this._themeFallbackPending) {
|
|
19793
22332
|
return true;
|
|
19794
22333
|
}
|
|
19795
|
-
|
|
22334
|
+
if (this._themeOscForeground && this._themeOscBackground) {
|
|
22335
|
+
this.applyThemeMode(inferThemeModeFromBackgroundColor(this._themeOscBackground), "osc");
|
|
22336
|
+
this._themeFallbackPending = false;
|
|
22337
|
+
}
|
|
22338
|
+
return true;
|
|
19796
22339
|
}).bind(this);
|
|
22340
|
+
applyThemeMode(mode, source) {
|
|
22341
|
+
if (source === "osc" && this._themeModeSource === "csi") {
|
|
22342
|
+
return;
|
|
22343
|
+
}
|
|
22344
|
+
const changed = this._themeMode !== mode;
|
|
22345
|
+
this._themeMode = mode;
|
|
22346
|
+
this._themeModeSource = source;
|
|
22347
|
+
if (changed) {
|
|
22348
|
+
this.emit("theme_mode" /* THEME_MODE */, mode);
|
|
22349
|
+
}
|
|
22350
|
+
}
|
|
19797
22351
|
dispatchSequenceHandlers(sequence) {
|
|
19798
22352
|
if (this._debugModeEnabled) {
|
|
19799
22353
|
this._debugInputs.push({
|
|
@@ -19838,6 +22392,9 @@ Captured output:
|
|
|
19838
22392
|
subscriber(event.sequence);
|
|
19839
22393
|
}
|
|
19840
22394
|
}
|
|
22395
|
+
if (event.protocol === "cpr" && this.processCapabilitySequence(event.sequence, true)) {
|
|
22396
|
+
return;
|
|
22397
|
+
}
|
|
19841
22398
|
this.dispatchSequenceHandlers(event.sequence);
|
|
19842
22399
|
return;
|
|
19843
22400
|
}
|
|
@@ -20124,28 +22681,45 @@ Captured output:
|
|
|
20124
22681
|
processResize(width, height) {
|
|
20125
22682
|
if (width === this._terminalWidth && height === this._terminalHeight)
|
|
20126
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);
|
|
20127
22689
|
const prevWidth = this._terminalWidth;
|
|
22690
|
+
const previousTerminalHeight = this._terminalHeight;
|
|
22691
|
+
const visiblePreviousSplitHeight = pendingSplitFooterTransition?.sourceHeight ?? previousGeometry.effectiveFooterHeight;
|
|
20128
22692
|
this._terminalWidth = width;
|
|
20129
22693
|
this._terminalHeight = height;
|
|
20130
22694
|
this.queryPixelResolution();
|
|
20131
22695
|
this.setCapturedRenderable(undefined);
|
|
20132
22696
|
this.stdinParser?.resetMouseState();
|
|
20133
|
-
|
|
20134
|
-
|
|
20135
|
-
|
|
20136
|
-
|
|
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);
|
|
20137
22709
|
this.writeOut(flush);
|
|
20138
22710
|
}
|
|
20139
|
-
this.renderOffset = height - this._splitHeight;
|
|
20140
|
-
this.width = width;
|
|
20141
|
-
this.height = this._splitHeight;
|
|
20142
22711
|
this.currentRenderBuffer.clear(this.backgroundColor);
|
|
20143
|
-
this.lib.setRenderOffset(this.rendererPtr, this.renderOffset);
|
|
20144
|
-
} else {
|
|
20145
|
-
this.width = width;
|
|
20146
|
-
this.height = height;
|
|
20147
22712
|
}
|
|
22713
|
+
this.clearPendingSplitFooterTransition();
|
|
22714
|
+
this._splitHeight = nextGeometry.effectiveFooterHeight;
|
|
22715
|
+
this.width = nextGeometry.renderWidth;
|
|
22716
|
+
this.height = nextGeometry.renderHeight;
|
|
20148
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
|
+
}
|
|
20149
22723
|
this.nextRenderBuffer = this.lib.getNextBuffer(this.rendererPtr);
|
|
20150
22724
|
this.currentRenderBuffer = this.lib.getCurrentBuffer(this.rendererPtr);
|
|
20151
22725
|
this._console.resize(this.width, this.height);
|
|
@@ -20293,6 +22867,9 @@ Captured output:
|
|
|
20293
22867
|
this._previousControlState = this._controlState;
|
|
20294
22868
|
this._controlState = "explicit_suspended" /* EXPLICIT_SUSPENDED */;
|
|
20295
22869
|
this.internalPause();
|
|
22870
|
+
if (this._terminalIsSetup) {
|
|
22871
|
+
this.flushPendingSplitOutputBeforeTransition(true);
|
|
22872
|
+
}
|
|
20296
22873
|
this._suspendedMouseEnabled = this._useMouse;
|
|
20297
22874
|
this.disableMouse();
|
|
20298
22875
|
this.removeExitListeners();
|
|
@@ -20300,7 +22877,8 @@ Captured output:
|
|
|
20300
22877
|
this.updateStdinParserProtocolContext({
|
|
20301
22878
|
privateCapabilityRepliesActive: false,
|
|
20302
22879
|
pixelResolutionQueryActive: false,
|
|
20303
|
-
explicitWidthCprActive: false
|
|
22880
|
+
explicitWidthCprActive: false,
|
|
22881
|
+
startupCursorCprActive: false
|
|
20304
22882
|
});
|
|
20305
22883
|
this.stdinParser?.reset();
|
|
20306
22884
|
this.stdin.removeListener("data", this.stdinListener);
|
|
@@ -20319,6 +22897,9 @@ Captured output:
|
|
|
20319
22897
|
this.stdin.resume();
|
|
20320
22898
|
this.addExitListeners();
|
|
20321
22899
|
this.lib.resumeRenderer(this.rendererPtr);
|
|
22900
|
+
if (this._screenMode === "split-footer" && this._splitHeight > 0) {
|
|
22901
|
+
this.syncSplitFooterState();
|
|
22902
|
+
}
|
|
20322
22903
|
if (this._suspendedMouseEnabled) {
|
|
20323
22904
|
this.enableMouse();
|
|
20324
22905
|
}
|
|
@@ -20380,7 +22961,6 @@ Captured output:
|
|
|
20380
22961
|
process.removeListener("unhandledRejection", this.handleError);
|
|
20381
22962
|
process.removeListener("warning", this.warningHandler);
|
|
20382
22963
|
process.removeListener("beforeExit", this.exitHandler);
|
|
20383
|
-
capture.removeListener("write", this.captureCallback);
|
|
20384
22964
|
this.removeExitListeners();
|
|
20385
22965
|
if (this.resizeTimeoutId !== null) {
|
|
20386
22966
|
this.clock.clearTimeout(this.resizeTimeoutId);
|
|
@@ -20390,6 +22970,10 @@ Captured output:
|
|
|
20390
22970
|
this.clock.clearTimeout(this.capabilityTimeoutId);
|
|
20391
22971
|
this.capabilityTimeoutId = null;
|
|
20392
22972
|
}
|
|
22973
|
+
if (this.splitStartupSeedTimeoutId !== null) {
|
|
22974
|
+
this.clock.clearTimeout(this.splitStartupSeedTimeoutId);
|
|
22975
|
+
this.splitStartupSeedTimeoutId = null;
|
|
22976
|
+
}
|
|
20393
22977
|
if (this.memorySnapshotTimer) {
|
|
20394
22978
|
this.clock.clearInterval(this.memorySnapshotTimer);
|
|
20395
22979
|
this.memorySnapshotTimer = null;
|
|
@@ -20403,7 +22987,8 @@ Captured output:
|
|
|
20403
22987
|
this.updateStdinParserProtocolContext({
|
|
20404
22988
|
privateCapabilityRepliesActive: false,
|
|
20405
22989
|
pixelResolutionQueryActive: false,
|
|
20406
|
-
explicitWidthCprActive: false
|
|
22990
|
+
explicitWidthCprActive: false,
|
|
22991
|
+
startupCursorCprActive: false
|
|
20407
22992
|
}, true);
|
|
20408
22993
|
this._useMouse = false;
|
|
20409
22994
|
this.setCapturedRenderable(undefined);
|
|
@@ -20442,6 +23027,16 @@ Captured output:
|
|
|
20442
23027
|
this.stdinParser = null;
|
|
20443
23028
|
this.oscSubscribers.clear();
|
|
20444
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();
|
|
20445
23040
|
this.lib.destroyRenderer(this.rendererPtr);
|
|
20446
23041
|
rendererTracker.removeRenderer(this);
|
|
20447
23042
|
if (this._onDestroy) {
|
|
@@ -20550,12 +23145,21 @@ Captured output:
|
|
|
20550
23145
|
console.error("Rendering called concurrently");
|
|
20551
23146
|
throw new Error("Rendering called concurrently");
|
|
20552
23147
|
}
|
|
20553
|
-
let force = false;
|
|
20554
|
-
if (this._splitHeight > 0) {
|
|
20555
|
-
force = this.flushStdoutCache(this._splitHeight);
|
|
20556
|
-
}
|
|
20557
23148
|
this.renderingNative = true;
|
|
20558
|
-
this.
|
|
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
|
+
}
|
|
20559
23163
|
this.renderingNative = false;
|
|
20560
23164
|
}
|
|
20561
23165
|
collectStatSample(frameTime) {
|
|
@@ -20737,7 +23341,7 @@ Captured output:
|
|
|
20737
23341
|
}
|
|
20738
23342
|
}
|
|
20739
23343
|
|
|
20740
|
-
export { __toESM, __commonJS, __export, __require,
|
|
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 };
|
|
20741
23345
|
|
|
20742
|
-
//# debugId=
|
|
20743
|
-
//# sourceMappingURL=index-
|
|
23346
|
+
//# debugId=F970487203C0DBFC64756E2164756E21
|
|
23347
|
+
//# sourceMappingURL=index-qpcsqve6.js.map
|