diff options
Diffstat (limited to 'src/config.zig')
| -rw-r--r-- | src/config.zig | 48 |
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)); |
