MCPcopy Create free account
hub / github.com/MoonshotAI/kimi-code / repaintViewport

Method repaintViewport

packages/pi-tui/src/tui.ts:1399–1468  ·  view source on GitHub ↗
(desiredTop: number, reason: string)

Source from the content-addressed store, hash-verified

1397 // otherwise nothing scrolls, so scrollback and the user's scroll
1398 // position stay intact.
1399 const repaintViewport = (desiredTop: number, reason: string): void => {
1400 // An advancing anchor must commit the rows it skips: paint from
1401 // the old anchor and let the paint loop scroll `advance` rows out
1402 // of the screen top. A pinned or rewound anchor paints the target
1403 // window in place without scrolling.
1404 const advance = Math.max(0, desiredTop - prevViewportTop);
1405 const paintStart = advance > 0 ? prevViewportTop : desiredTop;
1406 const paintCount = height + advance;
1407 // Kitty image lines need multi-row placement; fall back to a
1408 // destructive full render for that rare combination.
1409 for (let r = 0; r < paintCount; r++) {
1410 const idx = paintStart + r;
1411 if (idx < newLines.length && isImageLine(newLines[idx]!)) {
1412 logRedraw(`viewport repaint hit kitty image at line ${idx}`);
1413 fullRender(true);
1414 return;
1415 }
1416 }
1417 logRedraw(`viewport repaint: ${reason}`);
1418 let repaint = "\x1b[?2026h"; // Begin synchronized output
1419 // Delete kitty images placed in the old visible viewport; images
1420 // above it live in scrollback and are left alone. A multi-row
1421 // image can straddle the viewport top: its id lives on the image
1422 // line above prevViewportTop while its reserved rows are still
1423 // visible, so widen the range to include such blocks — otherwise
1424 // the stale overlay would survive the repaint and its id would
1425 // drop out of previousKittyImageIds, never to be cleaned up.
1426 let deleteFrom = prevViewportTop;
1427 for (let k = 0; k < prevViewportTop; k++) {
1428 const prevLine = this.previousLines[k] ?? "";
1429 if (!isImageLine(prevLine)) continue;
1430 const blockEnd = k + this.getKittyImageReservedRows(this.previousLines, k) - 1;
1431 if (blockEnd >= prevViewportTop) {
1432 deleteFrom = k;
1433 break;
1434 }
1435 }
1436 repaint += this.deleteChangedKittyImages(deleteFrom, this.previousLines.length - 1);
1437 // Move the cursor to the top of the screen (old anchor still valid).
1438 const cursorScreenRow = Math.max(0, Math.min(height - 1, hardwareCursorRow - prevViewportTop));
1439 if (cursorScreenRow > 0) {
1440 repaint += `\x1b[${cursorScreenRow}A`;
1441 }
1442 repaint += "\r";
1443 // Rewrite paintCount rows from paintStart. Rows written past the
1444 // bottom screen row scroll the terminal: with an advancing anchor
1445 // the first `advance` rows (freshly painted) scroll into
1446 // scrollback, committing them exactly once. With advance = 0 the
1447 // last row gets no trailing \r\n, so nothing scrolls.
1448 for (let r = 0; r < paintCount; r++) {
1449 if (r > 0) repaint += "\r\n";
1450 repaint += "\x1b[2K";
1451 const idx = paintStart + r;
1452 if (idx < newLines.length) {
1453 repaint += newLines[idx]!;
1454 }
1455 }
1456 repaint += "\x1b[?2026l"; // End synchronized output

Callers

nothing calls this directly

Calls 6

collectKittyImageIdsMethod · 0.95
isImageLineFunction · 0.90
writeMethod · 0.65

Tested by

no test coverage detected