mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-22 00:05:51 +00:00
@@ -74,7 +74,6 @@ import {
|
|||||||
DISABLE_MODIFY_OTHER_KEYS,
|
DISABLE_MODIFY_OTHER_KEYS,
|
||||||
ENABLE_KITTY_KEYBOARD,
|
ENABLE_KITTY_KEYBOARD,
|
||||||
ENABLE_MODIFY_OTHER_KEYS,
|
ENABLE_MODIFY_OTHER_KEYS,
|
||||||
ERASE_DOWN,
|
|
||||||
ERASE_SCREEN,
|
ERASE_SCREEN,
|
||||||
} from './termio/csi.js';
|
} from './termio/csi.js';
|
||||||
import {
|
import {
|
||||||
@@ -107,17 +106,6 @@ const ERASE_THEN_HOME_PATCH = Object.freeze({
|
|||||||
type: 'stdout' as const,
|
type: 'stdout' as const,
|
||||||
content: ERASE_SCREEN + CURSOR_HOME,
|
content: ERASE_SCREEN + CURSOR_HOME,
|
||||||
});
|
});
|
||||||
// Main-screen self-healing: CURSOR_HOME then ERASE_DOWN (CSI J) clears the
|
|
||||||
// entire visible viewport from (0,0) without touching scrollback. ERASE_SCREEN
|
|
||||||
// (CSI 2 J) on xterm.js / VSCode integrated terminals can produce residual
|
|
||||||
// ghosting because its implementation interacts with the scrollback boundary;
|
|
||||||
// CSI J has deterministic "erase from cursor to end of screen" semantics that
|
|
||||||
// never push visible content into scrollback. Order matters: home first, then
|
|
||||||
// erase — so the erase covers the full viewport.
|
|
||||||
const HOME_THEN_ERASE_DOWN_PATCH = Object.freeze({
|
|
||||||
type: 'stdout' as const,
|
|
||||||
content: CURSOR_HOME + ERASE_DOWN,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Cached per-Ink-instance, invalidated on resize. frame.cursor.y for
|
// Cached per-Ink-instance, invalidated on resize. frame.cursor.y for
|
||||||
// alt-screen is always terminalRows - 1 (renderer.ts).
|
// alt-screen is always terminalRows - 1 (renderer.ts).
|
||||||
@@ -795,15 +783,10 @@ export default class Ink {
|
|||||||
} else if (this.needsEraseBeforePaint && hasDiff) {
|
} else if (this.needsEraseBeforePaint && hasDiff) {
|
||||||
// Main-screen periodic self-healing: clear visible terminal before
|
// Main-screen periodic self-healing: clear visible terminal before
|
||||||
// painting the diff. Without this, rows past the new frame's height
|
// painting the diff. Without this, rows past the new frame's height
|
||||||
// would retain stale content from the previous frame. Uses
|
// would retain stale content from the previous frame. BSU/ESU keeps
|
||||||
// HOME_THEN_ERASE_DOWN_PATCH (CSI H + CSI J) instead of ERASE_SCREEN
|
// old content visible until the full erase+paint is flushed atomically.
|
||||||
// (CSI 2 J): the latter's behavior on xterm.js / VSCode integrated
|
|
||||||
// terminals can leave residual ghosting of the prior frame (banner +
|
|
||||||
// status bar duplicated). CSI J erases from cursor (now at 0,0) to
|
|
||||||
// end of screen with deterministic semantics and does not touch
|
|
||||||
// scrollback, so the user's conversation history is preserved.
|
|
||||||
this.needsEraseBeforePaint = false;
|
this.needsEraseBeforePaint = false;
|
||||||
optimized.unshift(HOME_THEN_ERASE_DOWN_PATCH);
|
optimized.unshift(ERASE_THEN_HOME_PATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Native cursor positioning: park the terminal cursor at the declared
|
// Native cursor positioning: park the terminal cursor at the declared
|
||||||
|
|||||||
@@ -225,23 +225,27 @@ export class LogUpdate {
|
|||||||
cursorAtBottom &&
|
cursorAtBottom &&
|
||||||
!isGrowing
|
!isGrowing
|
||||||
) {
|
) {
|
||||||
// Frame persistently overflows the viewport. The cursor-restore LF at the
|
// viewportY = rows in scrollback from content overflow
|
||||||
// end of the previous frame scrolled content into scrollback, and the
|
// +1 for the row pushed by cursor-restore scroll
|
||||||
// terminal's auto-scroll on cursor movement causes our relative-cursor
|
const viewportY = prev.screen.height - prev.viewport.height
|
||||||
// tracking to drift — visible-region diffs then land on the wrong rows
|
const scrollbackRows = viewportY + 1
|
||||||
// and produce ghosting (duplicate banners, shifted content).
|
|
||||||
//
|
let scrollbackChangeY = -1
|
||||||
// Relative cursor ops can't repaint scrollback rows at all, and even
|
diffEach(prev.screen, next.screen, (_x, y) => {
|
||||||
// visible-region writes are unsafe because the cursor origin we computed
|
if (y < scrollbackRows) {
|
||||||
// doesn't match where the terminal thinks it is. Full-reset emits
|
scrollbackChangeY = y
|
||||||
// clearTerminal (CSI 2 J + CSI 3 J + CSI H), wiping scrollback residue
|
return true // early exit
|
||||||
// and cursor drift, then repaints the whole frame from (0,0).
|
}
|
||||||
//
|
})
|
||||||
// Previously this branch only fired when a diff existed in the scrollback
|
if (scrollbackChangeY >= 0) {
|
||||||
// region; visible-region-only changes still produced ghosting. Cost: an
|
const prevLine = readLine(prev.screen, scrollbackChangeY)
|
||||||
// extra clear+repaint per render while content overflows. Acceptable
|
const nextLine = readLine(next.screen, scrollbackChangeY)
|
||||||
// because overflow is the exception, not the steady state of a TUI.
|
return fullResetSequence_CAUSES_FLICKER(next, 'offscreen', stylePool, {
|
||||||
return fullResetSequence_CAUSES_FLICKER(next, 'offscreen', stylePool)
|
triggerY: scrollbackChangeY,
|
||||||
|
prevLine,
|
||||||
|
nextLine,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const screen = new VirtualScreen(prev.cursor, next.viewport.width)
|
const screen = new VirtualScreen(prev.cursor, next.viewport.width)
|
||||||
|
|||||||
@@ -227,12 +227,6 @@ export const ERASE_SCREEN = csi(2, 'J')
|
|||||||
/** Erase scrollback buffer (CSI 3 J) */
|
/** Erase scrollback buffer (CSI 3 J) */
|
||||||
export const ERASE_SCROLLBACK = csi(3, 'J')
|
export const ERASE_SCROLLBACK = csi(3, 'J')
|
||||||
|
|
||||||
/** Erase from cursor to end of screen (CSI J) — constant form.
|
|
||||||
* Unlike ERASE_SCREEN (CSI 2 J), this never pushes content into scrollback
|
|
||||||
* on xterm.js / VSCode integrated terminals, making it safe for periodic
|
|
||||||
* self-healing redraws in main-screen mode. */
|
|
||||||
export const ERASE_DOWN = csi('J')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erase n lines starting from cursor line, moving cursor up
|
* Erase n lines starting from cursor line, moving cursor up
|
||||||
* This erases each line and moves up, ending at column 1
|
* This erases each line and moves up, ending at column 1
|
||||||
|
|||||||
Reference in New Issue
Block a user