From 50cf2fee6acb0eee9f557738011e32633b9cf09f Mon Sep 17 00:00:00 2001 From: yunusey Date: Sat, 24 May 2025 14:50:38 -0400 Subject: [PATCH] Use `Path` struct --- src/config.zig | 2 +- src/config/Config.zig | 139 +--------------------------------------- src/renderer/OpenGL.zig | 28 +++++--- 3 files changed, 20 insertions(+), 149 deletions(-) diff --git a/src/config.zig b/src/config.zig index 2eeeb29cf..26e652183 100644 --- a/src/config.zig +++ b/src/config.zig @@ -30,7 +30,7 @@ pub const RepeatableFontVariation = Config.RepeatableFontVariation; pub const RepeatableString = Config.RepeatableString; pub const RepeatableStringMap = @import("config/RepeatableStringMap.zig"); pub const RepeatablePath = Config.RepeatablePath; -pub const SinglePath = Config.SinglePath; +pub const Path = Config.Path; pub const ShellIntegrationFeatures = Config.ShellIntegrationFeatures; pub const WindowPaddingColor = Config.WindowPaddingColor; pub const BackgroundImageMode = Config.BackgroundImageMode; diff --git a/src/config/Config.zig b/src/config/Config.zig index 810818a33..33f01d847 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -460,7 +460,7 @@ background: Color = .{ .r = 0x28, .g = 0x2C, .b = 0x34 }, foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF }, /// Background image for the window. -@"background-image": SinglePath = .{}, +@"background-image": ?Path = null, /// Background image opacity @"background-image-opacity": f32 = 1.0, @@ -3012,86 +3012,6 @@ fn expandPaths(self: *Config, base: []const u8) !void { } } -/// Expand a relative path to an absolute path. This function is used by -/// the RepeatablePath and SinglePath to expand the paths they store. -fn expandPath( - alloc: Allocator, - base: []const u8, - path: []const u8, - diags: *cli.DiagnosticList, -) ![]const u8 { - assert(std.fs.path.isAbsolute(base)); - var dir = try std.fs.cwd().openDir(base, .{}); - defer dir.close(); - - // If it is already absolute we can just return it - if (path.len == 0 or std.fs.path.isAbsolute(path)) return path; - - // If it isn't absolute, we need to make it absolute relative - // to the base. - var buf: [std.fs.max_path_bytes]u8 = undefined; - - // Check if the path starts with a tilde and expand it to the - // home directory on Linux/macOS. We explicitly look for "~/" - // because we don't support alternate users such as "~alice/" - if (std.mem.startsWith(u8, path, "~/")) expand: { - // Windows isn't supported yet - if (comptime builtin.os.tag == .windows) break :expand; - - const expanded: []const u8 = internal_os.expandHome( - path, - &buf, - ) catch |err| { - try diags.append(alloc, .{ - .message = try std.fmt.allocPrintZ( - alloc, - "error expanding home directory for path {s}: {}", - .{ path, err }, - ), - }); - - // We can't expand this path so return an empty string - return ""; - }; - - log.debug( - "expanding file path from home directory: path={s}", - .{expanded}, - ); - - return expanded; - } - - const abs = dir.realpath(path, &buf) catch |err| abs: { - if (err == error.FileNotFound) { - // The file doesn't exist. Try to resolve the relative path - // another way. - const resolved = try std.fs.path.resolve(alloc, &.{ base, path }); - defer alloc.free(resolved); - @memcpy(buf[0..resolved.len], resolved); - break :abs buf[0..resolved.len]; - } - - try diags.append(alloc, .{ - .message = try std.fmt.allocPrintZ( - alloc, - "error resolving file path {s}: {}", - .{ path, err }, - ), - }); - - // We can't expand this path so return an empty string - return ""; - }; - - log.debug( - "expanding file path relative={s} abs={s}", - .{ path, abs }, - ); - - return abs; -} - fn loadTheme(self: *Config, theme: Theme) !void { // Load the correct theme depending on the conditional state. // Dark/light themes were programmed prior to conditional configuration @@ -4270,63 +4190,6 @@ pub const Palette = struct { } }; -/// SinglePath is a path to a single file. When loading the configuration -/// file, always the last one will be kept and be automatically expanded -/// relative to the path of the config file. -pub const SinglePath = struct { - const Self = @This(); - - /// The actual value that is updated as we parse. - value: ?[]const u8 = null, - - /// Parse a single path. - pub fn parseCLI(self: *Self, alloc: Allocator, input: ?[]const u8) !void { - const value = input orelse return error.ValueRequired; - // If the value is empty, we set the value to null - if (value.len == 0) { - self.value = null; - return; - } - const copy = try alloc.dupe(u8, value); - self.value = copy; - } - - /// Deep copy of the struct. Required by Config. - pub fn clone(self: Self, alloc: Allocator) Allocator.Error!Self { - const value = self.value orelse return .{}; - - const copy_path = try alloc.dupe(u8, value); - return .{ - .value = copy_path, - }; - } - - /// Used by Formatter - pub fn formatEntry(self: Self, formatter: anytype) !void { - const value = self.value orelse return; - try formatter.formatEntry([]const u8, value); - } - - /// Expand all the paths relative to the base directory. - pub fn expand( - self: *Self, - alloc: Allocator, - base: []const u8, - diags: *cli.DiagnosticList, - ) !void { - // Try expanding path relative to the base. - const path = self.value orelse return; - const abs = try expandPath(alloc, base, path, diags); - - if (abs.len == 0) { - // Blank this path so that we don't attempt to resolve it again - self.value = null; - return; - } - self.value = try alloc.dupeZ(u8, abs); - } -}; - /// RepeatableString is a string value that can be repeated to accumulate /// a list of strings. This isn't called "StringList" because I find that /// sometimes leads to confusion that it _accepts_ a list such as diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index bdf047599..0ffc2c91b 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -141,7 +141,7 @@ draw_mutex: DrawMutex = drawMutexZero, draw_background: terminal.color.RGB, /// The background image(s) to draw. Currently, we always draw the last image. -background_image: configpkg.SinglePath, +background_image: ?configpkg.Path, /// The opacity of the background image. Not to be confused with background-opacity background_image_opacity: f32, @@ -299,7 +299,7 @@ pub const DerivedConfig = struct { cursor_opacity: f64, background: terminal.color.RGB, background_opacity: f64, - background_image: configpkg.SinglePath, + background_image: ?configpkg.Path, background_image_opacity: f32, background_image_mode: configpkg.BackgroundImageMode, foreground: terminal.color.RGB, @@ -324,7 +324,7 @@ pub const DerivedConfig = struct { const custom_shaders = try config.@"custom-shader".clone(alloc); // Copy our background image - const background_image = try config.@"background-image".clone(alloc); + const background_image = try config.@"background-image".?.clone(alloc); // Copy our font features const font_features = try config.@"font-feature".clone(alloc); @@ -828,14 +828,22 @@ pub fn updateFrame( } if (self.current_background_image == null) { - if (self.background_image.value) |img_path| { + if (self.background_image) |background_image| { + const img_path, const optional = switch (background_image) { + .optional => |path| .{ path, true }, + .required => |path| .{ path, false }, + }; if (single_threaded_draw) self.draw_mutex.lock(); defer if (single_threaded_draw) self.draw_mutex.unlock(); - self.prepBackgroundImage(img_path) catch |err| switch (err) { - error.InvalidData => { - log.warn("invalid image data, skipping", .{}); - }, - else => return err, + self.prepBackgroundImage(img_path) catch |err| { + switch (err) { + error.InvalidData => { + if (!optional) { + log.err("error loading background image {s}: {}", .{ img_path, err }); + } + }, + else => return err, + } }; } } @@ -1246,7 +1254,7 @@ pub fn readImageContent(self: *OpenGL, path: []const u8) ![]u8 { assert(std.fs.path.isAbsolute(path)); // Open the file var file = std.fs.openFileAbsolute(path, .{}) catch |err| { - log.warn("failed to open file: {}", .{err}); + log.warn("failed to open file {s}: {}", .{ path, err }); return error.InvalidData; }; defer file.close();