summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-30 19:54:01 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit63983ab4b235fb2b6617e8d055e644e0e986d8fd (patch)
treea85df139318fa81500e9d1dd38a0b802f0a2f0db
parent872294ece905b8b5336e01ec3ce3f5420cd35b50 (diff)
downloadpardes-63983ab4b235fb2b6617e8d055e644e0e986d8fd.tar.gz
pardes-63983ab4b235fb2b6617e8d055e644e0e986d8fd.zip
Every setting's bad-value refusal names what it takes: InactiveDim 0-100, MessageLinger 0-60000 milliseconds, a path's limit, a font's form
A setting that chooses among words named them, but one that takes a number, a path or a font said only "bad value" over 9P and "does not take that value" from a tag, leaving the range to be guessed. The refusal, both ways, now says its range or what it takes, from one table beside the words. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--src/Messages.zig2
-rw-r--r--src/config.zig16
-rw-r--r--src/exec.zig9
-rw-r--r--src/ninep/ctl.zig9
4 files changed, 29 insertions, 7 deletions
diff --git a/src/Messages.zig b/src/Messages.zig
index 3eeb8c92..a316377a 100644
--- a/src/Messages.zig
+++ b/src/Messages.zig
@@ -876,7 +876,7 @@ test "a builtin announces itself on the message row, and Verbose silences it" {
// A value it does not take is said, in place of the announcement.
const wrapped = p.settings.wrap;
try std.testing.expect(p.executeBuiltinLine(p.active, "Wrap maybe"));
- try std.testing.expectEqualStrings("Wrap: takes on or off", pane.msg[0..pane.msg_len]);
+ try std.testing.expectEqualStrings("Wrap: takes on, off", pane.msg[0..pane.msg_len]);
try std.testing.expectEqual(wrapped, p.settings.wrap);
// The notice list is what the paint pass reads, so the announcement has to
diff --git a/src/config.zig b/src/config.zig
index a7377cfa..a17e2fd2 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -1242,6 +1242,22 @@ pub const Runtime = struct {
};
}
+ /// What a setting takes, for a refusal of a bad value to name: its
+ /// words (`choices`), else its range or the kind of thing it takes.
+ pub fn takes(action: Action) ?[]const u8 {
+ return choices(action) orelse switch (action) {
+ .inactive_dim, .window_opacity, .window_blur => "0-100 (a percentage)",
+ .grip_width => "50-300 (a percentage)",
+ .tagline_size => std.fmt.comptimePrint("{d}-{d} (a percentage)", .{ tagline_percent_min, tagline_percent_max }),
+ .message_ms => std.fmt.comptimePrint("0-{d} (milliseconds)", .{message_ms_max}),
+ .shell => "a path of at most 255 bytes; bare, the login shell",
+ .dump_dir => std.fmt.comptimePrint("a path of at most {d} bytes; bare, the default", .{limits.host_path_cap}),
+ .shader => "a Shadertoy file's path, or off",
+ .font => "a name or path, :8 to :72 after it (Mono:14)",
+ else => null,
+ };
+ }
+
/// The value a choice word names, or bare, the one after `now`; null for
/// a word it does not take.
fn stepped(comptime T: type, now: T, argument: ?[]const u8) ?T {
diff --git a/src/exec.zig b/src/exec.zig
index 215a4fd1..c673aab2 100644
--- a/src/exec.zig
+++ b/src/exec.zig
@@ -1015,12 +1015,13 @@ pub fn applySettingBuiltin(p: *Pardes, setting: config.Runtime.Setting, arg: ?[]
return p.reportFailure(p.active, std.fmt.bufPrint(&text, "Shell: {s}", .{refused}) catch "Shell: no such shell");
}
}
- if (!p.settings.apply(setting, want) and p.announce) p.reportFailure(p.active, "Shell: does not take that value");
+ if (!p.settings.apply(setting, want) and p.announce) p.reportFailure(p.active, "Shell: takes " ++ comptime config.Runtime.takes(.shell).?);
},
+ // Said with what it takes: its words, its range.
else => if (!p.settings.apply(setting, arg) and p.announce) {
- var text: [96]u8 = undefined;
- const takes = if (setting.action == .toggle) "takes on or off" else "does not take that value";
- p.reportFailure(p.active, std.fmt.bufPrint(&text, "{s}: {s}", .{ setting.word, takes }) catch takes);
+ var text: [160]u8 = undefined;
+ const why = if (config.Runtime.takes(setting.action)) |values| std.fmt.bufPrint(&text, "{s}: takes {s}", .{ setting.word, values }) else std.fmt.bufPrint(&text, "{s}: does not take that value", .{setting.word});
+ p.reportFailure(p.active, why catch "does not take that value");
},
}
if (p.settings.colors != previous_colors) {
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 27361124..2cd865de 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -491,8 +491,8 @@ fn checkBuiltin(p: *Pardes, req: Req, line: []const u8, scope: builtins.Scope) ?
},
};
if (takes) return null;
- var why: [104]u8 = undefined;
- return refuse(p, req, if (config.Runtime.choices(setting.action)) |values|
+ var why: [160]u8 = undefined;
+ return refuse(p, req, if (config.Runtime.takes(setting.action)) |values|
std.fmt.bufPrint(&why, "bad value in control message; takes {s}", .{values}) catch "bad value in control message"
else
"bad value in control message", line);
@@ -1256,6 +1256,11 @@ test "the root ctl reads the settings as a write takes them, and takes the sessi
try testing.expectEqualStrings("unknown control message \"Nonsense 1\"", wr(p, root_ctl, "Nonsense 1").reply.ename);
try testing.expectEqualStrings("bad value in control message; takes on, off \"Verbose maybe\"", wr(p, root_ctl, "Verbose maybe").reply.ename);
try testing.expectEqualStrings("bad value in control message; takes acme, pardes \"Placement east\"", wr(p, root_ctl, "Placement east").reply.ename);
+ // A number's refusal names its range, a path's what it takes.
+ try testing.expectEqualStrings("bad value in control message; takes 0-100 (a percentage) \"InactiveDim 200\"", wr(p, root_ctl, "InactiveDim 200").reply.ename);
+ try testing.expectEqualStrings("bad value in control message; takes 0-60000 (milliseconds) \"MessageLinger x\"", wr(p, root_ctl, "MessageLinger x").reply.ename);
+ for (config.Runtime.settings) |setting| if (setting.action != .theme)
+ try testing.expect(config.Runtime.takes(setting.action) != null);
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, "; Themes lists all \"Theme no-such-theme\""));