@sayknow-cli/tui 0.3.15 → 0.3.16
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/package.json +3 -3
- package/src/tui.ts +26 -8
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@sayknow-cli/tui",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.16",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://sayknow-cli.com",
|
|
7
7
|
"author": "jaybeyond",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"fmt": "biome format --write ."
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@sayknow-cli/natives": "0.3.
|
|
42
|
-
"@sayknow-cli/utils": "0.3.
|
|
41
|
+
"@sayknow-cli/natives": "0.3.16",
|
|
42
|
+
"@sayknow-cli/utils": "0.3.16",
|
|
43
43
|
"lru-cache": "11.3.6",
|
|
44
44
|
"marked": "^18.0.3"
|
|
45
45
|
},
|
package/src/tui.ts
CHANGED
|
@@ -2182,16 +2182,25 @@ export class TUI extends Container {
|
|
|
2182
2182
|
this.#previousHeight = height;
|
|
2183
2183
|
};
|
|
2184
2184
|
|
|
2185
|
-
const viewportRepaint = (reason: string): void => {
|
|
2185
|
+
const viewportRepaint = (reason: string, absoluteClear = false): void => {
|
|
2186
2186
|
this.#fullRedrawCount += 1;
|
|
2187
2187
|
if (renderMetrics.enabled) renderMetrics.recordFullRedraw(reason);
|
|
2188
2188
|
const nextViewportTop = Math.max(0, newLines.length - height);
|
|
2189
|
-
const currentScreenRow = Math.max(0, Math.min(height - 1, hardwareCursorRow - prevViewportTop));
|
|
2190
2189
|
let buffer = "\x1b[?2026h";
|
|
2191
|
-
if (
|
|
2192
|
-
|
|
2190
|
+
if (absoluteClear) {
|
|
2191
|
+
// A width reflow under a terminal multiplexer re-wraps the on-screen rows to
|
|
2192
|
+
// the new width before SIGWINCH fires, so cursor-relative row math (from the
|
|
2193
|
+
// old width) lands on the wrong physical row and corrupts the repaint. Clear
|
|
2194
|
+
// the visible screen and repaint from absolute home; skip 3J so scrollback
|
|
2195
|
+
// history is preserved.
|
|
2196
|
+
buffer += "\x1b[2J\x1b[H";
|
|
2197
|
+
} else {
|
|
2198
|
+
const currentScreenRow = Math.max(0, Math.min(height - 1, hardwareCursorRow - prevViewportTop));
|
|
2199
|
+
if (currentScreenRow > 0) {
|
|
2200
|
+
buffer += `\x1b[${currentScreenRow}A`;
|
|
2201
|
+
}
|
|
2202
|
+
buffer += "\r";
|
|
2193
2203
|
}
|
|
2194
|
-
buffer += "\r";
|
|
2195
2204
|
for (let screenRow = 0; screenRow < height; screenRow++) {
|
|
2196
2205
|
if (screenRow > 0) buffer += "\r\n";
|
|
2197
2206
|
buffer += "\x1b[2K";
|
|
@@ -2253,13 +2262,22 @@ export class TUI extends Container {
|
|
|
2253
2262
|
|
|
2254
2263
|
// Width changes always need a full re-render because wrapping changes.
|
|
2255
2264
|
if (widthChanged) {
|
|
2265
|
+
// A forced render (requestRender(true)) resets #previousWidth to -1: that is a
|
|
2266
|
+
// *fake* width change (the terminal never reflowed), so it keeps the cheap
|
|
2267
|
+
// cursor-relative repaint. A *real* width change (a valid prior width that
|
|
2268
|
+
// differs) means the multiplexer already re-wrapped the on-screen rows,
|
|
2269
|
+
// invalidating cursor-relative row math, so it needs the absolute clear.
|
|
2270
|
+
const realWidthChange = this.#previousWidth > 0 && this.#previousWidth !== width;
|
|
2256
2271
|
logRedraw(`terminal width changed (${this.#previousWidth} -> ${width})`);
|
|
2257
2272
|
if (useViewportRepaintPath(this.terminal)) {
|
|
2258
2273
|
// In viewport-repaint sessions a full replay can either pile the transcript
|
|
2259
2274
|
// back onto scrollback (tmux/screen) or visibly jump to the transcript top
|
|
2260
|
-
// (Windows Terminal).
|
|
2261
|
-
//
|
|
2262
|
-
|
|
2275
|
+
// (Windows Terminal). For a real width change the reflow invalidates
|
|
2276
|
+
// cursor-relative math, so clear the visible screen and repaint the viewport
|
|
2277
|
+
// from absolute home (absoluteClear) — fixing the corruption without replaying
|
|
2278
|
+
// the whole transcript (no scrollback storm). A fake (force) width change
|
|
2279
|
+
// keeps the in-place relative repaint.
|
|
2280
|
+
viewportRepaint(`terminal width changed (${this.#previousWidth} -> ${width})`, realWidthChange);
|
|
2263
2281
|
} else {
|
|
2264
2282
|
fullRender(true, "terminal width changed");
|
|
2265
2283
|
}
|