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 /nixos/doc/manual/development | |
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
Diffstat (limited to 'nixos/doc/manual/development')
-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 |
3 files changed, 559 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" /> |