aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/config/edit.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/config/edit.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/config/edit.zig')
-rw-r--r--vendor/libghostty-vt/src/config/edit.zig104
1 files changed, 104 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/config/edit.zig b/vendor/libghostty-vt/src/config/edit.zig
new file mode 100644
index 00000000..8cedc47a
--- /dev/null
+++ b/vendor/libghostty-vt/src/config/edit.zig
@@ -0,0 +1,104 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const assert = @import("../quirks.zig").inlineAssert;
+const Allocator = std.mem.Allocator;
+const ArenaAllocator = std.heap.ArenaAllocator;
+const file_load = @import("file_load.zig");
+
+/// The path to the configuration that should be opened for editing.
+///
+/// On Linux, this will use the file at the XDG config path. This is the
+/// only valid path for Linux so we don't need to check for other paths.
+///
+/// On macOS, both XDG and AppSupport paths are valid. Because Ghostty
+/// prioritizes AppSupport over XDG, we will use AppSupport if it exists,
+/// followed by XDG if it exists, and finally AppSupport if neither exist.
+/// For the existence check, we also prefer non-empty files over empty
+/// files.
+///
+/// The returned value is allocated using the provided allocator.
+pub fn openPath(alloc_gpa: Allocator) ![:0]const u8 {
+ // Use an arena to make memory management easier in here.
+ var arena = ArenaAllocator.init(alloc_gpa);
+ defer arena.deinit();
+ const alloc_arena = arena.allocator();
+
+ // Get the path we should open
+ const config_path = try configPath(alloc_arena);
+
+ // Create config directory recursively.
+ if (std.fs.path.dirname(config_path)) |config_dir| {
+ try std.fs.cwd().makePath(config_dir);
+ }
+
+ // Try to create file and go on if it already exists
+ _ = std.fs.createFileAbsolute(
+ config_path,
+ .{ .exclusive = true },
+ ) catch |err| {
+ switch (err) {
+ error.PathAlreadyExists => {},
+ else => return err,
+ }
+ };
+
+ return try alloc_gpa.dupeZ(u8, config_path);
+}
+
+/// Returns the config path to use for open for the current OS.
+///
+/// The allocator must be an arena allocator. No memory is freed by this
+/// function and the resulting path is not all the memory that is allocated.
+fn configPath(alloc_arena: Allocator) ![]const u8 {
+ const paths: []const []const u8 = try configPathCandidates(alloc_arena);
+ assert(paths.len > 0);
+
+ // Find the first path that exists and is non-empty. If no paths are
+ // non-empty but at least one exists, we will return the first path that
+ // exists.
+ var exists: ?[]const u8 = null;
+ for (paths) |path| {
+ const f = std.fs.openFileAbsolute(path, .{}) catch |err| {
+ switch (err) {
+ // File doesn't exist, continue.
+ error.BadPathName, error.FileNotFound => continue,
+
+ // Some other error, assume it exists and return it.
+ else => return err,
+ }
+ };
+ defer f.close();
+
+ // We expect stat to succeed because we just opened the file.
+ const stat = try f.stat();
+
+ // If the file is non-empty, return it.
+ if (stat.size > 0) return path;
+
+ // If the file is empty, remember it exists.
+ if (exists == null) exists = path;
+ }
+
+ // No paths are non-empty, return the first path that exists.
+ if (exists) |v| return v;
+
+ // No paths are non-empty or exist, return the first path.
+ return paths[0];
+}
+
+/// Returns a const list of possible paths the main config file could be
+/// in for the current OS.
+fn configPathCandidates(alloc_arena: Allocator) ![]const []const u8 {
+ var paths: std.ArrayList([]const u8) = try .initCapacity(alloc_arena, 4);
+ errdefer paths.deinit(alloc_arena);
+
+ if (comptime builtin.os.tag == .macos) {
+ paths.appendAssumeCapacity(try file_load.defaultAppSupportPath(alloc_arena));
+ paths.appendAssumeCapacity(try file_load.legacyDefaultAppSupportPath(alloc_arena));
+ }
+
+ paths.appendAssumeCapacity(try file_load.defaultXdgPath(alloc_arena));
+ paths.appendAssumeCapacity(try file_load.legacyDefaultXdgPath(alloc_arena));
+
+ return paths.items;
+}