summary refs log tree commit diff
path: root/nixos/doc/manual/development
diff options
context:
space:
mode:
authorEric Sagnes <eric.sagnes@gmail.com>2016-09-07 10:03:32 +0900
committerNicolas B. Pierron <nicolas.b.pierron@gmail.com>2016-11-06 00:05:58 +0100
commite14de56613fc8e42fb6249031efe9e7abbb65286 (patch)
tree4a0d884bf0b5698cf42705ff25c5806ace87951f /nixos/doc/manual/development
parentd10356b82558fe50e1ad0fa1fb5e151c43ed3e0a (diff)
downloadnixlib-e14de56613fc8e42fb6249031efe9e7abbb65286.tar
nixlib-e14de56613fc8e42fb6249031efe9e7abbb65286.tar.gz
nixlib-e14de56613fc8e42fb6249031efe9e7abbb65286.tar.bz2
nixlib-e14de56613fc8e42fb6249031efe9e7abbb65286.tar.lz
nixlib-e14de56613fc8e42fb6249031efe9e7abbb65286.tar.xz
nixlib-e14de56613fc8e42fb6249031efe9e7abbb65286.tar.zst
nixlib-e14de56613fc8e42fb6249031efe9e7abbb65286.zip
module system: extensible option types
Diffstat (limited to 'nixos/doc/manual/development')
-rw-r--r--nixos/doc/manual/development/option-declarations.xml88
-rw-r--r--nixos/doc/manual/development/option-types.xml110
2 files changed, 172 insertions, 26 deletions
diff --git a/nixos/doc/manual/development/option-declarations.xml b/nixos/doc/manual/development/option-declarations.xml
index 7be5e9d51d46..ce432a7fa6ca 100644
--- a/nixos/doc/manual/development/option-declarations.xml
+++ b/nixos/doc/manual/development/option-declarations.xml
@@ -65,4 +65,92 @@ options = {
 
 </para>
 
+<section xml:id="sec-option-declarations-eot"><title>Extensible Option 
+    Types</title>
+
+  <para>Extensible option types is a feature that allow to extend certain types 
+    declaration through multiple module files.
+    This feature only work with a restricted set of types, namely 
+    <literal>enum</literal> and <literal>submodules</literal> and any composed
+    forms of them.</para>
+
+  <para>Extensible option types can be used for <literal>enum</literal> options 
+    that affects multiple modules, or as an alternative to related 
+    <literal>enable</literal> options.</para>
+
+  <para>As an example, we will take the case of display managers. There is a
+    central display manager module for generic display manager options and a
+    module file per display manager backend (slim, kdm, gdm ...).
+  </para>
+
+  <para>There are two approach to this module structure:
+
+  <itemizedlist>
+    <listitem><para>Managing the display managers independently by adding an
+        enable option to every display manager module backend. (NixOS)</para>
+    </listitem>
+    <listitem><para>Managing the display managers in the central module by
+        adding an option to select which display manager backend to use.</para>
+    </listitem>
+  </itemizedlist>
+  </para>
+
+  <para>Both approachs have problems.</para>
+    
+  <para>Making backends independent can quickly become hard to manage. For
+    display managers, there can be only one enabled at a time, but the type
+    system can not enforce this restriction as there is no relation between
+    each backend <literal>enable</literal> option. As a result, this restriction
+    has to be done explicitely by adding assertions in each display manager
+    backend module.</para>
+
+  <para>On the other hand, managing the display managers backends in the
+    central module will require to change the central module option every time
+    a new backend is added or removed.</para>
+
+  <para>By using extensible option types, it is possible to create a placeholder 
+    option in the central module (<xref linkend='ex-option-declaration-eot-service' 
+      />), and to extend it in each backend module (<xref 
+      linkend='ex-option-declaration-eot-backend-slim' />, <xref 
+      linkend='ex-option-declaration-eot-backend-kdm' />).</para>
+ 
+  <para>As a result, <literal>displayManager.enable</literal> option values can
+  be added without changing the main service module file and the type system
+  automatically enforce that there can only be a single display manager
+  enabled.</para>
+
+<example xml:id='ex-option-declaration-eot-service'><title>Extensible type 
+    placeholder in the service module</title>
+<screen>
+services.xserver.displayManager.enable = mkOption {
+  description = "Display manager to use";
+  type = with types; nullOr (enum [ ]);
+};</screen></example>
+
+<example xml:id='ex-option-declaration-eot-backend-slim'><title>Extending 
+    <literal>services.xserver.displayManager.enable</literal> in the 
+    <literal>slim</literal> module</title>
+<screen>
+services.xserver.displayManager.enable = mkOption {
+  type = with types; nullOr (enum [ "slim" ]);
+};</screen></example>
+
+<example xml:id='ex-option-declaration-eot-backend-kdm'><title>Extending 
+    <literal>services.foo.backend</literal> in the <literal>kdm</literal> 
+    module</title>
+<screen>
+services.xserver.displayManager.enable = mkOption {
+  type = with types; nullOr (enum [ "kdm" ]);
+};</screen></example>
+
+<para>The placeholder declaration is a standard <literal>mkOption</literal> 
+  declaration, but it is important that extensible option declarations only use 
+  the <literal>type</literal> argument.</para>
+
+<para>Extensible option types work with any of the composed variants of 
+  <literal>enum</literal> such as 
+  <literal>with types; nullOr (enum [ "foo" "bar" ])</literal> 
+  or <literal>with types; listOf (enum [ "foo" "bar" ])</literal>.</para>
+
+</section>
 </section>
diff --git a/nixos/doc/manual/development/option-types.xml b/nixos/doc/manual/development/option-types.xml
index 9ef7bb30a576..8e6ac53ad480 100644
--- a/nixos/doc/manual/development/option-types.xml
+++ b/nixos/doc/manual/development/option-types.xml
@@ -62,23 +62,45 @@
     <listitem><para>A string. Multiple definitions are concatenated with a 
         collon <literal>":"</literal>.</para></listitem>
   </varlistentry>
+</variablelist>
+
+ </section>
+
+ <section><title>Value Types</title>
+
+   <para>Value types are type that take a value parameter. The only value type 
+     in the library is <literal>enum</literal>.</para>
+
+<variablelist>
   <varlistentry>
-    <term><varname>types.separatedString</varname> 
+    <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 
+    <listitem><para>A string with a custom separator
+        <replaceable>sep</replaceable>, e.g. <literal>types.separatedString
           "|"</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 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><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>
+   <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>
@@ -112,12 +134,6 @@
         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 
@@ -125,14 +141,6 @@
           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>
@@ -191,7 +199,6 @@ options.mod = mkOption {
   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 
@@ -317,9 +324,13 @@ code before creating a new type.</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>
+    <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>
@@ -382,6 +393,53 @@ code before creating a new type.</para>
         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>