diff options
| author | kj_sh604 | 2026-06-05 15:29:19 -0400 |
|---|---|---|
| committer | kj_sh604 | 2026-06-05 15:29:19 -0400 |
| commit | 393fd854892d1e2a31fce009c68c6cfb293fc9af (patch) | |
| tree | a36d559444e2678c3e7aab91a2b3ffbc05423260 /src/config.zig | |
| parent | 44f510c75fa470654aa607e2860571382dcde638 (diff) | |
refactor: src/config.zig
Diffstat (limited to 'src/config.zig')
| -rw-r--r-- | src/config.zig | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/config.zig b/src/config.zig new file mode 100644 index 0000000..6325b0b --- /dev/null +++ b/src/config.zig @@ -0,0 +1,133 @@ +const std = @import("std"); + +const c = @import("c.zig").c; + +pub const Config = struct { + // camera settings + min_scale: f32 = 0.5, + scroll_speed: f32 = 1.5, + drag_friction: f32 = 6.0, + scale_friction: f32 = 4.0, + velocity_threshold: f32 = 15.0, + scale_change_threshold: f32 = 0.5, + + // flashlight settings + initial_radius: f32 = 200.0, + initial_delta_radius: f32 = 250.0, + radius_damping: f32 = 10.0, + fade_speed: f32 = 6.0, + max_shadow_opacity: f32 = 0.8, + radius_change_threshold: f32 = 1.0, + feather: f32 = 0.0, + + // opengl settings + texture_filter: i32 = 0, + + // key bindings (KeySym = c_ulong on x86_64 linux) + key_escape: c_ulong = c.XK_Escape, + key_flashlight: c_ulong = c.XK_f, + key_reset: c_ulong = c.XK_0, + key_mirror: c_ulong = c.XK_m, + key_zoom_in: c_ulong = c.XK_equal, + key_zoom_out: c_ulong = c.XK_minus, + + modifier_flashlight: c_uint = c.ControlMask, + button_drag: c_uint = c.Button1, + button_zoom_in: c_uint = c.Button4, + button_zoom_out: c_uint = c.Button5, + + pub fn default() Config { + return .{}; + } + + pub fn applyValue(self: *Config, key: []const u8, value: f32) void { + if (std.mem.eql(u8, key, "min_scale")) self.min_scale = value; + if (std.mem.eql(u8, key, "scroll_speed")) self.scroll_speed = value; + if (std.mem.eql(u8, key, "drag_friction")) self.drag_friction = value; + if (std.mem.eql(u8, key, "scale_friction")) self.scale_friction = value; + if (std.mem.eql(u8, key, "velocity_threshold")) self.velocity_threshold = value; + if (std.mem.eql(u8, key, "scale_change_threshold")) self.scale_change_threshold = value; + if (std.mem.eql(u8, key, "initial_radius")) self.initial_radius = value; + if (std.mem.eql(u8, key, "initial_delta_radius")) self.initial_delta_radius = value; + if (std.mem.eql(u8, key, "radius_damping")) self.radius_damping = value; + if (std.mem.eql(u8, key, "fade_speed")) self.fade_speed = value; + if (std.mem.eql(u8, key, "max_shadow_opacity")) self.max_shadow_opacity = value; + if (std.mem.eql(u8, key, "radius_change_threshold")) self.radius_change_threshold = value; + if (std.mem.eql(u8, key, "feather")) self.feather = value; + if (std.mem.eql(u8, key, "texture_filter")) self.texture_filter = @intFromFloat(value); + } + + pub fn loadFromFile(self: *Config, path: []const u8) void { + var path_buf: [1024]u8 = undefined; + @memcpy(path_buf[0..@min(path.len, path_buf.len - 1)], path); + path_buf[@min(path.len, path_buf.len - 1)] = 0; + const path_z: [*:0]const u8 = @ptrCast(&path_buf); + + const f = c.fopen(path_z, "r") orelse return; + defer _ = c.fclose(f); + + var buf: [4096]u8 = undefined; + while (c.fgets(&buf, buf.len, f) != null) { + const raw = buf[0 .. std.mem.indexOfScalar(u8, &buf, 0) orelse buf.len]; + const line = std.mem.trimStart(u8, raw, " \t"); + if (line.len == 0 or line[0] == '#') continue; + + var parts = std.mem.splitScalar(u8, line, '='); + const key = std.mem.trimEnd(u8, parts.first(), " \t"); + const val_str = if (parts.next()) |v| std.mem.trimStart(u8, v, " \t") else continue; + const value = std.fmt.parseFloat(f32, val_str) catch continue; + + self.applyValue(key, value); + } + } + + pub fn writeDefault(self: Config, path: []const u8) !void { + var path_buf: [1024]u8 = undefined; + @memcpy(path_buf[0..@min(path.len, path_buf.len - 1)], path); + path_buf[@min(path.len, path_buf.len - 1)] = 0; + const path_z: [*:0]const u8 = @ptrCast(&path_buf); + + const f = c.fopen(path_z, "w") orelse { + std.debug.print("error: could not write config to {s}\n", .{path}); + return error.ConfigWriteFailed; + }; + defer _ = c.fclose(f); + + _ = c.fprintf(f, "min_scale = %.1f\n", self.min_scale); + _ = c.fprintf(f, "scroll_speed = %.1f\n", self.scroll_speed); + _ = c.fprintf(f, "drag_friction = %.1f\n", self.drag_friction); + _ = c.fprintf(f, "scale_friction = %.1f\n", self.scale_friction); + _ = c.fprintf(f, "velocity_threshold = %.1f\n", self.velocity_threshold); + _ = c.fprintf(f, "scale_change_threshold = %.2f\n", self.scale_change_threshold); + _ = c.fprintf(f, "initial_radius = %.1f\n", self.initial_radius); + _ = c.fprintf(f, "initial_delta_radius = %.1f\n", self.initial_delta_radius); + _ = c.fprintf(f, "radius_damping = %.1f\n", self.radius_damping); + _ = c.fprintf(f, "fade_speed = %.1f\n", self.fade_speed); + _ = c.fprintf(f, "max_shadow_opacity = %.2f\n", self.max_shadow_opacity); + _ = c.fprintf(f, "radius_change_threshold = %.2f\n", self.radius_change_threshold); + _ = c.fprintf(f, "feather = %.2f\n", self.feather); + _ = c.fprintf(f, "texture_filter = %d\n", self.texture_filter); + } + + pub fn defaultConfigPath(alloc: std.mem.Allocator) ?[]const u8 { + const home = std.c.getenv("HOME") orelse return null; + const home_slice = std.mem.sliceTo(home, 0); + const path = std.fs.path.join(alloc, &.{ home_slice, ".config", "boomer", "config" }) catch return null; + return path; + } + + pub fn mkdirP(path: []const u8) void { + var buf: [1024]u8 = undefined; + const len = @min(path.len, buf.len - 1); + @memcpy(buf[0..len], path[0..len]); + buf[len] = 0; + for (1..len) |i| { + if (buf[i] == '/') { + buf[i] = 0; + _ = std.c.mkdir((buf[0..i :0]).ptr, 0o755); + buf[i] = '/'; + } + } + _ = std.c.mkdir((buf[0..len :0]).ptr, 0o755); + } +};
\ No newline at end of file |
