From bfd21cd2c1492b799facdab2e77308c34edbe9e7 Mon Sep 17 00:00:00 2001 From: Bobby Rong Date: Sat, 3 Jul 2021 22:16:36 +0800 Subject: [PATCH] nixos: nixos/doc/manual/development/option-types.xml to CommonMark --- .../development/option-types.section.md | 558 ++++++++++ nixos/doc/manual/development/option-types.xml | 914 ---------------- .../manual/development/writing-modules.xml | 2 +- .../development/option-types.section.xml | 987 ++++++++++++++++++ 4 files changed, 1546 insertions(+), 915 deletions(-) create mode 100644 nixos/doc/manual/development/option-types.section.md delete mode 100644 nixos/doc/manual/development/option-types.xml create mode 100644 nixos/doc/manual/from_md/development/option-types.section.xml 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 000000000000..ed557206659f --- /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 3d2191e2f3f3..000000000000 --- a/nixos/doc/manual/development/option-types.xml +++ /dev/null @@ -1,914 +0,0 @@ -
- Options 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 - - - 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. - - <literal>types.anything</literal> Example - - Two definitions of this type like - -{ - str = lib.mkDefault "foo"; - pkg.hello = pkgs.hello; - fun.fun = x: x + 1; -} - - -{ - str = lib.mkIf true "bar"; - pkg.gcc = pkgs.gcc; - fun.fun = lib.mkForce (x: x + 2); -} - - will get merged to - -{ - str = "bar"; - pkg.gcc = pkgs.gcc; - pkg.hello = pkgs.hello; - fun.fun = x: x + 2; -} - - - - - - - - - types.attrs - - - - A free-form attribute set. - - 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 - −2n/2 - to - 2n/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 - - 2n−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 - - - 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 - . - - - - - - 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. - - 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 ) 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 - - - 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. - - 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. - - 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 - - - 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 - () or as reference - (). - - - - Directly defined submodule - -options.mod = mkOption { - description = "submodule example"; - type = with types; submodule { - options = { - foo = mkOption { - type = int; - }; - bar = mkOption { - type = str; - }; - }; - }; -}; - - - - Submodule defined as a reference - -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 - (), - submodule allows multiple definitions of the submodule - option set (). - - - - Declaration of a list of submodules - -options.mod = mkOption { - description = "submodule example"; - type = with types; listOf (submodule { - options = { - foo = mkOption { - type = int; - }; - bar = mkOption { - type = str; - }; - }; - }); -}; - - - - Definition of a list of submodules - -config.mod = [ - { foo = 1; bar = "one"; } - { foo = 2; bar = "two"; } -]; - - - - When composed with attrsOf - (), - submodule allows multiple named definitions of the - submodule option set (). - - - - Declaration of attribute sets of submodules - -options.mod = mkOption { - description = "submodule example"; - type = with types; attrsOf (submodule { - options = { - foo = mkOption { - type = int; - }; - bar = mkOption { - type = str; - }; - }; - }); -}; - - - - Declaration of attribute sets of submodules - -config.mod.one = { foo = 1; bar = "one"; }; -config.mod.two = { foo = 2; bar = "two"; }; - -
- -
- Extending types - - - 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 - (), or to fully - override the check function - (). - - - Adding a type check - -byte = mkOption { - description = "An integer between 0 and 255."; - type = types.addCheck types.int (x: x >= 0 && x <= 255); -}; - - - Overriding a type check - -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 - - - 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/writing-modules.xml b/nixos/doc/manual/development/writing-modules.xml index a1efbeac7232..245c49dbb7eb 100644 --- a/nixos/doc/manual/development/writing-modules.xml +++ b/nixos/doc/manual/development/writing-modules.xml @@ -180,7 +180,7 @@ in { - + 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 000000000000..c83ffa2add53 --- /dev/null +++ b/nixos/doc/manual/from_md/development/option-types.section.xml @@ -0,0 +1,987 @@ +
+ Options 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 + + 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. + + + + Example: + types.anything Example + + + Two definitions of this type like + + +{ + str = lib.mkDefault "foo"; + pkg.hello = pkgs.hello; + fun.fun = x: x + 1; +} + + +{ + str = lib.mkIf true "bar"; + pkg.gcc = pkgs.gcc; + fun.fun = lib.mkForce (x: x + 2); +} + + + will get merged to + + +{ + str = "bar"; + pkg.gcc = pkgs.gcc; + pkg.hello = pkgs.hello; + fun.fun = x: x + 2; +} + + + + + + types.attrs + + + + A free-form attribute set. + + + + 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 + + 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. + + + + + + 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. + + + + 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) 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 + + 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. + + + + 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. + + + + 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 + + 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) or as reference + (Example: Submodule defined + as a reference). + + + + Example: Directly defined + submodule + + +options.mod = mkOption { + description = "submodule example"; + type = with types; submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }; +}; + + + + Example: Submodule defined as a + reference + + +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), + submodule allows multiple definitions of the + submodule option set + (Example: + Definition of a list of submodules). + + + + Example: Declaration of a list of + submodules + + +options.mod = mkOption { + description = "submodule example"; + type = with types; listOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +}; + + + + Example: Definition of a list of + submodules + + +config.mod = [ + { foo = 1; bar = "one"; } + { foo = 2; bar = "two"; } +]; + + + When composed with attrsOf + (Example: + Declaration of attribute sets of submodules), + submodule allows multiple named definitions of + the submodule option set + (Example: + Definition of attribute sets of submodules). + + + + Example: Declaration of attribute sets of + submodules + + +options.mod = mkOption { + description = "submodule example"; + type = with types; attrsOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +}; + + + + Example: Definition of attribute sets of + submodules + + +config.mod.one = { foo = 1; bar = "one"; }; +config.mod.two = { foo = 2; bar = "two"; }; + +
+
+ Extending types + + 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), or to fully override the check function + (Example: + Overriding a type check). + + + + Example: Adding a type + check + + +byte = mkOption { + description = "An integer between 0 and 255."; + type = types.addCheck types.int (x: x >= 0 && x <= 255); +}; + + + + Example: Overriding a type + check + + +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 + + 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. + + + + + + + +
+