summaryrefslogtreecommitdiff
path: root/src/colors.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-30 20:05:16 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit506ca99f13aec67d593e4a30bbe416dea176d0ba (patch)
treedf61a0d3846b45b3ef70d189c676dfa98975541c /src/colors.zig
parent30378c63d752bf27d44f6a64738bab5a2cddc863 (diff)
downloadpardes-506ca99f13aec67d593e4a30bbe416dea176d0ba.tar.gz
pardes-506ca99f13aec67d593e4a30bbe416dea176d0ba.zip
A ThemeFile that fails names its file: "theme file /x/mine.zon: file not found", not "theme file: file not found"
The read and parse failures come back after the write, often from a relative name resolved against the config directory, so which file was missing or bad was left to guess. They now carry the resolved path, its middle cut when long. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/colors.zig')
-rw-r--r--src/colors.zig29
1 files changed, 24 insertions, 5 deletions
diff --git a/src/colors.zig b/src/colors.zig
index 8d541c13..b75cdc3d 100644
--- a/src/colors.zig
+++ b/src/colors.zig
@@ -759,7 +759,16 @@ pub fn themeFileRequest(p: *const Pardes, generation: u32) ?ThemeFileRequest {
pub fn failThemeFile(p: *Pardes, generation: u32, err: anyerror) void {
const request = themeFileRequest(p, generation) orelse return;
- p.reportError(request.pane, "theme file", err);
+ themeFileError(p, request, err);
+}
+
+/// A theme file's failure, said with its path: `theme file x.zon: file
+/// not found`, not which file left to guess.
+fn themeFileError(p: *Pardes, request: ThemeFileRequest, err: anyerror) void {
+ var said: [300]u8 = undefined;
+ 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);
}
pub fn loadThemeFile(p: *Pardes, generation: u32, bytes: []const u8, animate: bool) bool {
@@ -767,23 +776,23 @@ pub fn loadThemeFile(p: *Pardes, generation: u32, bytes: []const u8, animate: bo
@setEvalBranchQuota(10000);
const request = themeFileRequest(p, generation) orelse return false;
if (bytes.len > 1024 * 1024) {
- p.reportError(request.pane, "theme file", error.ThemeFileTooLarge);
+ themeFileError(p, request, error.ThemeFileTooLarge);
return false;
}
const source = p.gpa.dupeZ(u8, bytes) catch |err| {
- p.reportError(request.pane, "theme file", err);
+ themeFileError(p, request, err);
return false;
};
defer p.gpa.free(source);
var diagnostics: std.zon.parse.Diagnostics = .{};
defer diagnostics.deinit(p.gpa);
const parsed = std.zon.parse.fromSliceAlloc(Theme, p.gpa, source, &diagnostics, .{}) catch |err| {
- p.reportError(request.pane, "theme file", err);
+ themeFileError(p, request, err);
return false;
};
if (parsed.name.len == 0 or parsed.name.len > 255) {
std.zon.parse.free(p.gpa, parsed);
- p.reportError(request.pane, "theme file", error.InvalidThemeName);
+ themeFileError(p, request, error.InvalidThemeName);
return false;
}
@@ -912,6 +921,16 @@ pub fn setThemeIndex(p: *Pardes, index: usize) void {
invalidateThemeDependentRasters(p);
}
+test "a theme file that cannot be read is named in the failure" {
+ if (platform == .web) return;
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true });
+ defer p.deinit();
+ requestThemeFile(p, 0, "/nowhere/mine.zon");
+ failThemeFile(p, p.theme_file_generation, error.FileNotFound);
+ const pane = p.panes[0].?;
+ try std.testing.expect(std.mem.indexOf(u8, pane.msg[0..pane.msg_len], "theme file /nowhere/mine.zon: ") != null);
+}
+
test "ThemeFile parses ZON atomically and Theme returns to the compiled ring" {
if (platform == .web) return;
const p = try Pardes.init(std.testing.allocator, .{