From d87088eff0a10b8c76e4f30a3b6899419a9ad63d Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 29 Mar 2026 15:34:31 +0200 Subject: [PATCH] Fix: Pending-Wrap-Kaskade in iTerm2 behoben MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit render() schrieb pro Nicht-Letzte-Zeile exakt self.cols Zeichen → Cursor landet in Pending-Wrap-Zustand. In iTerm2 löscht ein Cursor-Positionierungs- befehl (_go) diesen Zustand NICHT: das erste Zeichen der nächsten Zeile triggert den Wrap → Zeile r+1 landet auf r+2 usw. → Kaskade. Folgen: Zeilen ohne Überschreibung zeigen alte Zeichen (Fragmente oberhalb der Wasserlinie), Unterwasserinhalt verschiebt sich aus dem sichtbaren Bereich (nichts unter der Wasserlinie sichtbar). Fix: letztes Zeichen jeder Zeile grundsätzlich auslassen (col_limit = cols - 1, für alle Zeilen). Pending-Wrap tritt nie auf. Letzte Spalte bleibt leer, was für die Animation völlig akzeptabel ist. --- asciiquarium_ng.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/asciiquarium_ng.py b/asciiquarium_ng.py index cbd8a6b..86a3045 100755 --- a/asciiquarium_ng.py +++ b/asciiquarium_ng.py @@ -119,18 +119,22 @@ class Canvas: self._ck[row][col] = ck def render(self) -> str: - # \033[H homes the cursor; every cell is rewritten below so \033[2J is - # not needed and would push content into the scrollback on every frame. - # The very last cell (bottom-right corner) is intentionally skipped: - # writing to it would trigger auto-wrap and scroll the terminal. - last_row = self.rows - 1 - last_col = self.cols - 1 + # \033[H homes the cursor; every cell is rewritten so \033[2J is not + # needed (it would push content into the scrollback on every frame). + # + # The last column of EVERY row is intentionally skipped (not just the + # last row). Writing to the last column triggers "pending-wrap" state. + # In iTerm2, cursor-position commands (_go) do NOT clear pending-wrap, + # so the first character of the next row triggers a wrap, placing it one + # row too low. This cascades: row r+1 lands at r+2, row r+2 at r+3, … + # Content below the waterline shifts off-screen; skipped rows show stale + # characters. Staying one column short prevents pending-wrap entirely. + col_limit = self.cols - 1 parts = ["\033[H", RESET] sentinel = object() last_ck: object = sentinel for r in range(self.rows): parts.append(_go(r, 0)) - col_limit = last_col if r == last_row else self.cols for c in range(col_limit): ck = self._ck[r][c] if ck is not last_ck: