From 277eea1cc7a5c37ea0b9aa8198cd1f2db3d6715c Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Sun, 9 Mar 2025 12:47:25 +0000 Subject: [PATCH] home-environment: add home.sessionSearchVariables This commit introduces `home.sessionSearchVariables` option, that is created to be a "generic" version of `home.sessionPath` for any environment variables that is similar to PATH (e.g.: MANPATH). This allows composition of those variables between multiple modules, avoiding issues like this one: https://github.com/nix-community/home-manager/pull/4579/files#r1364374048 This commit also reimplements `home.sessionPath` as terms of `home.sessionSearchVariables`, to reduce code duplication and show that the code is correct. The behavior is to prepend the new search paths. This will allow the user to override the defaults easily by setting it later in the configuration. --- modules/home-environment.nix | 36 ++++++++++++++++--- modules/lib/shell.nix | 8 +++++ tests/modules/home-environment/default.nix | 3 +- .../modules/home-environment/session-path.nix | 4 +-- .../session-search-variables.nix | 15 ++++++++ 5 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 tests/modules/home-environment/session-search-variables.nix diff --git a/modules/home-environment.nix b/modules/home-environment.nix index 0e3bef900..652ac086c 100644 --- a/modules/home-environment.nix +++ b/modules/home-environment.nix @@ -309,7 +309,7 @@ in ".git/safe/../../bin" ]; description = '' - Extra directories to add to {env}`PATH`. + Extra directories to prepend to {env}`PATH`. These directories are added to the {env}`PATH` variable in a double-quoted context, so expressions like `$HOME` are @@ -319,6 +319,27 @@ in ''; }; + home.sessionSearchVariables = mkOption { + default = { }; + type = with types; attrsOf (listOf str); + example = { + MANPATH = [ + "$HOME/.npm-packages/man" + "\${xdg.configHome}/.local/share/man" + ]; + }; + description = '' + Extra directories to prepend to arbitrary PATH-like + environment variables (e.g.: {env}`MANPATH`). The values + will be concatenated by `:`. + These directories are added to the environment variable in a + double-quoted context, so expressions like `$HOME` are + expanded by the shell. However, since expressions like `~` or + `*` are escaped, they will end up in the environment + verbatim. + ''; + }; + home.sessionVariablesExtra = mkOption { type = types.lines; default = ""; @@ -575,11 +596,18 @@ in export __HM_SESS_VARS_SOURCED=1 ${config.lib.shell.exportAll cfg.sessionVariables} - '' + lib.optionalString (cfg.sessionPath != [ ]) '' - export PATH="$PATH''${PATH:+:}${lib.concatStringsSep ":" cfg.sessionPath}" - '' + cfg.sessionVariablesExtra; + '' + lib.concatStringsSep "\n" + (lib.mapAttrsToList + (env: values: config.lib.shell.export + env + (config.lib.shell.prependToVar ":" env values)) + cfg.sessionSearchVariables) + + cfg.sessionVariablesExtra; }; + home.sessionSearchVariables.PATH = + lib.mkIf (cfg.sessionPath != [ ]) cfg.sessionPath; + home.packages = [ config.home.sessionVariablesPackage ]; # The entry acting as a boundary between the activation script's "check" and diff --git a/modules/lib/shell.nix b/modules/lib/shell.nix index ae30e0b0f..04f9135cf 100644 --- a/modules/lib/shell.nix +++ b/modules/lib/shell.nix @@ -17,6 +17,14 @@ let }; in rec { + # Produces a Bourne shell like statement that prepend new values to + # an possibly existing variable, using sep(arator). + # Example: + # prependToVar ":" "PATH" [ "$HOME/bin" "$HOME/.local/bin" ] + # => "$HOME/bin:$HOME/.local/bin:${PATH:+:}\$PATH" + prependToVar = sep: n: v: + "${lib.concatStringsSep sep v}\${${n}:+${sep}}\$${n}"; + # Produces a Bourne shell like variable export statement. export = n: v: ''export ${n}="${toString v}"''; diff --git a/tests/modules/home-environment/default.nix b/tests/modules/home-environment/default.nix index e76e248a1..c38ad5ce5 100644 --- a/tests/modules/home-environment/default.nix +++ b/tests/modules/home-environment/default.nix @@ -1,4 +1,5 @@ { - home-session-variables = ./session-variables.nix; home-session-path = ./session-path.nix; + home-session-search-variables = ./session-search-variables.nix; + home-session-variables = ./session-variables.nix; } diff --git a/tests/modules/home-environment/session-path.nix b/tests/modules/home-environment/session-path.nix index 57cfeceda..907d6c398 100644 --- a/tests/modules/home-environment/session-path.nix +++ b/tests/modules/home-environment/session-path.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ ... }: { imports = [ @@ -10,6 +10,6 @@ hmSessVars=home-path/etc/profile.d/hm-session-vars.sh assertFileExists $hmSessVars assertFileContains $hmSessVars \ - 'export PATH="$PATH''${PATH:+:}bar:baz:foo"' + 'export PATH="bar:baz:foo''${PATH:+:}$PATH"' ''; } diff --git a/tests/modules/home-environment/session-search-variables.nix b/tests/modules/home-environment/session-search-variables.nix new file mode 100644 index 000000000..b12009f2b --- /dev/null +++ b/tests/modules/home-environment/session-search-variables.nix @@ -0,0 +1,15 @@ +{ ... }: + +{ + imports = [ + ({ ... }: { config.home.sessionSearchVariables.TEST = [ "foo" ]; }) + ({ ... }: { config.home.sessionSearchVariables.TEST = [ "bar" "baz" ]; }) + ]; + + nmt.script = '' + hmSessVars=home-path/etc/profile.d/hm-session-vars.sh + assertFileExists $hmSessVars + assertFileContains $hmSessVars \ + 'export TEST="bar:baz:foo''${TEST:+:}$TEST"' + ''; +}