summaryrefslogtreecommitdiff
path: root/src/config.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/config.zig')
-rw-r--r--src/config.zig103
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);