@caupulican/pi-tui 0.86.2 → 0.86.5
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.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/tui.d.ts +24 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +190 -64
- package/dist/tui.js.map +1 -1
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +19 -2
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -19,5 +19,5 @@ export { StdinBuffer, type StdinBufferEventMap, type StdinBufferOptions } from "
|
|
|
19
19
|
export { ProcessTerminal, type Terminal } from "./terminal.ts";
|
|
20
20
|
export { allocateImageId, type CellDimensions, calculateImageRows, deleteAllKittyImages, deleteKittyImage, detectCapabilities, encodeITerm2, encodeKitty, getCapabilities, getCellDimensions, getGifDimensions, getImageDimensions, getJpegDimensions, getPngDimensions, getWebpDimensions, hyperlink, type ImageDimensions, type ImageProtocol, type ImageRenderOptions, imageFallback, renderImage, resetCapabilitiesCache, setCapabilities, setCellDimensions, type TerminalCapabilities, } from "./terminal-image.ts";
|
|
21
21
|
export { type Component, Container, CURSOR_MARKER, type Focusable, isFocusable, type OverlayAnchor, type OverlayHandle, type OverlayMargin, type OverlayOptions, type OverlayUnfocusOptions, type SizeValue, TUI, } from "./tui.ts";
|
|
22
|
-
export { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "./utils.ts";
|
|
22
|
+
export { getAmbiguousWidthMode, setAmbiguousWidthMode, truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "./utils.ts";
|
|
23
23
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -30,5 +30,5 @@ export { ProcessTerminal } from "./terminal.js";
|
|
|
30
30
|
export { allocateImageId, calculateImageRows, deleteAllKittyImages, deleteKittyImage, detectCapabilities, encodeITerm2, encodeKitty, getCapabilities, getCellDimensions, getGifDimensions, getImageDimensions, getJpegDimensions, getPngDimensions, getWebpDimensions, hyperlink, imageFallback, renderImage, resetCapabilitiesCache, setCapabilities, setCellDimensions, } from "./terminal-image.js";
|
|
31
31
|
export { Container, CURSOR_MARKER, isFocusable, TUI, } from "./tui.js";
|
|
32
32
|
// Utilities
|
|
33
|
-
export { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "./utils.js";
|
|
33
|
+
export { getAmbiguousWidthMode, setAmbiguousWidthMode, truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "./utils.js";
|
|
34
34
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAElC,uBAAuB;AACvB,OAAO,EAIN,4BAA4B,GAE5B,MAAM,mBAAmB,CAAC;AAC3B,aAAa;AACb,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAwC,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,KAAK,EAAsC,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,KAAK,EAAqB,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,MAAM,EAA+B,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAyB,QAAQ,EAA4C,MAAM,0BAA0B,CAAC;AACrH,OAAO,EAEN,UAAU,GAIV,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAoB,YAAY,EAA0B,MAAM,+BAA+B,CAAC;AACvG,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,kDAAkD;AAClD,OAAO,EAGN,2BAA2B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,iBAAiB;AACjB,OAAO,EAAmB,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtE,cAAc;AACd,OAAO,EACN,cAAc,EAOd,kBAAkB,EAClB,cAAc,EACd,eAAe,GACf,MAAM,kBAAkB,CAAC;AAC1B,0BAA0B;AAC1B,OAAO,EACN,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,GAAG,EAGH,UAAU,EACV,QAAQ,EACR,sBAAsB,GACtB,MAAM,WAAW,CAAC;AACnB,sCAAsC;AACtC,OAAO,EAAE,WAAW,EAAqD,MAAM,mBAAmB,CAAC;AACnG,yCAAyC;AACzC,OAAO,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAC/D,yBAAyB;AACzB,OAAO,EACN,eAAe,EAEf,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EAIT,aAAa,EACb,WAAW,EACX,sBAAsB,EACtB,eAAe,EACf,iBAAiB,GAEjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEN,SAAS,EACT,aAAa,EAEb,WAAW,EAOX,GAAG,GACH,MAAM,UAAU,CAAC;AAClB,YAAY;AACZ,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAElC,uBAAuB;AACvB,OAAO,EAIN,4BAA4B,GAE5B,MAAM,mBAAmB,CAAC;AAC3B,aAAa;AACb,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,MAAM,EAAwC,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,KAAK,EAAsC,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,KAAK,EAAqB,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,MAAM,EAA+B,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAyB,QAAQ,EAA4C,MAAM,0BAA0B,CAAC;AACrH,OAAO,EAEN,UAAU,GAIV,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAoB,YAAY,EAA0B,MAAM,+BAA+B,CAAC;AACvG,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,kDAAkD;AAClD,OAAO,EAGN,2BAA2B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,iBAAiB;AACjB,OAAO,EAAmB,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtE,cAAc;AACd,OAAO,EACN,cAAc,EAOd,kBAAkB,EAClB,cAAc,EACd,eAAe,GACf,MAAM,kBAAkB,CAAC;AAC1B,0BAA0B;AAC1B,OAAO,EACN,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,GAAG,EAGH,UAAU,EACV,QAAQ,EACR,sBAAsB,GACtB,MAAM,WAAW,CAAC;AACnB,sCAAsC;AACtC,OAAO,EAAE,WAAW,EAAqD,MAAM,mBAAmB,CAAC;AACnG,yCAAyC;AACzC,OAAO,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAC/D,yBAAyB;AACzB,OAAO,EACN,eAAe,EAEf,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EAIT,aAAa,EACb,WAAW,EACX,sBAAsB,EACtB,eAAe,EACf,iBAAiB,GAEjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEN,SAAS,EACT,aAAa,EAEb,WAAW,EAOX,GAAG,GACH,MAAM,UAAU,CAAC;AAClB,YAAY;AACZ,OAAO,EACN,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,gBAAgB,GAChB,MAAM,YAAY,CAAC","sourcesContent":["// Core TUI interfaces and classes\n\n// Autocomplete support\nexport {\n\ttype AutocompleteItem,\n\ttype AutocompleteProvider,\n\ttype AutocompleteSuggestions,\n\tCombinedAutocompleteProvider,\n\ttype SlashCommand,\n} from \"./autocomplete.ts\";\n// Components\nexport { Box } from \"./components/box.ts\";\nexport { CancellableLoader } from \"./components/cancellable-loader.ts\";\nexport { Editor, type EditorOptions, type EditorTheme } from \"./components/editor.ts\";\nexport { Image, type ImageOptions, type ImageTheme } from \"./components/image.ts\";\nexport { Input, type InputOptions } from \"./components/input.ts\";\nexport { Loader, type LoaderIndicatorOptions } from \"./components/loader.ts\";\nexport { type DefaultTextStyle, Markdown, type MarkdownOptions, type MarkdownTheme } from \"./components/markdown.ts\";\nexport {\n\ttype SelectItem,\n\tSelectList,\n\ttype SelectListLayoutOptions,\n\ttype SelectListTheme,\n\ttype SelectListTruncatePrimaryContext,\n} from \"./components/select-list.ts\";\nexport { type SettingItem, SettingsList, type SettingsListTheme } from \"./components/settings-list.ts\";\nexport { Spacer } from \"./components/spacer.ts\";\nexport { Text } from \"./components/text.ts\";\nexport { TruncatedText } from \"./components/truncated-text.ts\";\n// Editor component interface (for custom editors)\nexport {\n\ttype EditorChangeSummary,\n\ttype EditorComponent,\n\tfirstNonWhitespaceCharacter,\n} from \"./editor-component.ts\";\n// Fuzzy matching\nexport { type FuzzyMatch, fuzzyFilter, fuzzyMatch } from \"./fuzzy.ts\";\n// Keybindings\nexport {\n\tgetKeybindings,\n\ttype Keybinding,\n\ttype KeybindingConflict,\n\ttype KeybindingDefinition,\n\ttype KeybindingDefinitions,\n\ttype Keybindings,\n\ttype KeybindingsConfig,\n\tKeybindingsManager,\n\tsetKeybindings,\n\tTUI_KEYBINDINGS,\n} from \"./keybindings.ts\";\n// Keyboard input handling\nexport {\n\tdecodeKittyPrintable,\n\tisKeyRelease,\n\tisKeyRepeat,\n\tisKittyProtocolActive,\n\tKey,\n\ttype KeyEventType,\n\ttype KeyId,\n\tmatchesKey,\n\tparseKey,\n\tsetKittyProtocolActive,\n} from \"./keys.ts\";\n// Input buffering for batch splitting\nexport { StdinBuffer, type StdinBufferEventMap, type StdinBufferOptions } from \"./stdin-buffer.ts\";\n// Terminal interface and implementations\nexport { ProcessTerminal, type Terminal } from \"./terminal.ts\";\n// Terminal image support\nexport {\n\tallocateImageId,\n\ttype CellDimensions,\n\tcalculateImageRows,\n\tdeleteAllKittyImages,\n\tdeleteKittyImage,\n\tdetectCapabilities,\n\tencodeITerm2,\n\tencodeKitty,\n\tgetCapabilities,\n\tgetCellDimensions,\n\tgetGifDimensions,\n\tgetImageDimensions,\n\tgetJpegDimensions,\n\tgetPngDimensions,\n\tgetWebpDimensions,\n\thyperlink,\n\ttype ImageDimensions,\n\ttype ImageProtocol,\n\ttype ImageRenderOptions,\n\timageFallback,\n\trenderImage,\n\tresetCapabilitiesCache,\n\tsetCapabilities,\n\tsetCellDimensions,\n\ttype TerminalCapabilities,\n} from \"./terminal-image.ts\";\nexport {\n\ttype Component,\n\tContainer,\n\tCURSOR_MARKER,\n\ttype Focusable,\n\tisFocusable,\n\ttype OverlayAnchor,\n\ttype OverlayHandle,\n\ttype OverlayMargin,\n\ttype OverlayOptions,\n\ttype OverlayUnfocusOptions,\n\ttype SizeValue,\n\tTUI,\n} from \"./tui.ts\";\n// Utilities\nexport {\n\tgetAmbiguousWidthMode,\n\tsetAmbiguousWidthMode,\n\ttruncateToWidth,\n\tvisibleWidth,\n\twrapTextWithAnsi,\n} from \"./utils.ts\";\n"]}
|
package/dist/tui.d.ts
CHANGED
|
@@ -104,6 +104,8 @@ export interface OverlayOptions {
|
|
|
104
104
|
visible?: (termWidth: number, termHeight: number) => boolean;
|
|
105
105
|
/** If true, don't capture keyboard focus when shown */
|
|
106
106
|
nonCapturing?: boolean;
|
|
107
|
+
/** Called exactly once after hide() or hideOverlay() permanently removes the overlay; not for setHidden(). */
|
|
108
|
+
onRemove?: () => void;
|
|
107
109
|
}
|
|
108
110
|
/** Options for {@link OverlayHandle.unfocus}. */
|
|
109
111
|
export interface OverlayUnfocusOptions {
|
|
@@ -158,6 +160,13 @@ export declare class TUI extends Container {
|
|
|
158
160
|
private renderTimer;
|
|
159
161
|
private lastRenderAt;
|
|
160
162
|
private static readonly MIN_RENDER_INTERVAL_MS;
|
|
163
|
+
private static readonly TERMINAL_QUERY_RESPONSE_TIMEOUT_MS;
|
|
164
|
+
private cellSizeQueryTimer;
|
|
165
|
+
private cellSizeQueryPending;
|
|
166
|
+
private ambiguousWidthProbePending;
|
|
167
|
+
private ambiguousWidthProbeTimer;
|
|
168
|
+
private pendingFullRedrawClearMode;
|
|
169
|
+
private hasStarted;
|
|
161
170
|
private cursorRow;
|
|
162
171
|
private hardwareCursorRow;
|
|
163
172
|
private showHardwareCursor;
|
|
@@ -188,6 +197,7 @@ export declare class TUI extends Container {
|
|
|
188
197
|
private getVisibleOverlayFocusRestore;
|
|
189
198
|
private isOverlayFocusAncestor;
|
|
190
199
|
private retargetOverlayPreFocus;
|
|
200
|
+
private removeOverlay;
|
|
191
201
|
private isComponentMounted;
|
|
192
202
|
private containsComponent;
|
|
193
203
|
restoreFocus(component: Component | null): void;
|
|
@@ -209,8 +219,22 @@ export declare class TUI extends Container {
|
|
|
209
219
|
addInputListener(listener: InputListener): () => void;
|
|
210
220
|
removeInputListener(listener: InputListener): void;
|
|
211
221
|
private queryCellSize;
|
|
222
|
+
private clearCellSizeQuery;
|
|
223
|
+
/**
|
|
224
|
+
* Detect whether the terminal renders East Asian ambiguous characters (·, …, ●, ...) as
|
|
225
|
+
* two columns, as CJK-locale consoles do. Guessing from locale env vars is unreliable
|
|
226
|
+
* (Windows consoles expose none), so measure the terminal's actual behavior: print an
|
|
227
|
+
* ambiguous character at column 1, ask where the cursor ended up (DSR 6n), and erase the
|
|
228
|
+
* probe. The CPR response is consumed in handleInput; until it arrives the narrow default
|
|
229
|
+
* stays active and a positive answer triggers a full re-render with corrected widths.
|
|
230
|
+
*/
|
|
231
|
+
private queryAmbiguousWidth;
|
|
232
|
+
private clearAmbiguousWidthProbe;
|
|
233
|
+
private applyAmbiguousWidthMode;
|
|
234
|
+
private consumeAmbiguousWidthResponse;
|
|
212
235
|
stop(): void;
|
|
213
236
|
requestRender(force?: boolean): void;
|
|
237
|
+
private requestFullRender;
|
|
214
238
|
private scheduleRender;
|
|
215
239
|
private handleInput;
|
|
216
240
|
private consumeCellSizeResponse;
|
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;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"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"}
|
package/dist/tui.js
CHANGED
|
@@ -7,8 +7,10 @@ import * as path from "node:path";
|
|
|
7
7
|
import { performance } from "node:perf_hooks";
|
|
8
8
|
import { isKeyRelease, matchesKey } from "./keys.js";
|
|
9
9
|
import { deleteKittyImage, getCapabilities, isImageLine, setCellDimensions } from "./terminal-image.js";
|
|
10
|
-
import { extractSegments, normalizeTerminalOutput, sliceByColumn, sliceWithWidth, visibleWidth } from "./utils.js";
|
|
10
|
+
import { extractSegments, getAmbiguousWidthMode, normalizeTerminalOutput, setAmbiguousWidthMode, sliceByColumn, sliceWithWidth, visibleWidth, } from "./utils.js";
|
|
11
11
|
const KITTY_SEQUENCE_PREFIX = "\x1b_G";
|
|
12
|
+
const BRACKETED_PASTE_START = "\x1b[200~";
|
|
13
|
+
const BRACKETED_PASTE_END = "\x1b[201~";
|
|
12
14
|
function extractKittyImageIds(line) {
|
|
13
15
|
const sequenceStart = line.indexOf(KITTY_SEQUENCE_PREFIX);
|
|
14
16
|
if (sequenceStart === -1)
|
|
@@ -29,6 +31,30 @@ function extractKittyImageIds(line) {
|
|
|
29
31
|
}
|
|
30
32
|
return [];
|
|
31
33
|
}
|
|
34
|
+
function findBracketedPasteEnd(data, start) {
|
|
35
|
+
const endMarker = data.indexOf(BRACKETED_PASTE_END, start + BRACKETED_PASTE_START.length);
|
|
36
|
+
return endMarker === -1 ? data.length : endMarker + BRACKETED_PASTE_END.length;
|
|
37
|
+
}
|
|
38
|
+
/** Remove the first matching terminal response outside bracketed-paste payloads. */
|
|
39
|
+
function stripTerminalProtocolRange(data, pattern) {
|
|
40
|
+
const matcher = new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`);
|
|
41
|
+
let pasteStart = data.indexOf(BRACKETED_PASTE_START);
|
|
42
|
+
let pasteEnd = pasteStart === -1 ? -1 : findBracketedPasteEnd(data, pasteStart);
|
|
43
|
+
for (let match = matcher.exec(data); match; match = matcher.exec(data)) {
|
|
44
|
+
const start = match.index;
|
|
45
|
+
const end = start + match[0].length;
|
|
46
|
+
while (pasteStart !== -1 && pasteEnd <= start) {
|
|
47
|
+
pasteStart = data.indexOf(BRACKETED_PASTE_START, pasteEnd);
|
|
48
|
+
pasteEnd = pasteStart === -1 ? -1 : findBracketedPasteEnd(data, pasteStart);
|
|
49
|
+
}
|
|
50
|
+
if (pasteStart !== -1 && start < pasteEnd && end > pasteStart) {
|
|
51
|
+
matcher.lastIndex = Math.max(matcher.lastIndex, pasteEnd);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
return { data: data.slice(0, start) + data.slice(end), match };
|
|
55
|
+
}
|
|
56
|
+
return { data, match: undefined };
|
|
57
|
+
}
|
|
32
58
|
/** Type guard to check if a component implements Focusable */
|
|
33
59
|
export function isFocusable(component) {
|
|
34
60
|
return component !== null && "focused" in component;
|
|
@@ -132,6 +158,7 @@ export class Container {
|
|
|
132
158
|
*/
|
|
133
159
|
export class TUI extends Container {
|
|
134
160
|
static { this.MIN_RENDER_INTERVAL_MS = 16; }
|
|
161
|
+
static { this.TERMINAL_QUERY_RESPONSE_TIMEOUT_MS = 2000; }
|
|
135
162
|
constructor(terminal, showHardwareCursor) {
|
|
136
163
|
super();
|
|
137
164
|
this.previousLines = [];
|
|
@@ -142,6 +169,9 @@ export class TUI extends Container {
|
|
|
142
169
|
this.inputListeners = new Set();
|
|
143
170
|
this.renderRequested = false;
|
|
144
171
|
this.lastRenderAt = 0;
|
|
172
|
+
this.cellSizeQueryPending = false;
|
|
173
|
+
this.ambiguousWidthProbePending = false;
|
|
174
|
+
this.hasStarted = false;
|
|
145
175
|
this.cursorRow = 0; // Logical cursor row (end of rendered content)
|
|
146
176
|
this.hardwareCursorRow = 0; // Actual terminal cursor row (may differ due to IME positioning)
|
|
147
177
|
this.showHardwareCursor = process.env.PI_HARDWARE_CURSOR === "1";
|
|
@@ -285,6 +315,22 @@ export class TUI extends Container {
|
|
|
285
315
|
}
|
|
286
316
|
}
|
|
287
317
|
}
|
|
318
|
+
removeOverlay(entry) {
|
|
319
|
+
const index = this.overlayStack.indexOf(entry);
|
|
320
|
+
if (index === -1)
|
|
321
|
+
return;
|
|
322
|
+
this.clearOverlayFocusRestoreFor(entry);
|
|
323
|
+
this.retargetOverlayPreFocus(entry);
|
|
324
|
+
this.overlayStack.splice(index, 1);
|
|
325
|
+
if (this.focusedComponent === entry.component) {
|
|
326
|
+
const topVisible = this.getTopmostVisibleOverlay();
|
|
327
|
+
this.setFocus(topVisible?.component ?? entry.preFocus);
|
|
328
|
+
}
|
|
329
|
+
if (this.overlayStack.length === 0)
|
|
330
|
+
this.terminal.hideCursor();
|
|
331
|
+
this.requestRender();
|
|
332
|
+
entry.options?.onRemove?.();
|
|
333
|
+
}
|
|
288
334
|
isComponentMounted(component) {
|
|
289
335
|
return this.children.some((child) => this.containsComponent(child, component));
|
|
290
336
|
}
|
|
@@ -320,22 +366,7 @@ export class TUI extends Container {
|
|
|
320
366
|
this.requestRender();
|
|
321
367
|
// Return handle for controlling this overlay
|
|
322
368
|
return {
|
|
323
|
-
hide: () =>
|
|
324
|
-
const index = this.overlayStack.indexOf(entry);
|
|
325
|
-
if (index !== -1) {
|
|
326
|
-
this.clearOverlayFocusRestoreFor(entry);
|
|
327
|
-
this.retargetOverlayPreFocus(entry);
|
|
328
|
-
this.overlayStack.splice(index, 1);
|
|
329
|
-
// Restore focus if this overlay had focus
|
|
330
|
-
if (this.focusedComponent === component) {
|
|
331
|
-
const topVisible = this.getTopmostVisibleOverlay();
|
|
332
|
-
this.setFocus(topVisible?.component ?? entry.preFocus);
|
|
333
|
-
}
|
|
334
|
-
if (this.overlayStack.length === 0)
|
|
335
|
-
this.terminal.hideCursor();
|
|
336
|
-
this.requestRender();
|
|
337
|
-
}
|
|
338
|
-
},
|
|
369
|
+
hide: () => this.removeOverlay(entry),
|
|
339
370
|
setHidden: (hidden) => {
|
|
340
371
|
if (entry.hidden === hidden)
|
|
341
372
|
return;
|
|
@@ -405,17 +436,7 @@ export class TUI extends Container {
|
|
|
405
436
|
const overlay = this.overlayStack[this.overlayStack.length - 1];
|
|
406
437
|
if (!overlay)
|
|
407
438
|
return;
|
|
408
|
-
this.
|
|
409
|
-
this.retargetOverlayPreFocus(overlay);
|
|
410
|
-
this.overlayStack.pop();
|
|
411
|
-
if (this.focusedComponent === overlay.component) {
|
|
412
|
-
// Find topmost visible overlay, or fall back to preFocus
|
|
413
|
-
const topVisible = this.getTopmostVisibleOverlay();
|
|
414
|
-
this.setFocus(topVisible?.component ?? overlay.preFocus);
|
|
415
|
-
}
|
|
416
|
-
if (this.overlayStack.length === 0)
|
|
417
|
-
this.terminal.hideCursor();
|
|
418
|
-
this.requestRender();
|
|
439
|
+
this.removeOverlay(overlay);
|
|
419
440
|
}
|
|
420
441
|
/** Check if there are any visible overlays */
|
|
421
442
|
hasOverlay() {
|
|
@@ -448,11 +469,21 @@ export class TUI extends Container {
|
|
|
448
469
|
overlay.component.invalidate?.();
|
|
449
470
|
}
|
|
450
471
|
start() {
|
|
472
|
+
const restarting = this.hasStarted;
|
|
473
|
+
this.hasStarted = true;
|
|
451
474
|
this.stopped = false;
|
|
452
475
|
this.terminal.start((data) => this.handleInput(data), () => this.requestRender());
|
|
453
476
|
this.terminal.hideCursor();
|
|
477
|
+
if (restarting)
|
|
478
|
+
this.invalidate();
|
|
454
479
|
this.queryCellSize();
|
|
455
|
-
this.
|
|
480
|
+
this.queryAmbiguousWidth();
|
|
481
|
+
if (restarting) {
|
|
482
|
+
this.requestFullRender("viewport");
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
this.requestRender();
|
|
486
|
+
}
|
|
456
487
|
}
|
|
457
488
|
addInputListener(listener) {
|
|
458
489
|
this.inputListeners.add(listener);
|
|
@@ -464,16 +495,93 @@ export class TUI extends Container {
|
|
|
464
495
|
this.inputListeners.delete(listener);
|
|
465
496
|
}
|
|
466
497
|
queryCellSize() {
|
|
498
|
+
this.clearCellSizeQuery();
|
|
467
499
|
// Only query if terminal supports images (cell size is only used for image rendering)
|
|
468
500
|
if (!getCapabilities().images) {
|
|
469
501
|
return;
|
|
470
502
|
}
|
|
471
503
|
// Query terminal for cell size in pixels: CSI 16 t
|
|
472
504
|
// Response format: CSI 6 ; height ; width t
|
|
505
|
+
this.cellSizeQueryPending = true;
|
|
506
|
+
this.cellSizeQueryTimer = setTimeout(() => {
|
|
507
|
+
this.cellSizeQueryTimer = undefined;
|
|
508
|
+
this.cellSizeQueryPending = false;
|
|
509
|
+
}, TUI.TERMINAL_QUERY_RESPONSE_TIMEOUT_MS);
|
|
510
|
+
this.cellSizeQueryTimer.unref?.();
|
|
473
511
|
this.terminal.write("\x1b[16t");
|
|
474
512
|
}
|
|
513
|
+
clearCellSizeQuery() {
|
|
514
|
+
if (this.cellSizeQueryTimer) {
|
|
515
|
+
clearTimeout(this.cellSizeQueryTimer);
|
|
516
|
+
this.cellSizeQueryTimer = undefined;
|
|
517
|
+
}
|
|
518
|
+
this.cellSizeQueryPending = false;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Detect whether the terminal renders East Asian ambiguous characters (·, …, ●, ...) as
|
|
522
|
+
* two columns, as CJK-locale consoles do. Guessing from locale env vars is unreliable
|
|
523
|
+
* (Windows consoles expose none), so measure the terminal's actual behavior: print an
|
|
524
|
+
* ambiguous character at column 1, ask where the cursor ended up (DSR 6n), and erase the
|
|
525
|
+
* probe. The CPR response is consumed in handleInput; until it arrives the narrow default
|
|
526
|
+
* stays active and a positive answer triggers a full re-render with corrected widths.
|
|
527
|
+
*/
|
|
528
|
+
queryAmbiguousWidth() {
|
|
529
|
+
this.clearAmbiguousWidthProbe();
|
|
530
|
+
const override = process.env.PI_AMBIGUOUS_WIDTH;
|
|
531
|
+
if (override === "wide" || override === "narrow") {
|
|
532
|
+
this.applyAmbiguousWidthMode(override === "wide");
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
// CPR is byte-identical to modified-F3 input in some terminals, so this
|
|
536
|
+
// consumer must remain bounded to the startup query window.
|
|
537
|
+
this.ambiguousWidthProbePending = true;
|
|
538
|
+
this.ambiguousWidthProbeTimer = setTimeout(() => {
|
|
539
|
+
this.ambiguousWidthProbeTimer = undefined;
|
|
540
|
+
this.ambiguousWidthProbePending = false;
|
|
541
|
+
}, TUI.TERMINAL_QUERY_RESPONSE_TIMEOUT_MS);
|
|
542
|
+
this.ambiguousWidthProbeTimer.unref?.();
|
|
543
|
+
// CPR reports the column after the probe glyph: 2 = narrow, 3 = wide.
|
|
544
|
+
this.terminal.write("\r·\x1b[6n\r\x1b[2K");
|
|
545
|
+
}
|
|
546
|
+
clearAmbiguousWidthProbe() {
|
|
547
|
+
if (this.ambiguousWidthProbeTimer) {
|
|
548
|
+
clearTimeout(this.ambiguousWidthProbeTimer);
|
|
549
|
+
this.ambiguousWidthProbeTimer = undefined;
|
|
550
|
+
}
|
|
551
|
+
this.ambiguousWidthProbePending = false;
|
|
552
|
+
}
|
|
553
|
+
applyAmbiguousWidthMode(wide) {
|
|
554
|
+
if (wide === getAmbiguousWidthMode())
|
|
555
|
+
return;
|
|
556
|
+
setAmbiguousWidthMode(wide);
|
|
557
|
+
// Every cached width is now stale: rebuild components and repaint from a clean viewport.
|
|
558
|
+
this.invalidate();
|
|
559
|
+
if (this.previousWidth === 0 && this.previousHeight === 0) {
|
|
560
|
+
this.requestRender();
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
this.requestFullRender("viewport");
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
consumeAmbiguousWidthResponse(data) {
|
|
567
|
+
if (!this.ambiguousWidthProbePending)
|
|
568
|
+
return { data, consumed: false };
|
|
569
|
+
// Response format: ESC [ row ; col R (CPR)
|
|
570
|
+
const protocol = stripTerminalProtocolRange(data, /\x1b\[(\d+);(\d+)R/);
|
|
571
|
+
const { match } = protocol;
|
|
572
|
+
if (!match)
|
|
573
|
+
return { data, consumed: false };
|
|
574
|
+
this.clearAmbiguousWidthProbe();
|
|
575
|
+
const probeWidth = parseInt(match[2], 10) - 1;
|
|
576
|
+
this.applyAmbiguousWidthMode(probeWidth >= 2);
|
|
577
|
+
return { data: protocol.data, consumed: true };
|
|
578
|
+
}
|
|
475
579
|
stop() {
|
|
476
580
|
this.stopped = true;
|
|
581
|
+
this.clearCellSizeQuery();
|
|
582
|
+
this.clearAmbiguousWidthProbe();
|
|
583
|
+
this.renderRequested = false;
|
|
584
|
+
this.pendingFullRedrawClearMode = undefined;
|
|
477
585
|
if (this.renderTimer) {
|
|
478
586
|
clearTimeout(this.renderTimer);
|
|
479
587
|
this.renderTimer = undefined;
|
|
@@ -497,26 +605,7 @@ export class TUI extends Container {
|
|
|
497
605
|
}
|
|
498
606
|
requestRender(force = false) {
|
|
499
607
|
if (force) {
|
|
500
|
-
this.
|
|
501
|
-
this.previousWidth = -1; // -1 triggers widthChanged, forcing a full clear
|
|
502
|
-
this.previousHeight = -1; // -1 triggers heightChanged, forcing a full clear
|
|
503
|
-
this.cursorRow = 0;
|
|
504
|
-
this.hardwareCursorRow = 0;
|
|
505
|
-
this.maxLinesRendered = 0;
|
|
506
|
-
this.previousViewportTop = 0;
|
|
507
|
-
if (this.renderTimer) {
|
|
508
|
-
clearTimeout(this.renderTimer);
|
|
509
|
-
this.renderTimer = undefined;
|
|
510
|
-
}
|
|
511
|
-
this.renderRequested = true;
|
|
512
|
-
process.nextTick(() => {
|
|
513
|
-
if (this.stopped || !this.renderRequested) {
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
this.renderRequested = false;
|
|
517
|
-
this.lastRenderAt = performance.now();
|
|
518
|
-
this.doRender();
|
|
519
|
-
});
|
|
608
|
+
this.requestFullRender("saved-lines");
|
|
520
609
|
return;
|
|
521
610
|
}
|
|
522
611
|
if (this.renderRequested)
|
|
@@ -524,6 +613,32 @@ export class TUI extends Container {
|
|
|
524
613
|
this.renderRequested = true;
|
|
525
614
|
process.nextTick(() => this.scheduleRender());
|
|
526
615
|
}
|
|
616
|
+
requestFullRender(clearMode) {
|
|
617
|
+
// A public force redraw remains the strongest request if width detection races it.
|
|
618
|
+
if (this.pendingFullRedrawClearMode !== "saved-lines") {
|
|
619
|
+
this.pendingFullRedrawClearMode = clearMode;
|
|
620
|
+
}
|
|
621
|
+
this.previousLines = [];
|
|
622
|
+
this.previousWidth = -1; // -1 triggers widthChanged, forcing a full clear
|
|
623
|
+
this.previousHeight = -1; // -1 triggers heightChanged, forcing a full clear
|
|
624
|
+
this.cursorRow = 0;
|
|
625
|
+
this.hardwareCursorRow = 0;
|
|
626
|
+
this.maxLinesRendered = 0;
|
|
627
|
+
this.previousViewportTop = 0;
|
|
628
|
+
if (this.renderTimer) {
|
|
629
|
+
clearTimeout(this.renderTimer);
|
|
630
|
+
this.renderTimer = undefined;
|
|
631
|
+
}
|
|
632
|
+
this.renderRequested = true;
|
|
633
|
+
process.nextTick(() => {
|
|
634
|
+
if (this.stopped || !this.renderRequested) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
this.renderRequested = false;
|
|
638
|
+
this.lastRenderAt = performance.now();
|
|
639
|
+
this.doRender();
|
|
640
|
+
});
|
|
641
|
+
}
|
|
527
642
|
scheduleRender() {
|
|
528
643
|
if (this.stopped || this.renderTimer || !this.renderRequested) {
|
|
529
644
|
return;
|
|
@@ -544,6 +659,14 @@ export class TUI extends Container {
|
|
|
544
659
|
}, delay);
|
|
545
660
|
}
|
|
546
661
|
handleInput(data) {
|
|
662
|
+
// Terminal query responses are private protocol traffic. Remove them before
|
|
663
|
+
// public listeners while preserving any unrelated bytes batched alongside them.
|
|
664
|
+
const cellSizeInput = this.consumeCellSizeResponse(data);
|
|
665
|
+
const ambiguousWidthInput = this.consumeAmbiguousWidthResponse(cellSizeInput.data);
|
|
666
|
+
data = ambiguousWidthInput.data;
|
|
667
|
+
if ((cellSizeInput.consumed || ambiguousWidthInput.consumed) && data.length === 0) {
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
547
670
|
if (this.inputListeners.size > 0) {
|
|
548
671
|
let current = data;
|
|
549
672
|
for (const listener of this.inputListeners) {
|
|
@@ -560,10 +683,6 @@ export class TUI extends Container {
|
|
|
560
683
|
}
|
|
561
684
|
data = current;
|
|
562
685
|
}
|
|
563
|
-
// Consume terminal cell size responses without blocking unrelated input.
|
|
564
|
-
if (this.consumeCellSizeResponse(data)) {
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
686
|
// Global debug key handler (Shift+Ctrl+D)
|
|
568
687
|
if (matchesKey(data, "shift+ctrl+d") && this.onDebug) {
|
|
569
688
|
this.onDebug();
|
|
@@ -610,21 +729,24 @@ export class TUI extends Container {
|
|
|
610
729
|
}
|
|
611
730
|
}
|
|
612
731
|
consumeCellSizeResponse(data) {
|
|
732
|
+
if (!this.cellSizeQueryPending)
|
|
733
|
+
return { data, consumed: false };
|
|
613
734
|
// Response format: ESC [ 6 ; height ; width t
|
|
614
|
-
const
|
|
735
|
+
const protocol = stripTerminalProtocolRange(data, /\x1b\[6;(\d+);(\d+)t/);
|
|
736
|
+
const { match } = protocol;
|
|
615
737
|
if (!match) {
|
|
616
|
-
return false;
|
|
738
|
+
return { data, consumed: false };
|
|
617
739
|
}
|
|
740
|
+
this.clearCellSizeQuery();
|
|
618
741
|
const heightPx = parseInt(match[1], 10);
|
|
619
742
|
const widthPx = parseInt(match[2], 10);
|
|
620
|
-
if (heightPx
|
|
621
|
-
|
|
743
|
+
if (heightPx > 0 && widthPx > 0) {
|
|
744
|
+
setCellDimensions({ widthPx, heightPx });
|
|
745
|
+
// Invalidate all components so images re-render with correct dimensions.
|
|
746
|
+
this.invalidate();
|
|
747
|
+
this.requestRender();
|
|
622
748
|
}
|
|
623
|
-
|
|
624
|
-
// Invalidate all components so images re-render with correct dimensions.
|
|
625
|
-
this.invalidate();
|
|
626
|
-
this.requestRender();
|
|
627
|
-
return true;
|
|
749
|
+
return { data: protocol.data, consumed: true };
|
|
628
750
|
}
|
|
629
751
|
/**
|
|
630
752
|
* Resolve overlay layout from options.
|
|
@@ -934,6 +1056,8 @@ export class TUI extends Container {
|
|
|
934
1056
|
doRender() {
|
|
935
1057
|
if (this.stopped)
|
|
936
1058
|
return;
|
|
1059
|
+
const fullRedrawClearMode = this.pendingFullRedrawClearMode;
|
|
1060
|
+
this.pendingFullRedrawClearMode = undefined;
|
|
937
1061
|
const width = this.terminal.columns;
|
|
938
1062
|
const height = this.terminal.rows;
|
|
939
1063
|
const widthChanged = this.previousWidth !== 0 && this.previousWidth !== width;
|
|
@@ -958,13 +1082,15 @@ export class TUI extends Container {
|
|
|
958
1082
|
// mutates it in place - see findCursorMarker/applyLineResets.
|
|
959
1083
|
const cursorPos = this.findCursorMarker(newLines, height);
|
|
960
1084
|
newLines = this.applyLineResets(newLines, cursorPos);
|
|
961
|
-
// Helper to clear
|
|
1085
|
+
// Helper to clear the viewport (and optionally saved lines) and render all new lines
|
|
962
1086
|
const fullRender = (clear) => {
|
|
963
1087
|
this.fullRedrawCount += 1;
|
|
964
1088
|
let buffer = "\x1b[?2026h"; // Begin synchronized output
|
|
965
1089
|
if (clear) {
|
|
966
1090
|
buffer += this.deleteKittyImages(this.previousKittyImageIds);
|
|
967
|
-
buffer += "\x1b[2J\x1b[H
|
|
1091
|
+
buffer += "\x1b[2J\x1b[H"; // Clear screen and home.
|
|
1092
|
+
if (fullRedrawClearMode !== "viewport")
|
|
1093
|
+
buffer += "\x1b[3J"; // Clear saved lines unless preserving them.
|
|
968
1094
|
}
|
|
969
1095
|
for (let i = 0; i < newLines.length; i++) {
|
|
970
1096
|
if (i > 0)
|