summaryrefslogtreecommitdiff
path: root/src/config.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/config.zig')
-rw-r--r--src/config.zig48
1 files changed, 43 insertions, 5 deletions
diff --git a/src/config.zig b/src/config.zig
index 81fefd2c..98bbf3f4 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -677,7 +677,9 @@ pub const Runtime = struct {
pub fn takesArg(setting: Setting) bool {
return switch (setting.action) {
- .shell, .theme, .font, .tagline_size, .window_opacity, .window_blur => true,
+ // A toggle flips when it is a bare tagline word and SETS when
+ // it is given `on` or `off`, so the report is configuration.
+ .shell, .theme, .font, .tagline_size, .window_opacity, .window_blur, .toggle => true,
else => false,
};
}
@@ -781,9 +783,23 @@ pub const Runtime = struct {
pub fn apply(state: *Runtime, setting: Setting, argument: ?[]const u8) bool {
switch (setting.action) {
// Every toggle names a bool field of its own, so one line covers
- // all of them and a new toggle needs no arm here.
- .toggle => |field| switch (field) {
- inline else => |f| @field(state, @tagName(f)) = !@field(state, @tagName(f)),
+ // all of them and a new toggle needs no arm here. Bare, a toggle
+ // flips -- that is what a tagline word is for. With `on` or `off`
+ // it SETS, so the report `writeReport` prints (`Verbose on`) can
+ // be fed straight back as configuration and mean what it says.
+ .toggle => |field| {
+ const text = std.mem.trim(u8, argument orelse "", " \t\r\n");
+ const want: ?bool = if (text.len == 0)
+ null
+ else if (std.mem.eql(u8, text, "on"))
+ true
+ else if (std.mem.eql(u8, text, "off"))
+ false
+ else
+ return false;
+ switch (field) {
+ inline else => |f| @field(state, @tagName(f)) = want orelse !@field(state, @tagName(f)),
+ }
},
.shell => {
const value = std.mem.trim(u8, argument orelse return false, " \t\r\n");
@@ -977,12 +993,34 @@ pub const Runtime = struct {
for (settings[i + 1 ..]) |later|
try std.testing.expect(!std.mem.eql(u8, setting.word, later.word));
try std.testing.expectEqual(switch (setting.action) {
- .shell, .theme, .font, .tagline_size, .window_opacity, .window_blur => true,
+ .shell, .theme, .font, .tagline_size, .window_opacity, .window_blur, .toggle => true,
else => false,
}, setting.takesArg());
}
}
+ test "a toggle flips when bare and sets when told on or off" {
+ var state: Runtime = .{};
+ const verbose = find("Verbose").?;
+ try std.testing.expect(state.verbose);
+ // Bare, it flips: that is what a tagline word does.
+ try std.testing.expect(apply(&state, verbose, null));
+ try std.testing.expect(!state.verbose);
+ // Told, it SETS -- twice over, so the second call proves it is not
+ // flipping past the value it was given.
+ try std.testing.expect(apply(&state, verbose, "on"));
+ try std.testing.expect(state.verbose);
+ try std.testing.expect(apply(&state, verbose, " on\n"));
+ try std.testing.expect(state.verbose);
+ try std.testing.expect(apply(&state, verbose, "off"));
+ try std.testing.expect(!state.verbose);
+ try std.testing.expect(apply(&state, verbose, "off"));
+ try std.testing.expect(!state.verbose);
+ // And anything else is refused rather than silently flipping.
+ try std.testing.expect(!apply(&state, verbose, "maybe"));
+ try std.testing.expect(!state.verbose);
+ }
+
test "simple setting application mutates only its plain field" {
var state: Runtime = .{};
try std.testing.expect(apply(&state, find("Colors").?, null));