mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
Merge 65f3ab2c2fde47fec5200734199e9d5b4ec5ca80 into e7cbb7fd160ddcd3a89d6156310c12a5a9da48ef
This commit is contained in:
@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
_\$XDG_CONFIG_HOME/ghostty/config_
|
_\$XDG_CONFIG_HOME/ghostty/config_
|
||||||
|
|
||||||
: Location of the default configuration file.
|
: Location of the default user configuration file.
|
||||||
|
|
||||||
|
_\$XDG_CONFIG_DIRS/ghostty/config_
|
||||||
|
|
||||||
|
: Location of the default system configuration files.
|
||||||
|
|
||||||
_\$LOCALAPPDATA/ghostty/config_
|
_\$LOCALAPPDATA/ghostty/config_
|
||||||
|
|
||||||
@ -23,6 +27,10 @@ for configuration files.
|
|||||||
|
|
||||||
: Default location for configuration files.
|
: Default location for configuration files.
|
||||||
|
|
||||||
|
**XDG_CONFIG_DIRS**
|
||||||
|
|
||||||
|
: Colon separated list of paths to load configuration files.
|
||||||
|
|
||||||
**LOCALAPPDATA**
|
**LOCALAPPDATA**
|
||||||
|
|
||||||
: **WINDOWS ONLY:** alternate location to search for configuration files.
|
: **WINDOWS ONLY:** alternate location to search for configuration files.
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
_\$XDG_CONFIG_HOME/ghostty/config_
|
_\$XDG_CONFIG_HOME/ghostty/config_
|
||||||
|
|
||||||
: Location of the default configuration file.
|
: Location of the default user configuration file.
|
||||||
|
|
||||||
|
_\$XDG_CONFIG_DIRS/ghostty/config_
|
||||||
|
|
||||||
|
: Location of the default system configuration files.
|
||||||
|
|
||||||
_\$LOCALAPPDATA/ghostty/config_
|
_\$LOCALAPPDATA/ghostty/config_
|
||||||
|
|
||||||
@ -15,6 +19,10 @@ for configuration files.
|
|||||||
|
|
||||||
: Default location for configuration files.
|
: Default location for configuration files.
|
||||||
|
|
||||||
|
**XDG_CONFIG_DIRS**
|
||||||
|
|
||||||
|
: Colon separated list of paths to load configuration files.
|
||||||
|
|
||||||
**LOCALAPPDATA**
|
**LOCALAPPDATA**
|
||||||
|
|
||||||
: **WINDOWS ONLY:** alternate location to search for configuration files.
|
: **WINDOWS ONLY:** alternate location to search for configuration files.
|
||||||
|
@ -1548,8 +1548,10 @@ keybind: Keybinds = .{},
|
|||||||
@"config-file": RepeatablePath = .{},
|
@"config-file": RepeatablePath = .{},
|
||||||
|
|
||||||
/// When this is true, the default configuration file paths will be loaded.
|
/// When this is true, the default configuration file paths will be loaded.
|
||||||
/// The default configuration file paths are currently only the XDG
|
/// The default configuration files are at ./ghostty/config,
|
||||||
/// config path ($XDG_CONFIG_HOME/ghostty/config).
|
/// in each of the colon seperated directories in $XDG_CONFIG_DIRS, and,
|
||||||
|
/// the xdg user config directory $XDG_CONFIG_HOME
|
||||||
|
/// (/etc/xdg and ~/.config if these environment variables are not set).
|
||||||
///
|
///
|
||||||
/// If this is false, the default configuration paths will not be loaded.
|
/// If this is false, the default configuration paths will not be loaded.
|
||||||
/// This is targeted directly at using Ghostty from the CLI in a way
|
/// This is targeted directly at using Ghostty from the CLI in a way
|
||||||
@ -3074,20 +3076,32 @@ fn writeConfigTemplate(path: []const u8) !void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load configurations from the default configuration files. The default
|
/// Load configurations from the default configuration files.
|
||||||
/// configuration file is at `$XDG_CONFIG_HOME/ghostty/config`.
|
/// The default system configuration files are at `$XDG_CONFIG_DIRS/ghostty/config`.
|
||||||
|
/// The default user configuration file is at `$XDG_CONFIG_HOME/ghostty/config`.
|
||||||
///
|
///
|
||||||
/// On macOS, `$HOME/Library/Application Support/$CFBundleIdentifier/config`
|
/// On macOS, `$HOME/Library/Application Support/$CFBundleIdentifier/config`
|
||||||
/// is also loaded.
|
/// is also loaded.
|
||||||
pub fn loadDefaultFiles(self: *Config, alloc: Allocator) !void {
|
pub fn loadDefaultFiles(self: *Config, alloc: Allocator) !void {
|
||||||
// Load XDG first
|
const config_dir = "ghostty";
|
||||||
const xdg_path = try internal_os.xdg.config(alloc, .{ .subdir = "ghostty/config" });
|
const config_file = "config";
|
||||||
defer alloc.free(xdg_path);
|
const config_subdir = try std.fs.path.join(alloc, &[_][]const u8{
|
||||||
const xdg_action = self.loadOptionalFile(alloc, xdg_path);
|
config_dir,
|
||||||
|
config_file,
|
||||||
|
});
|
||||||
|
defer alloc.free(config_subdir);
|
||||||
|
var it = internal_os.xdg.Dir.config.iter(alloc, .{ .subdir = config_subdir });
|
||||||
|
var xdg_action: ?OptionalFileAction = null;
|
||||||
|
var xdg_path: ?[]const u8 = null;
|
||||||
|
while (try it.next()) |dir| {
|
||||||
|
defer alloc.free(dir);
|
||||||
|
xdg_path = dir;
|
||||||
|
xdg_action = self.loadOptionalFile(alloc, dir);
|
||||||
|
}
|
||||||
|
|
||||||
// On macOS load the app support directory as well
|
// On macOS load the app support directory as well
|
||||||
if (comptime builtin.os.tag == .macos) {
|
if (comptime builtin.os.tag == .macos) {
|
||||||
const app_support_path = try internal_os.macos.appSupportDir(alloc, "config");
|
const app_support_path = try internal_os.macos.appSupportDir(alloc, config_file);
|
||||||
defer alloc.free(app_support_path);
|
defer alloc.free(app_support_path);
|
||||||
const app_support_action = self.loadOptionalFile(alloc, app_support_path);
|
const app_support_action = self.loadOptionalFile(alloc, app_support_path);
|
||||||
|
|
||||||
@ -3100,9 +3114,10 @@ pub fn loadDefaultFiles(self: *Config, alloc: Allocator) !void {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (xdg_action == .not_found) {
|
if (xdg_action == .not_found) {
|
||||||
writeConfigTemplate(xdg_path) catch |err| {
|
if (xdg_path) |p|
|
||||||
log.warn("error creating template config file err={}", .{err});
|
writeConfigTemplate(p) catch |err| {
|
||||||
};
|
log.warn("error creating template config file err={}", .{err});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,9 +98,11 @@ fn configPathCandidates(alloc_arena: Allocator) ![]const []const u8 {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
paths.appendAssumeCapacity(try internal_os.xdg.config(
|
const subdir = try std.fs.path.join(alloc_arena, &[_][]const u8{ "ghostty", "config" });
|
||||||
|
defer alloc_arena.free(subdir);
|
||||||
|
paths.appendAssumeCapacity(try internal_os.xdg.UserDir.config.path(
|
||||||
alloc_arena,
|
alloc_arena,
|
||||||
.{ .subdir = "ghostty/config" },
|
.{ .subdir = subdir },
|
||||||
));
|
));
|
||||||
|
|
||||||
return paths.items;
|
return paths.items;
|
||||||
|
@ -31,7 +31,7 @@ pub const Location = enum {
|
|||||||
"ghostty", "themes",
|
"ghostty", "themes",
|
||||||
}) catch return error.OutOfMemory;
|
}) catch return error.OutOfMemory;
|
||||||
|
|
||||||
break :user internal_os.xdg.config(
|
break :user internal_os.xdg.UserDir.config.path(
|
||||||
arena_alloc,
|
arena_alloc,
|
||||||
.{ .subdir = subdir },
|
.{ .subdir = subdir },
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
|
@ -6,7 +6,9 @@ const internal_os = @import("../os/main.zig");
|
|||||||
/// Returns a Dir for the default directory. The Dir.path field must be
|
/// Returns a Dir for the default directory. The Dir.path field must be
|
||||||
/// freed with the given allocator.
|
/// freed with the given allocator.
|
||||||
pub fn defaultDir(alloc: Allocator) !Dir {
|
pub fn defaultDir(alloc: Allocator) !Dir {
|
||||||
const crash_dir = try internal_os.xdg.state(alloc, .{ .subdir = "ghostty/crash" });
|
const subdir = try std.fs.path.join(alloc, &[_][]const u8{ "ghostty", "crash" });
|
||||||
|
defer alloc.free(subdir);
|
||||||
|
const crash_dir = try internal_os.xdg.UserDir.state.path(alloc, .{ .subdir = subdir });
|
||||||
errdefer alloc.free(crash_dir);
|
errdefer alloc.free(crash_dir);
|
||||||
return .{ .path = crash_dir };
|
return .{ .path = crash_dir };
|
||||||
}
|
}
|
||||||
|
185
src/os/xdg.zig
185
src/os/xdg.zig
@ -19,33 +19,6 @@ pub const Options = struct {
|
|||||||
home: ?[]const u8 = null,
|
home: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Get the XDG user config directory. The returned value is allocated.
|
|
||||||
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",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the XDG state directory. The returned value is allocated.
|
|
||||||
pub fn state(alloc: Allocator, opts: Options) ![]u8 {
|
|
||||||
return try dir(alloc, opts, .{
|
|
||||||
.env = "XDG_STATE_HOME",
|
|
||||||
.windows_env = "LOCALAPPDATA",
|
|
||||||
.default_subdir = ".local/state",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const InternalOptions = struct {
|
const InternalOptions = struct {
|
||||||
env: []const u8,
|
env: []const u8,
|
||||||
windows_env: []const u8,
|
windows_env: []const u8,
|
||||||
@ -115,6 +88,43 @@ fn dir(
|
|||||||
return error.NoHomeDir;
|
return error.NoHomeDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// XDG user directories for program config, data, cache, or, state
|
||||||
|
pub const UserDir = enum {
|
||||||
|
config,
|
||||||
|
data,
|
||||||
|
cache,
|
||||||
|
state,
|
||||||
|
|
||||||
|
pub fn path(
|
||||||
|
self: UserDir,
|
||||||
|
alloc: Allocator,
|
||||||
|
opts: Options,
|
||||||
|
) ![]u8 {
|
||||||
|
const internal_opts: InternalOptions = switch (self) {
|
||||||
|
.config => .{
|
||||||
|
.env = "XDG_CONFIG_HOME",
|
||||||
|
.windows_env = "LOCALAPPDATA",
|
||||||
|
.default_subdir = ".config",
|
||||||
|
},
|
||||||
|
.data => .{
|
||||||
|
.env = "XDG_DATA_HOME",
|
||||||
|
.windows_env = "LOCALAPPDATA", // unclear what to use
|
||||||
|
.default_subdir = ".local/share",
|
||||||
|
},
|
||||||
|
.cache => .{
|
||||||
|
.env = "XDG_CACHE_HOME",
|
||||||
|
.windows_env = "LOCALAPPDATA", // also unclear
|
||||||
|
.default_subdir = ".cache",
|
||||||
|
},
|
||||||
|
.state => .{
|
||||||
|
.env = "XDG_STATE_HOME",
|
||||||
|
.windows_env = "LOCALAPPDATA", // again ...
|
||||||
|
.default_subdir = ".local/state",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return dir(alloc, opts, internal_opts);
|
||||||
|
}
|
||||||
|
};
|
||||||
/// Parses the xdg-terminal-exec specification. This expects argv[0] to
|
/// Parses the xdg-terminal-exec specification. This expects argv[0] to
|
||||||
/// be "xdg-terminal-exec".
|
/// be "xdg-terminal-exec".
|
||||||
pub fn parseTerminalExec(argv: []const [*:0]const u8) ?[]const [*:0]const u8 {
|
pub fn parseTerminalExec(argv: []const [*:0]const u8) ?[]const [*:0]const u8 {
|
||||||
@ -137,7 +147,7 @@ test {
|
|||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
{
|
{
|
||||||
const value = try config(alloc, .{});
|
const value = try UserDir.config.path(alloc, .{});
|
||||||
defer alloc.free(value);
|
defer alloc.free(value);
|
||||||
try testing.expect(value.len > 0);
|
try testing.expect(value.len > 0);
|
||||||
}
|
}
|
||||||
@ -152,14 +162,14 @@ test "cache directory paths" {
|
|||||||
{
|
{
|
||||||
// Test base path
|
// Test base path
|
||||||
{
|
{
|
||||||
const cache_path = try cache(alloc, .{ .home = mock_home });
|
const cache_path = try UserDir.cache.path(alloc, .{ .home = mock_home });
|
||||||
defer alloc.free(cache_path);
|
defer alloc.free(cache_path);
|
||||||
try testing.expectEqualStrings("/Users/test/.cache", cache_path);
|
try testing.expectEqualStrings("/Users/test/.cache", cache_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test with subdir
|
// Test with subdir
|
||||||
{
|
{
|
||||||
const cache_path = try cache(alloc, .{
|
const cache_path = try UserDir.cache.path(alloc, .{
|
||||||
.home = mock_home,
|
.home = mock_home,
|
||||||
.subdir = "ghostty",
|
.subdir = "ghostty",
|
||||||
});
|
});
|
||||||
@ -193,3 +203,118 @@ test parseTerminalExec {
|
|||||||
try testing.expectEqualSlices([*:0]const u8, actual, &.{ "a", "-e", "b", "c" });
|
try testing.expectEqualSlices([*:0]const u8, actual, &.{ "a", "-e", "b", "c" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterator over XDG directories system directories and user directories
|
||||||
|
/// wraps SystemDirIterator using any values from that iterator and then
|
||||||
|
/// the path from UserDir.path()
|
||||||
|
const DirIterator = struct {
|
||||||
|
index: usize,
|
||||||
|
alloc: Allocator,
|
||||||
|
opts: Options,
|
||||||
|
user_dir: UserDir,
|
||||||
|
sys_dir_it: SystemDirIterator,
|
||||||
|
const Self = @This();
|
||||||
|
pub fn next(self: *Self) !?[]const u8 {
|
||||||
|
// TODO ignore relative paths where
|
||||||
|
// path[0] != "/" and path not contains "/../?"
|
||||||
|
if (self.sys_dir_it.next()) |path| {
|
||||||
|
return try std.fs.path.join(self.alloc, &[_][]const u8{
|
||||||
|
path,
|
||||||
|
self.opts.subdir orelse "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.index += 1;
|
||||||
|
if (self.index == 1) return try self.user_dir.path(self.alloc, self.opts);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// System and home directories for program configs and data,
|
||||||
|
/// these are the environment variables $XDG_CONFIG_DIRS:$XDG_CONFIG_HOME, and,
|
||||||
|
/// $XDG_DATA_DIRS:$XDG_DATA_HOME respectively
|
||||||
|
pub const Dir = enum {
|
||||||
|
config,
|
||||||
|
data,
|
||||||
|
|
||||||
|
pub fn iter(self: Dir, alloc: Allocator, opts: Options) DirIterator {
|
||||||
|
const sys_dir: SystemDir = @enumFromInt(@intFromEnum(self));
|
||||||
|
const user_dir: UserDir = @enumFromInt(@intFromEnum(self));
|
||||||
|
return .{ .index = 0, .alloc = alloc, .opts = opts, .sys_dir_it = sys_dir.iter(), .user_dir = user_dir };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Iterator over system directories in order from least importance to most
|
||||||
|
/// importance, reverse order to how they are defined in XDG_*_DIRS
|
||||||
|
const SystemDirIterator = struct {
|
||||||
|
data: []const u8,
|
||||||
|
iterator: std.mem.SplitBackwardsIterator(u8, .scalar),
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub fn next(self: *Self) ?[]const u8 {
|
||||||
|
return self.iterator.next();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// XDG system directory for program configs or data
|
||||||
|
pub const SystemDir = enum {
|
||||||
|
config,
|
||||||
|
data,
|
||||||
|
|
||||||
|
pub fn key(self: SystemDir) [:0]const u8 {
|
||||||
|
return switch (self) {
|
||||||
|
.config => "XDG_CONFIG_DIRS",
|
||||||
|
.data => "XDG_DATA_DIRS",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default(self: SystemDir) [:0]const u8 {
|
||||||
|
return switch (self) {
|
||||||
|
.config => "/etc/xdg",
|
||||||
|
.data => "/usr/local/share:/usr/share",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(self: SystemDir) SystemDirIterator {
|
||||||
|
const data = data: {
|
||||||
|
if (posix.getenv(self.key())) |data| {
|
||||||
|
if (std.mem.trim(u8, data, &std.ascii.whitespace).len > 0)
|
||||||
|
break :data data;
|
||||||
|
}
|
||||||
|
break :data self.default();
|
||||||
|
};
|
||||||
|
return .{
|
||||||
|
.data = data,
|
||||||
|
.iterator = std.mem.splitBackwardsScalar(u8, data, ':'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test "xdg dirs" {
|
||||||
|
const c = @cImport({
|
||||||
|
@cInclude("stdlib.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
const testing = std.testing;
|
||||||
|
{
|
||||||
|
_ = c.unsetenv(SystemDir.config.key());
|
||||||
|
var it = SystemDir.config.iter();
|
||||||
|
try testing.expectEqualStrings("/etc/xdg", it.next().?);
|
||||||
|
try testing.expect(it.next() == null);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
_ = c.unsetenv(SystemDir.data.key());
|
||||||
|
var it = SystemDir.data.iter();
|
||||||
|
try testing.expectEqualStrings("/usr/share", it.next().?);
|
||||||
|
try testing.expectEqualStrings("/usr/local/share", it.next().?);
|
||||||
|
try testing.expect(it.next() == null);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
_ = c.setenv(SystemDir.config.key(), "a:b:c", 1);
|
||||||
|
var it = SystemDir.config.iter();
|
||||||
|
try testing.expectEqualStrings("c", it.next().?);
|
||||||
|
try testing.expectEqualStrings("b", it.next().?);
|
||||||
|
try testing.expectEqualStrings("a", it.next().?);
|
||||||
|
try testing.expect(it.next() == null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@ const configpkg = @import("../config.zig");
|
|||||||
const crash = @import("../crash/main.zig");
|
const crash = @import("../crash/main.zig");
|
||||||
const fastmem = @import("../fastmem.zig");
|
const fastmem = @import("../fastmem.zig");
|
||||||
const internal_os = @import("../os/main.zig");
|
const internal_os = @import("../os/main.zig");
|
||||||
|
const xdg = internal_os.xdg;
|
||||||
const renderer = @import("../renderer.zig");
|
const renderer = @import("../renderer.zig");
|
||||||
const shell_integration = @import("shell_integration.zig");
|
const shell_integration = @import("shell_integration.zig");
|
||||||
const terminal = @import("../terminal/main.zig");
|
const terminal = @import("../terminal/main.zig");
|
||||||
@ -802,18 +803,17 @@ const Subprocess = struct {
|
|||||||
|
|
||||||
var buf: [std.fs.max_path_bytes]u8 = undefined;
|
var buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||||
|
|
||||||
const xdg_data_dir_key = "XDG_DATA_DIRS";
|
|
||||||
if (std.fmt.bufPrint(&buf, "{s}/..", .{resources_dir})) |data_dir| {
|
if (std.fmt.bufPrint(&buf, "{s}/..", .{resources_dir})) |data_dir| {
|
||||||
try env.put(
|
try env.put(
|
||||||
xdg_data_dir_key,
|
xdg.SystemDir.data.key(),
|
||||||
try internal_os.appendEnv(
|
try internal_os.appendEnv(
|
||||||
alloc,
|
alloc,
|
||||||
env.get(xdg_data_dir_key) orelse "/usr/local/share:/usr/share",
|
env.get(xdg.SystemDir.data.key()) orelse xdg.SystemDir.data.default(),
|
||||||
data_dir,
|
data_dir,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else |err| {
|
} else |err| {
|
||||||
log.warn("error building {s}; err={}", .{ xdg_data_dir_key, err });
|
log.warn("error building {s}; err={}", .{ xdg.SystemDir.data.key(), err });
|
||||||
}
|
}
|
||||||
|
|
||||||
const manpath_key = "MANPATH";
|
const manpath_key = "MANPATH";
|
||||||
|
@ -6,6 +6,7 @@ const EnvMap = std.process.EnvMap;
|
|||||||
const config = @import("../config.zig");
|
const config = @import("../config.zig");
|
||||||
const homedir = @import("../os/homedir.zig");
|
const homedir = @import("../os/homedir.zig");
|
||||||
const internal_os = @import("../os/main.zig");
|
const internal_os = @import("../os/main.zig");
|
||||||
|
const xdg = internal_os.xdg;
|
||||||
|
|
||||||
const log = std.log.scoped(.shell_integration);
|
const log = std.log.scoped(.shell_integration);
|
||||||
|
|
||||||
@ -492,12 +493,11 @@ fn setupXdgDataDirs(
|
|||||||
// This ensures that the default directories aren't lost by setting
|
// This ensures that the default directories aren't lost by setting
|
||||||
// our desired integration dir directly. See #2711.
|
// our desired integration dir directly. See #2711.
|
||||||
// <https://specifications.freedesktop.org/basedir-spec/0.6/#variables>
|
// <https://specifications.freedesktop.org/basedir-spec/0.6/#variables>
|
||||||
const xdg_data_dirs_key = "XDG_DATA_DIRS";
|
|
||||||
try env.put(
|
try env.put(
|
||||||
xdg_data_dirs_key,
|
xdg.SystemDir.data.key(),
|
||||||
try internal_os.prependEnv(
|
try internal_os.prependEnv(
|
||||||
stack_alloc,
|
stack_alloc,
|
||||||
env.get(xdg_data_dirs_key) orelse "/usr/local/share:/usr/share",
|
env.get(xdg.SystemDir.data.key()) orelse xdg.SystemDir.data.default(),
|
||||||
integ_dir,
|
integ_dir,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user