{ config, lib, pkgs, ... }:
let
inherit (lib) mkOptionDefault mkIf mkOption types;
cfg = config.xdg;
fileType = (import ../lib/file-type.nix {
inherit (config.home) homeDirectory;
inherit lib pkgs;
}).fileType;
defaultCacheHome = "${config.home.homeDirectory}/.cache";
defaultConfigHome = "${config.home.homeDirectory}/.config";
defaultDataHome = "${config.home.homeDirectory}/.local/share";
defaultStateHome = "${config.home.homeDirectory}/.local/state";
getEnvFallback = name: fallback:
let value = builtins.getEnv name;
in if value != "" then value else fallback;
in {
options.xdg = {
enable = lib.mkEnableOption "management of XDG base directories";
cacheFile = mkOption {
type = fileType "xdg.cacheFile" "{var}`xdg.cacheHome`" cfg.cacheHome;
default = { };
description = ''
Attribute set of files to link into the user's XDG
cache home.
'';
};
cacheHome = mkOption {
type = types.path;
defaultText = "~/.cache";
apply = toString;
description = ''
Absolute path to directory holding application caches.
Sets `XDG_CACHE_HOME` for the user if `xdg.enable` is set `true`.
'';
};
configFile = mkOption {
type = fileType "xdg.configFile" "{var}`xdg.configHome`" cfg.configHome;
default = { };
description = ''
Attribute set of files to link into the user's XDG
configuration home.
'';
};
configHome = mkOption {
type = types.path;
defaultText = "~/.config";
apply = toString;
description = ''
Absolute path to directory holding application configurations.
Sets `XDG_CONFIG_HOME` for the user if `xdg.enable` is set `true`.
'';
};
dataFile = mkOption {
type =
fileType "xdg.dataFile" "xdg.dataHome" cfg.dataHome;
default = { };
description = ''
Attribute set of files to link into the user's XDG
data home.
'';
};
dataHome = mkOption {
type = types.path;
defaultText = "~/.local/share";
apply = toString;
description = ''
Absolute path to directory holding application data.
Sets `XDG_DATA_HOME` for the user if `xdg.enable` is set `true`.
'';
};
stateFile = mkOption {
type = fileType "xdg.stateFile" "xdg.stateHome"
cfg.stateHome;
default = { };
description = ''
Attribute set of files to link into the user's XDG
state home.
'';
};
stateHome = mkOption {
type = types.path;
defaultText = "~/.local/state";
apply = toString;
description = ''
Absolute path to directory holding application states.
Sets `XDG_STATE_HOME` for the user if `xdg.enable` is set `true`.
'';
};
};
config = lib.mkMerge [
(let
variables = {
XDG_CACHE_HOME = cfg.cacheHome;
XDG_CONFIG_HOME = cfg.configHome;
XDG_DATA_HOME = cfg.dataHome;
XDG_STATE_HOME = cfg.stateHome;
};
in mkIf cfg.enable {
xdg.cacheHome = mkOptionDefault defaultCacheHome;
xdg.configHome = mkOptionDefault defaultConfigHome;
xdg.dataHome = mkOptionDefault defaultDataHome;
xdg.stateHome = mkOptionDefault defaultStateHome;
home.sessionVariables = variables;
systemd.user.sessionVariables =
mkIf pkgs.stdenv.hostPlatform.isLinux variables;
})
# Legacy non-deterministic setup.
(mkIf (!cfg.enable && lib.versionOlder config.home.stateVersion "20.09") {
xdg.cacheHome =
mkOptionDefault (getEnvFallback "XDG_CACHE_HOME" defaultCacheHome);
xdg.configHome =
mkOptionDefault (getEnvFallback "XDG_CONFIG_HOME" defaultConfigHome);
xdg.dataHome =
mkOptionDefault (getEnvFallback "XDG_DATA_HOME" defaultDataHome);
xdg.stateHome =
mkOptionDefault (getEnvFallback "XDG_STATE_HOME" defaultStateHome);
})
# "Modern" deterministic setup.
(mkIf (!cfg.enable && lib.versionAtLeast config.home.stateVersion "20.09") {
xdg.cacheHome = mkOptionDefault defaultCacheHome;
xdg.configHome = mkOptionDefault defaultConfigHome;
xdg.dataHome = mkOptionDefault defaultDataHome;
xdg.stateHome = mkOptionDefault defaultStateHome;
})
{
home.file = lib.mkMerge [
(lib.mapAttrs'
(name: file: lib.nameValuePair "${cfg.cacheHome}/${name}" file)
cfg.cacheFile)
(lib.mapAttrs'
(name: file: lib.nameValuePair "${cfg.configHome}/${name}" file)
cfg.configFile)
(lib.mapAttrs'
(name: file: lib.nameValuePair "${cfg.dataHome}/${name}" file)
cfg.dataFile)
(lib.mapAttrs'
(name: file: lib.nameValuePair "${cfg.stateHome}/${name}" file)
cfg.stateFile)
{ "${cfg.cacheHome}/.keep".text = ""; }
{ "${cfg.stateHome}/.keep".text = ""; }
];
}
];
}