69 lines
2.6 KiB
Nix
69 lines
2.6 KiB
Nix
let
|
|
recursiveSelect =
|
|
selectorIndex: selectorList: target:
|
|
let
|
|
selector = builtins.elemAt selectorList selectorIndex;
|
|
in
|
|
|
|
# selector is empty, we are done
|
|
if selectorIndex + 1 > builtins.length selectorList then
|
|
target
|
|
|
|
else if builtins.isList target then
|
|
# support bla.* for lists and recurse into all elements
|
|
if selector == "*" then
|
|
builtins.map (v: recursiveSelect (selectorIndex + 1) selectorList v) target
|
|
# support bla.3 for lists and recurse into the 4th element
|
|
else if (builtins.match "[[:digit:]]*" selector) == [ ] then
|
|
recursiveSelect (selectorIndex + 1) selectorList (
|
|
builtins.elemAt target (builtins.fromJSON selector)
|
|
)
|
|
else
|
|
throw "only * or a number is allowed in list selector"
|
|
|
|
else if builtins.isAttrs target then
|
|
# handle the case bla.x.*.z where x is an attrset and we recurse into all elements
|
|
if selector == "*" then
|
|
builtins.mapAttrs (_: v: recursiveSelect (selectorIndex + 1) selectorList v) target
|
|
# support bla.{x,y,z}.world where we get world from each of x, y and z
|
|
else if (builtins.match ''^\{([^}]*)}$'' selector) != null then
|
|
let
|
|
attrsAsList = (
|
|
builtins.filter (x: !builtins.isList x) (
|
|
builtins.split "," (builtins.head (builtins.match ''^\{([^}]*)}$'' selector))
|
|
)
|
|
);
|
|
dummyAttrSet = builtins.listToAttrs (
|
|
map (x: {
|
|
name = x;
|
|
value = null;
|
|
}) attrsAsList
|
|
);
|
|
filteredAttrs = builtins.intersectAttrs dummyAttrSet target;
|
|
in
|
|
builtins.mapAttrs (_: v: recursiveSelect (selectorIndex + 1) selectorList v) filteredAttrs
|
|
else
|
|
recursiveSelect (selectorIndex + 1) selectorList (builtins.getAttr selector target)
|
|
else
|
|
throw "Expected a list or an attrset";
|
|
|
|
parseSelector =
|
|
selector:
|
|
let
|
|
splitByQuote = x: builtins.filter (x: !builtins.isList x) (builtins.split ''"'' x);
|
|
splitByDot =
|
|
x:
|
|
builtins.filter (x: x != "") (
|
|
map (builtins.replaceStrings [ "." ] [ "" ]) (
|
|
builtins.filter (x: !builtins.isList x) (builtins.split ''\.'' x)
|
|
)
|
|
);
|
|
handleQuoted =
|
|
x: if x == [ ] then [ ] else [ (builtins.head x) ] ++ handleUnquoted (builtins.tail x);
|
|
handleUnquoted =
|
|
x: if x == [ ] then [ ] else splitByDot (builtins.head x) ++ handleQuoted (builtins.tail x);
|
|
in
|
|
handleUnquoted (splitByQuote selector);
|
|
in
|
|
selector: target: recursiveSelect 0 (parseSelector selector) target
|