From fe52eb9494f1a4a631b66953046e07a1d29bb32b Mon Sep 17 00:00:00 2001 From: greathongtu Date: Sat, 27 Sep 2025 15:16:27 +0800 Subject: [PATCH 1/3] Adding keybind 'w' to the +list-themes TUI that would write out a file that contained themes --- src/cli/list_themes.zig | 43 +++++++++++++++++++++++++++++++++++++- src/config/config-template | 7 +++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/cli/list_themes.zig b/src/cli/list_themes.zig index cc6cfaf3e..e54bbf307 100644 --- a/src/cli/list_themes.zig +++ b/src/cli/list_themes.zig @@ -192,6 +192,28 @@ pub fn run(gpa_alloc: std.mem.Allocator) !u8 { return 0; } +fn resolveAutoThemePath(alloc: std.mem.Allocator) ![]u8 { + const main_cfg_path = try Config.preferredDefaultFilePath(alloc); + defer alloc.free(main_cfg_path); + + const base_dir = std.fs.path.dirname(main_cfg_path) orelse return error.BadPathName; + return try std.fs.path.join(alloc, &.{ base_dir, "auto", "theme.ghostty" }); +} + +fn writeAutoThemeFile(alloc: std.mem.Allocator, theme_name: []const u8) !void { + const auto_path = try resolveAutoThemePath(alloc); + defer alloc.free(auto_path); + + if (std.fs.path.dirname(auto_path)) |dir| { + try std.fs.cwd().makePath(dir); + } + + var f = try std.fs.createFileAbsolute(auto_path, .{ .truncate = true }); + defer f.close(); + + try f.writer().print("theme = {s}\n", .{theme_name}); +} + const Event = union(enum) { key_press: vaxis.Key, mouse: vaxis.Mouse, @@ -483,6 +505,9 @@ const Preview = struct { self.should_quit = true; if (key.matchesAny(&.{ vaxis.Key.escape, vaxis.Key.enter, vaxis.Key.kp_enter }, .{})) self.mode = .normal; + if (key.matches('w', .{})) { + self.saveSelectedTheme(); + } }, } }, @@ -694,7 +719,7 @@ const Preview = struct { .help => { win.hideCursor(); const width = 60; - const height = 20; + const height = 22; const child = win.child( .{ .x_off = win.width / 2 -| width / 2, @@ -729,6 +754,7 @@ const Preview = struct { .{ .keys = "/", .help = "Start search." }, .{ .keys = "^X, ^/", .help = "Clear search." }, .{ .keys = "⏎", .help = "Save theme or close search window." }, + .{ .keys = "w", .help = "Write theme to auto config file." }, }; for (key_help, 0..) |help, captured_i| { @@ -805,6 +831,9 @@ const Preview = struct { try std.fmt.allocPrint(alloc, "theme = {s}", .{theme.theme}), "", "Save the configuration file and then reload it to apply the new theme.", + "", + "Or press 'w' to write an auto theme file.", + "", "For more details on configuration and themes, visit the Ghostty documentation:", "", "https://ghostty.org/docs/config/reference", @@ -1653,6 +1682,18 @@ const Preview = struct { }); } } + + fn saveSelectedTheme(self: *Preview) void { + if (self.filtered.items.len == 0) + return; + + const idx = self.filtered.items[self.current]; + const theme = self.themes[idx]; + + writeAutoThemeFile(self.allocator, theme.theme) catch { + return; + }; + } }; fn color(config: Config, palette: usize) vaxis.Color { diff --git a/src/config/config-template b/src/config/config-template index 63309137a..d71c36a9e 100644 --- a/src/config/config-template +++ b/src/config/config-template @@ -24,6 +24,13 @@ # reloaded while running; some only apply to new windows and others may require # a full restart to take effect. +# Auto theme include +# ================== +# This include makes it easy to pick a theme via `ghostty +list-themes`: +# press Enter on a theme, then 'w' to write the auto theme file. +# This path is relative to this config file. +config-file = ?auto/theme.ghostty + # Config syntax crash course # ========================== # # The config file consists of simple key-value pairs, From 906dac3145e063d4b5a5f6dd10db1d55027ced79 Mon Sep 17 00:00:00 2001 From: greathongtu Date: Sat, 4 Oct 2025 21:17:04 +0800 Subject: [PATCH 2/3] io as interface --- src/cli/list_themes.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cli/list_themes.zig b/src/cli/list_themes.zig index e54bbf307..9b11947df 100644 --- a/src/cli/list_themes.zig +++ b/src/cli/list_themes.zig @@ -211,7 +211,10 @@ fn writeAutoThemeFile(alloc: std.mem.Allocator, theme_name: []const u8) !void { var f = try std.fs.createFileAbsolute(auto_path, .{ .truncate = true }); defer f.close(); - try f.writer().print("theme = {s}\n", .{theme_name}); + var buf: [128]u8 = undefined; + var w = f.writer(&buf); + try w.interface.print("theme = {s}\n", .{theme_name}); + try w.interface.flush(); } const Event = union(enum) { From f7d0d72f19cb8c6d6bd510a2f77e18e82d560794 Mon Sep 17 00:00:00 2001 From: greathongtu Date: Wed, 17 Dec 2025 00:31:39 +0800 Subject: [PATCH 3/3] remove auto theme include in config-template --- src/cli/list_themes.zig | 12 ++++++++---- src/config/config-template | 7 ------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/cli/list_themes.zig b/src/cli/list_themes.zig index 716d662b6..42aff9d56 100644 --- a/src/cli/list_themes.zig +++ b/src/cli/list_themes.zig @@ -2,6 +2,7 @@ const std = @import("std"); const args = @import("args.zig"); const Action = @import("ghostty.zig").Action; const Config = @import("../config/Config.zig"); +const configpkg = @import("../config.zig"); const themepkg = @import("../config/theme.zig"); const tui = @import("tui.zig"); const global_state = &@import("../global.zig").state; @@ -197,7 +198,7 @@ pub fn run(gpa_alloc: std.mem.Allocator) !u8 { } fn resolveAutoThemePath(alloc: std.mem.Allocator) ![]u8 { - const main_cfg_path = try Config.preferredDefaultFilePath(alloc); + const main_cfg_path = try configpkg.preferredDefaultFilePath(alloc); defer alloc.free(main_cfg_path); const base_dir = std.fs.path.dirname(main_cfg_path) orelse return error.BadPathName; @@ -815,8 +816,8 @@ const Preview = struct { .save => { const theme = self.themes[self.filtered.items[self.current]]; - const width = 90; - const height = 12; + const width = 92; + const height = 17; const child = win.child( .{ .x_off = win.width / 2 -| width / 2, @@ -839,7 +840,10 @@ const Preview = struct { "", "Save the configuration file and then reload it to apply the new theme.", "", - "Or press 'w' to write an auto theme file.", + "Or press 'w' to write an auto theme file to your system's preferred default config path.", + "Then add the following line to your Ghostty configuration and reload:", + "", + "config-file = ?auto/theme.ghostty", "", "For more details on configuration and themes, visit the Ghostty documentation:", "", diff --git a/src/config/config-template b/src/config/config-template index d71c36a9e..63309137a 100644 --- a/src/config/config-template +++ b/src/config/config-template @@ -24,13 +24,6 @@ # reloaded while running; some only apply to new windows and others may require # a full restart to take effect. -# Auto theme include -# ================== -# This include makes it easy to pick a theme via `ghostty +list-themes`: -# press Enter on a theme, then 'w' to write the auto theme file. -# This path is relative to this config file. -config-file = ?auto/theme.ghostty - # Config syntax crash course # ========================== # # The config file consists of simple key-value pairs,