From 6c0e9c5a6b6d4b0aa77f084fdac5eb4f6d1f482b Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Thu, 1 Oct 2026 02:37:39 -0300 Subject: A ThemeFile that fails to load changes nothing: /ctl and DumpConfig keep naming the file last loaded, or none, so they always replay The request's path was taken as the theme file before the host had read it, so a file not found or not ZON left /ctl saying ThemeFile , and writing the report back failed again. The path a load succeeds with is now kept apart; a failure puts the request back to it (and watches it again), or to none. Co-Authored-By: Claude Opus 5.5 --- src/colors.zig | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src/colors.zig') diff --git a/src/colors.zig b/src/colors.zig index b75cdc3d..d04c009e 100644 --- a/src/colors.zig +++ b/src/colors.zig @@ -9,6 +9,7 @@ const animation = @import("animation.zig"); const Color = @import("surface.zig").Color; const FontRole = @import("surface.zig").FontRole; const config = @import("config.zig"); +const limits = @import("memory.zig").limits; const pdf_enabled = panes.Pdf.enabled; const platform = pardes.platform; const theme_animation = @import("pardes_config").theme_animation; @@ -739,7 +740,7 @@ pub fn requestThemeFile(p: *Pardes, id: usize, argument: []const u8) void { /// /ctl and DumpConfig say in place of `Theme `, 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(); + const path = p.theme_file_loaded.get(); return if (p.custom_theme != null and path.len > 0) path else null; } @@ -769,6 +770,20 @@ fn themeFileError(p: *Pardes, request: ThemeFileRequest, err: anyerror) void { var cut: [200]u8 = undefined; const path = @import("ninep/tree.zig").fitErr(request.path, &cut); p.reportError(request.pane, std.fmt.bufPrint(&said, "theme file {s}", .{path}) catch "theme file", err); + revertThemeFile(p); +} + +/// A ThemeFile that did not load changes nothing: the request goes back to +/// the file last loaded (watched again), or to none, so /ctl and DumpConfig +/// still read what replays. A bad save of the loaded file itself keeps it. +fn revertThemeFile(p: *Pardes) void { + const loaded = p.theme_file_loaded.get(); + if (std.mem.eql(u8, loaded, p.theme_file_path.get())) return; + var keep: [limits.host_path_cap]u8 = undefined; + @memcpy(keep[0..loaded.len], loaded); + if (loaded.len == 0) p.theme_file_path.clear() else _ = p.theme_file_path.set(keep[0..loaded.len]); + const generation = nextThemeFileGeneration(p); + p.emit(.{ .theme_file = .{ .generation = generation, .on = loaded.len > 0 } }); } pub fn loadThemeFile(p: *Pardes, generation: u32, bytes: []const u8, animate: bool) bool { @@ -804,6 +819,9 @@ pub fn loadThemeFile(p: *Pardes, generation: u32, bytes: []const u8, animate: bo const old = p.custom_theme; p.custom_theme = parsed; if (old) |theme_value| std.zon.parse.free(p.gpa, theme_value); + var settled: [limits.host_path_cap]u8 = undefined; + @memcpy(settled[0..request.path.len], request.path); + _ = p.theme_file_loaded.set(settled[0..request.path.len]); invalidateThemeDependentRasters(p); _ = p.scratch.reset(.retain_capacity); p.sync(); @@ -912,6 +930,7 @@ pub fn setThemeIndex(p: *Pardes, index: usize) void { p.custom_theme = null; std.zon.parse.free(p.gpa, theme_value); } + p.theme_file_loaded.clear(); if (p.theme_file_path.get().len > 0) { p.theme_file_path.clear(); const generation = nextThemeFileGeneration(p); -- cgit v1.3