Adding keybind to the +list-themes TUI that would write out a file that contained themes (#8930)

This resolves issue: https://github.com/ghostty-org/ghostty/issues/8903,
so we can press 'w' when in TUI preview save mode to write a auto theme
config
pull/9089/head
Mitchell Hashimoto 2025-12-16 10:12:06 -08:00 committed by GitHub
commit 67eb480577
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 51 additions and 3 deletions

View File

@ -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;
@ -196,6 +197,31 @@ pub fn run(gpa_alloc: std.mem.Allocator) !u8 {
return 0;
}
fn resolveAutoThemePath(alloc: std.mem.Allocator) ![]u8 {
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;
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();
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) {
key_press: vaxis.Key,
mouse: vaxis.Mouse,
@ -487,6 +513,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();
}
},
}
},
@ -698,7 +727,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,
@ -733,6 +762,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| {
@ -786,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,
@ -809,6 +839,12 @@ 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 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:",
"",
"https://ghostty.org/docs/config/reference",
@ -1657,6 +1693,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 {