diff --git a/lib/options.nix b/lib/options.nix index 444ec37e6eaf3..c32d298890c15 100644 --- a/lib/options.nix +++ b/lib/options.nix @@ -15,6 +15,7 @@ rec { , defaultText ? null # Textual representation of the default, for in the manual. , example ? null # Example value used in the manual. , description ? null # String describing the option. + , packages ? [] # Related packages to be specified with `literalPackages*' functions , type ? null # Option type, providing type-checking and value merging. , apply ? null # Function that converts the option value to something else. , internal ? null # Whether the option is for NixOS developers only. @@ -24,13 +25,56 @@ rec { } @ attrs: attrs // { _type = "option"; }; - mkEnableOption = name: mkOption { - default = false; - example = true; - description = "Whether to enable ${name}."; - type = lib.types.bool; + # A boolean which determines whenever to do (or not to do) something. + mkWheneverToOption = + { default ? false + , what + , description ? null + , ... + } @ attrs: + mkOption ((removeAttrs attrs [ "what" ]) // { + inherit default; + example = !default; + type = lib.types.bool; + description = '' + Whether to ${what}. + + ${optionalString (description != null) description} + ''; + }); + + mkWheneverToPkgOption = + { description ? null + , broken ? false + , package ? null + , packages ? [] + , ... + } @ attrs: let + pkgs = optional (package != null) package + ++ packages; + in + mkWheneverToOption (removeAttrs attrs [ "broken" "package" ] // { + description = '' + ${optionalString (description != null) description} + + ${if broken then "THIS IS BROKEN." + else if (length pkgs > 1) then "Related packages:" + else if (length pkgs == 1) then "The package is:" + else ""} + ''; + # Don't evaluate when marked as broken + packages = optional (!broken && package != null) package; + }); + + mkEnableOption = name: mkWheneverToPkgOption { + what = "enable ${name}"; }; + mkEnableOption' = { name ? null, ... } @ attrs: + mkWheneverToPkgOption (removeAttrs attrs [ "name" ] // { + what = "enable ${name}"; + }); + # This option accept anything, but it does not produce any result. This # is useful for sharing a module across different module sets without # having to implement similar features as long as the value of the options @@ -77,6 +121,16 @@ rec { getValues = map (x: x.value); getFiles = map (x: x.file); + # Generate DocBook documentation for a list of packages + packageListToDocString = packages: + let + describePkg = n: p: + "" + + " (${p.name}): ${p.meta.description or "???"}." + # Lots of `longDescription's break DocBook, so we just wrap them into + + optionalString (p.meta ? longDescription) "\n${p.meta.longDescription}" + + ""; + in "${concatStringsSep "\n" (map ({name, value}: describePkg name value) packages)}"; # Generate documentation template from the list of option declaration like # the set generated with filterOptionSets. @@ -87,16 +141,17 @@ rec { let docOption = rec { name = showOption opt.loc; - description = opt.description or (throw "Option `${name}' has no description."); + description = (opt.description or (throw "Option `${name}' has no description.")) + + optionalString (opt ? packages && opt.packages != []) "\n\n${packageListToDocString opt.packages}"; declarations = filter (x: x != unknownModule) opt.declarations; internal = opt.internal or false; visible = opt.visible or true; readOnly = opt.readOnly or false; type = opt.type.name or null; } - // (if opt ? example then { example = scrubOptionValue opt.example; } else {}) - // (if opt ? default then { default = scrubOptionValue opt.default; } else {}) - // (if opt ? defaultText then { default = opt.defaultText; } else {}); + // (optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; }) + // (optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; }) + // (optionalAttrs (opt ? defaultText) { default = opt.defaultText; }); subOptions = let ss = opt.type.getSubOptions opt.loc; @@ -124,6 +179,14 @@ rec { functions. */ literalExample = text: { _type = "literalExample"; inherit text; }; + /* For use in the ‘packages’ option attribute. */ + literalPackage' = pkgs: n: p: nameValuePair "${optionalString (n != "") (n + ".")}${p}" (getAttrFromPath (splitString "." p) pkgs); + + literalPackages' = pkgs: n: l: map (literalPackage' pkgs n) l; + + literalPackage = pkgs: n: literalPackage' { inherit pkgs; } "" n; + + literalPackages = pkgs: l: literalPackages' { inherit pkgs; } "" l; /* Helper functions. */ showOption = concatStringsSep "."; diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix index 86a39322ba510..569b2942d37cf 100644 --- a/nixos/doc/manual/default.nix +++ b/nixos/doc/manual/default.nix @@ -15,14 +15,6 @@ let else if builtins.isFunction x then "" else x; - # Clean up declaration sites to not refer to the NixOS source tree. - optionsList' = flip map optionsList (opt: opt // { - declarations = map stripAnyPrefixes opt.declarations; - } - // optionalAttrs (opt ? example) { example = substFunction opt.example; } - // optionalAttrs (opt ? default) { default = substFunction opt.default; } - // optionalAttrs (opt ? type) { type = substFunction opt.type; }); - # We need to strip references to /nix/store/* from options, # including any `extraSources` if some modules came from elsewhere, # or else the build will fail. @@ -32,8 +24,25 @@ let prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources); stripAnyPrefixes = flip (fold removePrefix) prefixesToStrip; + # Clean up declaration sites to not refer to the NixOS source tree. + optionsList' = flip map optionsList (opt: opt // { + declarations = map stripAnyPrefixes opt.declarations; + } + // optionalAttrs (opt ? example) { example = substFunction opt.example; } + // optionalAttrs (opt ? default) { default = substFunction opt.default; } + // optionalAttrs (opt ? type) { type = substFunction opt.type; }); + + # Custom "less" that pushes up all the things ending in ".enable*" + isEnable = x: hasPrefix "enable" (last (splitString "." x)); + enableFirst = a: b: if isEnable a && !isEnable b then true + else if !isEnable a && isEnable b then false + else a < b; + + # Customly sort option list for the man page. + optionsList'' = sort (a: b: enableFirst a.name b.name) optionsList'; + # Convert the list of options into an XML file. - optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList'); + optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList''); optionsDocBook = runCommand "options-db.xml" {} '' optionsXML=${optionsXML} diff --git a/nixos/modules/hardware/ksm.nix b/nixos/modules/hardware/ksm.nix index d6ac69b5d65e9..7386eaeb6bd0a 100644 --- a/nixos/modules/hardware/ksm.nix +++ b/nixos/modules/hardware/ksm.nix @@ -1,7 +1,9 @@ { config, lib, ... }: { - options.hardware.enableKSM = lib.mkEnableOption "Kernel Same-Page Merging"; + options.hardware.enableKSM = lib.mkEnableOption' { + name = "Kernel Same-Page Merging"; + }; config = lib.mkIf config.hardware.enableKSM { systemd.services.enable-ksm = { diff --git a/nixos/modules/hardware/video/webcam/facetimehd.nix b/nixos/modules/hardware/video/webcam/facetimehd.nix index b35709763b903..f6e4742010038 100644 --- a/nixos/modules/hardware/video/webcam/facetimehd.nix +++ b/nixos/modules/hardware/video/webcam/facetimehd.nix @@ -12,7 +12,10 @@ in { - options.hardware.facetimehd.enable = mkEnableOption "facetimehd kernel module"; + options.hardware.facetimehd.enable = mkEnableOption' { + name = "facetimehd kernel module"; + package = literalPackage' kernelPackages "kernelPackages" "facetimehd"; + }; config = mkIf cfg.enable { diff --git a/nixos/modules/programs/atop.nix b/nixos/modules/programs/atop.nix index b91bd98047ee1..6d96fbbfe4edb 100644 --- a/nixos/modules/programs/atop.nix +++ b/nixos/modules/programs/atop.nix @@ -14,6 +14,11 @@ in programs.atop = { + enable = mkWheneverToPkgOption { + what = "globally configure atop"; + package = literalPackage pkgs "pkgs.atop"; + }; + settings = mkOption { type = types.attrs; default = {}; @@ -29,7 +34,7 @@ in }; }; - config = mkIf (cfg.settings != {}) { + config = mkIf cfg.enable { environment.etc."atoprc".text = concatStrings (mapAttrsToList (n: v: "${n} ${toString v}\n") cfg.settings); }; diff --git a/nixos/modules/programs/blcr.nix b/nixos/modules/programs/blcr.nix index 804e1d01f12b8..1c82f71e47ed5 100644 --- a/nixos/modules/programs/blcr.nix +++ b/nixos/modules/programs/blcr.nix @@ -1,19 +1,19 @@ { config, lib, ... }: +with lib; + let - inherit (lib) mkOption mkIf; cfg = config.environment.blcr; - blcrPkg = config.boot.kernelPackages.blcr; + kp = config.boot.kernelPackages; in { ###### interface options = { - environment.blcr.enable = mkOption { - default = false; - description = - "Whether to enable support for the BLCR checkpointing tool."; + environment.blcr.enable = mkEnableOption' { + name = "support for the BLCR checkpointing tool"; + #asserts #package = literalPackage' kp "kernelPackages" "blcr"; }; }; @@ -21,7 +21,7 @@ in config = mkIf cfg.enable { boot.kernelModules = [ "blcr" "blcr_imports" ]; - boot.extraModulePackages = [ blcrPkg ]; - environment.systemPackages = [ blcrPkg ]; + boot.extraModulePackages = [ kp.blcr ]; + environment.systemPackages = [ kp.blcr ]; }; } diff --git a/nixos/modules/programs/cdemu.nix b/nixos/modules/programs/cdemu.nix index 6a0185d362c50..e679d7f9793d4 100644 --- a/nixos/modules/programs/cdemu.nix +++ b/nixos/modules/programs/cdemu.nix @@ -7,13 +7,12 @@ in { options = { programs.cdemu = { - enable = mkOption { - default = false; - description = '' - cdemu for members of - . - ''; + + enable = mkWheneverToPkgOption { + what = "globally configure cdemu"; + package = literalPackage pkgs "pkgs.cdemu-daemon"; }; + group = mkOption { default = "cdrom"; description = '' diff --git a/nixos/modules/programs/kbdlight.nix b/nixos/modules/programs/kbdlight.nix index 0172368e968fa..6994e35e7e67f 100644 --- a/nixos/modules/programs/kbdlight.nix +++ b/nixos/modules/programs/kbdlight.nix @@ -7,7 +7,10 @@ let in { - options.programs.kbdlight.enable = mkEnableOption "kbdlight"; + options.programs.kbdlight.enable = mkEnableOption' { + name = "kbdlight"; + package = literalPackage pkgs "pkgs.kbdlight"; + }; config = mkIf cfg.enable { environment.systemPackages = [ pkgs.kbdlight ]; diff --git a/nixos/modules/programs/tmux.nix b/nixos/modules/programs/tmux.nix index 4220a2e17b3fd..d8af40fed6a85 100644 --- a/nixos/modules/programs/tmux.nix +++ b/nixos/modules/programs/tmux.nix @@ -1,7 +1,8 @@ { config, pkgs, lib, ... }: +with lib; + let - inherit (lib) mkOption mkEnableOption mkIf mkMerge types; cfg = config.programs.tmux; @@ -12,7 +13,10 @@ in options = { programs.tmux = { - enable = mkEnableOption "tmux - a screen replacement."; + enable = mkWheneverToPkgOption { + what = "globally configure tmux"; + package = literalPackage pkgs "pkgs.tmux"; + }; tmuxconf = mkOption { default = ""; diff --git a/nixos/modules/services/audio/icecast.nix b/nixos/modules/services/audio/icecast.nix index 6a8a0f9975b3b..47a8bff83d46a 100644 --- a/nixos/modules/services/audio/icecast.nix +++ b/nixos/modules/services/audio/icecast.nix @@ -44,7 +44,10 @@ in { services.icecast = { - enable = mkEnableOption "Icecast server"; + enable = mkEnableOption' { + name = "Icecast server"; + package = literalPackage pkgs "pkgs.icecast"; + }; hostname = mkOption { type = types.str; diff --git a/nixos/modules/services/backup/rsnapshot.nix b/nixos/modules/services/backup/rsnapshot.nix index 96657cf17fc5f..55c2b00e4b3c3 100644 --- a/nixos/modules/services/backup/rsnapshot.nix +++ b/nixos/modules/services/backup/rsnapshot.nix @@ -7,7 +7,11 @@ in { options = { services.rsnapshot = { - enable = mkEnableOption "rsnapshot backups"; + + enable = mkWheneverToPkgOption { + what = "enable backups with rsnapshot"; + package = literalPackage pkgs "pkgs.rsnapshot"; + }; extraConfig = mkOption { default = ""; diff --git a/nixos/modules/services/backup/znapzend.nix b/nixos/modules/services/backup/znapzend.nix index 648089f90b7b4..14fd5c2f1be33 100644 --- a/nixos/modules/services/backup/znapzend.nix +++ b/nixos/modules/services/backup/znapzend.nix @@ -8,7 +8,12 @@ in { options = { services.znapzend = { - enable = mkEnableOption "ZnapZend daemon"; + + enable = mkWheneverToPkgOption { + what = "enable backups with ZsnapZend"; + package = literalPackage pkgs "pkgs.znapzend"; + }; + }; }; diff --git a/nixos/modules/services/databases/riak.nix b/nixos/modules/services/databases/riak.nix index bee768fa42aed..6094f617800e4 100644 --- a/nixos/modules/services/databases/riak.nix +++ b/nixos/modules/services/databases/riak.nix @@ -16,7 +16,11 @@ in services.riak = { - enable = mkEnableOption "riak"; + enable = mkEnableOption' { + name = "riak"; + broken = true; + package = literalPackage pkgs "pkgs.riak"; + }; package = mkOption { type = types.package; diff --git a/nixos/modules/services/hardware/irqbalance.nix b/nixos/modules/services/hardware/irqbalance.nix index b139154432cf9..8186d4cd1251f 100644 --- a/nixos/modules/services/hardware/irqbalance.nix +++ b/nixos/modules/services/hardware/irqbalance.nix @@ -9,7 +9,10 @@ let in { - options.services.irqbalance.enable = mkEnableOption "irqbalance daemon"; + options.services.irqbalance.enable = mkEnableOption' { + name = "irqbalance daemon"; + package = literalPackage pkgs "pkgs.irqbalance"; + }; config = mkIf cfg.enable { diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index 127c3da69d14f..aee3542a6a4fc 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -70,7 +70,10 @@ in { options.services.dovecot2 = { - enable = mkEnableOption "Dovecot 2.x POP3/IMAP server"; + enable = mkEnableOption' { + name = "Dovecot POP3/IMAP server"; + package = literalPackage pkgs "pkgs.dovecot"; + }; enablePop3 = mkOption { type = types.bool; diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix index bad9d527f9a1d..3f9addac608aa 100644 --- a/nixos/modules/services/mail/postfix.nix +++ b/nixos/modules/services/mail/postfix.nix @@ -191,10 +191,9 @@ in services.postfix = { - enable = mkOption { - type = types.bool; - default = false; - description = "Whether to run the Postfix mail server."; + enable = mkEnableOption' { + name = "Postfix mail server"; + package = literalPackage pkgs "pkgs.postfix"; }; enableSmtp = mkOption { diff --git a/nixos/modules/services/misc/calibre-server.nix b/nixos/modules/services/misc/calibre-server.nix index a920aa22ccdf6..fa6fe4ca8f225 100644 --- a/nixos/modules/services/misc/calibre-server.nix +++ b/nixos/modules/services/misc/calibre-server.nix @@ -16,7 +16,10 @@ in services.calibre-server = { - enable = mkEnableOption "calibre-server"; + enable = mkEnableOption' { + name = "calibre-server"; + package = literalPackage pkgs "pkgs.calibre"; + }; libraryDir = mkOption { description = '' diff --git a/nixos/modules/services/misc/confd.nix b/nixos/modules/services/misc/confd.nix index c0fbf06e6c4c1..4fd1a2c40b5da 100644 --- a/nixos/modules/services/misc/confd.nix +++ b/nixos/modules/services/misc/confd.nix @@ -17,7 +17,10 @@ let in { options.services.confd = { - enable = mkEnableOption "confd service"; + enable = mkEnableOption' { + name = "confd service"; + package = literalPackage pkgs "pkgs.confd"; + }; backend = mkOption { description = "Confd config storage backend to use."; diff --git a/nixos/modules/services/misc/gammu-smsd.nix b/nixos/modules/services/misc/gammu-smsd.nix index 2d406b6344371..a720f73f5707d 100644 --- a/nixos/modules/services/misc/gammu-smsd.nix +++ b/nixos/modules/services/misc/gammu-smsd.nix @@ -53,7 +53,10 @@ in { options = { services.gammu-smsd = { - enable = mkEnableOption "gammu-smsd daemon"; + enable = mkEnableOption' { + name = "gammu-smsd daemon"; + package = literalPackage pkgs "pkgs.gammu"; + }; user = mkOption { type = types.str; diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix index 0ae0516769c05..ffa27074b99c2 100644 --- a/nixos/modules/services/misc/matrix-synapse.nix +++ b/nixos/modules/services/misc/matrix-synapse.nix @@ -57,7 +57,11 @@ ${cfg.extraConfig} in { options = { services.matrix-synapse = { - enable = mkEnableOption "matrix.org synapse"; + enable = mkEnableOption' { + name = "matrix.org synapse"; + package = literalPackage pkgs "pkgs.matrix-synapse"; + }; + package = mkOption { type = types.package; default = pkgs.matrix-synapse; diff --git a/nixos/modules/services/misc/plex.nix b/nixos/modules/services/misc/plex.nix index 92b352db416c2..6d5425ce5f14c 100644 --- a/nixos/modules/services/misc/plex.nix +++ b/nixos/modules/services/misc/plex.nix @@ -9,7 +9,10 @@ in { options = { services.plex = { - enable = mkEnableOption "Plex Media Server"; + enable = mkEnableOption' { + name = "Plex Media Server"; + #unfree #package = literalPackage pkgs "pkgs.plex"; + }; # FIXME: In order for this config option to work, symlinks in the Plex # package in the Nix store have to be changed to point to this directory. diff --git a/nixos/modules/services/misc/ripple-data-api.nix b/nixos/modules/services/misc/ripple-data-api.nix index dbca56b13335e..43bfe3ce60248 100644 --- a/nixos/modules/services/misc/ripple-data-api.nix +++ b/nixos/modules/services/misc/ripple-data-api.nix @@ -35,7 +35,11 @@ let in { options = { services.rippleDataApi = { - enable = mkEnableOption "ripple data api"; + enable = mkEnableOption' { + name = "ripple data api"; + broken = true; # does not exists + package = literalPackage pkgs "pkgs.ripple-data-api"; + }; port = mkOption { description = "Ripple data api port"; diff --git a/nixos/modules/services/misc/rippled.nix b/nixos/modules/services/misc/rippled.nix index c6b67e8498ca8..6549bffca1d08 100644 --- a/nixos/modules/services/misc/rippled.nix +++ b/nixos/modules/services/misc/rippled.nix @@ -202,7 +202,10 @@ in options = { services.rippled = { - enable = mkEnableOption "rippled"; + enable = mkEnableOption' { + name = "rippled"; + #unfree #package = literalPackage pkgs "pkgs.rippled"; + }; package = mkOption { description = "Which rippled package to use."; @@ -374,7 +377,10 @@ in }; statsd = { - enable = mkEnableOption "statsd monitoring for rippled"; + enable = mkEnableOption' { + name = "statsd monitoring for rippled"; + #unfree #package = literalPackage pkgs "pkgs.rippled"; + }; address = mkOption { description = "The UDP address and port of the listening StatsD server."; diff --git a/nixos/modules/services/monitoring/uptime.nix b/nixos/modules/services/monitoring/uptime.nix index 29616a085c8f3..526345e4220ea 100644 --- a/nixos/modules/services/monitoring/uptime.nix +++ b/nixos/modules/services/monitoring/uptime.nix @@ -1,7 +1,8 @@ { config, pkgs, lib, ... }: -let - inherit (lib) mkOption mkEnableOption mkIf mkMerge types optionalAttrs optional; +with lib; + +let cfg = config.services.uptime; configDir = pkgs.runCommand "config" {} (if cfg.configFile != null then '' @@ -49,9 +50,15 @@ in { type = types.bool; }; - enableWebService = mkEnableOption "the uptime monitoring program web service"; + enableWebService = mkEnableOption' { + name = "the uptime monitoring program web service"; + package = literalPackage pkgs "pkgs.nodePackages.node-uptime"; + }; - enableSeparateMonitoringService = mkEnableOption "the uptime monitoring service" // { default = cfg.enableWebService; }; + enableSeparateMonitoringService = mkEnableOption' { + name = "the uptime monitoring service"; + default = cfg.enableWebService; + }; nodeEnv = mkOption { description = "The node environment to run in (development, production, etc.)"; diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix index 333a3378c4cc1..be021e702f6dc 100644 --- a/nixos/modules/services/networking/nsd.nix +++ b/nixos/modules/services/networking/nsd.nix @@ -330,7 +330,10 @@ in # options are ordered alphanumerically options.services.nsd = { - enable = mkEnableOption "NSD authoritative DNS server"; + enable = mkEnableOption' { + name = "NSD authoritative DNS server"; + package = literalPackage pkgs "pkgs.nsd"; + }; bind8Stats = mkEnableOption "BIND8 like statistics"; diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix index 53648aef1e044..ea6b7f59828df 100644 --- a/nixos/modules/services/networking/wpa_supplicant.nix +++ b/nixos/modules/services/networking/wpa_supplicant.nix @@ -23,7 +23,10 @@ let in { options = { networking.wireless = { - enable = mkEnableOption "wpa_supplicant"; + enable = mkEnableOption' { + name = "wpa_supplicant"; + package = literalPackage pkgs "pkgs.wpa_supplicant"; + }; interfaces = mkOption { type = types.listOf types.str;