diff --git a/modules/default.nix b/modules/default.nix index 4cba27ffb..9b6ad758d 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -19,6 +19,7 @@ let ./misc/news.nix ./misc/nixpkgs.nix ./misc/pam.nix + ./misc/xdg.nix ./programs/bash.nix ./programs/beets.nix ./programs/browserpass.nix diff --git a/modules/misc/xdg.nix b/modules/misc/xdg.nix new file mode 100644 index 000000000..941d51ed8 --- /dev/null +++ b/modules/misc/xdg.nix @@ -0,0 +1,138 @@ +{ options, config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.xdg; + + fileType = basePath: (types.loaOf (types.submodule ( + { name, config, ... }: { + options = { + target = mkOption { + type = types.str; + apply = p: "${cfg.configHome}/${p}"; + description = '' + Path to target file relative to ${basePath}. + ''; + }; + + text = mkOption { + default = null; + type = types.nullOr types.lines; + description = "Text of the file."; + }; + + source = mkOption { + type = types.path; + description = '' + Path of the source file. The file name must not start + with a period since Nix will not allow such names in + the Nix store. + + This may refer to a directory. + ''; + }; + + executable = mkOption { + type = types.bool; + default = false; + description = "Whether the file should be executable."; + }; + }; + + config = { + target = mkDefault name; + source = mkIf (config.text != null) ( + let + file = pkgs.writeTextFile { + inherit (config) text executable; + name = "user-etc-" + baseNameOf name; + }; + in + mkDefault file + ); + }; + } + ))); + + defaultCacheHome = "${config.home.homeDirectory}/.cache"; + defaultConfigHome = "${config.home.homeDirectory}/.config"; + defaultDataHome = "${config.home.homeDirectory}/.local/share"; + + getXdgDir = name: fallback: + let + value = builtins.getEnv name; + in + if value != "" then value else fallback; + +in + +{ + options.xdg = { + enable = mkEnableOption "management of XDG base directories"; + + cacheHome = mkOption { + type = types.path; + defaultText = "~/.cache"; + description = '' + Absolute path to directory holding application caches. + ''; + }; + + configFile = mkOption { + type = fileType "xdg.configHome"; + default = {}; + description = '' + Attribute set of files to link into the user's XDG + configuration home. + ''; + }; + + configHome = mkOption { + type = types.path; + defaultText = "~/.config"; + description = '' + Absolute path to directory holding application configurations. + ''; + }; + + dataHome = mkOption { + type = types.path; + defaultText = "~/.local/share"; + description = '' + Absolute path to directory holding application data. + ''; + }; + }; + + config = mkMerge [ + (mkIf cfg.enable { + xdg.cacheHome = mkDefault defaultCacheHome; + xdg.configHome = mkDefault defaultConfigHome; + xdg.dataHome = mkDefault defaultDataHome; + + home.sessionVariables = { + XDG_CACHE_HOME = cfg.cacheHome; + XDG_CONFIG_HOME = cfg.configHome; + XDG_DATA_HOME = cfg.dataHome; + }; + }) + + (mkIf (!cfg.enable) { + xdg.cacheHome = getXdgDir "XDG_CACHE_HOME" defaultCacheHome; + xdg.configHome = getXdgDir "XDG_CONFIG_HOME" defaultConfigHome; + xdg.dataHome = getXdgDir "XDG_DATA_HOME" defaultDataHome; + }) + + { + home.file = + let + f = n: v: { + inherit (v) source target; + mode = if v.executable then "777" else "444"; + }; + in mapAttrsToList f cfg.configFile; + } + ]; +}