Modular, context-aware and aspect-oriented dendritic Nix configurations. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/
at main 117 lines 2.6 kB view raw
1{ 2 inputs, 3 lib, 4 config, 5 ... 6}: 7let 8 9 # "Just Give 'Em One of These" - Moe Szyslak 10 # A __functor that applies context to parametric includes (functions) 11 funk = 12 apply: aspect: 13 aspect 14 // { 15 __functor = self: ctx: { 16 includes = builtins.filter (x: x != { }) (map (apply ctx) (builtins.filter isFn self.includes)); 17 }; 18 }; 19 20 isFn = f: (builtins.isFunction f) || (builtins.isAttrs f && f ? __functor); 21 canTake = import ./fn-can-take.nix lib; 22 23 # an aspect producing only owned configs 24 owned = (lib.flip builtins.removeAttrs) [ 25 "includes" 26 "__functor" 27 ]; 28 29 # only static includes from an aspect. 30 statics = 31 aspect: 32 aspect 33 // { 34 __functor = 35 self: 36 { class, aspect-chain }: 37 { 38 includes = map (applyStatics { inherit class aspect-chain; }) self.includes; 39 }; 40 }; 41 42 applyStatics = 43 ctx: f: 44 if !isFn f then 45 f 46 else if isStatic f && isCtxStatic ctx then 47 f ctx 48 else 49 { }; 50 51 isStatic = canTake.atLeast { 52 class = ""; 53 aspect-chain = [ ]; 54 }; 55 isCtxStatic = (lib.flip canTake.exactly) ({ class, aspect-chain }: class aspect-chain); 56 57 take.unused = _unused: used: used; 58 take.exactly = take canTake.exactly; 59 take.atLeast = take canTake.atLeast; 60 take.__functor = 61 _: takes: fn: ctx: 62 if takes ctx fn then fn ctx else { }; 63 64 parametric.atLeast = funk (lib.flip take.atLeast); 65 parametric.exactly = funk (lib.flip take.exactly); 66 parametric.expands = 67 attrs: parametric.withOwn (aspect: ctx: parametric.atLeast aspect (ctx // attrs)); 68 parametric.fixedTo = 69 attrs: aspect: 70 aspect 71 // { 72 __functor = 73 self: 74 { class, aspect-chain }: 75 { 76 includes = [ 77 (owned self) 78 (statics self { inherit class aspect-chain; }) 79 (parametric.atLeast self attrs) 80 ]; 81 }; 82 }; 83 parametric.withOwn = 84 functor: aspect: 85 aspect 86 // { 87 __functor = self: ctx: { 88 includes = 89 if isCtxStatic ctx then 90 [ 91 (owned self) 92 (statics self ctx) 93 ] 94 else 95 [ (functor self ctx) ]; 96 }; 97 }; 98 parametric.__functor = _: parametric.withOwn parametric.atLeast; 99 100 aspects = inputs.flake-aspects.lib lib; 101 102 __findFile = import ./den-brackets.nix { inherit lib config; }; 103 104 den-lib = { 105 inherit 106 parametric 107 aspects 108 __findFile 109 statics 110 owned 111 isFn 112 canTake 113 take 114 ; 115 }; 116in 117den-lib