mirror of
https://github.com/NotAShelf/nvf.git
synced 2025-09-06 10:21:31 +00:00
refactor: move lib out of modules
This commit is contained in:
parent
206e17bbe4
commit
89be2b9d37
8 changed files with 334 additions and 0 deletions
107
lib/dag.nix
Normal file
107
lib/dag.nix
Normal file
|
@ -0,0 +1,107 @@
|
|||
# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/dag.nix
|
||||
# A generalization of Nixpkgs's `strings-with-deps.nix`.
|
||||
#
|
||||
# The main differences from the Nixpkgs version are
|
||||
#
|
||||
# - not specific to strings, i.e., any payload is OK,
|
||||
#
|
||||
# - the addition of the function `entryBefore` indicating a "wanted
|
||||
# by" relationship.
|
||||
{lib}: let
|
||||
inherit (lib) all filterAttrs nvim mapAttrs toposort;
|
||||
in {
|
||||
empty = {};
|
||||
|
||||
isEntry = e: e ? data && e ? after && e ? before;
|
||||
isDag = dag:
|
||||
builtins.isAttrs dag && all nvim.dag.isEntry (builtins.attrValues dag);
|
||||
|
||||
/*
|
||||
Takes an attribute set containing entries built by entryAnywhere,
|
||||
entryAfter, and entryBefore to a topologically sorted list of
|
||||
entries.
|
||||
|
||||
Internally this function uses the `toposort` function in
|
||||
`<nixpkgs/lib/lists.nix>` and its value is accordingly.
|
||||
|
||||
Specifically, the result on success is
|
||||
|
||||
{ result = [ { name = ?; data = ?; } … ] }
|
||||
|
||||
For example
|
||||
|
||||
nix-repl> topoSort {
|
||||
a = entryAnywhere "1";
|
||||
b = entryAfter [ "a" "c" ] "2";
|
||||
c = entryBefore [ "d" ] "3";
|
||||
d = entryBefore [ "e" ] "4";
|
||||
e = entryAnywhere "5";
|
||||
} == {
|
||||
result = [
|
||||
{ data = "1"; name = "a"; }
|
||||
{ data = "3"; name = "c"; }
|
||||
{ data = "2"; name = "b"; }
|
||||
{ data = "4"; name = "d"; }
|
||||
{ data = "5"; name = "e"; }
|
||||
];
|
||||
}
|
||||
true
|
||||
|
||||
And the result on error is
|
||||
|
||||
{
|
||||
cycle = [ { after = ?; name = ?; data = ? } … ];
|
||||
loops = [ { after = ?; name = ?; data = ? } … ];
|
||||
}
|
||||
|
||||
For example
|
||||
|
||||
nix-repl> topoSort {
|
||||
a = entryAnywhere "1";
|
||||
b = entryAfter [ "a" "c" ] "2";
|
||||
c = entryAfter [ "d" ] "3";
|
||||
d = entryAfter [ "b" ] "4";
|
||||
e = entryAnywhere "5";
|
||||
} == {
|
||||
cycle = [
|
||||
{ after = [ "a" "c" ]; data = "2"; name = "b"; }
|
||||
{ after = [ "d" ]; data = "3"; name = "c"; }
|
||||
{ after = [ "b" ]; data = "4"; name = "d"; }
|
||||
];
|
||||
loops = [
|
||||
{ after = [ "a" "c" ]; data = "2"; name = "b"; }
|
||||
];
|
||||
}
|
||||
true
|
||||
*/
|
||||
topoSort = dag: let
|
||||
dagBefore = dag: name:
|
||||
builtins.attrNames
|
||||
(filterAttrs (n: v: builtins.elem name v.before) dag);
|
||||
normalizedDag =
|
||||
mapAttrs (n: v: {
|
||||
name = n;
|
||||
data = v.data;
|
||||
after = v.after ++ dagBefore dag n;
|
||||
})
|
||||
dag;
|
||||
before = a: b: builtins.elem a.name b.after;
|
||||
sorted = toposort before (builtins.attrValues normalizedDag);
|
||||
in
|
||||
if sorted ? result
|
||||
then {
|
||||
result = map (v: {inherit (v) name data;}) sorted.result;
|
||||
}
|
||||
else sorted;
|
||||
|
||||
# Applies a function to each element of the given DAG.
|
||||
map = f: mapAttrs (n: v: v // {data = f n v.data;});
|
||||
|
||||
entryBetween = before: after: data: {inherit data before after;};
|
||||
|
||||
# Create a DAG entry with no particular dependency information.
|
||||
entryAnywhere = nvim.dag.entryBetween [] [];
|
||||
|
||||
entryAfter = nvim.dag.entryBetween [];
|
||||
entryBefore = before: nvim.dag.entryBetween before [];
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue