@@ -97,125 +97,228 @@ options = {
9797 </listitem>
9898 </varlistentry>
9999 </variablelist>
100− <section xml:id="sec-option-declarations-eot">
101− <title>Extensible Option Types</title>
102− <para>
103− Extensible option types is a feature that allow to extend certain
104− types declaration through multiple module files. This feature only
105− work with a restricted set of types, namely
106− <literal>enum</literal> and <literal>submodules</literal> and any
107− composed forms of them.
108− </para>
109− <para>
110− Extensible option types can be used for <literal>enum</literal>
111− options that affects multiple modules, or as an alternative to
112− related <literal>enable</literal> options.
113− </para>
114− <para>
115− As an example, we will take the case of display managers. There is
116− a central display manager module for generic display manager
117− options and a module file per display manager backend (sddm, gdm
118− ...).
119− </para>
120− <para>
121− There are two approach to this module structure:
122− </para>
123− <itemizedlist>
124− <listitem>
100+ <section xml:id="sec-option-declarations-util">
101+ <title>Utility functions for common option patterns</title>
102+ <section xml:id="sec-option-declarations-util-mkEnableOption">
103+ <title><literal>mkEnableOption</literal></title>
104+ <para>
105+ Creates an Option attribute set for a boolean value option i.e
106+ an option to be toggled on or off.
107+ </para>
108+ <para>
109+ This function takes a single string argument, the name of the
110+ thing to be toggled.
111+ </para>
112+ <para>
113+ The option’s description is <quote>Whether to enable
114+ <name>.</quote>.
115+ </para>
116+ <para>
117+ For example:
118+ </para>
119+ <anchor xml:id="ex-options-declarations-util-mkEnableOption-magic" />
120+ <programlisting language="bash">
121+lib.mkEnableOption "magic"
122+# is like
123+lib.mkOption {
124+ type = lib.types.bool;
125+ default = false;
126+ example = true;
127+ description = "Whether to enable magic.";
128+}
129+</programlisting>
130+ <section xml:id="sec-option-declarations-util-mkPackageOption">
131+ <title><literal>mkPackageOption</literal></title>
125132 <para>
126− Managing the display managers independently by adding an
127− enable option to every display manager module backend. (NixOS)
133+ Usage:
128134 </para>
129− </listitem>
130− <listitem>
135+ <programlisting language="bash">
136+mkPackageOption pkgs "name" { default = [ "path" "in" "pkgs" ]; example = "literal example"; }
137+</programlisting>
131138 <para>
132− Managing the display managers in the central module by adding
133− an option to select which display manager backend to use.
139+ Creates an Option attribute set for an option that specifies
140+ the package a module should use for some purpose.
134141 </para>
135− </listitem>
136− </itemizedlist>
137− <para>
138− Both approaches have problems.
139− </para>
140− <para>
141− Making backends independent can quickly become hard to manage. For
142− display managers, there can be only one enabled at a time, but the
143− type system can not enforce this restriction as there is no
144− relation between each backend <literal>enable</literal> option. As
145− a result, this restriction has to be done explicitely by adding
146− assertions in each display manager backend module.
147− </para>
148− <para>
149− On the other hand, managing the display managers backends in the
150− central module will require to change the central module option
151− every time a new backend is added or removed.
152− </para>
153− <para>
154− By using extensible option types, it is possible to create a
155− placeholder option in the central module
156− (<link linkend="ex-option-declaration-eot-service">Example:
157− Extensible type placeholder in the service module</link>), and to
158− extend it in each backend module
159− (<link linkend="ex-option-declaration-eot-backend-gdm">Example:
160− Extending
161− <literal>services.xserver.displayManager.enable</literal> in the
162− <literal>gdm</literal> module</link>,
163− <link linkend="ex-option-declaration-eot-backend-sddm">Example:
164− Extending
165− <literal>services.xserver.displayManager.enable</literal> in the
166− <literal>sddm</literal> module</link>).
167− </para>
168− <para>
169− As a result, <literal>displayManager.enable</literal> option
170− values can be added without changing the main service module file
171− and the type system automatically enforce that there can only be a
172− single display manager enabled.
173− </para>
174− <anchor xml:id="ex-option-declaration-eot-service" />
175− <para>
176− <emphasis role="strong">Example: Extensible type placeholder in
177− the service module</emphasis>
178− </para>
179− <programlisting language="bash">
142+ <para>
143+ <emphasis role="strong">Note</emphasis>: You shouldn’t
144+ necessarily make package options for all of your modules. You
145+ can always overwrite a specific package throughout nixpkgs by
146+ using
147+ <link xlink:href="https://nixos.org/manual/nixpkgs/stable/#chap-overlays">nixpkgs
148+ overlays</link>.
149+ </para>
150+ <para>
151+ The default package is specified as a list of strings
152+ representing its attribute path in nixpkgs. Because of this,
153+ you need to pass nixpkgs itself as the first argument.
154+ </para>
155+ <para>
156+ The second argument is the name of the option, used in the
157+ description <quote>The <name> package to use.</quote>.
158+ You can also pass an example value, either a literal string or
159+ a package’s attribute path.
160+ </para>
161+ <para>
162+ You can omit the default path if the name of the option is
163+ also attribute path in nixpkgs.
164+ </para>
165+ <anchor xml:id="ex-options-declarations-util-mkPackageOption" />
166+ <para>
167+ Examples:
168+ </para>
169+ <anchor xml:id="ex-options-declarations-util-mkPackageOption-hello" />
170+ <programlisting language="bash">
171+lib.mkPackageOption pkgs "hello" { }
172+# is like
173+lib.mkOption {
174+ type = lib.types.package;
175+ default = pkgs.hello;
176+ defaultText = lib.literalExpression "pkgs.hello";
177+ description = "The hello package to use.";
178+}
179+</programlisting>
180+ <anchor xml:id="ex-options-declarations-util-mkPackageOption-ghc" />
181+ <programlisting language="bash">
182+lib.mkPackageOption pkgs "GHC" {
183+ default = [ "ghc" ];
184+ example = "pkgs.haskell.package.ghc921.ghc.withPackages (hkgs: [ hkgs.primes ])";
185+}
186+# is like
187+lib.mkOption {
188+ type = lib.types.package;
189+ default = pkgs.ghc;
190+ defaultText = lib.literalExpression "pkgs.ghc";
191+ example = lib.literalExpression "pkgs.haskell.package.ghc921.ghc.withPackages (hkgs: [ hkgs.primes ])";
192+ description = "The GHC package to use.";
193+}
194+</programlisting>
195+ <section xml:id="sec-option-declarations-eot">
196+ <title>Extensible Option Types</title>
197+ <para>
198+ Extensible option types is a feature that allow to extend
199+ certain types declaration through multiple module files.
200+ This feature only work with a restricted set of types,
201+ namely <literal>enum</literal> and
202+ <literal>submodules</literal> and any composed forms of
203+ them.
204+ </para>
205+ <para>
206+ Extensible option types can be used for
207+ <literal>enum</literal> options that affects multiple
208+ modules, or as an alternative to related
209+ <literal>enable</literal> options.
210+ </para>
211+ <para>
212+ As an example, we will take the case of display managers.
213+ There is a central display manager module for generic
214+ display manager options and a module file per display
215+ manager backend (sddm, gdm ...).
216+ </para>
217+ <para>
218+ There are two approach to this module structure:
219+ </para>
220+ <itemizedlist>
221+ <listitem>
222+ <para>
223+ Managing the display managers independently by adding an
224+ enable option to every display manager module backend.
225+ (NixOS)
226+ </para>
227+ </listitem>
228+ <listitem>
229+ <para>
230+ Managing the display managers in the central module by
231+ adding an option to select which display manager backend
232+ to use.
233+ </para>
234+ </listitem>
235+ </itemizedlist>
236+ <para>
237+ Both approaches have problems.
238+ </para>
239+ <para>
240+ Making backends independent can quickly become hard to
241+ manage. For display managers, there can be only one enabled
242+ at a time, but the type system can not enforce this
243+ restriction as there is no relation between each backend
244+ <literal>enable</literal> option. As a result, this
245+ restriction has to be done explicitely by adding assertions
246+ in each display manager backend module.
247+ </para>
248+ <para>
249+ On the other hand, managing the display managers backends in
250+ the central module will require to change the central module
251+ option every time a new backend is added or removed.
252+ </para>
253+ <para>
254+ By using extensible option types, it is possible to create a
255+ placeholder option in the central module
256+ (<link linkend="ex-option-declaration-eot-service">Example:
257+ Extensible type placeholder in the service module</link>),
258+ and to extend it in each backend module
259+ (<link linkend="ex-option-declaration-eot-backend-gdm">Example:
260+ Extending
261+ <literal>services.xserver.displayManager.enable</literal> in
262+ the <literal>gdm</literal> module</link>,
263+ <link linkend="ex-option-declaration-eot-backend-sddm">Example:
264+ Extending
265+ <literal>services.xserver.displayManager.enable</literal> in
266+ the <literal>sddm</literal> module</link>).
267+ </para>
268+ <para>
269+ As a result, <literal>displayManager.enable</literal> option
270+ values can be added without changing the main service module
271+ file and the type system automatically enforce that there
272+ can only be a single display manager enabled.
273+ </para>
274+ <anchor xml:id="ex-option-declaration-eot-service" />
275+ <para>
276+ <emphasis role="strong">Example: Extensible type placeholder
277+ in the service module</emphasis>
278+ </para>
279+ <programlisting language="bash">
180280services.xserver.displayManager.enable = mkOption {
181281 description = "Display manager to use";
182282 type = with types; nullOr (enum [ ]);
183283};
184284</programlisting>
185− <anchor xml:id="ex-option-declaration-eot-backend-gdm" />
186− <para>
187− <emphasis role="strong">Example: Extending
188− <literal>services.xserver.displayManager.enable</literal> in the
189− <literal>gdm</literal> module</emphasis>
190− </para>
191− <programlisting language="bash">
285+ <anchor xml:id="ex-option-declaration-eot-backend-gdm" />
286+ <para>
287+ <emphasis role="strong">Example: Extending
288+ <literal>services.xserver.displayManager.enable</literal> in
289+ the <literal>gdm</literal> module</emphasis>
290+ </para>
291+ <programlisting language="bash">
192292services.xserver.displayManager.enable = mkOption {
193293 type = with types; nullOr (enum [ "gdm" ]);
194294};
195295</programlisting>
196− <anchor xml:id="ex-option-declaration-eot-backend-sddm" />
197− <para>
198− <emphasis role="strong">Example: Extending
199− <literal>services.xserver.displayManager.enable</literal> in the
200− <literal>sddm</literal> module</emphasis>
201− </para>
202− <programlisting language="bash">
296+ <anchor xml:id="ex-option-declaration-eot-backend-sddm" />
297+ <para>
298+ <emphasis role="strong">Example: Extending
299+ <literal>services.xserver.displayManager.enable</literal> in
300+ the <literal>sddm</literal> module</emphasis>
301+ </para>
302+ <programlisting language="bash">
203303services.xserver.displayManager.enable = mkOption {
204304 type = with types; nullOr (enum [ "sddm" ]);
205305};
206306</programlisting>
207− <para>
208− The placeholder declaration is a standard
209− <literal>mkOption</literal> declaration, but it is important that
210− extensible option declarations only use the
211− <literal>type</literal> argument.
212− </para>
213− <para>
214− Extensible option types work with any of the composed variants of
215− <literal>enum</literal> such as
216− <literal>with types; nullOr (enum [ "foo" "bar" ])</literal>
217− or
218− <literal>with types; listOf (enum [ "foo" "bar" ])</literal>.
219− </para>
307+ <para>
308+ The placeholder declaration is a standard
309+ <literal>mkOption</literal> declaration, but it is important
310+ that extensible option declarations only use the
311+ <literal>type</literal> argument.
312+ </para>
313+ <para>
314+ Extensible option types work with any of the composed
315+ variants of <literal>enum</literal> such as
316+ <literal>with types; nullOr (enum [ "foo" "bar" ])</literal>
317+ or
318+ <literal>with types; listOf (enum [ "foo" "bar" ])</literal>.
319+ </para>
320+ </section>
321+ </section>
322+ </section>
220323 </section>
221324</section>