···11MIT License
2233-Copyright (c) 2023 siluam
33+Copyright (c) 2023 simple
4455Permission is hereby granted, free of charge, to any person obtaining a copy
66of this software and associated documentation files (the "Software"), to deal
+22-21
README.md
···11-# siluam
11+# simple
22+33+This allows users to import flakes using `import <path to flake>`,
44+or import them using a local fork of `simple` using `import <path to flake> <path to local fork>`
55+or `import <path to local fork> <path to flake>`.
2637```nix
48let
55- siluam = ssrc:
66- import (let
77- lock = if (builtins.pathExists ./flake.lock) then
88- (builtins.fromJSON (builtins.readFile ./flake.lock))
99- else
1010- { };
1111- locked = lock.nodes.siluam.locked or { rev = "main"; };
1212- url = locked.url or "https://github.com/siluam/siluam/archive/${
1313- locked.rev or "main"
1414- }.tar.gz";
1515- in if ((ssrc != ./.) && (builtins.pathExists ssrc)) then
1616- ssrc
1717- else if (builtins ? getFlake) then
1818- (builtins.getFlake url)
1919- else
2020- (fetchTarball {
2121- inherit url;
2222- ${if (locked ? narHash) then "sha256" else null} = locked.narHash;
2323- }));
2424-in (siluam ./. ./.) // { __functor = self: ssrc: siluam ssrc ./.; }
99+ nodes = if (builtins.pathExists ./flake.lock) then
1010+ (builtins.fromJSON (builtins.readFile ./flake.lock))
1111+ else {
1212+ root.inputs.simple = "simple";
1313+ simple.locked.rev = "main";
1414+ };
1515+ inherit (nodes.${nodes.root.inputs.simple}) locked;
1616+ url =
1717+ locked.url or "https://tangled.org/@syvl.org/simple/archive/${locked.rev}";
1818+ simple = if (builtins ? getFlake) then
1919+ (builtins.getFlake url)
2020+ else
2121+ (import (fetchTarball {
2222+ inherit url;
2323+ ${if (locked ? narHash) then "sha256" else null} = locked.narHash;
2424+ }));
2525+in (builtins.getFlake or simple) (toString ./.)
2526```
···11-rec {
22- inherit (builtins) trace;
33- traceVal = value: trace value value;
44- traceValSeq = value: trace (builtins.deepSeq value value) value;
55-66- optionalAttrs = cond: attrs: if cond then attrs else { };
77- optionalString = cond: string: if cond then string else "";
88-99- stringToCharacters = s:
1010- builtins.genList (p: builtins.substring p 1 s) (builtins.stringLength s);
1111- lowerChars = stringToCharacters "abcdefghijklmnopqrstuvwxyz";
1212- upperChars = stringToCharacters "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1313- toLower = builtins.replaceStrings upperChars lowerChars;
1414- toUpper = builtins.replaceStrings lowerChars upperChars;
1515-1616- # Taken From: https://github.com/NixOS/nixpkgs/blob/master/lib/attrsets.nix#L747C1-L762C56
1717- /* Generate an attribute set by mapping a function over a list of
1818- attribute names.
1919-2020- Example:
2121- genAttrs [ "foo" "bar" ] (name: "x_" + name)
2222- => { foo = "x_foo"; bar = "x_bar"; }
2323-2424- Type:
2525- genAttrs :: [ String ] -> (String -> Any) -> AttrSet
2626- */
2727- genAttrs =
2828- # Names of values in the resulting attribute set.
2929- names:
3030- # A function, given the name of the attribute, returns the attribute's value.
3131- f:
3232- builtins.listToAttrs (map (name: {
3333- inherit name;
3434- value = f name;
3535- }) names);
3636-3737- # Taken From: https://github.com/NixOS/nixpkgs/blob/master/lib/lists.nix#L856C1-L864C73
3838- /* Remove duplicate elements from the list. O(n^2) complexity.
3939-4040- Type: unique :: [a] -> [a]
4141-4242- Example:
4343- unique [ 3 2 3 4 ]
4444- => [ 3 2 4 ]
4545- */
4646- unique =
4747- builtins.foldl' (acc: e: if builtins.elem e acc then acc else acc ++ [ e ])
4848- [ ];
4949-5050- # Taken From: https://github.com/NixOS/nixpkgs/blob/master/lib/lists.nix#L866C1-L876C59
5151- /* Check if list contains only unique elements. O(n^2) complexity.
5252-5353- Type: allUnique :: [a] -> bool
5454-5555- Example:
5656- allUnique [ 3 2 3 4 ]
5757- => false
5858- allUnique [ 3 2 4 1 ]
5959- => true
6060- */
6161- allUnique = list: (builtins.length (unique list) == builtins.length list);
6262-6363- # Taken From: https://github.com/NixOS/nixpkgs/blob/master/lib/strings.nix#L259C1-L284C53
6464- /* Determine whether a string has given prefix.
6565-6666- Type: hasPrefix :: string -> string -> bool
6767-6868- Example:
6969- hasPrefix "foo" "foobar"
7070- => true
7171- hasPrefix "foo" "barfoo"
7272- => false
7373- */
7474- hasPrefix =
7575- # Prefix to check for
7676- pref:
7777- # Input string
7878- str:
7979- # Before 23.05, paths would be copied to the store before converting them
8080- # to strings and comparing. This was surprising and confusing.
8181- if (builtins.isPath pref) then
8282- abort ''
8383- lib.strings.hasPrefix: The first argument (${
8484- toString pref
8585- }) is a path value, but only strings are supported.
8686- There is almost certainly a bug in the calling code, since this function always returns `false` in such a case.
8787- This function also copies the path to the Nix store, which may not be what you want.
8888- This behavior is deprecated.
8989- You might want to use `lib.path.hasPrefix` instead, which correctly supports paths.''
9090- else
9191- (builtins.substring 0 (builtins.stringLength pref) str == pref);
9292-9393- # Taken From: https://github.com/NixOS/nixpkgs/blob/master/lib/attrsets.nix#L616C1-L633C66
9494- /* Like `mapAttrs`, but allows the name of each attribute to be
9595- changed in addition to the value. The applied function should
9696- return both the new name and value as a `nameValuePair`.
9797-9898- Example:
9999- mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
100100- { x = "a"; y = "b"; }
101101- => { foo_x = "bar-a"; foo_y = "bar-b"; }
102102-103103- Type:
104104- mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
105105- */
106106- mapAttrs' =
107107- # A function, given an attribute's name and value, returns a new `nameValuePair`.
108108- f:
109109- # Attribute set to map over.
110110- set:
111111- builtins.listToAttrs
112112- (map (attr: f attr set.${attr}) (builtins.attrNames set));
113113-114114- mapAttrNames = f:
115115- mapAttrs' (name: value: {
116116- name = f name value;
117117- inherit value;
118118- });
119119-120120- # Taken From: https://github.com/NixOS/nixpkgs/blob/master/lib/attrsets.nix#L636C1-L653C56
121121- /* Call a function for each attribute in the given set and return
122122- the result in a list.
123123-124124- Example:
125125- mapAttrsToList (name: value: name + value)
126126- { x = "a"; y = "b"; }
127127- => [ "xa" "yb" ]
128128-129129- Type:
130130- mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
131131- */
132132- mapAttrsToList =
133133- # A function, given an attribute's name and value, returns a new value.
134134- f:
135135- # Attribute set to map over.
136136- attrs:
137137- map (name: f name attrs.${name}) (builtins.attrNames attrs);
138138-139139- # Taken From: https://github.com/NixOS/nixpkgs/blob/master/lib/attrsets.nix#L765C1-L780C47
140140- /* Check whether the argument is a derivation. Any set with
141141- `{ type = "derivation"; }` counts as a derivation.
142142-143143- Example:
144144- nixpkgs = import <nixpkgs> {}
145145- isDerivation nixpkgs.ruby
146146- => true
147147- isDerivation "foobar"
148148- => false
149149-150150- Type:
151151- isDerivation :: Any -> Bool
152152- */
153153- isDerivation =
154154- # Value to check.
155155- value:
156156- value.type or null == "derivation";
157157-158158- isAttrsOnly = value: (builtins.isAttrs value) && (!(isDerivation value));
159159-160160- processInputs = inputs:
161161- builtins.mapAttrs (n: sourceInfo: rec {
162162- inherit sourceInfo;
163163- inherit (sourceInfo) outPath;
164164- _type = toLower (sourceInfo.repository.type or sourceInfo.type);
165165- inputs = { };
166166- outputs = { };
167167- lastModified = 0;
168168- lastModifiedDate = "";
169169- rev = sourceInfo.revision or sourceInfo.rev;
170170- shortRev = builtins.substring 0 7 rev;
171171- }) inputs;
172172-173173- mkOutPath = args@{ src, owner ? "", repo ? "", rev ? "master", ... }:
174174- let
175175- name = args.name or repo;
176176- flakeLock = let path = src + "/flake.lock";
177177- in optionalAttrs (builtins.pathExists path)
178178- (builtins.fromJSON (builtins.readFile path));
179179- nivLock = let path = src + "/nix/sources.nix";
180180- in optionalAttrs (builtins.pathExists path) (import path);
181181- npinsLock = let path = src + "/npins";
182182- in optionalAttrs (builtins.pathExists path) (import path);
183183- lock = flakeLock.nodes.${name}.locked or { inherit rev; };
184184- in if (name != "") then
185185- (nivLock.${name} or npinsLock.${name} or {
186186- outPath = if ((owner != "") && (repo != "")) then
187187- (fetchTarball {
188188- url =
189189- lock.url or "https://github.com/${owner}/${repo}/archive/${lock.rev}.tar.gz";
190190- ${if (lock ? narHash) then "sha256" else null} = lock.narHash;
191191- })
192192- else
193193- src;
194194- }).outPath
195195- else
196196- src;
197197-198198- mkFlake = args@{ src, shell ? false, ... }:
199199- let
200200- srcString = toString src;
201201- flake = if (builtins ? getFlake) then
202202- (builtins.getFlake srcString)
203203- else
204204- (let
205205- flake-compat = args.flake-compat or (import (mkOutPath {
206206- inherit src;
207207- owner = "edolstra";
208208- repo = "flake-compat";
209209- }) src);
210210- outPath = let path = mkOutPath args;
211211- in if (srcString == (toString path)) then
212212- src
213213- else
214214- (builtins.unsafeDiscardStringContext path);
215215- in flake-compat { src = outPath; }).${
216216- if shell then "shellNix" else "defaultNix"
217217- };
218218- in flake // {
219219- inputs = mkInputs {
220220- inherit src;
221221- inherit (flake) inputs;
222222- };
223223- };
224224-225225- # TODO: Remove the tryEval from here
226226- # recursiveUpdateAll' = delim: a: b:
227227- # let a-names = attrNames a;
228228- # in (mapAttrs (n: v:
229229- # let e = tryEval v;
230230- # in if (e.success && (isAttrsOnly v)) then
231231- # (if (any (attr:
232232- # let g = tryEval attr;
233233- # in g.success
234234- # && ((isAttrsOnly attr) || (isList attr) || (isString attr)))
235235- # (attrValues v)) then
236236- # (recursiveUpdateAll' delim v (b.${n} or { }))
237237- # else
238238- # (v // (b.${n} or { })))
239239- # else if (isList v) then
240240- # (v ++ (b.${n} or [ ]))
241241- # else if ((delim != null) && (isString v)) then
242242- # (if (hasAttr n b) then (v + delim + b.${n}) else v)
243243- # else
244244- # (b.${n} or v)) a) // (removeAttrs b a-names);
245245- recursiveUpdateAll' = delim: a: b:
246246- let a-names = builtins.attrNames a;
247247- in (builtins.mapAttrs (n: v:
248248-249249- # TODO: Is this `tryEval' necessary?
250250- let e = builtins.tryEval v;
251251- in if (e.success && (builtins.any (x: x) [ (isAttrsOnly v) ])) then
252252-253253- # TODO: Need this to merge mkShells
254254- # in if (e.success && ((isAttrsOnly v) || (v ? shellHook))) then
255255-256256- # (if (any (attr: (isAttrs attr) || (isList attr) || (isString attr))
257257- # (attrValues v)) then
258258- # (recursiveUpdateAll' delim v (b.${n} or { }))
259259- # else
260260- # (v // (b.${n} or { })))
261261- (recursiveUpdateAll' delim v (b.${n} or { }))
262262- else if (e.success && (isDerivation v)
263263- && (b.${n}.__append__ or false)) then
264264- (recursiveUpdateAll' delim v (removeAttrs b.${n} [ "__append__" ]))
265265- else if (builtins.isList v) then
266266- (v ++ (b.${n} or [ ]))
267267- else if ((delim != null) && (builtins.isString v)) then
268268- (if (builtins.hasAttr n b) then (v + delim + b.${n}) else v)
269269- else
270270- (b.${n} or (if (n == "overridePythonAttrs") then "" else v))) a)
271271- // (removeAttrs b a-names);
272272- recursiveUpdateAll = recursiveUpdateAll' null;
273273-274274- mkInputs =
275275- args@{ src, inputs ? { }, niv ? true, npins ? true, overrides ? { }, ... }:
276276- let
277277- mkFlakes = default: manager:
278278- let
279279- managerIsString = builtins.isString manager;
280280- bool = managerIsString || ((builtins.isBool manager) && manager);
281281- path =
282282- optionalString bool (if managerIsString then manager else default);
283283- rootPath = src + "/${path}";
284284- in optionalAttrs (bool && (builtins.pathExists rootPath))
285285- (builtins.mapAttrs (name: v:
286286- let
287287- outPath = if (hasPrefix "/" v.outPath) then
288288- (builtins.unsafeDiscardStringContext v.outPath)
289289- else
290290- (src + "/${v.outPath}");
291291- flakePath = outPath + "/flake.nix";
292292- in if (builtins.pathExists flakePath) then
293293- (mkFlake {
294294- inherit name;
295295- src = outPath;
296296- owner = v.repository.owner or v.owner;
297297- repo = v.repository.repo or v.repo;
298298- inherit (v) rev;
299299- })
300300- else
301301- (processInputs v)) (import rootPath));
302302- in builtins.foldl' (a: b: a // b) inputs (mapAttrsToList mkFlakes {
303303- "nix/sources.nix" = niv;
304304- npins = npins;
305305- });
306306-}
+201
lib/default.nix
···11+inheritance@{ system, ... }:
22+final: prev:
33+with final;
44+let
55+ silicon = rec {
66+ _name = "syvl";
77+ isAttrsOnly = value: (builtins.isAttrs value) && (!(isDerivation value));
88+99+ # TODO: Remove the tryEval from here
1010+ # recursiveUpdateAll' = delim: a: b:
1111+ # let a-names = attrNames a;
1212+ # in (mapAttrs (n: v:
1313+ # let e = tryEval v;
1414+ # in if (e.success && (isAttrsOnly v)) then
1515+ # (if (any (attr:
1616+ # let g = tryEval attr;
1717+ # in g.success
1818+ # && ((isAttrsOnly attr) || (isList attr) || (isString attr)))
1919+ # (attrValues v)) then
2020+ # (recursiveUpdateAll' delim v (b.${n} or { }))
2121+ # else
2222+ # (v // (b.${n} or { })))
2323+ # else if (isList v) then
2424+ # (v ++ (b.${n} or [ ]))
2525+ # else if ((delim != null) && (isString v)) then
2626+ # (if (hasAttr n b) then (v + delim + b.${n}) else v)
2727+ # else
2828+ # (b.${n} or v)) a) // (builtins.removeAttrs b a-names);
2929+ recursiveUpdateAll' = delim: a: b:
3030+ let a-names = builtins.attrNames a;
3131+ in (builtins.mapAttrs (n: v:
3232+3333+ # TODO: Is this `tryEval' necessary?
3434+ let e = builtins.tryEval v;
3535+ in if (e.success && (builtins.any (x: x) [ (isAttrsOnly v) ])) then
3636+3737+ # TODO: Need this to merge mkShells
3838+ # in if (e.success && ((isAttrsOnly v) || (v ? shellHook))) then
3939+4040+ # (if (any (attr: (isAttrs attr) || (isList attr) || (isString attr))
4141+ # (attrValues v)) then
4242+ # (recursiveUpdateAll' delim v (b.${n} or { }))
4343+ # else
4444+ # (v // (b.${n} or { })))
4545+ (recursiveUpdateAll' delim v (b.${n} or { }))
4646+ else if (e.success && (isDerivation v)
4747+ && (b.${n}.__append__ or false)) then
4848+ (recursiveUpdateAll' delim v
4949+ (builtins.removeAttrs b.${n} [ "__append__" ]))
5050+ else if (builtins.isList v) then
5151+ (v ++ (b.${n} or [ ]))
5252+ else if ((delim != null) && (builtins.isString v)) then
5353+ (if (builtins.hasAttr n b) then (v + delim + b.${n}) else v)
5454+ else
5555+ (b.${n} or (if (n == "overridePythonAttrs") then "" else v))) a)
5656+ // (builtins.removeAttrs b a-names);
5757+ recursiveUpdateAll = recursiveUpdateAll' null;
5858+5959+ # Adapted From: https://github.com/NixOS/nixpkgs/blob/master/lib/fixed-points.nix#L40
6060+ mergeExtends = f: rattrs: self:
6161+ let super = rattrs self;
6262+ in (recursiveUpdateAll super (f self super));
6363+6464+ # Adapted From: https://github.com/NixOS/nixpkgs/blob/master/lib/fixed-points.nix#L107
6565+ mkMergeExtensibleWithCustomName = extenderName: rattrs:
6666+ fix' (self:
6767+ (rattrs self) // {
6868+ ${extenderName} = f:
6969+ mkMergeExtensibleWithCustomName extenderName
7070+ (mergeExtends f rattrs);
7171+ });
7272+7373+ # Adapted From: https://github.com/NixOS/nixpkgs/blob/master/lib/fixed-points.nix#L89
7474+ mkMergeExtensible = mkMergeExtensibleWithCustomName "extend";
7575+7676+ tracer = items: compose (map (item: builtins.trace item) items);
7777+ deepSeqVal = value: builtins.deepSeq value value;
7878+7979+ import = {
8080+ can = f:
8181+ let fString = toString f;
8282+ in ((isString f) || (isPath f)) && ((hasSuffix ".nix" fString)
8383+ || ((builtins.readDir fString) ? "default.nix"));
8484+ should = f:
8585+ let
8686+ should_import = silicon.import.can f;
8787+ should_return = builtins.isAttrs f || builtins.isFunction f;
8888+ in {
8989+ success = should_import || should_return;
9090+ value = if should_import then
9191+ (builtins.import f)
9292+ else if should_return then
9393+ f
9494+ else
9595+ false;
9696+ };
9797+ # TODO: Use an args set of includes and ignores
9898+ all = rec {
9999+ named = _dir:
100100+ { ignores ? "default", recurse ? false }:
101101+ let
102102+ dir = toString _dir;
103103+ removeNix = removeSuffix ".nix";
104104+ in if (builtins.pathExists dir) then
105105+ (if recurse then
106106+ (builtins.listToAttrs (map (file:
107107+ nameValuePair (builtins.baseNameOf (removeNix file))
108108+ (builtins.import file)) filesystem.listFilesRecursive))
109109+ else
110110+ (pipe dir [
111111+ builtins.readDir
112112+ (filterAttrs (n: v:
113113+ (!(elem (removeNix n) (toList ignores)))
114114+ && (!(hasPrefix "_" n)) && (let isDir = v == "directory";
115115+ in (isDir
116116+ && ((builtins.readDir "${dir}/${n}") ? "default.nix"))
117117+ || (!isDir))))
118118+ (mapAttrs' (n: v:
119119+ nameValuePair (removeNix n) (builtins.import "${dir}/${n}")))
120120+ ]))
121121+ else
122122+ { };
123123+ __functor = self: _dir: ignores:
124124+ builtins.attrValues (named _dir ignores);
125125+ };
126126+ };
127127+128128+ intersectArgs = f: with builtins; intersectAttrs (functionArgs f);
129129+130130+ callFunction = f: args: f (intersectArgs f args);
131131+ callFunction' = f: args: functionArgs: f (intersectAttrs functionArgs args);
132132+133133+ compose = flip pipe;
134134+135135+ callLib = final: prev: self: super: inheritance: file:
136136+ let
137137+ args = {
138138+ inherit final prev;
139139+ self = final.syvl;
140140+ super = prev.syvl;
141141+ lib = final;
142142+ inherit (final) syvl;
143143+ inherit silicon;
144144+ } // inheritance;
145145+ ifile = builtins.import file;
146146+ in if (isAttrs file) then
147147+ file
148148+ else if (isFunction file) then
149149+ (callFunction file args)
150150+ else if (isAttrs ifile) then
151151+ ifile
152152+ else
153153+ (callFunction ifile args);
154154+155155+ mks = {
156156+ call = final: prev: self: super: inheritance: f:
157157+ let
158158+ apply = callLib final prev self super inheritance;
159159+ e = silicon.import.should f;
160160+ in if e.success then
161161+ (apply e.value)
162162+ else if (isList f) then
163163+ (map apply f)
164164+ else
165165+ (map apply (silicon.import.all f { }));
166166+167167+ extend = name: final: prev: inheritance: f:
168168+ let
169169+ update = silicon: self: super:
170170+ let extension = mks.call final prev self super inheritance f;
171171+ in if (isAttrs extension) then
172172+ (recursiveUpdateAll silicon extension)
173173+ else
174174+ (foldl' recursiveUpdateAll silicon extension);
175175+ in if (hasAttr name prev) then
176176+ (prev.${name}.extend (update { }))
177177+ else
178178+ (mkMergeExtensible (self: update silicon self { }));
179179+180180+ # `final` is the final state of `lib`
181181+ # `prev` is the original state of `lib`
182182+ # `self` is the final state of `syvl`
183183+ # `super` is the original state of `syvl`
184184+ lib = name: lib: inheritance: f:
185185+ lib.extend
186186+ (final: prev: { ${name} = mks.extend name final prev inheritance f; });
187187+188188+ "${_name}lib" = mks.lib _name;
189189+190190+ libs = lib: inheritances: fs:
191191+ lib.extend (final: prev:
192192+ mapAttrs
193193+ (name: mks.extend name final prev (inheritances.${name} or { })) fs);
194194+195195+ };
196196+ __functor = _: mks.lib _name;
197197+ };
198198+in with silicon; {
199199+ ${_name} =
200200+ mks.extend _name final prev inheritance (silicon.import.all ./. { });
201201+}
+282
lib/flake.nix
···11+{ lib, prev, silicon, system }:
22+with lib;
33+with silicon; rec {
44+ getFlake = args@{ src, ... }:
55+ let
66+ yesFlake = builtins ? getFlake;
77+ flake = if yesFlake then
88+ (builtins.getFlake (toString src))
99+ else
1010+ (let
1111+ nodes = if (builtins.pathExists ./flake.lock) then
1212+ (builtins.fromJSON (builtins.readFile ./flake.lock))
1313+ else {
1414+ root.inputs.flake-compat = "flake-compat";
1515+ flake-compat.locked.rev = "master";
1616+ };
1717+ inherit (nodes.${nodes.root.inputs.flake-compat}) locked;
1818+ url =
1919+ locked.url or "https://github.com/edolstra/flake-compat/archive/${locked.rev}.tar.gz";
2020+ flake-compat = args.flake-compat or (if yesFlake then
2121+ (builtins.getFlake url)
2222+ else
2323+ (builtins.import (fetchTarball {
2424+ inherit url;
2525+ ${if (locked ? narHash) then "sha256" else null} = locked.narHash;
2626+ })));
2727+2828+ # builtins.unsafeDiscardStringContext
2929+ in flake-compat { inherit src; }).defaultNix;
3030+3131+ in formatOutputs flake;
3232+3333+ isLambda = f: (!(isAttrs f)) && (isFunction f);
3434+ isFunctor = f: (isAttrs f) && (isFunction f);
3535+ isCoerced = f: (f ? __functionArgs) && (f ? __functor);
3636+ isCoercedLambda = f: (isLambda f) || (isCoerced f);
3737+3838+ mk = {
3939+ # Adapted From: https://github.com/hercules-ci/flake-parts/blob/4524271976b625a4a605beefd893f270620fd751/lib.nix#L72C5-L125C11
4040+ __functor = self: mk.simple;
4141+ simple = let
4242+ strPath = with types; either str path;
4343+ extraLibType = with types;
4444+ oneOf [ str path attrs list (functionTo attrs) ];
4545+ in module:
4646+ formatOutputs (lib.evalModules {
4747+ class = "flake";
4848+ modules = [
4949+ ({ config, options, ... }: {
5050+ options = {
5151+ src = mkOption {
5252+ type = strPath;
5353+ default =
5454+ dirOf (unsafeGetAttrPos (head (attrNames module)) module).file;
5555+ apply = toString;
5656+ };
5757+ sources = mkOption {
5858+ type = with types;
5959+ coercedTo (either strPath (listOf strPath)) (compose [
6060+ toList
6161+ (map (src: config.src + "/" + src))
6262+ (filter pathExists)
6363+ ]) (listOf strPath);
6464+ };
6565+ self = mkOption {
6666+ type = types.attrs;
6767+ default = config.inputs.self;
6868+ };
6969+ inputs = mkOption {
7070+ type = types.attrs;
7171+ apply = mapAttrs
7272+ (n: v: if (isAttrsOnly v) then (formatOutputs v) else v);
7373+ };
7474+ ${_name} = mkOption {
7575+ type = extraLibType;
7676+ default = { };
7777+ };
7878+ lib = mkOption {
7979+ type = types.attrs;
8080+ default = lib;
8181+ apply = lib:
8282+ if (config.libs == { }) then
8383+ lib
8484+ else
8585+ (mks.libs lib config.inheritances config.libs);
8686+ };
8787+ inheritance = mkOption {
8888+ type = types.attrs;
8989+ default = { };
9090+ };
9191+ inheritances = mkOption {
9292+ type = types.attrs;
9393+ default = { };
9494+ };
9595+ libs = mkOption {
9696+ type = types.attrsOf extraLibType;
9797+ default = { };
9898+ };
9999+100100+ # TODO: Convert this to a nixpkgs settings submodule,
101101+ # using the `functionArgs' of `config.nixpkgs`.
102102+ settings = mkOption {
103103+ type = with types;
104104+ submodule ({ name, config, ... }: {
105105+ options = {
106106+ config = mkOption {
107107+ type = attrs;
108108+ default = { };
109109+ };
110110+ overlays = mkOption {
111111+ type = attrsOf (functionArgsTo 2 attrs);
112112+ default = { };
113113+ };
114114+ };
115115+ });
116116+ };
117117+ nixpkgs = mkOption {
118118+ type = types.attrs;
119119+ default = let
120120+ nixpkgs = attrValues
121121+ (filterAttrs (n: v: hasPrefix "nixpkgs" n) config.inputs);
122122+ in if (nixpkgs == [ ]) then { } else (head nixpkgs);
123123+ };
124124+125125+ specialArgs = mkOption { type = types.attrs; };
126126+ flake = mkOption {
127127+ type = types.attrs;
128128+ default = { };
129129+ };
130130+131131+ # TODO: Make `outputs' a submodule, and everything extra
132132+ # will be in a separate attrset that will be merged into the outputs
133133+ # at the end.
134134+ outputs = mkOption {
135135+ type = with types;
136136+ let
137137+ attrTypes = either attrs (functionTo attrs);
138138+ outputTypes = oneOf [ str path attrTypes ];
139139+ in coercedTo (either outputTypes (listOf outputTypes))
140140+ (compose [
141141+ toList
142142+ (map (f:
143143+ let e = silicon.import.should f;
144144+ in syvl.mif.null e.success e.value))
145145+ (remove null)
146146+ ]) (listOf attrTypes);
147147+ };
148148+149149+ systems = mkOption {
150150+ type = with types;
151151+ let systemType = enum lib.systems.flakeExposed;
152152+ in coercedTo (either systemType (listOf systemType)) toList
153153+ (listOf systemType);
154154+ default = [ system ];
155155+ };
156156+ makers = mkOption {
157157+ type = with types; attrsOf (optionTypes.functionArgsTo 2 attrs);
158158+ };
159159+ maker = mkOption {
160160+ type = with types;
161161+ either (functionTo (either attrs (functionTo attrs)))
162162+ (enum (builtins.attrNames config.makers));
163163+ default = "default";
164164+ };
165165+ };
166166+ _file = toString ./flake.nix;
167167+ config = let extraLib = !(elem config.${_name} [ { } [ ] ]);
168168+ in {
169169+ libs = mkIf extraLib { ${_name} = config.${_name}; };
170170+ inheritances = mkIf extraLib { ${_name} = config.inheritance; };
171171+172172+ sources = [ "nix/sources.nix" "npins" ];
173173+ inputs = mkMerge (map builtins.import config.sources);
174174+175175+ specialArgs = {
176176+ # inherit (config) self inputs lib pkgs;
177177+ };
178178+179179+ outputs = let srcDir = builtins.readDir config.src;
180180+ in [
181181+182182+ (let outputs = config.src + "/outputs.nix";
183183+ in syvl.mif.null
184184+ ((srcDir."outputs.nix" or "directory") != "directory") outputs)
185185+186186+ (let outputs = config.src + "/outputs";
187187+ in syvl.mif.null (((srcDir.outputs or "file") == "directory")
188188+ && ((builtins.readDir outputs) ? "default.nix")) outputs)
189189+190190+ ];
191191+192192+ makers = {
193193+ default = outputs: inputs:
194194+ if (isCoercedLambda outputs) then
195195+ (let
196196+ functionArgs =
197197+ outputs.__functionArgs or (builtins.functionArgs outputs);
198198+ in if (functionArgs ? system) then
199199+ (mkMerge (map (system:
200200+ mapAttrs (n: v: { ${system} = v; }) (callFunction' outputs
201201+ (inputs // {
202202+ inherit system;
203203+ pkgs = import config.nixpkgs
204204+ ((removeAttrs config.settings [ "overlays" ]) // {
205205+ inherit system;
206206+ hostPlatform = system;
207207+ overlays = attrValues config.settings.overlays;
208208+ });
209209+ }) functionArgs)) config.systems))
210210+ else
211211+ (callFunction' outputs inputs functionArgs))
212212+ else
213213+ outputs;
214214+ flake-parts = outputs:
215215+ inputs@{ flake-parts, ... }:
216216+ flake-parts.lib.mkFlake { inherit inputs; }
217217+ (if (isFunction outputs) then
218218+ outputs
219219+ else
220220+ ({ inherit (config) systems; } // outputs));
221221+ };
222222+223223+ flake = mkMerge ([{
224224+ inherit config;
225225+ simpleflake = true;
226226+ }] ++ (map (flip config.makers.${config.maker} ({
227227+ inherit (config) lib; # pkgs;
228228+ } // config.inputs)) (unique config.outputs)));
229229+ };
230230+ })
231231+232232+ # Adapted From: https://github.com/NixOS/nixpkgs/blob/df3de70468b743b371a7191ea61d1040fe3bf399/lib/modules.nix#L567-L570
233233+ ({ config, ... }: {
234234+ imports = let moduleLocation = "${config.src}/flake.nix";
235235+ in [{
236236+ _file = moduleLocation;
237237+ _module.args = { inherit moduleLocation; } // config.specialArgs;
238238+ imports = [ module ];
239239+ }];
240240+ })
241241+242242+ ];
243243+ }).config.flake;
244244+ };
245245+246246+ optionTypes.functionArgsTo = argNumber:
247247+ compose (replicate argNumber types.functionTo);
248248+249249+ formatOutputs = _flake:
250250+ let
251251+ systemsList = builtins.attrNames
252252+ (_flake.checks or _flake.packages or _flake.apps or _flake.formatter or _flake.devShells or _flake.legacyPackages or {
253253+ ${system} = null;
254254+ });
255255+ flake = {
256256+ lib = lib.genAttrs systemsList
257257+ (system: lib.extend (builtins.import ./. { inherit system; }));
258258+ } // _flake;
259259+ systems = let
260260+ allSystems = lib.genAttrs systemsList
261261+ (system: lib.mapAttrs (n: v: v.${system} or v) flake);
262262+ in allSystems // { currentSystem = allSystems.${system}; };
263263+ in {
264264+ inherit systems;
265265+ } // (lib.mapAttrs (n: v:
266266+ if ((isAttrsOnly v) && (builtins.hasAttr system v)) then
267267+ (v // { currentSystem = systems.currentSystem.${n}; })
268268+ else
269269+ v) flake) // {
270270+ inputs = let
271271+ simpleflake = flake.simpleflake or false;
272272+ inputs = if simpleflake then
273273+ flake.config.inputs
274274+ else
275275+ (flake.inputs or { });
276276+ in if simpleflake then
277277+ inputs
278278+ else
279279+ (mapAttrs (n: v: if (isAttrsOnly v) then (formatOutputs v) else v)
280280+ inputs);
281281+ };
282282+}
+27
lib/optionals.nix
···11+{ lib }:
22+with lib; {
33+ optionalName = condition: name: if condition then name else null;
44+ mif = {
55+ list = optionals;
66+ list' = optional;
77+ attrs = optionalAttrs;
88+ num = condition: value: if condition then value else 0;
99+ null = syvl.optionalName;
1010+ str = optionalString;
1111+ True = condition: value: if condition then value else true;
1212+ False = condition: value: if condition then value else false;
1313+ fn = condition: fn: value: if condition then (fn value) else value;
1414+ };
1515+ mifNotNull = {
1616+ __functor = self: a: b: if (a != null) then a else b;
1717+ list = a: optionals (a != null);
1818+ list' = a: optional (a != null);
1919+ attrs = a: optionalAttrs (a != null);
2020+ num = a: b: if (a != null) then b else 0;
2121+ null = a: b: if (a != null) then b else null;
2222+ nullb = a: b: c: if (a != null) then b else c;
2323+ str = a: optionalString (a != null);
2424+ True = a: b: if (a != null) then b else true;
2525+ False = a: b: if (a != null) then b else false;
2626+ };
2727+}