diff options
author | Bobby Rong <rjl931189261@126.com> | 2021-07-03 22:16:36 +0800 |
---|---|---|
committer | Bobby Rong <rjl931189261@126.com> | 2021-07-03 22:20:55 +0800 |
commit | bfd21cd2c1492b799facdab2e77308c34edbe9e7 (patch) | |
tree | a64a8bd3dfeabc62c415aa6c4b591ae28bac3cd7 | |
parent | 6877012179ebfbbf47451d2bc8d61212981c7940 (diff) | |
download | nixpkgs-bfd21cd2c1492b799facdab2e77308c34edbe9e7.tar nixpkgs-bfd21cd2c1492b799facdab2e77308c34edbe9e7.tar.gz nixpkgs-bfd21cd2c1492b799facdab2e77308c34edbe9e7.tar.bz2 nixpkgs-bfd21cd2c1492b799facdab2e77308c34edbe9e7.tar.lz nixpkgs-bfd21cd2c1492b799facdab2e77308c34edbe9e7.tar.xz nixpkgs-bfd21cd2c1492b799facdab2e77308c34edbe9e7.tar.zst nixpkgs-bfd21cd2c1492b799facdab2e77308c34edbe9e7.zip |
nixos: nixos/doc/manual/development/option-types.xml to CommonMark
-rw-r--r-- | nixos/doc/manual/development/option-types.section.md | 558 | ||||
-rw-r--r-- | nixos/doc/manual/development/option-types.xml | 914 | ||||
-rw-r--r-- | nixos/doc/manual/development/writing-modules.xml | 2 | ||||
-rw-r--r-- | nixos/doc/manual/from_md/development/option-types.section.xml | 987 |
4 files changed, 1546 insertions, 915 deletions
diff --git a/nixos/doc/manual/development/option-types.section.md b/nixos/doc/manual/development/option-types.section.md new file mode 100644 index 00000000000..ed557206659 --- /dev/null +++ b/nixos/doc/manual/development/option-types.section.md @@ -0,0 +1,558 @@ +# Options Types {#sec-option-types} + +Option types are a way to put constraints on the values a module option +can take. Types are also responsible of how values are merged in case of +multiple value definitions. + +## Basic Types {#sec-option-types-basic} + +Basic types are the simplest available types in the module system. Basic +types include multiple string types that mainly differ in how definition +merging is handled. + +`types.bool` + +: A boolean, its values can be `true` or `false`. + +`types.path` + +: A filesystem path, defined as anything that when coerced to a string + starts with a slash. Even if derivations can be considered as path, + the more specific `types.package` should be preferred. + +`types.package` + +: A derivation or a store path. + +`types.anything` + +: A type that accepts any value and recursively merges attribute sets + together. This type is recommended when the option type is unknown. + + ::: {#ex-types-anything .example} + ::: {.title} + **Example: `types.anything` Example** + ::: + Two definitions of this type like + + ```nix + { + str = lib.mkDefault "foo"; + pkg.hello = pkgs.hello; + fun.fun = x: x + 1; + } + ``` + + ```nix + { + str = lib.mkIf true "bar"; + pkg.gcc = pkgs.gcc; + fun.fun = lib.mkForce (x: x + 2); + } + ``` + + will get merged to + + ```nix + { + str = "bar"; + pkg.gcc = pkgs.gcc; + pkg.hello = pkgs.hello; + fun.fun = x: x + 2; + } + ``` + ::: + +`types.attrs` + +: A free-form attribute set. + + ::: {.warning} + This type will be deprecated in the future because it doesn\'t + recurse into attribute sets, silently drops earlier attribute + definitions, and doesn\'t discharge `lib.mkDefault`, `lib.mkIf` + and co. For allowing arbitrary attribute sets, prefer + `types.attrsOf types.anything` instead which doesn\'t have these + problems. + ::: + +Integer-related types: + +`types.int` + +: A signed integer. + +`types.ints.{s8, s16, s32}` + +: Signed integers with a fixed length (8, 16 or 32 bits). They go from + −2^n/2 to + 2^n/2−1 respectively (e.g. `−128` to + `127` for 8 bits). + +`types.ints.unsigned` + +: An unsigned integer (that is >= 0). + +`types.ints.{u8, u16, u32}` + +: Unsigned integers with a fixed length (8, 16 or 32 bits). They go + from 0 to 2^n−1 respectively (e.g. `0` + to `255` for 8 bits). + +`types.ints.positive` + +: A positive integer (that is > 0). + +`types.port` + +: A port number. This type is an alias to + `types.ints.u16`. + +String-related types: + +`types.str` + +: A string. Multiple definitions cannot be merged. + +`types.lines` + +: A string. Multiple definitions are concatenated with a new line + `"\n"`. + +`types.commas` + +: A string. Multiple definitions are concatenated with a comma `","`. + +`types.envVar` + +: A string. Multiple definitions are concatenated with a collon `":"`. + +`types.strMatching` + +: A string matching a specific regular expression. Multiple + definitions cannot be merged. The regular expression is processed + using `builtins.match`. + +## Value Types {#sec-option-types-value} + +Value types are types that take a value parameter. + +`types.enum` *`l`* + +: One element of the list *`l`*, e.g. `types.enum [ "left" "right" ]`. + Multiple definitions cannot be merged. + +`types.separatedString` *`sep`* + +: A string with a custom separator *`sep`*, e.g. + `types.separatedString "|"`. + +`types.ints.between` *`lowest highest`* + +: An integer between *`lowest`* and *`highest`* (both inclusive). Useful + for creating types like `types.port`. + +`types.submodule` *`o`* + +: A set of sub options *`o`*. *`o`* can be an attribute set, a function + returning an attribute set, or a path to a file containing such a + value. Submodules are used in composed types to create modular + options. This is equivalent to + `types.submoduleWith { modules = toList o; shorthandOnlyDefinesConfig = true; }`. + Submodules are detailed in [Submodule](#section-option-types-submodule). + +`types.submoduleWith` { *`modules`*, *`specialArgs`* ? {}, *`shorthandOnlyDefinesConfig`* ? false } + +: Like `types.submodule`, but more flexible and with better defaults. + It has parameters + + - *`modules`* A list of modules to use by default for this + submodule type. This gets combined with all option definitions + to build the final list of modules that will be included. + + ::: {.note} + Only options defined with this argument are included in rendered + documentation. + ::: + + - *`specialArgs`* An attribute set of extra arguments to be passed + to the module functions. The option `_module.args` should be + used instead for most arguments since it allows overriding. + *`specialArgs`* should only be used for arguments that can\'t go + through the module fixed-point, because of infinite recursion or + other problems. An example is overriding the `lib` argument, + because `lib` itself is used to define `_module.args`, which + makes using `_module.args` to define it impossible. + + - *`shorthandOnlyDefinesConfig`* Whether definitions of this type + should default to the `config` section of a module (see + [Example: Structure of NixOS Modules](#ex-module-syntax)) + if it is an attribute set. Enabling this only has a benefit + when the submodule defines an option named `config` or `options`. + In such a case it would allow the option to be set with + `the-submodule.config = "value"` instead of requiring + `the-submodule.config.config = "value"`. This is because + only when modules *don\'t* set the `config` or `options` + keys, all keys are interpreted as option definitions in the + `config` section. Enabling this option implicitly puts all + attributes in the `config` section. + + With this option enabled, defining a non-`config` section + requires using a function: + `the-submodule = { ... }: { options = { ... }; }`. + +## Composed Types {#sec-option-types-composed} + +Composed types are types that take a type as parameter. `listOf + int` and `either int str` are examples of composed types. + +`types.listOf` *`t`* + +: A list of *`t`* type, e.g. `types.listOf + int`. Multiple definitions are merged with list concatenation. + +`types.attrsOf` *`t`* + +: An attribute set of where all the values are of *`t`* type. Multiple + definitions result in the joined attribute set. + + ::: {.note} + This type is *strict* in its values, which in turn means attributes + cannot depend on other attributes. See ` + types.lazyAttrsOf` for a lazy version. + ::: + +`types.lazyAttrsOf` *`t`* + +: An attribute set of where all the values are of *`t`* type. Multiple + definitions result in the joined attribute set. This is the lazy + version of `types.attrsOf + `, allowing attributes to depend on each other. + + ::: {.warning} + This version does not fully support conditional definitions! With an + option `foo` of this type and a definition + `foo.attr = lib.mkIf false 10`, evaluating `foo ? attr` will return + `true` even though it should be false. Accessing the value will then + throw an error. For types *`t`* that have an `emptyValue` defined, + that value will be returned instead of throwing an error. So if the + type of `foo.attr` was `lazyAttrsOf (nullOr int)`, `null` would be + returned instead for the same `mkIf false` definition. + ::: + +`types.nullOr` *`t`* + +: `null` or type *`t`*. Multiple definitions are merged according to + type *`t`*. + +`types.uniq` *`t`* + +: Ensures that type *`t`* cannot be merged. It is used to ensure option + definitions are declared only once. + +`types.either` *`t1 t2`* + +: Type *`t1`* or type *`t2`*, e.g. `with types; either int str`. + Multiple definitions cannot be merged. + +`types.oneOf` \[ *`t1 t2`* \... \] + +: Type *`t1`* or type *`t2`* and so forth, e.g. + `with types; oneOf [ int str bool ]`. Multiple definitions cannot be + merged. + +`types.coercedTo` *`from f to`* + +: Type *`to`* or type *`from`* which will be coerced to type *`to`* using + function *`f`* which takes an argument of type *`from`* and return a + value of type *`to`*. Can be used to preserve backwards compatibility + of an option if its type was changed. + +## Submodule {#section-option-types-submodule} + +`submodule` is a very powerful type that defines a set of sub-options +that are handled like a separate module. + +It takes a parameter *`o`*, that should be a set, or a function returning +a set with an `options` key defining the sub-options. Submodule option +definitions are type-checked accordingly to the `options` declarations. +Of course, you can nest submodule option definitons for even higher +modularity. + +The option set can be defined directly +([Example: Directly defined submodule](#ex-submodule-direct)) or as reference +([Example: Submodule defined as a reference](#ex-submodule-reference)). + +::: {#ex-submodule-direct .example} +::: {.title} +**Example: Directly defined submodule** +::: +```nix +options.mod = mkOption { + description = "submodule example"; + type = with types; submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }; +}; +``` +::: + +::: {#ex-submodule-reference .example} +::: {.title} +**Example: Submodule defined as a reference** +::: +```nix +let + modOptions = { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = int; + }; + }; + }; +in +options.mod = mkOption { + description = "submodule example"; + type = with types; submodule modOptions; +}; +``` +::: + +The `submodule` type is especially interesting when used with composed +types like `attrsOf` or `listOf`. When composed with `listOf` +([Example: Declaration of a list of submodules](#ex-submodule-listof-declaration)), `submodule` allows +multiple definitions of the submodule option set +([Example: Definition of a list of submodules](#ex-submodule-listof-definition)). + +::: {#ex-submodule-listof-declaration .example} +::: {.title} +**Example: Declaration of a list of submodules** +::: +```nix +options.mod = mkOption { + description = "submodule example"; + type = with types; listOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +}; +``` +::: + +::: {#ex-submodule-listof-definition .example} +::: {.title} +**Example: Definition of a list of submodules** +::: +```nix +config.mod = [ + { foo = 1; bar = "one"; } + { foo = 2; bar = "two"; } +]; +``` +::: + +When composed with `attrsOf` +([Example: Declaration of attribute sets of submodules](#ex-submodule-attrsof-declaration)), `submodule` allows +multiple named definitions of the submodule option set +([Example: Definition of attribute sets of submodules](#ex-submodule-attrsof-definition)). + +::: {#ex-submodule-attrsof-declaration .example} +::: {.title} +**Example: Declaration of attribute sets of submodules** +::: +```nix +options.mod = mkOption { + description = "submodule example"; + type = with types; attrsOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +}; +``` +::: + +::: {#ex-submodule-attrsof-definition .example} +::: {.title} +**Example: Definition of attribute sets of submodules** +::: +```nix +config.mod.one = { foo = 1; bar = "one"; }; +config.mod.two = { foo = 2; bar = "two"; }; +``` +::: + +## Extending types {#sec-option-types-extending} + +Types are mainly characterized by their `check` and `merge` functions. + +`check` + +: The function to type check the value. Takes a value as parameter and + return a boolean. It is possible to extend a type check with the + `addCheck` function ([Example: Adding a type check](#ex-extending-type-check-1)), + or to fully override the check function + ([Example: Overriding a type check](#ex-extending-type-check-2)). + + ::: {#ex-extending-type-check-1 .example} + ::: {.title} + **Example: Adding a type check** + ::: + ```nix + byte = mkOption { + description = "An integer between 0 and 255."; + type = types.addCheck types.int (x: x >= 0 && x <= 255); + }; + ``` + ::: + + ::: {#ex-extending-type-check-2 .example} + ::: {.title} + **Example: Overriding a type check** + ::: + ```nix + nixThings = mkOption { + description = "words that start with 'nix'"; + type = types.str // { + check = (x: lib.hasPrefix "nix" x) + }; + }; + ``` + ::: + +`merge` + +: Function to merge the options values when multiple values are set. + The function takes two parameters, `loc` the option path as a list + of strings, and `defs` the list of defined values as a list. It is + possible to override a type merge function for custom needs. + +## Custom Types {#sec-option-types-custom} + +Custom types can be created with the `mkOptionType` function. As type +creation includes some more complex topics such as submodule handling, +it is recommended to get familiar with `types.nix` code before creating +a new type. + +The only required parameter is `name`. + +`name` + +: A string representation of the type function name. + +`definition` + +: Description of the type used in documentation. Give information of + the type and any of its arguments. + +`check` + +: A function to type check the definition value. Takes the definition + value as a parameter and returns a boolean indicating the type check + result, `true` for success and `false` for failure. + +`merge` + +: A function to merge multiple definitions values. Takes two + parameters: + + *`loc`* + + : The option path as a list of strings, e.g. `["boot" "loader + "grub" "enable"]`. + + *`defs`* + + : The list of sets of defined `value` and `file` where the value + was defined, e.g. `[ { + file = "/foo.nix"; value = 1; } { file = "/bar.nix"; value = 2 } + ]`. The `merge` function should return the merged value + or throw an error in case the values are impossible or not meant + to be merged. + +`getSubOptions` + +: For composed types that can take a submodule as type parameter, this + function generate sub-options documentation. It takes the current + option prefix as a list and return the set of sub-options. Usually + defined in a recursive manner by adding a term to the prefix, e.g. + `prefix: + elemType.getSubOptions (prefix ++ + ["prefix"])` where *`"prefix"`* is the newly added prefix. + +`getSubModules` + +: For composed types that can take a submodule as type parameter, this + function should return the type parameters submodules. If the type + parameter is called `elemType`, the function should just recursively + look into submodules by returning `elemType.getSubModules;`. + +`substSubModules` + +: For composed types that can take a submodule as type parameter, this + function can be used to substitute the parameter of a submodule + type. It takes a module as parameter and return the type with the + submodule options substituted. It is usually defined as a type + function call with a recursive call to `substSubModules`, e.g for a + type `composedType` that take an `elemtype` type parameter, this + function should be defined as `m: + composedType (elemType.substSubModules m)`. + +`typeMerge` + +: A function to merge multiple type declarations. Takes the type to + merge `functor` as parameter. A `null` return value means that type + cannot be merged. + + *`f`* + + : The type to merge `functor`. + + Note: There is a generic `defaultTypeMerge` that work with most of + value and composed types. + +`functor` + +: An attribute set representing the type. It is used for type + operations and has the following keys: + + `type` + + : The type function. + + `wrapped` + + : Holds the type parameter for composed types. + + `payload` + + : Holds the value parameter for value types. The types that have a + `payload` are the `enum`, `separatedString` and `submodule` + types. + + `binOp` + + : A binary operation that can merge the payloads of two same + types. Defined as a function that take two payloads as + parameters and return the payloads merged. diff --git a/nixos/doc/manual/development/option-types.xml b/nixos/doc/manual/development/option-types.xml deleted file mode 100644 index 3d2191e2f3f..00000000000 --- a/nixos/doc/manual/development/option-types.xml +++ /dev/null @@ -1,914 +0,0 @@ -<section xmlns="http://docbook.org/ns/docbook" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:xi="http://www.w3.org/2001/XInclude" - version="5.0" - xml:id="sec-option-types"> - <title>Options Types</title> - - <para> - Option types are a way to put constraints on the values a module option can - take. Types are also responsible of how values are merged in case of multiple - value definitions. - </para> - - <section xml:id="sec-option-types-basic"> - <title>Basic Types</title> - - <para> - Basic types are the simplest available types in the module system. Basic - types include multiple string types that mainly differ in how definition - merging is handled. - </para> - - <variablelist> - <varlistentry> - <term> - <varname>types.bool</varname> - </term> - <listitem> - <para> - A boolean, its values can be <literal>true</literal> or - <literal>false</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.path</varname> - </term> - <listitem> - <para> - A filesystem path, defined as anything that when coerced to a string - starts with a slash. Even if derivations can be considered as path, the - more specific <literal>types.package</literal> should be preferred. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.package</varname> - </term> - <listitem> - <para> - A derivation or a store path. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.anything</varname> - </term> - <listitem> - <para> - A type that accepts any value and recursively merges attribute sets together. - This type is recommended when the option type is unknown. - <example xml:id="ex-types-anything"> - <title><literal>types.anything</literal> Example</title> - <para> - Two definitions of this type like -<programlisting> -{ - str = lib.mkDefault "foo"; - pkg.hello = pkgs.hello; - fun.fun = x: x + 1; -} -</programlisting> -<programlisting> -{ - str = lib.mkIf true "bar"; - pkg.gcc = pkgs.gcc; - fun.fun = lib.mkForce (x: x + 2); -} -</programlisting> - will get merged to -<programlisting> -{ - str = "bar"; - pkg.gcc = pkgs.gcc; - pkg.hello = pkgs.hello; - fun.fun = x: x + 2; -} -</programlisting> - </para> - </example> - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.attrs</varname> - </term> - <listitem> - <para> - A free-form attribute set. - <warning><para> - This type will be deprecated in the future because it doesn't recurse - into attribute sets, silently drops earlier attribute definitions, and - doesn't discharge <literal>lib.mkDefault</literal>, <literal>lib.mkIf - </literal> and co. For allowing arbitrary attribute sets, prefer - <literal>types.attrsOf types.anything</literal> instead which doesn't - have these problems. - </para></warning> - </para> - </listitem> - </varlistentry> - </variablelist> - - <para> - Integer-related types: - </para> - - <variablelist> - <varlistentry> - <term> - <varname>types.int</varname> - </term> - <listitem> - <para> - A signed integer. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.ints.{s8, s16, s32}</varname> - </term> - <listitem> - <para> - Signed integers with a fixed length (8, 16 or 32 bits). They go from - <inlineequation><mathphrase>−2<superscript>n</superscript>/2</mathphrase> - </inlineequation> to <inlineequation> - <mathphrase>2<superscript>n</superscript>/2−1</mathphrase> - </inlineequation> respectively (e.g. <literal>−128</literal> to - <literal>127</literal> for 8 bits). - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.ints.unsigned</varname> - </term> - <listitem> - <para> - An unsigned integer (that is >= 0). - </para> - </listitem> - </varlistentry> - <varlistentry xml:id='types.ints.ux'> - <term> - <varname>types.ints.{u8, u16, u32}</varname> - </term> - <listitem> - <para> - Unsigned integers with a fixed length (8, 16 or 32 bits). They go from - <inlineequation><mathphrase>0</mathphrase></inlineequation> to - <inlineequation> - <mathphrase>2<superscript>n</superscript>−1</mathphrase> - </inlineequation> respectively (e.g. <literal>0</literal> to - <literal>255</literal> for 8 bits). - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.ints.positive</varname> - </term> - <listitem> - <para> - A positive integer (that is > 0). - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.port</varname> - </term> - <listitem> - <para> - A port number. This type is an alias to - <link linkend='types.ints.ux'><varname>types.ints.u16</varname></link>. - </para> - </listitem> - </varlistentry> - </variablelist> - - <para> - String-related types: - </para> - - <variablelist> - <varlistentry> - <term> - <varname>types.str</varname> - </term> - <listitem> - <para> - A string. Multiple definitions cannot be merged. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.lines</varname> - </term> - <listitem> - <para> - A string. Multiple definitions are concatenated with a new line - <literal>"\n"</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.commas</varname> - </term> - <listitem> - <para> - A string. Multiple definitions are concatenated with a comma - <literal>","</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.envVar</varname> - </term> - <listitem> - <para> - A string. Multiple definitions are concatenated with a collon - <literal>":"</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.strMatching</varname> - </term> - <listitem> - <para> - A string matching a specific regular expression. Multiple definitions - cannot be merged. The regular expression is processed using - <literal>builtins.match</literal>. - </para> - </listitem> - </varlistentry> - </variablelist> - </section> - - <section xml:id="sec-option-types-value"> - <title>Value Types</title> - - <para> - Value types are types that take a value parameter. - </para> - - <variablelist> - <varlistentry> - <term> - <varname>types.enum</varname> <replaceable>l</replaceable> - </term> - <listitem> - <para> - One element of the list <replaceable>l</replaceable>, e.g. - <literal>types.enum [ "left" "right" ]</literal>. Multiple definitions - cannot be merged. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.separatedString</varname> <replaceable>sep</replaceable> - </term> - <listitem> - <para> - A string with a custom separator <replaceable>sep</replaceable>, e.g. - <literal>types.separatedString "|"</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.ints.between</varname> <replaceable>lowest</replaceable> <replaceable>highest</replaceable> - </term> - <listitem> - <para> - An integer between <replaceable>lowest</replaceable> and - <replaceable>highest</replaceable> (both inclusive). Useful for creating - types like <literal>types.port</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.submodule</varname> <replaceable>o</replaceable> - </term> - <listitem> - <para> - A set of sub options <replaceable>o</replaceable>. - <replaceable>o</replaceable> can be an attribute set, a function - returning an attribute set, or a path to a file containing such a value. Submodules are used in - composed types to create modular options. This is equivalent to - <literal>types.submoduleWith { modules = toList o; shorthandOnlyDefinesConfig = true; }</literal>. - Submodules are detailed in - <xref - linkend='section-option-types-submodule' />. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.submoduleWith</varname> { - <replaceable>modules</replaceable>, - <replaceable>specialArgs</replaceable> ? {}, - <replaceable>shorthandOnlyDefinesConfig</replaceable> ? false } - </term> - <listitem> - <para> - Like <varname>types.submodule</varname>, but more flexible and with better defaults. - It has parameters - <itemizedlist> - <listitem><para> - <replaceable>modules</replaceable> - A list of modules to use by default for this submodule type. This gets combined - with all option definitions to build the final list of modules that will be included. - <note><para> - Only options defined with this argument are included in rendered documentation. - </para></note> - </para></listitem> - <listitem><para> - <replaceable>specialArgs</replaceable> - An attribute set of extra arguments to be passed to the module functions. - The option <literal>_module.args</literal> should be used instead - for most arguments since it allows overriding. <replaceable>specialArgs</replaceable> should only be - used for arguments that can't go through the module fixed-point, because of - infinite recursion or other problems. An example is overriding the - <varname>lib</varname> argument, because <varname>lib</varname> itself is used - to define <literal>_module.args</literal>, which makes using - <literal>_module.args</literal> to define it impossible. - </para></listitem> - <listitem><para> - <replaceable>shorthandOnlyDefinesConfig</replaceable> - Whether definitions of this type should default to the <literal>config</literal> - section of a module (see <xref linkend='ex-module-syntax'/>) if it is an attribute - set. Enabling this only has a benefit when the submodule defines an option named - <literal>config</literal> or <literal>options</literal>. In such a case it would - allow the option to be set with <literal>the-submodule.config = "value"</literal> - instead of requiring <literal>the-submodule.config.config = "value"</literal>. - This is because only when modules <emphasis>don't</emphasis> set the - <literal>config</literal> or <literal>options</literal> keys, all keys are interpreted - as option definitions in the <literal>config</literal> section. Enabling this option - implicitly puts all attributes in the <literal>config</literal> section. - </para> - <para> - With this option enabled, defining a non-<literal>config</literal> section requires - using a function: <literal>the-submodule = { ... }: { options = { ... }; }</literal>. - </para></listitem> - </itemizedlist> - </para> - </listitem> - </varlistentry> - </variablelist> - </section> - - <section xml:id="sec-option-types-composed"> - <title>Composed Types</title> - - <para> - Composed types are types that take a type as parameter. <literal>listOf - int</literal> and <literal>either int str</literal> are examples of composed - types. - </para> - - <variablelist> - <varlistentry> - <term> - <varname>types.listOf</varname> <replaceable>t</replaceable> - </term> - <listitem> - <para> - A list of <replaceable>t</replaceable> type, e.g. <literal>types.listOf - int</literal>. Multiple definitions are merged with list concatenation. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.attrsOf</varname> <replaceable>t</replaceable> - </term> - <listitem> - <para> - An attribute set of where all the values are of - <replaceable>t</replaceable> type. Multiple definitions result in the - joined attribute set. - <note><para> - This type is <emphasis>strict</emphasis> in its values, which in turn - means attributes cannot depend on other attributes. See <varname> - types.lazyAttrsOf</varname> for a lazy version. - </para></note> - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.lazyAttrsOf</varname> <replaceable>t</replaceable> - </term> - <listitem> - <para> - An attribute set of where all the values are of - <replaceable>t</replaceable> type. Multiple definitions result in the - joined attribute set. This is the lazy version of <varname>types.attrsOf - </varname>, allowing attributes to depend on each other. - <warning><para> - This version does not fully support conditional definitions! With an - option <varname>foo</varname> of this type and a definition - <literal>foo.attr = lib.mkIf false 10</literal>, evaluating - <literal>foo ? attr</literal> will return <literal>true</literal> - even though it should be false. Accessing the value will then throw - an error. For types <replaceable>t</replaceable> that have an - <literal>emptyValue</literal> defined, that value will be returned - instead of throwing an error. So if the type of <literal>foo.attr</literal> - was <literal>lazyAttrsOf (nullOr int)</literal>, <literal>null</literal> - would be returned instead for the same <literal>mkIf false</literal> definition. - </para></warning> - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.nullOr</varname> <replaceable>t</replaceable> - </term> - <listitem> - <para> - <literal>null</literal> or type <replaceable>t</replaceable>. Multiple - definitions are merged according to type <replaceable>t</replaceable>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.uniq</varname> <replaceable>t</replaceable> - </term> - <listitem> - <para> - Ensures that type <replaceable>t</replaceable> cannot be merged. It is - used to ensure option definitions are declared only once. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.either</varname> <replaceable>t1</replaceable> <replaceable>t2</replaceable> - </term> - <listitem> - <para> - Type <replaceable>t1</replaceable> or type <replaceable>t2</replaceable>, - e.g. <literal>with types; either int str</literal>. Multiple definitions - cannot be merged. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.oneOf</varname> [ <replaceable>t1</replaceable> <replaceable>t2</replaceable> ... ] - </term> - <listitem> - <para> - Type <replaceable>t1</replaceable> or type <replaceable>t2</replaceable> and so forth, - e.g. <literal>with types; oneOf [ int str bool ]</literal>. Multiple definitions - cannot be merged. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>types.coercedTo</varname> <replaceable>from</replaceable> <replaceable>f</replaceable> <replaceable>to</replaceable> - </term> - <listitem> - <para> - Type <replaceable>to</replaceable> or type - <replaceable>from</replaceable> which will be coerced to type - <replaceable>to</replaceable> using function <replaceable>f</replaceable> - which takes an argument of type <replaceable>from</replaceable> and - return a value of type <replaceable>to</replaceable>. Can be used to - preserve backwards compatibility of an option if its type was changed. - </para> - </listitem> - </varlistentry> - </variablelist> - </section> - - <section xml:id='section-option-types-submodule'> - <title>Submodule</title> - - <para> - <literal>submodule</literal> is a very powerful type that defines a set of - sub-options that are handled like a separate module. - </para> - - <para> - It takes a parameter <replaceable>o</replaceable>, that should be a set, or - a function returning a set with an <literal>options</literal> key defining - the sub-options. Submodule option definitions are type-checked accordingly - to the <literal>options</literal> declarations. Of course, you can nest - submodule option definitons for even higher modularity. - </para> - - <para> - The option set can be defined directly - (<xref linkend='ex-submodule-direct' />) or as reference - (<xref linkend='ex-submodule-reference' />). - </para> - - <example xml:id='ex-submodule-direct'> - <title>Directly defined submodule</title> -<screen> -options.mod = mkOption { - description = "submodule example"; - type = with types; submodule { - options = { - foo = mkOption { - type = int; - }; - bar = mkOption { - type = str; - }; - }; - }; -};</screen> - </example> - - <example xml:id='ex-submodule-reference'> - <title>Submodule defined as a reference</title> -<screen> -let - modOptions = { - options = { - foo = mkOption { - type = int; - }; - bar = mkOption { - type = int; - }; - }; - }; -in -options.mod = mkOption { - description = "submodule example"; - type = with types; submodule modOptions; -};</screen> - </example> - - <para> - The <literal>submodule</literal> type is especially interesting when used - with composed types like <literal>attrsOf</literal> or - <literal>listOf</literal>. When composed with <literal>listOf</literal> - (<xref linkend='ex-submodule-listof-declaration' />), - <literal>submodule</literal> allows multiple definitions of the submodule - option set (<xref linkend='ex-submodule-listof-definition' />). - </para> - - <example xml:id='ex-submodule-listof-declaration'> - <title>Declaration of a list of submodules</title> -<screen> -options.mod = mkOption { - description = "submodule example"; - type = with types; listOf (submodule { - options = { - foo = mkOption { - type = int; - }; - bar = mkOption { - type = str; - }; - }; - }); -};</screen> - </example> - - <example xml:id='ex-submodule-listof-definition'> - <title>Definition of a list of submodules</title> -<screen> -config.mod = [ - { foo = 1; bar = "one"; } - { foo = 2; bar = "two"; } -];</screen> - </example> - - <para> - When composed with <literal>attrsOf</literal> - (<xref linkend='ex-submodule-attrsof-declaration' />), - <literal>submodule</literal> allows multiple named definitions of the - submodule option set (<xref linkend='ex-submodule-attrsof-definition' />). - </para> - - <example xml:id='ex-submodule-attrsof-declaration'> - <title>Declaration of attribute sets of submodules</title> -<screen> -options.mod = mkOption { - description = "submodule example"; - type = with types; attrsOf (submodule { - options = { - foo = mkOption { - type = int; - }; - bar = mkOption { - type = str; - }; - }; - }); -};</screen> - </example> - - <example xml:id='ex-submodule-attrsof-definition'> - <title>Declaration of attribute sets of submodules</title> -<screen> -config.mod.one = { foo = 1; bar = "one"; }; -config.mod.two = { foo = 2; bar = "two"; };</screen> - </example> - </section> - - <section xml:id="sec-option-types-extending"> - <title>Extending types</title> - - <para> - Types are mainly characterized by their <literal>check</literal> and - <literal>merge</literal> functions. - </para> - - <variablelist> - <varlistentry> - <term> - <varname>check</varname> - </term> - <listitem> - <para> - The function to type check the value. Takes a value as parameter and - return a boolean. It is possible to extend a type check with the - <literal>addCheck</literal> function - (<xref - linkend='ex-extending-type-check-1' />), or to fully - override the check function - (<xref linkend='ex-extending-type-check-2' />). - </para> - <example xml:id='ex-extending-type-check-1'> - <title>Adding a type check</title> -<screen> -byte = mkOption { - description = "An integer between 0 and 255."; - type = types.addCheck types.int (x: x >= 0 && x <= 255); -};</screen> - </example> - <example xml:id='ex-extending-type-check-2'> - <title>Overriding a type check</title> -<screen> -nixThings = mkOption { - description = "words that start with 'nix'"; - type = types.str // { - check = (x: lib.hasPrefix "nix" x) - }; -};</screen> - </example> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>merge</varname> - </term> - <listitem> - <para> - Function to merge the options values when multiple values are set. The - function takes two parameters, <literal>loc</literal> the option path as - a list of strings, and <literal>defs</literal> the list of defined values - as a list. It is possible to override a type merge function for custom - needs. - </para> - </listitem> - </varlistentry> - </variablelist> - </section> - - <section xml:id="sec-option-types-custom"> - <title>Custom Types</title> - - <para> - Custom types can be created with the <literal>mkOptionType</literal> - function. As type creation includes some more complex topics such as - submodule handling, it is recommended to get familiar with - <filename - xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/types.nix">types.nix</filename> - code before creating a new type. - </para> - - <para> - The only required parameter is <literal>name</literal>. - </para> - - <variablelist> - <varlistentry> - <term> - <varname>name</varname> - </term> - <listitem> - <para> - A string representation of the type function name. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>definition</varname> - </term> - <listitem> - <para> - Description of the type used in documentation. Give information of the - type and any of its arguments. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>check</varname> - </term> - <listitem> - <para> - A function to type check the definition value. Takes the definition value - as a parameter and returns a boolean indicating the type check result, - <literal>true</literal> for success and <literal>false</literal> for - failure. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>merge</varname> - </term> - <listitem> - <para> - A function to merge multiple definitions values. Takes two parameters: - </para> - <variablelist> - <varlistentry> - <term> - <replaceable>loc</replaceable> - </term> - <listitem> - <para> - The option path as a list of strings, e.g. <literal>["boot" "loader - "grub" "enable"]</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <replaceable>defs</replaceable> - </term> - <listitem> - <para> - The list of sets of defined <literal>value</literal> and - <literal>file</literal> where the value was defined, e.g. <literal>[ { - file = "/foo.nix"; value = 1; } { file = "/bar.nix"; value = 2 } - ]</literal>. The <literal>merge</literal> function should return the - merged value or throw an error in case the values are impossible or - not meant to be merged. - </para> - </listitem> - </varlistentry> - </variablelist> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>getSubOptions</varname> - </term> - <listitem> - <para> - For composed types that can take a submodule as type parameter, this - function generate sub-options documentation. It takes the current option - prefix as a list and return the set of sub-options. Usually defined in a - recursive manner by adding a term to the prefix, e.g. <literal>prefix: - elemType.getSubOptions (prefix ++ - [<replaceable>"prefix"</replaceable>])</literal> where - <replaceable>"prefix"</replaceable> is the newly added prefix. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>getSubModules</varname> - </term> - <listitem> - <para> - For composed types that can take a submodule as type parameter, this - function should return the type parameters submodules. If the type - parameter is called <literal>elemType</literal>, the function should just - recursively look into submodules by returning - <literal>elemType.getSubModules;</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>substSubModules</varname> - </term> - <listitem> - <para> - For composed types that can take a submodule as type parameter, this - function can be used to substitute the parameter of a submodule type. It - takes a module as parameter and return the type with the submodule - options substituted. It is usually defined as a type function call with a - recursive call to <literal>substSubModules</literal>, e.g for a type - <literal>composedType</literal> that take an <literal>elemtype</literal> - type parameter, this function should be defined as <literal>m: - composedType (elemType.substSubModules m)</literal>. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>typeMerge</varname> - </term> - <listitem> - <para> - A function to merge multiple type declarations. Takes the type to merge - <literal>functor</literal> as parameter. A <literal>null</literal> return - value means that type cannot be merged. - </para> - <variablelist> - <varlistentry> - <term> - <replaceable>f</replaceable> - </term> - <listitem> - <para> - The type to merge <literal>functor</literal>. - </para> - </listitem> - </varlistentry> - </variablelist> - <para> - Note: There is a generic <literal>defaultTypeMerge</literal> that work - with most of value and composed types. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>functor</varname> - </term> - <listitem> - <para> - An attribute set representing the type. It is used for type operations - and has the following keys: - </para> - <variablelist> - <varlistentry> - <term> - <varname>type</varname> - </term> - <listitem> - <para> - The type function. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>wrapped</varname> - </term> - <listitem> - <para> - Holds the type parameter for composed types. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>payload</varname> - </term> - <listitem> - <para> - Holds the value parameter for value types. The types that have a - <literal>payload</literal> are the <literal>enum</literal>, - <literal>separatedString</literal> and <literal>submodule</literal> - types. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term> - <varname>binOp</varname> - </term> - <listitem> - <para> - A binary operation that can merge the payloads of two same types. - Defined as a function that take two payloads as parameters and return - the payloads merged. - </para> - </listitem> - </varlistentry> - </variablelist> - </listitem> - </varlistentry> - </variablelist> - </section> -</section> diff --git a/nixos/doc/manual/development/writing-modules.xml b/nixos/doc/manual/development/writing-modules.xml index a1efbeac723..245c49dbb7e 100644 --- a/nixos/doc/manual/development/writing-modules.xml +++ b/nixos/doc/manual/development/writing-modules.xml @@ -180,7 +180,7 @@ in { </programlisting> </example> <xi:include href="../from_md/development/option-declarations.section.xml" /> - <xi:include href="option-types.xml" /> + <xi:include href="../from_md/development/option-types.section.xml" /> <xi:include href="option-def.xml" /> <xi:include href="../from_md/development/assertions.section.xml" /> <xi:include href="meta-attributes.xml" /> diff --git a/nixos/doc/manual/from_md/development/option-types.section.xml b/nixos/doc/manual/from_md/development/option-types.section.xml new file mode 100644 index 00000000000..c83ffa2add5 --- /dev/null +++ b/nixos/doc/manual/from_md/development/option-types.section.xml @@ -0,0 +1,987 @@ +<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-option-types"> + <title>Options Types</title> + <para> + Option types are a way to put constraints on the values a module + option can take. Types are also responsible of how values are merged + in case of multiple value definitions. + </para> + <section xml:id="sec-option-types-basic"> + <title>Basic Types</title> + <para> + Basic types are the simplest available types in the module system. + Basic types include multiple string types that mainly differ in + how definition merging is handled. + </para> + <variablelist> + <varlistentry> + <term> + <literal>types.bool</literal> + </term> + <listitem> + <para> + A boolean, its values can be <literal>true</literal> or + <literal>false</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.path</literal> + </term> + <listitem> + <para> + A filesystem path, defined as anything that when coerced to + a string starts with a slash. Even if derivations can be + considered as path, the more specific + <literal>types.package</literal> should be preferred. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.package</literal> + </term> + <listitem> + <para> + A derivation or a store path. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.anything</literal> + </term> + <listitem> + <para> + A type that accepts any value and recursively merges + attribute sets together. This type is recommended when the + option type is unknown. + </para> + <anchor xml:id="ex-types-anything" /> + <para> + <emphasis role="strong">Example: + <literal>types.anything</literal> Example</emphasis> + </para> + <para> + Two definitions of this type like + </para> + <programlisting language="bash"> +{ + str = lib.mkDefault "foo"; + pkg.hello = pkgs.hello; + fun.fun = x: x + 1; +} +</programlisting> + <programlisting language="bash"> +{ + str = lib.mkIf true "bar"; + pkg.gcc = pkgs.gcc; + fun.fun = lib.mkForce (x: x + 2); +} +</programlisting> + <para> + will get merged to + </para> + <programlisting language="bash"> +{ + str = "bar"; + pkg.gcc = pkgs.gcc; + pkg.hello = pkgs.hello; + fun.fun = x: x + 2; +} +</programlisting> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.attrs</literal> + </term> + <listitem> + <para> + A free-form attribute set. + </para> + <warning> + <para> + This type will be deprecated in the future because it + doesn't recurse into attribute sets, silently drops + earlier attribute definitions, and doesn't discharge + <literal>lib.mkDefault</literal>, + <literal>lib.mkIf</literal> and co. For allowing arbitrary + attribute sets, prefer + <literal>types.attrsOf types.anything</literal> instead + which doesn't have these problems. + </para> + </warning> + </listitem> + </varlistentry> + </variablelist> + <para> + Integer-related types: + </para> + <variablelist> + <varlistentry> + <term> + <literal>types.int</literal> + </term> + <listitem> + <para> + A signed integer. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.ints.{s8, s16, s32}</literal> + </term> + <listitem> + <para> + Signed integers with a fixed length (8, 16 or 32 bits). They + go from −2^n/2 to 2^n/2−1 respectively (e.g. + <literal>−128</literal> to <literal>127</literal> for 8 + bits). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.ints.unsigned</literal> + </term> + <listitem> + <para> + An unsigned integer (that is >= 0). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.ints.{u8, u16, u32}</literal> + </term> + <listitem> + <para> + Unsigned integers with a fixed length (8, 16 or 32 bits). + They go from 0 to 2^n−1 respectively (e.g. + <literal>0</literal> to <literal>255</literal> for 8 bits). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.ints.positive</literal> + </term> + <listitem> + <para> + A positive integer (that is > 0). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.port</literal> + </term> + <listitem> + <para> + A port number. This type is an alias to + <literal>types.ints.u16</literal>. + </para> + </listitem> + </varlistentry> + </variablelist> + <para> + String-related types: + </para> + <variablelist> + <varlistentry> + <term> + <literal>types.str</literal> + </term> + <listitem> + <para> + A string. Multiple definitions cannot be merged. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.lines</literal> + </term> + <listitem> + <para> + A string. Multiple definitions are concatenated with a new + line <literal>"\n"</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.commas</literal> + </term> + <listitem> + <para> + A string. Multiple definitions are concatenated with a comma + <literal>","</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.envVar</literal> + </term> + <listitem> + <para> + A string. Multiple definitions are concatenated with a + collon <literal>":"</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.strMatching</literal> + </term> + <listitem> + <para> + A string matching a specific regular expression. Multiple + definitions cannot be merged. The regular expression is + processed using <literal>builtins.match</literal>. + </para> + </listitem> + </varlistentry> + </variablelist> + </section> + <section xml:id="sec-option-types-value"> + <title>Value Types</title> + <para> + Value types are types that take a value parameter. + </para> + <variablelist> + <varlistentry> + <term> + <literal>types.enum</literal> + <emphasis><literal>l</literal></emphasis> + </term> + <listitem> + <para> + One element of the list + <emphasis><literal>l</literal></emphasis>, e.g. + <literal>types.enum [ "left" "right" ]</literal>. + Multiple definitions cannot be merged. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.separatedString</literal> + <emphasis><literal>sep</literal></emphasis> + </term> + <listitem> + <para> + A string with a custom separator + <emphasis><literal>sep</literal></emphasis>, e.g. + <literal>types.separatedString "|"</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.ints.between</literal> + <emphasis><literal>lowest highest</literal></emphasis> + </term> + <listitem> + <para> + An integer between + <emphasis><literal>lowest</literal></emphasis> and + <emphasis><literal>highest</literal></emphasis> (both + inclusive). Useful for creating types like + <literal>types.port</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.submodule</literal> + <emphasis><literal>o</literal></emphasis> + </term> + <listitem> + <para> + A set of sub options + <emphasis><literal>o</literal></emphasis>. + <emphasis><literal>o</literal></emphasis> can be an + attribute set, a function returning an attribute set, or a + path to a file containing such a value. Submodules are used + in composed types to create modular options. This is + equivalent to + <literal>types.submoduleWith { modules = toList o; shorthandOnlyDefinesConfig = true; }</literal>. + Submodules are detailed in + <link linkend="section-option-types-submodule">Submodule</link>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.submoduleWith</literal> { + <emphasis><literal>modules</literal></emphasis>, + <emphasis><literal>specialArgs</literal></emphasis> ? {}, + <emphasis><literal>shorthandOnlyDefinesConfig</literal></emphasis> + ? false } + </term> + <listitem> + <para> + Like <literal>types.submodule</literal>, but more flexible + and with better defaults. It has parameters + </para> + <itemizedlist> + <listitem> + <para> + <emphasis><literal>modules</literal></emphasis> A list + of modules to use by default for this submodule type. + This gets combined with all option definitions to build + the final list of modules that will be included. + </para> + <note> + <para> + Only options defined with this argument are included + in rendered documentation. + </para> + </note> + </listitem> + <listitem> + <para> + <emphasis><literal>specialArgs</literal></emphasis> An + attribute set of extra arguments to be passed to the + module functions. The option + <literal>_module.args</literal> should be used instead + for most arguments since it allows overriding. + <emphasis><literal>specialArgs</literal></emphasis> + should only be used for arguments that can't go through + the module fixed-point, because of infinite recursion or + other problems. An example is overriding the + <literal>lib</literal> argument, because + <literal>lib</literal> itself is used to define + <literal>_module.args</literal>, which makes using + <literal>_module.args</literal> to define it impossible. + </para> + </listitem> + <listitem> + <para> + <emphasis><literal>shorthandOnlyDefinesConfig</literal></emphasis> + Whether definitions of this type should default to the + <literal>config</literal> section of a module (see + <link linkend="ex-module-syntax">Example: Structure of + NixOS Modules</link>) if it is an attribute set. + Enabling this only has a benefit when the submodule + defines an option named <literal>config</literal> or + <literal>options</literal>. In such a case it would + allow the option to be set with + <literal>the-submodule.config = "value"</literal> + instead of requiring + <literal>the-submodule.config.config = "value"</literal>. + This is because only when modules + <emphasis>don't</emphasis> set the + <literal>config</literal> or <literal>options</literal> + keys, all keys are interpreted as option definitions in + the <literal>config</literal> section. Enabling this + option implicitly puts all attributes in the + <literal>config</literal> section. + </para> + <para> + With this option enabled, defining a + non-<literal>config</literal> section requires using a + function: + <literal>the-submodule = { ... }: { options = { ... }; }</literal>. + </para> + </listitem> + </itemizedlist> + </listitem> + </varlistentry> + </variablelist> + </section> + <section xml:id="sec-option-types-composed"> + <title>Composed Types</title> + <para> + Composed types are types that take a type as parameter. + <literal>listOf int</literal> and + <literal>either int str</literal> are examples of composed types. + </para> + <variablelist> + <varlistentry> + <term> + <literal>types.listOf</literal> + <emphasis><literal>t</literal></emphasis> + </term> + <listitem> + <para> + A list of <emphasis><literal>t</literal></emphasis> type, + e.g. <literal>types.listOf int</literal>. Multiple + definitions are merged with list concatenation. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.attrsOf</literal> + <emphasis><literal>t</literal></emphasis> + </term> + <listitem> + <para> + An attribute set of where all the values are of + <emphasis><literal>t</literal></emphasis> type. Multiple + definitions result in the joined attribute set. + </para> + <note> + <para> + This type is <emphasis>strict</emphasis> in its values, + which in turn means attributes cannot depend on other + attributes. See <literal> types.lazyAttrsOf</literal> for + a lazy version. + </para> + </note> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.lazyAttrsOf</literal> + <emphasis><literal>t</literal></emphasis> + </term> + <listitem> + <para> + An attribute set of where all the values are of + <emphasis><literal>t</literal></emphasis> type. Multiple + definitions result in the joined attribute set. This is the + lazy version of <literal>types.attrsOf </literal>, allowing + attributes to depend on each other. + </para> + <warning> + <para> + This version does not fully support conditional + definitions! With an option <literal>foo</literal> of this + type and a definition + <literal>foo.attr = lib.mkIf false 10</literal>, + evaluating <literal>foo ? attr</literal> will return + <literal>true</literal> even though it should be false. + Accessing the value will then throw an error. For types + <emphasis><literal>t</literal></emphasis> that have an + <literal>emptyValue</literal> defined, that value will be + returned instead of throwing an error. So if the type of + <literal>foo.attr</literal> was + <literal>lazyAttrsOf (nullOr int)</literal>, + <literal>null</literal> would be returned instead for the + same <literal>mkIf false</literal> definition. + </para> + </warning> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.nullOr</literal> + <emphasis><literal>t</literal></emphasis> + </term> + <listitem> + <para> + <literal>null</literal> or type + <emphasis><literal>t</literal></emphasis>. Multiple + definitions are merged according to type + <emphasis><literal>t</literal></emphasis>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.uniq</literal> + <emphasis><literal>t</literal></emphasis> + </term> + <listitem> + <para> + Ensures that type <emphasis><literal>t</literal></emphasis> + cannot be merged. It is used to ensure option definitions + are declared only once. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.either</literal> + <emphasis><literal>t1 t2</literal></emphasis> + </term> + <listitem> + <para> + Type <emphasis><literal>t1</literal></emphasis> or type + <emphasis><literal>t2</literal></emphasis>, e.g. + <literal>with types; either int str</literal>. Multiple + definitions cannot be merged. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.oneOf</literal> [ + <emphasis><literal>t1 t2</literal></emphasis> ... ] + </term> + <listitem> + <para> + Type <emphasis><literal>t1</literal></emphasis> or type + <emphasis><literal>t2</literal></emphasis> and so forth, + e.g. <literal>with types; oneOf [ int str bool ]</literal>. + Multiple definitions cannot be merged. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>types.coercedTo</literal> + <emphasis><literal>from f to</literal></emphasis> + </term> + <listitem> + <para> + Type <emphasis><literal>to</literal></emphasis> or type + <emphasis><literal>from</literal></emphasis> which will be + coerced to type <emphasis><literal>to</literal></emphasis> + using function <emphasis><literal>f</literal></emphasis> + which takes an argument of type + <emphasis><literal>from</literal></emphasis> and return a + value of type <emphasis><literal>to</literal></emphasis>. + Can be used to preserve backwards compatibility of an option + if its type was changed. + </para> + </listitem> + </varlistentry> + </variablelist> + </section> + <section xml:id="section-option-types-submodule"> + <title>Submodule</title> + <para> + <literal>submodule</literal> is a very powerful type that defines + a set of sub-options that are handled like a separate module. + </para> + <para> + It takes a parameter <emphasis><literal>o</literal></emphasis>, + that should be a set, or a function returning a set with an + <literal>options</literal> key defining the sub-options. Submodule + option definitions are type-checked accordingly to the + <literal>options</literal> declarations. Of course, you can nest + submodule option definitons for even higher modularity. + </para> + <para> + The option set can be defined directly + (<link linkend="ex-submodule-direct">Example: Directly defined + submodule</link>) or as reference + (<link linkend="ex-submodule-reference">Example: Submodule defined + as a reference</link>). + </para> + <anchor xml:id="ex-submodule-direct" /> + <para> + <emphasis role="strong">Example: Directly defined + submodule</emphasis> + </para> + <programlisting language="bash"> +options.mod = mkOption { + description = "submodule example"; + type = with types; submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }; +}; +</programlisting> + <anchor xml:id="ex-submodule-reference" /> + <para> + <emphasis role="strong">Example: Submodule defined as a + reference</emphasis> + </para> + <programlisting language="bash"> +let + modOptions = { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = int; + }; + }; + }; +in +options.mod = mkOption { + description = "submodule example"; + type = with types; submodule modOptions; +}; +</programlisting> + <para> + The <literal>submodule</literal> type is especially interesting + when used with composed types like <literal>attrsOf</literal> or + <literal>listOf</literal>. When composed with + <literal>listOf</literal> + (<link linkend="ex-submodule-listof-declaration">Example: + Declaration of a list of submodules</link>), + <literal>submodule</literal> allows multiple definitions of the + submodule option set + (<link linkend="ex-submodule-listof-definition">Example: + Definition of a list of submodules</link>). + </para> + <anchor xml:id="ex-submodule-listof-declaration" /> + <para> + <emphasis role="strong">Example: Declaration of a list of + submodules</emphasis> + </para> + <programlisting language="bash"> +options.mod = mkOption { + description = "submodule example"; + type = with types; listOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +}; +</programlisting> + <anchor xml:id="ex-submodule-listof-definition" /> + <para> + <emphasis role="strong">Example: Definition of a list of + submodules</emphasis> + </para> + <programlisting language="bash"> +config.mod = [ + { foo = 1; bar = "one"; } + { foo = 2; bar = "two"; } +]; +</programlisting> + <para> + When composed with <literal>attrsOf</literal> + (<link linkend="ex-submodule-attrsof-declaration">Example: + Declaration of attribute sets of submodules</link>), + <literal>submodule</literal> allows multiple named definitions of + the submodule option set + (<link linkend="ex-submodule-attrsof-definition">Example: + Definition of attribute sets of submodules</link>). + </para> + <anchor xml:id="ex-submodule-attrsof-declaration" /> + <para> + <emphasis role="strong">Example: Declaration of attribute sets of + submodules</emphasis> + </para> + <programlisting language="bash"> +options.mod = mkOption { + description = "submodule example"; + type = with types; attrsOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +}; +</programlisting> + <anchor xml:id="ex-submodule-attrsof-definition" /> + <para> + <emphasis role="strong">Example: Definition of attribute sets of + submodules</emphasis> + </para> + <programlisting language="bash"> +config.mod.one = { foo = 1; bar = "one"; }; +config.mod.two = { foo = 2; bar = "two"; }; +</programlisting> + </section> + <section xml:id="sec-option-types-extending"> + <title>Extending types</title> + <para> + Types are mainly characterized by their <literal>check</literal> + and <literal>merge</literal> functions. + </para> + <variablelist> + <varlistentry> + <term> + <literal>check</literal> + </term> + <listitem> + <para> + The function to type check the value. Takes a value as + parameter and return a boolean. It is possible to extend a + type check with the <literal>addCheck</literal> function + (<link linkend="ex-extending-type-check-1">Example: Adding a + type check</link>), or to fully override the check function + (<link linkend="ex-extending-type-check-2">Example: + Overriding a type check</link>). + </para> + <anchor xml:id="ex-extending-type-check-1" /> + <para> + <emphasis role="strong">Example: Adding a type + check</emphasis> + </para> + <programlisting language="bash"> +byte = mkOption { + description = "An integer between 0 and 255."; + type = types.addCheck types.int (x: x >= 0 && x <= 255); +}; +</programlisting> + <anchor xml:id="ex-extending-type-check-2" /> + <para> + <emphasis role="strong">Example: Overriding a type + check</emphasis> + </para> + <programlisting language="bash"> +nixThings = mkOption { + description = "words that start with 'nix'"; + type = types.str // { + check = (x: lib.hasPrefix "nix" x) + }; +}; +</programlisting> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>merge</literal> + </term> + <listitem> + <para> + Function to merge the options values when multiple values + are set. The function takes two parameters, + <literal>loc</literal> the option path as a list of strings, + and <literal>defs</literal> the list of defined values as a + list. It is possible to override a type merge function for + custom needs. + </para> + </listitem> + </varlistentry> + </variablelist> + </section> + <section xml:id="sec-option-types-custom"> + <title>Custom Types</title> + <para> + Custom types can be created with the + <literal>mkOptionType</literal> function. As type creation + includes some more complex topics such as submodule handling, it + is recommended to get familiar with <literal>types.nix</literal> + code before creating a new type. + </para> + <para> + The only required parameter is <literal>name</literal>. + </para> + <variablelist> + <varlistentry> + <term> + <literal>name</literal> + </term> + <listitem> + <para> + A string representation of the type function name. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>definition</literal> + </term> + <listitem> + <para> + Description of the type used in documentation. Give + information of the type and any of its arguments. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>check</literal> + </term> + <listitem> + <para> + A function to type check the definition value. Takes the + definition value as a parameter and returns a boolean + indicating the type check result, <literal>true</literal> + for success and <literal>false</literal> for failure. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>merge</literal> + </term> + <listitem> + <para> + A function to merge multiple definitions values. Takes two + parameters: + </para> + <variablelist> + <varlistentry> + <term> + <emphasis><literal>loc</literal></emphasis> + </term> + <listitem> + <para> + The option path as a list of strings, e.g. + <literal>["boot" "loader "grub" "enable"]</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <emphasis><literal>defs</literal></emphasis> + </term> + <listitem> + <para> + The list of sets of defined <literal>value</literal> + and <literal>file</literal> where the value was + defined, e.g. + <literal>[ { file = "/foo.nix"; value = 1; } { file = "/bar.nix"; value = 2 } ]</literal>. + The <literal>merge</literal> function should return + the merged value or throw an error in case the values + are impossible or not meant to be merged. + </para> + </listitem> + </varlistentry> + </variablelist> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>getSubOptions</literal> + </term> + <listitem> + <para> + For composed types that can take a submodule as type + parameter, this function generate sub-options documentation. + It takes the current option prefix as a list and return the + set of sub-options. Usually defined in a recursive manner by + adding a term to the prefix, e.g. + <literal>prefix: elemType.getSubOptions (prefix ++ ["prefix"])</literal> + where + <emphasis><literal>"prefix"</literal></emphasis> + is the newly added prefix. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>getSubModules</literal> + </term> + <listitem> + <para> + For composed types that can take a submodule as type + parameter, this function should return the type parameters + submodules. If the type parameter is called + <literal>elemType</literal>, the function should just + recursively look into submodules by returning + <literal>elemType.getSubModules;</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>substSubModules</literal> + </term> + <listitem> + <para> + For composed types that can take a submodule as type + parameter, this function can be used to substitute the + parameter of a submodule type. It takes a module as + parameter and return the type with the submodule options + substituted. It is usually defined as a type function call + with a recursive call to <literal>substSubModules</literal>, + e.g for a type <literal>composedType</literal> that take an + <literal>elemtype</literal> type parameter, this function + should be defined as + <literal>m: composedType (elemType.substSubModules m)</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>typeMerge</literal> + </term> + <listitem> + <para> + A function to merge multiple type declarations. Takes the + type to merge <literal>functor</literal> as parameter. A + <literal>null</literal> return value means that type cannot + be merged. + </para> + <variablelist> + <varlistentry> + <term> + <emphasis><literal>f</literal></emphasis> + </term> + <listitem> + <para> + The type to merge <literal>functor</literal>. + </para> + </listitem> + </varlistentry> + </variablelist> + <para> + Note: There is a generic <literal>defaultTypeMerge</literal> + that work with most of value and composed types. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>functor</literal> + </term> + <listitem> + <para> + An attribute set representing the type. It is used for type + operations and has the following keys: + </para> + <variablelist> + <varlistentry> + <term> + <literal>type</literal> + </term> + <listitem> + <para> + The type function. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>wrapped</literal> + </term> + <listitem> + <para> + Holds the type parameter for composed types. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>payload</literal> + </term> + <listitem> + <para> + Holds the value parameter for value types. The types + that have a <literal>payload</literal> are the + <literal>enum</literal>, + <literal>separatedString</literal> and + <literal>submodule</literal> types. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>binOp</literal> + </term> + <listitem> + <para> + A binary operation that can merge the payloads of two + same types. Defined as a function that take two + payloads as parameters and return the payloads merged. + </para> + </listitem> + </varlistentry> + </variablelist> + </listitem> + </varlistentry> + </variablelist> + </section> +</section> |