diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/attrsets.nix | 1866 | ||||
-rw-r--r-- | lib/licenses.nix | 15 | ||||
-rw-r--r-- | lib/trivial.nix | 941 |
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 "[1;31mwarning: ${msg}[0m" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.") else msg: builtins.trace "[1;31mwarning: ${msg}[0m"; - /* + /** 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 |