diff options
| author | t <t@tjp.lol> | 2026-06-23 09:38:23 -0600 |
|---|---|---|
| committer | t <t@tjp.lol> | 2026-06-23 10:53:26 -0600 |
| commit | 69a1ee138bb78ad4663fe2d9e58678f7b0d07b74 (patch) | |
| tree | 453d3ad42a07536220e6ca5d91b439ff57793e32 /src/config_file.zig | |
| parent | 538a5d926fa626a00cc3dc12c555f11f82867efd (diff) | |
ponytail simplifications to panto cli and lua extensiosn
Diffstat (limited to 'src/config_file.zig')
| -rw-r--r-- | src/config_file.zig | 105 |
1 files changed, 12 insertions, 93 deletions
diff --git a/src/config_file.zig b/src/config_file.zig index 6d4b705..5bd2a51 100644 --- a/src/config_file.zig +++ b/src/config_file.zig @@ -54,15 +54,12 @@ const Io = std.Io; const toml = @import("toml"); const panto = @import("panto"); +const tvalue = toml.value_mod; const glob = @import("glob.zig"); const models_toml = @import("models_toml.zig"); - -// Document-building helpers live in the toml library's `value` module and -// are not re-exported at its root. `tableIterator` *is* re-exported, so we -// use `toml.tableIterator` directly but reach through `value_mod` for the -// constructors/mutators. -const tvalue = toml.value_mod; +const panto_home = @import("panto_home.zig"); +const toml_layer = @import("toml_layer.zig"); pub const APIStyle = panto.APIStyle; @@ -406,22 +403,11 @@ fn layerPaths( return .{ .base = base, .user = user, .project = project, .local = local }; } -/// `$PANTO_HOME/config.toml`, falling back to /// `${XDG_DATA_HOME:-$HOME/.local/share}/panto/config.toml`. -/// -/// `PANTO_HOME` is checked first so this always agrees with where the -/// bootstrap stages the default base config (see `panto_home.resolveHome`). pub fn baseConfigPath(allocator: Allocator, environ_map: *const std.process.Environ.Map) Error![]u8 { - if (environ_map.get("PANTO_HOME")) |home| { - return try std.fs.path.join(allocator, &.{ home, "config.toml" }); - } - if (environ_map.get("XDG_DATA_HOME")) |xdg| { - return try std.fs.path.join(allocator, &.{ xdg, "panto", "config.toml" }); - } - if (environ_map.get("HOME")) |home| { - return try std.fs.path.join(allocator, &.{ home, ".local", "share", "panto", "config.toml" }); - } - return error.NoHomeDirectory; + const home = try panto_home.homePath(allocator, environ_map); + defer allocator.free(home); + return try std.fs.path.join(allocator, &.{ home, "config.toml" }); } /// `${XDG_CONFIG_HOME:-$HOME/.config}/panto/config.toml`. @@ -461,73 +447,23 @@ pub fn loadFromPaths( defer merged.deinit(); for (paths) |path| { - const bytes = readFileAlloc(allocator, io, path) catch |err| switch (err) { + const bytes = toml_layer.readFileAlloc(allocator, io, path) catch |err| switch (err) { error.FileNotFound => continue, - else => return err, + error.ReadFailed => return error.ConfigReadFailed, + error.Canceled => return error.Canceled, + error.OutOfMemory => return error.OutOfMemory, }; defer allocator.free(bytes); const doc = parseDoc(allocator, bytes) catch return error.InvalidConfigToml; defer doc.deinit(); - try mergeTable(merged.allocator(), merged.root, doc.root); + try toml_layer.mergeTable(merged.allocator(), merged.root, doc.root); } return resolve(allocator, environ_map, merged.root); } // =========================================================================== -// Merge -// =========================================================================== - -/// Deep-merge `src` table into `dst` table (both must be `.table`). -/// Tables recurse; everything else (scalars, arrays) overwrites. Values are -/// deep-copied into `alloc` (the merged document's arena) so they outlive -/// the source document. -fn mergeTable(alloc: Allocator, dst: *toml.Value, src: *const toml.Value) Allocator.Error!void { - std.debug.assert(dst.* == .table); - if (src.* != .table) return; - - var it = toml.tableIterator(src); - while (it.next()) |entry| { - const existing = dst.get(entry.key); - if (existing != null and existing.?.* == .table and entry.value.* == .table) { - // Both sides are tables — recurse to accumulate keys. - try mergeTable(alloc, @constCast(existing.?), entry.value); - } else { - // Overwrite (or insert) with a deep copy of the source value. - const copy = try cloneValue(alloc, entry.value); - const key_copy = try alloc.dupe(u8, entry.key); - try tvalue.tableSet(alloc, dst, key_copy, copy); - } - } -} - -fn cloneValue(alloc: Allocator, src: *const toml.Value) Allocator.Error!*toml.Value { - const out = try alloc.create(toml.Value); - switch (src.*) { - .table => { - out.* = .{ .table = .{} }; - var it = toml.tableIterator(src); - while (it.next()) |entry| { - const child = try cloneValue(alloc, entry.value); - const key_copy = try alloc.dupe(u8, entry.key); - try tvalue.tableSet(alloc, out, key_copy, child); - } - }, - .array => |*a| { - out.* = .{ .array = .{} }; - for (a.items.items) |*item| { - const child = try cloneValue(alloc, item); - try tvalue.arrayAppend(alloc, out, child.*); - } - }, - .string => |s| out.* = .{ .string = try alloc.dupe(u8, s) }, - else => out.* = src.*, - } - return out; -} - -// =========================================================================== // Resolve // =========================================================================== @@ -956,26 +892,9 @@ pub fn parseModelRef(ref: []const u8) Error!ModelRef { } // =========================================================================== -// File / parse helpers +// Parse helpers // =========================================================================== -fn readFileAlloc(allocator: Allocator, io: Io, path: []const u8) (Allocator.Error || FileError)![]u8 { - const file = Io.Dir.cwd().openFile(io, path, .{ .mode = .read_only }) catch |err| switch (err) { - error.FileNotFound => return error.FileNotFound, - error.Canceled => return error.Canceled, - else => return error.ConfigReadFailed, - }; - defer file.close(io); - const len = file.length(io) catch return error.ConfigReadFailed; - const bytes = try allocator.alloc(u8, @intCast(len)); - errdefer allocator.free(bytes); - _ = file.readPositionalAll(io, bytes, 0) catch |err| switch (err) { - error.Canceled => return error.Canceled, - else => return error.ConfigReadFailed, - }; - return bytes; -} - fn parseDoc(allocator: Allocator, source: []const u8) !*toml.Document { const result = toml.parseWithError(allocator, source, .{}); switch (result) { |
