summaryrefslogtreecommitdiff
path: root/src/config.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/config.zig')
-rw-r--r--src/config.zig83
1 files changed, 53 insertions, 30 deletions
diff --git a/src/config.zig b/src/config.zig
index 8c37a7ce..f898df11 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -705,15 +705,6 @@ pub const Runtime = struct {
action: Action,
availability: ?Capability = null,
- pub fn takesArg(setting: Setting) bool {
- return switch (setting.action) {
- // 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, .message_ms, .dump_dir, .toggle => true,
- else => false,
- };
- }
-
pub fn enabled(setting: Setting, capabilities: Capabilities) bool {
const capability = setting.availability orelse return true;
return switch (capability) {
@@ -831,15 +822,7 @@ pub const Runtime = struct {
// 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;
+ const want = switchedTo(argument) catch return false;
switch (field) {
inline else => |f| @field(state, @tagName(f)) = want orelse !@field(state, @tagName(f)),
}
@@ -881,18 +864,42 @@ pub const Runtime = struct {
inline else => |w| @field(state, "message_" ++ @tagName(w) ++ "_ms") = ms,
}
},
- .transition => |effect| state.toggleTransition(effect),
- .scene => |effect| switch (effect) {
- inline else => |field| {
- const value = &@field(state.scene_effects, @tagName(field));
- value.* = !value.*;
- },
+ // Panel effects are one choice, so `on` picks this one and `off`
+ // turns it off only if it is the one on.
+ .transition => |effect| {
+ const want = switchedTo(argument) catch return false;
+ if (want == null) {
+ state.toggleTransition(effect);
+ } else if (want.?) {
+ state.panel_transition = effect;
+ } else if (state.panel_transition == effect) {
+ state.panel_transition = .off;
+ }
+ },
+ .scene => |effect| {
+ const want = switchedTo(argument) catch return false;
+ switch (effect) {
+ inline else => |field| {
+ const value = &@field(state.scene_effects, @tagName(field));
+ value.* = want orelse !value.*;
+ },
+ }
},
.theme, .font => return false,
}
return true;
}
+ /// What `on`, `off` or nothing after a switch word asks for: null flips
+ /// it, as a bare tagline word does.
+ fn switchedTo(argument: ?[]const u8) error{NotOnOrOff}!?bool {
+ const text = std.mem.trim(u8, argument orelse "", " \t\r\n");
+ if (text.len == 0) return null;
+ if (std.mem.eql(u8, text, "on")) return true;
+ if (std.mem.eql(u8, text, "off")) return false;
+ return error.NotOnOrOff;
+ }
+
// Slices are borrowed for one writeReport call.
pub const ReportContext = struct {
startup_config_path: ?[]const u8,
@@ -1055,15 +1062,32 @@ pub const Runtime = struct {
try out.print("Pet: {s}\n", .{@tagName(state.pet)});
}
- test "setting names are unique and argument metadata follows actions" {
+ test "setting names are unique" {
for (settings, 0..) |setting, i| {
try std.testing.expect(setting.word.len > 0);
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, .message_ms, .dump_dir, .toggle => true,
- else => false,
- }, setting.takesArg());
+ }
+ }
+
+ test "panel and scene effects flip bare and are set by on and off" {
+ var state: Runtime = .{};
+ const slide = findAction(.{ .transition = .slide }).?;
+ const zoom = findAction(.{ .transition = .zoom }).?;
+ try std.testing.expect(apply(&state, slide, "on"));
+ try std.testing.expectEqual(layout.Transition.slide, state.panel_transition);
+ try std.testing.expect(apply(&state, zoom, "off"));
+ try std.testing.expectEqual(layout.Transition.slide, state.panel_transition);
+ try std.testing.expect(apply(&state, slide, "on"));
+ try std.testing.expectEqual(layout.Transition.slide, state.panel_transition);
+ try std.testing.expect(apply(&state, slide, null));
+ try std.testing.expectEqual(layout.Transition.off, state.panel_transition);
+ try std.testing.expect(!apply(&state, slide, "yes"));
+ const scene = findAction(.{ .scene = std.enums.values(Scene)[0] }).?;
+ try std.testing.expect(apply(&state, scene, "on"));
+ try std.testing.expect(apply(&state, scene, "on"));
+ switch (std.enums.values(Scene)[0]) {
+ inline else => |f| try std.testing.expect(@field(state.scene_effects, @tagName(f))),
}
}
@@ -1125,7 +1149,6 @@ pub const Runtime = struct {
var state: Runtime = .{};
try std.testing.expectEqual(@as(u8, 100), state.window_opacity);
try std.testing.expect(state.window_opacity_pending);
- try std.testing.expect(setting.takesArg());
try std.testing.expectEqual(Capability.window_opacity, setting.availability.?);
for ([_][]const u8{ "0", " 85\n", "100" }, [_]u8{ 0, 85, 100 }) |argument, expected| {