imports-graph.elv 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. use flag
  2. use re
  3. use str
  4. var prefix = src.elv.sh/
  5. fn keep-if {|p| each {|x| if ($p $x) { put $x }} }
  6. fn get {|x k def| if (has-key $x $k) { put $x[$k] } else { put $def } }
  7. fn get-cluster {|x| put (re:find '^'(re:quote $prefix)'[^/]+/[^/]+' $x)[text] }
  8. fn node {|x| put '"'(str:trim-prefix $x $prefix)'"' }
  9. fn main {|&merge-clusters=$false|
  10. var imports-of = [&]
  11. var q = [$prefix''cmd/elvish]
  12. var seen = [&q[0]=$true]
  13. var clusters = [&]
  14. while (not-eq $q []) {
  15. var next-q = []
  16. for pkg $q {
  17. var c = (get-cluster $pkg)
  18. set clusters[$c] = [(all (get $clusters $c [])) $pkg]
  19. var @imports = (
  20. go list -json $pkg |
  21. all (get (from-json) Imports []) |
  22. keep-if {|x| str:has-prefix $x $prefix})
  23. set imports-of[$pkg] = $imports
  24. var @new-pkgs = (all $imports | keep-if {|x|
  25. not (has-key $seen $x)
  26. set seen[$x] = $true
  27. })
  28. set @next-q = (all $next-q) (all $new-pkgs)
  29. }
  30. set q = $next-q
  31. }
  32. echo 'strict digraph imports {'
  33. echo ' rankdir = LR;'
  34. echo ' node [shape = box, width = 1.5];'
  35. echo ' splines = ortho;'
  36. echo ' nodesep = 0.1;'
  37. if $merge-clusters {
  38. for pkg [(keys $imports-of)] {
  39. for import $imports-of[$pkg] {
  40. var src = (get-cluster $pkg)
  41. var dst = (get-cluster $import)
  42. if (not-eq $src $dst) {
  43. echo ' '(node $src)' -> '(node $dst)';'
  44. }
  45. }
  46. }
  47. } else {
  48. var cluster-seq = 0
  49. for c [(keys $clusters)] {
  50. var pkgs = $clusters[$c]
  51. if (<= (count $pkgs) 1) { continue }
  52. echo ' subgraph cluster'$cluster-seq' {'
  53. echo ' style = filled;'
  54. echo ' color = lightgrey;'
  55. for pkg $clusters[$c] {
  56. echo ' '(node $pkg)';'
  57. }
  58. echo ' }'
  59. set cluster-seq = (+ $cluster-seq 1)
  60. }
  61. for pkg [(keys $imports-of)] {
  62. for import $imports-of[$pkg] {
  63. echo ' '(node $pkg)' -> '(node $import)';'
  64. }
  65. }
  66. }
  67. echo '}'
  68. }
  69. flag:call $main~ $args