@simon_he/vue-tui 0.0.6 → 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 +825 -182
- package/dist/index.d.ts +63 -6
- package/dist/index.js +687 -121
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -380,6 +380,308 @@ function ansiColors(level) {
|
|
|
380
380
|
return ANSI256_COLORS;
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
+
//#endregion
|
|
384
|
+
//#region src/observability/cli-latency.ts
|
|
385
|
+
const EVENT_OP_ID = Symbol("dimcode.cliLatencyOpId");
|
|
386
|
+
const DEFAULT_LOG_PATH = "/tmp/dimcode-cli-latency.jsonl";
|
|
387
|
+
const INVALIDATE_ASSOCIATION_WINDOW_MS = 32;
|
|
388
|
+
const MAX_OP_AGE_MS = 5e3;
|
|
389
|
+
let nextOpId = 1;
|
|
390
|
+
let singleton;
|
|
391
|
+
function now$2() {
|
|
392
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
393
|
+
}
|
|
394
|
+
function diffMs(end, start) {
|
|
395
|
+
if (end == null || start == null) return null;
|
|
396
|
+
return Math.max(0, end - start);
|
|
397
|
+
}
|
|
398
|
+
function parseEnabled$1(value) {
|
|
399
|
+
const raw = String(value ?? "").trim().toLowerCase();
|
|
400
|
+
return raw === "1" || raw === "true" || raw === "yes";
|
|
401
|
+
}
|
|
402
|
+
function isTrackedEventType(type) {
|
|
403
|
+
return type === "keydown" || type === "beforeinput" || type === "input" || type === "paste";
|
|
404
|
+
}
|
|
405
|
+
function defineOpId(target, id) {
|
|
406
|
+
try {
|
|
407
|
+
Object.defineProperty(target, EVENT_OP_ID, {
|
|
408
|
+
configurable: true,
|
|
409
|
+
enumerable: false,
|
|
410
|
+
writable: true,
|
|
411
|
+
value: id
|
|
412
|
+
});
|
|
413
|
+
} catch {}
|
|
414
|
+
}
|
|
415
|
+
function readOpId(target) {
|
|
416
|
+
const value = target === null || target === void 0 ? void 0 : target[EVENT_OP_ID];
|
|
417
|
+
return typeof value === "number" ? value : null;
|
|
418
|
+
}
|
|
419
|
+
function createDisabledProfiler() {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
function createProfiler() {
|
|
423
|
+
var _process$once;
|
|
424
|
+
const env = (process$1 === null || process$1 === void 0 ? void 0 : process$1.env) ?? {};
|
|
425
|
+
if (!parseEnabled$1(env.DIMCODE_PROFILE_INPUT_LATENCY)) return createDisabledProfiler();
|
|
426
|
+
const logPath = String(env.DIMCODE_PROFILE_INPUT_LATENCY_LOG_PATH ?? DEFAULT_LOG_PATH).trim() || DEFAULT_LOG_PATH;
|
|
427
|
+
const ops = new Map();
|
|
428
|
+
const pendingCommitIds = new Set();
|
|
429
|
+
const pendingWriteIds = new Set();
|
|
430
|
+
let currentDispatchOpId = null;
|
|
431
|
+
let lastDispatchOpId = null;
|
|
432
|
+
let lastDispatchEndedAt = null;
|
|
433
|
+
let currentFlushIds = [];
|
|
434
|
+
let lastRawInputAt = null;
|
|
435
|
+
const emit = (record) => {
|
|
436
|
+
try {
|
|
437
|
+
appendFileSync(logPath, `${JSON.stringify(record)}\n`);
|
|
438
|
+
} catch {}
|
|
439
|
+
};
|
|
440
|
+
const cleanupOp = (id) => {
|
|
441
|
+
ops.delete(id);
|
|
442
|
+
pendingCommitIds.delete(id);
|
|
443
|
+
pendingWriteIds.delete(id);
|
|
444
|
+
if (currentDispatchOpId === id) currentDispatchOpId = null;
|
|
445
|
+
if (lastDispatchOpId === id) {
|
|
446
|
+
lastDispatchOpId = null;
|
|
447
|
+
lastDispatchEndedAt = null;
|
|
448
|
+
}
|
|
449
|
+
if (currentFlushIds.includes(id)) currentFlushIds = currentFlushIds.filter((value) => value !== id);
|
|
450
|
+
};
|
|
451
|
+
const flushOp = (op, outcome) => {
|
|
452
|
+
const totalStart = op.rawInputAt ?? op.stdinDispatchAt ?? op.dispatchStartAt;
|
|
453
|
+
emit({
|
|
454
|
+
ts: op.createdAtIso,
|
|
455
|
+
id: op.id,
|
|
456
|
+
event: {
|
|
457
|
+
type: op.eventType,
|
|
458
|
+
key: op.key,
|
|
459
|
+
code: op.code,
|
|
460
|
+
defaultPrevented: op.defaultPrevented,
|
|
461
|
+
parser: op.parser
|
|
462
|
+
},
|
|
463
|
+
operation: op.operation,
|
|
464
|
+
stages: {
|
|
465
|
+
rawInputAt: op.rawInputAt,
|
|
466
|
+
stdinDispatchAt: op.stdinDispatchAt,
|
|
467
|
+
dispatchStartAt: op.dispatchStartAt,
|
|
468
|
+
dispatchEndAt: op.dispatchEndAt,
|
|
469
|
+
invalidateAt: op.invalidateAt,
|
|
470
|
+
flushStartAt: op.flushStartAt,
|
|
471
|
+
flushEndAt: op.flushEndAt,
|
|
472
|
+
commitAt: op.commitAt,
|
|
473
|
+
stdoutRenderStartAt: op.stdoutRenderStartAt,
|
|
474
|
+
writeStartAt: op.writeStartAt,
|
|
475
|
+
writeEndAt: op.writeEndAt
|
|
476
|
+
},
|
|
477
|
+
timingsMs: {
|
|
478
|
+
inputParseWait: diffMs(op.stdinDispatchAt, op.rawInputAt),
|
|
479
|
+
eventDispatch: diffMs(op.dispatchEndAt, op.dispatchStartAt),
|
|
480
|
+
dispatchToInvalidate: diffMs(op.invalidateAt, op.dispatchEndAt),
|
|
481
|
+
dispatchToFlush: diffMs(op.flushStartAt, op.dispatchEndAt),
|
|
482
|
+
flushToCommitDone: diffMs(op.flushEndAt, op.flushStartAt),
|
|
483
|
+
commitToRender: diffMs(op.stdoutRenderStartAt, op.commitAt),
|
|
484
|
+
renderToWriteStart: diffMs(op.writeStartAt, op.stdoutRenderStartAt),
|
|
485
|
+
write: op.writeDurationMs,
|
|
486
|
+
totalToWrite: diffMs(op.writeEndAt, totalStart)
|
|
487
|
+
},
|
|
488
|
+
scheduler: {
|
|
489
|
+
invalidatePriority: op.invalidatePriority,
|
|
490
|
+
invalidatePlane: op.invalidatePlane,
|
|
491
|
+
commitSync: op.commitSync,
|
|
492
|
+
commitPlaneCount: op.commitPlaneCount,
|
|
493
|
+
commitDirtyRows: op.commitDirtyRows,
|
|
494
|
+
stdoutQueuedDelayMs: op.stdoutQueuedDelayMs,
|
|
495
|
+
writeMode: op.writeMode,
|
|
496
|
+
writeBytes: op.writeBytes
|
|
497
|
+
},
|
|
498
|
+
outcome
|
|
499
|
+
});
|
|
500
|
+
cleanupOp(op.id);
|
|
501
|
+
};
|
|
502
|
+
const expireOldOps = () => {
|
|
503
|
+
const currentTime = now$2();
|
|
504
|
+
for (const op of ops.values()) {
|
|
505
|
+
if (currentTime - op.createdAt < MAX_OP_AGE_MS) continue;
|
|
506
|
+
flushOp(op, op.writeEndAt != null ? "completed" : "timeout");
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
const flushPendingOps = (outcome) => {
|
|
510
|
+
for (const op of Array.from(ops.values())) flushOp(op, op.writeEndAt != null ? "completed" : outcome);
|
|
511
|
+
};
|
|
512
|
+
const ensureOp = (event) => {
|
|
513
|
+
const type = String((event === null || event === void 0 ? void 0 : event.type) ?? "");
|
|
514
|
+
if (!isTrackedEventType(type)) return null;
|
|
515
|
+
const existingId = readOpId(event);
|
|
516
|
+
if (existingId != null) return ops.get(existingId) ?? null;
|
|
517
|
+
const id = nextOpId++;
|
|
518
|
+
const op = {
|
|
519
|
+
id,
|
|
520
|
+
createdAt: now$2(),
|
|
521
|
+
createdAtIso: new Date().toISOString(),
|
|
522
|
+
eventType: type,
|
|
523
|
+
key: String((event === null || event === void 0 ? void 0 : event.key) ?? ""),
|
|
524
|
+
code: String((event === null || event === void 0 ? void 0 : event.code) ?? ""),
|
|
525
|
+
operation: null,
|
|
526
|
+
rawInputAt: null,
|
|
527
|
+
stdinDispatchAt: null,
|
|
528
|
+
dispatchStartAt: null,
|
|
529
|
+
dispatchEndAt: null,
|
|
530
|
+
invalidateAt: null,
|
|
531
|
+
invalidatePriority: null,
|
|
532
|
+
invalidatePlane: null,
|
|
533
|
+
flushStartAt: null,
|
|
534
|
+
flushEndAt: null,
|
|
535
|
+
commitAt: null,
|
|
536
|
+
commitSync: null,
|
|
537
|
+
commitPlaneCount: null,
|
|
538
|
+
commitDirtyRows: null,
|
|
539
|
+
stdoutQueuedDelayMs: null,
|
|
540
|
+
stdoutRenderStartAt: null,
|
|
541
|
+
writeStartAt: null,
|
|
542
|
+
writeEndAt: null,
|
|
543
|
+
writeDurationMs: null,
|
|
544
|
+
writeMode: null,
|
|
545
|
+
writeBytes: null,
|
|
546
|
+
defaultPrevented: null,
|
|
547
|
+
parser: null
|
|
548
|
+
};
|
|
549
|
+
ops.set(id, op);
|
|
550
|
+
defineOpId(event, id);
|
|
551
|
+
expireOldOps();
|
|
552
|
+
return op;
|
|
553
|
+
};
|
|
554
|
+
const forIds = (ids, fn) => {
|
|
555
|
+
for (const id of ids) {
|
|
556
|
+
const op = ops.get(id);
|
|
557
|
+
if (!op) continue;
|
|
558
|
+
fn(op);
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
const resolveActiveOp = () => {
|
|
562
|
+
if (currentDispatchOpId != null) return ops.get(currentDispatchOpId) ?? null;
|
|
563
|
+
if (lastDispatchOpId != null && lastDispatchEndedAt != null && now$2() - lastDispatchEndedAt <= INVALIDATE_ASSOCIATION_WINDOW_MS) return ops.get(lastDispatchOpId) ?? null;
|
|
564
|
+
return null;
|
|
565
|
+
};
|
|
566
|
+
process$1 === null || process$1 === void 0 || (_process$once = process$1.once) === null || _process$once === void 0 || _process$once.call(process$1, "exit", () => {
|
|
567
|
+
flushPendingOps("process-exit");
|
|
568
|
+
});
|
|
569
|
+
return {
|
|
570
|
+
enabled: true,
|
|
571
|
+
recordRawInput(_info) {
|
|
572
|
+
lastRawInputAt = now$2();
|
|
573
|
+
expireOldOps();
|
|
574
|
+
},
|
|
575
|
+
recordStdinDispatch(event, info) {
|
|
576
|
+
const op = ensureOp(event);
|
|
577
|
+
if (!op) return;
|
|
578
|
+
if (op.rawInputAt == null && lastRawInputAt != null) op.rawInputAt = lastRawInputAt;
|
|
579
|
+
if (op.stdinDispatchAt == null) op.stdinDispatchAt = now$2();
|
|
580
|
+
if (!op.parser && (info === null || info === void 0 ? void 0 : info.parser)) op.parser = String(info.parser);
|
|
581
|
+
},
|
|
582
|
+
recordEventDispatchStart(event) {
|
|
583
|
+
const op = ensureOp(event);
|
|
584
|
+
if (!op) return;
|
|
585
|
+
currentDispatchOpId = op.id;
|
|
586
|
+
if (op.dispatchStartAt == null) op.dispatchStartAt = now$2();
|
|
587
|
+
},
|
|
588
|
+
recordEventDispatchEnd(event, info) {
|
|
589
|
+
const op = ensureOp(event);
|
|
590
|
+
if (!op) return;
|
|
591
|
+
op.defaultPrevented = Boolean(info.defaultPrevented);
|
|
592
|
+
if (op.dispatchEndAt == null) op.dispatchEndAt = now$2();
|
|
593
|
+
currentDispatchOpId = currentDispatchOpId === op.id ? null : currentDispatchOpId;
|
|
594
|
+
lastDispatchOpId = op.id;
|
|
595
|
+
lastDispatchEndedAt = op.dispatchEndAt;
|
|
596
|
+
},
|
|
597
|
+
recordSchedulerInvalidate(info) {
|
|
598
|
+
const op = resolveActiveOp();
|
|
599
|
+
if (!op) return;
|
|
600
|
+
if (op.invalidateAt == null) op.invalidateAt = now$2();
|
|
601
|
+
if (!op.invalidatePriority && (info === null || info === void 0 ? void 0 : info.priority)) op.invalidatePriority = String(info.priority);
|
|
602
|
+
if (!op.invalidatePlane && (info === null || info === void 0 ? void 0 : info.plane)) op.invalidatePlane = String(info.plane);
|
|
603
|
+
pendingCommitIds.add(op.id);
|
|
604
|
+
},
|
|
605
|
+
recordFlushStart(info) {
|
|
606
|
+
currentFlushIds = Array.from(pendingCommitIds);
|
|
607
|
+
if (!currentFlushIds.length) return;
|
|
608
|
+
const flushTime = now$2();
|
|
609
|
+
forIds(currentFlushIds, (op) => {
|
|
610
|
+
if (op.flushStartAt == null) op.flushStartAt = flushTime;
|
|
611
|
+
if (op.commitSync == null && (info === null || info === void 0 ? void 0 : info.sync) != null) op.commitSync = Boolean(info.sync);
|
|
612
|
+
if (op.commitPlaneCount == null && Array.isArray(info === null || info === void 0 ? void 0 : info.activePlanes)) op.commitPlaneCount = info.activePlanes.length;
|
|
613
|
+
});
|
|
614
|
+
},
|
|
615
|
+
recordFlushEnd() {
|
|
616
|
+
if (!currentFlushIds.length) return;
|
|
617
|
+
const flushTime = now$2();
|
|
618
|
+
forIds(currentFlushIds, (op) => {
|
|
619
|
+
if (op.flushEndAt == null) op.flushEndAt = flushTime;
|
|
620
|
+
});
|
|
621
|
+
currentFlushIds = [];
|
|
622
|
+
},
|
|
623
|
+
recordCommit(info) {
|
|
624
|
+
if (!pendingCommitIds.size) return;
|
|
625
|
+
const commitTime = now$2();
|
|
626
|
+
const ids = Array.from(pendingCommitIds);
|
|
627
|
+
pendingCommitIds.clear();
|
|
628
|
+
forIds(ids, (op) => {
|
|
629
|
+
if (op.flushEndAt == null && op.flushStartAt != null) op.flushEndAt = commitTime;
|
|
630
|
+
if (op.commitAt == null) op.commitAt = commitTime;
|
|
631
|
+
op.commitSync = (info === null || info === void 0 ? void 0 : info.sync) == null ? op.commitSync : Boolean(info.sync);
|
|
632
|
+
op.commitPlaneCount = Array.isArray(info === null || info === void 0 ? void 0 : info.planes) ? info.planes.length : op.commitPlaneCount;
|
|
633
|
+
op.commitDirtyRows = Array.isArray(info === null || info === void 0 ? void 0 : info.dirtyRows) ? info.dirtyRows.length : (info === null || info === void 0 ? void 0 : info.dirtyRows) === null ? null : op.commitDirtyRows;
|
|
634
|
+
pendingWriteIds.add(op.id);
|
|
635
|
+
});
|
|
636
|
+
},
|
|
637
|
+
recordStdoutQueued(delayMs) {
|
|
638
|
+
if (!pendingWriteIds.size) return;
|
|
639
|
+
forIds(pendingWriteIds, (op) => {
|
|
640
|
+
if (op.stdoutQueuedDelayMs == null) op.stdoutQueuedDelayMs = Math.max(0, delayMs);
|
|
641
|
+
});
|
|
642
|
+
},
|
|
643
|
+
recordStdoutRenderStart() {
|
|
644
|
+
if (!pendingWriteIds.size) return;
|
|
645
|
+
const renderTime = now$2();
|
|
646
|
+
forIds(pendingWriteIds, (op) => {
|
|
647
|
+
if (op.stdoutRenderStartAt == null) op.stdoutRenderStartAt = renderTime;
|
|
648
|
+
});
|
|
649
|
+
},
|
|
650
|
+
recordStdoutNoOutput() {
|
|
651
|
+
if (!pendingWriteIds.size) return;
|
|
652
|
+
const ids = Array.from(pendingWriteIds);
|
|
653
|
+
pendingWriteIds.clear();
|
|
654
|
+
forIds(ids, (op) => flushOp(op, "no-output"));
|
|
655
|
+
},
|
|
656
|
+
recordStdoutWrite(info) {
|
|
657
|
+
if (!pendingWriteIds.size) return;
|
|
658
|
+
const writeEndTime = now$2();
|
|
659
|
+
const ids = Array.from(pendingWriteIds);
|
|
660
|
+
pendingWriteIds.clear();
|
|
661
|
+
forIds(ids, (op) => {
|
|
662
|
+
op.writeEndAt = writeEndTime;
|
|
663
|
+
op.writeDurationMs = Math.max(0, info.durationMs);
|
|
664
|
+
op.writeStartAt = writeEndTime - op.writeDurationMs;
|
|
665
|
+
op.writeMode = String(info.mode ?? "");
|
|
666
|
+
op.writeBytes = Math.max(0, Math.floor(info.bytes));
|
|
667
|
+
flushOp(op, "completed");
|
|
668
|
+
});
|
|
669
|
+
},
|
|
670
|
+
markOperation(operation) {
|
|
671
|
+
const nextOperation = String(operation ?? "").trim();
|
|
672
|
+
if (!nextOperation) return;
|
|
673
|
+
const op = resolveActiveOp();
|
|
674
|
+
if (!op) return;
|
|
675
|
+
op.operation = nextOperation;
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
function getCliLatencyProfiler() {
|
|
680
|
+
if (singleton !== void 0) return singleton;
|
|
681
|
+
singleton = createProfiler();
|
|
682
|
+
return singleton;
|
|
683
|
+
}
|
|
684
|
+
|
|
383
685
|
//#endregion
|
|
384
686
|
//#region src/utils/newlines.ts
|
|
385
687
|
function normalizeNewlines(text) {
|
|
@@ -1422,6 +1724,7 @@ function parseMouseSequence(sequence) {
|
|
|
1422
1724
|
const ESC$1 = "\x1B";
|
|
1423
1725
|
const BRACKETED_PASTE_START = "\x1B[200~";
|
|
1424
1726
|
const BRACKETED_PASTE_END = "\x1B[201~";
|
|
1727
|
+
const ESC_CONTINUATION_RESCUE_WINDOW_MS = 64;
|
|
1425
1728
|
function looksLikeQuotedPathPaste(value) {
|
|
1426
1729
|
if (!value) return false;
|
|
1427
1730
|
if (value.includes(ESC$1)) return false;
|
|
@@ -1524,6 +1827,11 @@ function extractCompleteSequences(buffer) {
|
|
|
1524
1827
|
remainder: ""
|
|
1525
1828
|
};
|
|
1526
1829
|
}
|
|
1830
|
+
function looksLikeSplitEscapeContinuation(value) {
|
|
1831
|
+
const first = value[0];
|
|
1832
|
+
if (first !== "[" && first !== "]" && first !== "P" && first !== "_" && first !== "O") return false;
|
|
1833
|
+
return isCompleteSequence(`${ESC$1}${value}`) !== "not-escape";
|
|
1834
|
+
}
|
|
1527
1835
|
var StdinBuffer = class extends EventEmitter {
|
|
1528
1836
|
constructor(options = {}) {
|
|
1529
1837
|
super();
|
|
@@ -1531,6 +1839,7 @@ var StdinBuffer = class extends EventEmitter {
|
|
|
1531
1839
|
this.timeout = null;
|
|
1532
1840
|
this.timeoutMs = void 0;
|
|
1533
1841
|
this.escTimeoutMs = void 0;
|
|
1842
|
+
this.pendingEscContinuationAt = null;
|
|
1534
1843
|
this.pasteMode = false;
|
|
1535
1844
|
this.pasteBuffer = "";
|
|
1536
1845
|
this.timeoutMs = options.timeout ?? 10;
|
|
@@ -1547,6 +1856,11 @@ var StdinBuffer = class extends EventEmitter {
|
|
|
1547
1856
|
str = `\x1B${String.fromCharCode(byte)}`;
|
|
1548
1857
|
} else str = data.toString();
|
|
1549
1858
|
else str = data;
|
|
1859
|
+
if (this.pendingEscContinuationAt != null) {
|
|
1860
|
+
const canRescue = Date.now() - this.pendingEscContinuationAt <= ESC_CONTINUATION_RESCUE_WINDOW_MS;
|
|
1861
|
+
this.pendingEscContinuationAt = null;
|
|
1862
|
+
if (canRescue && looksLikeSplitEscapeContinuation(str)) str = `${ESC$1}${str}`;
|
|
1863
|
+
}
|
|
1550
1864
|
if (str.length === 0 && this.buffer.length === 0) {
|
|
1551
1865
|
this.emit("data", "");
|
|
1552
1866
|
return;
|
|
@@ -1600,7 +1914,9 @@ var StdinBuffer = class extends EventEmitter {
|
|
|
1600
1914
|
if (this.buffer.length > 0) {
|
|
1601
1915
|
const timeoutMs = this.buffer === ESC$1 ? this.escTimeoutMs : this.timeoutMs;
|
|
1602
1916
|
this.timeout = setTimeout(() => {
|
|
1917
|
+
const rescuableLoneEsc = this.buffer === ESC$1;
|
|
1603
1918
|
const flushed = this.flush();
|
|
1919
|
+
if (rescuableLoneEsc && flushed.length === 1 && flushed[0] === ESC$1) this.pendingEscContinuationAt = Date.now();
|
|
1604
1920
|
for (const sequence of flushed) this.emit("data", sequence);
|
|
1605
1921
|
}, timeoutMs);
|
|
1606
1922
|
}
|
|
@@ -1621,6 +1937,7 @@ var StdinBuffer = class extends EventEmitter {
|
|
|
1621
1937
|
this.timeout = null;
|
|
1622
1938
|
}
|
|
1623
1939
|
this.buffer = "";
|
|
1940
|
+
this.pendingEscContinuationAt = null;
|
|
1624
1941
|
this.pasteMode = false;
|
|
1625
1942
|
this.pasteBuffer = "";
|
|
1626
1943
|
}
|
|
@@ -1634,6 +1951,10 @@ var StdinBuffer = class extends EventEmitter {
|
|
|
1634
1951
|
|
|
1635
1952
|
//#endregion
|
|
1636
1953
|
//#region src/cli/input.ts
|
|
1954
|
+
const KITTY_KEYBOARD_PROTOCOL_ENABLE = "\x1B[>1u";
|
|
1955
|
+
const KITTY_KEYBOARD_PROTOCOL_DISABLE = "\x1B[<u";
|
|
1956
|
+
const XTERM_MODIFY_OTHER_KEYS_ENABLE = "\x1B[>4;2m";
|
|
1957
|
+
const XTERM_MODIFY_OTHER_KEYS_DISABLE = "\x1B[>4n";
|
|
1637
1958
|
function isPrintable(ch) {
|
|
1638
1959
|
if (ch.length === 0) return false;
|
|
1639
1960
|
if (ch.length === 1) {
|
|
@@ -1653,12 +1974,54 @@ function ctrlKeyFromChar(ch) {
|
|
|
1653
1974
|
if (code >= 1 && code <= 26) return String.fromCharCode(code + 96);
|
|
1654
1975
|
return null;
|
|
1655
1976
|
}
|
|
1977
|
+
function isUnhandledCtrlC(event) {
|
|
1978
|
+
return event.type === "keydown" && (event.key === "c" || event.key === "C") && event.ctrlKey === true && event.metaKey !== true && event.altKey !== true && event.shiftKey !== true;
|
|
1979
|
+
}
|
|
1980
|
+
function parseKeyboardProtocol(value) {
|
|
1981
|
+
const normalized = String(value ?? "").trim().toLowerCase();
|
|
1982
|
+
if (normalized === "auto" || normalized === "kitty" || normalized === "xterm" || normalized === "off") return normalized;
|
|
1983
|
+
return null;
|
|
1984
|
+
}
|
|
1985
|
+
function detectKeyboardProtocol(env) {
|
|
1986
|
+
const termProgram = String(env.TERM_PROGRAM ?? "").trim().toLowerCase();
|
|
1987
|
+
const term = String(env.TERM ?? "").trim().toLowerCase();
|
|
1988
|
+
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");
|
|
1989
|
+
if (hasKittyProtocolTerminal) return "kitty";
|
|
1990
|
+
const isScreenLike = "TMUX" in env || term.includes("screen") || term.includes("tmux");
|
|
1991
|
+
const hasXtermKeyboardTerminal = termProgram.includes("iterm") || termProgram.includes("apple_terminal") || termProgram.includes("vscode") || term.includes("xterm") && !isScreenLike;
|
|
1992
|
+
return hasXtermKeyboardTerminal ? "xterm" : "off";
|
|
1993
|
+
}
|
|
1994
|
+
function resolveKeyboardProtocol(options) {
|
|
1995
|
+
var _options$env;
|
|
1996
|
+
const configured = parseKeyboardProtocol(options.keyboardProtocol) ?? "auto";
|
|
1997
|
+
if (configured !== "auto") return configured;
|
|
1998
|
+
const envOverride = parseKeyboardProtocol((_options$env = options.env) === null || _options$env === void 0 ? void 0 : _options$env.DIMCODE_KEYBOARD_PROTOCOL);
|
|
1999
|
+
if (envOverride && envOverride !== "auto") return envOverride;
|
|
2000
|
+
return detectKeyboardProtocol(options.env ?? {});
|
|
2001
|
+
}
|
|
2002
|
+
function getKeyboardProtocolSequences(protocol) {
|
|
2003
|
+
if (protocol === "kitty") return {
|
|
2004
|
+
enable: KITTY_KEYBOARD_PROTOCOL_ENABLE,
|
|
2005
|
+
disable: KITTY_KEYBOARD_PROTOCOL_DISABLE
|
|
2006
|
+
};
|
|
2007
|
+
if (protocol === "xterm") return {
|
|
2008
|
+
enable: XTERM_MODIFY_OTHER_KEYS_ENABLE,
|
|
2009
|
+
disable: XTERM_MODIFY_OTHER_KEYS_DISABLE
|
|
2010
|
+
};
|
|
2011
|
+
return null;
|
|
2012
|
+
}
|
|
1656
2013
|
function createStdinDriver(options) {
|
|
1657
2014
|
const stdin = options.stdin ?? process$1.stdin;
|
|
1658
2015
|
const stdout = options.stdout ?? process$1.stdout;
|
|
1659
2016
|
if (!stdin || !stdout) throw new Error("createStdinDriver requires Node process.stdin/stdout");
|
|
2017
|
+
const env = options.env ?? process$1.env ?? {};
|
|
1660
2018
|
const enableMouse = options.enableMouse ?? true;
|
|
1661
2019
|
const enableMouseMotion = options.enableMouseMotion ?? false;
|
|
2020
|
+
const keyboardProtocol = resolveKeyboardProtocol({
|
|
2021
|
+
keyboardProtocol: options.keyboardProtocol,
|
|
2022
|
+
env
|
|
2023
|
+
});
|
|
2024
|
+
const keyboardProtocolSequences = getKeyboardProtocolSequences(keyboardProtocol);
|
|
1662
2025
|
let disposed = false;
|
|
1663
2026
|
let swallowNextLF = false;
|
|
1664
2027
|
let lastMouseDown = null;
|
|
@@ -1668,55 +2031,61 @@ function createStdinDriver(options) {
|
|
|
1668
2031
|
});
|
|
1669
2032
|
const stdinBuffer = new StdinBuffer({
|
|
1670
2033
|
timeout: 50,
|
|
1671
|
-
escTimeout: enableMouse ?
|
|
2034
|
+
escTimeout: enableMouse ? 8 : 6
|
|
1672
2035
|
});
|
|
2036
|
+
const latency = getCliLatencyProfiler();
|
|
2037
|
+
const dispatchEvent = (event, parser) => {
|
|
2038
|
+
var _options$onExit;
|
|
2039
|
+
latency === null || latency === void 0 || latency.recordStdinDispatch(event, { parser });
|
|
2040
|
+
const prevented = Boolean(options.dispatch(event));
|
|
2041
|
+
if (isUnhandledCtrlC(event) && !prevented) (_options$onExit = options.onExit) === null || _options$onExit === void 0 || _options$onExit.call(options);
|
|
2042
|
+
return prevented;
|
|
2043
|
+
};
|
|
1673
2044
|
const handlePlainChar = (ch) => {
|
|
1674
2045
|
if (swallowNextLF) {
|
|
1675
2046
|
swallowNextLF = false;
|
|
1676
2047
|
if (ch === "\n") return;
|
|
1677
2048
|
}
|
|
1678
2049
|
if (ch === "") {
|
|
1679
|
-
|
|
1680
|
-
const prevented = Boolean(options.dispatch(keyEvent("c", "", { ctrlKey: true })));
|
|
1681
|
-
if (!prevented) (_options$onExit = options.onExit) === null || _options$onExit === void 0 || _options$onExit.call(options);
|
|
2050
|
+
dispatchEvent(keyEvent("c", "", { ctrlKey: true }), "plain");
|
|
1682
2051
|
return;
|
|
1683
2052
|
}
|
|
1684
2053
|
if (ch === "\r") {
|
|
1685
2054
|
swallowNextLF = true;
|
|
1686
|
-
|
|
2055
|
+
dispatchEvent(keyEvent("Enter", "Enter"), "plain");
|
|
1687
2056
|
return;
|
|
1688
2057
|
}
|
|
1689
2058
|
if (ch === "\n") {
|
|
1690
|
-
|
|
2059
|
+
dispatchEvent({
|
|
1691
2060
|
type: "input",
|
|
1692
2061
|
data: "\n",
|
|
1693
2062
|
inputType: "insertLineBreak",
|
|
1694
2063
|
text: "\n"
|
|
1695
|
-
});
|
|
2064
|
+
}, "plain");
|
|
1696
2065
|
return;
|
|
1697
2066
|
}
|
|
1698
2067
|
const ctrlKey = ctrlKeyFromChar(ch);
|
|
1699
2068
|
if (ctrlKey) {
|
|
1700
2069
|
if (ctrlKey === "i") {
|
|
1701
|
-
|
|
2070
|
+
dispatchEvent(keyEvent("Tab", "Tab"), "plain");
|
|
1702
2071
|
return;
|
|
1703
2072
|
}
|
|
1704
2073
|
if (ctrlKey === "h") {
|
|
1705
|
-
|
|
2074
|
+
dispatchEvent(keyEvent("Backspace", "Backspace"), "plain");
|
|
1706
2075
|
return;
|
|
1707
2076
|
}
|
|
1708
|
-
|
|
2077
|
+
dispatchEvent(keyEvent(ctrlKey, "", { ctrlKey: true }), "plain");
|
|
1709
2078
|
return;
|
|
1710
2079
|
}
|
|
1711
2080
|
if (ch === "") {
|
|
1712
|
-
|
|
2081
|
+
dispatchEvent(keyEvent("Backspace", "Backspace"), "plain");
|
|
1713
2082
|
return;
|
|
1714
2083
|
}
|
|
1715
2084
|
if (ch === " ") {
|
|
1716
|
-
|
|
2085
|
+
dispatchEvent(keyEvent("Tab", "Tab"), "plain");
|
|
1717
2086
|
return;
|
|
1718
2087
|
}
|
|
1719
|
-
if (isPrintable(ch))
|
|
2088
|
+
if (isPrintable(ch)) dispatchEvent(keyEvent(ch), "plain");
|
|
1720
2089
|
};
|
|
1721
2090
|
const handleMouseEvent = (event) => {
|
|
1722
2091
|
const ev = event;
|
|
@@ -1789,21 +2158,21 @@ function createStdinDriver(options) {
|
|
|
1789
2158
|
}
|
|
1790
2159
|
const kitty = parseKittySequence(sequence);
|
|
1791
2160
|
if (kitty.handled) {
|
|
1792
|
-
if (kitty.event)
|
|
2161
|
+
if (kitty.event) dispatchEvent(kitty.event, "kitty");
|
|
1793
2162
|
return;
|
|
1794
2163
|
}
|
|
1795
2164
|
const legacy = parseLegacySequence(sequence);
|
|
1796
2165
|
if (legacy.handled) {
|
|
1797
|
-
if (legacy.event)
|
|
2166
|
+
if (legacy.event) dispatchEvent(legacy.event, "legacy");
|
|
1798
2167
|
return;
|
|
1799
2168
|
}
|
|
1800
2169
|
if (sequence.startsWith("\x1B")) {
|
|
1801
2170
|
if (sequence.length === 2 && isPrintable(sequence[1])) {
|
|
1802
|
-
|
|
2171
|
+
dispatchEvent(keyEvent(sequence[1], "", { altKey: true }), "alt");
|
|
1803
2172
|
return;
|
|
1804
2173
|
}
|
|
1805
2174
|
if (sequence === "\x1B") {
|
|
1806
|
-
|
|
2175
|
+
dispatchEvent(keyEvent("Escape", "Escape"), "escape");
|
|
1807
2176
|
return;
|
|
1808
2177
|
}
|
|
1809
2178
|
return;
|
|
@@ -1813,10 +2182,10 @@ function createStdinDriver(options) {
|
|
|
1813
2182
|
stdinBuffer.on("data", handleSequence);
|
|
1814
2183
|
stdinBuffer.on("paste", (data) => {
|
|
1815
2184
|
const pastedText = normalizeNewlines(data);
|
|
1816
|
-
if (pastedText)
|
|
2185
|
+
if (pastedText) dispatchEvent({
|
|
1817
2186
|
type: "paste",
|
|
1818
2187
|
text: pastedText
|
|
1819
|
-
});
|
|
2188
|
+
}, "paste");
|
|
1820
2189
|
});
|
|
1821
2190
|
const decodeBytes = (bytes) => {
|
|
1822
2191
|
if (bytes.length === 1 && bytes[0] > 127) {
|
|
@@ -1829,6 +2198,7 @@ function createStdinDriver(options) {
|
|
|
1829
2198
|
};
|
|
1830
2199
|
const onData = (chunk) => {
|
|
1831
2200
|
if (disposed) return;
|
|
2201
|
+
latency === null || latency === void 0 || latency.recordRawInput();
|
|
1832
2202
|
if (typeof chunk === "string") {
|
|
1833
2203
|
stdinBuffer.process(chunk);
|
|
1834
2204
|
return;
|
|
@@ -1854,6 +2224,7 @@ function createStdinDriver(options) {
|
|
|
1854
2224
|
if (stdout.isTTY) {
|
|
1855
2225
|
stdout.write("\x1B[?2004h");
|
|
1856
2226
|
stdout.write("\x1B[?1004h");
|
|
2227
|
+
if (keyboardProtocolSequences) stdout.write(keyboardProtocolSequences.enable);
|
|
1857
2228
|
if (enableMouse) {
|
|
1858
2229
|
stdout.write("\x1B[?1007h");
|
|
1859
2230
|
if (enableMouseMotion) stdout.write("\x1B[?1000h\x1B[?1003h\x1B[?1006h");
|
|
@@ -1876,6 +2247,7 @@ function createStdinDriver(options) {
|
|
|
1876
2247
|
if (stdout.isTTY) {
|
|
1877
2248
|
stdout.write("\x1B[?2004l");
|
|
1878
2249
|
stdout.write("\x1B[?1004l");
|
|
2250
|
+
if (keyboardProtocolSequences) stdout.write(keyboardProtocolSequences.disable);
|
|
1879
2251
|
if (enableMouse) {
|
|
1880
2252
|
stdout.write("\x1B[?1007l");
|
|
1881
2253
|
if (enableMouseMotion) stdout.write("\x1B[?1000l\x1B[?1003l\x1B[?1006l");
|
|
@@ -3901,6 +4273,7 @@ function createCliEventManager(options) {
|
|
|
3901
4273
|
let hoverPath = [];
|
|
3902
4274
|
const record = options === null || options === void 0 ? void 0 : options.record;
|
|
3903
4275
|
const onFocusChange = options === null || options === void 0 ? void 0 : options.onFocusChange;
|
|
4276
|
+
const latency = getCliLatencyProfiler();
|
|
3904
4277
|
const MODAL_FOCUS_Z_THRESHOLD = 100;
|
|
3905
4278
|
const MODAL_ROOT_MIN_AREA = 40;
|
|
3906
4279
|
function focusLockTarget() {
|
|
@@ -4280,51 +4653,65 @@ function createCliEventManager(options) {
|
|
|
4280
4653
|
},
|
|
4281
4654
|
dispatch(event) {
|
|
4282
4655
|
record === null || record === void 0 || record(event);
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
capturedId = (target === null || target === void 0 ? void 0 : target.id) ?? null;
|
|
4290
|
-
updateHover(target, event);
|
|
4291
|
-
dispatchPointerEvent("pointerdown", event, target);
|
|
4292
|
-
return false;
|
|
4293
|
-
}
|
|
4294
|
-
if (event.type === "pointermove" && capturedId) {
|
|
4295
|
-
const target = nodes.get(capturedId) ?? null;
|
|
4296
|
-
if (!target) return false;
|
|
4297
|
-
updateHover(target, event);
|
|
4298
|
-
const path = ancestorsForTarget(target);
|
|
4299
|
-
const ev = buildPointerEvent("pointermove", path, event);
|
|
4300
|
-
dispatchWithPhases("pointermove", path, target, ev);
|
|
4301
|
-
return ev.defaultPrevented;
|
|
4302
|
-
}
|
|
4303
|
-
if (event.type === "pointermove") {
|
|
4304
|
-
const list = candidatesAt(event.cellX, event.cellY);
|
|
4305
|
-
const target = pickTarget(list);
|
|
4306
|
-
updateHover(target, event);
|
|
4307
|
-
dispatchPointerEvent("pointermove", event, target);
|
|
4308
|
-
return false;
|
|
4656
|
+
latency === null || latency === void 0 || latency.recordEventDispatchStart(event);
|
|
4657
|
+
let prevented = false;
|
|
4658
|
+
try {
|
|
4659
|
+
if (event.type === "keydown" || event.type === "keyup") {
|
|
4660
|
+
prevented = dispatchToFocused(event.type, event);
|
|
4661
|
+
return prevented;
|
|
4309
4662
|
}
|
|
4310
|
-
if (event.type === "pointerup"
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4663
|
+
if (event.type === "pointerdown" || event.type === "pointermove" || event.type === "pointerup" || event.type === "click" || event.type === "dblclick" || event.type === "contextmenu" || event.type === "wheel") {
|
|
4664
|
+
if (event.type === "pointerdown") {
|
|
4665
|
+
const list = candidatesAt(event.cellX, event.cellY);
|
|
4666
|
+
const target = pickTarget(list);
|
|
4667
|
+
if (target === null || target === void 0 ? void 0 : target.focusable) setFocus(target.id);
|
|
4668
|
+
capturedId = (target === null || target === void 0 ? void 0 : target.id) ?? null;
|
|
4669
|
+
updateHover(target, event);
|
|
4670
|
+
dispatchPointerEvent("pointerdown", event, target);
|
|
4671
|
+
return prevented;
|
|
4672
|
+
}
|
|
4673
|
+
if (event.type === "pointermove" && capturedId) {
|
|
4674
|
+
const target = nodes.get(capturedId) ?? null;
|
|
4675
|
+
if (!target) return prevented;
|
|
4676
|
+
updateHover(target, event);
|
|
4677
|
+
const path = ancestorsForTarget(target);
|
|
4678
|
+
const ev = buildPointerEvent("pointermove", path, event);
|
|
4679
|
+
dispatchWithPhases("pointermove", path, target, ev);
|
|
4680
|
+
prevented = ev.defaultPrevented;
|
|
4681
|
+
return prevented;
|
|
4682
|
+
}
|
|
4683
|
+
if (event.type === "pointermove") {
|
|
4684
|
+
const list = candidatesAt(event.cellX, event.cellY);
|
|
4685
|
+
const target = pickTarget(list);
|
|
4686
|
+
updateHover(target, event);
|
|
4687
|
+
dispatchPointerEvent("pointermove", event, target);
|
|
4688
|
+
return prevented;
|
|
4689
|
+
}
|
|
4690
|
+
if (event.type === "pointerup" && capturedId) {
|
|
4691
|
+
const target = nodes.get(capturedId) ?? null;
|
|
4692
|
+
const path = target ? ancestorsForTarget(target) : [];
|
|
4693
|
+
const ev = buildPointerEvent("pointerup", path, event);
|
|
4694
|
+
dispatchWithPhases("pointerup", path, target, ev);
|
|
4695
|
+
capturedId = null;
|
|
4696
|
+
prevented = ev.defaultPrevented;
|
|
4697
|
+
return prevented;
|
|
4698
|
+
}
|
|
4699
|
+
if (event.type === "pointerup") {
|
|
4700
|
+
dispatchPointerEvent("pointerup", event);
|
|
4701
|
+
capturedId = null;
|
|
4702
|
+
return prevented;
|
|
4703
|
+
}
|
|
4704
|
+
dispatchPointerEvent(event.type, event);
|
|
4705
|
+
return prevented;
|
|
4317
4706
|
}
|
|
4318
|
-
if (event.type === "
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
return false;
|
|
4707
|
+
if (event.type === "beforeinput" || event.type === "input" || event.type === "compositionstart" || event.type === "compositionupdate" || event.type === "compositionend" || event.type === "paste") {
|
|
4708
|
+
prevented = dispatchToFocusedText(event.type, event);
|
|
4709
|
+
return prevented;
|
|
4322
4710
|
}
|
|
4323
|
-
|
|
4324
|
-
|
|
4711
|
+
return prevented;
|
|
4712
|
+
} finally {
|
|
4713
|
+
latency === null || latency === void 0 || latency.recordEventDispatchEnd(event, { defaultPrevented: prevented });
|
|
4325
4714
|
}
|
|
4326
|
-
if (event.type === "beforeinput" || event.type === "input" || event.type === "compositionstart" || event.type === "compositionupdate" || event.type === "compositionend" || event.type === "paste") return dispatchToFocusedText(event.type, event);
|
|
4327
|
-
return false;
|
|
4328
4715
|
},
|
|
4329
4716
|
debugNodes() {
|
|
4330
4717
|
return Array.from(nodes.values()).map((n) => ({
|
|
@@ -5439,8 +5826,8 @@ function createTuiProfiler(name) {
|
|
|
5439
5826
|
const invalidatePlaneCounts = new Map();
|
|
5440
5827
|
const renderPlaneCounts = new Map();
|
|
5441
5828
|
const logEveryMs = Number((env === null || env === void 0 ? void 0 : env.DIMCODE_PROFILE_TUI_LOG_EVERY_MS) ?? 1e3);
|
|
5442
|
-
const now$
|
|
5443
|
-
let lastLogAt = now$
|
|
5829
|
+
const now$3 = defaultNow;
|
|
5830
|
+
let lastLogAt = now$3();
|
|
5444
5831
|
function incrementPlaneCount(target, key) {
|
|
5445
5832
|
const normalized = String(key ?? "all").trim() || "all";
|
|
5446
5833
|
target.set(normalized, (target.get(normalized) ?? 0) + 1);
|
|
@@ -5453,7 +5840,7 @@ function createTuiProfiler(name) {
|
|
|
5453
5840
|
if (dest === "stdout" || dest === "both") console.log(line);
|
|
5454
5841
|
}
|
|
5455
5842
|
function flushLog() {
|
|
5456
|
-
const at = now$
|
|
5843
|
+
const at = now$3();
|
|
5457
5844
|
const elapsed = at - lastLogAt;
|
|
5458
5845
|
if (elapsed <= 0) return;
|
|
5459
5846
|
lastLogAt = at;
|
|
@@ -5524,7 +5911,7 @@ function createTuiProfiler(name) {
|
|
|
5524
5911
|
const timer = setInterval(flushLog, Number.isFinite(logEveryMs) ? Math.max(100, logEveryMs) : 1e3);
|
|
5525
5912
|
(_unref = timer.unref) === null || _unref === void 0 || _unref.call(timer);
|
|
5526
5913
|
return {
|
|
5527
|
-
now: now$
|
|
5914
|
+
now: now$3,
|
|
5528
5915
|
recordInvalidate(info) {
|
|
5529
5916
|
invalidates++;
|
|
5530
5917
|
incrementPlaneCount(invalidatePlaneCounts, (info === null || info === void 0 ? void 0 : info.plane) ?? "all");
|
|
@@ -6644,6 +7031,7 @@ function createTerminalApp(options) {
|
|
|
6644
7031
|
rows: options.rows
|
|
6645
7032
|
});
|
|
6646
7033
|
const trace = createTraceStore({ enabled: Boolean(globalThis.__VT_DEBUG_TRACE__) });
|
|
7034
|
+
const latency = getCliLatencyProfiler();
|
|
6647
7035
|
const profiler = createTuiProfiler("cli-scheduler");
|
|
6648
7036
|
const events = createCliEventManager({
|
|
6649
7037
|
record: (event) => {
|
|
@@ -6665,7 +7053,12 @@ function createTerminalApp(options) {
|
|
|
6665
7053
|
}
|
|
6666
7054
|
});
|
|
6667
7055
|
const render = createRenderManager(terminal);
|
|
6668
|
-
const offCommit = terminal.on("commit", ({ dirtyRows, planes }) => {
|
|
7056
|
+
const offCommit = terminal.on("commit", ({ dirtyRows, planes, sync }) => {
|
|
7057
|
+
latency === null || latency === void 0 || latency.recordCommit({
|
|
7058
|
+
dirtyRows,
|
|
7059
|
+
planes,
|
|
7060
|
+
sync
|
|
7061
|
+
});
|
|
6669
7062
|
if (!trace.enabled.value) return;
|
|
6670
7063
|
trace.push({
|
|
6671
7064
|
type: "commit",
|
|
@@ -6686,7 +7079,6 @@ function createTerminalApp(options) {
|
|
|
6686
7079
|
let pendingInvalidateAllPlanes = false;
|
|
6687
7080
|
const pendingInvalidatePlanes = new Set();
|
|
6688
7081
|
const env = (process$1 === null || process$1 === void 0 ? void 0 : process$1.env) ?? {};
|
|
6689
|
-
const isGhostty = "GHOSTTY_RESOURCES_DIR" in env;
|
|
6690
7082
|
const throttleMs = (() => {
|
|
6691
7083
|
const raw = env.DIMCODE_TUI_THROTTLE_MS;
|
|
6692
7084
|
if (!raw) return 0;
|
|
@@ -6696,7 +7088,7 @@ function createTerminalApp(options) {
|
|
|
6696
7088
|
const frameThrottleMs = (() => {
|
|
6697
7089
|
var _process$stdout;
|
|
6698
7090
|
if (!(process$1 === null || process$1 === void 0 || (_process$stdout = process$1.stdout) === null || _process$stdout === void 0 ? void 0 : _process$stdout.isTTY)) return 0;
|
|
6699
|
-
return
|
|
7091
|
+
return 16;
|
|
6700
7092
|
})();
|
|
6701
7093
|
function queueInvalidatePlane(plane) {
|
|
6702
7094
|
if (!plane) {
|
|
@@ -6723,14 +7115,22 @@ function createTerminalApp(options) {
|
|
|
6723
7115
|
scheduled = false;
|
|
6724
7116
|
flushing = true;
|
|
6725
7117
|
const activePlanes = takeActivePlanes();
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
sync
|
|
7118
|
+
latency === null || latency === void 0 || latency.recordFlushStart({
|
|
7119
|
+
sync,
|
|
7120
|
+
activePlanes
|
|
6730
7121
|
});
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
7122
|
+
try {
|
|
7123
|
+
render.render({ activePlanes });
|
|
7124
|
+
terminal.commit({
|
|
7125
|
+
planes: activePlanes,
|
|
7126
|
+
sync
|
|
7127
|
+
});
|
|
7128
|
+
} finally {
|
|
7129
|
+
latency === null || latency === void 0 || latency.recordFlushEnd();
|
|
7130
|
+
flushing = false;
|
|
7131
|
+
lastFlushAtMs = Date.now();
|
|
7132
|
+
scheduledAtMs = 0;
|
|
7133
|
+
}
|
|
6734
7134
|
if (pendingInvalidateAfterFlush) {
|
|
6735
7135
|
pendingInvalidateAfterFlush = false;
|
|
6736
7136
|
flush(true);
|
|
@@ -6774,12 +7174,16 @@ function createTerminalApp(options) {
|
|
|
6774
7174
|
}
|
|
6775
7175
|
function invalidate(options$1) {
|
|
6776
7176
|
if (disposed) return;
|
|
7177
|
+
const priority = (options$1 === null || options$1 === void 0 ? void 0 : options$1.priority) ?? "normal";
|
|
7178
|
+
latency === null || latency === void 0 || latency.recordSchedulerInvalidate({
|
|
7179
|
+
priority,
|
|
7180
|
+
plane: (options$1 === null || options$1 === void 0 ? void 0 : options$1.plane) ?? null
|
|
7181
|
+
});
|
|
6777
7182
|
if (flushing) {
|
|
6778
7183
|
queueInvalidatePlane(options$1 === null || options$1 === void 0 ? void 0 : options$1.plane);
|
|
6779
7184
|
pendingInvalidateAfterFlush = true;
|
|
6780
7185
|
return;
|
|
6781
7186
|
}
|
|
6782
|
-
const priority = (options$1 === null || options$1 === void 0 ? void 0 : options$1.priority) ?? "normal";
|
|
6783
7187
|
queueInvalidatePlane(options$1 === null || options$1 === void 0 ? void 0 : options$1.plane);
|
|
6784
7188
|
profiler === null || profiler === void 0 || profiler.recordInvalidate({ plane: (options$1 === null || options$1 === void 0 ? void 0 : options$1.plane) ?? null });
|
|
6785
7189
|
if (priority === "high") {
|
|
@@ -7016,6 +7420,7 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7016
7420
|
let palette = options === null || options === void 0 ? void 0 : options.palette;
|
|
7017
7421
|
const trackResize = (options === null || options === void 0 ? void 0 : options.trackResize) ?? true;
|
|
7018
7422
|
const getImeAnchor = options === null || options === void 0 ? void 0 : options.getImeAnchor;
|
|
7423
|
+
const cliLatency = getCliLatencyProfiler();
|
|
7019
7424
|
const profiler = createTuiProfiler("stdout-renderer");
|
|
7020
7425
|
function resolveUseSyncOutput() {
|
|
7021
7426
|
if ((options === null || options === void 0 ? void 0 : options.useSyncOutput) != null) return options.useSyncOutput;
|
|
@@ -7025,13 +7430,13 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7025
7430
|
const v = String(envValue).trim().toLowerCase();
|
|
7026
7431
|
return v === "1" || v === "true" || v === "yes";
|
|
7027
7432
|
}
|
|
7028
|
-
const term = String(env$1.TERM ?? "").toLowerCase();
|
|
7029
|
-
const termProgram = String(env$1.TERM_PROGRAM ?? "").toLowerCase();
|
|
7433
|
+
const term$1 = String(env$1.TERM ?? "").toLowerCase();
|
|
7434
|
+
const termProgram$1 = String(env$1.TERM_PROGRAM ?? "").toLowerCase();
|
|
7030
7435
|
const termProgramVersion = env$1.TERM_PROGRAM_VERSION;
|
|
7031
7436
|
const isGhostty$1 = "GHOSTTY_RESOURCES_DIR" in env$1;
|
|
7032
|
-
const isProblematicTerminal = isGhostty$1 || termProgram.includes("apple_terminal") || term.includes("screen") && !term.includes("tmux");
|
|
7437
|
+
const isProblematicTerminal = isGhostty$1 || termProgram$1.includes("apple_terminal") || term$1.includes("screen") && !term$1.includes("tmux");
|
|
7033
7438
|
if (isProblematicTerminal) return false;
|
|
7034
|
-
const isGoodTerminal = termProgram.includes("iterm") && termProgramVersion && compareVersion(String(termProgramVersion), "3.5.0") >= 0;
|
|
7439
|
+
const isGoodTerminal = termProgram$1.includes("iterm") && termProgramVersion && compareVersion(String(termProgramVersion), "3.5.0") >= 0;
|
|
7035
7440
|
if (isGoodTerminal) return true;
|
|
7036
7441
|
return false;
|
|
7037
7442
|
}
|
|
@@ -7068,7 +7473,10 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7068
7473
|
return .6;
|
|
7069
7474
|
})();
|
|
7070
7475
|
const disableCursorPos = isGhostty && (process$1 === null || process$1 === void 0 || (_ref3 = process$1.env) === null || _ref3 === void 0 ? void 0 : _ref3.DIMCODE_DISABLE_CURSOR_POS) === "1";
|
|
7071
|
-
const
|
|
7476
|
+
const termProgram = String(env.TERM_PROGRAM ?? "").trim().toLowerCase();
|
|
7477
|
+
const term = String(env.TERM ?? "").trim().toLowerCase();
|
|
7478
|
+
const isVscodeTerminal = termProgram === "vscode" || "VSCODE_PID" in env || "VSCODE_IPC_HOOK_CLI" in env;
|
|
7479
|
+
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"));
|
|
7072
7480
|
const enableOsc8Links = (() => {
|
|
7073
7481
|
if (!out.isTTY) return false;
|
|
7074
7482
|
const raw = String(env.DIMCODE_TUI_LINKS ?? "").trim().toLowerCase();
|
|
@@ -7089,7 +7497,7 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7089
7497
|
let accumulatedDirtyMax = -1;
|
|
7090
7498
|
let accumulatedScrollOperations = null;
|
|
7091
7499
|
let accumulatedSkipUnchangedDirtyRows = true;
|
|
7092
|
-
const MIN_FRAME_MS = !out.isTTY ? 0 :
|
|
7500
|
+
const MIN_FRAME_MS = !out.isTTY ? 0 : 16;
|
|
7093
7501
|
function clampCellToViewport(cell, size) {
|
|
7094
7502
|
const maxX = Math.max(0, Math.floor(size.cols) - 1);
|
|
7095
7503
|
const maxY = Math.max(0, Math.floor(size.rows) - 1);
|
|
@@ -7558,6 +7966,7 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7558
7966
|
function doRender(dirtyRows, scrollOperations, skipUnchangedDirtyRows = false) {
|
|
7559
7967
|
if (isDebugEnabled()) getDebugLog().render(`doRender() START: dirtyRows=${(dirtyRows === null || dirtyRows === void 0 ? void 0 : dirtyRows.length) ?? "null"}`);
|
|
7560
7968
|
if (disposed) return;
|
|
7969
|
+
cliLatency === null || cliLatency === void 0 || cliLatency.recordStdoutRenderStart();
|
|
7561
7970
|
pendingRender = false;
|
|
7562
7971
|
accumulatedAllRows = false;
|
|
7563
7972
|
accumulatedDirtyBits = null;
|
|
@@ -7628,6 +8037,7 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7628
8037
|
if (!sorted) outRows.sort((a, b) => a - b);
|
|
7629
8038
|
return outRows;
|
|
7630
8039
|
})();
|
|
8040
|
+
if (fpPrevValid && rowsToRender) currentFP.set(prevFP);
|
|
7631
8041
|
const frameParts = [];
|
|
7632
8042
|
frameParts.push(!isGhostty && useSyncOutput ? SYNC_START : "");
|
|
7633
8043
|
frameParts.push("\x1B[?7l");
|
|
@@ -7735,6 +8145,10 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7735
8145
|
const overlayRowSet = overlayRows.length ? new Set(overlayRows) : null;
|
|
7736
8146
|
const overlayPartialRows = Array.from(new Set([...overlayCoverage.partialRows, ...prevOverlayPartialRows])).sort((a, b) => a - b);
|
|
7737
8147
|
const overlayPartialRowSet = overlayPartialRows.length ? new Set(overlayPartialRows) : null;
|
|
8148
|
+
const overlayTouchedRowSet = (() => {
|
|
8149
|
+
if (!overlayRowSet && !overlayPartialRowSet) return null;
|
|
8150
|
+
return new Set([...overlayRowSet ? Array.from(overlayRowSet) : [], ...overlayPartialRowSet ? Array.from(overlayPartialRowSet) : []]);
|
|
8151
|
+
})();
|
|
7738
8152
|
let explicitScrollOperations = normalizedScrollOperations;
|
|
7739
8153
|
let hiddenExplicitDirtyRows = null;
|
|
7740
8154
|
let allowInferredScrollRegions = true;
|
|
@@ -7818,12 +8232,12 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7818
8232
|
frameParts.push("\x1B[r");
|
|
7819
8233
|
}
|
|
7820
8234
|
const explicitDirtyRows = Array.from(explicitRowsToRender).sort((a, b) => a - b);
|
|
7821
|
-
const overlayDirtyRows =
|
|
8235
|
+
const overlayDirtyRows = overlayTouchedRowSet ? explicitDirtyRows.filter((y) => overlayTouchedRowSet.has(y)) : [];
|
|
7822
8236
|
const paintedExplicitRows = [];
|
|
7823
8237
|
for (const y of explicitDirtyRows) {
|
|
7824
8238
|
const row = terminal.getRow(y);
|
|
7825
|
-
const overlayRow =
|
|
7826
|
-
if (overlayRow) {
|
|
8239
|
+
const overlayRow = overlayTouchedRowSet === null || overlayTouchedRowSet === void 0 ? void 0 : overlayTouchedRowSet.has(y);
|
|
8240
|
+
if (overlayRow || useConservativeDirtyRowRendering) {
|
|
7827
8241
|
fingerprintRow(row, y, size.cols);
|
|
7828
8242
|
renderRow$1(y, row);
|
|
7829
8243
|
paintedExplicitRows.push(y);
|
|
@@ -7898,10 +8312,10 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7898
8312
|
const extraDirtyRows = overlayRowSet ? shift.extraDirtyRows.filter((y) => !overlayRowSet.has(y) || Boolean(overlayPartialRowSet === null || overlayPartialRowSet === void 0 ? void 0 : overlayPartialRowSet.has(y))) : shift.extraDirtyRows;
|
|
7899
8313
|
for (const y of extraDirtyRows) {
|
|
7900
8314
|
const row = terminal.getRow(y);
|
|
7901
|
-
const overlayRow =
|
|
7902
|
-
if (overlayRow) {
|
|
7903
|
-
renderRow$1(y, row);
|
|
8315
|
+
const overlayRow = overlayTouchedRowSet === null || overlayTouchedRowSet === void 0 ? void 0 : overlayTouchedRowSet.has(y);
|
|
8316
|
+
if (overlayRow || useConservativeDirtyRowRendering) {
|
|
7904
8317
|
fingerprintRow(row, y, size.cols);
|
|
8318
|
+
renderRow$1(y, row);
|
|
7905
8319
|
continue;
|
|
7906
8320
|
}
|
|
7907
8321
|
const span = resolveChangedSpanAgainstReference(row, y, size.cols);
|
|
@@ -7937,13 +8351,13 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7937
8351
|
renderRow$1(y, row);
|
|
7938
8352
|
}
|
|
7939
8353
|
} else {
|
|
7940
|
-
const overlayDirtyRows =
|
|
8354
|
+
const overlayDirtyRows = overlayTouchedRowSet ? rowsToRender.filter((y) => overlayTouchedRowSet.has(y)) : [];
|
|
7941
8355
|
if (isDebugEnabled()) getDebugLog().render(` Partial render: ${rowsToRender.length} dirty rows: [${rowsToRender.join(", ")}]${overlayDirtyRows.length ? ` (overlay-full-row: [${overlayDirtyRows.join(", ")}])` : ""}`);
|
|
7942
8356
|
for (const y of rowsToRender) {
|
|
7943
8357
|
const row = terminal.getRow(y);
|
|
7944
8358
|
fingerprintRow(row, y, size.cols);
|
|
7945
|
-
const overlayRow =
|
|
7946
|
-
if (overlayRow) {
|
|
8359
|
+
const overlayRow = overlayTouchedRowSet === null || overlayTouchedRowSet === void 0 ? void 0 : overlayTouchedRowSet.has(y);
|
|
8360
|
+
if (overlayRow || useConservativeDirtyRowRendering) {
|
|
7947
8361
|
renderRow$1(y, row);
|
|
7948
8362
|
continue;
|
|
7949
8363
|
}
|
|
@@ -7991,6 +8405,7 @@ function createStdoutRenderer(terminal, options) {
|
|
|
7991
8405
|
}
|
|
7992
8406
|
if (!hasFrameOutput) {
|
|
7993
8407
|
if (isDebugEnabled()) getDebugLog().render(" No-op frame skipped");
|
|
8408
|
+
cliLatency === null || cliLatency === void 0 || cliLatency.recordStdoutNoOutput();
|
|
7994
8409
|
return;
|
|
7995
8410
|
}
|
|
7996
8411
|
if (enableOsc8Links && activeStyle.href) frameParts.push(OSC8_CLOSE);
|
|
@@ -8119,6 +8534,11 @@ function createStdoutRenderer(terminal, options) {
|
|
|
8119
8534
|
bytes: frame.length,
|
|
8120
8535
|
mode: writeMode === "sync" ? "sync" : writeMode === "chunked" ? "chunked" : "stream"
|
|
8121
8536
|
});
|
|
8537
|
+
cliLatency === null || cliLatency === void 0 || cliLatency.recordStdoutWrite({
|
|
8538
|
+
durationMs: writeMs,
|
|
8539
|
+
bytes: frame.length,
|
|
8540
|
+
mode: writeMode === "sync" ? "sync" : writeMode === "chunked" ? "chunked" : "stream"
|
|
8541
|
+
});
|
|
8122
8542
|
}
|
|
8123
8543
|
if (isDebugEnabled()) {
|
|
8124
8544
|
const totalTime = (performance.now() - renderStart).toFixed(2);
|
|
@@ -8219,9 +8639,13 @@ function createStdoutRenderer(terminal, options) {
|
|
|
8219
8639
|
mergeScrollOperations(scrollOperations);
|
|
8220
8640
|
accumulatedSkipUnchangedDirtyRows && (accumulatedSkipUnchangedDirtyRows = skipUnchangedDirtyRows);
|
|
8221
8641
|
}
|
|
8222
|
-
|
|
8223
|
-
const now$
|
|
8224
|
-
const
|
|
8642
|
+
const now$3 = Date.now();
|
|
8643
|
+
const elapsed = now$3 - lastFrameTime;
|
|
8644
|
+
const queuedDelayMs = Math.max(0, MIN_FRAME_MS - elapsed);
|
|
8645
|
+
if (pendingRender && !sync) {
|
|
8646
|
+
cliLatency === null || cliLatency === void 0 || cliLatency.recordStdoutQueued(queuedDelayMs);
|
|
8647
|
+
return;
|
|
8648
|
+
}
|
|
8225
8649
|
if (sync) {
|
|
8226
8650
|
if (pendingRender) {
|
|
8227
8651
|
pendingRender = false;
|
|
@@ -8232,12 +8656,14 @@ function createStdoutRenderer(terminal, options) {
|
|
|
8232
8656
|
}
|
|
8233
8657
|
const rows = buildAccumulatedRows();
|
|
8234
8658
|
const pendingScrolls = buildAccumulatedScrollOperations();
|
|
8659
|
+
cliLatency === null || cliLatency === void 0 || cliLatency.recordStdoutQueued(0);
|
|
8235
8660
|
doRender(rows, pendingScrolls, accumulatedSkipUnchangedDirtyRows);
|
|
8236
8661
|
return;
|
|
8237
8662
|
}
|
|
8238
8663
|
if (elapsed >= MIN_FRAME_MS) {
|
|
8239
8664
|
const rows = buildAccumulatedRows();
|
|
8240
8665
|
const pendingScrolls = buildAccumulatedScrollOperations();
|
|
8666
|
+
cliLatency === null || cliLatency === void 0 || cliLatency.recordStdoutQueued(0);
|
|
8241
8667
|
doRender(rows, pendingScrolls, accumulatedSkipUnchangedDirtyRows);
|
|
8242
8668
|
} else {
|
|
8243
8669
|
pendingRender = true;
|
|
@@ -8249,7 +8675,8 @@ function createStdoutRenderer(terminal, options) {
|
|
|
8249
8675
|
const pendingScrolls = buildAccumulatedScrollOperations();
|
|
8250
8676
|
doRender(rows, pendingScrolls, accumulatedSkipUnchangedDirtyRows);
|
|
8251
8677
|
}
|
|
8252
|
-
},
|
|
8678
|
+
}, queuedDelayMs);
|
|
8679
|
+
cliLatency === null || cliLatency === void 0 || cliLatency.recordStdoutQueued(queuedDelayMs);
|
|
8253
8680
|
}
|
|
8254
8681
|
}
|
|
8255
8682
|
terminal.setFingerprintFn((ch, style) => {
|
|
@@ -8526,12 +8953,22 @@ const rowCache = new WeakMap();
|
|
|
8526
8953
|
function segmentsToKey(segments) {
|
|
8527
8954
|
return segments.map((s) => `${s.key}:${s.text}:${s.cols}:${s.wide}`).join("|");
|
|
8528
8955
|
}
|
|
8956
|
+
function isPlainStyle(style) {
|
|
8957
|
+
return !style.fg && !style.bg && !style.bold && !style.dim && !style.italic && !style.underline && !style.inverse && !style.href;
|
|
8958
|
+
}
|
|
8959
|
+
function isTransparentBlankRow(segments) {
|
|
8960
|
+
return segments.length === 1 && isPlainStyle(segments[0].style) && segments[0].text.trim().length === 0;
|
|
8961
|
+
}
|
|
8529
8962
|
function renderRow(terminal, metrics$1, wideScaleX, y, lineEl) {
|
|
8530
8963
|
const segments = computeRowSegments(terminal, y);
|
|
8531
8964
|
const newKey = segmentsToKey(segments);
|
|
8532
8965
|
const cachedKey = rowCache.get(lineEl);
|
|
8533
8966
|
if (cachedKey === newKey) return;
|
|
8534
8967
|
rowCache.set(lineEl, newKey);
|
|
8968
|
+
if (isTransparentBlankRow(segments)) {
|
|
8969
|
+
lineEl.replaceChildren();
|
|
8970
|
+
return;
|
|
8971
|
+
}
|
|
8535
8972
|
const fragment = document.createDocumentFragment();
|
|
8536
8973
|
for (const seg of segments) {
|
|
8537
8974
|
const span = document.createElement("span");
|
|
@@ -8552,6 +8989,7 @@ function createDomRenderer(terminal, container) {
|
|
|
8552
8989
|
container.style.whiteSpace = "pre";
|
|
8553
8990
|
container.style.display = "inline-block";
|
|
8554
8991
|
container.style.overflow = "hidden";
|
|
8992
|
+
container.style.position = "relative";
|
|
8555
8993
|
container.style.userSelect = "text";
|
|
8556
8994
|
container.style.outline = "none";
|
|
8557
8995
|
container.style.contain = "layout style";
|
|
@@ -8559,21 +8997,93 @@ function createDomRenderer(terminal, container) {
|
|
|
8559
8997
|
installAnsiPaletteCssVars(container);
|
|
8560
8998
|
let metrics$1 = measureCell(container);
|
|
8561
8999
|
let wideScaleX = 1;
|
|
8562
|
-
|
|
9000
|
+
const planeLayers = new Map();
|
|
8563
9001
|
let raf = 0;
|
|
8564
|
-
const pending = new
|
|
9002
|
+
const pending = new Map();
|
|
8565
9003
|
let disposed = false;
|
|
9004
|
+
function applyPlaneOffset(plane, offsetPx) {
|
|
9005
|
+
const layer = planeLayers.get(plane);
|
|
9006
|
+
if (!layer) return;
|
|
9007
|
+
const next = Number.isFinite(offsetPx) ? offsetPx : 0;
|
|
9008
|
+
if (layer.offsetPx === next) return;
|
|
9009
|
+
layer.offsetPx = next;
|
|
9010
|
+
layer.contentEl.style.transform = next ? `translateY(${next}px)` : "translateY(0px)";
|
|
9011
|
+
}
|
|
9012
|
+
function applyPlaneViewport(plane, viewport) {
|
|
9013
|
+
const layer = planeLayers.get(plane);
|
|
9014
|
+
if (!layer) return;
|
|
9015
|
+
const totalHeight = terminal.size().rows * metrics$1.cellHeight;
|
|
9016
|
+
if (!viewport) {
|
|
9017
|
+
layer.viewportTopPx = 0;
|
|
9018
|
+
layer.viewportHeightPx = null;
|
|
9019
|
+
layer.el.style.clipPath = "none";
|
|
9020
|
+
return;
|
|
9021
|
+
}
|
|
9022
|
+
const topPx = Math.max(0, Math.min(totalHeight, Math.floor(viewport.topPx)));
|
|
9023
|
+
const heightPx = Math.max(0, Math.min(totalHeight - topPx, Math.floor(viewport.heightPx)));
|
|
9024
|
+
layer.viewportTopPx = topPx;
|
|
9025
|
+
layer.viewportHeightPx = heightPx;
|
|
9026
|
+
if (topPx === 0 && heightPx >= totalHeight) {
|
|
9027
|
+
layer.el.style.clipPath = "none";
|
|
9028
|
+
return;
|
|
9029
|
+
}
|
|
9030
|
+
const bottomPx = Math.max(0, totalHeight - topPx - heightPx);
|
|
9031
|
+
layer.el.style.clipPath = `inset(${topPx}px 0px ${bottomPx}px 0px)`;
|
|
9032
|
+
}
|
|
8566
9033
|
function rebuildLines() {
|
|
8567
9034
|
const { rows, cols } = terminal.size();
|
|
8568
9035
|
container.style.width = `${cols * metrics$1.cellWidth}px`;
|
|
8569
9036
|
container.style.height = `${rows * metrics$1.cellHeight}px`;
|
|
8570
9037
|
const fragment = document.createDocumentFragment();
|
|
8571
|
-
|
|
8572
|
-
const
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
|
|
9038
|
+
for (let i = 0; i < TERMINAL_RENDER_PLANES.length; i++) {
|
|
9039
|
+
const plane = TERMINAL_RENDER_PLANES[i];
|
|
9040
|
+
const planeTerminal = getPlaneTerminal(terminal, plane);
|
|
9041
|
+
let layer = planeLayers.get(plane);
|
|
9042
|
+
if (!layer) {
|
|
9043
|
+
const el = document.createElement("div");
|
|
9044
|
+
const contentEl = document.createElement("div");
|
|
9045
|
+
el.dataset.vtPlane = plane;
|
|
9046
|
+
el.style.pointerEvents = "none";
|
|
9047
|
+
contentEl.style.position = "absolute";
|
|
9048
|
+
contentEl.style.left = "0";
|
|
9049
|
+
contentEl.style.top = "0";
|
|
9050
|
+
layer = {
|
|
9051
|
+
el,
|
|
9052
|
+
contentEl,
|
|
9053
|
+
lines: [],
|
|
9054
|
+
offsetPx: 0,
|
|
9055
|
+
terminal: planeTerminal,
|
|
9056
|
+
viewportTopPx: 0,
|
|
9057
|
+
viewportHeightPx: null
|
|
9058
|
+
};
|
|
9059
|
+
planeLayers.set(plane, layer);
|
|
9060
|
+
}
|
|
9061
|
+
layer.terminal = planeTerminal;
|
|
9062
|
+
layer.el.style.position = "absolute";
|
|
9063
|
+
layer.el.style.left = "0";
|
|
9064
|
+
layer.el.style.top = "0";
|
|
9065
|
+
layer.el.style.width = `${cols * metrics$1.cellWidth}px`;
|
|
9066
|
+
layer.el.style.height = `${rows * metrics$1.cellHeight}px`;
|
|
9067
|
+
layer.el.style.overflow = "hidden";
|
|
9068
|
+
layer.el.style.zIndex = String(i);
|
|
9069
|
+
layer.contentEl.style.width = `${cols * metrics$1.cellWidth}px`;
|
|
9070
|
+
layer.contentEl.style.height = `${rows * metrics$1.cellHeight}px`;
|
|
9071
|
+
applyPlaneOffset(plane, layer.offsetPx);
|
|
9072
|
+
applyPlaneViewport(plane, layer.viewportHeightPx == null ? null : {
|
|
9073
|
+
topPx: layer.viewportTopPx,
|
|
9074
|
+
heightPx: layer.viewportHeightPx
|
|
9075
|
+
});
|
|
9076
|
+
const lineFragment = document.createDocumentFragment();
|
|
9077
|
+
layer.lines = Array.from({ length: rows }, () => {
|
|
9078
|
+
const line = document.createElement("div");
|
|
9079
|
+
line.style.cssText = `height:${metrics$1.cellHeight}px;width:${cols * metrics$1.cellWidth}px;overflow:hidden;contain:layout style`;
|
|
9080
|
+
lineFragment.appendChild(line);
|
|
9081
|
+
return line;
|
|
9082
|
+
});
|
|
9083
|
+
layer.contentEl.replaceChildren(lineFragment);
|
|
9084
|
+
layer.el.replaceChildren(layer.contentEl);
|
|
9085
|
+
fragment.appendChild(layer.el);
|
|
9086
|
+
}
|
|
8577
9087
|
container.replaceChildren(fragment);
|
|
8578
9088
|
}
|
|
8579
9089
|
function refresh() {
|
|
@@ -8582,22 +9092,46 @@ function createDomRenderer(terminal, container) {
|
|
|
8582
9092
|
wideScaleX = wideW > 0 ? Math.max(1, Math.min(2, metrics$1.cellWidth * 2 / wideW)) : 1;
|
|
8583
9093
|
rebuildLines();
|
|
8584
9094
|
const size = terminal.size();
|
|
8585
|
-
for (
|
|
9095
|
+
for (const plane of TERMINAL_RENDER_PLANES) {
|
|
9096
|
+
const layer = planeLayers.get(plane);
|
|
9097
|
+
if (!layer) continue;
|
|
9098
|
+
for (let y = 0; y < size.rows; y++) renderRow(layer.terminal, metrics$1, wideScaleX, y, layer.lines[y]);
|
|
9099
|
+
}
|
|
8586
9100
|
}
|
|
8587
9101
|
function flushPending() {
|
|
8588
9102
|
raf = 0;
|
|
8589
9103
|
if (disposed) return;
|
|
8590
|
-
for (const
|
|
8591
|
-
const
|
|
8592
|
-
|
|
9104
|
+
for (const plane of TERMINAL_RENDER_PLANES) {
|
|
9105
|
+
const layer = planeLayers.get(plane);
|
|
9106
|
+
const rows = pending.get(plane);
|
|
9107
|
+
if (!layer || !(rows === null || rows === void 0 ? void 0 : rows.size)) continue;
|
|
9108
|
+
for (const y of rows) {
|
|
9109
|
+
const line = layer.lines[y];
|
|
9110
|
+
if (line) renderRow(layer.terminal, metrics$1, wideScaleX, y, line);
|
|
9111
|
+
}
|
|
9112
|
+
rows.clear();
|
|
8593
9113
|
}
|
|
8594
|
-
pending.clear();
|
|
8595
9114
|
}
|
|
8596
|
-
const offCommit = terminal.on("commit", ({ dirtyRows }) => {
|
|
9115
|
+
const offCommit = terminal.on("commit", ({ dirtyRows, planes }) => {
|
|
9116
|
+
const activePlanes = (planes === null || planes === void 0 ? void 0 : planes.length) ? planes : TERMINAL_RENDER_PLANES;
|
|
8597
9117
|
if (dirtyRows === null) {
|
|
8598
9118
|
const size = terminal.size();
|
|
8599
|
-
for (
|
|
8600
|
-
|
|
9119
|
+
for (const plane of activePlanes) {
|
|
9120
|
+
let rows = pending.get(plane);
|
|
9121
|
+
if (!rows) {
|
|
9122
|
+
rows = new Set();
|
|
9123
|
+
pending.set(plane, rows);
|
|
9124
|
+
}
|
|
9125
|
+
for (let y = 0; y < size.rows; y++) rows.add(y);
|
|
9126
|
+
}
|
|
9127
|
+
} else for (const plane of activePlanes) {
|
|
9128
|
+
let rows = pending.get(plane);
|
|
9129
|
+
if (!rows) {
|
|
9130
|
+
rows = new Set();
|
|
9131
|
+
pending.set(plane, rows);
|
|
9132
|
+
}
|
|
9133
|
+
for (const y of dirtyRows) rows.add(y);
|
|
9134
|
+
}
|
|
8601
9135
|
if (!raf) {
|
|
8602
9136
|
raf = -1;
|
|
8603
9137
|
const id = requestAnimationFrame(() => {
|
|
@@ -8623,7 +9157,14 @@ function createDomRenderer(terminal, container) {
|
|
|
8623
9157
|
offResize();
|
|
8624
9158
|
if (raf > 0) cancelAnimationFrame(raf);
|
|
8625
9159
|
pending.clear();
|
|
9160
|
+
planeLayers.clear();
|
|
8626
9161
|
container.replaceChildren();
|
|
9162
|
+
},
|
|
9163
|
+
setPlaneOffset(plane, offsetPx) {
|
|
9164
|
+
applyPlaneOffset(plane, offsetPx);
|
|
9165
|
+
},
|
|
9166
|
+
setPlaneViewport(plane, viewport) {
|
|
9167
|
+
applyPlaneViewport(plane, viewport);
|
|
8627
9168
|
}
|
|
8628
9169
|
};
|
|
8629
9170
|
}
|
|
@@ -10032,6 +10573,7 @@ function mentionIndexAt$1(value, mentionToken, index) {
|
|
|
10032
10573
|
return countMentionTokens$1(value, mentionToken, index);
|
|
10033
10574
|
}
|
|
10034
10575
|
function createPromptMentionPlugin(options = {}) {
|
|
10576
|
+
const latency = getCliLatencyProfiler();
|
|
10035
10577
|
return {
|
|
10036
10578
|
name: "promptMention",
|
|
10037
10579
|
install: (ctx) => {
|
|
@@ -10177,6 +10719,12 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10177
10719
|
query: ctx0.query
|
|
10178
10720
|
});
|
|
10179
10721
|
if (handled !== false) {
|
|
10722
|
+
const value = ctx.getValue();
|
|
10723
|
+
const before$1 = value.slice(0, ctx0.tokenStart);
|
|
10724
|
+
const after$1 = value.slice(ctx0.tokenEnd);
|
|
10725
|
+
const nextValue$1 = `${before$1}${after$1}`;
|
|
10726
|
+
ctx.pushUndoSnapshot(nextValue$1);
|
|
10727
|
+
ctx.applyEdit(nextValue$1, ctx0.tokenStart);
|
|
10180
10728
|
promptMention.promptSuppressedKey.value = ctx0.key;
|
|
10181
10729
|
ctx.scheduler.invalidate();
|
|
10182
10730
|
return;
|
|
@@ -10213,8 +10761,17 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10213
10761
|
}
|
|
10214
10762
|
function handlePromptKeydown(e) {
|
|
10215
10763
|
if (!promptMention.promptVisible.value) return false;
|
|
10764
|
+
const markPromptOperation = (suffix) => {
|
|
10765
|
+
const ctx0 = promptMention.activeContext.value;
|
|
10766
|
+
const mentionTrigger = getProps().mentionTrigger || "@";
|
|
10767
|
+
const skillTrigger = getProps().skillTrigger || "";
|
|
10768
|
+
const tokenText = String((ctx0 === null || ctx0 === void 0 ? void 0 : ctx0.tokenText) ?? "");
|
|
10769
|
+
const scope = tokenText.startsWith(mentionTrigger) ? "prompt.mention" : skillTrigger && tokenText.startsWith(skillTrigger) ? "prompt.skill" : "prompt.command";
|
|
10770
|
+
latency === null || latency === void 0 || latency.markOperation(`${scope}.${suffix}`);
|
|
10771
|
+
};
|
|
10216
10772
|
const len = promptMention.promptMatches.value.length;
|
|
10217
10773
|
if (e.key === "ArrowDown") {
|
|
10774
|
+
markPromptOperation("navigate.next");
|
|
10218
10775
|
e.preventDefault();
|
|
10219
10776
|
if (len <= 0) promptMention.promptActive.value = 0;
|
|
10220
10777
|
else if (promptMention.promptActive.value >= len - 1) promptMention.promptActive.value = 0;
|
|
@@ -10223,6 +10780,7 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10223
10780
|
return true;
|
|
10224
10781
|
}
|
|
10225
10782
|
if (e.key === "ArrowUp") {
|
|
10783
|
+
markPromptOperation("navigate.prev");
|
|
10226
10784
|
e.preventDefault();
|
|
10227
10785
|
if (len <= 0) promptMention.promptActive.value = 0;
|
|
10228
10786
|
else if (promptMention.promptActive.value <= 0) promptMention.promptActive.value = len - 1;
|
|
@@ -10244,11 +10802,13 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10244
10802
|
const typed = String((ctx0 === null || ctx0 === void 0 ? void 0 : ctx0.tokenText) ?? "");
|
|
10245
10803
|
const candidate = String((match === null || match === void 0 || (_match$item = match.item) === null || _match$item === void 0 ? void 0 : _match$item.value) ?? "");
|
|
10246
10804
|
if (!typed || !candidate.startsWith(typed)) return false;
|
|
10805
|
+
markPromptOperation("accept");
|
|
10247
10806
|
e.preventDefault();
|
|
10248
10807
|
acceptPrompt(promptMention.promptActive.value);
|
|
10249
10808
|
return true;
|
|
10250
10809
|
}
|
|
10251
10810
|
if (e.key === "Tab" && (isMention || isSkill)) {
|
|
10811
|
+
markPromptOperation("accept");
|
|
10252
10812
|
e.preventDefault();
|
|
10253
10813
|
if (len === 0) return true;
|
|
10254
10814
|
const list = promptMention.promptMatches.value;
|
|
@@ -10258,12 +10818,14 @@ function createPromptMentionPlugin(options = {}) {
|
|
|
10258
10818
|
return true;
|
|
10259
10819
|
}
|
|
10260
10820
|
if (len === 0) return false;
|
|
10821
|
+
markPromptOperation("accept");
|
|
10261
10822
|
e.preventDefault();
|
|
10262
10823
|
acceptPrompt(promptMention.promptActive.value);
|
|
10263
10824
|
return true;
|
|
10264
10825
|
}
|
|
10265
10826
|
if (e.key === "Escape") {
|
|
10266
10827
|
var _promptMention$active;
|
|
10828
|
+
markPromptOperation("dismiss");
|
|
10267
10829
|
e.preventDefault();
|
|
10268
10830
|
promptMention.promptSuppressedKey.value = ((_promptMention$active = promptMention.activeContext.value) === null || _promptMention$active === void 0 ? void 0 : _promptMention$active.key) ?? null;
|
|
10269
10831
|
ctx.scheduler.invalidate();
|
|
@@ -16015,8 +16577,8 @@ function normalizeDelta(deltaY, mode = "auto") {
|
|
|
16015
16577
|
if (abs <= LINE_UNIT_THRESHOLD && Number.isInteger(deltaY)) return deltaY;
|
|
16016
16578
|
return deltaY / PIXELS_PER_LINE;
|
|
16017
16579
|
}
|
|
16018
|
-
function accelFactor(now$
|
|
16019
|
-
const dt = now$
|
|
16580
|
+
function accelFactor(now$3, lastAt) {
|
|
16581
|
+
const dt = now$3 - lastAt;
|
|
16020
16582
|
if (!Number.isFinite(dt) || dt <= 0 || dt > ACCEL_WINDOW_MS) return 1;
|
|
16021
16583
|
const t = 1 - dt / ACCEL_WINDOW_MS;
|
|
16022
16584
|
return 1 + t * (MAX_ACCEL - 1);
|
|
@@ -16026,15 +16588,17 @@ function createWheelScrollState() {
|
|
|
16026
16588
|
accumulator: 0,
|
|
16027
16589
|
lastAt: 0,
|
|
16028
16590
|
lastEdgeDir: 0,
|
|
16029
|
-
lastEdgeAt: 0
|
|
16591
|
+
lastEdgeAt: 0,
|
|
16592
|
+
lastLineUnitDir: 0
|
|
16030
16593
|
};
|
|
16031
16594
|
}
|
|
16032
|
-
function applyWheelScroll(state, deltaY, scrollTop, maxTop, now$
|
|
16595
|
+
function applyWheelScroll(state, deltaY, scrollTop, maxTop, now$3 = Date.now(), deltaMode = "auto", options = {}) {
|
|
16033
16596
|
if (!Number.isFinite(deltaY) || deltaY === 0 || maxTop <= 0) {
|
|
16034
16597
|
if (maxTop <= 0) {
|
|
16035
16598
|
state.accumulator = 0;
|
|
16036
16599
|
state.lastEdgeDir = 0;
|
|
16037
16600
|
state.lastEdgeAt = 0;
|
|
16601
|
+
state.lastLineUnitDir = 0;
|
|
16038
16602
|
}
|
|
16039
16603
|
return {
|
|
16040
16604
|
nextTop: scrollTop,
|
|
@@ -16042,15 +16606,17 @@ function applyWheelScroll(state, deltaY, scrollTop, maxTop, now$2 = Date.now(),
|
|
|
16042
16606
|
lines: 0
|
|
16043
16607
|
};
|
|
16044
16608
|
}
|
|
16045
|
-
const dt = state.lastAt ? now$
|
|
16609
|
+
const dt = state.lastAt ? now$3 - state.lastAt : Infinity;
|
|
16046
16610
|
const lineUnits = isLineUnitDelta(deltaY, deltaMode);
|
|
16047
|
-
|
|
16611
|
+
const inputDir = Math.sign(normalizeDelta(deltaY, deltaMode));
|
|
16612
|
+
if (lineUnits && dt !== Infinity && dt >= 0 && dt < MIN_TICK_INTERVAL_MS && inputDir === state.lastLineUnitDir) return {
|
|
16048
16613
|
nextTop: scrollTop,
|
|
16049
16614
|
dir: 0,
|
|
16050
16615
|
lines: 0
|
|
16051
16616
|
};
|
|
16052
|
-
|
|
16053
|
-
state.lastAt
|
|
16617
|
+
state.lastLineUnitDir = lineUnits ? inputDir : 0;
|
|
16618
|
+
const accel = lineUnits ? 1 : options.disableAcceleration ? 1 : state.lastAt ? accelFactor(now$3, state.lastAt) : 1;
|
|
16619
|
+
state.lastAt = now$3;
|
|
16054
16620
|
state.accumulator += normalizeDelta(deltaY, deltaMode) * accel;
|
|
16055
16621
|
const lines = Math.trunc(state.accumulator);
|
|
16056
16622
|
if (lines === 0) return {
|
|
@@ -16064,7 +16630,7 @@ function applyWheelScroll(state, deltaY, scrollTop, maxTop, now$2 = Date.now(),
|
|
|
16064
16630
|
const atBottom = scrollTop >= maxTop;
|
|
16065
16631
|
if (dir < 0 && atTop || dir > 0 && atBottom) {
|
|
16066
16632
|
state.lastEdgeDir = dir;
|
|
16067
|
-
state.lastEdgeAt = now$
|
|
16633
|
+
state.lastEdgeAt = now$3;
|
|
16068
16634
|
state.accumulator = 0;
|
|
16069
16635
|
return {
|
|
16070
16636
|
nextTop: scrollTop,
|
|
@@ -16072,7 +16638,7 @@ function applyWheelScroll(state, deltaY, scrollTop, maxTop, now$2 = Date.now(),
|
|
|
16072
16638
|
lines: 0
|
|
16073
16639
|
};
|
|
16074
16640
|
}
|
|
16075
|
-
if (state.lastEdgeDir !== 0 && now$
|
|
16641
|
+
if (state.lastEdgeDir !== 0 && now$3 - state.lastEdgeAt < EDGE_BOUNCE_MS && dir === -state.lastEdgeDir && (atTop || atBottom)) return {
|
|
16076
16642
|
nextTop: scrollTop,
|
|
16077
16643
|
dir: 0,
|
|
16078
16644
|
lines: 0
|
|
@@ -18169,4 +18735,4 @@ const TRouterView = defineComponent({
|
|
|
18169
18735
|
});
|
|
18170
18736
|
|
|
18171
18737
|
//#endregion
|
|
18172
|
-
export { ANSI16_COLORS, ANSI256_COLORS, ANSI8_COLORS, SGR_RESET, TAnchor, TBox, TDebugOverlay, TDialog, TERMINAL_RENDER_PLANES, TFlow, TInput, TInputBox, TInputPluginsContextKey, TJsonEditor, TList, TMultilineModal, TPathPicker, TRenderLayer, TRenderPlane, TRouterView, TSelect, TText, TTransition, TView, TerminalProvider, ansiColors, ansiStyles, applyWheelScroll, charCellWidth, clearTextCaches, createCliEventManager, createDefaultTInputHostAdapter, createDomRenderer, createEventManager, createNodeMentionPathProvider, createNodePathPickerProvider, createPromptMentionPlugin, createRuntime, createStdinDriver, createStdoutRenderer, createTInputHostPlugin, createTerminal, createTerminalApp, createTerminalRouter, createTextRestrictionPlugin, createTraceStore, createWheelScrollState, defaultTInputHostPlugin, detectTerminalColorCapability, formatInlineCellLine, getStdoutRendererMetrics, lintJsonText, normalizeNewlines, padEndByCells, parseAnsiSgr, readEventLog, resolveUserPath$1 as resolveUserPath, rgbToAnsi256, sanitizeInlineText, sanitizeTextBlock, sliceByCells, sliceByCellsRange, spaces, suggestPaths, textCellWidth, truecolorBgOpen, truecolorFgOpen, useLayout, useRenderNode, useRoute, useRouter, useTerminal, useTerminalNode, useTerminalRuntime, useVisibility, wrapByCells, writeEventLog, writeSnapshot };
|
|
18738
|
+
export { ANSI16_COLORS, ANSI256_COLORS, ANSI8_COLORS, SGR_RESET, TAnchor, TBox, TDebugOverlay, TDialog, TERMINAL_RENDER_PLANES, TFlow, TInput, TInputBox, TInputPluginsContextKey, TJsonEditor, TList, TMultilineModal, TPathPicker, TRenderLayer, TRenderPlane, TRouterView, TSelect, TText, TTransition, TView, TerminalProvider, ansiColors, ansiStyles, applyWheelScroll, charCellWidth, clearTextCaches, createCliEventManager, createDefaultTInputHostAdapter, createDomRenderer, createEventManager, createNodeMentionPathProvider, createNodePathPickerProvider, createPromptMentionPlugin, createRuntime, createStdinDriver, createStdoutRenderer, createTInputHostPlugin, createTerminal, createTerminalApp, createTerminalRouter, createTextRestrictionPlugin, createTraceStore, createWheelScrollState, defaultTInputHostPlugin, detectTerminalColorCapability, formatInlineCellLine, getCliLatencyProfiler, getStdoutRendererMetrics, lintJsonText, normalizeNewlines, padEndByCells, parseAnsiSgr, readEventLog, resolveUserPath$1 as resolveUserPath, rgbToAnsi256, sanitizeInlineText, sanitizeTextBlock, sliceByCells, sliceByCellsRange, spaces, suggestPaths, textCellWidth, truecolorBgOpen, truecolorFgOpen, useLayout, useRenderNode, useRoute, useRouter, useTerminal, useTerminalNode, useTerminalRuntime, useVisibility, wrapByCells, writeEventLog, writeSnapshot };
|