diff options
| -rw-r--r-- | src/Output.zig | 1 | ||||
| -rw-r--r-- | src/colors.zig | 8 | ||||
| -rw-r--r-- | src/config.zig | 8 | ||||
| -rw-r--r-- | src/ninep/ctl.zig | 39 |
4 files changed, 54 insertions, 2 deletions
diff --git a/src/Output.zig b/src/Output.zig index 01797cbe..47fcc7e4 100644 --- a/src/Output.zig +++ b/src/Output.zig @@ -870,6 +870,7 @@ pub fn openConfig(p: *Pardes, id: usize) !void { .startup_config_path = p.opts.startup_config_path, .platform = @tagName(pardes.platform), .theme_name = p.theme().name, + .theme_file = pardes.colors.loadedThemeFile(p), .compiled_default_shell = config.defaultShell(), .hover_delay_frames = config.look_preview_delay_frames, .native_images = p.native_images, diff --git a/src/colors.zig b/src/colors.zig index c78043cc..8d541c13 100644 --- a/src/colors.zig +++ b/src/colors.zig @@ -735,6 +735,14 @@ pub fn requestThemeFile(p: *Pardes, id: usize, argument: []const u8) void { p.emit(.{ .theme_file = .{ .generation = generation, .on = true } }); } +/// The .zon a ThemeFile loaded, while it is the theme in effect: what +/// /ctl and DumpConfig say in place of `Theme <name>`, since the name +/// inside the file is no theme `Theme` knows. +pub fn loadedThemeFile(p: *const Pardes) ?[]const u8 { + const path = p.theme_file_path.get(); + return if (p.custom_theme != null and path.len > 0) path else null; +} + pub const ThemeFileRequest = struct { path: []const u8, pane: u8, diff --git a/src/config.zig b/src/config.zig index 592281d3..a7377cfa 100644 --- a/src/config.zig +++ b/src/config.zig @@ -1267,6 +1267,9 @@ pub const Runtime = struct { startup_config_path: ?[]const u8, platform: []const u8, theme_name: []const u8, + /// The ThemeFile in effect, said as `ThemeFile <path>` in place + /// of the theme's name. + theme_file: ?[]const u8 = null, compiled_default_shell: []const u8, hover_delay_frames: ?u16, /// Where dumps go when `DumpDir` is unset; empty without a host @@ -1305,7 +1308,10 @@ pub const Runtime = struct { }; try out.print("{s} {s}\n", .{ setting.word, onOff(value) }); }, - .theme => try out.print("{s} {s}\n", .{ setting.word, context.theme_name }), + .theme => if (context.theme_file) |path| + try out.print("ThemeFile {s}\n", .{path}) + else + try out.print("{s} {s}\n", .{ setting.word, context.theme_name }), .window_opacity => { if (setting.enabled(context.capabilities)) try out.print("{s} {d}\n", .{ setting.word, state.window_opacity }) diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index 902a9647..bc27f72b 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -554,7 +554,9 @@ pub fn writeSettingsOf(p: *Pardes, s: *const config.Runtime, w: *std.Io.Writer) const word = setting.word; switch (setting.action) { .toggle => |field| try w.print("{s} {s}\n", .{ word, if (@field(s, @tagName(field))) "on" else "off" }), - .theme => try w.print("{s} {s}\n", .{ word, if (s == &p.settings) p.theme().name else pardes.themes[s.theme].name }), + .theme => if (s == &p.settings) { + if (pardes.colors.loadedThemeFile(p)) |path| try w.print("ThemeFile {s}\n", .{path}) else try w.print("{s} {s}\n", .{ word, p.theme().name }); + } else try w.print("{s} {s}\n", .{ word, pardes.themes[s.theme].name }), .shell => { const chosen = s.shell.requested.get(); try w.print("{s} {s}\n", .{ word, if (chosen.len > 0) chosen else config.defaultShell() }); @@ -1829,6 +1831,41 @@ test "an error's words give the errno a mount reads: EINVAL for what is malforme } } +test "after a ThemeFile the root ctl and DumpConfig say ThemeFile and its path, which writes back" { + if (comptime !pardes.hosted) return; + const gpa = testing.allocator; + const p = try withFile(gpa, "x\n"); + defer p.deinit(); + const root_ctl = @intFromEnum(tree.TopFile.ctl); + const path = "/tmp/pardes-mine-theme.zon"; + try testing.expectEqual(Status.ok, wr(p, root_ctl, "ThemeFile " ++ path ++ "\n").reply.status); + var custom = pardes.themes[0]; + custom.name = "mine"; + var encoded: std.Io.Writer.Allocating = .init(gpa); + defer encoded.deinit(); + try std.zon.stringify.serialize(custom, .{}, &encoded.writer); + try testing.expect(pardes.colors.loadThemeFile(p, p.theme_file_generation, encoded.written(), false)); + const settings = rd(p, root_ctl, 0, 1 << 16).bytes; + try testing.expect(std.mem.indexOf(u8, settings, "ThemeFile " ++ path ++ "\n") != null); + try testing.expect(std.mem.indexOf(u8, settings, "Theme mine") == null); + var storage: [16384]u8 = undefined; + var out: std.Io.Writer = .fixed(&storage); + try config.Runtime.writeReport(&out, .{ + .startup_config_path = null, + .platform = @tagName(pardes.platform), + .theme_name = p.theme().name, + .theme_file = pardes.colors.loadedThemeFile(p), + .compiled_default_shell = config.defaultShell(), + .hover_delay_frames = null, + .native_images = false, + .capabilities = builtins.capabilities, + .state = &p.settings, + }); + try testing.expect(std.mem.indexOf(u8, out.buffered(), "ThemeFile " ++ path ++ "\n") != null); + // Written back, it is the same request again, not "no theme mine". + try testing.expectEqual(Status.ok, wr(p, root_ctl, "ThemeFile " ++ path ++ "\n").reply.status); +} + test "Joincol with no column to the right and Theme with no such theme say so" { const gpa = testing.allocator; const p = try withFile(gpa, "x\n"); |
