[[ch-writing-modules]]
== Writing Home Manager Modules
:writing-nixos-modules: https://nixos.org/nixos/manual/index.html#sec-writing-modules

The module system in Home Manager is based entirely on the NixOS module system so we will here only highlight aspects that are specific for Home Manager. For information about the module system as such please refer to the {writing-nixos-modules}[Writing NixOS Modules] chapter of the NixOS manual.

[[sec-option-types]]
=== Option Types
:wikipedia-dag: https://en.wikipedia.org/w/index.php?title=Directed_acyclic_graph&oldid=939656095
:gvariant-description: https://docs.gtk.org/glib/struct.Variant.html#description

Overall the basic option types are the same in Home Manager as NixOS. A few Home Manager options, however, make use of custom types that are worth describing in more detail. These are the option types `dagOf` and `gvariant` that are used, for example, by <<opt-programs.ssh.matchBlocks>> and <<opt-dconf.settings>>.

`hm.types.dagOf`::
Options of this type have attribute sets as values where each member is a node in a {wikipedia-dag}[directed acyclic graph] (DAG). This allows the attribute set entries to express dependency relations among themselves. This can, for example, be used to control the order of match blocks in a OpenSSH client configuration or the order of activation script blocks in <<opt-home.activation>>.
+
A number of functions are provided to create DAG nodes. The functions are shown below with examples using an option `foo.bar`  of type `hm.types.dagOf types.int`.
+
`hm.dag.entryAnywhere (value: T)`:::
Indicates that `value` can be placed anywhere within the DAG. This is also the default for plain attribute set entries, that is
+
[source,nix]
----
foo.bar = {
  a = hm.dag.entryAnywhere 0;
}
----
+
and
+
[source,nix]
----
foo.bar = {
  a = 0;
}
----
+
are equivalent.
+
`hm.dag.entryAfter (afters: list string) (value: T)`:::
Indicates that `value` must be placed _after_ each of the attribute names in the given list. For example
+
[source,nix]
----
foo.bar = {
  a = 0;
  b = hm.dag.entryAfter [ "a" ] 1;
}
----
+
would place `b` after `a` in the graph.
+
`hm.dag.entryBefore (befores: list string) (value: T)`:::
Indicates that `value` must be placed _before_ each of the attribute names in the given list. For example
+
[source,nix]
----
foo.bar = {
  b = hm.dag.entryBefore [ "a" ] 1;
  a = 0;
}
----
+
would place `b` before `a` in the graph.
+
`hm.dag.entryBetween (befores: list string) (afters: list string) (value: T)`:::
Indicates that `value` must be placed _before_ the attribute names in the first list and _after_ the attribute names in the second list. For example
+
[source,nix]
----
foo.bar = {
  a = 0;
  c = hm.dag.entryBetween [ "b" ] [ "a" ] 2;
  b = 1;
}
----
+
would place `c` before `b` and after `a` in the graph.

