mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
macos: implement config reloading callback
This commit is contained in:
@ -243,6 +243,7 @@ int ghostty_init(void);
|
|||||||
|
|
||||||
ghostty_config_t ghostty_config_new();
|
ghostty_config_t ghostty_config_new();
|
||||||
void ghostty_config_free(ghostty_config_t);
|
void ghostty_config_free(ghostty_config_t);
|
||||||
|
void ghostty_config_load_cli_args(ghostty_config_t);
|
||||||
void ghostty_config_load_string(ghostty_config_t, const char *, uintptr_t);
|
void ghostty_config_load_string(ghostty_config_t, const char *, uintptr_t);
|
||||||
void ghostty_config_load_default_files(ghostty_config_t);
|
void ghostty_config_load_default_files(ghostty_config_t);
|
||||||
void ghostty_config_load_recursive_files(ghostty_config_t);
|
void ghostty_config_load_recursive_files(ghostty_config_t);
|
||||||
|
@ -12,12 +12,25 @@ extension Ghostty {
|
|||||||
/// The readiness value of the state.
|
/// The readiness value of the state.
|
||||||
@Published var readiness: AppReadiness = .loading
|
@Published var readiness: AppReadiness = .loading
|
||||||
|
|
||||||
/// The ghostty global configuration.
|
/// The ghostty global configuration. This should only be changed when it is definitely
|
||||||
var config: ghostty_config_t? = nil
|
/// safe to change. It is definite safe to change only when the embedded app runtime
|
||||||
|
/// in Ghostty says so (usually, only in a reload configuration callback).
|
||||||
|
var config: ghostty_config_t? = nil {
|
||||||
|
didSet {
|
||||||
|
// Free the old value whenever we change
|
||||||
|
guard let old = oldValue else { return }
|
||||||
|
ghostty_config_free(old)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The ghostty app instance. We only have one of these for the entire app, although I guess
|
/// The ghostty app instance. We only have one of these for the entire app, although I guess
|
||||||
/// in theory you can have multiple... I don't know why you would...
|
/// in theory you can have multiple... I don't know why you would...
|
||||||
var app: ghostty_app_t? = nil
|
var app: ghostty_app_t? = nil {
|
||||||
|
didSet {
|
||||||
|
guard let old = oldValue else { return }
|
||||||
|
ghostty_app_free(old)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Cached clipboard string for `read_clipboard` callback.
|
/// Cached clipboard string for `read_clipboard` callback.
|
||||||
private var cached_clipboard_string: String? = nil
|
private var cached_clipboard_string: String? = nil
|
||||||
@ -31,24 +44,12 @@ extension Ghostty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the global configuration.
|
// Initialize the global configuration.
|
||||||
guard let cfg = ghostty_config_new() else {
|
guard let cfg = Self.reloadConfig() else {
|
||||||
GhosttyApp.logger.critical("ghostty_config_new failed")
|
|
||||||
readiness = .error
|
readiness = .error
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.config = cfg;
|
self.config = cfg;
|
||||||
|
|
||||||
// Load our configuration files from the home directory.
|
|
||||||
ghostty_config_load_default_files(cfg);
|
|
||||||
ghostty_config_load_recursive_files(cfg);
|
|
||||||
|
|
||||||
// TODO: we'd probably do some config loading here... for now we'd
|
|
||||||
// have to do this synchronously. When we support config updating we can do
|
|
||||||
// this async and update later.
|
|
||||||
|
|
||||||
// Finalize will make our defaults available.
|
|
||||||
ghostty_config_finalize(cfg)
|
|
||||||
|
|
||||||
// Create our "runtime" config. The "runtime" is the configuration that ghostty
|
// Create our "runtime" config. The "runtime" is the configuration that ghostty
|
||||||
// uses to interface with the application runtime environment.
|
// uses to interface with the application runtime environment.
|
||||||
var runtime_cfg = ghostty_runtime_config_s(
|
var runtime_cfg = ghostty_runtime_config_s(
|
||||||
@ -75,8 +76,32 @@ extension Ghostty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
ghostty_app_free(app)
|
// This will force the didSet callbacks to run which free.
|
||||||
ghostty_config_free(config)
|
self.app = nil
|
||||||
|
self.config = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes a new configuration and loads all the values.
|
||||||
|
static func reloadConfig() -> ghostty_config_t? {
|
||||||
|
// Initialize the global configuration.
|
||||||
|
guard let cfg = ghostty_config_new() else {
|
||||||
|
GhosttyApp.logger.critical("ghostty_config_new failed")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our configuration files from the home directory.
|
||||||
|
ghostty_config_load_default_files(cfg);
|
||||||
|
ghostty_config_load_cli_args(cfg);
|
||||||
|
ghostty_config_load_recursive_files(cfg);
|
||||||
|
|
||||||
|
// TODO: we'd probably do some config loading here... for now we'd
|
||||||
|
// have to do this synchronously. When we support config updating we can do
|
||||||
|
// this async and update later.
|
||||||
|
|
||||||
|
// Finalize will make our defaults available.
|
||||||
|
ghostty_config_finalize(cfg)
|
||||||
|
|
||||||
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
func appTick() {
|
func appTick() {
|
||||||
@ -142,12 +167,19 @@ extension Ghostty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static func reloadConfig(_ userdata: UnsafeMutableRawPointer?) -> ghostty_config_t? {
|
static func reloadConfig(_ userdata: UnsafeMutableRawPointer?) -> ghostty_config_t? {
|
||||||
// TODO: implement config reloading in the mac app
|
guard let newConfig = AppState.reloadConfig() else {
|
||||||
let state = Unmanaged<AppState>.fromOpaque(userdata!).takeUnretainedValue()
|
GhosttyApp.logger.warning("failed to reload configuration")
|
||||||
_ = state
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assign the new config. This will automatically free the old config.
|
||||||
|
// It is safe to free the old config from within this function call.
|
||||||
|
let state = Unmanaged<AppState>.fromOpaque(userdata!).takeUnretainedValue()
|
||||||
|
state.config = newConfig
|
||||||
|
|
||||||
|
return newConfig
|
||||||
|
}
|
||||||
|
|
||||||
static func wakeup(_ userdata: UnsafeMutableRawPointer?) {
|
static func wakeup(_ userdata: UnsafeMutableRawPointer?) {
|
||||||
let state = Unmanaged<AppState>.fromOpaque(userdata!).takeUnretainedValue()
|
let state = Unmanaged<AppState>.fromOpaque(userdata!).takeUnretainedValue()
|
||||||
|
|
||||||
|
@ -217,11 +217,7 @@ pub const Config = struct {
|
|||||||
try result.loadDefaultFiles(alloc_gpa);
|
try result.loadDefaultFiles(alloc_gpa);
|
||||||
|
|
||||||
// Parse the config from the CLI args
|
// Parse the config from the CLI args
|
||||||
{
|
try result.loadCliArgs(alloc_gpa);
|
||||||
var iter = try std.process.argsWithAllocator(alloc_gpa);
|
|
||||||
defer iter.deinit();
|
|
||||||
try cli_args.parse(Config, alloc_gpa, &result, &iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the config files that were added from our file and CLI args.
|
// Parse the config files that were added from our file and CLI args.
|
||||||
try result.loadRecursiveFiles(alloc_gpa);
|
try result.loadRecursiveFiles(alloc_gpa);
|
||||||
@ -564,6 +560,14 @@ pub const Config = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load and parse the CLI args.
|
||||||
|
pub fn loadCliArgs(self: *Config, alloc_gpa: Allocator) !void {
|
||||||
|
// Parse the config from the CLI args
|
||||||
|
var iter = try std.process.argsWithAllocator(alloc_gpa);
|
||||||
|
defer iter.deinit();
|
||||||
|
try cli_args.parse(Config, alloc_gpa, self, &iter);
|
||||||
|
}
|
||||||
|
|
||||||
/// Load and parse the config files that were added in the "config-file" key.
|
/// Load and parse the config files that were added in the "config-file" key.
|
||||||
pub fn loadRecursiveFiles(self: *Config, alloc: Allocator) !void {
|
pub fn loadRecursiveFiles(self: *Config, alloc: Allocator) !void {
|
||||||
// TODO(mitchellh): we should parse the files form the homedir first
|
// TODO(mitchellh): we should parse the files form the homedir first
|
||||||
@ -1190,6 +1194,13 @@ pub const CAPI = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load the configuration from the CLI args.
|
||||||
|
export fn ghostty_config_load_cli_args(self: *Config) void {
|
||||||
|
self.loadCliArgs(global.alloc) catch |err| {
|
||||||
|
log.err("error loading config err={}", .{err});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Load the configuration from a string in the same format as
|
/// Load the configuration from a string in the same format as
|
||||||
/// the file-based syntax for the desktop version of the terminal.
|
/// the file-based syntax for the desktop version of the terminal.
|
||||||
export fn ghostty_config_load_string(
|
export fn ghostty_config_load_string(
|
||||||
|
Reference in New Issue
Block a user