@simon_he/vue-tui 0.0.5 → 0.0.7
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/dist/index.cjs +2262 -266
- package/dist/index.d.ts +180 -106
- package/dist/index.js +1966 -217
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -361,7 +361,7 @@ __export(path_suggest_exports, {
|
|
|
361
361
|
});
|
|
362
362
|
function isNodeLike() {
|
|
363
363
|
var _a2;
|
|
364
|
-
const proc =
|
|
364
|
+
const proc = import_node_process4.default;
|
|
365
365
|
return typeof ((_a2 = proc == null ? void 0 : proc.versions) == null ? void 0 : _a2.node) === "string";
|
|
366
366
|
}
|
|
367
367
|
function loadGitignoreRulesAsync(workspaceAbs) {
|
|
@@ -559,16 +559,16 @@ async function suggestPaths2(options) {
|
|
|
559
559
|
}
|
|
560
560
|
function resolveUserPath2(workspaceAbs, input) {
|
|
561
561
|
var _a2;
|
|
562
|
-
const env = ((_a2 =
|
|
562
|
+
const env = ((_a2 = import_node_process4.default) == null ? void 0 : _a2.env) ?? {};
|
|
563
563
|
return resolveUserPath(workspaceAbs, input, {
|
|
564
564
|
homeDir: String(env.HOME || env.USERPROFILE || "")
|
|
565
565
|
});
|
|
566
566
|
}
|
|
567
|
-
var
|
|
567
|
+
var import_node_process4, DEFAULT_IGNORED_SEGMENTS, EMPTY_GITIGNORE_RULES, gitignoreRulesCache, gitignoreRulesLoading;
|
|
568
568
|
var init_path_suggest = __esm({
|
|
569
569
|
"src/cli/path-suggest.ts"() {
|
|
570
570
|
"use strict";
|
|
571
|
-
|
|
571
|
+
import_node_process4 = __toESM(require("process"), 1);
|
|
572
572
|
init_path();
|
|
573
573
|
init_path_suggest_core();
|
|
574
574
|
init_path_suggest_core();
|
|
@@ -638,6 +638,7 @@ __export(src_exports, {
|
|
|
638
638
|
defaultTInputHostPlugin: () => defaultTInputHostPlugin,
|
|
639
639
|
detectTerminalColorCapability: () => detectTerminalColorCapability,
|
|
640
640
|
formatInlineCellLine: () => formatInlineCellLine,
|
|
641
|
+
getCliLatencyProfiler: () => getCliLatencyProfiler,
|
|
641
642
|
getStdoutRendererMetrics: () => getStdoutRendererMetrics,
|
|
642
643
|
lintJsonText: () => lintJsonText,
|
|
643
644
|
normalizeNewlines: () => normalizeNewlines,
|
|
@@ -1017,7 +1018,359 @@ function ansiColors(level) {
|
|
|
1017
1018
|
}
|
|
1018
1019
|
|
|
1019
1020
|
// src/cli/input.ts
|
|
1020
|
-
var
|
|
1021
|
+
var import_node_process3 = __toESM(require("process"), 1);
|
|
1022
|
+
|
|
1023
|
+
// src/observability/cli-latency.ts
|
|
1024
|
+
var import_node_fs = require("fs");
|
|
1025
|
+
var import_node_process = __toESM(require("process"), 1);
|
|
1026
|
+
var EVENT_OP_ID = Symbol("dimcode.cliLatencyOpId");
|
|
1027
|
+
var DEFAULT_LOG_PATH = "/tmp/dimcode-cli-latency.jsonl";
|
|
1028
|
+
var INVALIDATE_ASSOCIATION_WINDOW_MS = 32;
|
|
1029
|
+
var MAX_OP_AGE_MS = 5e3;
|
|
1030
|
+
var nextOpId = 1;
|
|
1031
|
+
var singleton;
|
|
1032
|
+
function now() {
|
|
1033
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
1034
|
+
}
|
|
1035
|
+
function diffMs(end, start) {
|
|
1036
|
+
if (end == null || start == null)
|
|
1037
|
+
return null;
|
|
1038
|
+
return Math.max(0, end - start);
|
|
1039
|
+
}
|
|
1040
|
+
function parseEnabled(value) {
|
|
1041
|
+
const raw = String(value ?? "").trim().toLowerCase();
|
|
1042
|
+
return raw === "1" || raw === "true" || raw === "yes";
|
|
1043
|
+
}
|
|
1044
|
+
function isTrackedEventType(type) {
|
|
1045
|
+
return type === "keydown" || type === "beforeinput" || type === "input" || type === "paste";
|
|
1046
|
+
}
|
|
1047
|
+
function defineOpId(target, id) {
|
|
1048
|
+
try {
|
|
1049
|
+
Object.defineProperty(target, EVENT_OP_ID, {
|
|
1050
|
+
configurable: true,
|
|
1051
|
+
enumerable: false,
|
|
1052
|
+
writable: true,
|
|
1053
|
+
value: id
|
|
1054
|
+
});
|
|
1055
|
+
} catch {
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
function readOpId(target) {
|
|
1059
|
+
const value = target == null ? void 0 : target[EVENT_OP_ID];
|
|
1060
|
+
return typeof value === "number" ? value : null;
|
|
1061
|
+
}
|
|
1062
|
+
function createDisabledProfiler() {
|
|
1063
|
+
return null;
|
|
1064
|
+
}
|
|
1065
|
+
function createProfiler() {
|
|
1066
|
+
var _a2, _b2, _c;
|
|
1067
|
+
const env = ((_a2 = import_node_process.default) == null ? void 0 : _a2.env) ?? {};
|
|
1068
|
+
if (!parseEnabled(env.DIMCODE_PROFILE_INPUT_LATENCY))
|
|
1069
|
+
return createDisabledProfiler();
|
|
1070
|
+
const logPath = String(
|
|
1071
|
+
env.DIMCODE_PROFILE_INPUT_LATENCY_LOG_PATH ?? DEFAULT_LOG_PATH
|
|
1072
|
+
).trim() || DEFAULT_LOG_PATH;
|
|
1073
|
+
const ops = /* @__PURE__ */ new Map();
|
|
1074
|
+
const pendingCommitIds = /* @__PURE__ */ new Set();
|
|
1075
|
+
const pendingWriteIds = /* @__PURE__ */ new Set();
|
|
1076
|
+
let currentDispatchOpId = null;
|
|
1077
|
+
let lastDispatchOpId = null;
|
|
1078
|
+
let lastDispatchEndedAt = null;
|
|
1079
|
+
let currentFlushIds = [];
|
|
1080
|
+
let lastRawInputAt = null;
|
|
1081
|
+
const emit = (record) => {
|
|
1082
|
+
try {
|
|
1083
|
+
(0, import_node_fs.appendFileSync)(logPath, `${JSON.stringify(record)}
|
|
1084
|
+
`);
|
|
1085
|
+
} catch {
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
const cleanupOp = (id) => {
|
|
1089
|
+
ops.delete(id);
|
|
1090
|
+
pendingCommitIds.delete(id);
|
|
1091
|
+
pendingWriteIds.delete(id);
|
|
1092
|
+
if (currentDispatchOpId === id)
|
|
1093
|
+
currentDispatchOpId = null;
|
|
1094
|
+
if (lastDispatchOpId === id) {
|
|
1095
|
+
lastDispatchOpId = null;
|
|
1096
|
+
lastDispatchEndedAt = null;
|
|
1097
|
+
}
|
|
1098
|
+
if (currentFlushIds.includes(id))
|
|
1099
|
+
currentFlushIds = currentFlushIds.filter((value) => value !== id);
|
|
1100
|
+
};
|
|
1101
|
+
const flushOp = (op, outcome) => {
|
|
1102
|
+
const totalStart = op.rawInputAt ?? op.stdinDispatchAt ?? op.dispatchStartAt;
|
|
1103
|
+
emit({
|
|
1104
|
+
ts: op.createdAtIso,
|
|
1105
|
+
id: op.id,
|
|
1106
|
+
event: {
|
|
1107
|
+
type: op.eventType,
|
|
1108
|
+
key: op.key,
|
|
1109
|
+
code: op.code,
|
|
1110
|
+
defaultPrevented: op.defaultPrevented,
|
|
1111
|
+
parser: op.parser
|
|
1112
|
+
},
|
|
1113
|
+
operation: op.operation,
|
|
1114
|
+
stages: {
|
|
1115
|
+
rawInputAt: op.rawInputAt,
|
|
1116
|
+
stdinDispatchAt: op.stdinDispatchAt,
|
|
1117
|
+
dispatchStartAt: op.dispatchStartAt,
|
|
1118
|
+
dispatchEndAt: op.dispatchEndAt,
|
|
1119
|
+
invalidateAt: op.invalidateAt,
|
|
1120
|
+
flushStartAt: op.flushStartAt,
|
|
1121
|
+
flushEndAt: op.flushEndAt,
|
|
1122
|
+
commitAt: op.commitAt,
|
|
1123
|
+
stdoutRenderStartAt: op.stdoutRenderStartAt,
|
|
1124
|
+
writeStartAt: op.writeStartAt,
|
|
1125
|
+
writeEndAt: op.writeEndAt
|
|
1126
|
+
},
|
|
1127
|
+
timingsMs: {
|
|
1128
|
+
inputParseWait: diffMs(op.stdinDispatchAt, op.rawInputAt),
|
|
1129
|
+
eventDispatch: diffMs(op.dispatchEndAt, op.dispatchStartAt),
|
|
1130
|
+
dispatchToInvalidate: diffMs(op.invalidateAt, op.dispatchEndAt),
|
|
1131
|
+
dispatchToFlush: diffMs(op.flushStartAt, op.dispatchEndAt),
|
|
1132
|
+
flushToCommitDone: diffMs(op.flushEndAt, op.flushStartAt),
|
|
1133
|
+
commitToRender: diffMs(op.stdoutRenderStartAt, op.commitAt),
|
|
1134
|
+
renderToWriteStart: diffMs(op.writeStartAt, op.stdoutRenderStartAt),
|
|
1135
|
+
write: op.writeDurationMs,
|
|
1136
|
+
totalToWrite: diffMs(op.writeEndAt, totalStart)
|
|
1137
|
+
},
|
|
1138
|
+
scheduler: {
|
|
1139
|
+
invalidatePriority: op.invalidatePriority,
|
|
1140
|
+
invalidatePlane: op.invalidatePlane,
|
|
1141
|
+
commitSync: op.commitSync,
|
|
1142
|
+
commitPlaneCount: op.commitPlaneCount,
|
|
1143
|
+
commitDirtyRows: op.commitDirtyRows,
|
|
1144
|
+
stdoutQueuedDelayMs: op.stdoutQueuedDelayMs,
|
|
1145
|
+
writeMode: op.writeMode,
|
|
1146
|
+
writeBytes: op.writeBytes
|
|
1147
|
+
},
|
|
1148
|
+
outcome
|
|
1149
|
+
});
|
|
1150
|
+
cleanupOp(op.id);
|
|
1151
|
+
};
|
|
1152
|
+
const expireOldOps = () => {
|
|
1153
|
+
const currentTime = now();
|
|
1154
|
+
for (const op of ops.values()) {
|
|
1155
|
+
if (currentTime - op.createdAt < MAX_OP_AGE_MS)
|
|
1156
|
+
continue;
|
|
1157
|
+
flushOp(op, op.writeEndAt != null ? "completed" : "timeout");
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
const flushPendingOps = (outcome) => {
|
|
1161
|
+
for (const op of Array.from(ops.values()))
|
|
1162
|
+
flushOp(op, op.writeEndAt != null ? "completed" : outcome);
|
|
1163
|
+
};
|
|
1164
|
+
const ensureOp = (event) => {
|
|
1165
|
+
const type = String((event == null ? void 0 : event.type) ?? "");
|
|
1166
|
+
if (!isTrackedEventType(type))
|
|
1167
|
+
return null;
|
|
1168
|
+
const existingId = readOpId(event);
|
|
1169
|
+
if (existingId != null) {
|
|
1170
|
+
return ops.get(existingId) ?? null;
|
|
1171
|
+
}
|
|
1172
|
+
const id = nextOpId++;
|
|
1173
|
+
const op = {
|
|
1174
|
+
id,
|
|
1175
|
+
createdAt: now(),
|
|
1176
|
+
createdAtIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1177
|
+
eventType: type,
|
|
1178
|
+
key: String((event == null ? void 0 : event.key) ?? ""),
|
|
1179
|
+
code: String((event == null ? void 0 : event.code) ?? ""),
|
|
1180
|
+
operation: null,
|
|
1181
|
+
rawInputAt: null,
|
|
1182
|
+
stdinDispatchAt: null,
|
|
1183
|
+
dispatchStartAt: null,
|
|
1184
|
+
dispatchEndAt: null,
|
|
1185
|
+
invalidateAt: null,
|
|
1186
|
+
invalidatePriority: null,
|
|
1187
|
+
invalidatePlane: null,
|
|
1188
|
+
flushStartAt: null,
|
|
1189
|
+
flushEndAt: null,
|
|
1190
|
+
commitAt: null,
|
|
1191
|
+
commitSync: null,
|
|
1192
|
+
commitPlaneCount: null,
|
|
1193
|
+
commitDirtyRows: null,
|
|
1194
|
+
stdoutQueuedDelayMs: null,
|
|
1195
|
+
stdoutRenderStartAt: null,
|
|
1196
|
+
writeStartAt: null,
|
|
1197
|
+
writeEndAt: null,
|
|
1198
|
+
writeDurationMs: null,
|
|
1199
|
+
writeMode: null,
|
|
1200
|
+
writeBytes: null,
|
|
1201
|
+
defaultPrevented: null,
|
|
1202
|
+
parser: null
|
|
1203
|
+
};
|
|
1204
|
+
ops.set(id, op);
|
|
1205
|
+
defineOpId(event, id);
|
|
1206
|
+
expireOldOps();
|
|
1207
|
+
return op;
|
|
1208
|
+
};
|
|
1209
|
+
const forIds = (ids, fn) => {
|
|
1210
|
+
for (const id of ids) {
|
|
1211
|
+
const op = ops.get(id);
|
|
1212
|
+
if (!op)
|
|
1213
|
+
continue;
|
|
1214
|
+
fn(op);
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
1217
|
+
const resolveActiveOp = () => {
|
|
1218
|
+
if (currentDispatchOpId != null)
|
|
1219
|
+
return ops.get(currentDispatchOpId) ?? null;
|
|
1220
|
+
if (lastDispatchOpId != null && lastDispatchEndedAt != null && now() - lastDispatchEndedAt <= INVALIDATE_ASSOCIATION_WINDOW_MS) {
|
|
1221
|
+
return ops.get(lastDispatchOpId) ?? null;
|
|
1222
|
+
}
|
|
1223
|
+
return null;
|
|
1224
|
+
};
|
|
1225
|
+
(_c = (_b2 = import_node_process.default) == null ? void 0 : _b2.once) == null ? void 0 : _c.call(_b2, "exit", () => {
|
|
1226
|
+
flushPendingOps("process-exit");
|
|
1227
|
+
});
|
|
1228
|
+
return {
|
|
1229
|
+
enabled: true,
|
|
1230
|
+
recordRawInput(_info) {
|
|
1231
|
+
lastRawInputAt = now();
|
|
1232
|
+
expireOldOps();
|
|
1233
|
+
},
|
|
1234
|
+
recordStdinDispatch(event, info) {
|
|
1235
|
+
const op = ensureOp(event);
|
|
1236
|
+
if (!op)
|
|
1237
|
+
return;
|
|
1238
|
+
if (op.rawInputAt == null && lastRawInputAt != null)
|
|
1239
|
+
op.rawInputAt = lastRawInputAt;
|
|
1240
|
+
if (op.stdinDispatchAt == null)
|
|
1241
|
+
op.stdinDispatchAt = now();
|
|
1242
|
+
if (!op.parser && (info == null ? void 0 : info.parser))
|
|
1243
|
+
op.parser = String(info.parser);
|
|
1244
|
+
},
|
|
1245
|
+
recordEventDispatchStart(event) {
|
|
1246
|
+
const op = ensureOp(event);
|
|
1247
|
+
if (!op)
|
|
1248
|
+
return;
|
|
1249
|
+
currentDispatchOpId = op.id;
|
|
1250
|
+
if (op.dispatchStartAt == null)
|
|
1251
|
+
op.dispatchStartAt = now();
|
|
1252
|
+
},
|
|
1253
|
+
recordEventDispatchEnd(event, info) {
|
|
1254
|
+
const op = ensureOp(event);
|
|
1255
|
+
if (!op)
|
|
1256
|
+
return;
|
|
1257
|
+
op.defaultPrevented = Boolean(info.defaultPrevented);
|
|
1258
|
+
if (op.dispatchEndAt == null)
|
|
1259
|
+
op.dispatchEndAt = now();
|
|
1260
|
+
currentDispatchOpId = currentDispatchOpId === op.id ? null : currentDispatchOpId;
|
|
1261
|
+
lastDispatchOpId = op.id;
|
|
1262
|
+
lastDispatchEndedAt = op.dispatchEndAt;
|
|
1263
|
+
},
|
|
1264
|
+
recordSchedulerInvalidate(info) {
|
|
1265
|
+
const op = resolveActiveOp();
|
|
1266
|
+
if (!op)
|
|
1267
|
+
return;
|
|
1268
|
+
if (op.invalidateAt == null)
|
|
1269
|
+
op.invalidateAt = now();
|
|
1270
|
+
if (!op.invalidatePriority && (info == null ? void 0 : info.priority))
|
|
1271
|
+
op.invalidatePriority = String(info.priority);
|
|
1272
|
+
if (!op.invalidatePlane && (info == null ? void 0 : info.plane))
|
|
1273
|
+
op.invalidatePlane = String(info.plane);
|
|
1274
|
+
pendingCommitIds.add(op.id);
|
|
1275
|
+
},
|
|
1276
|
+
recordFlushStart(info) {
|
|
1277
|
+
currentFlushIds = Array.from(pendingCommitIds);
|
|
1278
|
+
if (!currentFlushIds.length)
|
|
1279
|
+
return;
|
|
1280
|
+
const flushTime = now();
|
|
1281
|
+
forIds(currentFlushIds, (op) => {
|
|
1282
|
+
if (op.flushStartAt == null)
|
|
1283
|
+
op.flushStartAt = flushTime;
|
|
1284
|
+
if (op.commitSync == null && (info == null ? void 0 : info.sync) != null)
|
|
1285
|
+
op.commitSync = Boolean(info.sync);
|
|
1286
|
+
if (op.commitPlaneCount == null && Array.isArray(info == null ? void 0 : info.activePlanes)) {
|
|
1287
|
+
op.commitPlaneCount = info.activePlanes.length;
|
|
1288
|
+
}
|
|
1289
|
+
});
|
|
1290
|
+
},
|
|
1291
|
+
recordFlushEnd() {
|
|
1292
|
+
if (!currentFlushIds.length)
|
|
1293
|
+
return;
|
|
1294
|
+
const flushTime = now();
|
|
1295
|
+
forIds(currentFlushIds, (op) => {
|
|
1296
|
+
if (op.flushEndAt == null)
|
|
1297
|
+
op.flushEndAt = flushTime;
|
|
1298
|
+
});
|
|
1299
|
+
currentFlushIds = [];
|
|
1300
|
+
},
|
|
1301
|
+
recordCommit(info) {
|
|
1302
|
+
if (!pendingCommitIds.size)
|
|
1303
|
+
return;
|
|
1304
|
+
const commitTime = now();
|
|
1305
|
+
const ids = Array.from(pendingCommitIds);
|
|
1306
|
+
pendingCommitIds.clear();
|
|
1307
|
+
forIds(ids, (op) => {
|
|
1308
|
+
if (op.flushEndAt == null && op.flushStartAt != null)
|
|
1309
|
+
op.flushEndAt = commitTime;
|
|
1310
|
+
if (op.commitAt == null)
|
|
1311
|
+
op.commitAt = commitTime;
|
|
1312
|
+
op.commitSync = (info == null ? void 0 : info.sync) == null ? op.commitSync : Boolean(info.sync);
|
|
1313
|
+
op.commitPlaneCount = Array.isArray(info == null ? void 0 : info.planes) ? info.planes.length : op.commitPlaneCount;
|
|
1314
|
+
op.commitDirtyRows = Array.isArray(info == null ? void 0 : info.dirtyRows) ? info.dirtyRows.length : (info == null ? void 0 : info.dirtyRows) === null ? null : op.commitDirtyRows;
|
|
1315
|
+
pendingWriteIds.add(op.id);
|
|
1316
|
+
});
|
|
1317
|
+
},
|
|
1318
|
+
recordStdoutQueued(delayMs) {
|
|
1319
|
+
if (!pendingWriteIds.size)
|
|
1320
|
+
return;
|
|
1321
|
+
forIds(pendingWriteIds, (op) => {
|
|
1322
|
+
if (op.stdoutQueuedDelayMs == null)
|
|
1323
|
+
op.stdoutQueuedDelayMs = Math.max(0, delayMs);
|
|
1324
|
+
});
|
|
1325
|
+
},
|
|
1326
|
+
recordStdoutRenderStart() {
|
|
1327
|
+
if (!pendingWriteIds.size)
|
|
1328
|
+
return;
|
|
1329
|
+
const renderTime = now();
|
|
1330
|
+
forIds(pendingWriteIds, (op) => {
|
|
1331
|
+
if (op.stdoutRenderStartAt == null)
|
|
1332
|
+
op.stdoutRenderStartAt = renderTime;
|
|
1333
|
+
});
|
|
1334
|
+
},
|
|
1335
|
+
recordStdoutNoOutput() {
|
|
1336
|
+
if (!pendingWriteIds.size)
|
|
1337
|
+
return;
|
|
1338
|
+
const ids = Array.from(pendingWriteIds);
|
|
1339
|
+
pendingWriteIds.clear();
|
|
1340
|
+
forIds(ids, (op) => flushOp(op, "no-output"));
|
|
1341
|
+
},
|
|
1342
|
+
recordStdoutWrite(info) {
|
|
1343
|
+
if (!pendingWriteIds.size)
|
|
1344
|
+
return;
|
|
1345
|
+
const writeEndTime = now();
|
|
1346
|
+
const ids = Array.from(pendingWriteIds);
|
|
1347
|
+
pendingWriteIds.clear();
|
|
1348
|
+
forIds(ids, (op) => {
|
|
1349
|
+
op.writeEndAt = writeEndTime;
|
|
1350
|
+
op.writeDurationMs = Math.max(0, info.durationMs);
|
|
1351
|
+
op.writeStartAt = writeEndTime - op.writeDurationMs;
|
|
1352
|
+
op.writeMode = String(info.mode ?? "");
|
|
1353
|
+
op.writeBytes = Math.max(0, Math.floor(info.bytes));
|
|
1354
|
+
flushOp(op, "completed");
|
|
1355
|
+
});
|
|
1356
|
+
},
|
|
1357
|
+
markOperation(operation) {
|
|
1358
|
+
const nextOperation = String(operation ?? "").trim();
|
|
1359
|
+
if (!nextOperation)
|
|
1360
|
+
return;
|
|
1361
|
+
const op = resolveActiveOp();
|
|
1362
|
+
if (!op)
|
|
1363
|
+
return;
|
|
1364
|
+
op.operation = nextOperation;
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
function getCliLatencyProfiler() {
|
|
1369
|
+
if (singleton !== void 0)
|
|
1370
|
+
return singleton;
|
|
1371
|
+
singleton = createProfiler();
|
|
1372
|
+
return singleton;
|
|
1373
|
+
}
|
|
1021
1374
|
|
|
1022
1375
|
// src/utils/newlines.ts
|
|
1023
1376
|
function normalizeNewlines(text) {
|
|
@@ -1474,13 +1827,13 @@ function parseLegacySequence(sequence) {
|
|
|
1474
1827
|
}
|
|
1475
1828
|
|
|
1476
1829
|
// src/cli/parse-mouse.ts
|
|
1477
|
-
var
|
|
1478
|
-
var
|
|
1830
|
+
var import_node_fs2 = require("fs");
|
|
1831
|
+
var import_node_process2 = __toESM(require("process"), 1);
|
|
1479
1832
|
function parseMouseSgr(sequence) {
|
|
1480
1833
|
var _a2;
|
|
1481
1834
|
if (!sequence.startsWith("\x1B[<"))
|
|
1482
1835
|
return { handled: false, event: null };
|
|
1483
|
-
const env = ((_a2 =
|
|
1836
|
+
const env = ((_a2 = import_node_process2.default) == null ? void 0 : _a2.env) ?? {};
|
|
1484
1837
|
const invertWheel = String(env.DIMCODE_WHEEL_INVERT ?? env.VUE_TUI_WHEEL_INVERT ?? "") === "1";
|
|
1485
1838
|
const mouseDebugEnabled = String(env.DIMCODE_MOUSE_DEBUG ?? env.VUE_TUI_MOUSE_DEBUG ?? "") === "1";
|
|
1486
1839
|
const mouseDebugPath = String(
|
|
@@ -1490,7 +1843,7 @@ function parseMouseSgr(sequence) {
|
|
|
1490
1843
|
if (!mouseDebugEnabled)
|
|
1491
1844
|
return;
|
|
1492
1845
|
try {
|
|
1493
|
-
(0,
|
|
1846
|
+
(0, import_node_fs2.appendFileSync)(mouseDebugPath, `${msg}
|
|
1494
1847
|
`);
|
|
1495
1848
|
} catch {
|
|
1496
1849
|
}
|
|
@@ -1619,6 +1972,7 @@ var import_node_events = require("events");
|
|
|
1619
1972
|
var ESC3 = "\x1B";
|
|
1620
1973
|
var BRACKETED_PASTE_START = "\x1B[200~";
|
|
1621
1974
|
var BRACKETED_PASTE_END = "\x1B[201~";
|
|
1975
|
+
var ESC_CONTINUATION_RESCUE_WINDOW_MS = 64;
|
|
1622
1976
|
function looksLikeQuotedPathPaste(value) {
|
|
1623
1977
|
if (!value)
|
|
1624
1978
|
return false;
|
|
@@ -1741,11 +2095,19 @@ function extractCompleteSequences(buffer) {
|
|
|
1741
2095
|
}
|
|
1742
2096
|
return { sequences, remainder: "" };
|
|
1743
2097
|
}
|
|
2098
|
+
function looksLikeSplitEscapeContinuation(value) {
|
|
2099
|
+
const first = value[0];
|
|
2100
|
+
if (first !== "[" && first !== "]" && first !== "P" && first !== "_" && first !== "O") {
|
|
2101
|
+
return false;
|
|
2102
|
+
}
|
|
2103
|
+
return isCompleteSequence(`${ESC3}${value}`) !== "not-escape";
|
|
2104
|
+
}
|
|
1744
2105
|
var StdinBuffer = class extends import_node_events.EventEmitter {
|
|
1745
2106
|
buffer = "";
|
|
1746
2107
|
timeout = null;
|
|
1747
2108
|
timeoutMs;
|
|
1748
2109
|
escTimeoutMs;
|
|
2110
|
+
pendingEscContinuationAt = null;
|
|
1749
2111
|
pasteMode = false;
|
|
1750
2112
|
pasteBuffer = "";
|
|
1751
2113
|
constructor(options = {}) {
|
|
@@ -1769,6 +2131,12 @@ var StdinBuffer = class extends import_node_events.EventEmitter {
|
|
|
1769
2131
|
} else {
|
|
1770
2132
|
str = data;
|
|
1771
2133
|
}
|
|
2134
|
+
if (this.pendingEscContinuationAt != null) {
|
|
2135
|
+
const canRescue = Date.now() - this.pendingEscContinuationAt <= ESC_CONTINUATION_RESCUE_WINDOW_MS;
|
|
2136
|
+
this.pendingEscContinuationAt = null;
|
|
2137
|
+
if (canRescue && looksLikeSplitEscapeContinuation(str))
|
|
2138
|
+
str = `${ESC3}${str}`;
|
|
2139
|
+
}
|
|
1772
2140
|
if (str.length === 0 && this.buffer.length === 0) {
|
|
1773
2141
|
this.emit("data", "");
|
|
1774
2142
|
return;
|
|
@@ -1830,7 +2198,10 @@ var StdinBuffer = class extends import_node_events.EventEmitter {
|
|
|
1830
2198
|
if (this.buffer.length > 0) {
|
|
1831
2199
|
const timeoutMs = this.buffer === ESC3 ? this.escTimeoutMs : this.timeoutMs;
|
|
1832
2200
|
this.timeout = setTimeout(() => {
|
|
2201
|
+
const rescuableLoneEsc = this.buffer === ESC3;
|
|
1833
2202
|
const flushed = this.flush();
|
|
2203
|
+
if (rescuableLoneEsc && flushed.length === 1 && flushed[0] === ESC3)
|
|
2204
|
+
this.pendingEscContinuationAt = Date.now();
|
|
1834
2205
|
for (const sequence of flushed)
|
|
1835
2206
|
this.emit("data", sequence);
|
|
1836
2207
|
}, timeoutMs);
|
|
@@ -1853,6 +2224,7 @@ var StdinBuffer = class extends import_node_events.EventEmitter {
|
|
|
1853
2224
|
this.timeout = null;
|
|
1854
2225
|
}
|
|
1855
2226
|
this.buffer = "";
|
|
2227
|
+
this.pendingEscContinuationAt = null;
|
|
1856
2228
|
this.pasteMode = false;
|
|
1857
2229
|
this.pasteBuffer = "";
|
|
1858
2230
|
}
|
|
@@ -1865,6 +2237,10 @@ var StdinBuffer = class extends import_node_events.EventEmitter {
|
|
|
1865
2237
|
};
|
|
1866
2238
|
|
|
1867
2239
|
// src/cli/input.ts
|
|
2240
|
+
var KITTY_KEYBOARD_PROTOCOL_ENABLE = "\x1B[>1u";
|
|
2241
|
+
var KITTY_KEYBOARD_PROTOCOL_DISABLE = "\x1B[<u";
|
|
2242
|
+
var XTERM_MODIFY_OTHER_KEYS_ENABLE = "\x1B[>4;2m";
|
|
2243
|
+
var XTERM_MODIFY_OTHER_KEYS_DISABLE = "\x1B[>4n";
|
|
1868
2244
|
function isPrintable(ch) {
|
|
1869
2245
|
if (ch.length === 0)
|
|
1870
2246
|
return false;
|
|
@@ -1888,13 +2264,64 @@ function ctrlKeyFromChar(ch) {
|
|
|
1888
2264
|
return String.fromCharCode(code + 96);
|
|
1889
2265
|
return null;
|
|
1890
2266
|
}
|
|
2267
|
+
function isUnhandledCtrlC(event) {
|
|
2268
|
+
return event.type === "keydown" && (event.key === "c" || event.key === "C") && event.ctrlKey === true && event.metaKey !== true && event.altKey !== true && event.shiftKey !== true;
|
|
2269
|
+
}
|
|
2270
|
+
function parseKeyboardProtocol(value) {
|
|
2271
|
+
const normalized = String(value ?? "").trim().toLowerCase();
|
|
2272
|
+
if (normalized === "auto" || normalized === "kitty" || normalized === "xterm" || normalized === "off") {
|
|
2273
|
+
return normalized;
|
|
2274
|
+
}
|
|
2275
|
+
return null;
|
|
2276
|
+
}
|
|
2277
|
+
function detectKeyboardProtocol(env) {
|
|
2278
|
+
const termProgram = String(env.TERM_PROGRAM ?? "").trim().toLowerCase();
|
|
2279
|
+
const term = String(env.TERM ?? "").trim().toLowerCase();
|
|
2280
|
+
const hasKittyProtocolTerminal = "GHOSTTY_RESOURCES_DIR" in env || "WEZTERM_PANE" in env || "KITTY_WINDOW_ID" in env || "KITTY_INSTALLATION_DIR" in env || "ALACRITTY_WINDOW_ID" in env || "ALACRITTY_LOG" in env || termProgram.includes("ghostty") || termProgram.includes("wezterm") || termProgram.includes("kitty") || termProgram.includes("alacritty");
|
|
2281
|
+
if (hasKittyProtocolTerminal)
|
|
2282
|
+
return "kitty";
|
|
2283
|
+
const isScreenLike = "TMUX" in env || term.includes("screen") || term.includes("tmux");
|
|
2284
|
+
const hasXtermKeyboardTerminal = termProgram.includes("iterm") || termProgram.includes("apple_terminal") || termProgram.includes("vscode") || term.includes("xterm") && !isScreenLike;
|
|
2285
|
+
return hasXtermKeyboardTerminal ? "xterm" : "off";
|
|
2286
|
+
}
|
|
2287
|
+
function resolveKeyboardProtocol(options) {
|
|
2288
|
+
var _a2;
|
|
2289
|
+
const configured = parseKeyboardProtocol(options.keyboardProtocol) ?? "auto";
|
|
2290
|
+
if (configured !== "auto")
|
|
2291
|
+
return configured;
|
|
2292
|
+
const envOverride = parseKeyboardProtocol((_a2 = options.env) == null ? void 0 : _a2.DIMCODE_KEYBOARD_PROTOCOL);
|
|
2293
|
+
if (envOverride && envOverride !== "auto")
|
|
2294
|
+
return envOverride;
|
|
2295
|
+
return detectKeyboardProtocol(options.env ?? {});
|
|
2296
|
+
}
|
|
2297
|
+
function getKeyboardProtocolSequences(protocol) {
|
|
2298
|
+
if (protocol === "kitty") {
|
|
2299
|
+
return {
|
|
2300
|
+
enable: KITTY_KEYBOARD_PROTOCOL_ENABLE,
|
|
2301
|
+
disable: KITTY_KEYBOARD_PROTOCOL_DISABLE
|
|
2302
|
+
};
|
|
2303
|
+
}
|
|
2304
|
+
if (protocol === "xterm") {
|
|
2305
|
+
return {
|
|
2306
|
+
enable: XTERM_MODIFY_OTHER_KEYS_ENABLE,
|
|
2307
|
+
disable: XTERM_MODIFY_OTHER_KEYS_DISABLE
|
|
2308
|
+
};
|
|
2309
|
+
}
|
|
2310
|
+
return null;
|
|
2311
|
+
}
|
|
1891
2312
|
function createStdinDriver(options) {
|
|
1892
|
-
const stdin = options.stdin ??
|
|
1893
|
-
const stdout = options.stdout ??
|
|
2313
|
+
const stdin = options.stdin ?? import_node_process3.default.stdin;
|
|
2314
|
+
const stdout = options.stdout ?? import_node_process3.default.stdout;
|
|
1894
2315
|
if (!stdin || !stdout)
|
|
1895
2316
|
throw new Error("createStdinDriver requires Node process.stdin/stdout");
|
|
2317
|
+
const env = options.env ?? import_node_process3.default.env ?? {};
|
|
1896
2318
|
const enableMouse = options.enableMouse ?? true;
|
|
1897
2319
|
const enableMouseMotion = options.enableMouseMotion ?? false;
|
|
2320
|
+
const keyboardProtocol = resolveKeyboardProtocol({
|
|
2321
|
+
keyboardProtocol: options.keyboardProtocol,
|
|
2322
|
+
env
|
|
2323
|
+
});
|
|
2324
|
+
const keyboardProtocolSequences = getKeyboardProtocolSequences(keyboardProtocol);
|
|
1898
2325
|
let disposed = false;
|
|
1899
2326
|
let swallowNextLF = false;
|
|
1900
2327
|
let lastMouseDown = null;
|
|
@@ -1903,61 +2330,69 @@ function createStdinDriver(options) {
|
|
|
1903
2330
|
timeout: 50,
|
|
1904
2331
|
// When mouse tracking is enabled, CSI mouse reports are frequent and we really want to avoid
|
|
1905
2332
|
// leaking "[<...;...;...M" into focused inputs if the leading ESC gets chunk-split.
|
|
1906
|
-
// Keep this
|
|
1907
|
-
|
|
2333
|
+
// Keep this well below one frame so plain Esc remains responsive while the
|
|
2334
|
+
// stdin buffer rescue path still covers delayed CSI continuations.
|
|
2335
|
+
escTimeout: enableMouse ? 8 : 6
|
|
1908
2336
|
});
|
|
1909
|
-
const
|
|
2337
|
+
const latency = getCliLatencyProfiler();
|
|
2338
|
+
const dispatchEvent = (event, parser) => {
|
|
1910
2339
|
var _a2;
|
|
2340
|
+
latency == null ? void 0 : latency.recordStdinDispatch(event, { parser });
|
|
2341
|
+
const prevented = Boolean(options.dispatch(event));
|
|
2342
|
+
if (isUnhandledCtrlC(event) && !prevented)
|
|
2343
|
+
(_a2 = options.onExit) == null ? void 0 : _a2.call(options);
|
|
2344
|
+
return prevented;
|
|
2345
|
+
};
|
|
2346
|
+
const handlePlainChar = (ch) => {
|
|
1911
2347
|
if (swallowNextLF) {
|
|
1912
2348
|
swallowNextLF = false;
|
|
1913
2349
|
if (ch === "\n")
|
|
1914
2350
|
return;
|
|
1915
2351
|
}
|
|
1916
2352
|
if (ch === "") {
|
|
1917
|
-
|
|
1918
|
-
options.dispatch(keyEvent("c", "", { ctrlKey: true }))
|
|
1919
|
-
);
|
|
1920
|
-
if (!prevented)
|
|
1921
|
-
(_a2 = options.onExit) == null ? void 0 : _a2.call(options);
|
|
2353
|
+
dispatchEvent(keyEvent("c", "", { ctrlKey: true }), "plain");
|
|
1922
2354
|
return;
|
|
1923
2355
|
}
|
|
1924
2356
|
if (ch === "\r") {
|
|
1925
2357
|
swallowNextLF = true;
|
|
1926
|
-
|
|
2358
|
+
dispatchEvent(keyEvent("Enter", "Enter"), "plain");
|
|
1927
2359
|
return;
|
|
1928
2360
|
}
|
|
1929
2361
|
if (ch === "\n") {
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
2362
|
+
dispatchEvent(
|
|
2363
|
+
{
|
|
2364
|
+
type: "input",
|
|
2365
|
+
data: "\n",
|
|
2366
|
+
inputType: "insertLineBreak",
|
|
2367
|
+
text: "\n"
|
|
2368
|
+
},
|
|
2369
|
+
"plain"
|
|
2370
|
+
);
|
|
1936
2371
|
return;
|
|
1937
2372
|
}
|
|
1938
2373
|
const ctrlKey = ctrlKeyFromChar(ch);
|
|
1939
2374
|
if (ctrlKey) {
|
|
1940
2375
|
if (ctrlKey === "i") {
|
|
1941
|
-
|
|
2376
|
+
dispatchEvent(keyEvent("Tab", "Tab"), "plain");
|
|
1942
2377
|
return;
|
|
1943
2378
|
}
|
|
1944
2379
|
if (ctrlKey === "h") {
|
|
1945
|
-
|
|
2380
|
+
dispatchEvent(keyEvent("Backspace", "Backspace"), "plain");
|
|
1946
2381
|
return;
|
|
1947
2382
|
}
|
|
1948
|
-
|
|
2383
|
+
dispatchEvent(keyEvent(ctrlKey, "", { ctrlKey: true }), "plain");
|
|
1949
2384
|
return;
|
|
1950
2385
|
}
|
|
1951
2386
|
if (ch === "\x7F") {
|
|
1952
|
-
|
|
2387
|
+
dispatchEvent(keyEvent("Backspace", "Backspace"), "plain");
|
|
1953
2388
|
return;
|
|
1954
2389
|
}
|
|
1955
2390
|
if (ch === " ") {
|
|
1956
|
-
|
|
2391
|
+
dispatchEvent(keyEvent("Tab", "Tab"), "plain");
|
|
1957
2392
|
return;
|
|
1958
2393
|
}
|
|
1959
2394
|
if (isPrintable(ch))
|
|
1960
|
-
|
|
2395
|
+
dispatchEvent(keyEvent(ch), "plain");
|
|
1961
2396
|
};
|
|
1962
2397
|
const handleMouseEvent = (event) => {
|
|
1963
2398
|
const ev = event;
|
|
@@ -2039,22 +2474,22 @@ function createStdinDriver(options) {
|
|
|
2039
2474
|
const kitty = parseKittySequence(sequence);
|
|
2040
2475
|
if (kitty.handled) {
|
|
2041
2476
|
if (kitty.event)
|
|
2042
|
-
|
|
2477
|
+
dispatchEvent(kitty.event, "kitty");
|
|
2043
2478
|
return;
|
|
2044
2479
|
}
|
|
2045
2480
|
const legacy = parseLegacySequence(sequence);
|
|
2046
2481
|
if (legacy.handled) {
|
|
2047
2482
|
if (legacy.event)
|
|
2048
|
-
|
|
2483
|
+
dispatchEvent(legacy.event, "legacy");
|
|
2049
2484
|
return;
|
|
2050
2485
|
}
|
|
2051
2486
|
if (sequence.startsWith("\x1B")) {
|
|
2052
2487
|
if (sequence.length === 2 && isPrintable(sequence[1])) {
|
|
2053
|
-
|
|
2488
|
+
dispatchEvent(keyEvent(sequence[1], "", { altKey: true }), "alt");
|
|
2054
2489
|
return;
|
|
2055
2490
|
}
|
|
2056
2491
|
if (sequence === "\x1B") {
|
|
2057
|
-
|
|
2492
|
+
dispatchEvent(keyEvent("Escape", "Escape"), "escape");
|
|
2058
2493
|
return;
|
|
2059
2494
|
}
|
|
2060
2495
|
return;
|
|
@@ -2066,7 +2501,7 @@ function createStdinDriver(options) {
|
|
|
2066
2501
|
stdinBuffer.on("paste", (data) => {
|
|
2067
2502
|
const pastedText = normalizeNewlines(data);
|
|
2068
2503
|
if (pastedText)
|
|
2069
|
-
|
|
2504
|
+
dispatchEvent({ type: "paste", text: pastedText }, "paste");
|
|
2070
2505
|
});
|
|
2071
2506
|
const decodeBytes = (bytes) => {
|
|
2072
2507
|
if (bytes.length === 1 && bytes[0] > 127) {
|
|
@@ -2081,6 +2516,7 @@ function createStdinDriver(options) {
|
|
|
2081
2516
|
const onData = (chunk) => {
|
|
2082
2517
|
if (disposed)
|
|
2083
2518
|
return;
|
|
2519
|
+
latency == null ? void 0 : latency.recordRawInput();
|
|
2084
2520
|
if (typeof chunk === "string") {
|
|
2085
2521
|
stdinBuffer.process(chunk);
|
|
2086
2522
|
return;
|
|
@@ -2111,6 +2547,8 @@ function createStdinDriver(options) {
|
|
|
2111
2547
|
if (stdout.isTTY) {
|
|
2112
2548
|
stdout.write("\x1B[?2004h");
|
|
2113
2549
|
stdout.write("\x1B[?1004h");
|
|
2550
|
+
if (keyboardProtocolSequences)
|
|
2551
|
+
stdout.write(keyboardProtocolSequences.enable);
|
|
2114
2552
|
if (enableMouse) {
|
|
2115
2553
|
stdout.write("\x1B[?1007h");
|
|
2116
2554
|
if (enableMouseMotion)
|
|
@@ -2140,6 +2578,8 @@ function createStdinDriver(options) {
|
|
|
2140
2578
|
if (stdout.isTTY) {
|
|
2141
2579
|
stdout.write("\x1B[?2004l");
|
|
2142
2580
|
stdout.write("\x1B[?1004l");
|
|
2581
|
+
if (keyboardProtocolSequences)
|
|
2582
|
+
stdout.write(keyboardProtocolSequences.disable);
|
|
2143
2583
|
if (enableMouse) {
|
|
2144
2584
|
stdout.write("\x1B[?1007l");
|
|
2145
2585
|
if (enableMouseMotion)
|
|
@@ -2662,12 +3102,53 @@ function createGridBuffer(cols, rows) {
|
|
|
2662
3102
|
cursorStyle: DEFAULT_STYLE,
|
|
2663
3103
|
scrollback: [],
|
|
2664
3104
|
scrollbackLimit: 1e3,
|
|
2665
|
-
rowPool: []
|
|
3105
|
+
rowPool: [],
|
|
3106
|
+
soaFingerprints: null,
|
|
3107
|
+
fingerprintFn: null
|
|
2666
3108
|
};
|
|
2667
3109
|
}
|
|
2668
3110
|
function clamp(n, min, max) {
|
|
2669
3111
|
return Math.max(min, Math.min(max, n));
|
|
2670
3112
|
}
|
|
3113
|
+
function setFingerprintFn(buffer, fn) {
|
|
3114
|
+
buffer.fingerprintFn = fn;
|
|
3115
|
+
const len = buffer.rows * buffer.cols;
|
|
3116
|
+
if (!len) {
|
|
3117
|
+
buffer.soaFingerprints = null;
|
|
3118
|
+
return;
|
|
3119
|
+
}
|
|
3120
|
+
buffer.soaFingerprints = new Uint32Array(len);
|
|
3121
|
+
for (let y = 0; y < buffer.rows; y++) {
|
|
3122
|
+
const row = getBufferRow(buffer, y);
|
|
3123
|
+
const physY = physicalRowIndex(buffer, y);
|
|
3124
|
+
const base = physY * buffer.cols;
|
|
3125
|
+
for (let x = 0; x < buffer.cols; x++) {
|
|
3126
|
+
const cell = row[x];
|
|
3127
|
+
buffer.soaFingerprints[base + x] = fn(cell.ch, cell.style);
|
|
3128
|
+
}
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
function getRowFingerprints(buffer, y) {
|
|
3132
|
+
if (!buffer.soaFingerprints)
|
|
3133
|
+
return null;
|
|
3134
|
+
const physY = physicalRowIndex(buffer, y);
|
|
3135
|
+
const base = physY * buffer.cols;
|
|
3136
|
+
return buffer.soaFingerprints.subarray(base, base + buffer.cols);
|
|
3137
|
+
}
|
|
3138
|
+
function updateCellFingerprint(buffer, physY, x, ch, style) {
|
|
3139
|
+
if (!buffer.soaFingerprints || !buffer.fingerprintFn)
|
|
3140
|
+
return;
|
|
3141
|
+
buffer.soaFingerprints[physY * buffer.cols + x] = buffer.fingerprintFn(ch, style);
|
|
3142
|
+
}
|
|
3143
|
+
function updateRangeFingerprint(buffer, physY, x0, x1, ch, style) {
|
|
3144
|
+
if (!buffer.soaFingerprints || !buffer.fingerprintFn)
|
|
3145
|
+
return;
|
|
3146
|
+
const fp = buffer.fingerprintFn(ch, style);
|
|
3147
|
+
const base = physY * buffer.cols;
|
|
3148
|
+
for (let x = x0; x < x1; x++) {
|
|
3149
|
+
buffer.soaFingerprints[base + x] = fp;
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
2671
3152
|
function physicalRowIndex(buffer, y) {
|
|
2672
3153
|
return (buffer.gridStart + y) % buffer.rows;
|
|
2673
3154
|
}
|
|
@@ -2740,9 +3221,17 @@ function putCell(buffer, x, y, ch, style) {
|
|
|
2740
3221
|
markDirty(buffer, y);
|
|
2741
3222
|
return;
|
|
2742
3223
|
}
|
|
2743
|
-
|
|
3224
|
+
const cell = createCell(ch, style);
|
|
3225
|
+
row[x] = cell;
|
|
2744
3226
|
if (width === 2 && x + 1 < buffer.cols)
|
|
2745
3227
|
row[x + 1] = createContinuationCell(style);
|
|
3228
|
+
if (buffer.soaFingerprints) {
|
|
3229
|
+
const physY = physicalRowIndex(buffer, y);
|
|
3230
|
+
updateCellFingerprint(buffer, physY, x, cell.ch, cell.style);
|
|
3231
|
+
if (width === 2 && x + 1 < buffer.cols) {
|
|
3232
|
+
updateCellFingerprint(buffer, physY, x + 1, "", cell.style);
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
2746
3235
|
markDirty(buffer, y);
|
|
2747
3236
|
}
|
|
2748
3237
|
function fillRect(buffer, x, y, w, h18, ch = " ", style) {
|
|
@@ -2766,6 +3255,10 @@ function fillRect(buffer, x, y, w, h18, ch = " ", style) {
|
|
|
2766
3255
|
row.fill(fillCell, x0, x1);
|
|
2767
3256
|
if (x1 < buffer.cols && ((_b2 = row[x1]) == null ? void 0 : _b2.continuation))
|
|
2768
3257
|
row[x1] = blank;
|
|
3258
|
+
if (buffer.soaFingerprints) {
|
|
3259
|
+
const physY = physicalRowIndex(buffer, yy);
|
|
3260
|
+
updateRangeFingerprint(buffer, physY, x0, x1, fillCell.ch, fillCell.style);
|
|
3261
|
+
}
|
|
2769
3262
|
markDirty(buffer, yy);
|
|
2770
3263
|
}
|
|
2771
3264
|
return;
|
|
@@ -2834,6 +3327,19 @@ function blankRow(buffer) {
|
|
|
2834
3327
|
pooled[x] = blank;
|
|
2835
3328
|
return pooled;
|
|
2836
3329
|
}
|
|
3330
|
+
function recomputeFingerprintsForRows(buffer, startY, endY) {
|
|
3331
|
+
if (!buffer.soaFingerprints || !buffer.fingerprintFn)
|
|
3332
|
+
return;
|
|
3333
|
+
for (let y = startY; y < endY; y++) {
|
|
3334
|
+
const row = getBufferRow(buffer, y);
|
|
3335
|
+
const physY = physicalRowIndex(buffer, y);
|
|
3336
|
+
const base = physY * buffer.cols;
|
|
3337
|
+
for (let x = 0; x < buffer.cols; x++) {
|
|
3338
|
+
const cell = row[x];
|
|
3339
|
+
buffer.soaFingerprints[base + x] = buffer.fingerprintFn(cell.ch, cell.style);
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
2837
3343
|
function scrollBuffer(buffer, lines) {
|
|
2838
3344
|
const n = Math.trunc(lines);
|
|
2839
3345
|
if (n === 0 || buffer.rows === 0)
|
|
@@ -2868,6 +3374,70 @@ function scrollBuffer(buffer, lines) {
|
|
|
2868
3374
|
markAllDirty(buffer);
|
|
2869
3375
|
buffer.cursorY = clamp(buffer.cursorY - n, 0, Math.max(0, buffer.rows - 1));
|
|
2870
3376
|
}
|
|
3377
|
+
function scrollBufferRegion(buffer, startY, endY, lines) {
|
|
3378
|
+
const n = Math.trunc(lines);
|
|
3379
|
+
if (n === 0 || buffer.rows === 0)
|
|
3380
|
+
return [];
|
|
3381
|
+
const start = clamp(Math.floor(startY), 0, buffer.rows);
|
|
3382
|
+
const end = clamp(Math.floor(endY), 0, buffer.rows);
|
|
3383
|
+
const height = end - start;
|
|
3384
|
+
if (height <= 0)
|
|
3385
|
+
return [];
|
|
3386
|
+
const absDelta = Math.abs(n);
|
|
3387
|
+
const insertedRows = [];
|
|
3388
|
+
const replaceRegionWithBlankRows = () => {
|
|
3389
|
+
for (let y = start; y < end; y++) {
|
|
3390
|
+
const physY = physicalRowIndex(buffer, y);
|
|
3391
|
+
buffer.rowPool.push(buffer.grid[physY]);
|
|
3392
|
+
buffer.grid[physY] = blankRow(buffer);
|
|
3393
|
+
markDirty(buffer, y);
|
|
3394
|
+
insertedRows.push(y);
|
|
3395
|
+
}
|
|
3396
|
+
};
|
|
3397
|
+
if (absDelta >= height) {
|
|
3398
|
+
replaceRegionWithBlankRows();
|
|
3399
|
+
recomputeFingerprintsForRows(buffer, start, end);
|
|
3400
|
+
if (buffer.cursorY >= start && buffer.cursorY < end)
|
|
3401
|
+
buffer.cursorY = clamp(buffer.cursorY - n, start, Math.max(start, end - 1));
|
|
3402
|
+
return insertedRows;
|
|
3403
|
+
}
|
|
3404
|
+
const regionRows = [];
|
|
3405
|
+
for (let y = start; y < end; y++)
|
|
3406
|
+
regionRows.push(getBufferRow(buffer, y));
|
|
3407
|
+
const nextRows = Array.from({ length: height }, () => []);
|
|
3408
|
+
if (n > 0) {
|
|
3409
|
+
const movedCount = height - n;
|
|
3410
|
+
for (let i = 0; i < movedCount; i++)
|
|
3411
|
+
nextRows[i] = regionRows[i + n];
|
|
3412
|
+
for (let i = 0; i < n; i++) {
|
|
3413
|
+
buffer.rowPool.push(regionRows[i]);
|
|
3414
|
+
const y = end - n + i;
|
|
3415
|
+
nextRows[movedCount + i] = blankRow(buffer);
|
|
3416
|
+
markDirty(buffer, y);
|
|
3417
|
+
insertedRows.push(y);
|
|
3418
|
+
}
|
|
3419
|
+
} else {
|
|
3420
|
+
const insertedCount = -n;
|
|
3421
|
+
const movedCount = height - insertedCount;
|
|
3422
|
+
for (let i = 0; i < insertedCount; i++) {
|
|
3423
|
+
buffer.rowPool.push(regionRows[height - insertedCount + i]);
|
|
3424
|
+
const y = start + i;
|
|
3425
|
+
nextRows[i] = blankRow(buffer);
|
|
3426
|
+
markDirty(buffer, y);
|
|
3427
|
+
insertedRows.push(y);
|
|
3428
|
+
}
|
|
3429
|
+
for (let i = 0; i < movedCount; i++)
|
|
3430
|
+
nextRows[insertedCount + i] = regionRows[i];
|
|
3431
|
+
}
|
|
3432
|
+
for (let i = 0; i < height; i++) {
|
|
3433
|
+
const physY = physicalRowIndex(buffer, start + i);
|
|
3434
|
+
buffer.grid[physY] = nextRows[i];
|
|
3435
|
+
}
|
|
3436
|
+
recomputeFingerprintsForRows(buffer, start, end);
|
|
3437
|
+
if (buffer.cursorY >= start && buffer.cursorY < end)
|
|
3438
|
+
buffer.cursorY = clamp(buffer.cursorY - n, start, Math.max(start, end - 1));
|
|
3439
|
+
return insertedRows;
|
|
3440
|
+
}
|
|
2871
3441
|
function resizeBuffer(buffer, cols, rows) {
|
|
2872
3442
|
var _a2;
|
|
2873
3443
|
const nextCols = Math.max(0, Math.floor(cols));
|
|
@@ -2904,6 +3474,22 @@ function resizeBuffer(buffer, cols, rows) {
|
|
|
2904
3474
|
buffer.dirtyAll = nextRows > 0;
|
|
2905
3475
|
buffer.cursorX = clamp(buffer.cursorX, 0, Math.max(0, nextCols));
|
|
2906
3476
|
buffer.cursorY = clamp(buffer.cursorY, 0, Math.max(0, nextRows - 1));
|
|
3477
|
+
if (buffer.fingerprintFn) {
|
|
3478
|
+
const len = nextRows * nextCols;
|
|
3479
|
+
if (len > 0) {
|
|
3480
|
+
buffer.soaFingerprints = new Uint32Array(len);
|
|
3481
|
+
for (let y = 0; y < nextRows; y++) {
|
|
3482
|
+
const row = nextGrid[y];
|
|
3483
|
+
const base = y * nextCols;
|
|
3484
|
+
for (let x = 0; x < nextCols; x++) {
|
|
3485
|
+
const cell = row[x];
|
|
3486
|
+
buffer.soaFingerprints[base + x] = buffer.fingerprintFn(cell.ch, cell.style);
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
} else {
|
|
3490
|
+
buffer.soaFingerprints = null;
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
2907
3493
|
}
|
|
2908
3494
|
function snapshotText(buffer) {
|
|
2909
3495
|
const out = [];
|
|
@@ -3092,6 +3678,40 @@ function scrollPlaneCoverage(state, lines) {
|
|
|
3092
3678
|
for (let i = 0; i < -n; i++)
|
|
3093
3679
|
state.coverage.unshift(new Uint8Array(cols));
|
|
3094
3680
|
}
|
|
3681
|
+
function scrollPlaneCoverageRegion(state, startY, endY, lines) {
|
|
3682
|
+
const n = Math.trunc(lines);
|
|
3683
|
+
if (n === 0 || state.coverage.length === 0)
|
|
3684
|
+
return;
|
|
3685
|
+
const start = Math.max(0, Math.min(state.coverage.length, Math.floor(startY)));
|
|
3686
|
+
const end = Math.max(0, Math.min(state.coverage.length, Math.floor(endY)));
|
|
3687
|
+
const height = end - start;
|
|
3688
|
+
if (height <= 0)
|
|
3689
|
+
return;
|
|
3690
|
+
const cols = state.buffer.cols;
|
|
3691
|
+
if (Math.abs(n) >= height) {
|
|
3692
|
+
for (let y = start; y < end; y++)
|
|
3693
|
+
state.coverage[y] = new Uint8Array(cols);
|
|
3694
|
+
return;
|
|
3695
|
+
}
|
|
3696
|
+
const region = state.coverage.slice(start, end);
|
|
3697
|
+
const next = Array.from({ length: height }, () => new Uint8Array(0));
|
|
3698
|
+
if (n > 0) {
|
|
3699
|
+
const movedCount = height - n;
|
|
3700
|
+
for (let i = 0; i < movedCount; i++)
|
|
3701
|
+
next[i] = region[i + n];
|
|
3702
|
+
for (let i = 0; i < n; i++)
|
|
3703
|
+
next[movedCount + i] = new Uint8Array(cols);
|
|
3704
|
+
} else {
|
|
3705
|
+
const insertedCount = -n;
|
|
3706
|
+
const movedCount = height - insertedCount;
|
|
3707
|
+
for (let i = 0; i < insertedCount; i++)
|
|
3708
|
+
next[i] = new Uint8Array(cols);
|
|
3709
|
+
for (let i = 0; i < movedCount; i++)
|
|
3710
|
+
next[insertedCount + i] = region[i];
|
|
3711
|
+
}
|
|
3712
|
+
for (let i = 0; i < height; i++)
|
|
3713
|
+
state.coverage[start + i] = next[i];
|
|
3714
|
+
}
|
|
3095
3715
|
function resizePlaneState(state, cols, rows) {
|
|
3096
3716
|
resizeBuffer(state.buffer, cols, rows);
|
|
3097
3717
|
state.coverage = resizeCoverage(state.coverage, state.buffer.cols, state.buffer.rows);
|
|
@@ -3127,6 +3747,14 @@ function resetPlaneRowsForRender(terminal, plane, dirtyRows) {
|
|
|
3127
3747
|
const internals = terminal[TERMINAL_PLANE_INTERNALS];
|
|
3128
3748
|
internals == null ? void 0 : internals.resetRowsForRender(plane, dirtyRows);
|
|
3129
3749
|
}
|
|
3750
|
+
function getPlaneRowCoverageKind(terminal, plane, y) {
|
|
3751
|
+
const internals = terminal[TERMINAL_PLANE_INTERNALS];
|
|
3752
|
+
return (internals == null ? void 0 : internals.getRowCoverageKind(plane, y)) ?? 0;
|
|
3753
|
+
}
|
|
3754
|
+
function scrollPlaneRows(terminal, plane, startY, endY, lines) {
|
|
3755
|
+
const internals = terminal[TERMINAL_PLANE_INTERNALS];
|
|
3756
|
+
internals == null ? void 0 : internals.scrollRows(plane, startY, endY, lines);
|
|
3757
|
+
}
|
|
3130
3758
|
function createTerminal(opts) {
|
|
3131
3759
|
const emitter = new Emitter();
|
|
3132
3760
|
const compositeBuffer = createGridBuffer(opts.cols, opts.rows);
|
|
@@ -3136,6 +3764,7 @@ function createTerminal(opts) {
|
|
|
3136
3764
|
let pendingCommit = false;
|
|
3137
3765
|
let pendingCommitAllPlanes = false;
|
|
3138
3766
|
let pendingCommitPlanes = null;
|
|
3767
|
+
const pendingPlaneScrollOps = /* @__PURE__ */ new Map();
|
|
3139
3768
|
const planeTerminals = /* @__PURE__ */ new Map();
|
|
3140
3769
|
let base;
|
|
3141
3770
|
compositeBuffer.cursorVisible = false;
|
|
@@ -3274,8 +3903,171 @@ function createTerminal(opts) {
|
|
|
3274
3903
|
scrollBuffer(state.buffer, lines);
|
|
3275
3904
|
scrollPlaneCoverage(state, lines);
|
|
3276
3905
|
}
|
|
3906
|
+
function normalizeScrollOperation(startY, endY, delta, totalRows) {
|
|
3907
|
+
const start = Math.max(0, Math.min(totalRows, Math.floor(startY)));
|
|
3908
|
+
const end = Math.max(0, Math.min(totalRows, Math.floor(endY)));
|
|
3909
|
+
const height = end - start;
|
|
3910
|
+
const lines = Math.trunc(delta);
|
|
3911
|
+
if (height <= 0 || lines === 0 || Math.abs(lines) >= height)
|
|
3912
|
+
return null;
|
|
3913
|
+
return { startY: start, endY: end, delta: lines };
|
|
3914
|
+
}
|
|
3915
|
+
function recordPendingScrollOp(plane, op) {
|
|
3916
|
+
const prev = pendingPlaneScrollOps.get(plane);
|
|
3917
|
+
if (prev && prev.startY === op.startY && prev.endY === op.endY) {
|
|
3918
|
+
const nextDelta = prev.delta + op.delta;
|
|
3919
|
+
if (nextDelta === 0) {
|
|
3920
|
+
pendingPlaneScrollOps.delete(plane);
|
|
3921
|
+
return;
|
|
3922
|
+
}
|
|
3923
|
+
const next = normalizeScrollOperation(
|
|
3924
|
+
op.startY,
|
|
3925
|
+
op.endY,
|
|
3926
|
+
nextDelta,
|
|
3927
|
+
compositeBuffer.rows
|
|
3928
|
+
);
|
|
3929
|
+
if (!next) {
|
|
3930
|
+
pendingPlaneScrollOps.delete(plane);
|
|
3931
|
+
return;
|
|
3932
|
+
}
|
|
3933
|
+
pendingPlaneScrollOps.set(plane, next);
|
|
3934
|
+
return;
|
|
3935
|
+
}
|
|
3936
|
+
pendingPlaneScrollOps.set(plane, op);
|
|
3937
|
+
}
|
|
3938
|
+
function takePendingScrollOps(planes) {
|
|
3939
|
+
const planesToTake = (planes == null ? void 0 : planes.length) ? planes : TERMINAL_RENDER_PLANES;
|
|
3940
|
+
const out = [];
|
|
3941
|
+
for (const plane of planesToTake) {
|
|
3942
|
+
const op = pendingPlaneScrollOps.get(plane);
|
|
3943
|
+
if (!op)
|
|
3944
|
+
continue;
|
|
3945
|
+
pendingPlaneScrollOps.delete(plane);
|
|
3946
|
+
out.push({ plane, ...op });
|
|
3947
|
+
}
|
|
3948
|
+
return out.length ? out : null;
|
|
3949
|
+
}
|
|
3950
|
+
function higherPlanesFor(plane) {
|
|
3951
|
+
const planeIndex = TERMINAL_RENDER_PLANES.indexOf(plane);
|
|
3952
|
+
if (planeIndex < 0)
|
|
3953
|
+
return [];
|
|
3954
|
+
return TERMINAL_RENDER_PLANES.slice(planeIndex + 1);
|
|
3955
|
+
}
|
|
3956
|
+
function higherPlaneCoverageKind(plane, y) {
|
|
3957
|
+
var _a2;
|
|
3958
|
+
const higherPlanes = higherPlanesFor(plane);
|
|
3959
|
+
if (!higherPlanes.length || y < 0 || y >= compositeBuffer.rows)
|
|
3960
|
+
return 0;
|
|
3961
|
+
let covered = 0;
|
|
3962
|
+
for (let x = 0; x < compositeBuffer.cols; x++) {
|
|
3963
|
+
let cellCovered = false;
|
|
3964
|
+
for (const higherPlane of higherPlanes) {
|
|
3965
|
+
const state = planeStates.get(higherPlane);
|
|
3966
|
+
if ((_a2 = state == null ? void 0 : state.coverage[y]) == null ? void 0 : _a2[x]) {
|
|
3967
|
+
cellCovered = true;
|
|
3968
|
+
break;
|
|
3969
|
+
}
|
|
3970
|
+
}
|
|
3971
|
+
if (cellCovered)
|
|
3972
|
+
covered++;
|
|
3973
|
+
}
|
|
3974
|
+
if (covered === 0)
|
|
3975
|
+
return 0;
|
|
3976
|
+
if (covered >= compositeBuffer.cols)
|
|
3977
|
+
return 2;
|
|
3978
|
+
return 1;
|
|
3979
|
+
}
|
|
3980
|
+
function prepareCompositeScrollOps(pendingOps) {
|
|
3981
|
+
if (!(pendingOps == null ? void 0 : pendingOps.length)) {
|
|
3982
|
+
return {
|
|
3983
|
+
scrollOperations: null,
|
|
3984
|
+
extraDirtyRows: []
|
|
3985
|
+
};
|
|
3986
|
+
}
|
|
3987
|
+
const scrollOperations = [];
|
|
3988
|
+
const extraDirtyRows = /* @__PURE__ */ new Set();
|
|
3989
|
+
for (const pending of pendingOps) {
|
|
3990
|
+
const blockedRows = /* @__PURE__ */ new Set();
|
|
3991
|
+
const partiallyBlockedRows = /* @__PURE__ */ new Set();
|
|
3992
|
+
for (let y = pending.startY; y < pending.endY; y++) {
|
|
3993
|
+
const coverageKind = higherPlaneCoverageKind(pending.plane, y);
|
|
3994
|
+
if (coverageKind === 0)
|
|
3995
|
+
continue;
|
|
3996
|
+
blockedRows.add(y);
|
|
3997
|
+
if (coverageKind === 1)
|
|
3998
|
+
partiallyBlockedRows.add(y);
|
|
3999
|
+
}
|
|
4000
|
+
if (!blockedRows.size) {
|
|
4001
|
+
scrollOperations.push({
|
|
4002
|
+
startY: pending.startY,
|
|
4003
|
+
endY: pending.endY,
|
|
4004
|
+
delta: pending.delta
|
|
4005
|
+
});
|
|
4006
|
+
continue;
|
|
4007
|
+
}
|
|
4008
|
+
const absDelta = Math.abs(pending.delta);
|
|
4009
|
+
for (let y = pending.startY; y < pending.endY; y++) {
|
|
4010
|
+
if (partiallyBlockedRows.has(y))
|
|
4011
|
+
extraDirtyRows.add(y);
|
|
4012
|
+
}
|
|
4013
|
+
let bandStart = -1;
|
|
4014
|
+
const flushBand = (bandEnd) => {
|
|
4015
|
+
if (bandStart < 0 || bandEnd <= bandStart)
|
|
4016
|
+
return;
|
|
4017
|
+
const bandHeight = bandEnd - bandStart;
|
|
4018
|
+
if (absDelta >= bandHeight) {
|
|
4019
|
+
for (let y = bandStart; y < bandEnd; y++)
|
|
4020
|
+
extraDirtyRows.add(y);
|
|
4021
|
+
bandStart = -1;
|
|
4022
|
+
return;
|
|
4023
|
+
}
|
|
4024
|
+
scrollOperations.push({
|
|
4025
|
+
startY: bandStart,
|
|
4026
|
+
endY: bandEnd,
|
|
4027
|
+
delta: pending.delta
|
|
4028
|
+
});
|
|
4029
|
+
if (pending.delta > 0) {
|
|
4030
|
+
for (let y = bandEnd - absDelta; y < bandEnd; y++)
|
|
4031
|
+
extraDirtyRows.add(y);
|
|
4032
|
+
} else {
|
|
4033
|
+
for (let y = bandStart; y < bandStart + absDelta; y++)
|
|
4034
|
+
extraDirtyRows.add(y);
|
|
4035
|
+
}
|
|
4036
|
+
bandStart = -1;
|
|
4037
|
+
};
|
|
4038
|
+
for (let y = pending.startY; y < pending.endY; y++) {
|
|
4039
|
+
if (blockedRows.has(y)) {
|
|
4040
|
+
flushBand(y);
|
|
4041
|
+
continue;
|
|
4042
|
+
}
|
|
4043
|
+
if (bandStart < 0)
|
|
4044
|
+
bandStart = y;
|
|
4045
|
+
}
|
|
4046
|
+
flushBand(pending.endY);
|
|
4047
|
+
}
|
|
4048
|
+
return {
|
|
4049
|
+
scrollOperations: scrollOperations.length ? scrollOperations : null,
|
|
4050
|
+
extraDirtyRows: Array.from(extraDirtyRows).sort((a, b) => a - b)
|
|
4051
|
+
};
|
|
4052
|
+
}
|
|
4053
|
+
function scrollRowsForPlane(plane, startY, endY, lines) {
|
|
4054
|
+
const state = getPlaneState(plane);
|
|
4055
|
+
const op = normalizeScrollOperation(
|
|
4056
|
+
startY,
|
|
4057
|
+
endY,
|
|
4058
|
+
lines,
|
|
4059
|
+
state.buffer.rows
|
|
4060
|
+
);
|
|
4061
|
+
if (!op)
|
|
4062
|
+
return;
|
|
4063
|
+
scrollBufferRegion(state.buffer, op.startY, op.endY, op.delta);
|
|
4064
|
+
scrollPlaneCoverageRegion(state, op.startY, op.endY, op.delta);
|
|
4065
|
+
recordPendingScrollOp(plane, op);
|
|
4066
|
+
}
|
|
3277
4067
|
function composeRows(rows) {
|
|
3278
4068
|
const blank = createBlankCell();
|
|
4069
|
+
const fpFn = compositeBuffer.fingerprintFn;
|
|
4070
|
+
const fpArr = compositeBuffer.soaFingerprints;
|
|
3279
4071
|
const rowList = rows ?? Array.from({ length: compositeBuffer.rows }, (_, index) => index);
|
|
3280
4072
|
for (const y of rowList) {
|
|
3281
4073
|
if (y < 0 || y >= compositeBuffer.rows)
|
|
@@ -3310,6 +4102,14 @@ function createTerminal(opts) {
|
|
|
3310
4102
|
}
|
|
3311
4103
|
}
|
|
3312
4104
|
}
|
|
4105
|
+
if (fpFn && fpArr) {
|
|
4106
|
+
const physY = (compositeBuffer.gridStart + y) % compositeBuffer.rows;
|
|
4107
|
+
const base2 = physY * cols;
|
|
4108
|
+
for (let x = 0; x < cols; x++) {
|
|
4109
|
+
const cell = dst[x];
|
|
4110
|
+
fpArr[base2 + x] = fpFn(cell.ch, cell.style);
|
|
4111
|
+
}
|
|
4112
|
+
}
|
|
3313
4113
|
markDirty(compositeBuffer, y);
|
|
3314
4114
|
}
|
|
3315
4115
|
}
|
|
@@ -3506,6 +4306,14 @@ function createTerminal(opts) {
|
|
|
3506
4306
|
return all.slice(
|
|
3507
4307
|
Math.max(0, all.length - Math.max(0, Math.floor(count)))
|
|
3508
4308
|
);
|
|
4309
|
+
},
|
|
4310
|
+
setFingerprintFn(fn) {
|
|
4311
|
+
assertNotDisposed();
|
|
4312
|
+
base.setFingerprintFn(fn);
|
|
4313
|
+
},
|
|
4314
|
+
getRowFingerprints(y) {
|
|
4315
|
+
assertNotDisposed();
|
|
4316
|
+
return base.getRowFingerprints(y);
|
|
3509
4317
|
}
|
|
3510
4318
|
};
|
|
3511
4319
|
planeTerminals.set(plane, api);
|
|
@@ -3580,6 +4388,9 @@ function createTerminal(opts) {
|
|
|
3580
4388
|
return pendingDirtyRowsForPlanes((meta == null ? void 0 : meta.planes) ?? null);
|
|
3581
4389
|
}
|
|
3582
4390
|
const planesToCompose = ((_b2 = meta == null ? void 0 : meta.planes) == null ? void 0 : _b2.length) ? meta.planes : TERMINAL_RENDER_PLANES;
|
|
4391
|
+
const pendingScrollOps = takePendingScrollOps(planesToCompose);
|
|
4392
|
+
const preparedScroll = prepareCompositeScrollOps(pendingScrollOps);
|
|
4393
|
+
const scrollOperations = preparedScroll.scrollOperations;
|
|
3583
4394
|
let composeAllRows = false;
|
|
3584
4395
|
const dirtyRows = /* @__PURE__ */ new Set();
|
|
3585
4396
|
for (const plane of planesToCompose) {
|
|
@@ -3594,12 +4405,23 @@ function createTerminal(opts) {
|
|
|
3594
4405
|
for (const y of rows)
|
|
3595
4406
|
dirtyRows.add(y);
|
|
3596
4407
|
}
|
|
4408
|
+
for (const y of preparedScroll.extraDirtyRows)
|
|
4409
|
+
dirtyRows.add(y);
|
|
3597
4410
|
const normalizedDirtyRows = composeAllRows ? null : Array.from(dirtyRows).sort((a, b) => a - b);
|
|
4411
|
+
if (scrollOperations) {
|
|
4412
|
+
for (const op of scrollOperations)
|
|
4413
|
+
scrollBufferRegion(compositeBuffer, op.startY, op.endY, op.delta);
|
|
4414
|
+
}
|
|
3598
4415
|
if (normalizedDirtyRows !== null && normalizedDirtyRows.length === 0) {
|
|
3599
4416
|
const pendingCompositeRows = collectAndClearDirtyRows(compositeBuffer);
|
|
3600
4417
|
if (pendingCompositeRows !== null && pendingCompositeRows.length === 0)
|
|
3601
4418
|
return pendingCompositeRows;
|
|
3602
|
-
emitter.emit("commit", {
|
|
4419
|
+
emitter.emit("commit", {
|
|
4420
|
+
dirtyRows: pendingCompositeRows,
|
|
4421
|
+
planes: (meta == null ? void 0 : meta.planes) ?? null,
|
|
4422
|
+
sync: meta == null ? void 0 : meta.sync,
|
|
4423
|
+
scrollOperations
|
|
4424
|
+
});
|
|
3603
4425
|
return pendingCompositeRows;
|
|
3604
4426
|
}
|
|
3605
4427
|
composeRows(normalizedDirtyRows);
|
|
@@ -3609,7 +4431,12 @@ function createTerminal(opts) {
|
|
|
3609
4431
|
const committedRows = collectAndClearDirtyRows(compositeBuffer);
|
|
3610
4432
|
if (committedRows !== null && committedRows.length === 0)
|
|
3611
4433
|
return committedRows;
|
|
3612
|
-
emitter.emit("commit", {
|
|
4434
|
+
emitter.emit("commit", {
|
|
4435
|
+
dirtyRows: committedRows,
|
|
4436
|
+
planes: (meta == null ? void 0 : meta.planes) ?? null,
|
|
4437
|
+
sync: meta == null ? void 0 : meta.sync,
|
|
4438
|
+
scrollOperations
|
|
4439
|
+
});
|
|
3613
4440
|
return committedRows;
|
|
3614
4441
|
},
|
|
3615
4442
|
on(event, cb) {
|
|
@@ -3675,6 +4502,14 @@ function createTerminal(opts) {
|
|
|
3675
4502
|
return all.slice(
|
|
3676
4503
|
Math.max(0, all.length - Math.max(0, Math.floor(count)))
|
|
3677
4504
|
);
|
|
4505
|
+
},
|
|
4506
|
+
setFingerprintFn(fn) {
|
|
4507
|
+
assertNotDisposed();
|
|
4508
|
+
setFingerprintFn(compositeBuffer, fn);
|
|
4509
|
+
},
|
|
4510
|
+
getRowFingerprints(y) {
|
|
4511
|
+
assertNotDisposed();
|
|
4512
|
+
return getRowFingerprints(compositeBuffer, y);
|
|
3678
4513
|
}
|
|
3679
4514
|
};
|
|
3680
4515
|
base[TERMINAL_PLANE_INTERNALS] = {
|
|
@@ -3689,6 +4524,27 @@ function createTerminal(opts) {
|
|
|
3689
4524
|
}
|
|
3690
4525
|
for (const y of rows)
|
|
3691
4526
|
clearPlaneCoverageRow(state, y);
|
|
4527
|
+
},
|
|
4528
|
+
getRowCoverageKind(plane, y) {
|
|
4529
|
+
const state = getPlaneState(plane);
|
|
4530
|
+
if (y < 0 || y >= state.coverage.length)
|
|
4531
|
+
return 0;
|
|
4532
|
+
const row = state.coverage[y];
|
|
4533
|
+
if (!(row == null ? void 0 : row.length))
|
|
4534
|
+
return 0;
|
|
4535
|
+
let covered = 0;
|
|
4536
|
+
for (let x = 0; x < row.length; x++) {
|
|
4537
|
+
if (row[x])
|
|
4538
|
+
covered++;
|
|
4539
|
+
}
|
|
4540
|
+
if (covered === 0)
|
|
4541
|
+
return 0;
|
|
4542
|
+
if (covered >= row.length)
|
|
4543
|
+
return 2;
|
|
4544
|
+
return 1;
|
|
4545
|
+
},
|
|
4546
|
+
scrollRows(plane, startY, endY, lines) {
|
|
4547
|
+
scrollRowsForPlane(plane, startY, endY, lines);
|
|
3692
4548
|
}
|
|
3693
4549
|
};
|
|
3694
4550
|
return base;
|
|
@@ -3797,8 +4653,8 @@ function createHeadlessRoot() {
|
|
|
3797
4653
|
}
|
|
3798
4654
|
|
|
3799
4655
|
// src/events/manager/cli-event-manager.ts
|
|
3800
|
-
var
|
|
3801
|
-
var
|
|
4656
|
+
var import_node_fs3 = require("fs");
|
|
4657
|
+
var import_node_process5 = __toESM(require("process"), 1);
|
|
3802
4658
|
function contains(rect, x, y) {
|
|
3803
4659
|
return x >= rect.x && y >= rect.y && x < rect.x + rect.w && y < rect.y + rect.h;
|
|
3804
4660
|
}
|
|
@@ -3811,7 +4667,7 @@ function area(rect) {
|
|
|
3811
4667
|
function isVisible(node) {
|
|
3812
4668
|
return node.visible !== false;
|
|
3813
4669
|
}
|
|
3814
|
-
function
|
|
4670
|
+
function now2() {
|
|
3815
4671
|
return typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
3816
4672
|
}
|
|
3817
4673
|
function rectRowRange(rect) {
|
|
@@ -3833,6 +4689,7 @@ function createCliEventManager(options) {
|
|
|
3833
4689
|
let hoverPath = [];
|
|
3834
4690
|
const record = options == null ? void 0 : options.record;
|
|
3835
4691
|
const onFocusChange = options == null ? void 0 : options.onFocusChange;
|
|
4692
|
+
const latency = getCliLatencyProfiler();
|
|
3836
4693
|
const MODAL_FOCUS_Z_THRESHOLD = 100;
|
|
3837
4694
|
const MODAL_ROOT_MIN_AREA = 40;
|
|
3838
4695
|
function focusLockTarget() {
|
|
@@ -4014,7 +4871,7 @@ function createCliEventManager(options) {
|
|
|
4014
4871
|
bubbles: true,
|
|
4015
4872
|
cancelable: true,
|
|
4016
4873
|
defaultPrevented: false,
|
|
4017
|
-
timeStamp:
|
|
4874
|
+
timeStamp: now2(),
|
|
4018
4875
|
__stopped: false,
|
|
4019
4876
|
stopPropagation() {
|
|
4020
4877
|
this.__stopped = true;
|
|
@@ -4038,10 +4895,10 @@ function createCliEventManager(options) {
|
|
|
4038
4895
|
handler(event);
|
|
4039
4896
|
} catch (err) {
|
|
4040
4897
|
try {
|
|
4041
|
-
const env = (_a2 =
|
|
4898
|
+
const env = (_a2 = import_node_process5.default) == null ? void 0 : _a2.env;
|
|
4042
4899
|
if ((env == null ? void 0 : env.DIMCODE_DEBUG) === "1") {
|
|
4043
4900
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[1].slice(0, -1);
|
|
4044
|
-
(0,
|
|
4901
|
+
(0, import_node_fs3.appendFileSync)(
|
|
4045
4902
|
"/tmp/goatchain-debug.log",
|
|
4046
4903
|
`[${timestamp}] [EVENT-MGR] ERROR in handler ${node.id}.${handlerKey}: ${err}
|
|
4047
4904
|
`
|
|
@@ -4275,57 +5132,67 @@ function createCliEventManager(options) {
|
|
|
4275
5132
|
},
|
|
4276
5133
|
dispatch(event) {
|
|
4277
5134
|
record == null ? void 0 : record(event);
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
const target = pickTarget(list);
|
|
4285
|
-
if (target == null ? void 0 : target.focusable)
|
|
4286
|
-
setFocus(target.id);
|
|
4287
|
-
capturedId = (target == null ? void 0 : target.id) ?? null;
|
|
4288
|
-
updateHover(target, event);
|
|
4289
|
-
dispatchPointerEvent("pointerdown", event, target);
|
|
4290
|
-
return false;
|
|
4291
|
-
}
|
|
4292
|
-
if (event.type === "pointermove" && capturedId) {
|
|
4293
|
-
const target = nodes.get(capturedId) ?? null;
|
|
4294
|
-
if (!target)
|
|
4295
|
-
return false;
|
|
4296
|
-
updateHover(target, event);
|
|
4297
|
-
const path = ancestorsForTarget(target);
|
|
4298
|
-
const ev = buildPointerEvent("pointermove", path, event);
|
|
4299
|
-
dispatchWithPhases("pointermove", path, target, ev);
|
|
4300
|
-
return ev.defaultPrevented;
|
|
4301
|
-
}
|
|
4302
|
-
if (event.type === "pointermove") {
|
|
4303
|
-
const list = candidatesAt(event.cellX, event.cellY);
|
|
4304
|
-
const target = pickTarget(list);
|
|
4305
|
-
updateHover(target, event);
|
|
4306
|
-
dispatchPointerEvent("pointermove", event, target);
|
|
4307
|
-
return false;
|
|
5135
|
+
latency == null ? void 0 : latency.recordEventDispatchStart(event);
|
|
5136
|
+
let prevented = false;
|
|
5137
|
+
try {
|
|
5138
|
+
if (event.type === "keydown" || event.type === "keyup") {
|
|
5139
|
+
prevented = dispatchToFocused(event.type, event);
|
|
5140
|
+
return prevented;
|
|
4308
5141
|
}
|
|
4309
|
-
if (event.type === "pointerup"
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
5142
|
+
if (event.type === "pointerdown" || event.type === "pointermove" || event.type === "pointerup" || event.type === "click" || event.type === "dblclick" || event.type === "contextmenu" || event.type === "wheel") {
|
|
5143
|
+
if (event.type === "pointerdown") {
|
|
5144
|
+
const list = candidatesAt(event.cellX, event.cellY);
|
|
5145
|
+
const target = pickTarget(list);
|
|
5146
|
+
if (target == null ? void 0 : target.focusable)
|
|
5147
|
+
setFocus(target.id);
|
|
5148
|
+
capturedId = (target == null ? void 0 : target.id) ?? null;
|
|
5149
|
+
updateHover(target, event);
|
|
5150
|
+
dispatchPointerEvent("pointerdown", event, target);
|
|
5151
|
+
return prevented;
|
|
5152
|
+
}
|
|
5153
|
+
if (event.type === "pointermove" && capturedId) {
|
|
5154
|
+
const target = nodes.get(capturedId) ?? null;
|
|
5155
|
+
if (!target)
|
|
5156
|
+
return prevented;
|
|
5157
|
+
updateHover(target, event);
|
|
5158
|
+
const path = ancestorsForTarget(target);
|
|
5159
|
+
const ev = buildPointerEvent("pointermove", path, event);
|
|
5160
|
+
dispatchWithPhases("pointermove", path, target, ev);
|
|
5161
|
+
prevented = ev.defaultPrevented;
|
|
5162
|
+
return prevented;
|
|
5163
|
+
}
|
|
5164
|
+
if (event.type === "pointermove") {
|
|
5165
|
+
const list = candidatesAt(event.cellX, event.cellY);
|
|
5166
|
+
const target = pickTarget(list);
|
|
5167
|
+
updateHover(target, event);
|
|
5168
|
+
dispatchPointerEvent("pointermove", event, target);
|
|
5169
|
+
return prevented;
|
|
5170
|
+
}
|
|
5171
|
+
if (event.type === "pointerup" && capturedId) {
|
|
5172
|
+
const target = nodes.get(capturedId) ?? null;
|
|
5173
|
+
const path = target ? ancestorsForTarget(target) : [];
|
|
5174
|
+
const ev = buildPointerEvent("pointerup", path, event);
|
|
5175
|
+
dispatchWithPhases("pointerup", path, target, ev);
|
|
5176
|
+
capturedId = null;
|
|
5177
|
+
prevented = ev.defaultPrevented;
|
|
5178
|
+
return prevented;
|
|
5179
|
+
}
|
|
5180
|
+
if (event.type === "pointerup") {
|
|
5181
|
+
dispatchPointerEvent("pointerup", event);
|
|
5182
|
+
capturedId = null;
|
|
5183
|
+
return prevented;
|
|
5184
|
+
}
|
|
5185
|
+
dispatchPointerEvent(event.type, event);
|
|
5186
|
+
return prevented;
|
|
4316
5187
|
}
|
|
4317
|
-
if (event.type === "
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
return false;
|
|
5188
|
+
if (event.type === "beforeinput" || event.type === "input" || event.type === "compositionstart" || event.type === "compositionupdate" || event.type === "compositionend" || event.type === "paste") {
|
|
5189
|
+
prevented = dispatchToFocusedText(event.type, event);
|
|
5190
|
+
return prevented;
|
|
4321
5191
|
}
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
if (event.type === "beforeinput" || event.type === "input" || event.type === "compositionstart" || event.type === "compositionupdate" || event.type === "compositionend" || event.type === "paste") {
|
|
4326
|
-
return dispatchToFocusedText(event.type, event);
|
|
5192
|
+
return prevented;
|
|
5193
|
+
} finally {
|
|
5194
|
+
latency == null ? void 0 : latency.recordEventDispatchEnd(event, { defaultPrevented: prevented });
|
|
4327
5195
|
}
|
|
4328
|
-
return false;
|
|
4329
5196
|
},
|
|
4330
5197
|
debugNodes() {
|
|
4331
5198
|
return Array.from(nodes.values()).map((n) => ({
|
|
@@ -4360,7 +5227,7 @@ function containsRect2(outer, inner) {
|
|
|
4360
5227
|
function area2(rect) {
|
|
4361
5228
|
return Math.max(0, rect.w) * Math.max(0, rect.h);
|
|
4362
5229
|
}
|
|
4363
|
-
function
|
|
5230
|
+
function now3() {
|
|
4364
5231
|
return typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
4365
5232
|
}
|
|
4366
5233
|
function rectRowRange2(rect) {
|
|
@@ -4383,9 +5250,9 @@ function createEventManager(container, metrics2, options) {
|
|
|
4383
5250
|
let hoverPath = [];
|
|
4384
5251
|
let lastPointerMoveEvent = null;
|
|
4385
5252
|
const rawRecord = options == null ? void 0 : options.record;
|
|
4386
|
-
const recordStart =
|
|
5253
|
+
const recordStart = now3();
|
|
4387
5254
|
const record = rawRecord ? (event) => {
|
|
4388
|
-
rawRecord({ ...event, time:
|
|
5255
|
+
rawRecord({ ...event, time: now3() - recordStart });
|
|
4389
5256
|
} : void 0;
|
|
4390
5257
|
const onFocusChange = options == null ? void 0 : options.onFocusChange;
|
|
4391
5258
|
const textInputTarget = (options == null ? void 0 : options.textInputTarget) ?? null;
|
|
@@ -4609,7 +5476,7 @@ function createEventManager(container, metrics2, options) {
|
|
|
4609
5476
|
bubbles: true,
|
|
4610
5477
|
cancelable: true,
|
|
4611
5478
|
defaultPrevented: false,
|
|
4612
|
-
timeStamp:
|
|
5479
|
+
timeStamp: now3(),
|
|
4613
5480
|
__stopped: false,
|
|
4614
5481
|
stopPropagation() {
|
|
4615
5482
|
this.__stopped = true;
|
|
@@ -5479,15 +6346,15 @@ function createTraceStore(opts) {
|
|
|
5479
6346
|
}
|
|
5480
6347
|
|
|
5481
6348
|
// src/observability/tui-profiler.ts
|
|
5482
|
-
var
|
|
5483
|
-
var
|
|
6349
|
+
var import_node_fs4 = require("fs");
|
|
6350
|
+
var import_node_process6 = __toESM(require("process"), 1);
|
|
5484
6351
|
function defaultNow() {
|
|
5485
6352
|
const p = globalThis.performance;
|
|
5486
6353
|
if (p && typeof p.now === "function")
|
|
5487
6354
|
return p.now();
|
|
5488
6355
|
return Date.now();
|
|
5489
6356
|
}
|
|
5490
|
-
function
|
|
6357
|
+
function parseEnabled2(v) {
|
|
5491
6358
|
return String(v ?? "").trim() === "1";
|
|
5492
6359
|
}
|
|
5493
6360
|
function parseLogFormat(v) {
|
|
@@ -5512,8 +6379,8 @@ function formatClockTime(ms) {
|
|
|
5512
6379
|
}
|
|
5513
6380
|
function createTuiProfiler(name) {
|
|
5514
6381
|
var _a2, _b2;
|
|
5515
|
-
const env = (_a2 =
|
|
5516
|
-
if (!
|
|
6382
|
+
const env = (_a2 = import_node_process6.default) == null ? void 0 : _a2.env;
|
|
6383
|
+
if (!parseEnabled2(env == null ? void 0 : env.DIMCODE_PROFILE_TUI))
|
|
5517
6384
|
return null;
|
|
5518
6385
|
const format = parseLogFormat(env == null ? void 0 : env.DIMCODE_PROFILE_TUI_FORMAT);
|
|
5519
6386
|
const logDest = parseLogDest(env == null ? void 0 : env.DIMCODE_PROFILE_TUI_LOG_DEST);
|
|
@@ -5536,8 +6403,8 @@ function createTuiProfiler(name) {
|
|
|
5536
6403
|
const invalidatePlaneCounts = /* @__PURE__ */ new Map();
|
|
5537
6404
|
const renderPlaneCounts = /* @__PURE__ */ new Map();
|
|
5538
6405
|
const logEveryMs = Number((env == null ? void 0 : env.DIMCODE_PROFILE_TUI_LOG_EVERY_MS) ?? 1e3);
|
|
5539
|
-
const
|
|
5540
|
-
let lastLogAt =
|
|
6406
|
+
const now4 = defaultNow;
|
|
6407
|
+
let lastLogAt = now4();
|
|
5541
6408
|
function incrementPlaneCount(target, key) {
|
|
5542
6409
|
const normalized = String(key ?? "all").trim() || "all";
|
|
5543
6410
|
target.set(normalized, (target.get(normalized) ?? 0) + 1);
|
|
@@ -5546,7 +6413,7 @@ function createTuiProfiler(name) {
|
|
|
5546
6413
|
const dest = logDest;
|
|
5547
6414
|
if ((dest === "file" || dest === "both") && logPath) {
|
|
5548
6415
|
try {
|
|
5549
|
-
(0,
|
|
6416
|
+
(0, import_node_fs4.appendFileSync)(logPath, `${line}
|
|
5550
6417
|
`);
|
|
5551
6418
|
} catch {
|
|
5552
6419
|
}
|
|
@@ -5556,7 +6423,7 @@ function createTuiProfiler(name) {
|
|
|
5556
6423
|
}
|
|
5557
6424
|
}
|
|
5558
6425
|
function flushLog() {
|
|
5559
|
-
const at =
|
|
6426
|
+
const at = now4();
|
|
5560
6427
|
const elapsed = at - lastLogAt;
|
|
5561
6428
|
if (elapsed <= 0)
|
|
5562
6429
|
return;
|
|
@@ -5638,7 +6505,7 @@ function createTuiProfiler(name) {
|
|
|
5638
6505
|
);
|
|
5639
6506
|
(_b2 = timer.unref) == null ? void 0 : _b2.call(timer);
|
|
5640
6507
|
return {
|
|
5641
|
-
now:
|
|
6508
|
+
now: now4,
|
|
5642
6509
|
recordInvalidate(info) {
|
|
5643
6510
|
invalidates++;
|
|
5644
6511
|
incrementPlaneCount(invalidatePlaneCounts, (info == null ? void 0 : info.plane) ?? "all");
|
|
@@ -6028,19 +6895,16 @@ var RenderStackKey = Symbol(
|
|
|
6028
6895
|
"RenderStack"
|
|
6029
6896
|
);
|
|
6030
6897
|
|
|
6031
|
-
// src/vue/render/render-manager.ts
|
|
6032
|
-
var import_node_process7 = __toESM(require("process"), 1);
|
|
6033
|
-
|
|
6034
6898
|
// src/core/debug-logger.ts
|
|
6035
|
-
var
|
|
6036
|
-
var
|
|
6899
|
+
var import_node_fs5 = require("fs");
|
|
6900
|
+
var import_node_process7 = __toESM(require("process"), 1);
|
|
6037
6901
|
var LOG_FILE = "/tmp/goatchain-debug.log";
|
|
6038
6902
|
var enabled = false;
|
|
6039
6903
|
function createDebugLogger(enable = false) {
|
|
6040
6904
|
enabled = enable;
|
|
6041
6905
|
if (enabled) {
|
|
6042
6906
|
try {
|
|
6043
|
-
(0,
|
|
6907
|
+
(0, import_node_fs5.writeFileSync)(
|
|
6044
6908
|
LOG_FILE,
|
|
6045
6909
|
`=== GoatChain Debug Log Started at ${(/* @__PURE__ */ new Date()).toISOString()} ===
|
|
6046
6910
|
|
|
@@ -6073,13 +6937,13 @@ function write(data) {
|
|
|
6073
6937
|
if (!enabled)
|
|
6074
6938
|
return;
|
|
6075
6939
|
try {
|
|
6076
|
-
(0,
|
|
6940
|
+
(0, import_node_fs5.appendFileSync)(LOG_FILE, data);
|
|
6077
6941
|
} catch {
|
|
6078
6942
|
}
|
|
6079
6943
|
}
|
|
6080
6944
|
function isDebugEnabled() {
|
|
6081
6945
|
var _a2;
|
|
6082
|
-
const env = (_a2 =
|
|
6946
|
+
const env = (_a2 = import_node_process7.default) == null ? void 0 : _a2.env;
|
|
6083
6947
|
return (env == null ? void 0 : env.DIMCODE_DEBUG) === "1" || (env == null ? void 0 : env.DEBUG) === "1";
|
|
6084
6948
|
}
|
|
6085
6949
|
|
|
@@ -6615,6 +7479,30 @@ function createRenderManager(terminal) {
|
|
|
6615
7479
|
}
|
|
6616
7480
|
}
|
|
6617
7481
|
}
|
|
7482
|
+
function markRows(plane, rows) {
|
|
7483
|
+
if (!rows.length)
|
|
7484
|
+
return;
|
|
7485
|
+
const state = getDirtyState(plane);
|
|
7486
|
+
for (let i = 0; i < rows.length; i++) {
|
|
7487
|
+
const y = Math.floor(rows[i] ?? -1);
|
|
7488
|
+
if (y < 0 || y >= terminalRows)
|
|
7489
|
+
continue;
|
|
7490
|
+
if (state.dirtyRowBits[y] === 0) {
|
|
7491
|
+
state.dirtyRowBits[y] = 1;
|
|
7492
|
+
state.dirtyRowCount++;
|
|
7493
|
+
if (y < state.dirtyMinY)
|
|
7494
|
+
state.dirtyMinY = y;
|
|
7495
|
+
if (y > state.dirtyMaxY)
|
|
7496
|
+
state.dirtyMaxY = y;
|
|
7497
|
+
}
|
|
7498
|
+
}
|
|
7499
|
+
}
|
|
7500
|
+
function scrollPlane(plane, startY, endY, delta) {
|
|
7501
|
+
scrollPlaneRows(terminal, plane, startY, endY, delta);
|
|
7502
|
+
}
|
|
7503
|
+
function invalidatePlane(plane) {
|
|
7504
|
+
getDirtyState(plane).allRowsDirty = true;
|
|
7505
|
+
}
|
|
6618
7506
|
function register(node) {
|
|
6619
7507
|
const id = `r${nextNodeId++}`;
|
|
6620
7508
|
const rect = node.rect ?? null;
|
|
@@ -6645,8 +7533,14 @@ function createRenderManager(terminal) {
|
|
|
6645
7533
|
const nextPlane = next.plane ?? prev.plane;
|
|
6646
7534
|
const nextRect = next.rect ?? prev.rect;
|
|
6647
7535
|
const { y0, y1 } = rectToYBounds(nextRect);
|
|
6648
|
-
|
|
6649
|
-
|
|
7536
|
+
const dirtyRowsHint = next.dirtyRowsHint;
|
|
7537
|
+
const canUseDirtyRowsHint = nextPlane === prev.plane && dirtyRowsHint != null && dirtyRowsHint.length > 0;
|
|
7538
|
+
if (canUseDirtyRowsHint) {
|
|
7539
|
+
markRows(nextPlane, dirtyRowsHint);
|
|
7540
|
+
} else {
|
|
7541
|
+
markRect(prev.plane, prev.rect);
|
|
7542
|
+
markRect(nextPlane, nextRect);
|
|
7543
|
+
}
|
|
6650
7544
|
const full = Object.freeze({
|
|
6651
7545
|
...prev,
|
|
6652
7546
|
stack: next.stack ?? prev.stack,
|
|
@@ -6713,11 +7607,10 @@ function createRenderManager(terminal) {
|
|
|
6713
7607
|
return false;
|
|
6714
7608
|
}
|
|
6715
7609
|
function render(options) {
|
|
6716
|
-
var _a2;
|
|
6717
7610
|
const renderStart = profiler == null ? void 0 : profiler.now();
|
|
6718
7611
|
const activePlanes = (options == null ? void 0 : options.activePlanes) ?? null;
|
|
6719
7612
|
const requestedPlanes = activePlanes ?? TERMINAL_RENDER_PLANES;
|
|
6720
|
-
const env =
|
|
7613
|
+
const env = process == null ? void 0 : process.env;
|
|
6721
7614
|
if ((env == null ? void 0 : env.DIMCODE_DEBUG) === "1")
|
|
6722
7615
|
renderMgrDebugLog.render("[RENDER-MANAGER] render() called");
|
|
6723
7616
|
if (!hasPendingDirtyWork(requestedPlanes)) {
|
|
@@ -6847,6 +7740,8 @@ function createRenderManager(terminal) {
|
|
|
6847
7740
|
return {
|
|
6848
7741
|
rootStack,
|
|
6849
7742
|
createStack,
|
|
7743
|
+
invalidatePlane,
|
|
7744
|
+
scrollPlane,
|
|
6850
7745
|
register,
|
|
6851
7746
|
update,
|
|
6852
7747
|
unregister,
|
|
@@ -6903,6 +7798,7 @@ function createTerminalApp(options) {
|
|
|
6903
7798
|
const trace = createTraceStore({
|
|
6904
7799
|
enabled: Boolean(globalThis.__VT_DEBUG_TRACE__)
|
|
6905
7800
|
});
|
|
7801
|
+
const latency = getCliLatencyProfiler();
|
|
6906
7802
|
const profiler = createTuiProfiler("cli-scheduler");
|
|
6907
7803
|
const events = createCliEventManager({
|
|
6908
7804
|
record: (event) => {
|
|
@@ -6917,7 +7813,8 @@ function createTerminalApp(options) {
|
|
|
6917
7813
|
}
|
|
6918
7814
|
});
|
|
6919
7815
|
const render = createRenderManager(terminal);
|
|
6920
|
-
const offCommit = terminal.on("commit", ({ dirtyRows, planes }) => {
|
|
7816
|
+
const offCommit = terminal.on("commit", ({ dirtyRows, planes, sync }) => {
|
|
7817
|
+
latency == null ? void 0 : latency.recordCommit({ dirtyRows, planes, sync });
|
|
6921
7818
|
if (!trace.enabled.value)
|
|
6922
7819
|
return;
|
|
6923
7820
|
trace.push({
|
|
@@ -6935,10 +7832,10 @@ function createTerminalApp(options) {
|
|
|
6935
7832
|
let lastFlushAtMs = 0;
|
|
6936
7833
|
let scheduledAtMs = 0;
|
|
6937
7834
|
let timer = null;
|
|
7835
|
+
let pendingInvalidateAfterFlush = false;
|
|
6938
7836
|
let pendingInvalidateAllPlanes = false;
|
|
6939
7837
|
const pendingInvalidatePlanes = /* @__PURE__ */ new Set();
|
|
6940
7838
|
const env = ((_a2 = import_node_process8.default) == null ? void 0 : _a2.env) ?? {};
|
|
6941
|
-
const isGhostty = "GHOSTTY_RESOURCES_DIR" in env;
|
|
6942
7839
|
const throttleMs = (() => {
|
|
6943
7840
|
const raw = env.DIMCODE_TUI_THROTTLE_MS;
|
|
6944
7841
|
if (!raw)
|
|
@@ -6950,7 +7847,7 @@ function createTerminalApp(options) {
|
|
|
6950
7847
|
var _a3, _b2;
|
|
6951
7848
|
if (!((_b2 = (_a3 = import_node_process8.default) == null ? void 0 : _a3.stdout) == null ? void 0 : _b2.isTTY))
|
|
6952
7849
|
return 0;
|
|
6953
|
-
return
|
|
7850
|
+
return 16;
|
|
6954
7851
|
})();
|
|
6955
7852
|
function queueInvalidatePlane(plane) {
|
|
6956
7853
|
if (!plane) {
|
|
@@ -6974,17 +7871,26 @@ function createTerminalApp(options) {
|
|
|
6974
7871
|
pendingInvalidatePlanes.clear();
|
|
6975
7872
|
return activePlanes;
|
|
6976
7873
|
}
|
|
6977
|
-
function flush() {
|
|
7874
|
+
function flush(sync) {
|
|
6978
7875
|
if (disposed)
|
|
6979
7876
|
return;
|
|
6980
7877
|
scheduled = false;
|
|
6981
7878
|
flushing = true;
|
|
6982
7879
|
const activePlanes = takeActivePlanes();
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
7880
|
+
latency == null ? void 0 : latency.recordFlushStart({ sync, activePlanes });
|
|
7881
|
+
try {
|
|
7882
|
+
render.render({ activePlanes });
|
|
7883
|
+
terminal.commit({ planes: activePlanes, sync });
|
|
7884
|
+
} finally {
|
|
7885
|
+
latency == null ? void 0 : latency.recordFlushEnd();
|
|
7886
|
+
flushing = false;
|
|
7887
|
+
lastFlushAtMs = Date.now();
|
|
7888
|
+
scheduledAtMs = 0;
|
|
7889
|
+
}
|
|
7890
|
+
if (pendingInvalidateAfterFlush) {
|
|
7891
|
+
pendingInvalidateAfterFlush = false;
|
|
7892
|
+
flush(true);
|
|
7893
|
+
}
|
|
6988
7894
|
}
|
|
6989
7895
|
function clearScheduledTimer() {
|
|
6990
7896
|
if (!timer)
|
|
@@ -7029,16 +7935,27 @@ function createTerminalApp(options) {
|
|
|
7029
7935
|
return;
|
|
7030
7936
|
clearScheduledTimer();
|
|
7031
7937
|
scheduled = false;
|
|
7032
|
-
flush();
|
|
7938
|
+
flush(true);
|
|
7033
7939
|
}
|
|
7034
7940
|
function invalidate(options2) {
|
|
7035
7941
|
if (disposed)
|
|
7036
7942
|
return;
|
|
7037
|
-
if (flushing)
|
|
7038
|
-
return;
|
|
7039
7943
|
const priority = (options2 == null ? void 0 : options2.priority) ?? "normal";
|
|
7944
|
+
latency == null ? void 0 : latency.recordSchedulerInvalidate({
|
|
7945
|
+
priority,
|
|
7946
|
+
plane: (options2 == null ? void 0 : options2.plane) ?? null
|
|
7947
|
+
});
|
|
7948
|
+
if (flushing) {
|
|
7949
|
+
queueInvalidatePlane(options2 == null ? void 0 : options2.plane);
|
|
7950
|
+
pendingInvalidateAfterFlush = true;
|
|
7951
|
+
return;
|
|
7952
|
+
}
|
|
7040
7953
|
queueInvalidatePlane(options2 == null ? void 0 : options2.plane);
|
|
7041
7954
|
profiler == null ? void 0 : profiler.recordInvalidate({ plane: (options2 == null ? void 0 : options2.plane) ?? null });
|
|
7955
|
+
if (priority === "high") {
|
|
7956
|
+
flushNow();
|
|
7957
|
+
return;
|
|
7958
|
+
}
|
|
7042
7959
|
const nowMs = Date.now();
|
|
7043
7960
|
const throttleDelayMs = throttleMs > 0 ? Math.max(0, lastFlushAtMs + throttleMs - nowMs) : 0;
|
|
7044
7961
|
const laneDelayMs = priority === "low" ? Math.max(throttleDelayMs, frameThrottleMs || 16) : priority === "normal" ? Math.max(throttleDelayMs, frameThrottleMs) : 0;
|
|
@@ -7181,6 +8098,7 @@ function createTerminalApp(options) {
|
|
|
7181
8098
|
if (disposed)
|
|
7182
8099
|
return;
|
|
7183
8100
|
disposed = true;
|
|
8101
|
+
clearScheduledTimer();
|
|
7184
8102
|
if (mounted)
|
|
7185
8103
|
app.unmount();
|
|
7186
8104
|
offResize == null ? void 0 : offResize();
|
|
@@ -7287,6 +8205,7 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7287
8205
|
let palette = options == null ? void 0 : options.palette;
|
|
7288
8206
|
const trackResize = (options == null ? void 0 : options.trackResize) ?? true;
|
|
7289
8207
|
const getImeAnchor = options == null ? void 0 : options.getImeAnchor;
|
|
8208
|
+
const cliLatency = getCliLatencyProfiler();
|
|
7290
8209
|
const profiler = createTuiProfiler("stdout-renderer");
|
|
7291
8210
|
function resolveUseSyncOutput() {
|
|
7292
8211
|
var _a3;
|
|
@@ -7298,15 +8217,15 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7298
8217
|
const v = String(envValue).trim().toLowerCase();
|
|
7299
8218
|
return v === "1" || v === "true" || v === "yes";
|
|
7300
8219
|
}
|
|
7301
|
-
const
|
|
7302
|
-
const
|
|
8220
|
+
const term2 = String(env2.TERM ?? "").toLowerCase();
|
|
8221
|
+
const termProgram2 = String(env2.TERM_PROGRAM ?? "").toLowerCase();
|
|
7303
8222
|
const termProgramVersion = env2.TERM_PROGRAM_VERSION;
|
|
7304
8223
|
const isGhostty2 = "GHOSTTY_RESOURCES_DIR" in env2;
|
|
7305
|
-
const isProblematicTerminal = isGhostty2 ||
|
|
8224
|
+
const isProblematicTerminal = isGhostty2 || termProgram2.includes("apple_terminal") || term2.includes("screen") && !term2.includes("tmux");
|
|
7306
8225
|
if (isProblematicTerminal) {
|
|
7307
8226
|
return false;
|
|
7308
8227
|
}
|
|
7309
|
-
const isGoodTerminal =
|
|
8228
|
+
const isGoodTerminal = termProgram2.includes("iterm") && termProgramVersion && compareVersion(String(termProgramVersion), "3.5.0") >= 0;
|
|
7310
8229
|
if (isGoodTerminal) {
|
|
7311
8230
|
return true;
|
|
7312
8231
|
}
|
|
@@ -7354,13 +8273,16 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7354
8273
|
return 0.6;
|
|
7355
8274
|
})();
|
|
7356
8275
|
const disableCursorPos = isGhostty && ((_d = (_c = import_node_process9.default) == null ? void 0 : _c.env) == null ? void 0 : _d.DIMCODE_DISABLE_CURSOR_POS) === "1";
|
|
7357
|
-
const
|
|
8276
|
+
const termProgram = String(env.TERM_PROGRAM ?? "").trim().toLowerCase();
|
|
8277
|
+
const term = String(env.TERM ?? "").trim().toLowerCase();
|
|
8278
|
+
const isVscodeTerminal = termProgram === "vscode" || "VSCODE_PID" in env || "VSCODE_IPC_HOOK_CLI" in env;
|
|
8279
|
+
const useConservativeDirtyRowRendering = out.isTTY !== false && !isVscodeTerminal && (isGhostty || "KITTY_WINDOW_ID" in env || "ALACRITTY_WINDOW_ID" in env || "ALACRITTY_LOG" in env || "WEZTERM_PANE" in env || "WEZTERM_EXECUTABLE" in env || termProgram.includes("kitty") || termProgram.includes("alacritty") || termProgram.includes("wezterm") || term.includes("kitty") || term.includes("alacritty"));
|
|
7358
8280
|
const enableOsc8Links = (() => {
|
|
7359
8281
|
if (!out.isTTY)
|
|
7360
8282
|
return false;
|
|
7361
8283
|
const raw = String(env.DIMCODE_TUI_LINKS ?? "").trim().toLowerCase();
|
|
7362
8284
|
if (!raw) {
|
|
7363
|
-
return !
|
|
8285
|
+
return !isVscodeTerminal;
|
|
7364
8286
|
}
|
|
7365
8287
|
return !(raw === "0" || raw === "false" || raw === "no");
|
|
7366
8288
|
})();
|
|
@@ -7369,12 +8291,16 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7369
8291
|
let pendingRender = false;
|
|
7370
8292
|
let renderTimer = null;
|
|
7371
8293
|
let writeEmaMs = 0;
|
|
8294
|
+
let lastCursorX = null;
|
|
8295
|
+
let lastCursorY = null;
|
|
7372
8296
|
let accumulatedAllRows = false;
|
|
7373
8297
|
let accumulatedDirtyBits = null;
|
|
7374
8298
|
let accumulatedDirtyCount = 0;
|
|
7375
8299
|
let accumulatedDirtyMin = Number.POSITIVE_INFINITY;
|
|
7376
8300
|
let accumulatedDirtyMax = -1;
|
|
7377
|
-
|
|
8301
|
+
let accumulatedScrollOperations = null;
|
|
8302
|
+
let accumulatedSkipUnchangedDirtyRows = true;
|
|
8303
|
+
const MIN_FRAME_MS = !out.isTTY ? 0 : 16;
|
|
7378
8304
|
function clampCellToViewport(cell, size) {
|
|
7379
8305
|
const maxX = Math.max(0, Math.floor(size.cols) - 1);
|
|
7380
8306
|
const maxY = Math.max(0, Math.floor(size.rows) - 1);
|
|
@@ -7398,17 +8324,35 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7398
8324
|
}
|
|
7399
8325
|
const colorMode = resolveColorMode();
|
|
7400
8326
|
const enableDim = colorMode === "truecolor";
|
|
8327
|
+
const COLOR_INDEX = {
|
|
8328
|
+
black: 1,
|
|
8329
|
+
red: 2,
|
|
8330
|
+
green: 3,
|
|
8331
|
+
yellow: 4,
|
|
8332
|
+
blue: 5,
|
|
8333
|
+
magenta: 6,
|
|
8334
|
+
cyan: 7,
|
|
8335
|
+
white: 8,
|
|
8336
|
+
blackBright: 9,
|
|
8337
|
+
redBright: 10,
|
|
8338
|
+
greenBright: 11,
|
|
8339
|
+
yellowBright: 12,
|
|
8340
|
+
blueBright: 13,
|
|
8341
|
+
magentaBright: 14,
|
|
8342
|
+
cyanBright: 15,
|
|
8343
|
+
whiteBright: 16
|
|
8344
|
+
};
|
|
7401
8345
|
let styleKeyCache2 = /* @__PURE__ */ new WeakMap();
|
|
7402
8346
|
function styleKey2(style) {
|
|
7403
8347
|
const cached = styleKeyCache2.get(style);
|
|
7404
|
-
if (cached)
|
|
8348
|
+
if (cached !== void 0)
|
|
7405
8349
|
return cached;
|
|
7406
|
-
const key =
|
|
8350
|
+
const key = (COLOR_INDEX[style.fg] ?? 0) | (COLOR_INDEX[style.bg ?? defaultBg] ?? 0) << 5 | (style.bold ? 1 << 10 : 0) | (enableDim && style.dim ? 1 << 11 : 0) | (style.italic ? 1 << 12 : 0) | (style.underline ? 1 << 13 : 0) | (style.inverse ? 1 << 14 : 0) | (style.href ? 1 << 15 : 0);
|
|
7407
8351
|
styleKeyCache2.set(style, key);
|
|
7408
8352
|
return key;
|
|
7409
8353
|
}
|
|
7410
8354
|
function styleKeyFromParts(style) {
|
|
7411
|
-
return
|
|
8355
|
+
return (COLOR_INDEX[style.fg] ?? 0) | (COLOR_INDEX[style.bg ?? defaultBg] ?? 0) << 5 | (style.bold ? 1 << 10 : 0) | (enableDim && style.dim ? 1 << 11 : 0) | (style.italic ? 1 << 12 : 0) | (style.underline ? 1 << 13 : 0) | (style.inverse ? 1 << 14 : 0) | (style.href ? 1 << 15 : 0);
|
|
7412
8356
|
}
|
|
7413
8357
|
function openColor(fg) {
|
|
7414
8358
|
if (!fg)
|
|
@@ -7455,7 +8399,47 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7455
8399
|
return result;
|
|
7456
8400
|
}
|
|
7457
8401
|
let lastRenderedRows = 0;
|
|
7458
|
-
let
|
|
8402
|
+
let fpCols = 0;
|
|
8403
|
+
let fpRows = 0;
|
|
8404
|
+
let currentFP = new Uint32Array(0);
|
|
8405
|
+
let prevFP = new Uint32Array(0);
|
|
8406
|
+
let fpPrevValid = false;
|
|
8407
|
+
let prevOverlayBlockedRows = [];
|
|
8408
|
+
let prevOverlayPartialRows = [];
|
|
8409
|
+
function ensureFingerprints(cols, rows) {
|
|
8410
|
+
if (cols === fpCols && rows === fpRows)
|
|
8411
|
+
return;
|
|
8412
|
+
fpCols = cols;
|
|
8413
|
+
fpRows = rows;
|
|
8414
|
+
const len = cols * rows;
|
|
8415
|
+
currentFP = new Uint32Array(len);
|
|
8416
|
+
prevFP = new Uint32Array(len);
|
|
8417
|
+
fpPrevValid = false;
|
|
8418
|
+
prevOverlayBlockedRows = [];
|
|
8419
|
+
prevOverlayPartialRows = [];
|
|
8420
|
+
}
|
|
8421
|
+
function charHash16(ch) {
|
|
8422
|
+
if (ch.length <= 1)
|
|
8423
|
+
return ch.charCodeAt(0) || 0;
|
|
8424
|
+
let h18 = 33052;
|
|
8425
|
+
for (let i = 0; i < ch.length; i++) {
|
|
8426
|
+
h18 ^= ch.charCodeAt(i);
|
|
8427
|
+
h18 = h18 * 257 & 65535;
|
|
8428
|
+
}
|
|
8429
|
+
return h18;
|
|
8430
|
+
}
|
|
8431
|
+
function fingerprintRow(row, y, cols) {
|
|
8432
|
+
const rowFP = terminal.getRowFingerprints(y);
|
|
8433
|
+
if (rowFP && rowFP.length >= cols) {
|
|
8434
|
+
currentFP.set(rowFP.subarray(0, cols), y * fpCols);
|
|
8435
|
+
return;
|
|
8436
|
+
}
|
|
8437
|
+
const base = y * fpCols;
|
|
8438
|
+
for (let x = 0; x < cols; x++) {
|
|
8439
|
+
const cell = row[x];
|
|
8440
|
+
currentFP[base + x] = styleKey2(cell.style) << 16 | charHash16(cell.ch);
|
|
8441
|
+
}
|
|
8442
|
+
}
|
|
7459
8443
|
const rowCursorToCol1 = [];
|
|
7460
8444
|
const rowClearToEol = [];
|
|
7461
8445
|
const rowTextPartsScratch = [];
|
|
@@ -7474,14 +8458,6 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7474
8458
|
rowClearToEol[y] = `\x1B[${y + 1};1H\x1B[K`;
|
|
7475
8459
|
}
|
|
7476
8460
|
};
|
|
7477
|
-
const ensureRenderedRowCache = (rows) => {
|
|
7478
|
-
if (renderedRowCache.length > rows) {
|
|
7479
|
-
renderedRowCache.length = rows;
|
|
7480
|
-
return;
|
|
7481
|
-
}
|
|
7482
|
-
while (renderedRowCache.length < rows)
|
|
7483
|
-
renderedRowCache.push([]);
|
|
7484
|
-
};
|
|
7485
8461
|
const expandSpanStart = (row, startX) => {
|
|
7486
8462
|
var _a3;
|
|
7487
8463
|
let x = Math.max(0, Math.min(row.length, startX));
|
|
@@ -7501,40 +8477,296 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7501
8477
|
}
|
|
7502
8478
|
return x;
|
|
7503
8479
|
};
|
|
7504
|
-
const resolveChangedSpan = (row,
|
|
7505
|
-
if (!
|
|
8480
|
+
const resolveChangedSpan = (row, y, cols) => {
|
|
8481
|
+
if (!fpCols || y >= fpRows || !fpPrevValid)
|
|
8482
|
+
return row.length ? { startX: 0, endXExclusive: row.length } : null;
|
|
8483
|
+
const base = y * fpCols;
|
|
8484
|
+
let startX = -1;
|
|
8485
|
+
let endXExclusive = -1;
|
|
8486
|
+
for (let x = 0; x < cols; x++) {
|
|
8487
|
+
if (currentFP[base + x] === prevFP[base + x])
|
|
8488
|
+
continue;
|
|
8489
|
+
if (startX === -1)
|
|
8490
|
+
startX = x;
|
|
8491
|
+
endXExclusive = x + 1;
|
|
8492
|
+
}
|
|
8493
|
+
if (startX === -1)
|
|
8494
|
+
return null;
|
|
8495
|
+
const expandedStart = expandSpanStart(row, startX);
|
|
8496
|
+
const expandedEnd = expandSpanEnd(row, endXExclusive);
|
|
8497
|
+
return expandedEnd > expandedStart ? { startX: expandedStart, endXExclusive: expandedEnd } : null;
|
|
8498
|
+
};
|
|
8499
|
+
const resolveChangedSpanAgainstFill = (row, y, cols, fillFingerprint) => {
|
|
8500
|
+
if (!fpCols || y >= fpRows)
|
|
7506
8501
|
return row.length ? { startX: 0, endXExclusive: row.length } : null;
|
|
8502
|
+
const base = y * fpCols;
|
|
8503
|
+
let startX = -1;
|
|
8504
|
+
let endXExclusive = -1;
|
|
8505
|
+
for (let x = 0; x < cols; x++) {
|
|
8506
|
+
if (currentFP[base + x] === fillFingerprint)
|
|
8507
|
+
continue;
|
|
8508
|
+
if (startX === -1)
|
|
8509
|
+
startX = x;
|
|
8510
|
+
endXExclusive = x + 1;
|
|
7507
8511
|
}
|
|
8512
|
+
if (startX === -1)
|
|
8513
|
+
return null;
|
|
8514
|
+
const expandedStart = expandSpanStart(row, startX);
|
|
8515
|
+
const expandedEnd = expandSpanEnd(row, endXExclusive);
|
|
8516
|
+
return expandedEnd > expandedStart ? { startX: expandedStart, endXExclusive: expandedEnd } : null;
|
|
8517
|
+
};
|
|
8518
|
+
const resolveChangedSpanAgainstReference = (row, y, cols) => {
|
|
8519
|
+
if (!fpCols || y >= fpRows)
|
|
8520
|
+
return row.length ? { startX: 0, endXExclusive: row.length } : null;
|
|
8521
|
+
const rowFP = terminal.getRowFingerprints(y);
|
|
8522
|
+
const base = y * fpCols;
|
|
7508
8523
|
let startX = -1;
|
|
7509
8524
|
let endXExclusive = -1;
|
|
7510
|
-
for (let x = 0; x <
|
|
7511
|
-
|
|
8525
|
+
for (let x = 0; x < cols; x++) {
|
|
8526
|
+
const fingerprint = rowFP && rowFP.length >= cols ? rowFP[x] : styleKey2(row[x].style) << 16 | charHash16(row[x].ch);
|
|
8527
|
+
if (fingerprint === currentFP[base + x])
|
|
8528
|
+
continue;
|
|
8529
|
+
if (startX === -1)
|
|
8530
|
+
startX = x;
|
|
8531
|
+
endXExclusive = x + 1;
|
|
8532
|
+
}
|
|
8533
|
+
if (startX === -1)
|
|
8534
|
+
return null;
|
|
8535
|
+
const expandedStart = expandSpanStart(row, startX);
|
|
8536
|
+
const expandedEnd = expandSpanEnd(row, endXExclusive);
|
|
8537
|
+
return expandedEnd > expandedStart ? { startX: expandedStart, endXExclusive: expandedEnd } : null;
|
|
8538
|
+
};
|
|
8539
|
+
const rowMatchesPreviousFrame = (y, cols) => {
|
|
8540
|
+
if (!fpCols || y < 0 || y >= fpRows || !fpPrevValid)
|
|
8541
|
+
return false;
|
|
8542
|
+
const rowFP = terminal.getRowFingerprints(y);
|
|
8543
|
+
const row = rowFP && rowFP.length >= cols ? null : terminal.getRow(y);
|
|
8544
|
+
const base = y * fpCols;
|
|
8545
|
+
for (let x = 0; x < cols; x++) {
|
|
8546
|
+
const fingerprint = rowFP && rowFP.length >= cols ? rowFP[x] : styleKey2(row[x].style) << 16 | charHash16(row[x].ch);
|
|
8547
|
+
if (fingerprint !== prevFP[base + x])
|
|
8548
|
+
return false;
|
|
8549
|
+
}
|
|
8550
|
+
return true;
|
|
8551
|
+
};
|
|
8552
|
+
const rowHasNonDefaultBlankCell = (source, y, cols) => {
|
|
8553
|
+
if (!fpCols || y < 0 || y >= fpRows)
|
|
8554
|
+
return false;
|
|
8555
|
+
const blankFP = styleKeyFromParts({ bg: defaultBg }) << 16 | charHash16(" ");
|
|
8556
|
+
const base = y * fpCols;
|
|
8557
|
+
const limit = Math.min(cols, fpCols);
|
|
8558
|
+
for (let x = 0; x < limit; x++) {
|
|
8559
|
+
if (source[base + x] !== blankFP)
|
|
8560
|
+
return true;
|
|
8561
|
+
}
|
|
8562
|
+
return false;
|
|
8563
|
+
};
|
|
8564
|
+
function overlayPlaneCoverageRows(totalRows) {
|
|
8565
|
+
const blockedRows = [];
|
|
8566
|
+
const partialRows = [];
|
|
8567
|
+
for (let y = 0; y < totalRows; y++) {
|
|
8568
|
+
const kind = getPlaneRowCoverageKind(terminal, "overlay", y);
|
|
8569
|
+
if (!kind)
|
|
8570
|
+
continue;
|
|
8571
|
+
blockedRows.push(y);
|
|
8572
|
+
if (kind === 1)
|
|
8573
|
+
partialRows.push(y);
|
|
8574
|
+
}
|
|
8575
|
+
return { blockedRows, partialRows };
|
|
8576
|
+
}
|
|
8577
|
+
const enableScrollRegions = (() => {
|
|
8578
|
+
const raw = String(env.DIMCODE_TUI_SCROLL_REGIONS ?? "").trim();
|
|
8579
|
+
if (raw === "0" || raw === "false")
|
|
8580
|
+
return false;
|
|
8581
|
+
if (isGhostty || isVscodeTerminal)
|
|
8582
|
+
return false;
|
|
8583
|
+
return out.isTTY !== false;
|
|
8584
|
+
})();
|
|
8585
|
+
function prepareExplicitScrollOperations(operations, blockedRows) {
|
|
8586
|
+
if (!operations.length || !(blockedRows == null ? void 0 : blockedRows.size)) {
|
|
8587
|
+
return {
|
|
8588
|
+
operations,
|
|
8589
|
+
hiddenRows: /* @__PURE__ */ new Set(),
|
|
8590
|
+
trimmed: false,
|
|
8591
|
+
blockedInterior: false
|
|
8592
|
+
};
|
|
8593
|
+
}
|
|
8594
|
+
const hiddenRows = /* @__PURE__ */ new Set();
|
|
8595
|
+
const prepared = [];
|
|
8596
|
+
let trimmed = false;
|
|
8597
|
+
for (const op of operations) {
|
|
8598
|
+
let startY = op.startY;
|
|
8599
|
+
let endY = op.endY;
|
|
8600
|
+
while (startY < endY && blockedRows.has(startY)) {
|
|
8601
|
+
hiddenRows.add(startY);
|
|
8602
|
+
startY++;
|
|
8603
|
+
trimmed = true;
|
|
8604
|
+
}
|
|
8605
|
+
while (endY > startY && blockedRows.has(endY - 1)) {
|
|
8606
|
+
hiddenRows.add(endY - 1);
|
|
8607
|
+
endY--;
|
|
8608
|
+
trimmed = true;
|
|
8609
|
+
}
|
|
8610
|
+
for (let y = startY; y < endY; y++) {
|
|
8611
|
+
if (!blockedRows.has(y))
|
|
8612
|
+
continue;
|
|
8613
|
+
return {
|
|
8614
|
+
operations: null,
|
|
8615
|
+
hiddenRows,
|
|
8616
|
+
trimmed,
|
|
8617
|
+
blockedInterior: true
|
|
8618
|
+
};
|
|
8619
|
+
}
|
|
8620
|
+
if (endY <= startY || Math.abs(op.delta) >= endY - startY) {
|
|
8621
|
+
return {
|
|
8622
|
+
operations: null,
|
|
8623
|
+
hiddenRows,
|
|
8624
|
+
trimmed,
|
|
8625
|
+
blockedInterior: false
|
|
8626
|
+
};
|
|
8627
|
+
}
|
|
8628
|
+
prepared.push(
|
|
8629
|
+
startY === op.startY && endY === op.endY ? op : { startY, endY, delta: op.delta }
|
|
8630
|
+
);
|
|
8631
|
+
}
|
|
8632
|
+
return {
|
|
8633
|
+
operations: prepared,
|
|
8634
|
+
hiddenRows,
|
|
8635
|
+
trimmed,
|
|
8636
|
+
blockedInterior: false
|
|
8637
|
+
};
|
|
8638
|
+
}
|
|
8639
|
+
function largestDirtyBand(rows, blockedRows) {
|
|
8640
|
+
if (rows.length === 0)
|
|
8641
|
+
return null;
|
|
8642
|
+
const blocked = (blockedRows == null ? void 0 : blockedRows.length) ? new Set(blockedRows) : null;
|
|
8643
|
+
let bestStart = -1;
|
|
8644
|
+
let bestEnd = -1;
|
|
8645
|
+
let bandStart = -1;
|
|
8646
|
+
let prev = -1;
|
|
8647
|
+
for (let i = 0; i < rows.length; i++) {
|
|
8648
|
+
const y = rows[i];
|
|
8649
|
+
if (blocked == null ? void 0 : blocked.has(y)) {
|
|
8650
|
+
if (bandStart !== -1 && prev + 1 - bandStart > bestEnd - bestStart) {
|
|
8651
|
+
bestStart = bandStart;
|
|
8652
|
+
bestEnd = prev + 1;
|
|
8653
|
+
}
|
|
8654
|
+
bandStart = -1;
|
|
8655
|
+
prev = -1;
|
|
8656
|
+
continue;
|
|
8657
|
+
}
|
|
8658
|
+
if (bandStart === -1) {
|
|
8659
|
+
bandStart = y;
|
|
8660
|
+
prev = y;
|
|
8661
|
+
if (bestStart === -1) {
|
|
8662
|
+
bestStart = y;
|
|
8663
|
+
bestEnd = y + 1;
|
|
8664
|
+
}
|
|
8665
|
+
continue;
|
|
8666
|
+
}
|
|
8667
|
+
if (y === prev + 1) {
|
|
8668
|
+
prev = y;
|
|
7512
8669
|
continue;
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
8670
|
+
}
|
|
8671
|
+
if (prev + 1 - bandStart > bestEnd - bestStart) {
|
|
8672
|
+
bestStart = bandStart;
|
|
8673
|
+
bestEnd = prev + 1;
|
|
8674
|
+
}
|
|
8675
|
+
bandStart = y;
|
|
8676
|
+
prev = y;
|
|
8677
|
+
}
|
|
8678
|
+
if (bandStart !== -1 && prev + 1 - bandStart > bestEnd - bestStart) {
|
|
8679
|
+
bestStart = bandStart;
|
|
8680
|
+
bestEnd = prev + 1;
|
|
7516
8681
|
}
|
|
7517
|
-
if (
|
|
8682
|
+
if (bestStart === -1)
|
|
7518
8683
|
return null;
|
|
7519
|
-
const
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
|
|
8684
|
+
const outsideRows = [];
|
|
8685
|
+
for (const y of rows) {
|
|
8686
|
+
if ((blocked == null ? void 0 : blocked.has(y)) || y < bestStart || y >= bestEnd) {
|
|
8687
|
+
outsideRows.push(y);
|
|
8688
|
+
}
|
|
8689
|
+
}
|
|
8690
|
+
return { start: bestStart, end: bestEnd, outsideRows };
|
|
8691
|
+
}
|
|
8692
|
+
function detectScrollShift(cols, dirtyRows, blockedRows) {
|
|
8693
|
+
if (!fpPrevValid || !fpCols || cols !== fpCols)
|
|
8694
|
+
return null;
|
|
8695
|
+
const band = largestDirtyBand(dirtyRows, blockedRows);
|
|
8696
|
+
if (!band || band.end - band.start < 3)
|
|
8697
|
+
return null;
|
|
8698
|
+
const maxDelta = Math.min(
|
|
8699
|
+
12,
|
|
8700
|
+
Math.max(5, band.end - band.start - 1)
|
|
7526
8701
|
);
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
8702
|
+
for (let delta = -maxDelta; delta <= maxDelta; delta++) {
|
|
8703
|
+
if (delta === 0)
|
|
8704
|
+
continue;
|
|
8705
|
+
let matches = 0;
|
|
8706
|
+
let checked = 0;
|
|
8707
|
+
let mismatches = 0;
|
|
8708
|
+
for (let y = band.start; y < band.end; y++) {
|
|
8709
|
+
const srcY = y + delta;
|
|
8710
|
+
if (srcY < band.start || srcY >= band.end)
|
|
8711
|
+
continue;
|
|
8712
|
+
const informative = rowHasNonDefaultBlankCell(currentFP, y, cols) || rowHasNonDefaultBlankCell(prevFP, srcY, cols);
|
|
8713
|
+
if (!informative)
|
|
8714
|
+
continue;
|
|
8715
|
+
checked++;
|
|
8716
|
+
const curBase = y * fpCols;
|
|
8717
|
+
const prevBase = srcY * fpCols;
|
|
8718
|
+
let rowMatch = true;
|
|
8719
|
+
for (let x = 0; x < cols; x++) {
|
|
8720
|
+
if (currentFP[curBase + x] !== prevFP[prevBase + x]) {
|
|
8721
|
+
rowMatch = false;
|
|
8722
|
+
break;
|
|
8723
|
+
}
|
|
8724
|
+
}
|
|
8725
|
+
if (rowMatch) {
|
|
8726
|
+
matches++;
|
|
8727
|
+
} else {
|
|
8728
|
+
mismatches++;
|
|
8729
|
+
}
|
|
8730
|
+
}
|
|
8731
|
+
if (checked > 0 && matches >= 3 && mismatches <= Math.ceil(checked * 0.2)) {
|
|
8732
|
+
const absDelta = Math.abs(delta);
|
|
8733
|
+
let newRowStart;
|
|
8734
|
+
let newRowEnd;
|
|
8735
|
+
if (delta > 0) {
|
|
8736
|
+
newRowStart = Math.max(band.start, band.end - absDelta);
|
|
8737
|
+
newRowEnd = band.end;
|
|
8738
|
+
} else {
|
|
8739
|
+
newRowStart = band.start;
|
|
8740
|
+
newRowEnd = Math.min(band.end, band.start + absDelta);
|
|
8741
|
+
}
|
|
8742
|
+
const extraDirty = [...band.outsideRows];
|
|
8743
|
+
for (let y = band.start; y < band.end; y++) {
|
|
8744
|
+
const srcY = y + delta;
|
|
8745
|
+
if (srcY < band.start || srcY >= band.end)
|
|
8746
|
+
continue;
|
|
8747
|
+
const curBase = y * fpCols;
|
|
8748
|
+
const prevBase = srcY * fpCols;
|
|
8749
|
+
let rowMatch = true;
|
|
8750
|
+
for (let x = 0; x < cols; x++) {
|
|
8751
|
+
if (currentFP[curBase + x] !== prevFP[prevBase + x]) {
|
|
8752
|
+
rowMatch = false;
|
|
8753
|
+
break;
|
|
8754
|
+
}
|
|
8755
|
+
}
|
|
8756
|
+
if (!rowMatch)
|
|
8757
|
+
extraDirty.push(y);
|
|
8758
|
+
}
|
|
8759
|
+
return {
|
|
8760
|
+
regionStart: band.start,
|
|
8761
|
+
regionEnd: band.end,
|
|
8762
|
+
delta,
|
|
8763
|
+
newRowStart,
|
|
8764
|
+
newRowEnd,
|
|
8765
|
+
extraDirtyRows: extraDirty
|
|
8766
|
+
};
|
|
7535
8767
|
}
|
|
7536
8768
|
}
|
|
7537
|
-
return
|
|
8769
|
+
return null;
|
|
7538
8770
|
}
|
|
7539
8771
|
function writeChunked(data) {
|
|
7540
8772
|
if (!isGhostty) {
|
|
@@ -7569,7 +8801,7 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7569
8801
|
getDebugLog().error(`writeChunked: write error`, e);
|
|
7570
8802
|
}
|
|
7571
8803
|
}
|
|
7572
|
-
function doRender(dirtyRows) {
|
|
8804
|
+
function doRender(dirtyRows, scrollOperations, skipUnchangedDirtyRows = false) {
|
|
7573
8805
|
if (isDebugEnabled()) {
|
|
7574
8806
|
getDebugLog().render(
|
|
7575
8807
|
`doRender() START: dirtyRows=${(dirtyRows == null ? void 0 : dirtyRows.length) ?? "null"}`
|
|
@@ -7577,21 +8809,63 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7577
8809
|
}
|
|
7578
8810
|
if (disposed)
|
|
7579
8811
|
return;
|
|
8812
|
+
cliLatency == null ? void 0 : cliLatency.recordStdoutRenderStart();
|
|
7580
8813
|
pendingRender = false;
|
|
7581
8814
|
accumulatedAllRows = false;
|
|
7582
8815
|
accumulatedDirtyBits = null;
|
|
7583
8816
|
accumulatedDirtyCount = 0;
|
|
7584
8817
|
accumulatedDirtyMin = Number.POSITIVE_INFINITY;
|
|
7585
8818
|
accumulatedDirtyMax = -1;
|
|
8819
|
+
accumulatedScrollOperations = null;
|
|
8820
|
+
accumulatedSkipUnchangedDirtyRows = true;
|
|
7586
8821
|
lastFrameTime = Date.now();
|
|
7587
8822
|
const renderStart = performance.now();
|
|
7588
8823
|
const size = terminal.size();
|
|
7589
8824
|
ensureRowEscapes(Math.max(size.rows, lastRenderedRows));
|
|
7590
|
-
|
|
8825
|
+
ensureFingerprints(size.cols, size.rows);
|
|
7591
8826
|
const bgSeq = openBg(defaultBg);
|
|
7592
8827
|
const bgOnlyStyle = { bg: defaultBg };
|
|
7593
8828
|
const bgKey = styleKeyFromParts({ bg: defaultBg });
|
|
8829
|
+
const blankFP = bgKey << 16 | charHash16(" ");
|
|
8830
|
+
const cellFingerprint = (cell) => styleKey2(cell.style) << 16 | charHash16(cell.ch);
|
|
8831
|
+
const lastOccupiedColumnInRow = (row, cols) => {
|
|
8832
|
+
const limit = Math.min(row.length, cols);
|
|
8833
|
+
for (let x = limit - 1; x >= 0; x--) {
|
|
8834
|
+
if (cellFingerprint(row[x]) !== blankFP)
|
|
8835
|
+
return x;
|
|
8836
|
+
}
|
|
8837
|
+
return -1;
|
|
8838
|
+
};
|
|
8839
|
+
const lastOccupiedColumnInReference = (source, y, cols) => {
|
|
8840
|
+
if (!fpCols || y < 0 || y >= fpRows)
|
|
8841
|
+
return -1;
|
|
8842
|
+
const limit = Math.min(fpCols, cols);
|
|
8843
|
+
const base = y * fpCols;
|
|
8844
|
+
for (let x = limit - 1; x >= 0; x--) {
|
|
8845
|
+
if (source[base + x] !== blankFP)
|
|
8846
|
+
return x;
|
|
8847
|
+
}
|
|
8848
|
+
return -1;
|
|
8849
|
+
};
|
|
8850
|
+
const shouldRewriteRowTail = (row, y, cols, reference) => lastOccupiedColumnInRow(row, cols) < lastOccupiedColumnInReference(reference, y, cols);
|
|
7594
8851
|
let dirtySorted = true;
|
|
8852
|
+
const normalizedScrollOperations = (() => {
|
|
8853
|
+
if (!(scrollOperations == null ? void 0 : scrollOperations.length))
|
|
8854
|
+
return null;
|
|
8855
|
+
const outOps = [];
|
|
8856
|
+
for (const op of scrollOperations) {
|
|
8857
|
+
const startY = Math.max(0, Math.min(size.rows, Math.floor(op.startY)));
|
|
8858
|
+
const endY = Math.max(0, Math.min(size.rows, Math.floor(op.endY)));
|
|
8859
|
+
const delta = Math.trunc(op.delta);
|
|
8860
|
+
if (endY <= startY || delta === 0 || Math.abs(delta) >= endY - startY)
|
|
8861
|
+
continue;
|
|
8862
|
+
outOps.push({ startY, endY, delta });
|
|
8863
|
+
}
|
|
8864
|
+
if (!outOps.length)
|
|
8865
|
+
return null;
|
|
8866
|
+
outOps.sort((a, b) => a.startY - b.startY);
|
|
8867
|
+
return outOps;
|
|
8868
|
+
})();
|
|
7595
8869
|
let rowsToRender = (() => {
|
|
7596
8870
|
if (!dirtyRows || dirtyRows.length === 0)
|
|
7597
8871
|
return null;
|
|
@@ -7617,13 +8891,16 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7617
8891
|
outRows.sort((a, b) => a - b);
|
|
7618
8892
|
return outRows;
|
|
7619
8893
|
})();
|
|
7620
|
-
if (
|
|
7621
|
-
|
|
8894
|
+
if (fpPrevValid && rowsToRender) {
|
|
8895
|
+
currentFP.set(prevFP);
|
|
7622
8896
|
}
|
|
7623
8897
|
const frameParts = [];
|
|
7624
8898
|
frameParts.push(!isGhostty && useSyncOutput ? SYNC_START : "");
|
|
7625
8899
|
frameParts.push("\x1B[?7l");
|
|
7626
8900
|
frameParts.push(SGR_RESET, bgSeq);
|
|
8901
|
+
let lastRenderedY = -1;
|
|
8902
|
+
let lastRenderWasFullRow = false;
|
|
8903
|
+
let hasFrameOutput = false;
|
|
7627
8904
|
let activeStyleKey = null;
|
|
7628
8905
|
let activeStyle = {
|
|
7629
8906
|
fg: null,
|
|
@@ -7688,13 +8965,17 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7688
8965
|
Math.min(row.length, Math.floor(endXExclusive))
|
|
7689
8966
|
);
|
|
7690
8967
|
if (spanStart >= spanEnd && !clearToEol) {
|
|
7691
|
-
renderedRowCache[y] = row.slice();
|
|
7692
8968
|
return;
|
|
7693
8969
|
}
|
|
8970
|
+
hasFrameOutput = true;
|
|
7694
8971
|
if (!disableCursorPos) {
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
8972
|
+
if (spanStart === 0 && lastRenderWasFullRow && y === lastRenderedY + 1) {
|
|
8973
|
+
frameParts.push("\r\n");
|
|
8974
|
+
} else {
|
|
8975
|
+
frameParts.push(
|
|
8976
|
+
spanStart === 0 ? rowCursorToCol1[y] : `\x1B[${y + 1};${spanStart + 1}H`
|
|
8977
|
+
);
|
|
8978
|
+
}
|
|
7698
8979
|
}
|
|
7699
8980
|
let currentKey = null;
|
|
7700
8981
|
let currentStyle = null;
|
|
@@ -7718,7 +8999,7 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7718
8999
|
}
|
|
7719
9000
|
continue;
|
|
7720
9001
|
}
|
|
7721
|
-
if (key === currentKey) {
|
|
9002
|
+
if (key === currentKey && !(key & 32768 && nextStyle.href !== (currentStyle == null ? void 0 : currentStyle.href))) {
|
|
7722
9003
|
currentTextParts.push(ch);
|
|
7723
9004
|
if (needsWideCursorFix(cell, ch)) {
|
|
7724
9005
|
currentTextParts.push(
|
|
@@ -7750,39 +9031,342 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7750
9031
|
}
|
|
7751
9032
|
frameParts.push("\x1B[K");
|
|
7752
9033
|
}
|
|
7753
|
-
|
|
9034
|
+
lastRenderedY = y;
|
|
9035
|
+
lastRenderWasFullRow = spanStart === 0 && clearToEol;
|
|
7754
9036
|
};
|
|
7755
|
-
|
|
9037
|
+
const overlayCoverage = overlayPlaneCoverageRows(size.rows);
|
|
9038
|
+
const overlayRows = Array.from(
|
|
9039
|
+
/* @__PURE__ */ new Set([
|
|
9040
|
+
...overlayCoverage.blockedRows,
|
|
9041
|
+
...prevOverlayBlockedRows
|
|
9042
|
+
])
|
|
9043
|
+
).sort((a, b) => a - b);
|
|
9044
|
+
const overlayRowSet = overlayRows.length ? new Set(overlayRows) : null;
|
|
9045
|
+
const overlayPartialRows = Array.from(
|
|
9046
|
+
/* @__PURE__ */ new Set([
|
|
9047
|
+
...overlayCoverage.partialRows,
|
|
9048
|
+
...prevOverlayPartialRows
|
|
9049
|
+
])
|
|
9050
|
+
).sort((a, b) => a - b);
|
|
9051
|
+
const overlayPartialRowSet = overlayPartialRows.length ? new Set(overlayPartialRows) : null;
|
|
9052
|
+
const overlayTouchedRowSet = (() => {
|
|
9053
|
+
if (!overlayRowSet && !overlayPartialRowSet)
|
|
9054
|
+
return null;
|
|
9055
|
+
return /* @__PURE__ */ new Set([
|
|
9056
|
+
...overlayRowSet ? Array.from(overlayRowSet) : [],
|
|
9057
|
+
...overlayPartialRowSet ? Array.from(overlayPartialRowSet) : []
|
|
9058
|
+
]);
|
|
9059
|
+
})();
|
|
9060
|
+
let explicitScrollOperations = normalizedScrollOperations;
|
|
9061
|
+
let hiddenExplicitDirtyRows = null;
|
|
9062
|
+
let allowInferredScrollRegions = true;
|
|
9063
|
+
if (explicitScrollOperations && overlayRows.length) {
|
|
9064
|
+
const preparedExplicit = prepareExplicitScrollOperations(
|
|
9065
|
+
explicitScrollOperations,
|
|
9066
|
+
overlayRowSet
|
|
9067
|
+
);
|
|
9068
|
+
hiddenExplicitDirtyRows = preparedExplicit.hiddenRows.size ? preparedExplicit.hiddenRows : null;
|
|
9069
|
+
if (preparedExplicit.operations) {
|
|
9070
|
+
explicitScrollOperations = preparedExplicit.operations;
|
|
9071
|
+
if (preparedExplicit.trimmed && isDebugEnabled()) {
|
|
9072
|
+
getDebugLog().render(
|
|
9073
|
+
` Explicit scroll ops clipped around overlay rows: ${normalizedScrollOperations.map((op, index) => `${op.startY}-${op.endY - 1}:${op.delta}->${explicitScrollOperations[index].startY}-${explicitScrollOperations[index].endY - 1}:${explicitScrollOperations[index].delta}`).join(", ")}`
|
|
9074
|
+
);
|
|
9075
|
+
}
|
|
9076
|
+
} else {
|
|
9077
|
+
allowInferredScrollRegions = false;
|
|
9078
|
+
const expandedRows = new Set(rowsToRender ?? []);
|
|
9079
|
+
for (const op of explicitScrollOperations) {
|
|
9080
|
+
for (let y = op.startY; y < op.endY; y++)
|
|
9081
|
+
expandedRows.add(y);
|
|
9082
|
+
}
|
|
9083
|
+
rowsToRender = Array.from(expandedRows).sort((a, b) => a - b);
|
|
9084
|
+
dirtySorted = true;
|
|
9085
|
+
explicitScrollOperations = null;
|
|
9086
|
+
hiddenExplicitDirtyRows = null;
|
|
9087
|
+
if (isDebugEnabled()) {
|
|
9088
|
+
getDebugLog().render(
|
|
9089
|
+
preparedExplicit.blockedInterior ? " Explicit scroll ops split by interior overlay rows; falling back to region repaint" : " Explicit scroll ops could not be clipped safely; falling back to region repaint"
|
|
9090
|
+
);
|
|
9091
|
+
}
|
|
9092
|
+
}
|
|
9093
|
+
}
|
|
9094
|
+
const scrollRowsCandidate = rowsToRender;
|
|
9095
|
+
if (explicitScrollOperations && rowsToRender && (!enableScrollRegions || !fpPrevValid)) {
|
|
9096
|
+
const expandedRows = new Set(rowsToRender);
|
|
9097
|
+
for (const op of explicitScrollOperations) {
|
|
9098
|
+
for (let y = op.startY; y < op.endY; y++) {
|
|
9099
|
+
if (hiddenExplicitDirtyRows == null ? void 0 : hiddenExplicitDirtyRows.has(y))
|
|
9100
|
+
continue;
|
|
9101
|
+
expandedRows.add(y);
|
|
9102
|
+
}
|
|
9103
|
+
}
|
|
9104
|
+
rowsToRender = Array.from(expandedRows).sort((a, b) => a - b);
|
|
9105
|
+
dirtySorted = true;
|
|
9106
|
+
explicitScrollOperations = null;
|
|
9107
|
+
hiddenExplicitDirtyRows = null;
|
|
9108
|
+
if (isDebugEnabled()) {
|
|
9109
|
+
getDebugLog().render(
|
|
9110
|
+
enableScrollRegions ? " Explicit scroll ops fell back to region repaint because previous fingerprints are unavailable" : " Explicit scroll ops fell back to region repaint because scroll regions are disabled"
|
|
9111
|
+
);
|
|
9112
|
+
}
|
|
9113
|
+
}
|
|
9114
|
+
const denseDirtyRows = Boolean(
|
|
9115
|
+
rowsToRender && rowsToRender.length >= size.rows * dirtyFullThreshold
|
|
9116
|
+
);
|
|
9117
|
+
if (denseDirtyRows) {
|
|
9118
|
+
rowsToRender = null;
|
|
9119
|
+
}
|
|
9120
|
+
let profiledRowCount = rowsToRender ? rowsToRender.length : size.rows;
|
|
9121
|
+
const useScrollRegions = enableScrollRegions && fpPrevValid && scrollRowsCandidate && scrollRowsCandidate.length >= 3 && allowInferredScrollRegions;
|
|
9122
|
+
let scrollHandled = false;
|
|
9123
|
+
if (enableScrollRegions && explicitScrollOperations && scrollRowsCandidate && fpPrevValid) {
|
|
9124
|
+
if (currentFP.length === prevFP.length)
|
|
9125
|
+
currentFP.set(prevFP);
|
|
9126
|
+
const insertedRows = /* @__PURE__ */ new Set();
|
|
9127
|
+
const explicitRowsToRender = /* @__PURE__ */ new Set();
|
|
9128
|
+
for (const y of scrollRowsCandidate) {
|
|
9129
|
+
if (hiddenExplicitDirtyRows == null ? void 0 : hiddenExplicitDirtyRows.has(y))
|
|
9130
|
+
continue;
|
|
9131
|
+
explicitRowsToRender.add(y);
|
|
9132
|
+
}
|
|
9133
|
+
if (isDebugEnabled()) {
|
|
9134
|
+
getDebugLog().render(
|
|
9135
|
+
` Explicit scroll ops: ${explicitScrollOperations.map((op) => `${op.startY}-${op.endY - 1}:${op.delta}`).join(", ")}`
|
|
9136
|
+
);
|
|
9137
|
+
}
|
|
9138
|
+
for (const op of explicitScrollOperations) {
|
|
9139
|
+
hasFrameOutput = true;
|
|
9140
|
+
frameParts.push(`\x1B[${op.startY + 1};${op.endY}r`);
|
|
9141
|
+
if (op.delta > 0) {
|
|
9142
|
+
frameParts.push(`\x1B[${op.endY};1H`);
|
|
9143
|
+
frameParts.push(`\x1B[${op.delta}S`);
|
|
9144
|
+
for (let y = op.startY; y < op.endY - op.delta; y++) {
|
|
9145
|
+
const dstBase = y * fpCols;
|
|
9146
|
+
const srcBase = (y + op.delta) * fpCols;
|
|
9147
|
+
for (let x = 0; x < size.cols; x++)
|
|
9148
|
+
currentFP[dstBase + x] = prevFP[srcBase + x];
|
|
9149
|
+
}
|
|
9150
|
+
for (let y = op.endY - op.delta; y < op.endY; y++) {
|
|
9151
|
+
const base = y * fpCols;
|
|
9152
|
+
insertedRows.add(y);
|
|
9153
|
+
explicitRowsToRender.add(y);
|
|
9154
|
+
for (let x = 0; x < size.cols; x++)
|
|
9155
|
+
currentFP[base + x] = blankFP;
|
|
9156
|
+
}
|
|
9157
|
+
} else {
|
|
9158
|
+
const absDelta = -op.delta;
|
|
9159
|
+
frameParts.push(`\x1B[${op.startY + 1};1H`);
|
|
9160
|
+
frameParts.push(`\x1B[${absDelta}T`);
|
|
9161
|
+
for (let y = op.endY - 1; y >= op.startY + absDelta; y--) {
|
|
9162
|
+
const dstBase = y * fpCols;
|
|
9163
|
+
const srcBase = (y - absDelta) * fpCols;
|
|
9164
|
+
for (let x = 0; x < size.cols; x++)
|
|
9165
|
+
currentFP[dstBase + x] = prevFP[srcBase + x];
|
|
9166
|
+
}
|
|
9167
|
+
for (let y = op.startY; y < op.startY + absDelta; y++) {
|
|
9168
|
+
const base = y * fpCols;
|
|
9169
|
+
insertedRows.add(y);
|
|
9170
|
+
explicitRowsToRender.add(y);
|
|
9171
|
+
for (let x = 0; x < size.cols; x++)
|
|
9172
|
+
currentFP[base + x] = blankFP;
|
|
9173
|
+
}
|
|
9174
|
+
}
|
|
9175
|
+
frameParts.push("\x1B[r");
|
|
9176
|
+
}
|
|
9177
|
+
const explicitDirtyRows = Array.from(explicitRowsToRender).sort(
|
|
9178
|
+
(a, b) => a - b
|
|
9179
|
+
);
|
|
9180
|
+
const overlayDirtyRows = overlayTouchedRowSet ? explicitDirtyRows.filter((y) => overlayTouchedRowSet.has(y)) : [];
|
|
9181
|
+
const paintedExplicitRows = [];
|
|
9182
|
+
for (const y of explicitDirtyRows) {
|
|
9183
|
+
const row = terminal.getRow(y);
|
|
9184
|
+
const overlayRow = overlayTouchedRowSet == null ? void 0 : overlayTouchedRowSet.has(y);
|
|
9185
|
+
if (overlayRow || useConservativeDirtyRowRendering) {
|
|
9186
|
+
fingerprintRow(row, y, size.cols);
|
|
9187
|
+
renderRow2(y, row);
|
|
9188
|
+
paintedExplicitRows.push(y);
|
|
9189
|
+
continue;
|
|
9190
|
+
}
|
|
9191
|
+
const span = (() => {
|
|
9192
|
+
if (insertedRows.has(y)) {
|
|
9193
|
+
fingerprintRow(row, y, size.cols);
|
|
9194
|
+
return resolveChangedSpanAgainstFill(row, y, size.cols, blankFP);
|
|
9195
|
+
}
|
|
9196
|
+
return resolveChangedSpanAgainstReference(row, y, size.cols);
|
|
9197
|
+
})();
|
|
9198
|
+
if (!span) {
|
|
9199
|
+
if (!skipUnchangedDirtyRows)
|
|
9200
|
+
fingerprintRow(row, y, size.cols);
|
|
9201
|
+
if (!skipUnchangedDirtyRows) {
|
|
9202
|
+
renderRow2(y, row);
|
|
9203
|
+
paintedExplicitRows.push(y);
|
|
9204
|
+
}
|
|
9205
|
+
continue;
|
|
9206
|
+
}
|
|
9207
|
+
const rewriteTail = !insertedRows.has(y) && shouldRewriteRowTail(row, y, size.cols, currentFP);
|
|
9208
|
+
fingerprintRow(row, y, size.cols);
|
|
9209
|
+
renderRow2(
|
|
9210
|
+
y,
|
|
9211
|
+
row,
|
|
9212
|
+
span.startX,
|
|
9213
|
+
rewriteTail ? row.length : span.endXExclusive,
|
|
9214
|
+
rewriteTail || span.endXExclusive >= row.length
|
|
9215
|
+
);
|
|
9216
|
+
paintedExplicitRows.push(y);
|
|
9217
|
+
}
|
|
9218
|
+
if (isDebugEnabled() && overlayDirtyRows.length) {
|
|
9219
|
+
getDebugLog().render(
|
|
9220
|
+
` Explicit scroll ops overlay rows: [${overlayDirtyRows.join(", ")}]`
|
|
9221
|
+
);
|
|
9222
|
+
}
|
|
9223
|
+
profiledRowCount = explicitDirtyRows.length;
|
|
9224
|
+
scrollHandled = true;
|
|
9225
|
+
} else if (useScrollRegions && scrollRowsCandidate) {
|
|
9226
|
+
for (let y = 0; y < size.rows; y++) {
|
|
9227
|
+
fingerprintRow(terminal.getRow(y), y, size.cols);
|
|
9228
|
+
}
|
|
9229
|
+
const shift = detectScrollShift(
|
|
9230
|
+
size.cols,
|
|
9231
|
+
scrollRowsCandidate,
|
|
9232
|
+
overlayRows
|
|
9233
|
+
);
|
|
9234
|
+
if (shift) {
|
|
9235
|
+
if (currentFP.length === prevFP.length)
|
|
9236
|
+
currentFP.set(prevFP);
|
|
9237
|
+
hasFrameOutput = true;
|
|
9238
|
+
if (isDebugEnabled()) {
|
|
9239
|
+
getDebugLog().render(
|
|
9240
|
+
` Scroll region: delta=${shift.delta}, region=${shift.regionStart}-${shift.regionEnd - 1}, new rows=${shift.newRowStart}-${shift.newRowEnd - 1}`
|
|
9241
|
+
);
|
|
9242
|
+
}
|
|
9243
|
+
frameParts.push(`\x1B[${shift.regionStart + 1};${shift.regionEnd}r`);
|
|
9244
|
+
if (shift.delta > 0) {
|
|
9245
|
+
frameParts.push(`\x1B[${shift.regionEnd};1H`);
|
|
9246
|
+
frameParts.push(`\x1B[${shift.delta}S`);
|
|
9247
|
+
} else {
|
|
9248
|
+
frameParts.push(`\x1B[${shift.regionStart + 1};1H`);
|
|
9249
|
+
frameParts.push(`\x1B[${-shift.delta}T`);
|
|
9250
|
+
}
|
|
9251
|
+
frameParts.push("\x1B[r");
|
|
9252
|
+
if (shift.delta > 0) {
|
|
9253
|
+
for (let y = shift.regionStart; y < shift.regionEnd - shift.delta; y++) {
|
|
9254
|
+
const dstBase = y * fpCols;
|
|
9255
|
+
const srcBase = (y + shift.delta) * fpCols;
|
|
9256
|
+
for (let x = 0; x < size.cols; x++)
|
|
9257
|
+
currentFP[dstBase + x] = prevFP[srcBase + x];
|
|
9258
|
+
}
|
|
9259
|
+
for (let y = shift.regionEnd - shift.delta; y < shift.regionEnd; y++) {
|
|
9260
|
+
const base = y * fpCols;
|
|
9261
|
+
for (let x = 0; x < size.cols; x++)
|
|
9262
|
+
currentFP[base + x] = blankFP;
|
|
9263
|
+
}
|
|
9264
|
+
} else {
|
|
9265
|
+
const absDelta = -shift.delta;
|
|
9266
|
+
for (let y = shift.regionEnd - 1; y >= shift.regionStart + absDelta; y--) {
|
|
9267
|
+
const dstBase = y * fpCols;
|
|
9268
|
+
const srcBase = (y - absDelta) * fpCols;
|
|
9269
|
+
for (let x = 0; x < size.cols; x++)
|
|
9270
|
+
currentFP[dstBase + x] = prevFP[srcBase + x];
|
|
9271
|
+
}
|
|
9272
|
+
for (let y = shift.regionStart; y < shift.regionStart + absDelta; y++) {
|
|
9273
|
+
const base = y * fpCols;
|
|
9274
|
+
for (let x = 0; x < size.cols; x++)
|
|
9275
|
+
currentFP[base + x] = blankFP;
|
|
9276
|
+
}
|
|
9277
|
+
}
|
|
9278
|
+
for (let y = shift.newRowStart; y < shift.newRowEnd; y++) {
|
|
9279
|
+
const row = terminal.getRow(y);
|
|
9280
|
+
fingerprintRow(row, y, size.cols);
|
|
9281
|
+
renderRow2(y, row);
|
|
9282
|
+
}
|
|
9283
|
+
const extraDirtyRows = overlayRowSet ? shift.extraDirtyRows.filter(
|
|
9284
|
+
(y) => !overlayRowSet.has(y) || Boolean(overlayPartialRowSet == null ? void 0 : overlayPartialRowSet.has(y))
|
|
9285
|
+
) : shift.extraDirtyRows;
|
|
9286
|
+
for (const y of extraDirtyRows) {
|
|
9287
|
+
const row = terminal.getRow(y);
|
|
9288
|
+
const overlayRow = overlayTouchedRowSet == null ? void 0 : overlayTouchedRowSet.has(y);
|
|
9289
|
+
if (overlayRow || useConservativeDirtyRowRendering) {
|
|
9290
|
+
fingerprintRow(row, y, size.cols);
|
|
9291
|
+
renderRow2(y, row);
|
|
9292
|
+
continue;
|
|
9293
|
+
}
|
|
9294
|
+
const span = resolveChangedSpanAgainstReference(row, y, size.cols);
|
|
9295
|
+
if (!span) {
|
|
9296
|
+
if (!skipUnchangedDirtyRows) {
|
|
9297
|
+
fingerprintRow(row, y, size.cols);
|
|
9298
|
+
renderRow2(y, row);
|
|
9299
|
+
}
|
|
9300
|
+
continue;
|
|
9301
|
+
}
|
|
9302
|
+
const rewriteTail = shouldRewriteRowTail(row, y, size.cols, currentFP);
|
|
9303
|
+
renderRow2(
|
|
9304
|
+
y,
|
|
9305
|
+
row,
|
|
9306
|
+
span.startX,
|
|
9307
|
+
rewriteTail ? row.length : span.endXExclusive,
|
|
9308
|
+
rewriteTail || span.endXExclusive >= row.length
|
|
9309
|
+
);
|
|
9310
|
+
fingerprintRow(row, y, size.cols);
|
|
9311
|
+
}
|
|
9312
|
+
for (let y = shift.newRowStart; y < shift.newRowEnd; y++) {
|
|
9313
|
+
fingerprintRow(terminal.getRow(y), y, size.cols);
|
|
9314
|
+
}
|
|
9315
|
+
const renderedRows = /* @__PURE__ */ new Set();
|
|
9316
|
+
for (let y = shift.newRowStart; y < shift.newRowEnd; y++)
|
|
9317
|
+
renderedRows.add(y);
|
|
9318
|
+
for (const y of extraDirtyRows)
|
|
9319
|
+
renderedRows.add(y);
|
|
9320
|
+
profiledRowCount = renderedRows.size;
|
|
9321
|
+
scrollHandled = true;
|
|
9322
|
+
}
|
|
9323
|
+
}
|
|
9324
|
+
if (!scrollHandled && denseDirtyRows && scrollRowsCandidate && useScrollRegions) {
|
|
9325
|
+
rowsToRender = scrollRowsCandidate;
|
|
9326
|
+
profiledRowCount = rowsToRender.length;
|
|
9327
|
+
if (isDebugEnabled()) {
|
|
9328
|
+
getDebugLog().render(
|
|
9329
|
+
` Dense dirty rows fell back to partial render: ${rowsToRender.length} rows`
|
|
9330
|
+
);
|
|
9331
|
+
}
|
|
9332
|
+
}
|
|
9333
|
+
if (scrollHandled) {
|
|
9334
|
+
} else if (!rowsToRender) {
|
|
7756
9335
|
if (isDebugEnabled())
|
|
7757
9336
|
getDebugLog().render(` Full render: ${size.rows} rows`);
|
|
7758
9337
|
for (let y = 0; y < size.rows; y++) {
|
|
7759
9338
|
const row = terminal.getRow(y);
|
|
9339
|
+
fingerprintRow(row, y, size.cols);
|
|
7760
9340
|
renderRow2(y, row);
|
|
7761
9341
|
}
|
|
7762
9342
|
} else {
|
|
7763
|
-
const
|
|
9343
|
+
const overlayDirtyRows = overlayTouchedRowSet ? rowsToRender.filter((y) => overlayTouchedRowSet.has(y)) : [];
|
|
7764
9344
|
if (isDebugEnabled()) {
|
|
7765
9345
|
getDebugLog().render(
|
|
7766
|
-
` Partial render: ${rowsToRender.length} dirty rows: [${rowsToRender.join(", ")}]${
|
|
9346
|
+
` Partial render: ${rowsToRender.length} dirty rows: [${rowsToRender.join(", ")}]${overlayDirtyRows.length ? ` (overlay-full-row: [${overlayDirtyRows.join(", ")}])` : ""}`
|
|
7767
9347
|
);
|
|
7768
9348
|
}
|
|
7769
9349
|
for (const y of rowsToRender) {
|
|
7770
9350
|
const row = terminal.getRow(y);
|
|
7771
|
-
|
|
9351
|
+
fingerprintRow(row, y, size.cols);
|
|
9352
|
+
const overlayRow = overlayTouchedRowSet == null ? void 0 : overlayTouchedRowSet.has(y);
|
|
9353
|
+
if (overlayRow || useConservativeDirtyRowRendering) {
|
|
7772
9354
|
renderRow2(y, row);
|
|
7773
9355
|
continue;
|
|
7774
9356
|
}
|
|
7775
|
-
const span = resolveChangedSpan(row,
|
|
9357
|
+
const span = resolveChangedSpan(row, y, size.cols);
|
|
7776
9358
|
if (!span) {
|
|
7777
|
-
|
|
9359
|
+
if (!skipUnchangedDirtyRows)
|
|
9360
|
+
renderRow2(y, row);
|
|
7778
9361
|
continue;
|
|
7779
9362
|
}
|
|
9363
|
+
const rewriteTail = shouldRewriteRowTail(row, y, size.cols, prevFP);
|
|
7780
9364
|
renderRow2(
|
|
7781
9365
|
y,
|
|
7782
9366
|
row,
|
|
7783
9367
|
span.startX,
|
|
7784
|
-
span.endXExclusive,
|
|
7785
|
-
span.endXExclusive >= row.length
|
|
9368
|
+
rewriteTail ? row.length : span.endXExclusive,
|
|
9369
|
+
rewriteTail || span.endXExclusive >= row.length
|
|
7786
9370
|
);
|
|
7787
9371
|
}
|
|
7788
9372
|
}
|
|
@@ -7793,20 +9377,36 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7793
9377
|
activeStyleKey = bgKey;
|
|
7794
9378
|
}
|
|
7795
9379
|
for (let i = 0; i < extraRows; i++) {
|
|
9380
|
+
hasFrameOutput = true;
|
|
7796
9381
|
frameParts.push(rowClearToEol[size.rows + i]);
|
|
7797
9382
|
}
|
|
7798
9383
|
}
|
|
7799
9384
|
if (!rowsToRender)
|
|
7800
9385
|
lastRenderedRows = size.rows;
|
|
7801
|
-
|
|
7802
|
-
|
|
9386
|
+
const tmpFP = prevFP;
|
|
9387
|
+
prevFP = currentFP;
|
|
9388
|
+
currentFP = tmpFP;
|
|
9389
|
+
fpPrevValid = true;
|
|
9390
|
+
prevOverlayBlockedRows = overlayCoverage.blockedRows;
|
|
9391
|
+
prevOverlayPartialRows = overlayCoverage.partialRows;
|
|
9392
|
+
let emittedCursorPos = null;
|
|
7803
9393
|
if (getImeAnchor) {
|
|
7804
9394
|
const anchor = getImeAnchor();
|
|
7805
9395
|
if (anchor) {
|
|
7806
9396
|
const { x, y } = clampCellToViewport(anchor, size);
|
|
7807
|
-
|
|
9397
|
+
if (hasFrameOutput || x !== lastCursorX || y !== lastCursorY) {
|
|
9398
|
+
hasFrameOutput = true;
|
|
9399
|
+
emittedCursorPos = { x, y };
|
|
9400
|
+
frameParts.push(`\x1B[${y + 1};${x + 1}H`);
|
|
9401
|
+
}
|
|
7808
9402
|
}
|
|
7809
9403
|
}
|
|
9404
|
+
if (!hasFrameOutput) {
|
|
9405
|
+
if (isDebugEnabled())
|
|
9406
|
+
getDebugLog().render(" No-op frame skipped");
|
|
9407
|
+
cliLatency == null ? void 0 : cliLatency.recordStdoutNoOutput();
|
|
9408
|
+
return;
|
|
9409
|
+
}
|
|
7810
9410
|
if (enableOsc8Links && activeStyle.href)
|
|
7811
9411
|
frameParts.push(OSC8_CLOSE);
|
|
7812
9412
|
frameParts.push(SGR_RESET);
|
|
@@ -7816,9 +9416,9 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7816
9416
|
if (profiler) {
|
|
7817
9417
|
profiler.recordRender({
|
|
7818
9418
|
durationMs: profiler.now() - renderStart,
|
|
7819
|
-
rows:
|
|
9419
|
+
rows: profiledRowCount,
|
|
7820
9420
|
nodes: 0,
|
|
7821
|
-
fullRepaint: !rowsToRender,
|
|
9421
|
+
fullRepaint: !rowsToRender && !scrollHandled,
|
|
7822
9422
|
sorted: dirtySorted
|
|
7823
9423
|
});
|
|
7824
9424
|
}
|
|
@@ -7944,6 +9544,13 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7944
9544
|
{
|
|
7945
9545
|
const writeMs = performance.now() - writeStart;
|
|
7946
9546
|
writeEmaMs = writeEmaMs === 0 ? writeMs : writeEmaMs * 0.85 + writeMs * 0.15;
|
|
9547
|
+
if (emittedCursorPos) {
|
|
9548
|
+
lastCursorX = emittedCursorPos.x;
|
|
9549
|
+
lastCursorY = emittedCursorPos.y;
|
|
9550
|
+
} else {
|
|
9551
|
+
lastCursorX = null;
|
|
9552
|
+
lastCursorY = null;
|
|
9553
|
+
}
|
|
7947
9554
|
recordStdoutFrame({
|
|
7948
9555
|
at: Date.now(),
|
|
7949
9556
|
bytes: frame.length,
|
|
@@ -7958,6 +9565,11 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7958
9565
|
mode: writeMode === "sync" ? "sync" : writeMode === "chunked" ? "chunked" : "stream"
|
|
7959
9566
|
});
|
|
7960
9567
|
}
|
|
9568
|
+
cliLatency == null ? void 0 : cliLatency.recordStdoutWrite({
|
|
9569
|
+
durationMs: writeMs,
|
|
9570
|
+
bytes: frame.length,
|
|
9571
|
+
mode: writeMode === "sync" ? "sync" : writeMode === "chunked" ? "chunked" : "stream"
|
|
9572
|
+
});
|
|
7961
9573
|
}
|
|
7962
9574
|
if (isDebugEnabled()) {
|
|
7963
9575
|
const totalTime = (performance.now() - renderStart).toFixed(2);
|
|
@@ -7965,7 +9577,7 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7965
9577
|
getDebugLog().render(`doRender() END`);
|
|
7966
9578
|
}
|
|
7967
9579
|
}
|
|
7968
|
-
function render(dirtyRows) {
|
|
9580
|
+
function render(dirtyRows, sync, scrollOperations, skipUnchangedDirtyRows = false) {
|
|
7969
9581
|
if (disposed)
|
|
7970
9582
|
return;
|
|
7971
9583
|
if (isDebugEnabled()) {
|
|
@@ -7973,6 +9585,24 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7973
9585
|
`render() called: dirtyRows=${(dirtyRows == null ? void 0 : dirtyRows.length) ?? "null"}, pending=${pendingRender}, elapsed=${Date.now() - lastFrameTime}ms`
|
|
7974
9586
|
);
|
|
7975
9587
|
}
|
|
9588
|
+
const isSmallSyncPatch = Boolean(
|
|
9589
|
+
sync && (dirtyRows == null ? void 0 : dirtyRows.length) && dirtyRows.length <= 12 && !(scrollOperations == null ? void 0 : scrollOperations.length)
|
|
9590
|
+
);
|
|
9591
|
+
if (isSmallSyncPatch)
|
|
9592
|
+
skipUnchangedDirtyRows = false;
|
|
9593
|
+
if ((dirtyRows == null ? void 0 : dirtyRows.length) && skipUnchangedDirtyRows && fpPrevValid && !(scrollOperations == null ? void 0 : scrollOperations.length) && dirtyRows.length < terminal.size().rows) {
|
|
9594
|
+
const cols = terminal.size().cols;
|
|
9595
|
+
const nextDirtyRows = dirtyRows.filter((y) => !rowMatchesPreviousFrame(y, cols));
|
|
9596
|
+
if (nextDirtyRows.length === 0) {
|
|
9597
|
+
if (isDebugEnabled()) {
|
|
9598
|
+
getDebugLog().render(
|
|
9599
|
+
`Skipped unchanged dirty commit: ${dirtyRows.length} rows`
|
|
9600
|
+
);
|
|
9601
|
+
}
|
|
9602
|
+
return;
|
|
9603
|
+
}
|
|
9604
|
+
dirtyRows = nextDirtyRows;
|
|
9605
|
+
}
|
|
7976
9606
|
const ensureDirtyBits = (rowCount) => {
|
|
7977
9607
|
if (!accumulatedDirtyBits || accumulatedDirtyBits.length !== rowCount) {
|
|
7978
9608
|
accumulatedDirtyBits = new Uint8Array(rowCount);
|
|
@@ -8003,12 +9633,43 @@ function createStdoutRenderer(terminal, options) {
|
|
|
8003
9633
|
out2.length = outLen;
|
|
8004
9634
|
return outLen ? out2 : null;
|
|
8005
9635
|
};
|
|
9636
|
+
const buildAccumulatedScrollOperations = () => {
|
|
9637
|
+
return (accumulatedScrollOperations == null ? void 0 : accumulatedScrollOperations.length) ? accumulatedScrollOperations : null;
|
|
9638
|
+
};
|
|
9639
|
+
const mergeScrollOperations = (next) => {
|
|
9640
|
+
if (!(next == null ? void 0 : next.length) || accumulatedAllRows)
|
|
9641
|
+
return;
|
|
9642
|
+
const merged = accumulatedScrollOperations ? accumulatedScrollOperations.slice() : [];
|
|
9643
|
+
for (const op of next) {
|
|
9644
|
+
const startY = Math.floor(op.startY);
|
|
9645
|
+
const endY = Math.floor(op.endY);
|
|
9646
|
+
const delta = Math.trunc(op.delta);
|
|
9647
|
+
if (endY <= startY || delta === 0)
|
|
9648
|
+
continue;
|
|
9649
|
+
const existingIndex = merged.findIndex(
|
|
9650
|
+
(existing) => existing.startY === startY && existing.endY === endY
|
|
9651
|
+
);
|
|
9652
|
+
if (existingIndex >= 0) {
|
|
9653
|
+
const existing = merged[existingIndex];
|
|
9654
|
+
const nextDelta = existing.delta + delta;
|
|
9655
|
+
if (nextDelta === 0)
|
|
9656
|
+
merged.splice(existingIndex, 1);
|
|
9657
|
+
else
|
|
9658
|
+
merged[existingIndex] = { startY, endY, delta: nextDelta };
|
|
9659
|
+
} else {
|
|
9660
|
+
merged.push({ startY, endY, delta });
|
|
9661
|
+
}
|
|
9662
|
+
}
|
|
9663
|
+
accumulatedScrollOperations = merged.length ? merged : null;
|
|
9664
|
+
};
|
|
8006
9665
|
if (!dirtyRows || dirtyRows.length === 0) {
|
|
8007
9666
|
accumulatedAllRows = true;
|
|
8008
9667
|
accumulatedDirtyBits = null;
|
|
8009
9668
|
accumulatedDirtyCount = 0;
|
|
8010
9669
|
accumulatedDirtyMin = Number.POSITIVE_INFINITY;
|
|
8011
9670
|
accumulatedDirtyMax = -1;
|
|
9671
|
+
accumulatedScrollOperations = null;
|
|
9672
|
+
accumulatedSkipUnchangedDirtyRows = false;
|
|
8012
9673
|
} else if (!accumulatedAllRows) {
|
|
8013
9674
|
const rowCount = terminal.size().rows;
|
|
8014
9675
|
const bits = ensureDirtyBits(rowCount);
|
|
@@ -8025,14 +9686,35 @@ function createStdoutRenderer(terminal, options) {
|
|
|
8025
9686
|
accumulatedDirtyMax = y;
|
|
8026
9687
|
}
|
|
8027
9688
|
}
|
|
9689
|
+
mergeScrollOperations(scrollOperations);
|
|
9690
|
+
accumulatedSkipUnchangedDirtyRows && (accumulatedSkipUnchangedDirtyRows = skipUnchangedDirtyRows);
|
|
9691
|
+
}
|
|
9692
|
+
const now4 = Date.now();
|
|
9693
|
+
const elapsed = now4 - lastFrameTime;
|
|
9694
|
+
const queuedDelayMs = Math.max(0, MIN_FRAME_MS - elapsed);
|
|
9695
|
+
if (pendingRender && !sync) {
|
|
9696
|
+
cliLatency == null ? void 0 : cliLatency.recordStdoutQueued(queuedDelayMs);
|
|
9697
|
+
return;
|
|
8028
9698
|
}
|
|
8029
|
-
if (
|
|
9699
|
+
if (sync) {
|
|
9700
|
+
if (pendingRender) {
|
|
9701
|
+
pendingRender = false;
|
|
9702
|
+
if (renderTimer) {
|
|
9703
|
+
clearTimeout(renderTimer);
|
|
9704
|
+
renderTimer = null;
|
|
9705
|
+
}
|
|
9706
|
+
}
|
|
9707
|
+
const rows = buildAccumulatedRows();
|
|
9708
|
+
const pendingScrolls = buildAccumulatedScrollOperations();
|
|
9709
|
+
cliLatency == null ? void 0 : cliLatency.recordStdoutQueued(0);
|
|
9710
|
+
doRender(rows, pendingScrolls, accumulatedSkipUnchangedDirtyRows);
|
|
8030
9711
|
return;
|
|
8031
|
-
|
|
8032
|
-
const elapsed = now3 - lastFrameTime;
|
|
9712
|
+
}
|
|
8033
9713
|
if (elapsed >= MIN_FRAME_MS) {
|
|
8034
9714
|
const rows = buildAccumulatedRows();
|
|
8035
|
-
|
|
9715
|
+
const pendingScrolls = buildAccumulatedScrollOperations();
|
|
9716
|
+
cliLatency == null ? void 0 : cliLatency.recordStdoutQueued(0);
|
|
9717
|
+
doRender(rows, pendingScrolls, accumulatedSkipUnchangedDirtyRows);
|
|
8036
9718
|
} else {
|
|
8037
9719
|
pendingRender = true;
|
|
8038
9720
|
if (renderTimer)
|
|
@@ -8041,11 +9723,16 @@ function createStdoutRenderer(terminal, options) {
|
|
|
8041
9723
|
renderTimer = null;
|
|
8042
9724
|
if (!disposed) {
|
|
8043
9725
|
const rows = buildAccumulatedRows();
|
|
8044
|
-
|
|
9726
|
+
const pendingScrolls = buildAccumulatedScrollOperations();
|
|
9727
|
+
doRender(rows, pendingScrolls, accumulatedSkipUnchangedDirtyRows);
|
|
8045
9728
|
}
|
|
8046
|
-
},
|
|
9729
|
+
}, queuedDelayMs);
|
|
9730
|
+
cliLatency == null ? void 0 : cliLatency.recordStdoutQueued(queuedDelayMs);
|
|
8047
9731
|
}
|
|
8048
9732
|
}
|
|
9733
|
+
terminal.setFingerprintFn((ch, style) => {
|
|
9734
|
+
return styleKey2(style) << 16 | charHash16(ch);
|
|
9735
|
+
});
|
|
8049
9736
|
if (altScreen && out.isTTY)
|
|
8050
9737
|
out.write("\x1B[?1049h");
|
|
8051
9738
|
if (hideCursor)
|
|
@@ -8053,13 +9740,13 @@ function createStdoutRenderer(terminal, options) {
|
|
|
8053
9740
|
if (clear) {
|
|
8054
9741
|
out.write(`${SGR_RESET}${openBg(defaultBg)}\x1B[2J\x1B[H${SGR_RESET}`);
|
|
8055
9742
|
}
|
|
8056
|
-
const off = terminal.on("commit", ({ dirtyRows }) => {
|
|
9743
|
+
const off = terminal.on("commit", ({ dirtyRows, scrollOperations, sync }) => {
|
|
8057
9744
|
if (isDebugEnabled()) {
|
|
8058
9745
|
getDebugLog().render(
|
|
8059
|
-
`Commit event: dirtyRows=${(dirtyRows == null ? void 0 : dirtyRows.length) ?? "null"}, rows=${(dirtyRows == null ? void 0 : dirtyRows.join(",")) ?? "all"}`
|
|
9746
|
+
`Commit event: dirtyRows=${(dirtyRows == null ? void 0 : dirtyRows.length) ?? "null"}, rows=${(dirtyRows == null ? void 0 : dirtyRows.join(",")) ?? "all"}${(scrollOperations == null ? void 0 : scrollOperations.length) ? `, scrollOps=${scrollOperations.map((op) => `${op.startY}-${op.endY - 1}:${op.delta}`).join("|")}` : ""}${sync ? " (sync)" : ""}`
|
|
8060
9747
|
);
|
|
8061
9748
|
}
|
|
8062
|
-
render(dirtyRows);
|
|
9749
|
+
render(dirtyRows, sync, scrollOperations, true);
|
|
8063
9750
|
});
|
|
8064
9751
|
const resizeSource = (options == null ? void 0 : options.output) ?? import_node_process9.default.stdout;
|
|
8065
9752
|
const canTrackResize = Boolean(
|
|
@@ -8093,6 +9780,8 @@ function createStdoutRenderer(terminal, options) {
|
|
|
8093
9780
|
{ cols: size.cols, rows: size.rows }
|
|
8094
9781
|
);
|
|
8095
9782
|
out.write(`\x1B[${cy + 1};${cx + 1}H`);
|
|
9783
|
+
lastCursorX = cx;
|
|
9784
|
+
lastCursorY = cy;
|
|
8096
9785
|
}
|
|
8097
9786
|
function showCursor(visible) {
|
|
8098
9787
|
if (disposed)
|
|
@@ -8137,7 +9826,10 @@ function createStdoutRenderer(terminal, options) {
|
|
|
8137
9826
|
if ("palette" in next)
|
|
8138
9827
|
palette = next.palette;
|
|
8139
9828
|
styleKeyCache2 = /* @__PURE__ */ new WeakMap();
|
|
8140
|
-
|
|
9829
|
+
fpRows = 0;
|
|
9830
|
+
fpPrevValid = false;
|
|
9831
|
+
prevOverlayBlockedRows = [];
|
|
9832
|
+
prevOverlayPartialRows = [];
|
|
8141
9833
|
render();
|
|
8142
9834
|
};
|
|
8143
9835
|
return { render, dispose, setCursor, showCursor, updateTheme };
|
|
@@ -8324,6 +10016,12 @@ var rowCache = /* @__PURE__ */ new WeakMap();
|
|
|
8324
10016
|
function segmentsToKey(segments) {
|
|
8325
10017
|
return segments.map((s) => `${s.key}:${s.text}:${s.cols}:${s.wide}`).join("|");
|
|
8326
10018
|
}
|
|
10019
|
+
function isPlainStyle(style) {
|
|
10020
|
+
return !style.fg && !style.bg && !style.bold && !style.dim && !style.italic && !style.underline && !style.inverse && !style.href;
|
|
10021
|
+
}
|
|
10022
|
+
function isTransparentBlankRow(segments) {
|
|
10023
|
+
return segments.length === 1 && isPlainStyle(segments[0].style) && segments[0].text.trim().length === 0;
|
|
10024
|
+
}
|
|
8327
10025
|
function renderRow(terminal, metrics2, wideScaleX, y, lineEl) {
|
|
8328
10026
|
const segments = computeRowSegments(terminal, y);
|
|
8329
10027
|
const newKey = segmentsToKey(segments);
|
|
@@ -8331,6 +10029,10 @@ function renderRow(terminal, metrics2, wideScaleX, y, lineEl) {
|
|
|
8331
10029
|
if (cachedKey === newKey)
|
|
8332
10030
|
return;
|
|
8333
10031
|
rowCache.set(lineEl, newKey);
|
|
10032
|
+
if (isTransparentBlankRow(segments)) {
|
|
10033
|
+
lineEl.replaceChildren();
|
|
10034
|
+
return;
|
|
10035
|
+
}
|
|
8334
10036
|
const fragment = document.createDocumentFragment();
|
|
8335
10037
|
for (const seg of segments) {
|
|
8336
10038
|
const span = document.createElement("span");
|
|
@@ -8353,6 +10055,7 @@ function createDomRenderer(terminal, container) {
|
|
|
8353
10055
|
container.style.whiteSpace = "pre";
|
|
8354
10056
|
container.style.display = "inline-block";
|
|
8355
10057
|
container.style.overflow = "hidden";
|
|
10058
|
+
container.style.position = "relative";
|
|
8356
10059
|
container.style.userSelect = "text";
|
|
8357
10060
|
container.style.outline = "none";
|
|
8358
10061
|
container.style.contain = "layout style";
|
|
@@ -8360,21 +10063,105 @@ function createDomRenderer(terminal, container) {
|
|
|
8360
10063
|
installAnsiPaletteCssVars(container);
|
|
8361
10064
|
let metrics2 = measureCell(container);
|
|
8362
10065
|
let wideScaleX = 1;
|
|
8363
|
-
|
|
10066
|
+
const planeLayers = /* @__PURE__ */ new Map();
|
|
8364
10067
|
let raf = 0;
|
|
8365
|
-
const pending = /* @__PURE__ */ new
|
|
10068
|
+
const pending = /* @__PURE__ */ new Map();
|
|
8366
10069
|
let disposed = false;
|
|
10070
|
+
function applyPlaneOffset(plane, offsetPx) {
|
|
10071
|
+
const layer = planeLayers.get(plane);
|
|
10072
|
+
if (!layer)
|
|
10073
|
+
return;
|
|
10074
|
+
const next = Number.isFinite(offsetPx) ? offsetPx : 0;
|
|
10075
|
+
if (layer.offsetPx === next)
|
|
10076
|
+
return;
|
|
10077
|
+
layer.offsetPx = next;
|
|
10078
|
+
layer.contentEl.style.transform = next ? `translateY(${next}px)` : "translateY(0px)";
|
|
10079
|
+
}
|
|
10080
|
+
function applyPlaneViewport(plane, viewport) {
|
|
10081
|
+
const layer = planeLayers.get(plane);
|
|
10082
|
+
if (!layer)
|
|
10083
|
+
return;
|
|
10084
|
+
const totalHeight = terminal.size().rows * metrics2.cellHeight;
|
|
10085
|
+
if (!viewport) {
|
|
10086
|
+
layer.viewportTopPx = 0;
|
|
10087
|
+
layer.viewportHeightPx = null;
|
|
10088
|
+
layer.el.style.clipPath = "none";
|
|
10089
|
+
return;
|
|
10090
|
+
}
|
|
10091
|
+
const topPx = Math.max(
|
|
10092
|
+
0,
|
|
10093
|
+
Math.min(totalHeight, Math.floor(viewport.topPx))
|
|
10094
|
+
);
|
|
10095
|
+
const heightPx = Math.max(
|
|
10096
|
+
0,
|
|
10097
|
+
Math.min(totalHeight - topPx, Math.floor(viewport.heightPx))
|
|
10098
|
+
);
|
|
10099
|
+
layer.viewportTopPx = topPx;
|
|
10100
|
+
layer.viewportHeightPx = heightPx;
|
|
10101
|
+
if (topPx === 0 && heightPx >= totalHeight) {
|
|
10102
|
+
layer.el.style.clipPath = "none";
|
|
10103
|
+
return;
|
|
10104
|
+
}
|
|
10105
|
+
const bottomPx = Math.max(0, totalHeight - topPx - heightPx);
|
|
10106
|
+
layer.el.style.clipPath = `inset(${topPx}px 0px ${bottomPx}px 0px)`;
|
|
10107
|
+
}
|
|
8367
10108
|
function rebuildLines() {
|
|
8368
10109
|
const { rows, cols } = terminal.size();
|
|
8369
10110
|
container.style.width = `${cols * metrics2.cellWidth}px`;
|
|
8370
10111
|
container.style.height = `${rows * metrics2.cellHeight}px`;
|
|
8371
10112
|
const fragment = document.createDocumentFragment();
|
|
8372
|
-
|
|
8373
|
-
const
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
10113
|
+
for (let i = 0; i < TERMINAL_RENDER_PLANES.length; i++) {
|
|
10114
|
+
const plane = TERMINAL_RENDER_PLANES[i];
|
|
10115
|
+
const planeTerminal = getPlaneTerminal(terminal, plane);
|
|
10116
|
+
let layer = planeLayers.get(plane);
|
|
10117
|
+
if (!layer) {
|
|
10118
|
+
const el = document.createElement("div");
|
|
10119
|
+
const contentEl = document.createElement("div");
|
|
10120
|
+
el.dataset.vtPlane = plane;
|
|
10121
|
+
el.style.pointerEvents = "none";
|
|
10122
|
+
contentEl.style.position = "absolute";
|
|
10123
|
+
contentEl.style.left = "0";
|
|
10124
|
+
contentEl.style.top = "0";
|
|
10125
|
+
layer = {
|
|
10126
|
+
el,
|
|
10127
|
+
contentEl,
|
|
10128
|
+
lines: [],
|
|
10129
|
+
offsetPx: 0,
|
|
10130
|
+
terminal: planeTerminal,
|
|
10131
|
+
viewportTopPx: 0,
|
|
10132
|
+
viewportHeightPx: null
|
|
10133
|
+
};
|
|
10134
|
+
planeLayers.set(plane, layer);
|
|
10135
|
+
}
|
|
10136
|
+
layer.terminal = planeTerminal;
|
|
10137
|
+
layer.el.style.position = "absolute";
|
|
10138
|
+
layer.el.style.left = "0";
|
|
10139
|
+
layer.el.style.top = "0";
|
|
10140
|
+
layer.el.style.width = `${cols * metrics2.cellWidth}px`;
|
|
10141
|
+
layer.el.style.height = `${rows * metrics2.cellHeight}px`;
|
|
10142
|
+
layer.el.style.overflow = "hidden";
|
|
10143
|
+
layer.el.style.zIndex = String(i);
|
|
10144
|
+
layer.contentEl.style.width = `${cols * metrics2.cellWidth}px`;
|
|
10145
|
+
layer.contentEl.style.height = `${rows * metrics2.cellHeight}px`;
|
|
10146
|
+
applyPlaneOffset(plane, layer.offsetPx);
|
|
10147
|
+
applyPlaneViewport(
|
|
10148
|
+
plane,
|
|
10149
|
+
layer.viewportHeightPx == null ? null : {
|
|
10150
|
+
topPx: layer.viewportTopPx,
|
|
10151
|
+
heightPx: layer.viewportHeightPx
|
|
10152
|
+
}
|
|
10153
|
+
);
|
|
10154
|
+
const lineFragment = document.createDocumentFragment();
|
|
10155
|
+
layer.lines = Array.from({ length: rows }, () => {
|
|
10156
|
+
const line = document.createElement("div");
|
|
10157
|
+
line.style.cssText = `height:${metrics2.cellHeight}px;width:${cols * metrics2.cellWidth}px;overflow:hidden;contain:layout style`;
|
|
10158
|
+
lineFragment.appendChild(line);
|
|
10159
|
+
return line;
|
|
10160
|
+
});
|
|
10161
|
+
layer.contentEl.replaceChildren(lineFragment);
|
|
10162
|
+
layer.el.replaceChildren(layer.contentEl);
|
|
10163
|
+
fragment.appendChild(layer.el);
|
|
10164
|
+
}
|
|
8378
10165
|
container.replaceChildren(fragment);
|
|
8379
10166
|
}
|
|
8380
10167
|
function refresh() {
|
|
@@ -8383,28 +10170,54 @@ function createDomRenderer(terminal, container) {
|
|
|
8383
10170
|
wideScaleX = wideW > 0 ? Math.max(1, Math.min(2, metrics2.cellWidth * 2 / wideW)) : 1;
|
|
8384
10171
|
rebuildLines();
|
|
8385
10172
|
const size = terminal.size();
|
|
8386
|
-
for (
|
|
8387
|
-
|
|
10173
|
+
for (const plane of TERMINAL_RENDER_PLANES) {
|
|
10174
|
+
const layer = planeLayers.get(plane);
|
|
10175
|
+
if (!layer)
|
|
10176
|
+
continue;
|
|
10177
|
+
for (let y = 0; y < size.rows; y++)
|
|
10178
|
+
renderRow(layer.terminal, metrics2, wideScaleX, y, layer.lines[y]);
|
|
10179
|
+
}
|
|
8388
10180
|
}
|
|
8389
10181
|
function flushPending() {
|
|
8390
10182
|
raf = 0;
|
|
8391
10183
|
if (disposed)
|
|
8392
10184
|
return;
|
|
8393
|
-
for (const
|
|
8394
|
-
const
|
|
8395
|
-
|
|
8396
|
-
|
|
10185
|
+
for (const plane of TERMINAL_RENDER_PLANES) {
|
|
10186
|
+
const layer = planeLayers.get(plane);
|
|
10187
|
+
const rows = pending.get(plane);
|
|
10188
|
+
if (!layer || !(rows == null ? void 0 : rows.size))
|
|
10189
|
+
continue;
|
|
10190
|
+
for (const y of rows) {
|
|
10191
|
+
const line = layer.lines[y];
|
|
10192
|
+
if (line)
|
|
10193
|
+
renderRow(layer.terminal, metrics2, wideScaleX, y, line);
|
|
10194
|
+
}
|
|
10195
|
+
rows.clear();
|
|
8397
10196
|
}
|
|
8398
|
-
pending.clear();
|
|
8399
10197
|
}
|
|
8400
|
-
const offCommit = terminal.on("commit", ({ dirtyRows }) => {
|
|
10198
|
+
const offCommit = terminal.on("commit", ({ dirtyRows, planes }) => {
|
|
10199
|
+
const activePlanes = (planes == null ? void 0 : planes.length) ? planes : TERMINAL_RENDER_PLANES;
|
|
8401
10200
|
if (dirtyRows === null) {
|
|
8402
10201
|
const size = terminal.size();
|
|
8403
|
-
for (
|
|
8404
|
-
pending.
|
|
10202
|
+
for (const plane of activePlanes) {
|
|
10203
|
+
let rows = pending.get(plane);
|
|
10204
|
+
if (!rows) {
|
|
10205
|
+
rows = /* @__PURE__ */ new Set();
|
|
10206
|
+
pending.set(plane, rows);
|
|
10207
|
+
}
|
|
10208
|
+
for (let y = 0; y < size.rows; y++)
|
|
10209
|
+
rows.add(y);
|
|
10210
|
+
}
|
|
8405
10211
|
} else {
|
|
8406
|
-
for (const
|
|
8407
|
-
pending.
|
|
10212
|
+
for (const plane of activePlanes) {
|
|
10213
|
+
let rows = pending.get(plane);
|
|
10214
|
+
if (!rows) {
|
|
10215
|
+
rows = /* @__PURE__ */ new Set();
|
|
10216
|
+
pending.set(plane, rows);
|
|
10217
|
+
}
|
|
10218
|
+
for (const y of dirtyRows)
|
|
10219
|
+
rows.add(y);
|
|
10220
|
+
}
|
|
8408
10221
|
}
|
|
8409
10222
|
if (!raf) {
|
|
8410
10223
|
raf = -1;
|
|
@@ -8433,7 +10246,14 @@ function createDomRenderer(terminal, container) {
|
|
|
8433
10246
|
if (raf > 0)
|
|
8434
10247
|
cancelAnimationFrame(raf);
|
|
8435
10248
|
pending.clear();
|
|
10249
|
+
planeLayers.clear();
|
|
8436
10250
|
container.replaceChildren();
|
|
10251
|
+
},
|
|
10252
|
+
setPlaneOffset(plane, offsetPx) {
|
|
10253
|
+
applyPlaneOffset(plane, offsetPx);
|
|
10254
|
+
},
|
|
10255
|
+
setPlaneViewport(plane, viewport) {
|
|
10256
|
+
applyPlaneViewport(plane, viewport);
|
|
8437
10257
|
}
|
|
8438
10258
|
};
|
|
8439
10259
|
}
|
|
@@ -8602,23 +10422,39 @@ function useTerminal() {
|
|
|
8602
10422
|
|
|
8603
10423
|
// src/vue/composables/use-render-node.ts
|
|
8604
10424
|
var pendingInvalidateByScheduler = /* @__PURE__ */ new WeakMap();
|
|
8605
|
-
function
|
|
10425
|
+
function mergePriority(prev, next) {
|
|
10426
|
+
if (prev === "high" || next === "high")
|
|
10427
|
+
return "high";
|
|
10428
|
+
if (prev === "normal" || next === "normal")
|
|
10429
|
+
return "normal";
|
|
10430
|
+
return "low";
|
|
10431
|
+
}
|
|
10432
|
+
function requestBatchedInvalidate(scheduler, plane, priority) {
|
|
8606
10433
|
let state = pendingInvalidateByScheduler.get(scheduler);
|
|
8607
10434
|
if (!state) {
|
|
8608
|
-
state = { queued: false, plane: null };
|
|
10435
|
+
state = { queued: false, plane: null, priority: "low" };
|
|
8609
10436
|
pendingInvalidateByScheduler.set(scheduler, state);
|
|
8610
10437
|
}
|
|
8611
10438
|
if (state.queued) {
|
|
8612
10439
|
state.plane = state.plane == null || state.plane === plane ? plane : null;
|
|
10440
|
+
state.priority = mergePriority(state.priority, priority);
|
|
8613
10441
|
return;
|
|
8614
10442
|
}
|
|
8615
10443
|
state.plane = plane;
|
|
10444
|
+
state.priority = priority;
|
|
8616
10445
|
state.queued = true;
|
|
8617
10446
|
queueMicrotask(() => {
|
|
8618
10447
|
state.queued = false;
|
|
8619
10448
|
const queuedPlane = state.plane;
|
|
10449
|
+
const queuedPriority = state.priority;
|
|
8620
10450
|
state.plane = null;
|
|
8621
|
-
|
|
10451
|
+
state.priority = "low";
|
|
10452
|
+
scheduler.invalidate(
|
|
10453
|
+
queuedPlane || queuedPriority !== "normal" ? {
|
|
10454
|
+
plane: queuedPlane ?? void 0,
|
|
10455
|
+
priority: queuedPriority
|
|
10456
|
+
} : void 0
|
|
10457
|
+
);
|
|
8622
10458
|
});
|
|
8623
10459
|
}
|
|
8624
10460
|
function useRenderNode(getOptions) {
|
|
@@ -8626,11 +10462,13 @@ function useRenderNode(getOptions) {
|
|
|
8626
10462
|
const parentStack = useRenderStack();
|
|
8627
10463
|
const plane = (0, import_vue7.inject)(RenderPlaneContextKey, (0, import_vue7.ref)("default"));
|
|
8628
10464
|
const id = (0, import_vue7.ref)(null);
|
|
10465
|
+
const lastPlane = (0, import_vue7.ref)(plane.value);
|
|
8629
10466
|
const options = (0, import_vue7.computed)(() => getOptions());
|
|
8630
10467
|
const stop = (0, import_vue7.watchEffect)(() => {
|
|
8631
10468
|
const opt = options.value;
|
|
8632
10469
|
void opt.deps;
|
|
8633
10470
|
const stack = opt.stack ?? parentStack.value;
|
|
10471
|
+
lastPlane.value = plane.value;
|
|
8634
10472
|
if (!stack)
|
|
8635
10473
|
return;
|
|
8636
10474
|
if (!id.value) {
|
|
@@ -8642,23 +10480,24 @@ function useRenderNode(getOptions) {
|
|
|
8642
10480
|
paint: opt.paint
|
|
8643
10481
|
});
|
|
8644
10482
|
id.value = node.id;
|
|
8645
|
-
requestBatchedInvalidate(scheduler, plane.value);
|
|
10483
|
+
requestBatchedInvalidate(scheduler, plane.value, opt.priority ?? "normal");
|
|
8646
10484
|
return;
|
|
8647
10485
|
}
|
|
8648
10486
|
render.update(id.value, {
|
|
8649
10487
|
stack,
|
|
8650
10488
|
zIndex: opt.zIndex ?? 0,
|
|
8651
10489
|
rect: opt.rect ?? null,
|
|
10490
|
+
dirtyRowsHint: opt.dirtyRowsHint,
|
|
8652
10491
|
plane: plane.value,
|
|
8653
10492
|
paint: opt.paint
|
|
8654
10493
|
});
|
|
8655
|
-
requestBatchedInvalidate(scheduler, plane.value);
|
|
10494
|
+
requestBatchedInvalidate(scheduler, plane.value, opt.priority ?? "normal");
|
|
8656
10495
|
});
|
|
8657
10496
|
(0, import_vue7.onBeforeUnmount)(() => {
|
|
8658
10497
|
stop();
|
|
8659
10498
|
if (id.value) {
|
|
8660
10499
|
render.unregister(id.value);
|
|
8661
|
-
requestBatchedInvalidate(scheduler,
|
|
10500
|
+
requestBatchedInvalidate(scheduler, lastPlane.value, "normal");
|
|
8662
10501
|
}
|
|
8663
10502
|
});
|
|
8664
10503
|
return { id };
|
|
@@ -9902,6 +11741,7 @@ function mentionIndexAt2(value, mentionToken, index) {
|
|
|
9902
11741
|
return countMentionTokens2(value, mentionToken, index);
|
|
9903
11742
|
}
|
|
9904
11743
|
function createPromptMentionPlugin(options = {}) {
|
|
11744
|
+
const latency = getCliLatencyProfiler();
|
|
9905
11745
|
return {
|
|
9906
11746
|
name: "promptMention",
|
|
9907
11747
|
install: (ctx) => {
|
|
@@ -9910,6 +11750,8 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
9910
11750
|
ctx.render.rootStack,
|
|
9911
11751
|
1e4
|
|
9912
11752
|
);
|
|
11753
|
+
let lastTopClampedRect = null;
|
|
11754
|
+
let lastPromptRect = null;
|
|
9913
11755
|
const derivedStyleCache = /* @__PURE__ */ new WeakMap();
|
|
9914
11756
|
const reactiveProps = (0, import_vue10.reactive)({
|
|
9915
11757
|
promptSuggestions: getProps().promptSuggestions,
|
|
@@ -9957,6 +11799,25 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
9957
11799
|
multilineToken: "\uFFFC",
|
|
9958
11800
|
mentionToken: ctx.mentionToken
|
|
9959
11801
|
});
|
|
11802
|
+
(0, import_vue10.watch)(
|
|
11803
|
+
() => {
|
|
11804
|
+
if (!ctx.visible.value || !promptMention.promptVisible.value)
|
|
11805
|
+
return null;
|
|
11806
|
+
const rect = promptMention.promptRect.value;
|
|
11807
|
+
return [
|
|
11808
|
+
Math.floor(rect.x),
|
|
11809
|
+
Math.floor(rect.y),
|
|
11810
|
+
Math.floor(rect.w),
|
|
11811
|
+
Math.floor(rect.h)
|
|
11812
|
+
].join(":");
|
|
11813
|
+
},
|
|
11814
|
+
(nextRectKey, prevRectKey) => {
|
|
11815
|
+
if (!prevRectKey || nextRectKey === prevRectKey)
|
|
11816
|
+
return;
|
|
11817
|
+
ctx.render.invalidatePlane("default");
|
|
11818
|
+
ctx.scheduler.invalidate({ priority: "high" });
|
|
11819
|
+
}
|
|
11820
|
+
);
|
|
9960
11821
|
ctx.registerChipStyleProvider({
|
|
9961
11822
|
getStyle: (baseStyle, chip) => {
|
|
9962
11823
|
if (chip.kind !== "mention")
|
|
@@ -10043,6 +11904,12 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10043
11904
|
query: ctx0.query
|
|
10044
11905
|
});
|
|
10045
11906
|
if (handled !== false) {
|
|
11907
|
+
const value = ctx.getValue();
|
|
11908
|
+
const before2 = value.slice(0, ctx0.tokenStart);
|
|
11909
|
+
const after2 = value.slice(ctx0.tokenEnd);
|
|
11910
|
+
const nextValue2 = `${before2}${after2}`;
|
|
11911
|
+
ctx.pushUndoSnapshot(nextValue2);
|
|
11912
|
+
ctx.applyEdit(nextValue2, ctx0.tokenStart);
|
|
10046
11913
|
promptMention.promptSuppressedKey.value = ctx0.key;
|
|
10047
11914
|
ctx.scheduler.invalidate();
|
|
10048
11915
|
return;
|
|
@@ -10086,8 +11953,17 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10086
11953
|
var _a2, _b2, _c, _d;
|
|
10087
11954
|
if (!promptMention.promptVisible.value)
|
|
10088
11955
|
return false;
|
|
11956
|
+
const markPromptOperation = (suffix) => {
|
|
11957
|
+
const ctx0 = promptMention.activeContext.value;
|
|
11958
|
+
const mentionTrigger = getProps().mentionTrigger || "@";
|
|
11959
|
+
const skillTrigger = getProps().skillTrigger || "";
|
|
11960
|
+
const tokenText = String((ctx0 == null ? void 0 : ctx0.tokenText) ?? "");
|
|
11961
|
+
const scope = tokenText.startsWith(mentionTrigger) ? "prompt.mention" : skillTrigger && tokenText.startsWith(skillTrigger) ? "prompt.skill" : "prompt.command";
|
|
11962
|
+
latency == null ? void 0 : latency.markOperation(`${scope}.${suffix}`);
|
|
11963
|
+
};
|
|
10089
11964
|
const len = promptMention.promptMatches.value.length;
|
|
10090
11965
|
if (e.key === "ArrowDown") {
|
|
11966
|
+
markPromptOperation("navigate.next");
|
|
10091
11967
|
e.preventDefault();
|
|
10092
11968
|
if (len <= 0) {
|
|
10093
11969
|
promptMention.promptActive.value = 0;
|
|
@@ -10104,6 +11980,7 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10104
11980
|
return true;
|
|
10105
11981
|
}
|
|
10106
11982
|
if (e.key === "ArrowUp") {
|
|
11983
|
+
markPromptOperation("navigate.prev");
|
|
10107
11984
|
e.preventDefault();
|
|
10108
11985
|
if (len <= 0) {
|
|
10109
11986
|
promptMention.promptActive.value = 0;
|
|
@@ -10139,11 +12016,13 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10139
12016
|
const candidate = String(((_c = match == null ? void 0 : match.item) == null ? void 0 : _c.value) ?? "");
|
|
10140
12017
|
if (!typed || !candidate.startsWith(typed))
|
|
10141
12018
|
return false;
|
|
12019
|
+
markPromptOperation("accept");
|
|
10142
12020
|
e.preventDefault();
|
|
10143
12021
|
acceptPrompt(promptMention.promptActive.value);
|
|
10144
12022
|
return true;
|
|
10145
12023
|
}
|
|
10146
12024
|
if (e.key === "Tab" && (isMention || isSkill)) {
|
|
12025
|
+
markPromptOperation("accept");
|
|
10147
12026
|
e.preventDefault();
|
|
10148
12027
|
if (len === 0)
|
|
10149
12028
|
return true;
|
|
@@ -10160,11 +12039,13 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10160
12039
|
}
|
|
10161
12040
|
if (len === 0)
|
|
10162
12041
|
return false;
|
|
12042
|
+
markPromptOperation("accept");
|
|
10163
12043
|
e.preventDefault();
|
|
10164
12044
|
acceptPrompt(promptMention.promptActive.value);
|
|
10165
12045
|
return true;
|
|
10166
12046
|
}
|
|
10167
12047
|
if (e.key === "Escape") {
|
|
12048
|
+
markPromptOperation("dismiss");
|
|
10168
12049
|
e.preventDefault();
|
|
10169
12050
|
promptMention.promptSuppressedKey.value = ((_d = promptMention.activeContext.value) == null ? void 0 : _d.key) ?? null;
|
|
10170
12051
|
ctx.scheduler.invalidate();
|
|
@@ -10176,6 +12057,28 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10176
12057
|
useRenderNode(() => ({
|
|
10177
12058
|
zIndex: getProps().zIndex + 5,
|
|
10178
12059
|
stack: promptOverlayStack,
|
|
12060
|
+
dirtyRowsHint: (() => {
|
|
12061
|
+
const currentRect = ctx.visible.value && promptMention.promptVisible.value ? {
|
|
12062
|
+
y: Math.floor(promptMention.promptRect.value.y),
|
|
12063
|
+
h: Math.max(0, Math.floor(promptMention.promptRect.value.h))
|
|
12064
|
+
} : null;
|
|
12065
|
+
const rects = [lastPromptRect, currentRect].filter(Boolean);
|
|
12066
|
+
if (!rects.length)
|
|
12067
|
+
return void 0;
|
|
12068
|
+
const maxRows = ctx.terminal.size().rows;
|
|
12069
|
+
const start = Math.max(
|
|
12070
|
+
0,
|
|
12071
|
+
Math.min(...rects.map((rect) => rect.y)) - 1
|
|
12072
|
+
);
|
|
12073
|
+
const end = Math.min(
|
|
12074
|
+
maxRows,
|
|
12075
|
+
Math.max(...rects.map((rect) => rect.y + rect.h)) + 1
|
|
12076
|
+
);
|
|
12077
|
+
if (end <= start)
|
|
12078
|
+
return void 0;
|
|
12079
|
+
return Array.from({ length: end - start }, (_, index) => start + index);
|
|
12080
|
+
})(),
|
|
12081
|
+
priority: "high",
|
|
10179
12082
|
rect: ctx.visible.value && promptMention.promptVisible.value ? promptMention.promptRect.value : { x: 0, y: 0, w: 0, h: 0 },
|
|
10180
12083
|
deps: [
|
|
10181
12084
|
ctx.visible.value,
|
|
@@ -10199,6 +12102,10 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10199
12102
|
const r = promptMention.promptRect.value;
|
|
10200
12103
|
if (r.w < 3 || r.h < 3)
|
|
10201
12104
|
return;
|
|
12105
|
+
lastPromptRect = {
|
|
12106
|
+
y: Math.floor(r.y),
|
|
12107
|
+
h: Math.max(0, Math.floor(r.h))
|
|
12108
|
+
};
|
|
10202
12109
|
const base = getProps().style ?? ctx.defaultStyle.value;
|
|
10203
12110
|
const selectedOverride = { bg: "blue" };
|
|
10204
12111
|
const styleKey2 = base && typeof base === "object" ? base : null;
|
|
@@ -10231,6 +12138,18 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10231
12138
|
const contentW = Math.max(0, innerW - sidePad * 2);
|
|
10232
12139
|
const contentX = x0 + 1 + sidePad;
|
|
10233
12140
|
const borderStyle = derived.borderStyle;
|
|
12141
|
+
if (lastTopClampedRect && y0 > 0) {
|
|
12142
|
+
ctx.terminal.write(spaces(lastTopClampedRect.w), {
|
|
12143
|
+
x: lastTopClampedRect.x,
|
|
12144
|
+
y: 0,
|
|
12145
|
+
style: getProps().style ?? ctx.defaultStyle.value
|
|
12146
|
+
});
|
|
12147
|
+
lastTopClampedRect = null;
|
|
12148
|
+
}
|
|
12149
|
+
if (y0 === 0)
|
|
12150
|
+
lastTopClampedRect = { x: x0, w };
|
|
12151
|
+
else
|
|
12152
|
+
lastTopClampedRect = null;
|
|
10234
12153
|
ctx.terminal.write(`\u250C${repeatChar("\u2500", innerW)}\u2510`, {
|
|
10235
12154
|
x: x0,
|
|
10236
12155
|
y: y0,
|
|
@@ -12376,6 +14295,8 @@ var TerminalProvider = (0, import_vue19.defineComponent)({
|
|
|
12376
14295
|
let rafToken = 0;
|
|
12377
14296
|
let pendingInvalidate = false;
|
|
12378
14297
|
let timer = null;
|
|
14298
|
+
let holdNormalInvalidates = false;
|
|
14299
|
+
let holdReleaseToken = 0;
|
|
12379
14300
|
let pendingInvalidateAllPlanes = false;
|
|
12380
14301
|
const pendingInvalidatePlanes = /* @__PURE__ */ new Set();
|
|
12381
14302
|
let imeComposing = false;
|
|
@@ -12406,12 +14327,12 @@ var TerminalProvider = (0, import_vue19.defineComponent)({
|
|
|
12406
14327
|
pendingInvalidatePlanes.clear();
|
|
12407
14328
|
return activePlanes;
|
|
12408
14329
|
}
|
|
12409
|
-
function flush() {
|
|
14330
|
+
function flush(sync = false) {
|
|
12410
14331
|
if (unmounting)
|
|
12411
14332
|
return;
|
|
12412
14333
|
const activePlanes = takeActivePlanes();
|
|
12413
14334
|
render.render({ activePlanes });
|
|
12414
|
-
terminal.commit({ planes: activePlanes });
|
|
14335
|
+
terminal.commit({ planes: activePlanes, sync });
|
|
12415
14336
|
updateImePositionAfterFlush == null ? void 0 : updateImePositionAfterFlush();
|
|
12416
14337
|
}
|
|
12417
14338
|
function clearTimer() {
|
|
@@ -12420,6 +14341,18 @@ var TerminalProvider = (0, import_vue19.defineComponent)({
|
|
|
12420
14341
|
clearTimeout(timer);
|
|
12421
14342
|
timer = null;
|
|
12422
14343
|
}
|
|
14344
|
+
function scheduleNormalInvalidateRelease() {
|
|
14345
|
+
const token = ++holdReleaseToken;
|
|
14346
|
+
void (0, import_vue19.nextTick)(() => {
|
|
14347
|
+
if (token !== holdReleaseToken)
|
|
14348
|
+
return;
|
|
14349
|
+
holdNormalInvalidates = false;
|
|
14350
|
+
if (unmounting || !pendingInvalidate)
|
|
14351
|
+
return;
|
|
14352
|
+
pendingInvalidate = false;
|
|
14353
|
+
invalidate({ priority: "normal" });
|
|
14354
|
+
});
|
|
14355
|
+
}
|
|
12423
14356
|
function flushNow() {
|
|
12424
14357
|
if (unmounting)
|
|
12425
14358
|
return;
|
|
@@ -12431,7 +14364,9 @@ var TerminalProvider = (0, import_vue19.defineComponent)({
|
|
|
12431
14364
|
raf = 0;
|
|
12432
14365
|
}
|
|
12433
14366
|
clearTimer();
|
|
12434
|
-
|
|
14367
|
+
holdNormalInvalidates = true;
|
|
14368
|
+
scheduleNormalInvalidateRelease();
|
|
14369
|
+
flush(true);
|
|
12435
14370
|
}
|
|
12436
14371
|
function invalidate(options) {
|
|
12437
14372
|
if (unmounting)
|
|
@@ -12443,6 +14378,10 @@ var TerminalProvider = (0, import_vue19.defineComponent)({
|
|
|
12443
14378
|
flushNow();
|
|
12444
14379
|
return;
|
|
12445
14380
|
}
|
|
14381
|
+
if (holdNormalInvalidates) {
|
|
14382
|
+
pendingInvalidate = true;
|
|
14383
|
+
return;
|
|
14384
|
+
}
|
|
12446
14385
|
if (priority === "low") {
|
|
12447
14386
|
if (timer || raf)
|
|
12448
14387
|
return;
|
|
@@ -13022,6 +14961,8 @@ var TerminalProvider = (0, import_vue19.defineComponent)({
|
|
|
13022
14961
|
(0, import_vue19.onBeforeUnmount)(() => {
|
|
13023
14962
|
unmounting = true;
|
|
13024
14963
|
offCommit == null ? void 0 : offCommit();
|
|
14964
|
+
clearTimer();
|
|
14965
|
+
holdReleaseToken++;
|
|
13025
14966
|
if (raf > 0)
|
|
13026
14967
|
cancelAnimationFrame(raf);
|
|
13027
14968
|
raf = 0;
|
|
@@ -14024,7 +15965,10 @@ var TInput = (0, import_vue21.defineComponent)({
|
|
|
14024
15965
|
emit("input", nextValue);
|
|
14025
15966
|
if (commit)
|
|
14026
15967
|
emit("change", nextValue);
|
|
14027
|
-
scheduler.
|
|
15968
|
+
scheduler.flushNow();
|
|
15969
|
+
void (0, import_vue21.nextTick)(() => {
|
|
15970
|
+
scheduler.flushNow();
|
|
15971
|
+
});
|
|
14028
15972
|
}
|
|
14029
15973
|
function applyMove(nextCursor, extend) {
|
|
14030
15974
|
const prev = cursor.value;
|
|
@@ -14058,7 +16002,7 @@ var TInput = (0, import_vue21.defineComponent)({
|
|
|
14058
16002
|
}
|
|
14059
16003
|
ensureCursorVisible();
|
|
14060
16004
|
syncImeAnchorNow();
|
|
14061
|
-
scheduler.
|
|
16005
|
+
scheduler.flushNow();
|
|
14062
16006
|
}
|
|
14063
16007
|
(0, import_vue21.watch)(
|
|
14064
16008
|
[() => absRect.value.w, () => absRect.value.h, () => wrapMode.value],
|
|
@@ -14192,7 +16136,11 @@ var TInput = (0, import_vue21.defineComponent)({
|
|
|
14192
16136
|
terminal,
|
|
14193
16137
|
scheduler,
|
|
14194
16138
|
defaultStyle,
|
|
14195
|
-
render
|
|
16139
|
+
render: {
|
|
16140
|
+
rootStack: render.rootStack,
|
|
16141
|
+
createStack: render.createStack,
|
|
16142
|
+
invalidatePlane: render.invalidatePlane
|
|
16143
|
+
},
|
|
14196
16144
|
visible,
|
|
14197
16145
|
rawAbsRect,
|
|
14198
16146
|
eventZ,
|
|
@@ -14306,7 +16254,7 @@ var TInput = (0, import_vue21.defineComponent)({
|
|
|
14306
16254
|
emitMentions(nextMentions);
|
|
14307
16255
|
ensureCursorVisible();
|
|
14308
16256
|
syncImeAnchorNow();
|
|
14309
|
-
scheduler.
|
|
16257
|
+
scheduler.flushNow();
|
|
14310
16258
|
}
|
|
14311
16259
|
function removePendingPasteImage(placeholderPath) {
|
|
14312
16260
|
const current = getCurrentMentions();
|
|
@@ -15124,10 +17072,12 @@ var TInput = (0, import_vue21.defineComponent)({
|
|
|
15124
17072
|
clearAll();
|
|
15125
17073
|
return;
|
|
15126
17074
|
}
|
|
15127
|
-
|
|
15128
|
-
|
|
15129
|
-
|
|
15130
|
-
|
|
17075
|
+
const manager = events.value;
|
|
17076
|
+
if (manager && manager.getFocused()) {
|
|
17077
|
+
manager.focus(null);
|
|
17078
|
+
return;
|
|
17079
|
+
}
|
|
17080
|
+
applyBlur();
|
|
15131
17081
|
return;
|
|
15132
17082
|
}
|
|
15133
17083
|
if (isPrintableKey(e)) {
|
|
@@ -15390,6 +17340,7 @@ var TInput = (0, import_vue21.defineComponent)({
|
|
|
15390
17340
|
var _a2;
|
|
15391
17341
|
return {
|
|
15392
17342
|
zIndex: props.zIndex,
|
|
17343
|
+
priority: pendingValue.value != null ? "high" : "normal",
|
|
15393
17344
|
rect: visible.value ? absRect.value : { x: 0, y: 0, w: 0, h: 0 },
|
|
15394
17345
|
deps: [
|
|
15395
17346
|
visible.value,
|
|
@@ -15417,6 +17368,7 @@ var TInput = (0, import_vue21.defineComponent)({
|
|
|
15417
17368
|
blinkOn.value,
|
|
15418
17369
|
defaultStyle.value,
|
|
15419
17370
|
((_a2 = chipStyleProvider.value) == null ? void 0 : _a2.version.value) ?? 0,
|
|
17371
|
+
pendingValue.value,
|
|
15420
17372
|
props.skillHighlightStyle,
|
|
15421
17373
|
props.skillTrigger
|
|
15422
17374
|
],
|
|
@@ -15986,26 +17938,34 @@ var import_vue24 = require("vue");
|
|
|
15986
17938
|
|
|
15987
17939
|
// src/vue/utils/wheel-scroll.ts
|
|
15988
17940
|
var LINE_UNIT_THRESHOLD = 3;
|
|
15989
|
-
var PIXELS_PER_LINE =
|
|
17941
|
+
var PIXELS_PER_LINE = 0.75;
|
|
15990
17942
|
var ACCEL_WINDOW_MS = 120;
|
|
15991
|
-
var MAX_ACCEL =
|
|
17943
|
+
var MAX_ACCEL = 26;
|
|
15992
17944
|
var EDGE_BOUNCE_MS = 120;
|
|
15993
17945
|
var MIN_TICK_INTERVAL_MS = 6;
|
|
15994
17946
|
function clamp5(n, min, max) {
|
|
15995
17947
|
return Math.max(min, Math.min(max, n));
|
|
15996
17948
|
}
|
|
15997
|
-
function isLineUnitDelta(deltaY) {
|
|
17949
|
+
function isLineUnitDelta(deltaY, mode = "auto") {
|
|
17950
|
+
if (mode === "line")
|
|
17951
|
+
return true;
|
|
17952
|
+
if (mode === "pixel")
|
|
17953
|
+
return false;
|
|
15998
17954
|
const abs = Math.abs(deltaY);
|
|
15999
17955
|
return abs > 0 && abs <= LINE_UNIT_THRESHOLD && Number.isInteger(deltaY);
|
|
16000
17956
|
}
|
|
16001
|
-
function normalizeDelta(deltaY) {
|
|
17957
|
+
function normalizeDelta(deltaY, mode = "auto") {
|
|
17958
|
+
if (mode === "line")
|
|
17959
|
+
return deltaY;
|
|
17960
|
+
if (mode === "pixel")
|
|
17961
|
+
return deltaY / PIXELS_PER_LINE;
|
|
16002
17962
|
const abs = Math.abs(deltaY);
|
|
16003
17963
|
if (abs <= LINE_UNIT_THRESHOLD && Number.isInteger(deltaY))
|
|
16004
17964
|
return deltaY;
|
|
16005
17965
|
return deltaY / PIXELS_PER_LINE;
|
|
16006
17966
|
}
|
|
16007
|
-
function accelFactor(
|
|
16008
|
-
const dt =
|
|
17967
|
+
function accelFactor(now4, lastAt) {
|
|
17968
|
+
const dt = now4 - lastAt;
|
|
16009
17969
|
if (!Number.isFinite(dt) || dt <= 0 || dt > ACCEL_WINDOW_MS)
|
|
16010
17970
|
return 1;
|
|
16011
17971
|
const t = 1 - dt / ACCEL_WINDOW_MS;
|
|
@@ -16016,25 +17976,30 @@ function createWheelScrollState() {
|
|
|
16016
17976
|
accumulator: 0,
|
|
16017
17977
|
lastAt: 0,
|
|
16018
17978
|
lastEdgeDir: 0,
|
|
16019
|
-
lastEdgeAt: 0
|
|
17979
|
+
lastEdgeAt: 0,
|
|
17980
|
+
lastLineUnitDir: 0
|
|
16020
17981
|
};
|
|
16021
17982
|
}
|
|
16022
|
-
function applyWheelScroll(state, deltaY, scrollTop, maxTop,
|
|
17983
|
+
function applyWheelScroll(state, deltaY, scrollTop, maxTop, now4 = Date.now(), deltaMode = "auto", options = {}) {
|
|
16023
17984
|
if (!Number.isFinite(deltaY) || deltaY === 0 || maxTop <= 0) {
|
|
16024
17985
|
if (maxTop <= 0) {
|
|
16025
17986
|
state.accumulator = 0;
|
|
16026
17987
|
state.lastEdgeDir = 0;
|
|
16027
17988
|
state.lastEdgeAt = 0;
|
|
17989
|
+
state.lastLineUnitDir = 0;
|
|
16028
17990
|
}
|
|
16029
17991
|
return { nextTop: scrollTop, dir: 0, lines: 0 };
|
|
16030
17992
|
}
|
|
16031
|
-
const dt = state.lastAt ?
|
|
16032
|
-
const lineUnits = isLineUnitDelta(deltaY);
|
|
16033
|
-
|
|
17993
|
+
const dt = state.lastAt ? now4 - state.lastAt : Infinity;
|
|
17994
|
+
const lineUnits = isLineUnitDelta(deltaY, deltaMode);
|
|
17995
|
+
const inputDir = Math.sign(normalizeDelta(deltaY, deltaMode));
|
|
17996
|
+
if (lineUnits && dt !== Infinity && dt >= 0 && dt < MIN_TICK_INTERVAL_MS && inputDir === state.lastLineUnitDir) {
|
|
16034
17997
|
return { nextTop: scrollTop, dir: 0, lines: 0 };
|
|
16035
|
-
|
|
16036
|
-
state.
|
|
16037
|
-
state.
|
|
17998
|
+
}
|
|
17999
|
+
state.lastLineUnitDir = lineUnits ? inputDir : 0;
|
|
18000
|
+
const accel = lineUnits ? 1 : options.disableAcceleration ? 1 : state.lastAt ? accelFactor(now4, state.lastAt) : 1;
|
|
18001
|
+
state.lastAt = now4;
|
|
18002
|
+
state.accumulator += normalizeDelta(deltaY, deltaMode) * accel;
|
|
16038
18003
|
const lines = Math.trunc(state.accumulator);
|
|
16039
18004
|
if (lines === 0)
|
|
16040
18005
|
return { nextTop: scrollTop, dir: 0, lines: 0 };
|
|
@@ -16044,11 +18009,11 @@ function applyWheelScroll(state, deltaY, scrollTop, maxTop, now3 = Date.now()) {
|
|
|
16044
18009
|
const atBottom = scrollTop >= maxTop;
|
|
16045
18010
|
if (dir < 0 && atTop || dir > 0 && atBottom) {
|
|
16046
18011
|
state.lastEdgeDir = dir;
|
|
16047
|
-
state.lastEdgeAt =
|
|
18012
|
+
state.lastEdgeAt = now4;
|
|
16048
18013
|
state.accumulator = 0;
|
|
16049
18014
|
return { nextTop: scrollTop, dir: 0, lines: 0 };
|
|
16050
18015
|
}
|
|
16051
|
-
if (state.lastEdgeDir !== 0 &&
|
|
18016
|
+
if (state.lastEdgeDir !== 0 && now4 - state.lastEdgeAt < EDGE_BOUNCE_MS && dir === -state.lastEdgeDir && (atTop || atBottom)) {
|
|
16052
18017
|
return { nextTop: scrollTop, dir: 0, lines: 0 };
|
|
16053
18018
|
}
|
|
16054
18019
|
const unclamped = scrollTop + lines;
|
|
@@ -16071,6 +18036,18 @@ function applyWheelScroll(state, deltaY, scrollTop, maxTop, now3 = Date.now()) {
|
|
|
16071
18036
|
function clamp6(n, min, max) {
|
|
16072
18037
|
return Math.max(min, Math.min(max, n));
|
|
16073
18038
|
}
|
|
18039
|
+
function getWheelScrollInput(e) {
|
|
18040
|
+
const deltaY = Number(e.deltaY ?? 0);
|
|
18041
|
+
const deltaMode = typeof e.deltaMode === "number" ? e.deltaMode : void 0;
|
|
18042
|
+
if (Number.isInteger(deltaY) && deltaY !== 0 && Math.abs(deltaY) >= 100 && Math.abs(deltaY) % 100 === 0 && (deltaMode == null || deltaMode === 0)) {
|
|
18043
|
+
return { deltaY: deltaY / 100, mode: "line" };
|
|
18044
|
+
}
|
|
18045
|
+
if (deltaMode === 1)
|
|
18046
|
+
return { deltaY, mode: "line" };
|
|
18047
|
+
if (deltaMode === 0)
|
|
18048
|
+
return { deltaY, mode: "pixel" };
|
|
18049
|
+
return { deltaY, mode: "auto" };
|
|
18050
|
+
}
|
|
16074
18051
|
var TList = (0, import_vue24.defineComponent)({
|
|
16075
18052
|
name: "TList",
|
|
16076
18053
|
props: {
|
|
@@ -16249,7 +18226,8 @@ var TList = (0, import_vue24.defineComponent)({
|
|
|
16249
18226
|
commit(idx);
|
|
16250
18227
|
},
|
|
16251
18228
|
wheel: (e) => {
|
|
16252
|
-
const
|
|
18229
|
+
const { deltaY, mode } = getWheelScrollInput(e);
|
|
18230
|
+
const delta = deltaY;
|
|
16253
18231
|
if (!delta)
|
|
16254
18232
|
return;
|
|
16255
18233
|
const h18 = Math.max(0, props.h);
|
|
@@ -16258,7 +18236,9 @@ var TList = (0, import_vue24.defineComponent)({
|
|
|
16258
18236
|
wheelState,
|
|
16259
18237
|
delta,
|
|
16260
18238
|
scrollTop.value,
|
|
16261
|
-
maxTop
|
|
18239
|
+
maxTop,
|
|
18240
|
+
Date.now(),
|
|
18241
|
+
mode
|
|
16262
18242
|
);
|
|
16263
18243
|
if (!dir || nextTop === scrollTop.value)
|
|
16264
18244
|
return;
|
|
@@ -16552,6 +18532,18 @@ init_path();
|
|
|
16552
18532
|
function clamp7(n, min, max) {
|
|
16553
18533
|
return Math.max(min, Math.min(max, n));
|
|
16554
18534
|
}
|
|
18535
|
+
function getWheelScrollInput2(e) {
|
|
18536
|
+
const deltaY = Number(e.deltaY ?? 0);
|
|
18537
|
+
const deltaMode = typeof e.deltaMode === "number" ? e.deltaMode : void 0;
|
|
18538
|
+
if (Number.isInteger(deltaY) && deltaY !== 0 && Math.abs(deltaY) >= 100 && Math.abs(deltaY) % 100 === 0 && (deltaMode == null || deltaMode === 0)) {
|
|
18539
|
+
return { deltaY: deltaY / 100, mode: "line" };
|
|
18540
|
+
}
|
|
18541
|
+
if (deltaMode === 1)
|
|
18542
|
+
return { deltaY, mode: "line" };
|
|
18543
|
+
if (deltaMode === 0)
|
|
18544
|
+
return { deltaY, mode: "pixel" };
|
|
18545
|
+
return { deltaY, mode: "auto" };
|
|
18546
|
+
}
|
|
16555
18547
|
function isCtrlLike(e) {
|
|
16556
18548
|
return Boolean(e.ctrlKey || e.metaKey);
|
|
16557
18549
|
}
|
|
@@ -16917,7 +18909,8 @@ var TPathPicker = (0, import_vue26.defineComponent)({
|
|
|
16917
18909
|
await trySelect(s.absPath);
|
|
16918
18910
|
},
|
|
16919
18911
|
wheel: (e) => {
|
|
16920
|
-
const
|
|
18912
|
+
const { deltaY, mode } = getWheelScrollInput2(e);
|
|
18913
|
+
const delta = deltaY;
|
|
16921
18914
|
if (!delta)
|
|
16922
18915
|
return;
|
|
16923
18916
|
const h18 = Math.max(0, listH.value);
|
|
@@ -16926,7 +18919,9 @@ var TPathPicker = (0, import_vue26.defineComponent)({
|
|
|
16926
18919
|
wheelState,
|
|
16927
18920
|
delta,
|
|
16928
18921
|
scrollTop.value,
|
|
16929
|
-
maxTop
|
|
18922
|
+
maxTop,
|
|
18923
|
+
Date.now(),
|
|
18924
|
+
mode
|
|
16930
18925
|
);
|
|
16931
18926
|
if (!dir || nextTop === scrollTop.value)
|
|
16932
18927
|
return;
|
|
@@ -18073,6 +20068,7 @@ var TRouterView = (0, import_vue32.defineComponent)({
|
|
|
18073
20068
|
defaultTInputHostPlugin,
|
|
18074
20069
|
detectTerminalColorCapability,
|
|
18075
20070
|
formatInlineCellLine,
|
|
20071
|
+
getCliLatencyProfiler,
|
|
18076
20072
|
getStdoutRendererMetrics,
|
|
18077
20073
|
lintJsonText,
|
|
18078
20074
|
normalizeNewlines,
|