fix: flickering eyebleed

This commit is contained in:
2025-05-20 10:53:37 -06:00
parent e5b173155a
commit 90f1547e02
3 changed files with 37 additions and 21 deletions

View File

@@ -111,6 +111,8 @@ export class TerminalBlock {
private renderHeight: number = 0;
private lastRenderRow = 1;
private lastRendered: string[] = [];
private preserveHistory = false;
constructor(private prepend: string = "") {}
@@ -193,27 +195,37 @@ export class TerminalBlock {
}
renderInternal(startRow?: number) {
this.lastRenderRow = startRow ?? this.lastRenderRow;
this.clear(); // uses old renderedLineCount
const outputLines: string[] = [];
const outputLines = this.renderLines.map((line) =>
`${this.prepend}${line}\x1b[K`
);
const output = outputLines.join("\n");
if (startRow !== undefined) {
const moveCursor = `\x1b[${startRow};1H`;
Deno.stdout.writeSync(new TextEncoder().encode(moveCursor + output));
} else {
Deno.stdout.writeSync(new TextEncoder().encode(output));
for (let i = 0; i < this.renderLines.length; i++) {
const line = `${this.prepend}${this.renderLines[i]}`;
const previous = this.lastRendered[i];
if (line !== previous) {
const moveToLine = `\x1b[${(startRow ?? this.lastRenderRow) + i};1H`;
outputLines.push(moveToLine + line + "\x1b[K");
}
}
// update rendered line count *after* rendering
this.renderedLineCount = outputLines.reduce(
(count, line) =>
count +
Math.ceil((line.length) / (Deno.consoleSize().columns || 80)),
0,
);
if (this.lastRendered.length > this.renderLines.length) {
const baseRow = startRow ?? this.lastRenderRow;
for (let i = this.renderLines.length; i < this.lastRendered.length; i++) {
const moveToLine = `\x1b[${baseRow + i};1H\x1b[2K`;
Deno.stdout.writeSync(new TextEncoder().encode(moveToLine));
}
}
const baseRow = startRow ?? this.lastRenderRow;
const excessLines = this.renderHeight - this.renderLines.length;
for (let i = 0; i < excessLines; i++) {
const moveToLine = `[${baseRow + this.renderLines.length + i};1H`;
Deno.stdout.writeSync(new TextEncoder().encode(moveToLine));
}
this.lastRendered = [...this.renderLines];
this.renderedLineCount = this.renderHeight;
this.lastRenderRow = baseRow;
const output = outputLines.join("\n");
Deno.stdout.writeSync(new TextEncoder().encode(output));
}
clear() {