diff options
Diffstat (limited to 'src/config.zig')
| -rw-r--r-- | src/config.zig | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/config.zig b/src/config.zig index 01a5daf8..24c48770 100644 --- a/src/config.zig +++ b/src/config.zig @@ -119,6 +119,10 @@ pub const leader_path = paths: { if (builtins.capabilities.window_opacity) table.set(.WindowOpacity, null); if (builtins.capabilities.window_blur) table.set(.WindowBlur, null); if (builtins.capabilities.ligatures) table.set(.Ligatures, null); + if (builtins.capabilities.lift) table.set(.Lift, null); + table.set(.Motion, null); + table.set(.InactiveDim, null); + if (builtins.capabilities.lift) table.set(.GripWidth, null); if (builtins.capabilities.panel_transitions) { table.set(.PanelSlide, "as"); table.set(.PanelZoom, "az"); @@ -621,6 +625,24 @@ pub const Runtime = struct { /// A font's programming ligatures (`->`, `!=`) draw across their cells. /// Only a shell that shapes text has the setting (`Capabilities.ligatures`). ligatures: bool = true, + /// How the focused pane and the notices stand off the page (G1, + /// docs/render-pipeline.md §9.1), or off. Opt-in until the focus lift's + /// default is decided. Only a pixel shell draws it (`Capabilities.lift`). + lift: LiftStyle = .off, + /// Blends the unfocused panes' text toward each cell's own ground, + /// percent (0 off): the focused pane wins by comparison, its tag tint + /// untouched. Kept above min(each cell's contrast, 4.5). + inactive_dim: u8 = 0, + /// The grip's button and the scrollbar under it, one width, as a percent + /// of the theme's `rail_px` (acme's 12px Scrollwid at a 17px tagline): + /// a pixel shell's (docs/themes.md). + grip_width: u16 = 150, + /// How the fx track's animations move (animation.Motion): off for + /// reduced motion. + /// Smooth by default, tuned so arrivals land inside §8.1's 220 ms; the + /// slower flavours are a choice. + motion: animation.Motion.Flavour = .smooth, + /// Builtins announce themselves on the message row. verbose: bool = true, /// A message falls into its row and dissolves out of it. @@ -678,6 +700,16 @@ pub const Runtime = struct { /// A setting that is one of a few words, each an enum field of Runtime. pub const Choice = enum { placement, boot_shell }; + /// shadow: a soft drop shadow. rim: a light hairline along the top of + /// the focused pane's tag rows. auto: a shadow on a light page; on a + /// dark one, where a shadow has nothing to darken, the other panes + /// recede instead (InactiveDim, at `auto_dim` unless it is set). + pub const LiftStyle = enum(u8) { off, shadow, rim, auto }; + /// What `Lift auto` dims the unfocused panes by on a dark page when + /// InactiveDim is 0: enough to read at a glance (the user's own init + /// sets 35), not so much that they stop being worth reading. + pub const auto_dim: u8 = 30; + /// Each pass the bundled Crt or a Shadertoy file. pub const Post = struct { pub const max = 8; @@ -822,6 +854,8 @@ pub const Runtime = struct { window_blur: bool = false, /// The shell shapes text, so it can draw ligatures and stop drawing them. ligatures: bool = false, + /// The shell draws soft shadows under what stands off the page. + lift: bool = false, }; pub const Capability = std.meta.FieldEnum(Capabilities); @@ -843,6 +877,13 @@ pub const Runtime = struct { window_blur, message_ms: MessageTime, dump_dir, + /// A lift style, `on` (auto) or `off`; bare flips auto and off. + lift, + /// A motion flavour. + motion, + /// A percentage, 0 through 100. + inactive_dim, + grip_width, transition: animation.Transition, scene: Scene, /// A Shadertoy file into the post chain or out of it; `off` empties @@ -877,6 +918,10 @@ pub const Runtime = struct { .{ .word = "Verbose", .action = .{ .toggle = .verbose } }, .{ .word = "MessageAnimation", .action = .{ .toggle = .message_animation } }, .{ .word = "Ligatures", .action = .{ .toggle = .ligatures }, .availability = .ligatures }, + .{ .word = "Lift", .action = .lift, .availability = .lift }, + .{ .word = "Motion", .action = .motion }, + .{ .word = "InactiveDim", .action = .inactive_dim }, + .{ .word = "GripWidth", .action = .grip_width, .availability = .lift }, .{ .word = "MessageLinger", .action = .{ .message_ms = .linger } }, .{ .word = "MessageFall", .action = .{ .message_ms = .fall } }, .{ .word = "MessageDissolve", .action = .{ .message_ms = .dissolve } }, @@ -940,6 +985,8 @@ pub const Runtime = struct { @compileError("scene effects must use the scene-shader capability"), // A toggle is plain state any shell can hold, except one for // what only some shells draw: that one exists where they do. + .lift, .grip_width => if (setting.availability != .lift) + @compileError("Lift and GripWidth must use the lift capability (a pixel shell's)"), .toggle => |field| if (field == .ligatures) { if (setting.availability != .ligatures) @compileError("the ligatures toggle must use the ligatures capability"); @@ -1073,6 +1120,31 @@ pub const Runtime = struct { std.meta.stringToEnum(T, text) orelse return false; }, }, + .lift => { + const text = std.mem.trim(u8, argument orelse "", " \t\r\n"); + state.lift = if (text.len == 0) + (if (state.lift == .off) .auto else .off) + else if (std.mem.eql(u8, text, "on")) + .auto + else + std.meta.stringToEnum(LiftStyle, text) orelse return false; + }, + .motion => { + const text = std.mem.trim(u8, argument orelse return false, " \t\r\n"); + state.motion = std.meta.stringToEnum(animation.Motion.Flavour, text) orelse return false; + }, + .inactive_dim => { + const text = std.mem.trim(u8, argument orelse return false, " \t\r\n%"); + const percent = std.fmt.parseInt(u8, text, 10) catch return false; + if (percent > 100) return false; + state.inactive_dim = percent; + }, + .grip_width => { + const text = std.mem.trim(u8, argument orelse return false, " \t\r\n%"); + const percent = std.fmt.parseInt(u16, text, 10) catch return false; + if (percent < 50 or percent > 300) return false; + state.grip_width = percent; + }, .theme, .font => return false, } return true; @@ -1245,6 +1317,13 @@ pub const Runtime = struct { .choice => |which| switch (which) { inline else => |field| try out.print("{s} {s}\n", .{ setting.word, @tagName(@field(state, @tagName(field))) }), }, + .lift => if (setting.enabled(context.capabilities)) + try out.print("{s} {s}\n", .{ setting.word, @tagName(state.lift) }) + else + try out.print("{s} unsupported\n", .{setting.word}), + .motion => try out.print("{s} {s}\n", .{ setting.word, @tagName(state.motion) }), + .inactive_dim => try out.print("{s} {d}\n", .{ setting.word, state.inactive_dim }), + .grip_width => try out.print("{s} {d}\n", .{ setting.word, state.grip_width }), }; if (context.startup_config_path) |path| @@ -1376,6 +1455,21 @@ pub const Runtime = struct { try std.testing.expectEqual(@as(u8, 0), state.post.level(.crt)); } + test "Lift takes a style, on is auto, and bare flips it off and back to auto" { + var state: Runtime = .{}; + const lift = find("Lift").?; + try std.testing.expect(apply(&state, lift, null)); + try std.testing.expectEqual(LiftStyle.auto, state.lift); + try std.testing.expect(apply(&state, lift, "rim")); + try std.testing.expectEqual(LiftStyle.rim, state.lift); + try std.testing.expect(apply(&state, lift, null)); + try std.testing.expectEqual(LiftStyle.off, state.lift); + try std.testing.expect(apply(&state, lift, "on")); + try std.testing.expectEqual(LiftStyle.auto, state.lift); + try std.testing.expect(!apply(&state, lift, "sparkle")); + try std.testing.expectEqual(LiftStyle.auto, state.lift); + } + test "tagline size validates before mutating live state" { const setting = find("TaglineSize").?; var state: Runtime = .{}; @@ -1478,6 +1572,7 @@ pub const Runtime = struct { .window_opacity = true, .window_blur = true, .ligatures = true, + .lift = true, }, .state = &state, }; @@ -1500,6 +1595,10 @@ pub const Runtime = struct { .placement => "pardes", .boot_shell => "replace", }, + .lift => "rim", + .motion => "playful", + .inactive_dim => "35", + .grip_width => "200", else => null, }; try std.testing.expect(apply(&state, setting, argument)); @@ -1553,6 +1652,10 @@ pub const Runtime = struct { .placement => "Placement pardes\n", .boot_shell => "BootShell replace\n", }, + .lift => "Lift rim\n", + .motion => "Motion playful\n", + .inactive_dim => "InactiveDim 35\n", + .grip_width => "GripWidth 200\n", .theme, .font => unreachable, }; try std.testing.expect(std.mem.indexOf(u8, report, expected) != null); |
