os: add xdg cache dir function

This commit is contained in:
Mitchell Hashimoto
2024-08-27 18:56:33 -07:00
parent 42b3ee8df2
commit 7f143d9df4

View File

@ -21,17 +21,45 @@ pub const Options = struct {
/// Get the XDG user config directory. The returned value is allocated. /// Get the XDG user config directory. The returned value is allocated.
pub fn config(alloc: Allocator, opts: Options) ![]u8 { pub fn config(alloc: Allocator, opts: Options) ![]u8 {
return try dir(alloc, opts, .{
.env = "XDG_CONFIG_HOME",
.windows_env = "LOCALAPPDATA",
.default_subdir = ".config",
});
}
/// Get the XDG cache directory. The returned value is allocated.
pub fn cache(alloc: Allocator, opts: Options) ![]u8 {
return try dir(alloc, opts, .{
.env = "XDG_CACHE_HOME",
.windows_env = "LOCALAPPDATA",
.default_subdir = ".cache",
});
}
const InternalOptions = struct {
env: []const u8,
windows_env: []const u8,
default_subdir: []const u8,
};
/// Unified helper to get XDG directories that follow a common pattern.
fn dir(
alloc: Allocator,
opts: Options,
internal_opts: InternalOptions,
) ![]u8 {
// First check the env var. On Windows we have to allocate so this tracks // First check the env var. On Windows we have to allocate so this tracks
// both whether we have the env var and whether we own it. // both whether we have the env var and whether we own it.
// on Windows we treat `LOCALAPPDATA` as a fallback for `XDG_CONFIG_HOME` // on Windows we treat `LOCALAPPDATA` as a fallback for `XDG_CONFIG_HOME`
const env_, const owned = switch (builtin.os.tag) { const env_, const owned = switch (builtin.os.tag) {
else => .{ posix.getenv("XDG_CONFIG_HOME"), false }, else => .{ posix.getenv(internal_opts.env), false },
.windows => windows: { .windows => windows: {
if (std.process.getEnvVarOwned(alloc, "XDG_CONFIG_HOME")) |env| { if (std.process.getEnvVarOwned(alloc, internal_opts.env)) |env| {
break :windows .{ env, true }; break :windows .{ env, true };
} else |err| switch (err) { } else |err| switch (err) {
error.EnvironmentVariableNotFound => { error.EnvironmentVariableNotFound => {
if (std.process.getEnvVarOwned(alloc, "LOCALAPPDATA")) |env| { if (std.process.getEnvVarOwned(alloc, internal_opts.windows_env)) |env| {
break :windows .{ env, true }; break :windows .{ env, true };
} else |err2| switch (err2) { } else |err2| switch (err2) {
error.EnvironmentVariableNotFound => break :windows .{ null, false }, error.EnvironmentVariableNotFound => break :windows .{ null, false },
@ -60,7 +88,7 @@ pub fn config(alloc: Allocator, opts: Options) ![]u8 {
if (opts.home) |home| { if (opts.home) |home| {
return try std.fs.path.join(alloc, &[_][]const u8{ return try std.fs.path.join(alloc, &[_][]const u8{
home, home,
".config", internal_opts.default_subdir,
opts.subdir orelse "", opts.subdir orelse "",
}); });
} }
@ -70,7 +98,7 @@ pub fn config(alloc: Allocator, opts: Options) ![]u8 {
if (try homedir.home(&buf)) |home| { if (try homedir.home(&buf)) |home| {
return try std.fs.path.join(alloc, &[_][]const u8{ return try std.fs.path.join(alloc, &[_][]const u8{
home, home,
".config", internal_opts.default_subdir,
opts.subdir orelse "", opts.subdir orelse "",
}); });
} }