diff options
Diffstat (limited to 'src/config.zig')
| -rw-r--r-- | src/config.zig | 148 |
1 files changed, 143 insertions, 5 deletions
diff --git a/src/config.zig b/src/config.zig index 2eaaa505..24c48770 100644 --- a/src/config.zig +++ b/src/config.zig @@ -73,11 +73,12 @@ pub const leader_path = paths: { .Newcol = "cn", .Delcol = "cd", .Joincol = "cj", + .Placement = "cp", + .BootShell = null, .Debug = "td", .Msg = null, .Colors = "tc", .FocusTint = null, - .ColumnTags = null, .SyntaxBold = null, .Verbose = null, .TreeContextTagStyle = null, @@ -118,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"); @@ -616,11 +621,28 @@ pub const Runtime = struct { /// menu bar) turn it off and carry its commands there instead; the core /// keeps the row as the acme tradition everywhere else. workspace_tag: bool = true, - column_tags: bool = true, syntax_bold: bool = false, /// 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. @@ -664,8 +686,29 @@ pub const Runtime = struct { /// never, while the window has the focus, or always (ghostty's /// custom-shader-animation). shader_animation: ShaderAnimation = .on, + /// Where a new pane goes (exec.placeNew): `acme`, acme's makenewwindow, + /// or `pardes`, the rules pardes had before it. + placement: Placement = .acme, + /// A document dragged into the left column where a lone shell nobody + /// has typed into stands: `keep` leaves the shell, `replace` closes it + /// (exec.evictLonePristineTty). + boot_shell: BootShell = .keep, pub const ShaderAnimation = enum { off, on, always }; + pub const Placement = enum { acme, pardes }; + pub const BootShell = enum { keep, replace }; + /// 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 { @@ -811,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); @@ -818,7 +863,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 }; + pub const Toggle = enum { colors, wrap, tree_context_tag_style, tag_bottom, debug, focus_tint, syntax_bold, verbose, message_animation, ligatures }; /// The bundled post pass, a Shadertoy file in shaders/post/. pub const Scene = enum { crt }; @@ -832,12 +877,20 @@ 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 /// it of files. shader, shader_animation, + choice: Choice, }; pub const Setting = struct { @@ -861,11 +914,14 @@ pub const Runtime = struct { .{ .word = "Tagbottom", .action = .{ .toggle = .tag_bottom } }, .{ .word = "Debug", .action = .{ .toggle = .debug } }, .{ .word = "FocusTint", .action = .{ .toggle = .focus_tint } }, - .{ .word = "ColumnTags", .action = .{ .toggle = .column_tags } }, .{ .word = "SyntaxBold", .action = .{ .toggle = .syntax_bold } }, .{ .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 } }, @@ -890,6 +946,8 @@ pub const Runtime = struct { .{ .word = "Crt", .action = .{ .scene = .crt }, .availability = .scene_shaders }, .{ .word = "Shader", .action = .shader, .availability = .scene_shaders }, .{ .word = "ShaderAnimation", .action = .shader_animation, .availability = .scene_shaders }, + .{ .word = "Placement", .action = .{ .choice = .placement } }, + .{ .word = "BootShell", .action = .{ .choice = .boot_shell } }, }; pub fn find(name: []const u8) ?Setting { @@ -927,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"); @@ -1048,6 +1108,43 @@ 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; }, + // Bare, it steps to the next word, as a tag word should. + .choice => |which| switch (which) { + inline else => |field| { + const now = &@field(state, @tagName(field)); + const T = @TypeOf(now.*); + const text = std.mem.trim(u8, argument orelse "", " \t\r\n"); + now.* = if (text.len == 0) + @enumFromInt((@as(usize, @intFromEnum(now.*)) + 1) % std.enums.values(T).len) + else + 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; @@ -1217,6 +1314,16 @@ 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}), + .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| @@ -1348,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 = .{}; @@ -1450,6 +1572,7 @@ pub const Runtime = struct { .window_opacity = true, .window_blur = true, .ligatures = true, + .lift = true, }, .state = &state, }; @@ -1468,6 +1591,14 @@ pub const Runtime = struct { .dump_dir => "~/dumps", .shader => "~/crt.glsl", .shader_animation => "always", + .choice => |which| switch (which) { + .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)); @@ -1483,7 +1614,6 @@ pub const Runtime = struct { .tag_bottom => "Tagbottom on\n", .debug => "Debug on\n", .focus_tint => "FocusTint off\n", - .column_tags => "ColumnTags off\n", .syntax_bold => "SyntaxBold on\n", .verbose => "Verbose off\n", .message_animation => "MessageAnimation off\n", @@ -1518,6 +1648,14 @@ pub const Runtime = struct { }, .shader => "Shader ~/crt.glsl\n", .shader_animation => "ShaderAnimation always\n", + .choice => |which| switch (which) { + .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); |
