about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Sagnes <eric.sagnes@gmail.com>2016-09-13 14:04:02 +0900
committerFranz Pletz <fpletz@fnordicwalking.de>2016-09-13 07:04:02 +0200
commitb32252ddfa530ff67e297ff6ba9e5cb0f91a767a (patch)
tree89b2fc1e62f2b96bd926be3999f6a06e07df496d
parent3e7bb6579bccd885c67bca47ad1a4592769260f0 (diff)
downloadnixlib-b32252ddfa530ff67e297ff6ba9e5cb0f91a767a.tar
nixlib-b32252ddfa530ff67e297ff6ba9e5cb0f91a767a.tar.gz
nixlib-b32252ddfa530ff67e297ff6ba9e5cb0f91a767a.tar.bz2
nixlib-b32252ddfa530ff67e297ff6ba9e5cb0f91a767a.tar.lz
nixlib-b32252ddfa530ff67e297ff6ba9e5cb0f91a767a.tar.xz
nixlib-b32252ddfa530ff67e297ff6ba9e5cb0f91a767a.tar.zst
nixlib-b32252ddfa530ff67e297ff6ba9e5cb0f91a767a.zip
NixOS manual: add module option types doc (#18525)
-rw-r--r--nixos/doc/manual/development/option-declarations.xml88
-rw-r--r--nixos/doc/manual/development/option-types.xml394
-rw-r--r--nixos/doc/manual/development/writing-modules.xml1
3 files changed, 398 insertions, 85 deletions
diff --git a/nixos/doc/manual/development/option-declarations.xml b/nixos/doc/manual/development/option-declarations.xml
index b0689aa1d97f..7be5e9d51d46 100644
--- a/nixos/doc/manual/development/option-declarations.xml
+++ b/nixos/doc/manual/development/option-declarations.xml
@@ -31,9 +31,9 @@ options = {
   <varlistentry>
     <term><varname>type</varname></term>
     <listitem>
-      <para>The type of the option (see below).  It may be omitted,
-      but that’s not advisable since it may lead to errors that are
-      hard to diagnose.</para>
+      <para>The type of the option (see <xref linkend='sec-option-types' />).
+      It may be omitted, but that’s not advisable since it may lead to errors
+      that are hard to diagnose.</para>
     </listitem>
   </varlistentry>
 
@@ -65,86 +65,4 @@ options = {
 
 </para>
 
-<para>Here is a non-exhaustive list of option types:
-
-<variablelist>
-
-  <varlistentry>
-    <term><varname>types.bool</varname></term>
-    <listitem>
-      <para>A Boolean.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.int</varname></term>
-    <listitem>
-      <para>An integer.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.str</varname></term>
-    <listitem>
-      <para>A string.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.lines</varname></term>
-    <listitem>
-      <para>A string.  If there are multiple definitions, they are
-      concatenated, with newline characters in between.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.path</varname></term>
-    <listitem>
-      <para>A path, defined as anything that, when coerced to a
-      string, starts with a slash.  This includes derivations.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.package</varname></term>
-    <listitem>
-      <para>A derivation (such as <literal>pkgs.hello</literal>) or a
-      store path (such as
-      <filename>/nix/store/1ifi1cfbfs5iajmvwgrbmrnrw3a147h9-hello-2.10</filename>).</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.listOf</varname> <replaceable>t</replaceable></term>
-    <listitem>
-      <para>A list of elements of type <replaceable>t</replaceable>
-      (e.g., <literal>types.listOf types.str</literal> is a list of
-      strings).  Multiple definitions are concatenated together.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.attrsOf</varname> <replaceable>t</replaceable></term>
-    <listitem>
-      <para>A set of elements of type <replaceable>t</replaceable>
-      (e.g., <literal>types.attrsOf types.int</literal> is a set of
-      name/value pairs, the values being integers).</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.nullOr</varname> <replaceable>t</replaceable></term>
-    <listitem>
-      <para>Either the value <literal>null</literal> or something of
-      type <replaceable>t</replaceable>.</para>
-    </listitem>
-  </varlistentry>
-
-</variablelist>
-
-You can also create new types using the function
-<varname>mkOptionType</varname>.  See
-<filename>lib/types.nix</filename> in Nixpkgs for details.</para>
-
 </section>
diff --git a/nixos/doc/manual/development/option-types.xml b/nixos/doc/manual/development/option-types.xml
new file mode 100644
index 000000000000..8871b02cebf1
--- /dev/null
+++ b/nixos/doc/manual/development/option-types.xml
@@ -0,0 +1,394 @@
+<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><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.int</varname></term>
+    <listitem><para>An integer.</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>
+</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.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>
+</variablelist>
+
+ </section>
+
+ <section><title>Composed Types</title>
+
+   <para>Composed types allow to create complex types by taking another type(s) 
+     or value(s) as parameter(s).
+     It is possible to compose types multiple times, e.g. <literal>with types; 
+       nullOr (enum [ "left" "right" ])</literal>.</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.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.loaOf</varname> <replaceable>t</replaceable></term>
+    <listitem><para>An attribute set or a list of <replaceable>t</replaceable> 
+        type. Multiple definitions are merged according to the 
+        value.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.loeOf</varname> <replaceable>t</replaceable></term>
+    <listitem><para>A list or an element of <replaceable>t</replaceable> type. 
+        Multiple definitions are merged according to the 
+        values.</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.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.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.submodule</varname> <replaceable>o</replaceable></term>
+    <listitem><para>A set of sub options <replaceable>o</replaceable>. 
+        <replaceable>o</replaceable> can be an attribute set or a function 
+        returning an attribute set. Submodules are used in composed types to 
+        create modular options. Submodule are detailed in <xref 
+          linkend='section-option-types-submodule' />.</para></listitem>
+  </varlistentry>
+</variablelist>
+
+</section>
+
+<section xml:id='section-option-types-submodule'><title>Submodule</title>
+
+  <para>Submodule is a very powerful type that defines a set of sub-options that 
+    are handled like a separate module.
+    It is especially interesting when used with composed types like 
+    <literal>attrsOf</literal> or <literal>listOf</literal>.</para>
+
+  <para>The submodule type take 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.
+    The option set can be defined directly (<xref linkend='ex-submodule-direct' 
+      />) or as reference (<xref linkend='ex-submodule-reference' />).</para>
+
+  <para>Submodule option definitions are type-checked accordingly to the options 
+    declarations. It is possible to declare submodule options inside a submodule 
+    sub-options for even higher modularity.</para>
+
+<example xml:id='ex-submodule-direct'><title>Directly defined submodule</title>
+<screen>
+options.mod = mkOption {
+  name = "mod";
+  description = "submodule example";
+  type = with types; listOf (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; listOf (submodule modOptions);
+};</screen></example>
+
+
+<section><title>Composed with <literal>listOf</literal></title>
+
+  <para>When composed with <literal>listOf</literal>, submodule allows multiple 
+    definitions of the submodule option set.</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>
+
+</section>
+
+
+<section><title>Composed with <literal>attrsOf</literal></title>
+
+  <para>When composed with <literal>attrsOf</literal>, submodule allows multiple 
+    named definitions of the submodule option set.</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>
+
+<section><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 = addCheck (x: x &gt;= 0 &amp;&amp; x &lt;= 255) types.int;
+};</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><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, name 
+        usually changes accordingly parameters passed to 
+        types.</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 usally 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>
+</variablelist>
+
+</section>
+</section>
diff --git a/nixos/doc/manual/development/writing-modules.xml b/nixos/doc/manual/development/writing-modules.xml
index a68b122ce022..ef6920160e6d 100644
--- a/nixos/doc/manual/development/writing-modules.xml
+++ b/nixos/doc/manual/development/writing-modules.xml
@@ -176,6 +176,7 @@ in {
 </example>
 
 <xi:include href="option-declarations.xml" />
+<xi:include href="option-types.xml" />
 <xi:include href="option-def.xml" />
 <xi:include href="meta-attributes.xml" />