summaryrefslogtreecommitdiff
path: root/src/ninep
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 13:31:20 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit238e35e89d387f3c266b40f107e9419ea75d77bb (patch)
treed531d6aaa608c4e1f025969e4d4a1428efce3e70 /src/ninep
parent917e9a099f3a5048ac436aafcfabbf3d40d1c24f (diff)
downloadpardes-238e35e89d387f3c266b40f107e9419ea75d77bb.tar.gz
pardes-238e35e89d387f3c266b40f107e9419ea75d77bb.zip
Joincol with no column to the right and Theme with no such theme say so
Both did nothing without a word, from a click or a ctl write alike, and a script could not tell a no-op from success. Joincol in the rightmost column now fails 'Joincol: no column to the right'. A Theme name that is none says so and names the themes sharing its first letter, since all of them (ThemeSel lists them) are too many for a message or a refused write; a startup config line still fails quietly, as its other bad lines do. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep')
-rw-r--r--src/ninep/ctl.zig30
1 files changed, 28 insertions, 2 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 386fd9a9..1ba78457 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -213,7 +213,12 @@ fn checkBuiltin(p: *Pardes, req: Req, line: []const u8, scope: builtins.Scope) ?
const takes = switch (setting.action) {
.theme => for (pardes.themes) |t| {
if (std.mem.eql(u8, t.name, arg)) break true;
- } else false,
+ } else {
+ // `refuse` quotes the line after it, in what is left of 128.
+ var near: [40]u8 = undefined;
+ var why: [104]u8 = undefined;
+ return refuse(p, req, std.fmt.bufPrint(&why, "bad value in control message; like it: {s}; ThemeSel lists all", .{pardes.colors.themesNear(&near, arg)}) catch "bad value in control message", line);
+ },
.font => config.Runtime.FontSpec.parse(arg) != null,
else => probe: {
var probe = p.settings;
@@ -638,7 +643,9 @@ test "the root ctl reads the settings as a write takes them, and takes the sessi
try testing.expectEqualStrings("not a session control message \"Del\"", wr(p, root_ctl, "Del").reply.ename);
try testing.expectEqualStrings("unknown control message \"Nonsense 1\"", wr(p, root_ctl, "Nonsense 1").reply.ename);
try testing.expectEqualStrings("bad value in control message \"Verbose maybe\"", wr(p, root_ctl, "Verbose maybe").reply.ename);
- try testing.expectEqualStrings("bad value in control message \"Theme no-such-theme\"", wr(p, root_ctl, "Theme no-such-theme").reply.ename);
+ const no_theme = wr(p, root_ctl, "Theme no-such-theme").reply.ename;
+ try testing.expectStringStartsWith(no_theme, "bad value in control message; like it: n");
+ try testing.expect(std.mem.endsWith(u8, no_theme, "; ThemeSel lists all \"Theme no-such-theme\""));
try testing.expectEqualStrings("wrong #args in control message \"Newcol 2\"", wr(p, root_ctl, "Newcol 2").reply.ename);
try testing.expectEqualStrings("wrong #args in control message \"Theme\"", wr(p, root_ctl, "Theme").reply.ename);
// A bare required word fails the check, so the line before never runs.
@@ -951,3 +958,22 @@ test "an error's words give the errno a mount reads: EINVAL for what is malforme
for (other) |w| try testing.expect(std.ascii.findIgnoreCase(c.text, w) == null);
}
}
+
+test "Joincol with no column to the right and Theme with no such theme say so" {
+ const gpa = testing.allocator;
+ const p = try withFile(gpa, "x\n");
+ defer p.deinit();
+ const root_ctl = @intFromEnum(tree.TopFile.ctl);
+ const joined = wr(p, root_ctl, "Joincol\n");
+ try testing.expectEqual(tree.Status.err, joined.reply.status);
+ try testing.expectStringStartsWith(joined.reply.ename, "Joincol: no column to the right");
+ const themed = wr(p, root_ctl, "Theme drak\n");
+ try testing.expectEqual(E.INVAL, themed.errno());
+ try testing.expectStringStartsWith(themed.reply.ename, "bad value in control message; like it: ");
+ try testing.expect(std.mem.indexOf(u8, themed.reply.ename, " dark") != null or std.mem.indexOf(u8, themed.reply.ename, ": dark") != null);
+ try testing.expect(std.mem.endsWith(u8, themed.reply.ename, "\"Theme drak\""));
+ // A click on the word says it on the message row.
+ _ = wr(p, Node.of(serialOf(p), .exec), "Theme drak\n");
+ const pane = p.panes[p.active].?;
+ try testing.expect(std.mem.indexOf(u8, pane.msg[0..pane.msg_len], "no theme \"drak\"") != null);
+}