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