elvish/tools/imports-graph.elv
Qi Xiao 51a388b9ec Add imports-graph.elv, a script to visualize package dependencies.
This script focuses on showing the dependencies between source packages in src.elv.sh. It outputs a DOT file.
2021-12-17 00:52:59 +00:00

74 lines
1.8 KiB
Plaintext

use re
use str
var prefix = src.elv.sh/
var merge-clusters = $false
var imports-of = [&]
var q = [$prefix''cmd/elvish]
var seen = [&q[0]=$true]
var clusters = [&]
fn keep-if {|p| each {|x| if ($p $x) { put $x }} }
fn get {|x k def| if (has-key $x $k) { put $x[$k] } else { put $def } }
fn get-cluster {|x| put (re:find '^'(re:quote $prefix)'[^/]+/[^/]+' $x)[text] }
while (not-eq $q []) {
var next-q = []
for pkg $q {
var c = (get-cluster $pkg)
set clusters[$c] = [(all (get $clusters $c [])) $pkg]
var @imports = (
go list -json $pkg |
all (get (from-json) Imports []) |
keep-if {|x| str:has-prefix $x $prefix})
set imports-of[$pkg] = $imports
var @new-pkgs = (all $imports | keep-if {|x|
not (has-key $seen $x)
set seen[$x] = $true
})
set @next-q = (all $next-q) (all $new-pkgs)
}
set q = $next-q
}
fn node {|x| put '"'(str:trim-prefix $x $prefix)'"' }
echo 'strict digraph imports {'
echo ' rankdir = LR;'
echo ' node [shape = box, width = 1.5];'
echo ' splines = ortho;'
echo ' nodesep = 0.1;'
if $merge-clusters {
for pkg [(keys $imports-of)] {
for import $imports-of[$pkg] {
var src = (get-cluster $pkg)
var dst = (get-cluster $import)
if (not-eq $src $dst) {
echo ' '(node $src)' -> '(node $dst)';'
}
}
}
} else {
var cluster-seq = 0
for c [(keys $clusters)] {
var pkgs = $clusters[$c]
if (<= (count $pkgs) 1) { continue }
echo ' subgraph cluster'$cluster-seq' {'
echo ' style = filled;'
echo ' color = lightgrey;'
for pkg $clusters[$c] {
echo ' '(node $pkg)';'
}
echo ' }'
set cluster-seq = (+ $cluster-seq 1)
}
for pkg [(keys $imports-of)] {
for import $imports-of[$pkg] {
echo ' '(node $pkg)' -> '(node $import)';'
}
}
}
echo '}'