diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-04-04 19:22:04 +0300 |
|---|---|---|
| committer | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 01:23:06 +0300 |
| commit | 41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch) | |
| tree | 3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/config/file_load.zig | |
| parent | 55c138263e190a1e79d4b997bfb9397306c0ec1f (diff) | |
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/config/file_load.zig')
| -rw-r--r-- | vendor/libghostty-vt/src/config/file_load.zig | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/config/file_load.zig b/vendor/libghostty-vt/src/config/file_load.zig new file mode 100644 index 00000000..7885de32 --- /dev/null +++ b/vendor/libghostty-vt/src/config/file_load.zig @@ -0,0 +1,166 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const assert = @import("../quirks.zig").inlineAssert; +const Allocator = std.mem.Allocator; +const internal_os = @import("../os/main.zig"); + +const log = std.log.scoped(.config); + +/// Default path for the XDG home configuration file. Returned value +/// must be freed by the caller. +pub fn defaultXdgPath(alloc: Allocator) ![]const u8 { + return try internal_os.xdg.config( + alloc, + .{ .subdir = "ghostty/config.ghostty" }, + ); +} + +/// Ghostty <1.3.0 default path for the XDG home configuration file. +/// Returned value must be freed by the caller. +pub fn legacyDefaultXdgPath(alloc: Allocator) ![]const u8 { + return try internal_os.xdg.config( + alloc, + .{ .subdir = "ghostty/config" }, + ); +} + +/// Preferred default path for the XDG home configuration file. +/// Returned value must be freed by the caller. +pub fn preferredXdgPath(alloc: Allocator) ![]const u8 { + // If the XDG path exists, use that. + const xdg_path = try defaultXdgPath(alloc); + if (open(xdg_path)) |f| { + f.close(); + return xdg_path; + } else |_| {} + + // Try the legacy path + errdefer alloc.free(xdg_path); + const legacy_xdg_path = try legacyDefaultXdgPath(alloc); + if (open(legacy_xdg_path)) |f| { + f.close(); + alloc.free(xdg_path); + return legacy_xdg_path; + } else |_| {} + + // Legacy path and XDG path both don't exist. Return the + // new one. + alloc.free(legacy_xdg_path); + return xdg_path; +} + +/// Default path for the macOS Application Support configuration file. +/// Returned value must be freed by the caller. +pub fn defaultAppSupportPath(alloc: Allocator) ![]const u8 { + return try internal_os.macos.appSupportDir(alloc, "config.ghostty"); +} + +/// Ghostty <1.3.0 default path for the macOS Application Support +/// configuration file. Returned value must be freed by the caller. +pub fn legacyDefaultAppSupportPath(alloc: Allocator) ![]const u8 { + return try internal_os.macos.appSupportDir(alloc, "config"); +} + +/// Preferred default path for the macOS Application Support configuration file. +/// Returned value must be freed by the caller. +pub fn preferredAppSupportPath(alloc: Allocator) ![]const u8 { + // If the app support path exists, use that. + const app_support_path = try defaultAppSupportPath(alloc); + if (open(app_support_path)) |f| { + f.close(); + return app_support_path; + } else |_| {} + + // Try the legacy path + errdefer alloc.free(app_support_path); + const legacy_app_support_path = try legacyDefaultAppSupportPath(alloc); + if (open(legacy_app_support_path)) |f| { + f.close(); + alloc.free(app_support_path); + return legacy_app_support_path; + } else |_| {} + + // Legacy path and app support path both don't exist. Return the + // new one. + alloc.free(legacy_app_support_path); + return app_support_path; +} + +/// Returns the path to the preferred default configuration file. +/// This is the file where users should place their configuration. +/// +/// This doesn't create or populate the file with any default +/// contents; downstream callers must handle this. +/// +/// The returned value must be freed by the caller. +pub fn preferredDefaultFilePath(alloc: Allocator) ![]const u8 { + switch (builtin.os.tag) { + .macos => { + // macOS prefers the Application Support directory + // if it exists. + const app_support_path = try preferredAppSupportPath(alloc); + const app_support_file = open(app_support_path) catch { + // Try the XDG path if it exists + const xdg_path = try preferredXdgPath(alloc); + const xdg_file = open(xdg_path) catch { + // If neither file exists, use app support + alloc.free(xdg_path); + return app_support_path; + }; + xdg_file.close(); + alloc.free(app_support_path); + return xdg_path; + }; + app_support_file.close(); + return app_support_path; + }, + + // All other platforms use XDG only + else => return try preferredXdgPath(alloc), + } +} + +const OpenFileError = error{ + FileNotFound, + FileIsEmpty, + FileOpenFailed, + NotAFile, +}; + +/// Opens the file at the given path and returns the file handle +/// if it exists and is non-empty. This also constrains the possible +/// errors to a smaller set that we can explicitly handle. +pub fn open(path: []const u8) OpenFileError!std.fs.File { + assert(std.fs.path.isAbsolute(path)); + + var file = std.fs.openFileAbsolute( + path, + .{}, + ) catch |err| switch (err) { + error.FileNotFound => return OpenFileError.FileNotFound, + else => { + log.warn("unexpected file open error path={s} err={}", .{ + path, + err, + }); + return OpenFileError.FileOpenFailed; + }, + }; + errdefer file.close(); + + const stat = file.stat() catch |err| { + log.warn("error getting file stat path={s} err={}", .{ + path, + err, + }); + return OpenFileError.FileOpenFailed; + }; + switch (stat.kind) { + .file => {}, + else => return OpenFileError.NotAFile, + } + + if (stat.size == 0) return OpenFileError.FileIsEmpty; + + return file; +} |
