forked from mirrors/nixpkgs
88 lines
3 KiB
XML
88 lines
3 KiB
XML
|
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-freeform-modules">
|
||
|
<title>Freeform modules</title>
|
||
|
<para>
|
||
|
Freeform modules allow you to define values for option paths that
|
||
|
have not been declared explicitly. This can be used to add
|
||
|
attribute-specific types to what would otherwise have to be
|
||
|
<literal>attrsOf</literal> options in order to accept all attribute
|
||
|
names.
|
||
|
</para>
|
||
|
<para>
|
||
|
This feature can be enabled by using the attribute
|
||
|
<literal>freeformType</literal> to define a freeform type. By doing
|
||
|
this, all assignments without an associated option will be merged
|
||
|
using the freeform type and combined into the resulting
|
||
|
<literal>config</literal> set. Since this feature nullifies name
|
||
|
checking for entire option trees, it is only recommended for use in
|
||
|
submodules.
|
||
|
</para>
|
||
|
<anchor xml:id="ex-freeform-module" />
|
||
|
<para>
|
||
|
<emphasis role="strong">Example: Freeform submodule</emphasis>
|
||
|
</para>
|
||
|
<para>
|
||
|
The following shows a submodule assigning a freeform type that
|
||
|
allows arbitrary attributes with <literal>str</literal> values below
|
||
|
<literal>settings</literal>, but also declares an option for the
|
||
|
<literal>settings.port</literal> attribute to have it type-checked
|
||
|
and assign a default value. See
|
||
|
<link linkend="ex-settings-typed-attrs">Example: Declaring a
|
||
|
type-checked <literal>settings</literal> attribute</link> for a more
|
||
|
complete example.
|
||
|
</para>
|
||
|
<programlisting language="bash">
|
||
|
{ lib, config, ... }: {
|
||
|
|
||
|
options.settings = lib.mkOption {
|
||
|
type = lib.types.submodule {
|
||
|
|
||
|
freeformType = with lib.types; attrsOf str;
|
||
|
|
||
|
# We want this attribute to be checked for the correct type
|
||
|
options.port = lib.mkOption {
|
||
|
type = lib.types.port;
|
||
|
# Declaring the option also allows defining a default value
|
||
|
default = 8080;
|
||
|
};
|
||
|
|
||
|
};
|
||
|
};
|
||
|
}
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
And the following shows what such a module then allows
|
||
|
</para>
|
||
|
<programlisting language="bash">
|
||
|
{
|
||
|
# Not a declared option, but the freeform type allows this
|
||
|
settings.logLevel = "debug";
|
||
|
|
||
|
# Not allowed because the the freeform type only allows strings
|
||
|
# settings.enable = true;
|
||
|
|
||
|
# Allowed because there is a port option declared
|
||
|
settings.port = 80;
|
||
|
|
||
|
# Not allowed because the port option doesn't allow strings
|
||
|
# settings.port = "443";
|
||
|
}
|
||
|
</programlisting>
|
||
|
<note>
|
||
|
<para>
|
||
|
Freeform attributes cannot depend on other attributes of the same
|
||
|
set without infinite recursion:
|
||
|
</para>
|
||
|
<programlisting language="bash">
|
||
|
{
|
||
|
# This throws infinite recursion encountered
|
||
|
settings.logLevel = lib.mkIf (config.settings.port == 80) "debug";
|
||
|
}
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
To prevent this, declare options for all attributes that need to
|
||
|
depend on others. For above example this means to declare
|
||
|
<literal>logLevel</literal> to be an option.
|
||
|
</para>
|
||
|
</note>
|
||
|
</section>
|