Theme switch repaints every cell: cells are diffed by role name, so F4 left old-theme speckles on spaces and unchanged glyphs; fix a loop-less live stream test that never fired its timers
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -97,7 +97,7 @@ def _fromisoformat(text):
|
||||
return parsed.replace(tzinfo=tzinfo)
|
||||
raise ValueError("invalid datetime, use ISO like 2026-10-08T09:00")
|
||||
|
||||
VERSION = "1.33.0"
|
||||
VERSION = "1.33.1"
|
||||
WORKER_STEPS = 12
|
||||
CREATE_SKILL_STEPS = 40
|
||||
FORK_MAX_DEPTH = 2
|
||||
@@ -13255,9 +13255,12 @@ class TuiApp:
|
||||
self._need_paint = True
|
||||
|
||||
def set_theme(self, name):
|
||||
"""Switch the global theme and redraw everything. Raises
|
||||
"""Switch the global theme and repaint every cell. Cells are diffed
|
||||
by style key (role names), which does not change with the theme, so
|
||||
the compositor must forget what the terminal shows. Raises
|
||||
ValueError naming the available themes when unknown."""
|
||||
tui_set_theme(name)
|
||||
self.compositor.invalidate()
|
||||
self.dirty_paint()
|
||||
return tui_theme()
|
||||
|
||||
|
||||
+18
@@ -5861,6 +5861,22 @@ class TuiThemeTests(unittest.TestCase):
|
||||
with self.assertRaises(ValueError):
|
||||
app.set_theme("nope")
|
||||
|
||||
def test_set_theme_repaints_every_cell_on_the_terminal(self):
|
||||
"""Regression: after a theme switch only cells whose text changed got the
|
||||
new colors, leaving old-theme speckles on spaces and unchanged glyphs."""
|
||||
def screen(theme, switch_to=None):
|
||||
tai.tui_set_theme(theme)
|
||||
app = tai.TuiApp()
|
||||
app.rows, app.cols = 10, 40
|
||||
app.mount(tai.TuiText("hello world and more words", style=tai.TuiStyle(fg="role:fg", bg="role:bubble_in")))
|
||||
vt = tai.TuiVtScreen(10, 40)
|
||||
vt.feed(app.frame_bytes().encode("utf-8"))
|
||||
if switch_to:
|
||||
app.set_theme(switch_to)
|
||||
vt.feed(app.frame_bytes().encode("utf-8"))
|
||||
return vt.grid
|
||||
self.assertEqual(screen("dark", "gruvbox"), screen("gruvbox"))
|
||||
|
||||
def test_cycle_order(self):
|
||||
self.assertEqual(tai.tui_cycle_theme_name("dark"), "light")
|
||||
self.assertEqual(tai.tui_cycle_theme_name("ansi"), "dark")
|
||||
@@ -6207,8 +6223,10 @@ class TuiChatTests(unittest.TestCase):
|
||||
app.offload(work, lambda value, error: done.append((value, error)))
|
||||
for _ in range(300):
|
||||
await asyncio.sleep(0.01)
|
||||
app._fire_timers(time.time())
|
||||
if done:
|
||||
await asyncio.sleep(0.2)
|
||||
app._fire_timers(time.time())
|
||||
break
|
||||
app.layout()
|
||||
self.shown = app.render_text()
|
||||
|
||||
@@ -242,8 +242,10 @@ render uncolored rather than crashing.
|
||||
|
||||
Selection precedence: `--theme` flag, `TAI_THEME` env var, `dark`
|
||||
default; an unknown name prints the available list and exits 2.
|
||||
`App.set_theme(name)` swaps the global theme and redraws everything;
|
||||
F4 cycles registry order in the chat scene. To change a color, edit
|
||||
`App.set_theme(name)` swaps the global theme and invalidates the compositor,
|
||||
because cells are diffed by style key (role names), which a theme switch does
|
||||
not change; without the invalidation only cells whose text changed got the
|
||||
new colors and old-theme speckles stayed on spaces. F4 cycles registry order in the chat scene. To change a color, edit
|
||||
one value in `_tui_builtin_themes()` or register a custom theme.
|
||||
|
||||
## Chat scene (`--tui`)
|
||||
|
||||
Reference in New Issue
Block a user