@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 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
@@ -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,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,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 { truncateToWidth, visibleWidth, wrapTextWithAnsi } from \"./utils.ts\";\n"]}
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":"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"}
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.clearOverlayFocusRestoreFor(overlay);
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.requestRender();
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.previousLines = [];
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 match = data.match(/^\x1b\[6;(\d+);(\d+)t$/);
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 <= 0 || widthPx <= 0) {
621
- return true;
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
- setCellDimensions({ widthPx, heightPx });
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 scrollback and viewport and render all new lines
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\x1b[3J"; // Clear screen, home, then clear scrollback
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)