home-manager/modules/home-environment.nix

296 lines
7.5 KiB
Nix
Raw Normal View History

2017-01-07 19:16:26 +01:00
{ config, lib, pkgs, ... }:
with lib;
with import ./lib/dag.nix { inherit lib; };
2017-01-07 19:16:26 +01:00
let
cfg = config.home;
languageSubModule = types.submodule {
options = {
base = mkOption {
default = null;
type = types.nullOr types.str;
2017-01-07 19:16:26 +01:00
description = ''
The language to use unless overridden by a more specific option.
'';
};
address = mkOption {
default = null;
type = types.nullOr types.str;
description = ''
The language to use for addresses.
'';
};
monetary = mkOption {
default = null;
type = types.nullOr types.str;
description = ''
The language to use for formatting currencies and money amounts.
'';
};
paper = mkOption {
default = null;
type = types.nullOr types.str;
description = ''
The language to use for paper sizes.
'';
};
time = mkOption {
default = null;
type = types.nullOr types.str;
description = ''
The language to use for formatting times.
'';
};
};
};
keyboardSubModule = types.submodule {
options = {
layout = mkOption {
type = types.str;
default = "us";
description = ''
Keyboard layout.
'';
};
model = mkOption {
type = types.str;
default = "pc104";
example = "presario";
description = ''
Keyboard model.
'';
};
options = mkOption {
type = types.listOf types.str;
default = [];
example = ["grp:caps_toggle" "grp_led:scroll"];
description = ''
X keyboard options; layout switching goes here.
'';
};
variant = mkOption {
type = types.str;
default = "";
example = "colemak";
description = ''
X keyboard variant.
'';
};
};
};
in
{
meta.maintainers = [ maintainers.rycee ];
2017-01-07 19:16:26 +01:00
options = {
home.username = mkOption {
type = types.str;
defaultText = "$USER";
readOnly = true;
description = "The user's username";
};
home.homeDirectory = mkOption {
type = types.path;
defaultText = "$HOME";
readOnly = true;
description = "The user's home directory";
};
2017-01-07 19:16:26 +01:00
home.language = mkOption {
type = languageSubModule;
default = {};
description = "Language configuration.";
};
home.keyboard = mkOption {
type = keyboardSubModule;
default = {};
description = "Keyboard configuration.";
};
home.sessionVariables = mkOption {
default = {};
type = types.attrs;
2017-01-15 20:03:55 +01:00
example = { EDITOR = "emacs"; GS_OPTIONS = "-sPAPERSIZE=a4"; };
description = ''
Environment variables to always set at login.
'';
};
home.sessionVariableSetter = mkOption {
default = "bash";
2017-08-15 13:54:33 +02:00
type = types.enum [ "pam" "bash" "zsh" ];
example = "pam";
description = ''
Identifies the module that should set the session variables.
</para><para>
If "bash" is set then <varname>config.bash.enable</varname>
must also be enabled.
</para><para>
If "pam" is set then PAM must be used to set the system
environment. Also mind that typical environment variables
might not be set by the time PAM starts up.
'';
2017-01-07 19:16:26 +01:00
};
home.packages = mkOption {
type = types.listOf types.package;
default = [];
description = "The set of packages to appear in the user environment.";
};
home.extraOutputsToInstall = mkOption {
type = types.listOf types.str;
default = [];
example = [ "doc" "info" "devdoc" ];
description = ''
List of additional package outputs of the packages
<varname>home.packages</varname> that should be installed into
the user environment.
'';
};
2017-01-07 19:16:26 +01:00
home.path = mkOption {
internal = true;
description = "The derivation installing the user packages.";
};
home.activation = mkOption {
internal = true;
default = {};
type = types.attrs;
description = ''
Activation scripts for the home environment.
</para><para>
Any script should respect the <varname>DRY_RUN</varname>
variable, if it is set then no actual action should be taken.
The variable <varname>DRY_RUN_CMD</varname> is set to
<code>echo</code> if dry run is enabled. Thus, many cases you
can use the idiom <code>$DRY_RUN_CMD rm -rf /</code>.
'';
2017-01-07 19:16:26 +01:00
};
home.activationPackage = mkOption {
internal = true;
type = types.package;
description = "The package containing the complete activation script.";
};
};
config = {
assertions = [
{
assertion = config.home.username != "";
message = "Username could not be determined";
}
{
assertion = config.home.homeDirectory != "";
message = "Home directory could not be determined";
}
];
home.username = mkDefault (builtins.getEnv "USER");
home.homeDirectory = mkDefault (builtins.getEnv "HOME");
2017-01-07 19:16:26 +01:00
home.sessionVariables =
let
maybeSet = name: value:
listToAttrs (optional (value != null) { inherit name value; });
in
(maybeSet "LANG" cfg.language.base)
//
(maybeSet "LC_ADDRESS" cfg.language.address)
//
(maybeSet "LC_MONETARY" cfg.language.monetary)
//
(maybeSet "LC_PAPER" cfg.language.paper)
//
(maybeSet "LC_TIME" cfg.language.time);
# A dummy entry acting as a boundary between the activation
# script's "check" and the "write" phases.
home.activation.writeBoundary = dagEntryAnywhere "";
home.activation.installPackages = dagEntryAfter ["writeBoundary"] ''
$DRY_RUN_CMD nix-env -i ${cfg.path}
'';
2017-01-07 19:16:26 +01:00
home.activationPackage =
let
mkCmd = res: ''
noteEcho Activating ${res.name}
${res.data}
'';
sortedCommands = dagTopoSort cfg.activation;
2017-01-07 19:16:26 +01:00
activationCmds =
if sortedCommands ? result then
concatStringsSep "\n" (map mkCmd sortedCommands.result)
else
abort ("Dependency cycle in activation script: "
+ builtins.toJSON sortedCommands);
2017-01-07 19:16:26 +01:00
# Programs that always should be available on the activation
# script's PATH.
activationBinPaths = lib.makeBinPath [
pkgs.bash
pkgs.coreutils
];
2017-01-07 19:16:26 +01:00
sf = pkgs.writeText "activation-script" ''
#!${pkgs.stdenv.shell}
set -eu
set -o pipefail
export PATH="${activationBinPaths}:$PATH"
. ${./lib-bash/color-echo.sh}
${builtins.readFile ./lib-bash/activation-init.sh}
2017-01-07 19:16:26 +01:00
${activationCmds}
'';
in
pkgs.stdenv.mkDerivation {
name = "home-manager-generation";
2017-01-07 19:16:26 +01:00
phases = [ "installPhase" ];
installPhase = ''
2017-02-09 22:32:09 +01:00
install -D -m755 ${sf} $out/activate
substituteInPlace $out/activate \
--subst-var-by GENERATION_DIR $out
ln -s ${config.home-files} $out/home-files
ln -s ${cfg.path} $out/home-path
2017-01-07 19:16:26 +01:00
'';
};
home.path = pkgs.buildEnv {
name = "home-manager-path";
paths = cfg.packages;
inherit (cfg) extraOutputsToInstall;
2017-01-07 19:16:26 +01:00
meta = {
description = "Environment of packages installed through home-manager";
};
};
};
}