Fix: WRAP_OFF durch Last-Cell-Skip ersetzen

WRAP_OFF (ESC[?7l) verhinderte Scrollback, blockierte aber in iTerm2
die Darstellung der unteren Bildschirmhälfte.

Stattdessen: die allerletzte Zelle (Zeile rows-1, Spalte cols-1)
wird nicht beschrieben – ncurses-Standardansatz. Kein Auto-Wrap,
kein Scrollback, keine Darstellungsprobleme.
This commit is contained in:
rene 2026-03-29 11:28:14 +02:00
parent 860fb7b3dd
commit 177e66c626

View file

@ -27,8 +27,6 @@ HIDE_CUR = "\033[?25l"
SHOW_CUR = "\033[?25h"
ALT_ON = "\033[?1049h"
ALT_OFF = "\033[?1049l"
WRAP_OFF = "\033[?7l" # disable auto-wrap (prevents scrollback on last-col write)
WRAP_ON = "\033[?7h" # re-enable auto-wrap
def _fg(r, g, b): return f"\033[38;2;{r};{g};{b}m"
def _go(row, col): return f"\033[{row+1};{col+1}H"
@ -123,12 +121,17 @@ class Canvas:
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
parts = ["\033[H", RESET]
sentinel = object()
last_ck: object = sentinel
for r in range(self.rows):
parts.append(_go(r, 0))
for c in range(self.cols):
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:
parts.append(RESET if ck is None else _esc(ck))
@ -1565,7 +1568,7 @@ def main():
signal.signal(signal.SIGWINCH, on_resize)
fd = sys.stdout.fileno()
os.write(fd, (ALT_ON + HIDE_CUR + WRAP_OFF + "\033[2J\033[H").encode())
os.write(fd, (ALT_ON + HIDE_CUR + "\033[2J\033[H").encode())
try:
TICK = 0.1 / cfg.speed
@ -1603,7 +1606,7 @@ def main():
pass
finally:
inp.restore()
os.write(fd, (SHOW_CUR + WRAP_ON + ALT_OFF + RESET).encode())
os.write(fd, (SHOW_CUR + ALT_OFF + RESET).encode())
if __name__ == '__main__':