Skip to content

Commit

Permalink
feat: add configurable hoistLists transformer
Browse files Browse the repository at this point in the history
  • Loading branch information
blaggacao committed Apr 10, 2023
1 parent 6f4e01a commit ace585d
Showing 1 changed file with 85 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/transformers/hoistLists.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{ lib }: from: to:

# Example from / to
# - Lifting `imports` from: _imports, to: imports
# - Lifting `options` from: _api, to: options
#
# Note: underscore used as mere convention to
# signalling to the user the "private"
# nature, they won't be part of the final
# view presented to the user

let
inherit (lib)
catAttrs
flip
pipe
mapAttrs
attrValues
foldl'
flatten
;

/*mergeAttrsButConcatOn: merge attributes shallowly, but
concat values of a specific key into a list in that key
Type:
(key :: String -> AttrSet -> AttrSet) -> { ${key} :: List; ... }
*/
mergeAttrsButConcatOn = key: x: y:
x // y // {
${key} = flatten (catAttrs key [ x y ]);
};

/*concatMapAttrsWith: map each attribute in the given set into
a list of attributes and subsequently merge them into
a new attribute set with the specified mergeFun.
Type:
concatMapAttrsWith :: (AttrSet -> AttrSet -> AttrSet) -> (String -> a -> AttrSet)
-> AttrSet -> AttrSet
Example:
concatMapAttrsWith (mergeAttrsButConcatOn "mykey")
(name: value: {
${name} = value;
${key} = value ++ value;
})
{ x = "a"; y = "b"; }
=> { x = "a"; y = "b"; mykey = [ "aa" "bb"]; }
*/
concatMapAttrsWith = mergeFun: f: flip pipe [ (mapAttrs f) attrValues (foldl' mergeFun { }) ];

in
cursor: mod:
if cursor == [ ] # toplevel
then
concatMapAttrsWith (mergeAttrsButConcatOn to)
(file: value:
# to may be already lifted from a previous transformer (e.g. from default.nix)
if file == to then { ${file} = value; }
else if value ? ${from}
then {
${file} = if value ? ${from} then removeAttrs value [ from ] else value;
${to} = value.${from} or null;
}
else {
${file} = if value ? ${from} then removeAttrs value [ from ] else value;
})
mod
else
concatMapAttrsWith (mergeAttrsButConcatOn from)
(file: value:
# from may be already lifted from a previous transformer (e.g. from default.nix)
if file == from then { ${file} = value; }
else if value ? ${from}
then {
${file} = if value ? ${from} then removeAttrs value [ from ] else value;
${from} = value.${from} or null;
}
else {
${file} = if value ? ${from} then removeAttrs value [ from ] else value;
})
mod

0 comments on commit ace585d

Please sign in to comment.