aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/doc/manual/development/freeform-modules.xml
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/doc/manual/development/freeform-modules.xml')
-rw-r--r--nixpkgs/nixos/doc/manual/development/freeform-modules.xml68
1 files changed, 68 insertions, 0 deletions
diff --git a/nixpkgs/nixos/doc/manual/development/freeform-modules.xml b/nixpkgs/nixos/doc/manual/development/freeform-modules.xml
new file mode 100644
index 00000000000..257e6b11bf0
--- /dev/null
+++ b/nixpkgs/nixos/doc/manual/development/freeform-modules.xml
@@ -0,0 +1,68 @@
+<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>