diff options
author | Eric Sagnes <eric.sagnes@gmail.com> | 2016-09-07 10:03:32 +0900 |
---|---|---|
committer | Nicolas B. Pierron <nicolas.b.pierron@gmail.com> | 2016-11-06 00:05:58 +0100 |
commit | e14de56613fc8e42fb6249031efe9e7abbb65286 (patch) | |
tree | 4a0d884bf0b5698cf42705ff25c5806ace87951f /nixos/doc/manual/development | |
parent | d10356b82558fe50e1ad0fa1fb5e151c43ed3e0a (diff) | |
download | nixlib-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.xml | 88 | ||||
-rw-r--r-- | nixos/doc/manual/development/option-types.xml | 110 |
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> |