about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/attrsets.nix1866
-rw-r--r--lib/licenses.nix15
-rw-r--r--lib/trivial.nix941
3 files changed, 2071 insertions, 751 deletions
diff --git a/lib/attrsets.nix b/lib/attrsets.nix
index 34054460ba761..de5968b953485 100644
--- a/lib/attrsets.nix
+++ b/lib/attrsets.nix
@@ -1,4 +1,6 @@
-/* Operations on attribute sets. */
+/**
+  Operations on attribute sets.
+*/
 { lib }:
 
 let
@@ -12,35 +14,57 @@ rec {
   inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr removeAttrs;
 
 
-  /* Return an attribute from nested attribute sets.
+  /**
+    Return an attribute from nested attribute sets.
+
+    Nix has an [attribute selection operator `. or`](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
+
+    ```nix
+    (x.a.b or 6) == attrByPath ["a" "b"] 6 x
+    # and
+    (x.${f p}."example.com" or 6) == attrByPath [ (f p) "example.com" ] 6 x
+    ```
+
 
-     Nix has an [attribute selection operator `. or`](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
+    # Inputs
 
-     ```nix
-     (x.a.b or 6) == attrByPath ["a" "b"] 6 x
-     # and
-     (x.${f p}."example.com" or 6) == attrByPath [ (f p) "example.com" ] 6 x
-     ```
+    `attrPath`
 
-     Example:
-       x = { a = { b = 3; }; }
-       # ["a" "b"] is equivalent to x.a.b
-       # 6 is a default value to return if the path does not exist in attrset
-       attrByPath ["a" "b"] 6 x
-       => 3
-       attrByPath ["z" "z"] 6 x
-       => 6
+    : A list of strings representing the attribute path to return from `set`
 
-     Type:
-       attrByPath :: [String] -> Any -> AttrSet -> Any
+    `default`
+
+    : Default value if `attrPath` does not resolve to an existing value
+
+    `set`
+
+    : The nested attribute set to select values from
+
+    # Type
 
+    ```
+    attrByPath :: [String] -> Any -> AttrSet -> Any
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrByPath` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    # ["a" "b"] is equivalent to x.a.b
+    # 6 is a default value to return if the path does not exist in attrset
+    attrByPath ["a" "b"] 6 x
+    => 3
+    attrByPath ["z" "z"] 6 x
+    => 6
+    ```
+
+    :::
   */
   attrByPath =
-    # A list of strings representing the attribute path to return from `set`
     attrPath:
-    # Default value if `attrPath` does not resolve to an existing value
     default:
-    # The nested attribute set to select values from
     set:
     let
       lenAttrPath = length attrPath;
@@ -57,37 +81,57 @@ rec {
     in
       attrByPath' 0 set;
 
-  /* Return if an attribute from nested attribute set exists.
+  /**
+    Return if an attribute from nested attribute set exists.
+
+    Nix has a [has attribute operator `?`](https://nixos.org/manual/nix/stable/language/operators#has-attribute), which is sufficient for such queries, as long as the number of attributes is static. For example:
 
-     Nix has a [has attribute operator `?`](https://nixos.org/manual/nix/stable/language/operators#has-attribute), which is sufficient for such queries, as long as the number of attributes is static. For example:
+    ```nix
+    (x?a.b) == hasAttryByPath ["a" "b"] x
+    # and
+    (x?${f p}."example.com") == hasAttryByPath [ (f p) "example.com" ] x
+    ```
+
+    **Laws**:
+     1.  ```nix
+         hasAttrByPath [] x == true
+         ```
+
+
+    # Inputs
 
-     ```nix
-     (x?a.b) == hasAttryByPath ["a" "b"] x
-     # and
-     (x?${f p}."example.com") == hasAttryByPath [ (f p) "example.com" ] x
-     ```
+    `attrPath`
 
-     **Laws**:
-      1.  ```nix
-          hasAttrByPath [] x == true
-          ```
+    : A list of strings representing the attribute path to check from `set`
 
-     Example:
-       x = { a = { b = 3; }; }
-       hasAttrByPath ["a" "b"] x
-       => true
-       hasAttrByPath ["z" "z"] x
-       => false
-       hasAttrByPath [] (throw "no need")
-       => true
+    `e`
 
-    Type:
-      hasAttrByPath :: [String] -> AttrSet -> Bool
+    : The nested attribute set to check
+
+    # Type
+
+    ```
+    hasAttrByPath :: [String] -> AttrSet -> Bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.hasAttrByPath` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    hasAttrByPath ["a" "b"] x
+    => true
+    hasAttrByPath ["z" "z"] x
+    => false
+    hasAttrByPath [] (throw "no need")
+    => true
+    ```
+
+    :::
   */
   hasAttrByPath =
-    # A list of strings representing the attribute path to check from `set`
     attrPath:
-    # The nested attribute set to check
     e:
     let
       lenAttrPath = length attrPath;
@@ -103,7 +147,7 @@ rec {
     in
       hasAttrByPath' 0 e;
 
-  /*
+  /**
     Return the longest prefix of an attribute path that refers to an existing attribute in a nesting of attribute sets.
 
     Can be used after [`mapAttrsRecursiveCond`](#function-library-lib.attrsets.mapAttrsRecursiveCond) to apply a condition,
@@ -120,24 +164,43 @@ rec {
         hasAttrByPath (attrsets.longestValidPathPrefix p x) x == true
         ```
 
-    Example:
-      x = { a = { b = 3; }; }
-      attrsets.longestValidPathPrefix ["a" "b" "c"] x
-      => ["a" "b"]
-      attrsets.longestValidPathPrefix ["a"] x
-      => ["a"]
-      attrsets.longestValidPathPrefix ["z" "z"] x
-      => []
-      attrsets.longestValidPathPrefix ["z" "z"] (throw "no need")
-      => []
-
-    Type:
-      attrsets.longestValidPathPrefix :: [String] -> Value -> [String]
+
+    # Inputs
+
+    `attrPath`
+
+    : A list of strings representing the longest possible path that may be returned.
+
+    `v`
+
+    : The nested attribute set to check.
+
+    # Type
+
+    ```
+    attrsets.longestValidPathPrefix :: [String] -> Value -> [String]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.longestValidPathPrefix` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    attrsets.longestValidPathPrefix ["a" "b" "c"] x
+    => ["a" "b"]
+    attrsets.longestValidPathPrefix ["a"] x
+    => ["a"]
+    attrsets.longestValidPathPrefix ["z" "z"] x
+    => []
+    attrsets.longestValidPathPrefix ["z" "z"] (throw "no need")
+    => []
+    ```
+
+    :::
   */
   longestValidPathPrefix =
-    # A list of strings representing the longest possible path that may be returned.
     attrPath:
-    # The nested attribute set to check.
     v:
     let
       lenAttrPath = length attrPath;
@@ -168,19 +231,39 @@ rec {
     in
       getPrefixForSetAtIndex v 0;
 
-  /* Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
+  /**
+    Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
+
 
-     Example:
-       setAttrByPath ["a" "b"] 3
-       => { a = { b = 3; }; }
+    # Inputs
 
-     Type:
-       setAttrByPath :: [String] -> Any -> AttrSet
+    `attrPath`
+
+    : A list of strings representing the attribute path to set
+
+    `value`
+
+    : The value to set at the location described by `attrPath`
+
+    # Type
+
+    ```
+    setAttrByPath :: [String] -> Any -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.setAttrByPath` usage example
+
+    ```nix
+    setAttrByPath ["a" "b"] 3
+    => { a = { b = 3; }; }
+    ```
+
+    :::
   */
   setAttrByPath =
-    # A list of strings representing the attribute path to set
     attrPath:
-    # The value to set at the location described by `attrPath`
     value:
     let
       len = length attrPath;
@@ -190,47 +273,89 @@ rec {
         else { ${elemAt attrPath n} = atDepth (n + 1); };
     in atDepth 0;
 
-  /* Like `attrByPath`, but without a default value. If it doesn't find the
-     path it will throw an error.
+  /**
+    Like `attrByPath`, but without a default value. If it doesn't find the
+    path it will throw an error.
 
-     Nix has an [attribute selection operator](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
+    Nix has an [attribute selection operator](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
 
     ```nix
-     x.a.b == getAttrByPath ["a" "b"] x
-     # and
-     x.${f p}."example.com" == getAttrByPath [ (f p) "example.com" ] x
-     ```
-
-     Example:
-       x = { a = { b = 3; }; }
-       getAttrFromPath ["a" "b"] x
-       => 3
-       getAttrFromPath ["z" "z"] x
-       => error: cannot find attribute `z.z'
-
-     Type:
-       getAttrFromPath :: [String] -> AttrSet -> Any
+    x.a.b == getAttrByPath ["a" "b"] x
+    # and
+    x.${f p}."example.com" == getAttrByPath [ (f p) "example.com" ] x
+    ```
+
+
+    # Inputs
+
+    `attrPath`
+
+    : A list of strings representing the attribute path to get from `set`
+
+    `set`
+
+    : The nested attribute set to find the value in.
+
+    # Type
+
+    ```
+    getAttrFromPath :: [String] -> AttrSet -> Any
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getAttrFromPath` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    getAttrFromPath ["a" "b"] x
+    => 3
+    getAttrFromPath ["z" "z"] x
+    => error: cannot find attribute `z.z'
+    ```
+
+    :::
   */
   getAttrFromPath =
-    # A list of strings representing the attribute path to get from `set`
     attrPath:
-    # The nested attribute set to find the value in.
     set:
     attrByPath attrPath (abort ("cannot find attribute `" + concatStringsSep "." attrPath + "'")) set;
 
-  /* Map each attribute in the given set and merge them into a new attribute set.
+  /**
+    Map each attribute in the given set and merge them into a new attribute set.
+
+
+    # Inputs
 
-     Type:
-       concatMapAttrs :: (String -> a -> AttrSet) -> AttrSet -> AttrSet
+    `f`
 
-     Example:
-       concatMapAttrs
-         (name: value: {
-           ${name} = value;
-           ${name + value} = value;
-         })
-         { x = "a"; y = "b"; }
-       => { x = "a"; xa = "a"; y = "b"; yb = "b"; }
+    : 1\. Function argument
+
+    `v`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    concatMapAttrs :: (String -> a -> AttrSet) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.concatMapAttrs` usage example
+
+    ```nix
+    concatMapAttrs
+      (name: value: {
+        ${name} = value;
+        ${name + value} = value;
+      })
+      { x = "a"; y = "b"; }
+    => { x = "a"; xa = "a"; y = "b"; yb = "b"; }
+    ```
+
+    :::
   */
   concatMapAttrs = f: v:
     foldl' mergeAttrs { }
@@ -239,49 +364,61 @@ rec {
       );
 
 
-  /* Update or set specific paths of an attribute set.
-
-     Takes a list of updates to apply and an attribute set to apply them to,
-     and returns the attribute set with the updates applied. Updates are
-     represented as `{ path = ...; update = ...; }` values, where `path` is a
-     list of strings representing the attribute path that should be updated,
-     and `update` is a function that takes the old value at that attribute path
-     as an argument and returns the new
-     value it should be.
-
-     Properties:
-
-     - Updates to deeper attribute paths are applied before updates to more
-       shallow attribute paths
-
-     - Multiple updates to the same attribute path are applied in the order
-       they appear in the update list
-
-     - If any but the last `path` element leads into a value that is not an
-       attribute set, an error is thrown
-
-     - If there is an update for an attribute path that doesn't exist,
-       accessing the argument in the update function causes an error, but
-       intermediate attribute sets are implicitly created as needed
-
-     Example:
-       updateManyAttrsByPath [
-         {
-           path = [ "a" "b" ];
-           update = old: { d = old.c; };
-         }
-         {
-           path = [ "a" "b" "c" ];
-           update = old: old + 1;
-         }
-         {
-           path = [ "x" "y" ];
-           update = old: "xy";
-         }
-       ] { a.b.c = 0; }
-       => { a = { b = { d = 1; }; }; x = { y = "xy"; }; }
-
-    Type: updateManyAttrsByPath :: [{ path :: [String]; update :: (Any -> Any); }] -> AttrSet -> AttrSet
+  /**
+    Update or set specific paths of an attribute set.
+
+    Takes a list of updates to apply and an attribute set to apply them to,
+    and returns the attribute set with the updates applied. Updates are
+    represented as `{ path = ...; update = ...; }` values, where `path` is a
+    list of strings representing the attribute path that should be updated,
+    and `update` is a function that takes the old value at that attribute path
+    as an argument and returns the new
+    value it should be.
+
+    Properties:
+
+    - Updates to deeper attribute paths are applied before updates to more
+      shallow attribute paths
+
+    - Multiple updates to the same attribute path are applied in the order
+      they appear in the update list
+
+    - If any but the last `path` element leads into a value that is not an
+      attribute set, an error is thrown
+
+    - If there is an update for an attribute path that doesn't exist,
+      accessing the argument in the update function causes an error, but
+      intermediate attribute sets are implicitly created as needed
+
+    # Type
+
+    ```
+    updateManyAttrsByPath :: [{ path :: [String]; update :: (Any -> Any); }] -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.updateManyAttrsByPath` usage example
+
+    ```nix
+    updateManyAttrsByPath [
+      {
+        path = [ "a" "b" ];
+        update = old: { d = old.c; };
+      }
+      {
+        path = [ "a" "b" "c" ];
+        update = old: old + 1;
+      }
+      {
+        path = [ "x" "y" ];
+        update = old: "xy";
+      }
+    ] { a.b.c = 0; }
+    => { a = { b = { d = 1; }; }; x = { y = "xy"; }; }
+    ```
+
+    :::
   */
   updateManyAttrsByPath = let
     # When recursing into attributes, instead of updating the `path` of each
@@ -342,96 +479,208 @@ rec {
 
   in updates: value: go 0 true value updates;
 
-  /* Return the specified attributes from a set.
+  /**
+    Return the specified attributes from a set.
+
+
+    # Inputs
+
+    `nameList`
+
+    : The list of attributes to fetch from `set`. Each attribute name must exist on the attrbitue set
 
-     Example:
-       attrVals ["a" "b" "c"] as
-       => [as.a as.b as.c]
+    `set`
 
-     Type:
-       attrVals :: [String] -> AttrSet -> [Any]
+    : The set to get attribute values from
+
+    # Type
+
+    ```
+    attrVals :: [String] -> AttrSet -> [Any]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrVals` usage example
+
+    ```nix
+    attrVals ["a" "b" "c"] as
+    => [as.a as.b as.c]
+    ```
+
+    :::
   */
   attrVals =
-    # The list of attributes to fetch from `set`. Each attribute name must exist on the attrbitue set
     nameList:
-    # The set to get attribute values from
     set: map (x: set.${x}) nameList;
 
 
-  /* Return the values of all attributes in the given set, sorted by
-     attribute name.
+  /**
+    Return the values of all attributes in the given set, sorted by
+    attribute name.
 
-     Example:
-       attrValues {c = 3; a = 1; b = 2;}
-       => [1 2 3]
+    # Type
 
-     Type:
-       attrValues :: AttrSet -> [Any]
+    ```
+    attrValues :: AttrSet -> [Any]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrValues` usage example
+
+    ```nix
+    attrValues {c = 3; a = 1; b = 2;}
+    => [1 2 3]
+    ```
+
+    :::
   */
   attrValues = builtins.attrValues;
 
 
-  /* Given a set of attribute names, return the set of the corresponding
-     attributes from the given set.
+  /**
+    Given a set of attribute names, return the set of the corresponding
+    attributes from the given set.
+
+
+    # Inputs
+
+    `names`
 
-     Example:
-       getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
-       => { a = 1; b = 2; }
+    : A list of attribute names to get out of `set`
 
-     Type:
-       getAttrs :: [String] -> AttrSet -> AttrSet
+    `attrs`
+
+    : The set to get the named attributes from
+
+    # Type
+
+    ```
+    getAttrs :: [String] -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getAttrs` usage example
+
+    ```nix
+    getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
+    => { a = 1; b = 2; }
+    ```
+
+    :::
   */
   getAttrs =
-    # A list of attribute names to get out of `set`
     names:
-    # The set to get the named attributes from
     attrs: genAttrs names (name: attrs.${name});
 
-  /* Collect each attribute named `attr` from a list of attribute
-     sets.  Sets that don't contain the named attribute are ignored.
+  /**
+    Collect each attribute named `attr` from a list of attribute
+    sets.  Sets that don't contain the named attribute are ignored.
+
+    # Inputs
+
+    `attr`
+
+    : The attribute name to get out of the sets.
 
-     Example:
-       catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
-       => [1 2]
+    `list`
 
-     Type:
-       catAttrs :: String -> [AttrSet] -> [Any]
+    : The list of attribute sets to go through
+
+    # Type
+
+    ```
+    catAttrs :: String -> [AttrSet] -> [Any]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.catAttrs` usage example
+
+    ```nix
+    catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
+    => [1 2]
+    ```
+
+    :::
   */
   catAttrs = builtins.catAttrs;
 
 
-  /* Filter an attribute set by removing all attributes for which the
-     given predicate return false.
+  /**
+    Filter an attribute set by removing all attributes for which the
+    given predicate return false.
+
+
+    # Inputs
+
+    `pred`
 
-     Example:
-       filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
-       => { foo = 1; }
+    : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
 
-     Type:
-       filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    `set`
+
+    : The attribute set to filter
+
+    # Type
+
+    ```
+    filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.filterAttrs` usage example
+
+    ```nix
+    filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
+    => { foo = 1; }
+    ```
+
+    :::
   */
   filterAttrs =
-    # Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
     pred:
-    # The attribute set to filter
     set:
     listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set));
 
 
-  /* Filter an attribute set recursively by removing all attributes for
-     which the given predicate return false.
+  /**
+    Filter an attribute set recursively by removing all attributes for
+    which the given predicate return false.
+
+
+    # Inputs
+
+    `pred`
+
+    : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
+
+    `set`
+
+    : The attribute set to filter
+
+    # Type
+
+    ```
+    filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    ```
 
-     Example:
-       filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
-       => { foo = {}; }
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.filterAttrsRecursive` usage example
 
-     Type:
-       filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    ```nix
+    filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
+    => { foo = {}; }
+    ```
+
+    :::
   */
   filterAttrsRecursive =
-    # Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
     pred:
-    # The attribute set to filter
     set:
     listToAttrs (
       concatMap (name:
@@ -445,59 +694,84 @@ rec {
       ) (attrNames set)
     );
 
-   /*
+   /**
     Like [`lib.lists.foldl'`](#function-library-lib.lists.foldl-prime) but for attribute sets.
     Iterates over every name-value pair in the given attribute set.
     The result of the callback function is often called `acc` for accumulator. It is passed between callbacks from left to right and the final `acc` is the return value of `foldlAttrs`.
 
     Attention:
-      There is a completely different function
-      `lib.foldAttrs`
-      which has nothing to do with this function, despite the similar name.
-
-    Example:
-      foldlAttrs
-        (acc: name: value: {
-          sum = acc.sum + value;
-          names = acc.names ++ [name];
-        })
-        { sum = 0; names = []; }
-        {
-          foo = 1;
-          bar = 10;
-        }
-      ->
-        {
-          sum = 11;
-          names = ["bar" "foo"];
-        }
-
-      foldlAttrs
-        (throw "function not needed")
-        123
-        {};
-      ->
-        123
-
-      foldlAttrs
-        (acc: _: _: acc)
-        3
-        { z = throw "value not needed"; a = throw "value not needed"; };
-      ->
-        3
-
-      The accumulator doesn't have to be an attrset.
-      It can be as simple as a number or string.
-
-      foldlAttrs
-        (acc: _: v: acc * 10 + v)
-        1
-        { z = 1; a = 2; };
-      ->
-        121
-
-    Type:
-      foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
+
+    There is a completely different function `lib.foldAttrs`
+    which has nothing to do with this function, despite the similar name.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
+
+    `init`
+
+    : 2\. Function argument
+
+    `set`
+
+    : 3\. Function argument
+
+    # Type
+
+    ```
+    foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.foldlAttrs` usage example
+
+    ```nix
+    foldlAttrs
+      (acc: name: value: {
+        sum = acc.sum + value;
+        names = acc.names ++ [name];
+      })
+      { sum = 0; names = []; }
+      {
+        foo = 1;
+        bar = 10;
+      }
+    ->
+      {
+        sum = 11;
+        names = ["bar" "foo"];
+      }
+
+    foldlAttrs
+      (throw "function not needed")
+      123
+      {};
+    ->
+      123
+
+    foldlAttrs
+      (acc: _: _: acc)
+      3
+      { z = throw "value not needed"; a = throw "value not needed"; };
+    ->
+      3
+
+    The accumulator doesn't have to be an attrset.
+    It can be as simple as a number or string.
+
+    foldlAttrs
+      (acc: _: v: acc * 10 + v)
+      1
+      { z = 1; a = 2; };
+    ->
+      121
+    ```
+
+    :::
   */
   foldlAttrs = f: init: set:
     foldl'
@@ -505,22 +779,44 @@ rec {
       init
       (attrNames set);
 
-  /* Apply fold functions to values grouped by key.
+  /**
+    Apply fold functions to values grouped by key.
+
+
+    # Inputs
+
+    `op`
+
+    : A function, given a value and a collector combines the two.
+
+    `nul`
+
+    : The starting value.
+
+    `list_of_attrs`
+
+    : A list of attribute sets to fold together by key.
+
+    # Type
+
+    ```
+    foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any
+    ```
 
-     Example:
-       foldAttrs (item: acc: [item] ++ acc) [] [{ a = 2; } { a = 3; }]
-       => { a = [ 2 3 ]; }
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.foldAttrs` usage example
 
-     Type:
-       foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any
+    ```nix
+    foldAttrs (item: acc: [item] ++ acc) [] [{ a = 2; } { a = 3; }]
+    => { a = [ 2 3 ]; }
+    ```
 
+    :::
   */
   foldAttrs =
-    # A function, given a value and a collector combines the two.
     op:
-    # The starting value.
     nul:
-    # A list of attribute sets to fold together by key.
     list_of_attrs:
     foldr (n: a:
         foldr (name: o:
@@ -529,26 +825,46 @@ rec {
     ) {} list_of_attrs;
 
 
-  /* Recursively collect sets that verify a given predicate named `pred`
-     from the set `attrs`.  The recursion is stopped when the predicate is
-     verified.
+  /**
+    Recursively collect sets that verify a given predicate named `pred`
+    from the set `attrs`. The recursion is stopped when the predicate is
+    verified.
+
 
-     Example:
-       collect isList { a = { b = ["b"]; }; c = [1]; }
-       => [["b"] [1]]
+    # Inputs
 
-       collect (x: x ? outPath)
-          { a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
-       => [{ outPath = "a/"; } { outPath = "b/"; }]
+    `pred`
+
+    : Given an attribute's value, determine if recursion should stop.
+
+    `attrs`
+
+    : The attribute set to recursively collect.
+
+    # Type
 
-     Type:
-       collect :: (AttrSet -> Bool) -> AttrSet -> [x]
+    ```
+    collect :: (AttrSet -> Bool) -> AttrSet -> [x]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.collect` usage example
+
+    ```nix
+    collect isList { a = { b = ["b"]; }; c = [1]; }
+    => [["b"] [1]]
+
+    collect (x: x ? outPath)
+       { a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
+    => [{ outPath = "a/"; } { outPath = "b/"; }]
+    ```
+
+    :::
   */
   collect =
-  # Given an attribute's value, determine if recursion should stop.
-  pred:
-  # The attribute set to recursively collect.
-  attrs:
+    pred:
+    attrs:
     if pred attrs then
       [ attrs ]
     else if isAttrs attrs then
@@ -556,21 +872,39 @@ rec {
     else
       [];
 
-  /* Return the cartesian product of attribute set value combinations.
-
-    Example:
-      cartesianProductOfSets { a = [ 1 2 ]; b = [ 10 20 ]; }
-      => [
-           { a = 1; b = 10; }
-           { a = 1; b = 20; }
-           { a = 2; b = 10; }
-           { a = 2; b = 20; }
-         ]
-     Type:
-       cartesianProductOfSets :: AttrSet -> [AttrSet]
+  /**
+    Return the cartesian product of attribute set value combinations.
+
+
+    # Inputs
+
+    `attrsOfLists`
+
+    : Attribute set with attributes that are lists of values
+
+    # Type
+
+    ```
+    cartesianProductOfSets :: AttrSet -> [AttrSet]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.cartesianProductOfSets` usage example
+
+    ```nix
+    cartesianProductOfSets { a = [ 1 2 ]; b = [ 10 20 ]; }
+    => [
+         { a = 1; b = 10; }
+         { a = 1; b = 20; }
+         { a = 2; b = 10; }
+         { a = 2; b = 20; }
+       ]
+    ```
+
+    :::
   */
   cartesianProductOfSets =
-    # Attribute set with attributes that are lists of values
     attrsOfLists:
     foldl' (listOfAttrs: attrName:
       concatMap (attrs:
@@ -579,76 +913,155 @@ rec {
     ) [{}] (attrNames attrsOfLists);
 
 
-  /* Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
+  /**
+    Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
+
+
+    # Inputs
 
-     Example:
-       nameValuePair "some" 6
-       => { name = "some"; value = 6; }
+    `name`
 
-     Type:
-       nameValuePair :: String -> Any -> { name :: String; value :: Any; }
+    : Attribute name
+
+    `value`
+
+    : Attribute value
+
+    # Type
+
+    ```
+    nameValuePair :: String -> Any -> { name :: String; value :: Any; }
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.nameValuePair` usage example
+
+    ```nix
+    nameValuePair "some" 6
+    => { name = "some"; value = 6; }
+    ```
+
+    :::
   */
   nameValuePair =
-    # Attribute name
     name:
-    # Attribute value
     value:
     { inherit name value; };
 
 
-  /* Apply a function to each element in an attribute set, creating a new attribute set.
+  /**
+    Apply a function to each element in an attribute set, creating a new attribute set.
+
+    # Inputs
+
+    `f`
 
-     Example:
-       mapAttrs (name: value: name + "-" + value)
-          { x = "foo"; y = "bar"; }
-       => { x = "x-foo"; y = "y-bar"; }
+    : A function that takes an attribute name and its value, and returns the new value for the attribute.
 
-     Type:
-       mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
+    `attrset`
+
+    : The attribute set to iterate through.
+
+    # Type
+
+    ```
+    mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mapAttrs` usage example
+
+    ```nix
+    mapAttrs (name: value: name + "-" + value)
+       { x = "foo"; y = "bar"; }
+    => { x = "x-foo"; y = "y-bar"; }
+    ```
+
+    :::
   */
   mapAttrs = builtins.mapAttrs;
 
 
-  /* Like `mapAttrs`, but allows the name of each attribute to be
-     changed in addition to the value.  The applied function should
-     return both the new name and value as a `nameValuePair`.
+  /**
+    Like `mapAttrs`, but allows the name of each attribute to be
+    changed in addition to the value.  The applied function should
+    return both the new name and value as a `nameValuePair`.
+
+
+    # Inputs
 
-     Example:
-       mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
-          { x = "a"; y = "b"; }
-       => { foo_x = "bar-a"; foo_y = "bar-b"; }
+    `f`
 
-     Type:
-       mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
+    : A function, given an attribute's name and value, returns a new `nameValuePair`.
+
+    `set`
+
+    : Attribute set to map over.
+
+    # Type
+
+    ```
+    mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mapAttrs'` usage example
+
+    ```nix
+    mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
+       { x = "a"; y = "b"; }
+    => { foo_x = "bar-a"; foo_y = "bar-b"; }
+    ```
+
+    :::
   */
   mapAttrs' =
-    # A function, given an attribute's name and value, returns a new `nameValuePair`.
     f:
-    # Attribute set to map over.
     set:
     listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
 
 
-  /* Call a function for each attribute in the given set and return
-     the result in a list.
+  /**
+    Call a function for each attribute in the given set and return
+    the result in a list.
+
+    # Inputs
+
+    `f`
 
-     Example:
-       mapAttrsToList (name: value: name + value)
-          { x = "a"; y = "b"; }
-       => [ "xa" "yb" ]
+    : A function, given an attribute's name and value, returns a new value.
 
-     Type:
-       mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
+    `attrs`
 
+    : Attribute set to map over.
+
+    # Type
+
+    ```
+    mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mapAttrsToList` usage example
+
+    ```nix
+    mapAttrsToList (name: value: name + value)
+       { x = "a"; y = "b"; }
+    => [ "xa" "yb" ]
+    ```
+
+    :::
   */
   mapAttrsToList =
-    # A function, given an attribute's name and value, returns a new value.
     f:
-    # Attribute set to map over.
     attrs:
     map (name: f name attrs.${name}) (attrNames attrs);
 
-  /*
+  /**
     Deconstruct an attrset to a list of name-value pairs as expected by [`builtins.listToAttrs`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-listToAttrs).
     Each element of the resulting list is an attribute set with these attributes:
     - `name` (string): The name of the attribute
@@ -668,13 +1081,28 @@ rec {
     This is because the `listToAttrs` removes duplicate names and doesn't preserve the order of the list.
     :::
 
-    Example:
-      attrsToList { foo = 1; bar = "asdf"; }
-      => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]
+    # Inputs
+
+    `set`
 
-    Type:
-      attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]
+    : The attribute set to deconstruct.
+
+    # Type
 
+    ```
+    attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrsToList` usage example
+
+    ```nix
+    attrsToList { foo = 1; bar = "asdf"; }
+    => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]
+    ```
+
+    :::
   */
   attrsToList = mapAttrsToList nameValuePair;
 
@@ -705,9 +1133,7 @@ rec {
     ```
   */
   mapAttrsRecursive =
-    # A function that, given an attribute path as a list of strings and the corresponding attribute value, returns a new value.
     f:
-    # Attribute set to recursively map over.
     set:
     mapAttrsRecursiveCond (as: true) f set;
 
@@ -736,12 +1162,8 @@ rec {
     ```
   */
   mapAttrsRecursiveCond =
-    # A function that, given the attribute set the recursion is currently at, determines if to recurse deeper into that attribute set.
     cond:
-    # A function that, given an attribute path as a list of strings and the corresponding attribute value, returns a new value.
-    # The attribute value is either an attribute set for which `cond` returns false, or something other than an attribute set.
     f:
-    # Attribute set to recursively map over.
     set:
     let
       recurse = path:
@@ -754,48 +1176,95 @@ rec {
     recurse [ ] set;
 
 
-  /* Generate an attribute set by mapping a function over a list of
-     attribute names.
+  /**
+    Generate an attribute set by mapping a function over a list of
+    attribute names.
+
+
+    # Inputs
+
+    `names`
+
+    : Names of values in the resulting attribute set.
+
+    `f`
+
+    : A function, given the name of the attribute, returns the attribute's value.
+
+    # Type
+
+    ```
+    genAttrs :: [ String ] -> (String -> Any) -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.genAttrs` usage example
 
-     Example:
-       genAttrs [ "foo" "bar" ] (name: "x_" + name)
-       => { foo = "x_foo"; bar = "x_bar"; }
+    ```nix
+    genAttrs [ "foo" "bar" ] (name: "x_" + name)
+    => { foo = "x_foo"; bar = "x_bar"; }
+    ```
 
-     Type:
-       genAttrs :: [ String ] -> (String -> Any) -> AttrSet
+    :::
   */
   genAttrs =
-    # Names of values in the resulting attribute set.
     names:
-    # A function, given the name of the attribute, returns the attribute's value.
     f:
     listToAttrs (map (n: nameValuePair n (f n)) names);
 
 
-  /* Check whether the argument is a derivation. Any set with
-     `{ type = "derivation"; }` counts as a derivation.
+  /**
+    Check whether the argument is a derivation. Any set with
+    `{ type = "derivation"; }` counts as a derivation.
+
 
-     Example:
-       nixpkgs = import <nixpkgs> {}
-       isDerivation nixpkgs.ruby
-       => true
-       isDerivation "foobar"
-       => false
+    # Inputs
 
-     Type:
-       isDerivation :: Any -> Bool
+    `value`
+
+    : Value to check.
+
+    # Type
+
+    ```
+    isDerivation :: Any -> Bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.isDerivation` usage example
+
+    ```nix
+    nixpkgs = import <nixpkgs> {}
+    isDerivation nixpkgs.ruby
+    => true
+    isDerivation "foobar"
+    => false
+    ```
+
+    :::
   */
   isDerivation =
-    # Value to check.
     value: value.type or null == "derivation";
 
-   /* Converts a store path to a fake derivation.
+   /**
+    Converts a store path to a fake derivation.
+
+
+    # Inputs
+
+    `path`
 
-      Type:
-        toDerivation :: Path -> Derivation
-   */
+    : A store path to convert to a derivation.
+
+    # Type
+
+    ```
+    toDerivation :: Path -> Derivation
+    ```
+  */
    toDerivation =
-     # A store path to convert to a derivation.
      path:
      let
        path' = builtins.storePath path;
@@ -810,42 +1279,85 @@ rec {
     in res;
 
 
-  /* If `cond` is true, return the attribute set `as`,
-     otherwise an empty attribute set.
+  /**
+    If `cond` is true, return the attribute set `as`,
+    otherwise an empty attribute set.
+
+
+    # Inputs
+
+    `cond`
 
-     Example:
-       optionalAttrs (true) { my = "set"; }
-       => { my = "set"; }
-       optionalAttrs (false) { my = "set"; }
-       => { }
+    : Condition under which the `as` attribute set is returned.
+
+    `as`
+
+    : The attribute set to return if `cond` is `true`.
+
+    # Type
+
+    ```
+    optionalAttrs :: Bool -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.optionalAttrs` usage example
+
+    ```nix
+    optionalAttrs (true) { my = "set"; }
+    => { my = "set"; }
+    optionalAttrs (false) { my = "set"; }
+    => { }
+    ```
 
-     Type:
-       optionalAttrs :: Bool -> AttrSet -> AttrSet
+    :::
   */
   optionalAttrs =
-    # Condition under which the `as` attribute set is returned.
     cond:
-    # The attribute set to return if `cond` is `true`.
     as:
     if cond then as else {};
 
 
-  /* Merge sets of attributes and use the function `f` to merge attributes
-     values.
+  /**
+    Merge sets of attributes and use the function `f` to merge attributes
+    values.
+
+
+    # Inputs
+
+    `names`
 
-     Example:
-       zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
-       => { a = ["x" "y"]; }
+    : List of attribute names to zip.
 
-     Type:
-       zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    `f`
+
+    : A function, accepts an attribute name, all the values, and returns a combined value.
+
+    `sets`
+
+    : List of values from the list of attribute sets.
+
+    # Type
+
+    ```
+    zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.zipAttrsWithNames` usage example
+
+    ```nix
+    zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
+    => { a = ["x" "y"]; }
+    ```
+
+    :::
   */
   zipAttrsWithNames =
-    # List of attribute names to zip.
     names:
-    # A function, accepts an attribute name, all the values, and returns a combined value.
     f:
-    # List of values from the list of attribute sets.
     sets:
     listToAttrs (map (name: {
       inherit name;
@@ -853,52 +1365,91 @@ rec {
     }) names);
 
 
-  /* Merge sets of attributes and use the function f to merge attribute values.
-     Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`.
+  /**
+    Merge sets of attributes and use the function f to merge attribute values.
+    Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`.
 
-     Implementation note: Common names appear multiple times in the list of
-     names, hopefully this does not affect the system because the maximal
-     laziness avoid computing twice the same expression and `listToAttrs` does
-     not care about duplicated attribute names.
+    Implementation note: Common names appear multiple times in the list of
+    names, hopefully this does not affect the system because the maximal
+    laziness avoid computing twice the same expression and `listToAttrs` does
+    not care about duplicated attribute names.
 
-     Example:
-       zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
-       => { a = ["x" "y"]; b = ["z"]; }
+    # Type
+
+    ```
+    zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.zipAttrsWith` usage example
 
-     Type:
-       zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    ```nix
+    zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
+    => { a = ["x" "y"]; b = ["z"]; }
+    ```
+
+    :::
   */
   zipAttrsWith =
     builtins.zipAttrsWith or (f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets);
 
 
-  /* Merge sets of attributes and combine each attribute value in to a list.
+  /**
+    Merge sets of attributes and combine each attribute value in to a list.
+
+    Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function.
+
+    # Type
+
+    ```
+    zipAttrs :: [ AttrSet ] -> AttrSet
+    ```
 
-     Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function.
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.zipAttrs` usage example
 
-     Example:
-       zipAttrs [{a = "x";} {a = "y"; b = "z";}]
-       => { a = ["x" "y"]; b = ["z"]; }
+    ```nix
+    zipAttrs [{a = "x";} {a = "y"; b = "z";}]
+    => { a = ["x" "y"]; b = ["z"]; }
+    ```
 
-     Type:
-       zipAttrs :: [ AttrSet ] -> AttrSet
+    :::
   */
   zipAttrs = zipAttrsWith (name: values: values);
 
-  /*
+  /**
     Merge a list of attribute sets together using the `//` operator.
     In case of duplicate attributes, values from later list elements take precedence over earlier ones.
     The result is the same as `foldl mergeAttrs { }`, but the performance is better for large inputs.
     For n list elements, each with an attribute set containing m unique attributes, the complexity of this operation is O(nm log n).
 
-    Type:
-      mergeAttrsList :: [ Attrs ] -> Attrs
 
-    Example:
-      mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ]
-      => { a = 0; b = 1; c = 2; d = 3; }
-      mergeAttrsList [ { a = 0; } { a = 1; } ]
-      => { a = 1; }
+    # Inputs
+
+    `list`
+
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    mergeAttrsList :: [ Attrs ] -> Attrs
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mergeAttrsList` usage example
+
+    ```nix
+    mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ]
+    => { a = 0; b = 1; c = 2; d = 3; }
+    mergeAttrsList [ { a = 0; } { a = 1; } ]
+    => { a = 1; }
+    ```
+
+    :::
   */
   mergeAttrsList = list:
     let
@@ -922,42 +1473,65 @@ rec {
       binaryMerge 0 (length list);
 
 
-  /* Does the same as the update operator '//' except that attributes are
-     merged until the given predicate is verified.  The predicate should
-     accept 3 arguments which are the path to reach the attribute, a part of
-     the first attribute set and a part of the second attribute set.  When
-     the predicate is satisfied, the value of the first attribute set is
-     replaced by the value of the second attribute set.
-
-     Example:
-       recursiveUpdateUntil (path: l: r: path == ["foo"]) {
-         # first attribute set
-         foo.bar = 1;
-         foo.baz = 2;
-         bar = 3;
-       } {
-         #second attribute set
-         foo.bar = 1;
-         foo.quz = 2;
-         baz = 4;
-       }
-
-       => {
-         foo.bar = 1; # 'foo.*' from the second set
-         foo.quz = 2; #
-         bar = 3;     # 'bar' from the first set
-         baz = 4;     # 'baz' from the second set
-       }
-
-     Type:
-       recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
+  /**
+    Does the same as the update operator '//' except that attributes are
+    merged until the given predicate is verified.  The predicate should
+    accept 3 arguments which are the path to reach the attribute, a part of
+    the first attribute set and a part of the second attribute set.  When
+    the predicate is satisfied, the value of the first attribute set is
+    replaced by the value of the second attribute set.
+
+
+    # Inputs
+
+    `pred`
+
+    : Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
+
+    `lhs`
+
+    : Left attribute set of the merge.
+
+    `rhs`
+
+    : Right attribute set of the merge.
+
+    # Type
+
+    ```
+    recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.recursiveUpdateUntil` usage example
+
+    ```nix
+    recursiveUpdateUntil (path: l: r: path == ["foo"]) {
+      # first attribute set
+      foo.bar = 1;
+      foo.baz = 2;
+      bar = 3;
+    } {
+      #second attribute set
+      foo.bar = 1;
+      foo.quz = 2;
+      baz = 4;
+    }
+
+    => {
+      foo.bar = 1; # 'foo.*' from the second set
+      foo.quz = 2; #
+      bar = 3;     # 'bar' from the first set
+      baz = 4;     # 'baz' from the second set
+    }
+    ```
+
+    :::
   */
   recursiveUpdateUntil =
-    # Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
     pred:
-    # Left attribute set of the merge.
     lhs:
-    # Right attribute set of the merge.
     rhs:
     let f = attrPath:
       zipAttrsWith (n: values:
@@ -971,51 +1545,90 @@ rec {
     in f [] [rhs lhs];
 
 
-  /* A recursive variant of the update operator ‘//’.  The recursion
-     stops when one of the attribute values is not an attribute set,
-     in which case the right hand side value takes precedence over the
-     left hand side value.
+  /**
+    A recursive variant of the update operator ‘//’.  The recursion
+    stops when one of the attribute values is not an attribute set,
+    in which case the right hand side value takes precedence over the
+    left hand side value.
+
+
+    # Inputs
+
+    `lhs`
+
+    : Left attribute set of the merge.
+
+    `rhs`
+
+    : Right attribute set of the merge.
+
+    # Type
+
+    ```
+    recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
+    ```
 
-     Example:
-       recursiveUpdate {
-         boot.loader.grub.enable = true;
-         boot.loader.grub.device = "/dev/hda";
-       } {
-         boot.loader.grub.device = "";
-       }
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.recursiveUpdate` usage example
 
-       returns: {
-         boot.loader.grub.enable = true;
-         boot.loader.grub.device = "";
-       }
+    ```nix
+    recursiveUpdate {
+      boot.loader.grub.enable = true;
+      boot.loader.grub.device = "/dev/hda";
+    } {
+      boot.loader.grub.device = "";
+    }
+
+    returns: {
+      boot.loader.grub.enable = true;
+      boot.loader.grub.device = "";
+    }
+    ```
 
-     Type:
-       recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
+    :::
   */
   recursiveUpdate =
-    # Left attribute set of the merge.
     lhs:
-    # Right attribute set of the merge.
     rhs:
     recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs;
 
 
-  /*
+  /**
     Recurse into every attribute set of the first argument and check that:
     - Each attribute path also exists in the second argument.
     - If the attribute's value is not a nested attribute set, it must have the same value in the right argument.
 
-     Example:
-       matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
-       => true
 
-     Type:
-       matchAttrs :: AttrSet -> AttrSet -> Bool
+    # Inputs
+
+    `pattern`
+
+    : Attribute set structure to match
+
+    `attrs`
+
+    : Attribute set to check
+
+    # Type
+
+    ```
+    matchAttrs :: AttrSet -> AttrSet -> Bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.matchAttrs` usage example
+
+    ```nix
+    matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
+    => true
+    ```
+
+    :::
   */
   matchAttrs =
-    # Attribute set structure to match
     pattern:
-    # Attribute set to check
     attrs:
     assert isAttrs pattern;
     all
@@ -1034,161 +1647,340 @@ rec {
     )
     (attrNames pattern);
 
-  /* Override only the attributes that are already present in the old set
+  /**
+    Override only the attributes that are already present in the old set
     useful for deep-overriding.
 
-    Example:
-      overrideExisting {} { a = 1; }
-      => {}
-      overrideExisting { b = 2; } { a = 1; }
-      => { b = 2; }
-      overrideExisting { a = 3; b = 2; } { a = 1; }
-      => { a = 1; b = 2; }
 
-    Type:
-      overrideExisting :: AttrSet -> AttrSet -> AttrSet
+    # Inputs
+
+    `old`
+
+    : Original attribute set
+
+    `new`
+
+    : Attribute set with attributes to override in `old`.
+
+    # Type
+
+    ```
+    overrideExisting :: AttrSet -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.overrideExisting` usage example
+
+    ```nix
+    overrideExisting {} { a = 1; }
+    => {}
+    overrideExisting { b = 2; } { a = 1; }
+    => { b = 2; }
+    overrideExisting { a = 3; b = 2; } { a = 1; }
+    => { a = 1; b = 2; }
+    ```
+
+    :::
   */
   overrideExisting =
-    # Original attribute set
     old:
-    # Attribute set with attributes to override in `old`.
     new:
     mapAttrs (name: value: new.${name} or value) old;
 
 
-  /* Turns a list of strings into a human-readable description of those
+  /**
+    Turns a list of strings into a human-readable description of those
     strings represented as an attribute path. The result of this function is
     not intended to be machine-readable.
     Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
 
-    Example:
-      showAttrPath [ "foo" "10" "bar" ]
-      => "foo.\"10\".bar"
-      showAttrPath []
-      => "<root attribute path>"
 
-    Type:
-      showAttrPath :: [String] -> String
+    # Inputs
+
+    `path`
+
+    : Attribute path to render to a string
+
+    # Type
+
+    ```
+    showAttrPath :: [String] -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.showAttrPath` usage example
+
+    ```nix
+    showAttrPath [ "foo" "10" "bar" ]
+    => "foo.\"10\".bar"
+    showAttrPath []
+    => "<root attribute path>"
+    ```
+
+    :::
   */
   showAttrPath =
-    # Attribute path to render to a string
     path:
     if path == [] then "<root attribute path>"
     else concatMapStringsSep "." escapeNixIdentifier path;
 
 
-  /* Get a package output.
-     If no output is found, fallback to `.out` and then to the default.
+  /**
+    Get a package output.
+    If no output is found, fallback to `.out` and then to the default.
+
+
+    # Inputs
+
+    `output`
 
-     Example:
-       getOutput "dev" pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    : 1\. Function argument
 
-     Type:
-       getOutput :: String -> Derivation -> String
+    `pkg`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    getOutput :: String -> Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getOutput` usage example
+
+    ```nix
+    getOutput "dev" pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    ```
+
+    :::
   */
   getOutput = output: pkg:
     if ! pkg ? outputSpecified || ! pkg.outputSpecified
       then pkg.${output} or pkg.out or pkg
       else pkg;
 
-  /* Get a package's `bin` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `bin` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
 
-     Example:
-       getBin pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r"
+    : The package whose `bin` output will be retrieved.
 
-     Type:
-       getBin :: Derivation -> String
+    # Type
+
+    ```
+    getBin :: Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getBin` usage example
+
+    ```nix
+    getBin pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r"
+    ```
+
+    :::
   */
   getBin = getOutput "bin";
 
 
-  /* Get a package's `lib` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `lib` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
 
-     Example:
-       getLib pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib"
+    : The package whose `lib` output will be retrieved.
 
-     Type:
-       getLib :: Derivation -> String
+    # Type
+
+    ```
+    getLib :: Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getLib` usage example
+
+    ```nix
+    getLib pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib"
+    ```
+
+    :::
   */
   getLib = getOutput "lib";
 
 
-  /* Get a package's `dev` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `dev` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
 
-     Example:
-       getDev pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    : The package whose `dev` output will be retrieved.
+
+    # Type
+
+    ```
+    getDev :: Derivation -> String
+    ```
 
-     Type:
-       getDev :: Derivation -> String
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getDev` usage example
+
+    ```nix
+    getDev pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    ```
+
+    :::
   */
   getDev = getOutput "dev";
 
 
-  /* Get a package's `man` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `man` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
+
+    : The package whose `man` output will be retrieved.
+
+    # Type
+
+    ```
+    getMan :: Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getMan` usage example
 
-     Example:
-       getMan pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man"
+    ```nix
+    getMan pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man"
+    ```
 
-     Type:
-       getMan :: Derivation -> String
+    :::
   */
   getMan = getOutput "man";
 
-  /* Pick the outputs of packages to place in `buildInputs`
+  /**
+    Pick the outputs of packages to place in `buildInputs`
+
+    # Inputs
 
-   Type: chooseDevOutputs :: [Derivation] -> [String]
+    `pkgs`
 
+    : List of packages.
+
+    # Type
+
+    ```
+    chooseDevOutputs :: [Derivation] -> [String]
+    ```
   */
   chooseDevOutputs = builtins.map getDev;
 
-  /* Make various Nix tools consider the contents of the resulting
-     attribute set when looking for what to build, find, etc.
+  /**
+    Make various Nix tools consider the contents of the resulting
+    attribute set when looking for what to build, find, etc.
 
-     This function only affects a single attribute set; it does not
-     apply itself recursively for nested attribute sets.
+    This function only affects a single attribute set; it does not
+    apply itself recursively for nested attribute sets.
 
-     Example:
-       { pkgs ? import <nixpkgs> {} }:
-       {
-         myTools = pkgs.lib.recurseIntoAttrs {
-           inherit (pkgs) hello figlet;
-         };
-       }
 
-     Type:
-       recurseIntoAttrs :: AttrSet -> AttrSet
+    # Inputs
+
+    `attrs`
+
+    : An attribute set to scan for derivations.
+
+    # Type
 
-   */
+    ```
+    recurseIntoAttrs :: AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.recurseIntoAttrs` usage example
+
+    ```nix
+    { pkgs ? import <nixpkgs> {} }:
+    {
+      myTools = pkgs.lib.recurseIntoAttrs {
+        inherit (pkgs) hello figlet;
+      };
+    }
+    ```
+
+    :::
+  */
   recurseIntoAttrs =
-    # An attribute set to scan for derivations.
     attrs:
     attrs // { recurseForDerivations = true; };
 
-  /* Undo the effect of recurseIntoAttrs.
+  /**
+    Undo the effect of recurseIntoAttrs.
 
-     Type:
-       dontRecurseIntoAttrs :: AttrSet -> AttrSet
-   */
+
+    # Inputs
+
+    `attrs`
+
+    : An attribute set to not scan for derivations.
+
+    # Type
+
+    ```
+    dontRecurseIntoAttrs :: AttrSet -> AttrSet
+    ```
+  */
   dontRecurseIntoAttrs =
-    # An attribute set to not scan for derivations.
     attrs:
     attrs // { recurseForDerivations = false; };
 
-  /* `unionOfDisjoint x y` is equal to `x // y // z` where the
-     attrnames in `z` are the intersection of the attrnames in `x` and
-     `y`, and all values `assert` with an error message.  This
-      operator is commutative, unlike (//).
+  /**
+    `unionOfDisjoint x y` is equal to `x // y // z` where the
+    attrnames in `z` are the intersection of the attrnames in `x` and
+    `y`, and all values `assert` with an error message.  This
+     operator is commutative, unlike (//).
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
 
-     Type: unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet
+    ```
   */
   unionOfDisjoint = x: y:
     let
diff --git a/lib/licenses.nix b/lib/licenses.nix
index 30ca31ff71f2f..a60171e55c129 100644
--- a/lib/licenses.nix
+++ b/lib/licenses.nix
@@ -599,6 +599,11 @@ in mkLicense lset) ({
     url = "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception";
   };
 
+  giftware = {
+    spdxId = "Giftware";
+    fullName = "Giftware License";
+  };
+
   hpnd = {
     spdxId = "HPND";
     fullName = "Historic Permission Notice and Disclaimer";
@@ -609,6 +614,11 @@ in mkLicense lset) ({
     spdxId = "HPND-sell-variant";
   };
 
+  hpndUc = {
+    spdxId = "HPND-UC";
+    fullName = "Historical Permission Notice and Disclaimer - University of California variant";
+  };
+
   # Intel's license, seems free
   iasl = {
     spdxId = "Intel-ACPI";
@@ -894,6 +904,11 @@ in mkLicense lset) ({
     url = "https://raw.githubusercontent.com/netdata/netdata/master/web/gui/v2/LICENSE.md";
   };
 
+  nistSoftware = {
+    spdxId = "NIST-Software";
+    fullName = "NIST Software License";
+  };
+
   nlpl = {
     spdxId = "NLPL";
     fullName = "No Limit Public License";
diff --git a/lib/trivial.nix b/lib/trivial.nix
index c197822a4f8e5..936ad207c03df 100644
--- a/lib/trivial.nix
+++ b/lib/trivial.nix
@@ -16,59 +16,114 @@ in {
 
   ## Simple (higher order) functions
 
-  /* The identity function
-     For when you need a function that does “nothing”.
+  /**
+    The identity function
+    For when you need a function that does “nothing”.
 
-     Type: id :: a -> a
+
+    # Inputs
+
+    `x`
+
+    : The value to return
+
+    # Type
+
+    ```
+    id :: a -> a
+    ```
   */
-  id =
-    # The value to return
-    x: x;
+  id = x: x;
+
+  /**
+    The constant function
+
+    Ignores the second argument. If called with only one argument,
+    constructs a function that always returns a static value.
+
+
+    # Inputs
+
+    `x`
+
+    : Value to return
+
+    `y`
+
+    : Value to ignore
+
+    # Type
+
+    ```
+    const :: a -> b -> a
+    ```
 
-  /* The constant function
+    # Examples
+    :::{.example}
+    ## `lib.trivial.const` usage example
 
-     Ignores the second argument. If called with only one argument,
-     constructs a function that always returns a static value.
+    ```nix
+    let f = const 5; in f 10
+    => 5
+    ```
 
-     Type: const :: a -> b -> a
-     Example:
-       let f = const 5; in f 10
-       => 5
+    :::
   */
   const =
-    # Value to return
     x:
-    # Value to ignore
     y: x;
 
-  /* Pipes a value through a list of functions, left to right.
+  /**
+    Pipes a value through a list of functions, left to right.
 
-     Type: pipe :: a -> [<functions>] -> <return type of last function>
-     Example:
-       pipe 2 [
-         (x: x + 2)  # 2 + 2 = 4
-         (x: x * 2)  # 4 * 2 = 8
-       ]
-       => 8
+    # Inputs
 
-       # ideal to do text transformations
-       pipe [ "a/b" "a/c" ] [
+    `value`
 
-         # create the cp command
-         (map (file: ''cp "${src}/${file}" $out\n''))
+    : Value to start piping.
 
-         # concatenate all commands into one string
-         lib.concatStrings
+    `fns`
 
-         # make that string into a nix derivation
-         (pkgs.runCommand "copy-to-out" {})
+    : List of functions to apply sequentially.
 
-       ]
-       => <drv which copies all files to $out>
+    # Type
 
-     The output type of each function has to be the input type
-     of the next function, and the last function returns the
-     final value.
+    ```
+    pipe :: a -> [<functions>] -> <return type of last function>
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.pipe` usage example
+
+    ```nix
+    pipe 2 [
+        (x: x + 2)  # 2 + 2 = 4
+        (x: x * 2)  # 4 * 2 = 8
+      ]
+    => 8
+
+    # ideal to do text transformations
+    pipe [ "a/b" "a/c" ] [
+
+      # create the cp command
+      (map (file: ''cp "${src}/${file}" $out\n''))
+
+      # concatenate all commands into one string
+      lib.concatStrings
+
+      # make that string into a nix derivation
+      (pkgs.runCommand "copy-to-out" {})
+
+    ]
+    => <drv which copies all files to $out>
+
+    The output type of each function has to be the input type
+    of the next function, and the last function returns the
+    final value.
+    ```
+
+    :::
   */
   pipe = builtins.foldl' (x: f: f x);
 
@@ -79,71 +134,197 @@ in {
 
   ## Named versions corresponding to some builtin operators.
 
-  /* Concatenate two lists
+  /**
+    Concatenate two lists
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
+
+    : 2\. Function argument
 
-     Type: concat :: [a] -> [a] -> [a]
+    # Type
 
-     Example:
-       concat [ 1 2 ] [ 3 4 ]
-       => [ 1 2 3 4 ]
+    ```
+    concat :: [a] -> [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.concat` usage example
+
+    ```nix
+    concat [ 1 2 ] [ 3 4 ]
+    => [ 1 2 3 4 ]
+    ```
+
+    :::
   */
   concat = x: y: x ++ y;
 
-  /* boolean “or” */
+  /**
+    boolean “or”
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
+
+    : 2\. Function argument
+  */
   or = x: y: x || y;
 
-  /* boolean “and” */
+  /**
+    boolean “and”
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
+
+    : 2\. Function argument
+  */
   and = x: y: x && y;
 
-  /* bitwise “not” */
+  /**
+    bitwise “not”
+  */
   bitNot = builtins.sub (-1);
 
-  /* Convert a boolean to a string.
+  /**
+    Convert a boolean to a string.
+
+    This function uses the strings "true" and "false" to represent
+    boolean values. Calling `toString` on a bool instead returns "1"
+    and "" (sic!).
+
+
+    # Inputs
+
+    `b`
+
+    : 1\. Function argument
 
-     This function uses the strings "true" and "false" to represent
-     boolean values. Calling `toString` on a bool instead returns "1"
-     and "" (sic!).
+    # Type
 
-     Type: boolToString :: bool -> string
+    ```
+    boolToString :: bool -> string
+    ```
   */
   boolToString = b: if b then "true" else "false";
 
-  /* Merge two attribute sets shallowly, right side trumps left
+  /**
+    Merge two attribute sets shallowly, right side trumps left
+
+    mergeAttrs :: attrs -> attrs -> attrs
+
+
+    # Inputs
+
+    `x`
+
+    : Left attribute set
+
+    `y`
+
+    : Right attribute set (higher precedence for equal keys)
 
-     mergeAttrs :: attrs -> attrs -> attrs
 
-     Example:
-       mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
-       => { a = 1; b = 3; c = 4; }
+    # Examples
+    :::{.example}
+    ## `lib.trivial.mergeAttrs` usage example
+
+    ```nix
+    mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
+    => { a = 1; b = 3; c = 4; }
+    ```
+
+    :::
   */
   mergeAttrs =
-    # Left attribute set
     x:
-    # Right attribute set (higher precedence for equal keys)
     y: x // y;
 
-  /* Flip the order of the arguments of a binary function.
+  /**
+    Flip the order of the arguments of a binary function.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
+
+    `a`
+
+    : 2\. Function argument
 
-     Type: flip :: (a -> b -> c) -> (b -> a -> c)
+    `b`
 
-     Example:
-       flip concat [1] [2]
-       => [ 2 1 ]
+    : 3\. Function argument
+
+    # Type
+
+    ```
+    flip :: (a -> b -> c) -> (b -> a -> c)
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.flip` usage example
+
+    ```nix
+    flip concat [1] [2]
+    => [ 2 1 ]
+    ```
+
+    :::
   */
   flip = f: a: b: f b a;
 
-  /* Apply function if the supplied argument is non-null.
+  /**
+    Apply function if the supplied argument is non-null.
+
+
+    # Inputs
 
-     Example:
-       mapNullable (x: x+1) null
-       => null
-       mapNullable (x: x+1) 22
-       => 23
+    `f`
+
+    : Function to call
+
+    `a`
+
+    : Argument to check for null before passing it to `f`
+
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.mapNullable` usage example
+
+    ```nix
+    mapNullable (x: x+1) null
+    => null
+    mapNullable (x: x+1) 22
+    => 23
+    ```
+
+    :::
   */
   mapNullable =
-    # Function to call
     f:
-    # Argument to check for null before passing it to `f`
     a: if a == null then a else f a;
 
   # Pull in some builtins not included elsewhere.
@@ -155,57 +336,84 @@ in {
 
   ## nixpkgs version strings
 
-  /* Returns the current full nixpkgs version number. */
+  /**
+    Returns the current full nixpkgs version number.
+  */
   version = release + versionSuffix;
 
-  /* Returns the current nixpkgs release number as string. */
+  /**
+    Returns the current nixpkgs release number as string.
+  */
   release = lib.strings.fileContents ./.version;
 
-  /* The latest release that is supported, at the time of release branch-off,
-     if applicable.
+  /**
+    The latest release that is supported, at the time of release branch-off,
+    if applicable.
 
-     Ideally, out-of-tree modules should be able to evaluate cleanly with all
-     supported Nixpkgs versions (master, release and old release until EOL).
-     So if possible, deprecation warnings should take effect only when all
-     out-of-tree expressions/libs/modules can upgrade to the new way without
-     losing support for supported Nixpkgs versions.
+    Ideally, out-of-tree modules should be able to evaluate cleanly with all
+    supported Nixpkgs versions (master, release and old release until EOL).
+    So if possible, deprecation warnings should take effect only when all
+    out-of-tree expressions/libs/modules can upgrade to the new way without
+    losing support for supported Nixpkgs versions.
 
-     This release number allows deprecation warnings to be implemented such that
-     they take effect as soon as the oldest release reaches end of life. */
+    This release number allows deprecation warnings to be implemented such that
+    they take effect as soon as the oldest release reaches end of life.
+  */
   oldestSupportedRelease =
     # Update on master only. Do not backport.
     2311;
 
-  /* Whether a feature is supported in all supported releases (at the time of
-     release branch-off, if applicable). See `oldestSupportedRelease`. */
+  /**
+    Whether a feature is supported in all supported releases (at the time of
+    release branch-off, if applicable). See `oldestSupportedRelease`.
+
+
+    # Inputs
+
+    `release`
+
+    : Release number of feature introduction as an integer, e.g. 2111 for 21.11.
+    Set it to the upcoming release, matching the nixpkgs/.version file.
+  */
   isInOldestRelease =
-    /* Release number of feature introduction as an integer, e.g. 2111 for 21.11.
-       Set it to the upcoming release, matching the nixpkgs/.version file.
-    */
     release:
       release <= lib.trivial.oldestSupportedRelease;
 
-  /* Returns the current nixpkgs release code name.
+  /**
+    Returns the current nixpkgs release code name.
 
-     On each release the first letter is bumped and a new animal is chosen
-     starting with that new letter.
+    On each release the first letter is bumped and a new animal is chosen
+    starting with that new letter.
   */
   codeName = "Uakari";
 
-  /* Returns the current nixpkgs version suffix as string. */
+  /**
+    Returns the current nixpkgs version suffix as string.
+  */
   versionSuffix =
     let suffixFile = ../.version-suffix;
     in if pathExists suffixFile
     then lib.strings.fileContents suffixFile
     else "pre-git";
 
-  /* Attempts to return the the current revision of nixpkgs and
-     returns the supplied default value otherwise.
+  /**
+    Attempts to return the the current revision of nixpkgs and
+    returns the supplied default value otherwise.
+
+
+    # Inputs
+
+    `default`
 
-     Type: revisionWithDefault :: string -> string
+    : Default value to return if revision can not be determined
+
+    # Type
+
+    ```
+    revisionWithDefault :: string -> string
+    ```
   */
   revisionWithDefault =
-    # Default value to return if revision can not be determined
     default:
     let
       revisionFile = "${toString ./..}/.git-revision";
@@ -217,47 +425,115 @@ in {
 
   nixpkgsVersion = warn "lib.nixpkgsVersion is a deprecated alias of lib.version." version;
 
-  /* Determine whether the function is being called from inside a Nix
-     shell.
+  /**
+    Determine whether the function is being called from inside a Nix
+    shell.
 
-     Type: inNixShell :: bool
+    # Type
+
+    ```
+    inNixShell :: bool
+    ```
   */
   inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
 
-  /* Determine whether the function is being called from inside pure-eval mode
-     by seeing whether `builtins` contains `currentSystem`. If not, we must be in
-     pure-eval mode.
+  /**
+    Determine whether the function is being called from inside pure-eval mode
+    by seeing whether `builtins` contains `currentSystem`. If not, we must be in
+    pure-eval mode.
+
+    # Type
 
-     Type: inPureEvalMode :: bool
+    ```
+    inPureEvalMode :: bool
+    ```
   */
   inPureEvalMode = ! builtins ? currentSystem;
 
   ## Integer operations
 
-  /* Return minimum of two numbers. */
+  /**
+    Return minimum of two numbers.
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
+
+    : 2\. Function argument
+  */
   min = x: y: if x < y then x else y;
 
-  /* Return maximum of two numbers. */
+  /**
+    Return maximum of two numbers.
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
+
+    : 2\. Function argument
+  */
   max = x: y: if x > y then x else y;
 
-  /* Integer modulus
+  /**
+    Integer modulus
+
+
+    # Inputs
+
+    `base`
+
+    : 1\. Function argument
+
+    `int`
+
+    : 2\. Function argument
+
 
-     Example:
-       mod 11 10
-       => 1
-       mod 1 10
-       => 1
+    # Examples
+    :::{.example}
+    ## `lib.trivial.mod` usage example
+
+    ```nix
+    mod 11 10
+    => 1
+    mod 1 10
+    => 1
+    ```
+
+    :::
   */
   mod = base: int: base - (int * (builtins.div base int));
 
 
   ## Comparisons
 
-  /* C-style comparisons
+  /**
+    C-style comparisons
+
+    a < b,  compare a b => -1
+    a == b, compare a b => 0
+    a > b,  compare a b => 1
+
+
+    # Inputs
+
+    `a`
+
+    : 1\. Function argument
+
+    `b`
 
-     a < b,  compare a b => -1
-     a == b, compare a b => 0
-     a > b,  compare a b => 1
+    : 2\. Function argument
   */
   compare = a: b:
     if a < b
@@ -266,50 +542,100 @@ in {
          then 1
          else 0;
 
-  /* Split type into two subtypes by predicate `p`, take all elements
-     of the first subtype to be less than all the elements of the
-     second subtype, compare elements of a single subtype with `yes`
-     and `no` respectively.
+  /**
+    Split type into two subtypes by predicate `p`, take all elements
+    of the first subtype to be less than all the elements of the
+    second subtype, compare elements of a single subtype with `yes`
+    and `no` respectively.
+
+
+    # Inputs
+
+    `p`
+
+    : Predicate
+
+    `yes`
+
+    : Comparison function if predicate holds for both values
+
+    `no`
 
-     Type: (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
+    : Comparison function if predicate holds for neither value
 
-     Example:
-       let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
+    `a`
 
-       cmp "a" "z" => -1
-       cmp "fooa" "fooz" => -1
+    : First value to compare
 
-       cmp "f" "a" => 1
-       cmp "fooa" "a" => -1
-       # while
-       compare "fooa" "a" => 1
+    `b`
+
+    : Second value to compare
+
+    # Type
+
+    ```
+    (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.splitByAndCompare` usage example
+
+    ```nix
+    let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
+
+    cmp "a" "z" => -1
+    cmp "fooa" "fooz" => -1
+
+    cmp "f" "a" => 1
+    cmp "fooa" "a" => -1
+    # while
+    compare "fooa" "a" => 1
+    ```
+
+    :::
   */
   splitByAndCompare =
-    # Predicate
-    p:
-    # Comparison function if predicate holds for both values
-    yes:
-    # Comparison function if predicate holds for neither value
-    no:
-    # First value to compare
-    a:
-    # Second value to compare
-    b:
+    p: yes: no: a: b:
     if p a
     then if p b then yes a b else -1
     else if p b then 1 else no a b;
 
 
-  /* Reads a JSON file.
+  /**
+    Reads a JSON file.
 
-     Type: importJSON :: path -> any
+
+    # Inputs
+
+    `path`
+
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    importJSON :: path -> any
+    ```
   */
   importJSON = path:
     builtins.fromJSON (builtins.readFile path);
 
-  /* Reads a TOML file.
+  /**
+    Reads a TOML file.
+
+
+    # Inputs
 
-     Type: importTOML :: path -> any
+    `path`
+
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    importTOML :: path -> any
+    ```
   */
   importTOML = path:
     builtins.fromTOML (builtins.readFile path);
@@ -329,7 +655,7 @@ in {
   # TODO: figure out a clever way to integrate location information from
   # something like __unsafeGetAttrPos.
 
-  /*
+  /**
     Print a warning before returning the second argument. This function behaves
     like `builtins.trace`, but requires a string message and formats it as a
     warning, including the `warning: ` prefix.
@@ -337,28 +663,80 @@ in {
     To get a call stack trace and abort evaluation, set the environment variable
     `NIX_ABORT_ON_WARN=true` and set the Nix options `--option pure-eval false --show-trace`
 
-    Type: string -> a -> a
+    # Inputs
+
+    `msg`
+
+    : Warning message to print.
+
+    `val`
+
+    : Value to return as-is.
+
+    # Type
+
+    ```
+    string -> a -> a
+    ```
   */
   warn =
     if lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") ["1" "true" "yes"]
     then msg: builtins.trace "warning: ${msg}" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
     else msg: builtins.trace "warning: ${msg}";
 
-  /*
+  /**
     Like warn, but only warn when the first argument is `true`.
 
-    Type: bool -> string -> a -> a
+
+    # Inputs
+
+    `cond`
+
+    : 1\. Function argument
+
+    `msg`
+
+    : 2\. Function argument
+
+    `val`
+
+    : Value to return as-is.
+
+    # Type
+
+    ```
+    bool -> string -> a -> a
+    ```
   */
   warnIf = cond: msg: if cond then warn msg else x: x;
 
-  /*
+  /**
     Like warnIf, but negated (warn if the first argument is `false`).
 
-    Type: bool -> string -> a -> a
+
+    # Inputs
+
+    `cond`
+
+    : 1\. Function argument
+
+    `msg`
+
+    : 2\. Function argument
+
+    `val`
+
+    : Value to return as-is.
+
+    # Type
+
+    ```
+    bool -> string -> a -> a
+    ```
   */
   warnIfNot = cond: msg: if cond then x: x else warn msg;
 
-  /*
+  /**
     Like the `assert b; e` expression, but with a custom error message and
     without the semicolon.
 
@@ -369,33 +747,95 @@ in {
     Calls can be juxtaposed using function application, as `(r: r) a = a`, so
     `(r: r) (r: r) a = a`, and so forth.
 
-    Type: bool -> string -> a -> a
 
-    Example:
+    # Inputs
+
+    `cond`
+
+    : 1\. Function argument
 
-        throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list."
-        lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays
-        pkgs
+    `msg`
 
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    bool -> string -> a -> a
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.throwIfNot` usage example
+
+    ```nix
+    throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list."
+    lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays
+    pkgs
+    ```
+
+    :::
   */
   throwIfNot = cond: msg: if cond then x: x else throw msg;
 
-  /*
+  /**
     Like throwIfNot, but negated (throw if the first argument is `true`).
 
-    Type: bool -> string -> a -> a
+
+    # Inputs
+
+    `cond`
+
+    : 1\. Function argument
+
+    `msg`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    bool -> string -> a -> a
+    ```
   */
   throwIf = cond: msg: if cond then throw msg else x: x;
 
-  /* Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
+  /**
+    Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
+
+
+    # Inputs
+
+    `msg`
 
-     Example:
-       let colorVariants = ["bright" "dark" "black"]
-       in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants;
-       =>
-       error: color variants: bright, black unexpected; valid ones: standard, light, dark
+    : 1\. Function argument
 
-     Type: String -> List ComparableVal -> List ComparableVal -> a -> a
+    `valid`
+
+    : 2\. Function argument
+
+    `given`
+
+    : 3\. Function argument
+
+    # Type
+
+    ```
+    String -> List ComparableVal -> List ComparableVal -> a -> a
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.checkListOfEnum` usage example
+
+    ```nix
+    let colorVariants = ["bright" "dark" "black"]
+    in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants;
+    =>
+    error: color variants: bright, black unexpected; valid ones: standard, light, dark
+    ```
+
+    :::
   */
   checkListOfEnum = msg: valid: given:
     let
@@ -410,15 +850,27 @@ in {
 
   ## Function annotations
 
-  /* Add metadata about expected function arguments to a function.
-     The metadata should match the format given by
-     builtins.functionArgs, i.e. a set from expected argument to a bool
-     representing whether that argument has a default or not.
-     setFunctionArgs : (a → b) → Map String Bool → (a → b)
+  /**
+    Add metadata about expected function arguments to a function.
+    The metadata should match the format given by
+    builtins.functionArgs, i.e. a set from expected argument to a bool
+    representing whether that argument has a default or not.
+    setFunctionArgs : (a → b) → Map String Bool → (a → b)
 
-     This function is necessary because you can't dynamically create a
-     function of the { a, b ? foo, ... }: format, but some facilities
-     like callPackage expect to be able to query expected arguments.
+    This function is necessary because you can't dynamically create a
+    function of the { a, b ? foo, ... }: format, but some facilities
+    like callPackage expect to be able to query expected arguments.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
+
+    `args`
+
+    : 2\. Function argument
   */
   setFunctionArgs = f: args:
     { # TODO: Should we add call-time "type" checking like built in?
@@ -426,84 +878,133 @@ in {
       __functionArgs = args;
     };
 
-  /* Extract the expected function arguments from a function.
-     This works both with nix-native { a, b ? foo, ... }: style
-     functions and functions with args set with 'setFunctionArgs'. It
-     has the same return type and semantics as builtins.functionArgs.
-     setFunctionArgs : (a → b) → Map String Bool.
+  /**
+    Extract the expected function arguments from a function.
+    This works both with nix-native { a, b ? foo, ... }: style
+    functions and functions with args set with 'setFunctionArgs'. It
+    has the same return type and semantics as builtins.functionArgs.
+    setFunctionArgs : (a → b) → Map String Bool.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
   */
   functionArgs = f:
     if f ? __functor
     then f.__functionArgs or (functionArgs (f.__functor f))
     else builtins.functionArgs f;
 
-  /* Check whether something is a function or something
-     annotated with function args.
+  /**
+    Check whether something is a function or something
+    annotated with function args.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
   */
   isFunction = f: builtins.isFunction f ||
     (f ? __functor && isFunction (f.__functor f));
 
-  /*
+  /**
     `mirrorFunctionArgs f g` creates a new function `g'` with the same behavior as `g` (`g' x == g x`)
     but its function arguments mirroring `f` (`lib.functionArgs g' == lib.functionArgs f`).
 
-    Type:
-      mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c)
-
-    Example:
-      addab = {a, b}: a + b
-      addab { a = 2; b = 4; }
-      => 6
-      lib.functionArgs addab
-      => { a = false; b = false; }
-      addab1 = attrs: addab attrs + 1
-      addab1 { a = 2; b = 4; }
-      => 7
-      lib.functionArgs addab1
-      => { }
-      addab1' = lib.mirrorFunctionArgs addab addab1
-      addab1' { a = 2; b = 4; }
-      => 7
-      lib.functionArgs addab1'
-      => { a = false; b = false; }
+
+    # Inputs
+
+    `f`
+
+    : Function to provide the argument metadata
+
+    `g`
+
+    : Function to set the argument metadata to
+
+    # Type
+
+    ```
+    mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c)
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.mirrorFunctionArgs` usage example
+
+    ```nix
+    addab = {a, b}: a + b
+    addab { a = 2; b = 4; }
+    => 6
+    lib.functionArgs addab
+    => { a = false; b = false; }
+    addab1 = attrs: addab attrs + 1
+    addab1 { a = 2; b = 4; }
+    => 7
+    lib.functionArgs addab1
+    => { }
+    addab1' = lib.mirrorFunctionArgs addab addab1
+    addab1' { a = 2; b = 4; }
+    => 7
+    lib.functionArgs addab1'
+    => { a = false; b = false; }
+    ```
+
+    :::
   */
   mirrorFunctionArgs =
-    # Function to provide the argument metadata
     f:
     let
       fArgs = functionArgs f;
     in
-    # Function to set the argument metadata to
     g:
     setFunctionArgs g fArgs;
 
-  /*
+  /**
     Turns any non-callable values into constant functions.
     Returns callable values as is.
 
-    Example:
 
-      nix-repl> lib.toFunction 1 2
-      1
+    # Inputs
+
+    `v`
+
+    : Any value
+
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.toFunction` usage example
+
+    ```nix
+    nix-repl> lib.toFunction 1 2
+    1
 
-      nix-repl> lib.toFunction (x: x + 1) 2
-      3
+    nix-repl> lib.toFunction (x: x + 1) 2
+    3
+    ```
+
+    :::
   */
   toFunction =
-    # Any value
     v:
     if isFunction v
     then v
     else k: v;
 
-  /* Convert the given positive integer to a string of its hexadecimal
-     representation. For example:
+  /**
+    Convert the given positive integer to a string of its hexadecimal
+    representation. For example:
 
-     toHexString 0 => "0"
+    toHexString 0 => "0"
 
-     toHexString 16 => "10"
+    toHexString 16 => "10"
 
-     toHexString 250 => "FA"
+    toHexString 250 => "FA"
   */
   toHexString = let
     hexDigits = {
@@ -520,14 +1021,26 @@ in {
       else hexDigits.${toString d};
   in i: lib.concatMapStrings toHexDigit (toBaseDigits 16 i);
 
-  /* `toBaseDigits base i` converts the positive integer i to a list of its
-     digits in the given base. For example:
+  /**
+    `toBaseDigits base i` converts the positive integer i to a list of its
+    digits in the given base. For example:
+
+    toBaseDigits 10 123 => [ 1 2 3 ]
+
+    toBaseDigits 2 6 => [ 1 1 0 ]
+
+    toBaseDigits 16 250 => [ 15 10 ]
+
+
+    # Inputs
+
+    `base`
 
-     toBaseDigits 10 123 => [ 1 2 3 ]
+    : 1\. Function argument
 
-     toBaseDigits 2 6 => [ 1 1 0 ]
+    `i`
 
-     toBaseDigits 16 250 => [ 15 10 ]
+    : 2\. Function argument
   */
   toBaseDigits = base: i:
     let