better clustering

This commit is contained in:
Primrose 2025-06-23 17:23:04 +02:00
parent f2cdc96007
commit 6dba1aaca8
Signed by: primrose
GPG key ID: 4E887A4CA9714ADA
3 changed files with 128 additions and 38 deletions

View file

@ -16,6 +16,14 @@
};
};
packages = import ./nix/packages {inherit sources;};
#
#
# Module graph generation experiment below
#
#
inherit (nixosConfigurations.vanadium) options;
/*
@ -27,21 +35,28 @@
We could draw out file -> option, and cluster each option in a file rectangle
*/
traceShowId = x: builtins.trace x x;
# Drop those that fail to eval
filtered = let
drop = path: {
inherit path;
update = _: {};
};
in
lib.updateManyAttrsByPath
(map drop [
["_module"]
["services" "immich"] # caused by option referencing a config value
["services" "nagios"]
["hardware" "nvidia"]
])
options;
filtered =
let
drop = path: {
inherit path;
update = _: {};
};
in
lib.updateManyAttrsByPath
(map drop [
["_module"]
["services" "immich"] # caused by option referencing a config value
["services" "nagios"]
["hardware" "nvidia"]
])
# options
# Use this for a smaller example
# {inherit (options.programs) vim less;}
{ inherit (options) programs; }
;
# Transform each option to its path and call site
mapped =
@ -55,7 +70,9 @@
_type = "result";
optionPath = v.loc;
definedBy = definedBy.value;
declaredAt = map (x: x.file) v.declarationPositions;
declaredAt =
# There can only be one
(builtins.head v.declarationPositions).file;
}
)
filtered;
@ -70,13 +87,62 @@
# Run `nix eval --json -f ./. 'asList' | jq >asList.json` to generate
asList = let
untag = map (lib.flip lib.removeAttrs ["_type"]);
untag = lib.flip lib.removeAttrs ["_type"];
in
untag (
map untag (
attrValuesRecursiveCond
(as: !(as ? _type && as._type == "result"))
mapped
);
packages = import ./nix/packages {inherit sources;};
# TODO: Improve the granularity by checking the prefix
#
# Each attribute is a list of nodes in the same file
clusterized =
builtins.foldl' (
acc: elem:
acc
// {
${elem.declaredAt} =
acc.${elem.declaredAt} or []
++ [elem];
}
)
{}
asList;
subgraphs =
lib.mapAttrsToList (
declaredAt: elems: let
entries =
lib.concatMapStrings (
elem:
lib.concatMapStrings (
def:
lib.optionalString (
def != elem.declaredAt # remove loops
)
''
"${def}" -> "${builtins.concatStringsSep "." elem.optionPath}";
''
)
elem.definedBy
)
elems;
in ''
subgraph "cluster_${declaredAt}" {
${entries}
label = "${declaredAt}";
}
''
)
clusterized;
graphvizOutput = ''
digraph {
// compound=true;
rankdir="TB";
${builtins.concatStringsSep "\n" subgraphs}
}
'';
}

View file

@ -11,25 +11,8 @@
pkgs.mkShell {
name = "dotfiles";
packages = with pkgs; [
#
# Just scripts
#
just
jq
#
# XMonad
#
(haskellPackages.ghcWithPackages (self: [
self.xmonad-contrib
self.xmonad-extras
]))
haskell-language-server
cabal-install
#
# Installer testing
#
disko
python3
pyright
graphviz
];
}

41
toDot.py Executable file
View file

@ -0,0 +1,41 @@
#!/usr/bin/env python3
import json
def group_by_prefix(x, y):
# sections = []
# with open("asList.json", "r") as generatedFile:
# data = json.load(generatedFile)
#
# # list of all groups of entries that are in the same file
#
# by_file = {}
# for entry in data:
# by_file[entry["declaredAt"][0]] = entry
#
# for file, entry in by_file.items():
# def as_cluster(content):
# return f"""
# subgraph \"{file}\" {{
# {content}
# }}
# """
#
# buffer = []
# for arc in entry["definedBy"]:
# for defsite in entry["declaredAt"]:
# if arc != defsite:
#
# buffer += [
# f"\"{arc}\" -> \"{".".join(entry["optionPath"])}\";"
# ]
#
# if len(buffer) > 0:
# sections += [ as_cluster("\n".join(buffer)) ]
#
# content = "\n".join(sections)
# print("digraph {\n compound=true;\n" + content + "\n}")