summaryrefslogtreecommitdiff
path: root/src/config_file.zig
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-06-23 09:38:23 -0600
committert <t@tjp.lol>2026-06-23 10:53:26 -0600
commit69a1ee138bb78ad4663fe2d9e58678f7b0d07b74 (patch)
tree453d3ad42a07536220e6ca5d91b439ff57793e32 /src/config_file.zig
parent538a5d926fa626a00cc3dc12c555f11f82867efd (diff)
ponytail simplifications to panto cli and lua extensiosn
Diffstat (limited to 'src/config_file.zig')
-rw-r--r--src/config_file.zig105
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) {