config: load themes

This commit is contained in:
Mitchell Hashimoto
2023-11-22 21:34:26 -08:00
parent 45a4be6873
commit 4dfbb79f8c

View File

@ -7,6 +7,7 @@ const builtin = @import("builtin");
const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator;
const global_state = &@import("../main.zig").state;
const fontpkg = @import("../font/main.zig");
const inputpkg = @import("../input.zig");
const terminal = @import("../terminal/main.zig");
@ -1326,7 +1327,85 @@ fn expandPaths(self: *Config, base: []const u8) !void {
}
}
fn loadTheme(self: *Config, theme: []const u8) !void {
const alloc = self._arena.?.allocator();
const resources_dir = global_state.resources_dir orelse {
try self._errors.add(alloc, .{
.message = "no resources directory found, themes will not work",
});
return;
};
const path = try std.fs.path.join(alloc, &.{
resources_dir,
"themes",
theme,
});
const cwd = std.fs.cwd();
var file = cwd.openFile(path, .{}) catch |err| {
switch (err) {
error.FileNotFound => try self._errors.add(alloc, .{
.message = try std.fmt.allocPrintZ(
alloc,
"theme \"{s}\" not found, path={s}",
.{ theme, path },
),
}),
else => try self._errors.add(alloc, .{
.message = try std.fmt.allocPrintZ(
alloc,
"failed to load theme \"{s}\": {}",
.{ theme, err },
),
}),
}
return;
};
defer file.close();
// From this point onwards, we load the theme and do a bit of a dance
// to achive two separate goals:
//
// (1) We want the theme to be loaded and our existing config to
// override the theme. So we need to load the theme and apply
// our config on top of it.
//
// (2) We want to free existing memory that we aren't using anymore
// as a result of reloading the configuration.
//
// Point 2 is strictly a result of aur approach to point 1.
// Keep track of our input length prior ot loading the theme
// so that we can replay the previous config to override values.
const input_len = self._inputs.items.len;
// Load into a new configuration so that we can free the existing memory.
const alloc_gpa = self._arena.?.child_allocator;
var new_config = try default(alloc_gpa);
errdefer new_config.deinit();
// Load our theme
var buf_reader = std.io.bufferedReader(file.reader());
var iter = cli.args.lineIterator(buf_reader.reader());
try new_config.loadIter(alloc_gpa, &iter);
// Replay our previous inputs so that we can override values
// from the theme.
var slice_it = cli.args.sliceIterator(self._inputs.items[0..input_len]);
try new_config.loadIter(alloc_gpa, &slice_it);
// Success, swap our new config in and free the old.
self.deinit();
self.* = new_config;
}
pub fn finalize(self: *Config) !void {
// We always load the theme first because it may set other fields
// in our config.
if (self.theme) |theme| try self.loadTheme(theme);
// If we have a font-family set and don't set the others, default
// the others to the font family. This way, if someone does
// --font-family=foo, then we try to get the stylized versions of