summaryrefslogtreecommitdiff
path: root/src/config.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 18:14:36 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commitf41d0209f65237568c9f7d527d5989ac8921b74c (patch)
treec313dc20fa0593ecff725de32d6ad191b01d82ac /src/config.zig
parentb4781b334a06d16aedb0b6a3d604cb249eb619de (diff)
downloadpardes-f41d0209f65237568c9f7d527d5989ac8921b74c.tar.gz
pardes-f41d0209f65237568c9f7d527d5989ac8921b74c.zip
Lift takes a style: shadow, surface, rim, glow or auto
The user wants Lift to read on dark themes, where a shadow has nothing to darken. `Lift shadow|surface|rim|glow|auto` (`on` is auto, bare flips auto and off): surface lightens the lifted part's ground about 5.5% (Material-dark), rim is a thin soft light off its top and left edges, glow a faint halo in the theme's accent (Chrome.accent, the focused box colour), auto a shadow on a light page and surface with half a rim on a dark one (by the page's luminance). Rim and glow are the soft kernel in a light colour (no pre-warp: coloured light is laid on as is, within §8.2's budget); each style is capped per theme so text keeps min(its contrast, 4.5) (tests: darkening and lightening over the native themes). The style travels in the palette (Chrome.lift_style, one byte on the wire). Config reports and ctl reads `Lift <style>`. Shared files touched: config.zig, builtins.zig, ninep/ctl.zig, detached/wire.zig (palette byte), gui.zig. Not touched: pardes.zig, Messages.zig, mouse.zig.
Diffstat (limited to 'src/config.zig')
-rw-r--r--src/config.zig59
1 files changed, 50 insertions, 9 deletions
diff --git a/src/config.zig b/src/config.zig
index 0ed8726a..f7e83e91 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -619,10 +619,11 @@ 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,
- /// The focused pane and the notices stand off the page on soft shadows
- /// (G1, docs/render-pipeline.md §9.1). Opt-in until the focus lift's
+ /// 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: bool = false,
+ lift: LiftStyle = .off,
+
/// Builtins announce themselves on the message row.
verbose: bool = true,
/// A message falls into its row and dissolves out of it.
@@ -669,6 +670,13 @@ pub const Runtime = struct {
pub const ShaderAnimation = enum { off, on, always };
+ /// shadow: a soft drop shadow. surface: the lifted pane's ground
+ /// lightens, as a raised surface does on a dark theme. rim: a soft light
+ /// along its top and left edges. glow: a faint halo in the theme's
+ /// accent. auto: shadow on a light page, surface and a faint rim on a
+ /// dark one.
+ pub const LiftStyle = enum(u8) { off, shadow, surface, rim, glow, auto };
+
/// Each pass the bundled Crt or a Shadertoy file.
pub const Post = struct {
pub const max = 8;
@@ -822,7 +830,7 @@ pub const Runtime = struct {
/// The message timings a setting word sets, each in milliseconds.
pub const MessageTime = enum { linger, fall, dissolve };
- pub const Toggle = enum { colors, wrap, tree_context_tag_style, tag_bottom, debug, focus_tint, column_tags, syntax_bold, verbose, message_animation, ligatures, lift };
+ pub const Toggle = enum { colors, wrap, tree_context_tag_style, tag_bottom, debug, focus_tint, column_tags, syntax_bold, verbose, message_animation, ligatures };
/// The bundled post pass, a Shadertoy file in shaders/post/.
pub const Scene = enum { crt };
@@ -836,6 +844,8 @@ pub const Runtime = struct {
window_blur,
message_ms: MessageTime,
dump_dir,
+ /// A lift style, `on` (auto) or `off`; bare flips auto and off.
+ lift,
transition: animation.Transition,
scene: Scene,
/// A Shadertoy file into the post chain or out of it; `off` empties
@@ -870,7 +880,7 @@ 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 = .{ .toggle = .lift }, .availability = .lift },
+ .{ .word = "Lift", .action = .lift, .availability = .lift },
.{ .word = "MessageLinger", .action = .{ .message_ms = .linger } },
.{ .word = "MessageFall", .action = .{ .message_ms = .fall } },
.{ .word = "MessageDissolve", .action = .{ .message_ms = .dissolve } },
@@ -932,9 +942,11 @@ 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.
- .toggle => |field| if (field == .ligatures or field == .lift) {
- if (setting.availability == null or !std.mem.eql(u8, @tagName(setting.availability.?), @tagName(field)))
- @compileError("a pixel shell's toggle must use its own capability: " ++ @tagName(field));
+ .lift => if (setting.availability != .lift)
+ @compileError("Lift must use the lift capability"),
+ .toggle => |field| if (field == .ligatures) {
+ if (setting.availability != .ligatures)
+ @compileError("the ligatures toggle must use the ligatures capability");
} else if (setting.availability != null)
@compileError("unconditional toggles cannot carry a backend capability"),
else => if (setting.availability != null)
@@ -1053,6 +1065,15 @@ pub const Runtime = struct {
const text = std.mem.trim(u8, argument orelse return false, " \t\r\n");
state.shader_animation = std.meta.stringToEnum(ShaderAnimation, 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;
+ },
.theme, .font => return false,
}
return true;
@@ -1222,6 +1243,10 @@ pub const Runtime = struct {
try out.print("{s} {s}\n", .{ setting.word, @tagName(state.shader_animation) })
else
try out.print("{s} unsupported\n", .{setting.word}),
+ .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}),
};
if (context.startup_config_path) |path|
@@ -1353,6 +1378,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 = .{};
@@ -1474,6 +1514,7 @@ pub const Runtime = struct {
.dump_dir => "~/dumps",
.shader => "~/crt.glsl",
.shader_animation => "always",
+ .lift => "glow",
else => null,
};
try std.testing.expect(apply(&state, setting, argument));
@@ -1494,7 +1535,6 @@ pub const Runtime = struct {
.verbose => "Verbose off\n",
.message_animation => "MessageAnimation off\n",
.ligatures => "Ligatures off\n",
- .lift => "Lift on\n",
},
.shell => "Shell requested (new panes) fish\n",
.tagline_size => "TaglineSize 73\n",
@@ -1525,6 +1565,7 @@ pub const Runtime = struct {
},
.shader => "Shader ~/crt.glsl\n",
.shader_animation => "ShaderAnimation always\n",
+ .lift => "Lift glow\n",
.theme, .font => unreachable,
};
try std.testing.expect(std.mem.indexOf(u8, report, expected) != null);