mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
Use Path
struct
This commit is contained in:
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user