//! Implementation of the XDG Base Directory specification //! (https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) const std = @import("std"); const builtin = @import("builtin"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; const homedir = @import("homedir.zig"); pub const Options = struct { /// Subdirectories to join to the base. This avoids extra allocations /// when building up the directory. This is commonly the application. subdir: ?[]const u8 = null, /// The home directory for the user. If this is not set, we will attempt /// to look it up which is an expensive process. By setting this, you can /// avoid lookups. home: ?[]const u8 = null, }; /// Get the XDG user config directory. The returned value is allocated. pub fn config(alloc: Allocator, opts: Options) ![]u8 { if (std.os.getenv("XDG_CONFIG_HOME")) |env| { // If we have a subdir, then we use the env as-is to avoid a copy. if (opts.subdir) |subdir| { return try std.fs.path.join(alloc, &[_][]const u8{ env, subdir, }); } return try alloc.dupe(u8, env); } // If we have a cached home dir, use that. if (opts.home) |home| { return try std.fs.path.join(alloc, &[_][]const u8{ home, ".config", opts.subdir orelse "", }); } // Get our home dir var buf: [1024]u8 = undefined; if (try homedir.home(&buf)) |home| { return try std.fs.path.join(alloc, &[_][]const u8{ home, ".config", opts.subdir orelse "", }); } return error.NoHomeDir; } test { const testing = std.testing; const alloc = testing.allocator; { const value = try config(alloc, .{}); defer alloc.free(value); try testing.expect(value.len > 0); } }