lib/options: Add more options to mkPackageOption

This commit is contained in:
Anselm Schüler 2022-02-20 16:17:28 +01:00 committed by pennae
parent d6ae1560b0
commit 9769e90233
2 changed files with 79 additions and 18 deletions

View File

@ -36,6 +36,9 @@ let
inherit (lib.types)
mkOptionType
;
inherit (lib.lists)
last
;
prioritySuggestion = ''
Use `lib.mkForce value` or `lib.mkDefault value` to change the priority on any of these definitions.
'';
@ -107,17 +110,28 @@ rec {
/* Creates an Option attribute set for an option that specifies the
package a module should use for some purpose.
The package is specified as a list of strings representing its attribute path in nixpkgs.
Type: mkPackageOption :: pkgs -> (string|[string]) ->
{ default? :: [string], example? :: null|string|[string], extraDescription? :: string } ->
option
Because of this, you need to pass nixpkgs itself as the first argument.
The package is specified in the third argument under `default` as a list of strings
representing its attribute path in nixpkgs (or another package set).
Because of this, you need to pass nixpkgs itself (or a subset) as the first argument.
The second argument is the name of the option, used in the description "The <name> package to use.".
The second argument may be either a string or a list of strings.
It provides the display name of the package in the description of the generated option
(using only the last element if the passed value is a list)
and serves as the fallback value for the `default` argument.
You can also pass an example value, either a literal string or a package's attribute path.
To include extra information in the description, pass `extraDescription` to
append arbitrary text to the generated description.
You can also pass an `example` value, either a literal string or an attribute path.
You can omit the default path if the name of the option is also attribute path in nixpkgs.
The default argument can be omitted if the provided name is
an attribute of pkgs (if name is a string) or a
valid attribute path in pkgs (if name is a list).
Type: mkPackageOption :: pkgs -> string -> { default :: [string]; example :: null | string | [string]; } -> option
If you wish to explicitly provide no default, pass `null` as `default`.
Example:
mkPackageOption pkgs "hello" { }
@ -129,27 +143,46 @@ rec {
example = "pkgs.haskell.packages.ghc92.ghc.withPackages (hkgs: [ hkgs.primes ])";
}
=> { _type = "option"; default = «derivation /nix/store/jxx55cxsjrf8kyh3fp2ya17q99w7541r-ghc-8.10.7.drv»; defaultText = { ... }; description = "The GHC package to use."; example = { ... }; type = { ... }; }
Example:
mkPackageOption pkgs [ "python39Packages" "pytorch" ] {
extraDescription = "This is an example and doesn't actually do anything.";
}
=> { _type = "option"; default = «derivation /nix/store/gvqgsnc4fif9whvwd9ppa568yxbkmvk8-python3.9-pytorch-1.10.2.drv»; defaultText = { ... }; description = "The pytorch package to use. This is an example and doesn't actually do anything."; type = { ... }; }
*/
mkPackageOption =
# Package set (a specific version of nixpkgs)
# Package set (a specific version of nixpkgs or a subset)
pkgs:
# Name for the package, shown in option description
name:
{ default ? [ name ], example ? null }:
let default' = if !isList default then [ default ] else default;
{
# The attribute path where the default package is located
default ? name,
# A string or an attribute path to use as an example
example ? null,
# Additional text to include in the option description
extraDescription ? "",
}:
let
name' = if isList name then last name else name;
default' = if isList default then default else [ default ];
defaultPath = concatStringsSep "." default';
defaultValue = attrByPath default'
(throw "${defaultPath} cannot be found in pkgs") pkgs;
in mkOption {
defaultText = literalExpression ("pkgs." + defaultPath);
type = lib.types.package;
description = "The ${name} package to use.";
default = attrByPath default'
(throw "${concatStringsSep "." default'} cannot be found in pkgs") pkgs;
defaultText = literalExpression ("pkgs." + concatStringsSep "." default');
description = "The ${name'} package to use."
+ (if extraDescription == "" then "" else " ") + extraDescription;
${if default != null then "default" else null} = defaultValue;
${if example != null then "example" else null} = literalExpression
(if isList example then "pkgs." + concatStringsSep "." example else example);
};
/* Like mkPackageOption, but emit an mdDoc description instead of DocBook. */
mkPackageOptionMD = args: name: extra:
let option = mkPackageOption args name extra;
mkPackageOptionMD = pkgs: name: extra:
let option = mkPackageOption pkgs name extra;
in option // { description = lib.mdDoc option.description; };
/* This option accepts anything, but it does not produce any result.

View File

@ -101,11 +101,24 @@ Creates an Option attribute set for an option that specifies the package a modul
**Note**: You shouldnt necessarily make package options for all of your modules. You can always overwrite a specific package throughout nixpkgs by using [nixpkgs overlays](https://nixos.org/manual/nixpkgs/stable/#chap-overlays).
The default package is specified as a list of strings representing its attribute path in nixpkgs. Because of this, you need to pass nixpkgs itself as the first argument.
The package is specified in the third argument under `default` as a list of strings
representing its attribute path in nixpkgs (or another package set).
Because of this, you need to pass nixpkgs itself (or a subset) as the first argument.
The second argument is the name of the option, used in the description "The \<name\> package to use.". You can also pass an example value, either a literal string or a package's attribute path.
The second argument may be either a string or a list of strings.
It provides the display name of the package in the description of the generated option
(using only the last element if the passed value is a list)
and serves as the fallback value for the `default` argument.
You can omit the default path if the name of the option is also attribute path in nixpkgs.
To include extra information in the description, pass `extraDescription` to
append arbitrary text to the generated description.
You can also pass an `example` value, either a literal string or an attribute path.
The default argument can be omitted if the provided name is
an attribute of pkgs (if name is a string) or a
valid attribute path in pkgs (if name is a list).
If you wish to explicitly provide no default, pass `null` as `default`.
During the transition to CommonMark documentation `mkPackageOption` creates an option with a DocBook description attribute, once the transition is completed it will create a CommonMark description instead. `mkPackageOptionMD` always creates an option with a CommonMark description attribute and will be removed some time after the transition is completed.
@ -142,6 +155,21 @@ lib.mkOption {
```
:::
::: {#ex-options-declarations-util-mkPackageOption-extraDescription .example}
```nix
mkPackageOption pkgs [ "python39Packages" "pytorch" ] {
extraDescription = "This is an example and doesn't actually do anything.";
}
# is like
lib.mkOption {
type = lib.types.package;
default = pkgs.python39Packages.pytorch;
defaultText = lib.literalExpression "pkgs.python39Packages.pytorch";
description = "The pytorch package to use. This is an example and doesn't actually do anything.";
}
```
:::
## Extensible Option Types {#sec-option-declarations-eot}
Extensible option types is a feature that allow to extend certain types