Commit bfd21cd2 authored by Bobby Rong's avatar Bobby Rong
Browse files

nixos: nixos/doc/manual/development/option-types.xml to CommonMark

parent 68770121
Loading
Loading
Loading
Loading
+558 −0
Original line number Diff line number Diff line
# 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.
+0 −914

File deleted.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -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" />
+987 −0

File added.

Preview size limit exceeded, changes collapsed.