aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-14 20:58:48 +0200
committeruser <user@clank>2026-08-14 20:58:48 +0200
commit76d2032ff807d536114f46e1a183eeb62eacdc61 (patch)
treed88197d2d50ff48c470128e61fee6c44b72735f2 /tests
parentsl0ppty: find the crossing whichever way the tree is nested (diff)
downloadslosh-76d2032ff807d536114f46e1a183eeb62eacdc61.tar.gz
slosh-76d2032ff807d536114f46e1a183eeb62eacdc61.tar.xz
slosh-76d2032ff807d536114f46e1a183eeb62eacdc61.zip
sl0ppty: contrib themes, a way to look at them, and a handover
Six themes, each setting every colour the config knows about. A theme that has fallen behind silently keeps the compiled-in default for whatever it forgot, which looks like a bug in the theme rather than a missing line in it, so a test compares each file against the names config.c actually parses. contrib/theme-tour applies one to a running session, or cycles the lot. It does that by writing over the file the session was started with and letting the config watcher notice, which makes the showcase a demonstration of the watcher as well. HANDOVER.md is for the next context. It deliberately does not restate DESIGN.md or the README; it is the part that was only learnable by getting it wrong — which state is derived and which is intent and what happens when you confuse them, the dwell repaint list, that glyph width and glyph weight are different problems, that settle() in the harness is a sleep in disguise, and that a test pinned to a coordinate it does not care about will eventually look like a regression it is not.
Diffstat (limited to 'tests')
-rw-r--r--tests/test_themes.py59
1 files changed, 59 insertions, 0 deletions
diff --git a/tests/test_themes.py b/tests/test_themes.py
new file mode 100644
index 0000000..5e21bc7
--- /dev/null
+++ b/tests/test_themes.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+"""The themes in contrib/.
+
+Mostly a guard: a theme file that has fallen behind the config silently keeps
+the compiled-in default for whatever it forgot, which looks like a bug in the
+theme rather than a missing line in it.
+"""
+import glob
+import os
+import re
+import sys
+
+from harness import Session, check, report
+
+SH = ["/bin/sh", "-c", 'printf "\\033]2;p\\007"; stty raw -echo; cat']
+HERE = os.path.dirname(os.path.abspath(__file__))
+THEMES = sorted(glob.glob(os.path.join(HERE, "..", "contrib", "themes", "*.kdl")))
+
+
+def declared_in_config():
+ src = open(os.path.join(HERE, "..", "src", "config.c")).read()
+ return set(re.findall(r'\{"([a-z_]+)", &c->', src))
+
+
+def set_by(path):
+ return set(re.findall(r'^ ([a-z_]+) "', open(path).read(), re.M))
+
+
+def test_there_are_themes():
+ check("contrib ships some", len(THEMES) >= 3, str(THEMES))
+
+
+def test_each_sets_every_colour_the_config_knows():
+ want = declared_in_config()
+ for t in THEMES:
+ missing = want - set_by(t)
+ check(f"{os.path.basename(t)} sets all {len(want)} of them",
+ not missing, "missing: " + ", ".join(sorted(missing)))
+
+
+def test_each_one_parses_and_reaches_the_screen():
+ for t in THEMES:
+ declared = dict(re.findall(r'^ ([a-z_]+) "(#[0-9a-fA-F]{6})"',
+ open(t).read(), re.M))
+ with Session(SH, cols=50, rows=10, config=os.path.abspath(t)) as s:
+ s.settle(30)
+ snap, p = s.snapshot(), s.pane()
+ drawn = (snap.style_at(p["x"], p["y"] + 1) or {}).get("fg")
+ check(f"{os.path.basename(t)} draws its own frame colour",
+ drawn == declared["frame_focus"],
+ f"{drawn} != {declared['frame_focus']}")
+ check(f"{os.path.basename(t)} leaves the session alive", s.alive(), "")
+
+
+if __name__ == "__main__":
+ test_there_are_themes()
+ test_each_sets_every_colour_the_config_knows()
+ test_each_one_parses_and_reaches_the_screen()
+ sys.exit(report())