diff options
| author | user <user@clank> | 2026-08-15 23:21:40 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-15 23:21:40 +0200 |
| commit | b9ae6cbcbce3816c2b2e8f760f082d3eaa3b5184 (patch) | |
| tree | 8dd1f16ac15edd16f51ba07e37c312ccb89f53f1 /tests/test_include.py | |
| parent | sl0ppty: watch what the config was built from, not just what it was called (diff) | |
| download | slosh-b9ae6cbcbce3816c2b2e8f760f082d3eaa3b5184.tar.gz slosh-b9ae6cbcbce3816c2b2e8f760f082d3eaa3b5184.tar.xz slosh-b9ae6cbcbce3816c2b2e8f760f082d3eaa3b5184.zip | |
sl0ppty: say what the config could not honour
A config that half-applied said nothing. An unknown shader, a binding
that does not parse, an include that is not there: the file loaded, that
line did not, and the session announced "config reloaded" as though
nothing had happened. Every one of those messages was already being
produced -- config_load has filled `err` on a successful load since it
was written -- and then dropped on the floor by every caller, because a
non-zero return meant "fine".
So the complaint from the last load is kept, and the front end says it
where it would have said "config reloaded". Once at startup too: a config
that loaded with a complaint still started the session, and the stderr
line goes where nobody attached can read it. The `reload` control verb
answers `{"ok":true,"warning":"..."}` -- ok, because the file did apply,
with the reason attached for a script that cares.
Two things fell out of writing the test for it.
An include's complaint was reported by nobody when the file in the middle
was fine. apply_includes only looked at the return value, so a theme that
loaded while *its* include was missing swallowed the message: the child
returned true, and true meant there was nothing to say. The complaint now
travels up whether or not the include itself loaded.
And a complaint now carries the name of the file it happened in, exactly
once -- added by the file that produced it, never by the files that
included it, because prefixing at every level builds a chain that
truncates before the part that matters. So:
t.kdl: unknown shader: bloom
keys.kdl: line 2: unknown action fly
b.kdl: includes nested too deep (a cycle?)
cannot open /home/you/.config/sl0ppty/themes/nope.kdl
which is enough to know which file to open, in a message that fits in a
toast.
Diffstat (limited to 'tests/test_include.py')
| -rwxr-xr-x | tests/test_include.py | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/tests/test_include.py b/tests/test_include.py index 42baa89..b2f5200 100755 --- a/tests/test_include.py +++ b/tests/test_include.py @@ -123,7 +123,8 @@ def test_anything_can_be_included_not_only_a_theme(): def test_a_missing_include_costs_a_line_and_no_more(): """Losing your keybindings over a mistyped theme name would be a worse - answer than a session that carries on without the theme (D9).""" + answer than a session that carries on without the theme (D9) -- but silence + would be its own kind of wrong, so it is a line and not nothing.""" root = tree({"config.kdl": 'include "themes/nope.kdl"\ngap 2\n'}) with Session(SH, cols=60, rows=14, config=root + "/config.kdl") as s: s.settle() @@ -131,6 +132,23 @@ def test_a_missing_include_costs_a_line_and_no_more(): check("and the rest of the file applied anyway", s.pane()["x"] == 4, str(s.pane())) + reply = s.api("reload") + check("the reload succeeds", reply.get("ok"), str(reply)) + check("...and says which line it could not honour", + "nope.kdl" in reply.get("warning", ""), str(reply)) + check("the session says it out loud too", + "nope.kdl" in s.snapshot().screen(), + repr(s.snapshot().screen()[-200:])) + + +def test_a_cycle_says_so(): + root = tree({"a.kdl": 'include "b.kdl"\n', "b.kdl": 'include "a.kdl"\n'}) + with Session(SH, cols=70, rows=14, config=root + "/a.kdl") as s: + s.settle() + reply = s.api("reload") + check("a cycle is reported rather than followed", + "too deep" in reply.get("warning", ""), str(reply)) + def test_a_cycle_stops_rather_than_spinning(): """A config that includes itself is a mistake, and the depth limit is what @@ -195,6 +213,7 @@ if __name__ == "__main__": test_a_leading_tilde_is_a_home_directory() test_anything_can_be_included_not_only_a_theme() test_a_missing_include_costs_a_line_and_no_more() + test_a_cycle_says_so() test_a_cycle_stops_rather_than_spinning() test_an_include_is_picked_up_by_a_reload() test_every_contrib_theme_can_be_included() |
