@code-yeongyu/senpi-tui 2026.8.3 → 2026.8.4
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/components/editor.d.ts.map +1 -1
- package/dist/components/editor.js +5 -1
- package/dist/components/editor.js.map +1 -1
- package/dist/slash-command-autocomplete.d.ts.map +1 -1
- package/dist/slash-command-autocomplete.js +36 -8
- package/dist/slash-command-autocomplete.js.map +1 -1
- package/dist/tui.d.ts +2 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +49 -33
- package/dist/tui.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slash-command-autocomplete.d.ts","sourceRoot":"","sources":["../src/slash-command-autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"slash-command-autocomplete.d.ts","sourceRoot":"","sources":["../src/slash-command-autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA+BxE,wBAAgB,0BAA0B,CACzC,QAAQ,EAAE,SAAS,CAAC,YAAY,GAAG,gBAAgB,CAAC,EAAE,EACtD,MAAM,EAAE,MAAM,GACZ,gBAAgB,EAAE,CAuDpB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fuzzyFilter } from "./fuzzy.js";
|
|
2
|
+
const SKILL_COMMAND_PREFIX = "skill:";
|
|
2
3
|
function compareSlashCommandSuggestion(prefix, left, right) {
|
|
3
4
|
const leftExact = left.value === prefix;
|
|
4
5
|
const rightExact = right.value === prefix;
|
|
@@ -14,25 +15,52 @@ function compareSlashCommandSuggestion(prefix, left, right) {
|
|
|
14
15
|
return left.index - right.index;
|
|
15
16
|
}
|
|
16
17
|
export function getSlashCommandSuggestions(commands, prefix) {
|
|
17
|
-
const
|
|
18
|
+
const normalizedPrefix = prefix.toLowerCase();
|
|
19
|
+
const explicitSkillNamespace = normalizedPrefix.startsWith(SKILL_COMMAND_PREFIX);
|
|
20
|
+
const hasSkillCommands = commands.some((cmd) => {
|
|
18
21
|
const name = "name" in cmd ? cmd.name : cmd.value;
|
|
22
|
+
return name.startsWith(SKILL_COMMAND_PREFIX);
|
|
23
|
+
});
|
|
24
|
+
const commandItems = commands.flatMap((cmd) => {
|
|
25
|
+
const name = "name" in cmd ? cmd.name : cmd.value;
|
|
26
|
+
const isSkill = name.startsWith(SKILL_COMMAND_PREFIX);
|
|
27
|
+
const skillName = isSkill ? name.slice(SKILL_COMMAND_PREFIX.length) : "";
|
|
28
|
+
if (isSkill &&
|
|
29
|
+
!explicitSkillNamespace &&
|
|
30
|
+
(normalizedPrefix.length === 0 || !skillName.toLowerCase().startsWith(normalizedPrefix))) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
19
33
|
const hint = "argumentHint" in cmd && cmd.argumentHint ? cmd.argumentHint : undefined;
|
|
20
34
|
const desc = cmd.description ?? "";
|
|
21
35
|
const fullDesc = hint ? (desc ? `${hint} — ${desc}` : hint) : desc;
|
|
22
|
-
return
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
36
|
+
return [
|
|
37
|
+
{
|
|
38
|
+
name,
|
|
39
|
+
label: name,
|
|
40
|
+
description: fullDesc || undefined,
|
|
41
|
+
searchText: isSkill && !explicitSkillNamespace ? skillName : name,
|
|
42
|
+
},
|
|
43
|
+
];
|
|
27
44
|
});
|
|
28
|
-
|
|
45
|
+
if (hasSkillCommands &&
|
|
46
|
+
!explicitSkillNamespace &&
|
|
47
|
+
normalizedPrefix.length > 0 &&
|
|
48
|
+
SKILL_COMMAND_PREFIX.startsWith(normalizedPrefix)) {
|
|
49
|
+
commandItems.push({
|
|
50
|
+
name: SKILL_COMMAND_PREFIX,
|
|
51
|
+
label: SKILL_COMMAND_PREFIX,
|
|
52
|
+
description: "Browse available skills",
|
|
53
|
+
searchText: SKILL_COMMAND_PREFIX,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return fuzzyFilter(commandItems, prefix, (item) => item.searchText)
|
|
29
57
|
.map((item, index) => ({
|
|
30
58
|
value: item.name,
|
|
31
59
|
label: item.label,
|
|
32
60
|
...(item.description && { description: item.description }),
|
|
33
61
|
index,
|
|
34
62
|
}))
|
|
35
|
-
.sort((left, right) => compareSlashCommandSuggestion(
|
|
63
|
+
.sort((left, right) => compareSlashCommandSuggestion(normalizedPrefix, left, right))
|
|
36
64
|
.map(({ index: _index, ...item }) => item);
|
|
37
65
|
}
|
|
38
66
|
//# sourceMappingURL=slash-command-autocomplete.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slash-command-autocomplete.js","sourceRoot":"","sources":["../src/slash-command-autocomplete.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"slash-command-autocomplete.js","sourceRoot":"","sources":["../src/slash-command-autocomplete.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AutocompleteItem, SlashCommand } from \"./autocomplete.ts\";\nimport { fuzzyFilter } from \"./fuzzy.ts\";\n\nconst SKILL_COMMAND_PREFIX = \"skill:\";\n\ntype CommandItem = {\n\treadonly name: string;\n\treadonly label: string;\n\treadonly description?: string;\n\treadonly searchText: string;\n};\n\ntype RankedCommandItem = AutocompleteItem & {\n\treadonly index: number;\n};\n\nfunction compareSlashCommandSuggestion(prefix: string, left: RankedCommandItem, right: RankedCommandItem): number {\n\tconst leftExact = left.value === prefix;\n\tconst rightExact = right.value === prefix;\n\tif (leftExact !== rightExact) return leftExact ? -1 : 1;\n\n\tconst leftPrefix = left.value.startsWith(prefix);\n\tconst rightPrefix = right.value.startsWith(prefix);\n\tif (leftPrefix !== rightPrefix) return leftPrefix ? -1 : 1;\n\tif (leftPrefix && rightPrefix && left.value.length !== right.value.length) {\n\t\treturn right.value.length - left.value.length;\n\t}\n\n\treturn left.index - right.index;\n}\n\nexport function getSlashCommandSuggestions(\n\tcommands: readonly (SlashCommand | AutocompleteItem)[],\n\tprefix: string,\n): AutocompleteItem[] {\n\tconst normalizedPrefix = prefix.toLowerCase();\n\tconst explicitSkillNamespace = normalizedPrefix.startsWith(SKILL_COMMAND_PREFIX);\n\tconst hasSkillCommands = commands.some((cmd) => {\n\t\tconst name = \"name\" in cmd ? cmd.name : cmd.value;\n\t\treturn name.startsWith(SKILL_COMMAND_PREFIX);\n\t});\n\tconst commandItems: CommandItem[] = commands.flatMap((cmd) => {\n\t\tconst name = \"name\" in cmd ? cmd.name : cmd.value;\n\t\tconst isSkill = name.startsWith(SKILL_COMMAND_PREFIX);\n\t\tconst skillName = isSkill ? name.slice(SKILL_COMMAND_PREFIX.length) : \"\";\n\t\tif (\n\t\t\tisSkill &&\n\t\t\t!explicitSkillNamespace &&\n\t\t\t(normalizedPrefix.length === 0 || !skillName.toLowerCase().startsWith(normalizedPrefix))\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst hint = \"argumentHint\" in cmd && cmd.argumentHint ? cmd.argumentHint : undefined;\n\t\tconst desc = cmd.description ?? \"\";\n\t\tconst fullDesc = hint ? (desc ? `${hint} — ${desc}` : hint) : desc;\n\t\treturn [\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tlabel: name,\n\t\t\t\tdescription: fullDesc || undefined,\n\t\t\t\tsearchText: isSkill && !explicitSkillNamespace ? skillName : name,\n\t\t\t},\n\t\t];\n\t});\n\n\tif (\n\t\thasSkillCommands &&\n\t\t!explicitSkillNamespace &&\n\t\tnormalizedPrefix.length > 0 &&\n\t\tSKILL_COMMAND_PREFIX.startsWith(normalizedPrefix)\n\t) {\n\t\tcommandItems.push({\n\t\t\tname: SKILL_COMMAND_PREFIX,\n\t\t\tlabel: SKILL_COMMAND_PREFIX,\n\t\t\tdescription: \"Browse available skills\",\n\t\t\tsearchText: SKILL_COMMAND_PREFIX,\n\t\t});\n\t}\n\n\treturn fuzzyFilter(commandItems, prefix, (item) => item.searchText)\n\t\t.map((item, index) => ({\n\t\t\tvalue: item.name,\n\t\t\tlabel: item.label,\n\t\t\t...(item.description && { description: item.description }),\n\t\t\tindex,\n\t\t}))\n\t\t.sort((left, right) => compareSlashCommandSuggestion(normalizedPrefix, left, right))\n\t\t.map(({ index: _index, ...item }) => item);\n}\n"]}
|
package/dist/tui.d.ts
CHANGED
|
@@ -325,6 +325,8 @@ export declare abstract class TuiBase extends Container {
|
|
|
325
325
|
* @param cursorPos The cursor position extracted from rendered output, or null
|
|
326
326
|
* @param totalLines Total number of rendered lines
|
|
327
327
|
*/
|
|
328
|
+
private buildHardwareCursorSequence;
|
|
329
|
+
private finishFrame;
|
|
328
330
|
private positionHardwareCursor;
|
|
329
331
|
/**
|
|
330
332
|
* Query the terminal's default background color with OSC 11 (`ESC ] 11 ; ? BEL`).
|
package/dist/tui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAIN,KAAK,QAAQ,EACb,KAAK,mBAAmB,EACxB,MAAM,sBAAsB,CAAC;AAS9B,OAAO,EAA2E,YAAY,EAAE,MAAM,YAAY,CAAC;AA0CnH;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEhC;;OAEG;IACH,WAAW,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjC;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,UAAU,IAAI,IAAI,CAAC;IAEnB,OAAO,CAAC,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,MAAM,sBAAsB,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC;AACtF,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,sBAAsB,CAAC;AAcxE,UAAU,mBAAmB;IAC5B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,0BAA0B,EAAE,MAAM,CAAC;IAC5C,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AASD;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACzB,oFAAoF;IACpF,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,IAAI,SAAS,GAAG,SAAS,CAE3F;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,sBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"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"}
|
package/dist/tui.js
CHANGED
|
@@ -56,6 +56,9 @@ export function isFocusable(component) {
|
|
|
56
56
|
* TUI finds and strips this marker, then positions the hardware cursor there.
|
|
57
57
|
*/
|
|
58
58
|
export const CURSOR_MARKER = "\x1b_pi:c\x07";
|
|
59
|
+
const FAKE_CURSOR_START = "\x1b[7m";
|
|
60
|
+
const FAKE_CURSOR_END = "\x1b[27m";
|
|
61
|
+
const FAKE_CURSOR_RESET = "\x1b[0m";
|
|
59
62
|
export { visibleWidth };
|
|
60
63
|
const renderErrorLoggedClasses = new Set();
|
|
61
64
|
let renderErrorLogWrites = 0;
|
|
@@ -355,9 +358,6 @@ export class TuiBase extends Container {
|
|
|
355
358
|
if (this.showHardwareCursor === enabled)
|
|
356
359
|
return;
|
|
357
360
|
this.showHardwareCursor = enabled;
|
|
358
|
-
if (!enabled) {
|
|
359
|
-
this.#setCursorVisibility(false);
|
|
360
|
-
}
|
|
361
361
|
this.requestRender();
|
|
362
362
|
}
|
|
363
363
|
getClearOnShrink() {
|
|
@@ -696,8 +696,11 @@ export class TuiBase extends Container {
|
|
|
696
696
|
this.beforeTerminalStop();
|
|
697
697
|
// Move cursor to the end of the content to prevent overwriting/artifacts on exit
|
|
698
698
|
if (this.previousLines.length > 0) {
|
|
699
|
-
//
|
|
700
|
-
|
|
699
|
+
// Only overwrite the cursor cell when the last published frame kept the hardware cursor hidden;
|
|
700
|
+
// a pending visibility change has not rendered yet and must not erase content.
|
|
701
|
+
if (this.#lastCursorVisibility === false) {
|
|
702
|
+
this.terminal.write(" ");
|
|
703
|
+
}
|
|
701
704
|
const targetRow = this.previousLines.length; // Line after the last content
|
|
702
705
|
const lineDiff = targetRow - this.hardwareCursorRow;
|
|
703
706
|
if (lineDiff > 0) {
|
|
@@ -1373,13 +1376,12 @@ export class TuiBase extends Container {
|
|
|
1373
1376
|
buffer += row.content;
|
|
1374
1377
|
finalPaintedScreenRow = row.screenRow;
|
|
1375
1378
|
}
|
|
1376
|
-
|
|
1379
|
+
const finalCursorRow = plan.viewportTop + finalPaintedScreenRow;
|
|
1380
|
+
buffer = this.finishFrame(buffer, cursorPos, newLines.length, finalCursorRow);
|
|
1377
1381
|
this.terminal.write(buffer);
|
|
1378
1382
|
this.cursorRow = Math.max(0, newLines.length - 1);
|
|
1379
|
-
this.hardwareCursorRow = plan.viewportTop + finalPaintedScreenRow;
|
|
1380
1383
|
this.maxLinesRendered = Math.max(this.maxLinesRendered, newLines.length);
|
|
1381
1384
|
this.previousViewportTop = plan.viewportTop;
|
|
1382
|
-
this.positionHardwareCursor(cursorPos, newLines.length);
|
|
1383
1385
|
this.setPreviousLines(newLines, rawLines);
|
|
1384
1386
|
this.previousKittyImageIds = this.collectKittyImageIds(newLines);
|
|
1385
1387
|
this.previousWidth = width;
|
|
@@ -1402,13 +1404,11 @@ export class TuiBase extends Container {
|
|
|
1402
1404
|
buffer += `\r\x1b[2K${TUI.SEGMENT_RESET}`;
|
|
1403
1405
|
buffer += newLines[row] ?? "";
|
|
1404
1406
|
}
|
|
1405
|
-
buffer
|
|
1407
|
+
buffer = this.finishFrame(buffer, cursorPos, newLines.length, bufferLength - 1);
|
|
1406
1408
|
this.terminal.write(buffer);
|
|
1407
1409
|
this.cursorRow = Math.max(0, newLines.length - 1);
|
|
1408
|
-
this.hardwareCursorRow = bufferLength - 1;
|
|
1409
1410
|
this.maxLinesRendered = newLines.length;
|
|
1410
1411
|
this.previousViewportTop = Math.max(0, bufferLength - height);
|
|
1411
|
-
this.positionHardwareCursor(cursorPos, newLines.length);
|
|
1412
1412
|
this.setPreviousLines(newLines, rawLines);
|
|
1413
1413
|
this.previousKittyImageIds = this.collectKittyImageIds(newLines);
|
|
1414
1414
|
this.previousWidth = width;
|
|
@@ -1431,14 +1431,13 @@ export class TuiBase extends Container {
|
|
|
1431
1431
|
buffer += `\r\x1b[2K${TUI.SEGMENT_RESET}`;
|
|
1432
1432
|
buffer += newLines[viewportTop + row] ?? "";
|
|
1433
1433
|
}
|
|
1434
|
-
|
|
1434
|
+
const finalCursorRow = viewportTop + Math.max(0, height - 1);
|
|
1435
|
+
buffer = this.finishFrame(buffer, cursorPos, newLines.length, finalCursorRow);
|
|
1435
1436
|
this.terminal.write(buffer);
|
|
1436
1437
|
this.muxViewportRepaintCount += 1;
|
|
1437
1438
|
this.cursorRow = Math.max(0, newLines.length - 1);
|
|
1438
|
-
this.hardwareCursorRow = viewportTop + Math.max(0, height - 1);
|
|
1439
1439
|
this.maxLinesRendered = newLines.length;
|
|
1440
1440
|
this.previousViewportTop = viewportTop;
|
|
1441
|
-
this.positionHardwareCursor(cursorPos, newLines.length);
|
|
1442
1441
|
this.setPreviousLines(newLines, rawLines);
|
|
1443
1442
|
this.previousKittyImageIds = this.collectKittyImageIds(newLines);
|
|
1444
1443
|
this.previousWidth = width;
|
|
@@ -1505,8 +1504,22 @@ export class TuiBase extends Container {
|
|
|
1505
1504
|
// Calculate visual column (width of text before marker)
|
|
1506
1505
|
const beforeMarker = line.slice(0, markerIndex);
|
|
1507
1506
|
const col = visibleWidth(beforeMarker);
|
|
1508
|
-
|
|
1509
|
-
|
|
1507
|
+
let afterMarker = line.slice(markerIndex + CURSOR_MARKER.length);
|
|
1508
|
+
if (this.showHardwareCursor && afterMarker.startsWith(FAKE_CURSOR_START)) {
|
|
1509
|
+
const fakeCursorEnd = afterMarker.indexOf(FAKE_CURSOR_END, FAKE_CURSOR_START.length);
|
|
1510
|
+
const fakeCursorReset = afterMarker.indexOf(FAKE_CURSOR_RESET, FAKE_CURSOR_START.length);
|
|
1511
|
+
if (fakeCursorReset !== -1 && (fakeCursorEnd === -1 || fakeCursorReset < fakeCursorEnd)) {
|
|
1512
|
+
// Keep a full reset because it may also terminate styles surrounding the fake cursor.
|
|
1513
|
+
afterMarker = afterMarker.slice(FAKE_CURSOR_START.length);
|
|
1514
|
+
}
|
|
1515
|
+
else if (fakeCursorEnd !== -1) {
|
|
1516
|
+
afterMarker =
|
|
1517
|
+
afterMarker.slice(FAKE_CURSOR_START.length, fakeCursorEnd) +
|
|
1518
|
+
afterMarker.slice(fakeCursorEnd + FAKE_CURSOR_END.length);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
// Strip marker and any colocated fake cursor styling when the hardware cursor owns the position.
|
|
1522
|
+
lines[row] = beforeMarker + afterMarker;
|
|
1510
1523
|
return { row, col };
|
|
1511
1524
|
}
|
|
1512
1525
|
}
|
|
@@ -1572,10 +1585,10 @@ export class TuiBase extends Container {
|
|
|
1572
1585
|
}
|
|
1573
1586
|
buffer += line;
|
|
1574
1587
|
}
|
|
1575
|
-
|
|
1588
|
+
const finalCursorRow = Math.max(0, newLines.length - 1);
|
|
1589
|
+
buffer = this.finishFrame(buffer, cursorPos, newLines.length, finalCursorRow);
|
|
1576
1590
|
this.terminal.write(buffer);
|
|
1577
1591
|
this.cursorRow = Math.max(0, newLines.length - 1);
|
|
1578
|
-
this.hardwareCursorRow = this.cursorRow;
|
|
1579
1592
|
// Reset max lines when clearing, otherwise track growth
|
|
1580
1593
|
if (clear) {
|
|
1581
1594
|
this.maxLinesRendered = newLines.length;
|
|
@@ -1585,7 +1598,6 @@ export class TuiBase extends Container {
|
|
|
1585
1598
|
}
|
|
1586
1599
|
const bufferLength = Math.max(height, newLines.length);
|
|
1587
1600
|
this.previousViewportTop = Math.max(0, bufferLength - height);
|
|
1588
|
-
this.positionHardwareCursor(cursorPos, newLines.length);
|
|
1589
1601
|
this.setPreviousLines(newLines, rawLines);
|
|
1590
1602
|
this.previousKittyImageIds = this.collectKittyImageIds(newLines);
|
|
1591
1603
|
this.previousWidth = width;
|
|
@@ -1718,12 +1730,13 @@ export class TuiBase extends Container {
|
|
|
1718
1730
|
if (moveBack > 0) {
|
|
1719
1731
|
buffer += `\x1b[${moveBack}A`;
|
|
1720
1732
|
}
|
|
1721
|
-
buffer
|
|
1733
|
+
buffer = this.finishFrame(buffer, cursorPos, newLines.length, targetRow);
|
|
1722
1734
|
this.terminal.write(buffer);
|
|
1723
1735
|
this.cursorRow = targetRow;
|
|
1724
|
-
this.hardwareCursorRow = targetRow;
|
|
1725
1736
|
}
|
|
1726
|
-
|
|
1737
|
+
else {
|
|
1738
|
+
this.positionHardwareCursor(cursorPos, newLines.length);
|
|
1739
|
+
}
|
|
1727
1740
|
this.setPreviousLines(newLines, rawLines);
|
|
1728
1741
|
this.previousKittyImageIds = this.collectKittyImageIds(newLines);
|
|
1729
1742
|
this.previousWidth = width;
|
|
@@ -1787,13 +1800,12 @@ export class TuiBase extends Container {
|
|
|
1787
1800
|
buffer += `\r\x1b[2K${TUI.SEGMENT_RESET}`;
|
|
1788
1801
|
buffer += newLines[viewportTop + row] ?? "";
|
|
1789
1802
|
}
|
|
1790
|
-
|
|
1803
|
+
const finalCursorRow = viewportTop + Math.max(0, height - 1);
|
|
1804
|
+
buffer = this.finishFrame(buffer, cursorPos, newLines.length, finalCursorRow);
|
|
1791
1805
|
this.terminal.write(buffer);
|
|
1792
1806
|
this.cursorRow = Math.max(0, newLines.length - 1);
|
|
1793
|
-
this.hardwareCursorRow = viewportTop + Math.max(0, height - 1);
|
|
1794
1807
|
this.maxLinesRendered = Math.max(this.maxLinesRendered, newLines.length);
|
|
1795
1808
|
this.previousViewportTop = viewportTop;
|
|
1796
|
-
this.positionHardwareCursor(cursorPos, newLines.length);
|
|
1797
1809
|
this.setPreviousLines(newLines, rawLines);
|
|
1798
1810
|
this.previousKittyImageIds = this.collectKittyImageIds(newLines);
|
|
1799
1811
|
this.previousWidth = width;
|
|
@@ -1908,7 +1920,7 @@ export class TuiBase extends Container {
|
|
|
1908
1920
|
// Move cursor back to end of new content
|
|
1909
1921
|
buffer += `\x1b[${extraLines}A`;
|
|
1910
1922
|
}
|
|
1911
|
-
buffer
|
|
1923
|
+
buffer = this.finishFrame(buffer, cursorPos, newLines.length, finalCursorRow);
|
|
1912
1924
|
if (process.env.PI_TUI_DEBUG === "1") {
|
|
1913
1925
|
const debugDir = "/tmp/tui";
|
|
1914
1926
|
fs.mkdirSync(debugDir, { recursive: true });
|
|
@@ -1944,12 +1956,9 @@ export class TuiBase extends Container {
|
|
|
1944
1956
|
// cursorRow tracks end of content (for viewport calculation)
|
|
1945
1957
|
// hardwareCursorRow tracks actual terminal cursor position (for movement)
|
|
1946
1958
|
this.cursorRow = Math.max(0, newLines.length - 1);
|
|
1947
|
-
this.hardwareCursorRow = finalCursorRow;
|
|
1948
1959
|
// Track terminal's working area (grows but doesn't shrink unless cleared)
|
|
1949
1960
|
this.maxLinesRendered = Math.max(this.maxLinesRendered, newLines.length);
|
|
1950
1961
|
this.previousViewportTop = Math.max(prevViewportTop, finalCursorRow - height + 1);
|
|
1951
|
-
// Position hardware cursor for IME
|
|
1952
|
-
this.positionHardwareCursor(cursorPos, newLines.length);
|
|
1953
1962
|
this.setPreviousLines(newLines, rawLines);
|
|
1954
1963
|
if (needsKittyImageExpansion) {
|
|
1955
1964
|
this.previousKittyImageIds = this.collectKittyImageIds(newLines);
|
|
@@ -1962,7 +1971,7 @@ export class TuiBase extends Container {
|
|
|
1962
1971
|
* @param cursorPos The cursor position extracted from rendered output, or null
|
|
1963
1972
|
* @param totalLines Total number of rendered lines
|
|
1964
1973
|
*/
|
|
1965
|
-
|
|
1974
|
+
buildHardwareCursorSequence(cursorPos, totalLines) {
|
|
1966
1975
|
let buffer = "";
|
|
1967
1976
|
if (!cursorPos || totalLines <= 0) {
|
|
1968
1977
|
if (this.#lastCursorVisibility !== false) {
|
|
@@ -1990,9 +1999,16 @@ export class TuiBase extends Container {
|
|
|
1990
1999
|
this.#lastCursorVisibility = this.showHardwareCursor;
|
|
1991
2000
|
}
|
|
1992
2001
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2002
|
+
return buffer;
|
|
2003
|
+
}
|
|
2004
|
+
finishFrame(buffer, cursorPos, totalLines, hardwareCursorRow) {
|
|
2005
|
+
this.hardwareCursorRow = hardwareCursorRow;
|
|
2006
|
+
return buffer + this.buildHardwareCursorSequence(cursorPos, totalLines) + TUI.FRAME_END;
|
|
2007
|
+
}
|
|
2008
|
+
positionHardwareCursor(cursorPos, totalLines) {
|
|
2009
|
+
const buffer = this.buildHardwareCursorSequence(cursorPos, totalLines);
|
|
2010
|
+
if (buffer)
|
|
2011
|
+
this.terminal.write(TUI.FRAME_BEGIN + buffer + TUI.FRAME_END);
|
|
1996
2012
|
}
|
|
1997
2013
|
/**
|
|
1998
2014
|
* Query the terminal's default background color with OSC 11 (`ESC ] 11 ; ? BEL`).
|