nixos: nixos/doc/manual/development/freeform-modules.xml to CommonMark
This commit is contained in:
parent
a743c6d35a
commit
31be0b922d
3 changed files with 166 additions and 68 deletions
79
nixos/doc/manual/development/freeform-modules.section.md
Normal file
79
nixos/doc/manual/development/freeform-modules.section.md
Normal file
|
@ -0,0 +1,79 @@
|
|||
# Freeform modules {#sec-freeform-modules}
|
||||
|
||||
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 `attrsOf` options in order to
|
||||
accept all attribute names.
|
||||
|
||||
This feature can be enabled by using the attribute `freeformType` 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 `config` set. Since this feature nullifies name
|
||||
checking for entire option trees, it is only recommended for use in
|
||||
submodules.
|
||||
|
||||
::: {#ex-freeform-module .example}
|
||||
::: {.title}
|
||||
**Example: Freeform submodule**
|
||||
:::
|
||||
The following shows a submodule assigning a freeform type that allows
|
||||
arbitrary attributes with `str` values below `settings`, but also
|
||||
declares an option for the `settings.port` attribute to have it
|
||||
type-checked and assign a default value. See
|
||||
[Example: Declaring a type-checked `settings` attribute](#ex-settings-typed-attrs)
|
||||
for a more complete example.
|
||||
|
||||
```nix
|
||||
{ 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;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
And the following shows what such a module then allows
|
||||
|
||||
```nix
|
||||
{
|
||||
# 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";
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
::: {.note}
|
||||
Freeform attributes cannot depend on other attributes of the same set
|
||||
without infinite recursion:
|
||||
|
||||
```nix
|
||||
{
|
||||
# This throws infinite recursion encountered
|
||||
settings.logLevel = lib.mkIf (config.settings.port == 80) "debug";
|
||||
}
|
||||
```
|
||||
|
||||
To prevent this, declare options for all attributes that need to depend
|
||||
on others. For above example this means to declare `logLevel` to be an
|
||||
option.
|
||||
:::
|
|
@ -1,68 +0,0 @@
|
|||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
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>
|
||||
<example xml:id="ex-freeform-module">
|
||||
<title>Freeform submodule</title>
|
||||
<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 <xref linkend="ex-settings-typed-attrs"/> for a more complete example.
|
||||
</para>
|
||||
<programlisting>
|
||||
{ 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>
|
||||
{
|
||||
# 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>
|
||||
</example>
|
||||
<note>
|
||||
<para>
|
||||
Freeform attributes cannot depend on other attributes of the same set without infinite recursion:
|
||||
<programlisting>
|
||||
{
|
||||
# This throws infinite recursion encountered
|
||||
settings.logLevel = lib.mkIf (config.settings.port == 80) "debug";
|
||||
}
|
||||
</programlisting>
|
||||
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>
|
|
@ -0,0 +1,87 @@
|
|||
<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>
|
Loading…
Reference in a new issue