{ 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 = ""; } ]; } ]; }