blob: 1d3cabe6f1b685a8c173b97d48947d8969dae57f (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
# Operations on attribute sets.
with {
inherit (builtins) head tail;
inherit (import ./default.nix) fold;
inherit (import ./strings.nix) concatStringsSep;
};
rec {
inherit (builtins) attrNames listToAttrs hasAttr isAttrs;
/* Return an attribute from nested attribute sets. For instance
["x" "y"] applied to some set e returns e.x.y, if it exists. The
default value is returned otherwise. */
attrByPath = attrPath: default: e:
let attr = head attrPath;
in
if attrPath == [] then e
else if builtins ? hasAttr && hasAttr attr e
then attrByPath (tail attrPath) default (builtins.getAttr attr e)
else default;
# keep compatibility for some time. will be removed soon (the name getAttr
# should only be used for the builtins primop)
getAttr = a : b : c : builtins.trace "depreceated usage of lib.getAttr!"
(attrByPath a b c);
getAttrFromPath = attrPath: set:
let errorMsg = "cannot find attribute `" + concatStringsSep "." attrPath + "'";
in attrByPath attrPath (abort errorMsg) set;
/* Return the specified attributes from a set.
Example:
attrVals ["a" "b" "c"] as
=> [as.a as.b as.c]
*/
attrVals = nameList: set:
map (x: builtins.getAttr x set) nameList;
/* 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]
*/
attrValues = attrs: attrVals (attrNames attrs) attrs;
/* Collect each attribute named `attr' from a list of attribute
sets. Sets that don't contain the named attribute are ignored.
Example:
catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
=> [1 2]
*/
catAttrs = attr: l: fold (s: l: if hasAttr attr s then [(builtins.getAttr attr s)] ++ l else l) [] l;
/* Utility function that creates a {name, value} pair as expected by
builtins.listToAttrs. */
nameValuePair = name: value: { inherit name value; };
/* Apply a function to each element in an attribute set. The
function takes two arguments --- the attribute name and its value
--- and returns the new value for the attribute. The result is a
new attribute set.
Example:
mapAttrs (name: value: name + "-" + value)
{x = "foo"; y = "bar";}
=> {x = "x-foo"; y = "y-bar";}
*/
mapAttrs = f: set:
listToAttrs (map (attr: nameValuePair attr (f attr (builtins.getAttr attr set))) (attrNames set));
/* Like `mapAttrs', except that it recursively applies itself to
attribute sets. Also, the first argument of the argument
function is a *list* of the names of the containing attributes.
Type:
mapAttrsRecursive ::
([String] -> a -> b) -> AttrSet -> AttrSet
Example:
mapAttrsRecursive (path: value: concatStringsSep "-" (path ++ [value]))
{ n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; }
=> { n = { a = "n-a-A"; m = { b = "n-m-b-B"; c = "n-m-c-C"; }; }; d = "d-D"; }
*/
mapAttrsRecursive = mapAttrsRecursiveCond (as: true);
/* Like `mapAttrsRecursive', but it takes an additional predicate
function that tells it whether to recursive into an attribute
set. If it returns false, `mapAttrsRecursiveCond' does not
recurse, but does apply the map function. It is returns true, it
does recurse, and does not apply the map function.
Type:
mapAttrsRecursiveCond ::
(AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> AttrSet
Example:
# To prevent recursing into derivations (which are attribute
# sets with the attribute "type" equal to "derivation"):
mapAttrsRecursiveCond
(as: !(as ? "type" && as.type == "derivation"))
(x: ... do something ...)
attrs
*/
mapAttrsRecursiveCond = cond: f: set:
let
recurse = path: set:
let
g =
name: value:
if isAttrs value && cond value
then recurse (path ++ [name]) value
else f (path ++ [name]) value;
in mapAttrs g set;
in recurse [] set;
/* Check whether the argument is a derivation. */
isDerivation = x: isAttrs x && x ? type && x.type == "derivation";
}
|