Commit d8fe8785 authored by Vitaly Lipatov's avatar Vitaly Lipatov

service: refactor config and theme modules

- Add parseKeyValue() helper to eliminate key=value parsing duplication - Use writer.print() instead of multiple appendSlice() calls in setValue() - Add setDefault() method that properly frees allocated memory (fixes leak) - Refactor ensureDefaults() using inline for with defaults tuple - Extract common applyTheme() function in theme.zig
parent 2412fc32
const std = @import("std");
const KeyValue = struct { key: []const u8, value: []const u8 };
fn parseKeyValue(line: []const u8) ?KeyValue {
const idx = std.mem.indexOf(u8, line, "=") orelse return null;
return .{
.key = std.mem.trim(u8, line[0..idx], " \t"),
.value = std.mem.trim(u8, line[idx + 1 ..], " \t\r"),
};
}
pub const Config = struct {
pub const SYSTEM_PATH = "/etc/ximper-unified-theme-switcher/themes";
pub const HOME_DIR = ".config/ximper-unified-theme-switcher";
......@@ -65,20 +75,17 @@ pub const Config = struct {
var lines = std.mem.splitScalar(u8, buf[0..content], '\n');
while (lines.next()) |line| {
if (std.mem.indexOf(u8, line, "=")) |idx| {
const k = std.mem.trim(u8, line[0..idx], " \t");
if (std.mem.eql(u8, k, key)) {
const v = std.mem.trim(u8, line[idx + 1 ..], " \t\r");
return try self.allocator.dupe(u8, v);
}
}
const kv = parseKeyValue(line) orelse continue;
if (std.mem.eql(u8, kv.key, key))
return try self.allocator.dupe(u8, kv.value);
}
return null;
}
pub fn setValue(self: *Config, key: []const u8, value: []const u8) !void {
var lines_list: std.ArrayListUnmanaged(u8) = .{};
defer lines_list.deinit(self.allocator);
var lines: std.ArrayListUnmanaged(u8) = .{};
defer lines.deinit(self.allocator);
const writer = lines.writer(self.allocator);
var found = false;
......@@ -90,49 +97,40 @@ pub const Config = struct {
var iter = std.mem.splitScalar(u8, buf[0..content], '\n');
while (iter.next()) |line| {
if (line.len == 0) continue;
if (std.mem.indexOf(u8, line, "=")) |idx| {
const k = std.mem.trim(u8, line[0..idx], " \t");
if (std.mem.eql(u8, k, key)) {
try lines_list.appendSlice(self.allocator, key);
try lines_list.append(self.allocator, '=');
try lines_list.appendSlice(self.allocator, value);
try lines_list.append(self.allocator, '\n');
found = true;
continue;
}
const kv = parseKeyValue(line);
if (kv != null and std.mem.eql(u8, kv.?.key, key)) {
try writer.print("{s}={s}\n", .{ key, value });
found = true;
} else {
try writer.print("{s}\n", .{line});
}
try lines_list.appendSlice(self.allocator, line);
try lines_list.append(self.allocator, '\n');
}
} else |_| {}
if (!found) {
try lines_list.appendSlice(self.allocator, key);
try lines_list.append(self.allocator, '=');
try lines_list.appendSlice(self.allocator, value);
try lines_list.append(self.allocator, '\n');
}
if (!found)
try writer.print("{s}={s}\n", .{ key, value });
const file = try std.fs.cwd().createFile(self.path, .{});
defer file.close();
_ = try file.write(lines_list.items);
_ = try file.write(lines.items);
}
pub fn ensureDefaults(self: *Config) !void {
if (try self.getValue("CURRENT_THEME") == null) {
try self.setValue("CURRENT_THEME", "dark");
}
if (try self.getValue("KV_LIGHT_THEME") == null) {
try self.setValue("KV_LIGHT_THEME", DEFAULT_KV_LIGHT);
}
if (try self.getValue("KV_DARK_THEME") == null) {
try self.setValue("KV_DARK_THEME", DEFAULT_KV_DARK);
}
if (try self.getValue("GTK3_LIGHT_THEME") == null) {
try self.setValue("GTK3_LIGHT_THEME", DEFAULT_GTK3_LIGHT);
}
if (try self.getValue("GTK3_DARK_THEME") == null) {
try self.setValue("GTK3_DARK_THEME", DEFAULT_GTK3_DARK);
fn setDefault(self: *Config, key: []const u8, default: []const u8) !void {
if (try self.getValue(key)) |v| {
self.allocator.free(v);
} else {
try self.setValue(key, default);
}
}
pub fn ensureDefaults(self: *Config) !void {
const defaults = .{
.{ "CURRENT_THEME", "dark" },
.{ "KV_LIGHT_THEME", DEFAULT_KV_LIGHT },
.{ "KV_DARK_THEME", DEFAULT_KV_DARK },
.{ "GTK3_LIGHT_THEME", DEFAULT_GTK3_LIGHT },
.{ "GTK3_DARK_THEME", DEFAULT_GTK3_DARK },
};
inline for (defaults) |d| try self.setDefault(d[0], d[1]);
}
};
......@@ -16,31 +16,32 @@ pub const ThemeManager = struct {
self.applyGtk3(mode);
}
fn applyKvantum(self: *ThemeManager, mode: []const u8) void {
std.debug.print("Updating Kvantum theme to {s}…\n", .{mode});
const key = if (std.mem.eql(u8, mode, "light")) "KV_LIGHT_THEME" else "KV_DARK_THEME";
fn applyTheme(
self: *ThemeManager,
comptime name: []const u8,
comptime light_key: []const u8,
comptime dark_key: []const u8,
mode: []const u8,
comptime cmd: []const [:0]const u8,
) void {
std.debug.print("Updating {s} theme to {s}…\n", .{ name, mode });
const key = if (std.mem.eql(u8, mode, "light")) light_key else dark_key;
const theme = (self.config.getValue(key) catch null) orelse return;
defer self.config.allocator.free(theme);
const theme_z = self.config.allocator.dupeZ(u8, theme) catch return;
defer self.config.allocator.free(theme_z);
var child = std.process.Child.init(&.{ "kvantummanager", "--set", theme_z }, self.config.allocator);
var child = std.process.Child.init(cmd ++ .{theme_z}, self.config.allocator);
_ = child.spawnAndWait() catch {};
}
fn applyGtk3(self: *ThemeManager, mode: []const u8) void {
std.debug.print("Updating GTK3 theme to {s}…\n", .{mode});
const key = if (std.mem.eql(u8, mode, "light")) "GTK3_LIGHT_THEME" else "GTK3_DARK_THEME";
const theme = (self.config.getValue(key) catch null) orelse return;
defer self.config.allocator.free(theme);
const theme_z = self.config.allocator.dupeZ(u8, theme) catch return;
defer self.config.allocator.free(theme_z);
fn applyKvantum(self: *ThemeManager, mode: []const u8) void {
self.applyTheme("Kvantum", "KV_LIGHT_THEME", "KV_DARK_THEME", mode, &.{ "kvantummanager", "--set" });
}
var child = std.process.Child.init(&.{ "gsettings", "set", "org.gnome.desktop.interface", "gtk-theme", theme_z }, self.config.allocator);
_ = child.spawnAndWait() catch {};
fn applyGtk3(self: *ThemeManager, mode: []const u8) void {
self.applyTheme("GTK3", "GTK3_LIGHT_THEME", "GTK3_DARK_THEME", mode, &.{ "gsettings", "set", "org.gnome.desktop.interface", "gtk-theme" });
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment