mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
config: support loading from "Application Support" directory on macOS
This commit is contained in:
@ -724,7 +724,7 @@ pub const Surface = struct {
|
||||
/// Set the shape of the cursor.
|
||||
fn setMouseShape(self: *Surface, shape: terminal.MouseShape) !void {
|
||||
if ((comptime builtin.target.isDarwin()) and
|
||||
!internal_os.macosVersionAtLeast(13, 0, 0))
|
||||
!internal_os.macos.isAtLeastVersion(13, 0, 0))
|
||||
{
|
||||
// We only set our cursor if we're NOT on Mac, or if we are then the
|
||||
// macOS version is >= 13 (Ventura). On prior versions, glfw crashes
|
||||
|
@ -1809,10 +1809,15 @@ pub fn deinit(self: *Config) void {
|
||||
/// Load the configuration according to the default rules:
|
||||
///
|
||||
/// 1. Defaults
|
||||
/// 2. XDG Config File
|
||||
/// 2. Configuration Files
|
||||
/// 3. CLI flags
|
||||
/// 4. Recursively defined configuration files
|
||||
///
|
||||
/// Configuration files are loaded in the follow order:
|
||||
///
|
||||
/// 1. XDG Config File
|
||||
/// 2. "Application Support" Config File on macOS
|
||||
///
|
||||
pub fn load(alloc_gpa: Allocator) !Config {
|
||||
var result = try default(alloc_gpa);
|
||||
errdefer result.deinit();
|
||||
@ -2394,25 +2399,37 @@ pub fn loadFile(self: *Config, alloc: Allocator, path: []const u8) !void {
|
||||
try self.expandPaths(std.fs.path.dirname(path).?);
|
||||
}
|
||||
|
||||
/// Load the configuration from the default configuration file. The default
|
||||
/// configuration file is at `$XDG_CONFIG_HOME/ghostty/config`.
|
||||
pub fn loadDefaultFiles(self: *Config, alloc: Allocator) !void {
|
||||
const config_path = try internal_os.xdg.config(alloc, .{ .subdir = "ghostty/config" });
|
||||
defer alloc.free(config_path);
|
||||
|
||||
self.loadFile(alloc, config_path) catch |err| switch (err) {
|
||||
/// Load optional configuration file from `path`. All errors are ignored.
|
||||
pub fn loadOptionalFile(self: *Config, alloc: Allocator, path: []const u8) void {
|
||||
self.loadFile(alloc, path) catch |err| switch (err) {
|
||||
error.FileNotFound => std.log.info(
|
||||
"homedir config not found, not loading path={s}",
|
||||
.{config_path},
|
||||
"optional config file not found, not loading path={s}",
|
||||
.{path},
|
||||
),
|
||||
|
||||
else => std.log.warn(
|
||||
"error reading config file, not loading err={} path={s}",
|
||||
.{ err, config_path },
|
||||
"error reading optional config file, not loading err={} path={s}",
|
||||
.{ err, path },
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/// Load configurations from the default configuration files. The default
|
||||
/// configuration file is at `$XDG_CONFIG_HOME/ghostty/config`.
|
||||
///
|
||||
/// On macOS, `$HOME/Library/Application Support/$CFBundleIdentifier/config`
|
||||
/// is also loaded.
|
||||
pub fn loadDefaultFiles(self: *Config, alloc: Allocator) !void {
|
||||
const xdg_path = try internal_os.xdg.config(alloc, .{ .subdir = "ghostty/config" });
|
||||
defer alloc.free(xdg_path);
|
||||
self.loadOptionalFile(alloc, xdg_path);
|
||||
|
||||
if (builtin.os.tag == .macos) {
|
||||
const app_support_path = try internal_os.macos.getAppSupportDir(alloc, "config");
|
||||
defer alloc.free(app_support_path);
|
||||
self.loadOptionalFile(alloc, app_support_path);
|
||||
}
|
||||
}
|
||||
|
||||
/// Load and parse the CLI args.
|
||||
pub fn loadCliArgs(self: *Config, alloc_gpa: Allocator) !void {
|
||||
switch (builtin.os.tag) {
|
||||
|
54
src/os/macos.zig
Normal file
54
src/os/macos.zig
Normal file
@ -0,0 +1,54 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
const objc = @import("objc");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub const NSOperatingSystemVersion = extern struct {
|
||||
major: i64,
|
||||
minor: i64,
|
||||
patch: i64,
|
||||
};
|
||||
|
||||
/// Verifies that the running macOS system version is at least the given version.
|
||||
pub fn isAtLeastVersion(major: i64, minor: i64, patch: i64) bool {
|
||||
assert(builtin.target.isDarwin());
|
||||
|
||||
const NSProcessInfo = objc.getClass("NSProcessInfo").?;
|
||||
const info = NSProcessInfo.msgSend(objc.Object, objc.sel("processInfo"), .{});
|
||||
return info.msgSend(bool, objc.sel("isOperatingSystemAtLeastVersion:"), .{
|
||||
NSOperatingSystemVersion{ .major = major, .minor = minor, .patch = patch },
|
||||
});
|
||||
}
|
||||
|
||||
pub const NSSearchPathDirectory = enum(c_ulong) {
|
||||
NSApplicationSupportDirectory = 14,
|
||||
};
|
||||
|
||||
pub const NSSearchPathDomainMask = enum(c_ulong) {
|
||||
NSUserDomainMask = 1,
|
||||
};
|
||||
|
||||
pub fn getAppSupportDir(alloc: Allocator, sub_path: []const u8) ![]u8 {
|
||||
assert(builtin.target.isDarwin());
|
||||
|
||||
const err: ?*anyopaque = undefined;
|
||||
const NSFileManager = objc.getClass("NSFileManager").?;
|
||||
const manager = NSFileManager.msgSend(objc.Object, objc.sel("defaultManager"), .{});
|
||||
const url = manager.msgSend(
|
||||
objc.Object,
|
||||
objc.sel("URLForDirectory:inDomain:appropriateForURL:create:error:"),
|
||||
.{
|
||||
NSSearchPathDirectory.NSApplicationSupportDirectory,
|
||||
NSSearchPathDomainMask.NSUserDomainMask,
|
||||
@as(?*anyopaque, null),
|
||||
true,
|
||||
&err,
|
||||
},
|
||||
);
|
||||
const path = url.getProperty(objc.Object, "path");
|
||||
const c_str = path.getProperty([*:0]const u8, "UTF8String");
|
||||
const app_support_dir = std.mem.sliceTo(c_str, 0);
|
||||
|
||||
return try std.fs.path.join(alloc, &.{ app_support_dir, "com.mitchellh.ghostty", sub_path });
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
const objc = @import("objc");
|
||||
|
||||
/// Verifies that the running macOS system version is at least the given version.
|
||||
pub fn macosVersionAtLeast(major: i64, minor: i64, patch: i64) bool {
|
||||
assert(builtin.target.isDarwin());
|
||||
|
||||
const NSProcessInfo = objc.getClass("NSProcessInfo").?;
|
||||
const info = NSProcessInfo.msgSend(objc.Object, objc.sel("processInfo"), .{});
|
||||
return info.msgSend(bool, objc.sel("isOperatingSystemAtLeastVersion:"), .{
|
||||
NSOperatingSystemVersion{ .major = major, .minor = minor, .patch = patch },
|
||||
});
|
||||
}
|
||||
|
||||
pub const NSOperatingSystemVersion = extern struct {
|
||||
major: i64,
|
||||
minor: i64,
|
||||
patch: i64,
|
||||
};
|
@ -8,7 +8,6 @@ const file = @import("file.zig");
|
||||
const flatpak = @import("flatpak.zig");
|
||||
const homedir = @import("homedir.zig");
|
||||
const locale = @import("locale.zig");
|
||||
const macos_version = @import("macos_version.zig");
|
||||
const mouse = @import("mouse.zig");
|
||||
const openpkg = @import("open.zig");
|
||||
const pipepkg = @import("pipe.zig");
|
||||
@ -21,6 +20,7 @@ pub const hostname = @import("hostname.zig");
|
||||
pub const passwd = @import("passwd.zig");
|
||||
pub const xdg = @import("xdg.zig");
|
||||
pub const windows = @import("windows.zig");
|
||||
pub const macos = @import("macos.zig");
|
||||
|
||||
// Functions and types
|
||||
pub const CFReleaseThread = @import("cf_release_thread.zig");
|
||||
@ -37,7 +37,6 @@ pub const freeTmpDir = file.freeTmpDir;
|
||||
pub const isFlatpak = flatpak.isFlatpak;
|
||||
pub const home = homedir.home;
|
||||
pub const ensureLocale = locale.ensureLocale;
|
||||
pub const macosVersionAtLeast = macos_version.macosVersionAtLeast;
|
||||
pub const clickInterval = mouse.clickInterval;
|
||||
pub const open = openpkg.open;
|
||||
pub const pipe = pipepkg.pipe;
|
||||
|
Reference in New Issue
Block a user