parent
a743c6d35a
commit
31be0b922d
@ -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 new issue