[[sec-option-types-gvariant]]`hm.types.gvariant`::
This type is useful for options representing {gvariant-description}[GVariant] values. The type accepts all primitive GVariant types as well as arrays and tuples. Dictionaries are not currently supported.
+
To create a GVariant value you can use a number of provided functions. Examples assume an option `foo.bar`  of type `hm.types.gvariant`.
+
[[sec-option-types-gvariant-mkBoolean]]`hm.gvariant.mkBoolean (v: bool)`:::
Takes a Nix value `v` to a GVariant `boolean` value. Note, Nix booleans are automatically coerced using this function. That is,
+
[source,nix]
----
foo.bar = hm.gvariant.mkBoolean true;
----
+
is equivalent to
+
[source,nix]
----
foo.bar = true;
----
[[sec-option-types-gvariant-mkString]]`hm.gvariant.mkString (v: string)`:::
Takes a Nix value `v` to a GVariant `string` value. Note, Nix strings are automatically coerced using this function. That is,
+
[source,nix]
----
foo.bar = hm.gvariant.mkString "a string";
----
+
is equivalent to
+
[source,nix]
----
foo.bar = "a string";
----
[[sec-option-types-gvariant-mkObjectpath]]`hm.gvariant.mkObjectpath (v: string)`:::
Takes a Nix value `v` to a GVariant `objectpath` value.
[[sec-option-types-gvariant-mkUchar]]`hm.gvariant.mkUchar (v: string)`:::
Takes a Nix value `v` to a GVariant `uchar` value.
[[sec-option-types-gvariant-mkInt16]]`hm.gvariant.mkInt16 (v: int)`:::
Takes a Nix value `v` to a GVariant `int16` value.
[[sec-option-types-gvariant-mkUint16]]`hm.gvariant.mkUint16 (v: int)`:::
Takes a Nix value `v` to a GVariant `uint16` value.
[[sec-option-types-gvariant-mkInt32]]`hm.gvariant.mkInt32 (v: int)`:::
Takes a Nix value `v` to a GVariant `int32` value. Note, Nix integers are automatically coerced using this function. That is,
+
[source,nix]
----
foo.bar = hm.gvariant.mkInt32 7;
----
+
is equivalent to
+
[source,nix]
----
foo.bar = 7;
----
[[sec-option-types-gvariant-mkUint32]]`hm.gvariant.mkUint32 (v: int)`:::
Takes a Nix value `v` to a GVariant `uint32` value.
[[sec-option-types-gvariant-mkInt64]]`hm.gvariant.mkInt64 (v: int)`:::
Takes a Nix value `v` to a GVariant `int64` value.
[[sec-option-types-gvariant-mkUint64]]`hm.gvariant.mkUint64 (v: int)`:::
Takes a Nix value `v` to a GVariant `uint64` value.
[[sec-option-types-gvariant-mkDouble]]`hm.gvariant.mkDouble (v: double)`:::
Takes a Nix value `v` to a GVariant `double` value. Note, Nix floats are automatically coerced using this function. That is,
+
[source,nix]
----
foo.bar = hm.gvariant.mkDouble 3.14;
----
+
is equivalent to
+
[source,nix]
----
foo.bar = 3.14;
----
+
[[sec-option-types-gvariant-mkArray]]`hm.gvariant.mkArray type elements`:::
Builds a GVariant array containing the given list of elements, where each element is a GVariant value of the given type. The `type` value can be constructed using
+
--
- `hm.gvariant.type.string`
- `hm.gvariant.type.boolean`
- `hm.gvariant.type.uchar`
- `hm.gvariant.type.int16`
- `hm.gvariant.type.uint16`
- `hm.gvariant.type.int32`
- `hm.gvariant.type.uint32`
- `hm.gvariant.type.int64`
- `hm.gvariant.type.uint64`
- `hm.gvariant.type.double`
- `hm.gvariant.type.variant`
- `hm.gvariant.type.arrayOf type`
- `hm.gvariant.type.maybeOf type`
- `hm.gvariant.type.tupleOf types`
- `hm.gvariant.type.dictionaryEntryOf types`
--
+
where `type` and `types` are themselves a type and list of types, respectively.
+
[[sec-option-types-gvariant-mkEmptyArray]]`hm.gvariant.mkEmptyArray type`:::
An alias of `hm.gvariant.mkArray type []`.
+
[[sec-option-types-gvariant-mkNothing]]`hm.gvariant.mkNothing type`:::
Builds a GVariant maybe value whose (non-existent) element is of the given type. The `type` value is constructed as described for the `mkArray` function above.
+
[[sec-option-types-gvariant-mkJust]]`hm.gvariant.mkJust element`:::
Builds a GVariant maybe value containing the given GVariant element.
+
[[sec-option-types-gvariant-mkTuple]]`hm.gvariant.mkTuple elements`:::
Builds a GVariant tuple containing the given list of elements, where each element is a GVariant value.
+
[[sec-option-types-gvariant-mkVariant]]`hm.gvariant.mkVariant element`:::
Builds a GVariant variant which contains the value of a GVariant element.
+
[[sec-option-types-gvariant-mkDictionaryEntry]]`hm.gvariant.mkDictionaryEntry elements`:::
Builds a GVariant dictionary entry containing the given list of elements, where each element is a GVariant value.
