fix(tui): normalize tabs for terminal output (#6697)

This commit is contained in:
Xiangzhe
2026-07-16 15:17:05 +08:00
committed by GitHub
parent c6d8371521
commit 1c799cecd0
2 changed files with 84 additions and 4 deletions
+24 -3
View File
@@ -274,14 +274,35 @@ export function visibleWidth(str: string): number {
* Normalize text for terminal output without changing logical editor content.
* Some terminals render precomposed Thai/Lao AM vowels inconsistently during
* differential repaint. Their compatibility decompositions have the same cell
* width but avoid stale-cell artifacts in terminal renderers.
* width but avoid stale-cell artifacts in terminal renderers. Visible tabs are
* expanded to the fixed width used by layout so terminal tab stops cannot wrap
* a logical line, while tabs inside terminal string sequences stay untouched.
*/
const THAI_LAO_AM_REGEX = /[\u0e33\u0eb3]/;
const THAI_LAO_AM_GLOBAL_REGEX = /[\u0e33\u0eb3]/g;
export function normalizeTerminalOutput(str: string): string {
if (!THAI_LAO_AM_REGEX.test(str)) return str;
return str.replace(THAI_LAO_AM_GLOBAL_REGEX, (char) => (char === "\u0e33" ? "\u0e4d\u0e32" : "\u0ecd\u0eb2"));
let normalized = str;
if (THAI_LAO_AM_REGEX.test(normalized)) {
normalized = normalized.replace(THAI_LAO_AM_GLOBAL_REGEX, (char) =>
char === "\u0e33" ? "\u0e4d\u0e32" : "\u0ecd\u0eb2",
);
}
if (!normalized.includes("\t")) return normalized;
let result = "";
let i = 0;
while (i < normalized.length) {
const ansi = extractAnsiCode(normalized, i);
if (ansi) {
result += ansi.code;
i += ansi.length;
continue;
}
result += normalized[i] === "\t" ? " " : normalized[i];
i++;
}
return result;
}
/**