summaryrefslogtreecommitdiff
path: root/src/user_config.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-11 15:58:58 -0300
committerGabriel Schneider <[email protected]>2026-08-11 16:26:20 -0300
commit4ca28745d774c232cd31a29c17878f19bbe24cf5 (patch)
treeface852acae5bc347e6bab2bb5cede501e0ce1d3 /src/user_config.zig
parentdedfdea43f0d6c7151c541284c81027969d89032 (diff)
parent89d93d5e7348304bc7d8a148f9ad9c1beb200459 (diff)
downloadpardes-4ca28745d774c232cd31a29c17878f19bbe24cf5.tar.gz
pardes-4ca28745d774c232cd31a29c17878f19bbe24cf5.zip
merge the macOS app branch: the AppKit shell, pixel attachments, live theming, and mupdf -Djpx
Three commits off 38e9919 (macos-app@upstream) merged into main's ghostty bump. No textual conflicts, and two things the merge needed: - nested.zig asked libc for fstatat. Darwin has it; on linux std.c declares it `void` (glibc hides it behind a versioned symbol std cannot name), so the tty build stopped at 'type void not a function'. statNoFollow keeps fstatat on darwin and asks statx on linux for the same three fields, which is what this file did before the branch generalized it to both platforms. - .DS_Store rode along with a797a1a. Deleted, and .gitignore now says so. linux: snap 86/86, unit-test, image-harness and mupdf-check green. nested.zig also type-checks for aarch64-macos.
Diffstat (limited to 'src/user_config.zig')
-rw-r--r--src/user_config.zig37
1 files changed, 26 insertions, 11 deletions
diff --git a/src/user_config.zig b/src/user_config.zig
index 455e8a3c..389188c1 100644
--- a/src/user_config.zig
+++ b/src/user_config.zig
@@ -31,17 +31,26 @@ pub fn path(gpa: std.mem.Allocator, env: *const std.process.Environ.Map) !?[]u8
return try std.fs.path.join(gpa, &.{ home, ".config", "pardes" });
}
-/// Missing, unreadable, oversized, or otherwise unusable config is simply no
-/// config. The arena passed by main owns successful bytes for the process.
+/// The config file: WHERE it was looked for, and what was there. Missing,
+/// unreadable, oversized, or otherwise unusable config is simply no config —
+/// but the path resolves either way, because "nothing is there yet" is the
+/// answer the Config builtin exists to give and a null would erase it. The
+/// arena passed by the launcher owns both for the process.
+pub const Found = struct {
+ path: ?[]const u8 = null,
+ bytes: ?[]const u8 = null,
+};
+
pub fn load(
io: std.Io,
gpa: std.mem.Allocator,
env: *const std.process.Environ.Map,
-) ?[]u8 {
- const config_path = path(gpa, env) catch return null;
- defer if (config_path) |p| gpa.free(p);
- const p = config_path orelse return null;
- return std.Io.Dir.cwd().readFileAlloc(io, p, gpa, .limited(max_bytes)) catch null;
+) Found {
+ const config_path = (path(gpa, env) catch return .{}) orelse return .{};
+ return .{
+ .path = config_path,
+ .bytes = std.Io.Dir.cwd().readFileAlloc(io, config_path, gpa, .limited(max_bytes)) catch null,
+ };
}
fn nonEmpty(value: ?[]const u8) ?[]const u8 {
@@ -88,10 +97,16 @@ test "config loader is silent when missing and returns exact file bytes" {
defer env.deinit();
try env.put("XDG_CONFIG_HOME", base_buf[0..base_len]);
- try std.testing.expect(load(std.testing.io, std.testing.allocator, &env) == null);
+ const missing = load(std.testing.io, std.testing.allocator, &env);
+ defer std.testing.allocator.free(missing.path.?);
+ const expected = try std.fs.path.join(std.testing.allocator, &.{ base_buf[0..base_len], "pardes" });
+ defer std.testing.allocator.free(expected);
+ try std.testing.expectEqualStrings(expected, missing.path.?);
+ try std.testing.expect(missing.bytes == null);
const source = "Theme dark\nUnknown command\nTheme acme\n";
try tmp.dir.writeFile(std.testing.io, .{ .sub_path = "pardes", .data = source });
- const bytes = load(std.testing.io, std.testing.allocator, &env).?;
- defer std.testing.allocator.free(bytes);
- try std.testing.expectEqualStrings(source, bytes);
+ const found = load(std.testing.io, std.testing.allocator, &env);
+ defer std.testing.allocator.free(found.path.?);
+ defer std.testing.allocator.free(found.bytes.?);
+ try std.testing.expectEqualStrings(source, found.bytes.?);
}