diff --git a/home-manager/home-manager b/home-manager/home-manager index 1a5676e5..d3ef4dfc 100644 --- a/home-manager/home-manager +++ b/home-manager/home-manager @@ -26,8 +26,9 @@ function setConfigFile() { return fi + local defaultConfFile="${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home.nix" local confFile - for confFile in "$HOME/.config/nixpkgs/home.nix" \ + for confFile in "$defaultConfFile" \ "$HOME/.nixpkgs/home.nix" ; do if [[ -e "$confFile" ]] ; then HOME_MANAGER_CONFIG="$confFile" @@ -36,14 +37,14 @@ function setConfigFile() { done errorEcho "No configuration file found." \ - "Please create one at ~/.config/nixpkgs/home.nix" + "Please create one at $defaultConfFile" exit 1 } function setHomeManagerNixPath() { local path for path in "@HOME_MANAGER_PATH@" \ - "$HOME/.config/nixpkgs/home-manager" \ + "${XDG_CONFIG_HOME:-$HOME/.config}/nixpkgs/home-manager" \ "$HOME/.nixpkgs/home-manager" ; do if [[ -e "$path" || "$path" =~ ^https?:// ]] ; then export NIX_PATH="$NIX_PATH${NIX_PATH:+:}home-manager=$path" diff --git a/modules/default.nix b/modules/default.nix index 4cba27ff..9b6ad758 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/fontconfig.nix b/modules/misc/fontconfig.nix index aab29b67..e76e135e 100644 --- a/modules/misc/fontconfig.nix +++ b/modules/misc/fontconfig.nix @@ -29,7 +29,7 @@ in }; config = mkIf cfg.enableProfileFonts { - home.file.".config/fontconfig/conf.d/10-nix-profile-fonts.conf".text = '' + xdg.configFile."fontconfig/conf.d/10-nix-profile-fonts.conf".text = '' diff --git a/modules/misc/gtk.nix b/modules/misc/gtk.nix index a95e8d6e..f0fc8b1a 100644 --- a/modules/misc/gtk.nix +++ b/modules/misc/gtk.nix @@ -124,10 +124,10 @@ in mapAttrsToList formatGtk2Option ini ) + "\n" + cfg2.extraConfig; - home.file.".config/gtk-3.0/settings.ini".text = + xdg.configFile."gtk-3.0/settings.ini".text = toGtk3Ini { Settings = ini // cfg3.extraConfig; }; - home.file.".config/gtk-3.0/gtk.css".text = cfg3.extraCss; + xdg.configFile."gtk-3.0/gtk.css".text = cfg3.extraCss; } ); } diff --git a/modules/misc/news.nix b/modules/misc/news.nix index dc546ed0..eb25444e 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -422,6 +422,31 @@ in commands run outside Home Manager. ''; } + + { + time = "2017-10-28T23:39:55+00:00"; + message = '' + A new module is available: 'xdg'. + + If enabled, this module allows configuration of the XDG base + directory paths. + + Whether the module is enabled or not, it also offers the + option 'xdg.configFile', which acts much like 'home.file' + except the target path is relative to the XDG configuration + directory. That is, unless `XDG_CONFIG_HOME` is configured + otherwise, the assignment + + xdg.configFile.hello.text = "hello world"; + + will result in a file '$HOME/.config/hello'. + + Most modules in Home Manager that previously were hard coded + to write configuration to '$HOME/.config' now use this + option and will therefore honor the XDG configuration + directory. + ''; + } ]; }; } diff --git a/modules/misc/xdg.nix b/modules/misc/xdg.nix new file mode 100644 index 00000000..941d51ed --- /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; + } + ]; +} diff --git a/modules/programs/beets.nix b/modules/programs/beets.nix index 34aa0460..40e06a6b 100644 --- a/modules/programs/beets.nix +++ b/modules/programs/beets.nix @@ -27,7 +27,7 @@ in config = mkIf (cfg.settings != {}) { home.packages = [ pkgs.beets ]; - home.file.".config/beets/config.yaml".text = + xdg.configFile."beets/config.yaml".text = builtins.toJSON config.programs.beets.settings; }; } diff --git a/modules/programs/feh.nix b/modules/programs/feh.nix index 1ca83ca8..12d828ec 100644 --- a/modules/programs/feh.nix +++ b/modules/programs/feh.nix @@ -30,7 +30,7 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.feh ]; - home.file.".config/feh/keys".text = '' + xdg.configFile."feh/keys".text = '' # Disable default keybindings ${concatStringsSep "\n" (mapAttrsToList disableBinding cfg.keybindings)} diff --git a/modules/programs/htop.nix b/modules/programs/htop.nix index 10235ccd..d700c485 100644 --- a/modules/programs/htop.nix +++ b/modules/programs/htop.nix @@ -290,7 +290,7 @@ in config = mkIf cfg.enable { home.packages = [ pkgs.htop ]; - home.file.".config/htop/htoprc".text = let + xdg.configFile."htop/htoprc".text = let leftMeters = map (m: m.kind) cfg.meters.left; leftModes = map (m: m.mode) cfg.meters.left; rightMeters = map (m: m.kind) cfg.meters.right; diff --git a/modules/programs/termite.nix b/modules/programs/termite.nix index 1e4ee671..ce047b8f 100644 --- a/modules/programs/termite.nix +++ b/modules/programs/termite.nix @@ -310,7 +310,7 @@ in optionalString = name: val: lib.optionalString (val != null) "${name} = ${val}"; in mkIf cfg.enable { home.packages = [ pkgs.termite ]; - home.file.".config/termite/config".text = '' + xdg.configFile."termite/config".text = '' [options] ${optionalBoolean "allow_bold" cfg.allowBold} ${optionalBoolean "audible_bell" cfg.audibleBell} diff --git a/modules/services/dunst.nix b/modules/services/dunst.nix index 22a7d216..a2f5dae9 100644 --- a/modules/services/dunst.nix +++ b/modules/services/dunst.nix @@ -71,7 +71,7 @@ in } (mkIf (cfg.settings != {}) { - home.file.".config/dunst/dunstrc".text = toDunstIni cfg.settings; + xdg.configFile."dunst/dunstrc".text = toDunstIni cfg.settings; }) ] ); diff --git a/modules/services/polybar.nix b/modules/services/polybar.nix index 8e92b4af..2e24f2a9 100644 --- a/modules/services/polybar.nix +++ b/modules/services/polybar.nix @@ -111,7 +111,7 @@ in config = mkIf cfg.enable { home.packages = [ cfg.package ]; - home.file.".config/polybar/config".source = configFile; + xdg.configFile."polybar/config".source = configFile; systemd.user.services.polybar = { Unit = { diff --git a/modules/systemd.nix b/modules/systemd.nix index 06630477..8ee2db65 100644 --- a/modules/systemd.nix +++ b/modules/systemd.nix @@ -28,12 +28,12 @@ let wantedBy = target: { - name = ".config/systemd/user/${target}.wants/${name}.${style}"; + name = "systemd/user/${target}.wants/${name}.${style}"; value = { inherit source; }; }; in singleton { - name = ".config/systemd/user/${name}.${style}"; + name = "systemd/user/${name}.${style}"; value = { inherit source; }; } ++ @@ -107,7 +107,7 @@ in # If we run under a Linux system we assume that systemd is # available, in particular we assume that systemctl is in PATH. (mkIf pkgs.stdenv.isLinux { - home.file = + xdg.configFile = listToAttrs ( (buildServices "service" cfg.services) ++