Modules with Declarations
In this section, we'll look at an example of a module from
<nixpkgs/nixos/modules>
that declares some options to provide a session for the i3 window manager.
(Comments and formatting are my own)
# <nixpkgs/nixos/modules/services/x11/window-managers/i3.nix>
{ config, lib, pkgs, ... }: with lib; let
# it's convention to define `cfg` as your own config
cfg = config.services.xserver.windowManger.i3;
in {
options = {
services.xserver.windowManager.i3 = {
# lib.mkEnableOption generates an option that accepts a bool and has the
# description "Whether to enable {arg}"
enable = mkEnableOption "i3 window manager";
# lib.mkOption is more general and accepts a whole set of options.
# in this case, a default value, a description, and a lib.types type
configFile = mkOption {
default = null;
type = with types; nullOr path;
description = ''
Path to the i3 configuration file.
If left at the default value, $HOME/.i3/config will be used.
'';
};
extraSessionCommands = mkOption {
default = "";
type = types.lines;
description = ''
Shell commands executed just before i3 is started.
'';
}
# sometimes packages have multiple variants you can use in place of the
# original.
# in these cases, an option `package` is usually supplied to configure
# what the module puts in your environment.
package = mkOption {
type = types.package;
default = pkgs.i3;
defaultText = "pkgs.i3";
example = "pkgs.i3-gaps";
description = ''
i3 package to use.
'';
};
extraPackages = mkOption {
type = with types; listOf package;
default = with pkgs; [ dmenu i3status i3lock ];
example = literalExample ''
with pkgs; [
dmenu
i3status
i3lock
]
'';
description = ''
Extra packages to be installed system wide.
'';
};
};
};
# lib.mkIf only applies configuration if the predicate is true
config = mkIf cfg.enable {
environment.systemPackages = [ cfg.package ] ++ cfg.extraPackages;
environment.etc."i3/config" = mkIf (cfg.configFile != null) {
source = cfg.configFile;
};
services.xserver.windowManager.session = [
{
name = "i3";
start = ''
${cfg.extraSessionCommands}
# lib.optionalString returns "" if the predicate is false
${cfg.package}/bin/i3 ${optionalString (cfg.configFile != null)
"-c /etc/i3/config"
} &
waitPID=$!
'';
};
];
};
imports = [
# lib.mkRemovedOptionModule returns a path to a module with a single option
# that throws an error message
(mkRemovedOptionModule [ "services" "xserver" "windowManager" "i3-gaps" "enable" ]
"Use services.xserver.windowManager.i3.enable and set services.xserver.windowManager.i3.package to pkgs.i3-gaps to use i3-gaps.")
];
}
As you can see, it's pretty simple. If you enable it, you get the i3
package
and an X session that runs the provided binary. Like most modules, it makes
heavy use of the library provided in
<nixpkgs/lib>
.