nixpkgs-suyu/nixos/doc/manual/from_md/development/option-def.section.xml
Naïm Favier 07cb3bf3cc
nixos/doc: bump Pandoc
Update the pinned channel in `md-to-db`, which bumps the Pandoc version,
which fixes https://github.com/NixOS/nixpkgs/issues/125511 maybe.
2022-12-27 17:23:25 +01:00

132 lines
4.7 KiB
XML

<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-option-definitions">
<title>Option Definitions</title>
<para>
Option definitions are generally straight-forward bindings of values
to option names, like
</para>
<programlisting language="nix">
config = {
services.httpd.enable = true;
};
</programlisting>
<para>
However, sometimes you need to wrap an option definition or set of
option definitions in a <emphasis>property</emphasis> to achieve
certain effects:
</para>
<section xml:id="sec-option-definitions-delaying-conditionals">
<title>Delaying Conditionals</title>
<para>
If a set of option definitions is conditional on the value of
another option, you may need to use <literal>mkIf</literal>.
Consider, for instance:
</para>
<programlisting language="nix">
config = if config.services.httpd.enable then {
environment.systemPackages = [ ... ];
...
} else {};
</programlisting>
<para>
This definition will cause Nix to fail with an <quote>infinite
recursion</quote> error. Why? Because the value of
<literal>config.services.httpd.enable</literal> depends on the
value being constructed here. After all, you could also write the
clearly circular and contradictory:
</para>
<programlisting language="nix">
config = if config.services.httpd.enable then {
services.httpd.enable = false;
} else {
services.httpd.enable = true;
};
</programlisting>
<para>
The solution is to write:
</para>
<programlisting language="nix">
config = mkIf config.services.httpd.enable {
environment.systemPackages = [ ... ];
...
};
</programlisting>
<para>
The special function <literal>mkIf</literal> causes the evaluation
of the conditional to be <quote>pushed down</quote> into the
individual definitions, as if you had written:
</para>
<programlisting language="nix">
config = {
environment.systemPackages = if config.services.httpd.enable then [ ... ] else [];
...
};
</programlisting>
</section>
<section xml:id="sec-option-definitions-setting-priorities">
<title>Setting Priorities</title>
<para>
A module can override the definitions of an option in other
modules by setting an <emphasis>override priority</emphasis>. All
option definitions that do not have the lowest priority value are
discarded. By default, option definitions have priority 100 and
option defaults have priority 1500. You can specify an explicit
priority by using <literal>mkOverride</literal>, e.g.
</para>
<programlisting language="nix">
services.openssh.enable = mkOverride 10 false;
</programlisting>
<para>
This definition causes all other definitions with priorities above
10 to be discarded. The function <literal>mkForce</literal> is
equal to <literal>mkOverride 50</literal>, and
<literal>mkDefault</literal> is equal to
<literal>mkOverride 1000</literal>.
</para>
</section>
<section xml:id="sec-option-definitions-ordering">
<title>Ordering Definitions</title>
<para>
It is also possible to influence the order in which the
definitions for an option are merged by setting an <emphasis>order
priority</emphasis> with <literal>mkOrder</literal>. The default
order priority is 1000. The functions <literal>mkBefore</literal>
and <literal>mkAfter</literal> are equal to
<literal>mkOrder 500</literal> and
<literal>mkOrder 1500</literal>, respectively. As an example,
</para>
<programlisting language="nix">
hardware.firmware = mkBefore [ myFirmware ];
</programlisting>
<para>
This definition ensures that <literal>myFirmware</literal> comes
before other unordered definitions in the final list value of
<literal>hardware.firmware</literal>.
</para>
<para>
Note that this is different from
<link linkend="sec-option-definitions-setting-priorities">override
priorities</link>: setting an order does not affect whether the
definition is included or not.
</para>
</section>
<section xml:id="sec-option-definitions-merging">
<title>Merging Configurations</title>
<para>
In conjunction with <literal>mkIf</literal>, it is sometimes
useful for a module to return multiple sets of option definitions,
to be merged together as if they were declared in separate
modules. This can be done using <literal>mkMerge</literal>:
</para>
<programlisting language="nix">
config = mkMerge
[ # Unconditional stuff.
{ environment.systemPackages = [ ... ];
}
# Conditional stuff.
(mkIf config.services.bla.enable {
environment.systemPackages = [ ... ];
})
];
</programlisting>
</section>
</section>