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 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 Config = struct {
pub const SYSTEM_PATH = "/etc/ximper-unified-theme-switcher/themes"; pub const SYSTEM_PATH = "/etc/ximper-unified-theme-switcher/themes";
pub const HOME_DIR = ".config/ximper-unified-theme-switcher"; pub const HOME_DIR = ".config/ximper-unified-theme-switcher";
...@@ -65,20 +75,17 @@ pub const Config = struct { ...@@ -65,20 +75,17 @@ pub const Config = struct {
var lines = std.mem.splitScalar(u8, buf[0..content], '\n'); var lines = std.mem.splitScalar(u8, buf[0..content], '\n');
while (lines.next()) |line| { while (lines.next()) |line| {
if (std.mem.indexOf(u8, line, "=")) |idx| { const kv = parseKeyValue(line) orelse continue;
const k = std.mem.trim(u8, line[0..idx], " \t"); if (std.mem.eql(u8, kv.key, key))
if (std.mem.eql(u8, k, key)) { return try self.allocator.dupe(u8, kv.value);
const v = std.mem.trim(u8, line[idx + 1 ..], " \t\r");
return try self.allocator.dupe(u8, v);
}
}
} }
return null; return null;
} }
pub fn setValue(self: *Config, key: []const u8, value: []const u8) !void { pub fn setValue(self: *Config, key: []const u8, value: []const u8) !void {
var lines_list: std.ArrayListUnmanaged(u8) = .{}; var lines: std.ArrayListUnmanaged(u8) = .{};
defer lines_list.deinit(self.allocator); defer lines.deinit(self.allocator);
const writer = lines.writer(self.allocator);
var found = false; var found = false;
...@@ -90,49 +97,40 @@ pub const Config = struct { ...@@ -90,49 +97,40 @@ pub const Config = struct {
var iter = std.mem.splitScalar(u8, buf[0..content], '\n'); var iter = std.mem.splitScalar(u8, buf[0..content], '\n');
while (iter.next()) |line| { while (iter.next()) |line| {
if (line.len == 0) continue; if (line.len == 0) continue;
if (std.mem.indexOf(u8, line, "=")) |idx| { const kv = parseKeyValue(line);
const k = std.mem.trim(u8, line[0..idx], " \t"); if (kv != null and std.mem.eql(u8, kv.?.key, key)) {
if (std.mem.eql(u8, k, key)) { try writer.print("{s}={s}\n", .{ key, value });
try lines_list.appendSlice(self.allocator, key); found = true;
try lines_list.append(self.allocator, '='); } else {
try lines_list.appendSlice(self.allocator, value); try writer.print("{s}\n", .{line});
try lines_list.append(self.allocator, '\n');
found = true;
continue;
}
} }
try lines_list.appendSlice(self.allocator, line);
try lines_list.append(self.allocator, '\n');
} }
} else |_| {} } else |_| {}
if (!found) { if (!found)
try lines_list.appendSlice(self.allocator, key); try writer.print("{s}={s}\n", .{ key, value });
try lines_list.append(self.allocator, '=');
try lines_list.appendSlice(self.allocator, value);
try lines_list.append(self.allocator, '\n');
}
const file = try std.fs.cwd().createFile(self.path, .{}); const file = try std.fs.cwd().createFile(self.path, .{});
defer file.close(); defer file.close();
_ = try file.write(lines_list.items); _ = try file.write(lines.items);
} }
pub fn ensureDefaults(self: *Config) !void { fn setDefault(self: *Config, key: []const u8, default: []const u8) !void {
if (try self.getValue("CURRENT_THEME") == null) { if (try self.getValue(key)) |v| {
try self.setValue("CURRENT_THEME", "dark"); self.allocator.free(v);
} } else {
if (try self.getValue("KV_LIGHT_THEME") == null) { try self.setValue(key, default);
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);
} }
} }
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 { ...@@ -16,31 +16,32 @@ pub const ThemeManager = struct {
self.applyGtk3(mode); self.applyGtk3(mode);
} }
fn applyKvantum(self: *ThemeManager, mode: []const u8) void { fn applyTheme(
std.debug.print("Updating Kvantum theme to {s}…\n", .{mode}); self: *ThemeManager,
comptime name: []const u8,
const key = if (std.mem.eql(u8, mode, "light")) "KV_LIGHT_THEME" else "KV_DARK_THEME"; 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; const theme = (self.config.getValue(key) catch null) orelse return;
defer self.config.allocator.free(theme); defer self.config.allocator.free(theme);
const theme_z = self.config.allocator.dupeZ(u8, theme) catch return; const theme_z = self.config.allocator.dupeZ(u8, theme) catch return;
defer self.config.allocator.free(theme_z); 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 {}; _ = child.spawnAndWait() catch {};
} }
fn applyGtk3(self: *ThemeManager, mode: []const u8) void { fn applyKvantum(self: *ThemeManager, mode: []const u8) void {
std.debug.print("Updating GTK3 theme to {s}…\n", .{mode}); self.applyTheme("Kvantum", "KV_LIGHT_THEME", "KV_DARK_THEME", mode, &.{ "kvantummanager", "--set" });
}
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);
var child = std.process.Child.init(&.{ "gsettings", "set", "org.gnome.desktop.interface", "gtk-theme", theme_z }, self.config.allocator); fn applyGtk3(self: *ThemeManager, mode: []const u8) void {
_ = child.spawnAndWait() catch {}; 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