@@ -10,10 +10,16 @@ import (
1010 "strings"
1111)
1212
13+ type graphPrinter interface {
14+ writeHeader (hLayout bool )
15+ writeNode (pkgName string , attrs * build.Package )
16+ writeEdge (u string , v string )
17+ writeEnd ()
18+ }
19+
1320var (
1421 pkgs map [string ]* build.Package
1522 erroredPkgs map [string ]bool
16- ids map [string ]string
1723
1824 ignored = map [string ]bool {
1925 "C" : true ,
3238 horizontal = flag .Bool ("horizontal" , false , "lay out the dependency graph horizontally instead of vertically" )
3339 withTests = flag .Bool ("withtests" , false , "include test packages" )
3440 maxLevel = flag .Int ("maxlevel" , 256 , "max level of go dependency graph" )
41+ format = flag .String ("format" , "dot" , "output format of graph (dot, mermaid)" )
3542
3643 buildTags []string
3744 buildContext = build .Default
@@ -50,7 +57,6 @@ func init() {
5057func main () {
5158 pkgs = make (map [string ]* build.Package )
5259 erroredPkgs = make (map [string ]bool )
53- ids = make (map [string ]string )
5460 flag .Parse ()
5561
5662 args := flag .Args ()
@@ -75,6 +81,11 @@ func main() {
7581 }
7682 buildContext .BuildTags = buildTags
7783
84+ printer , err := getPrinter ()
85+ if err != nil {
86+ log .Fatal (err )
87+ }
88+
7889 cwd , err := os .Getwd ()
7990 if err != nil {
8091 log .Fatalf ("failed to get cwd: %s" , err )
@@ -85,16 +96,7 @@ func main() {
8596 }
8697 }
8798
88- fmt .Println ("digraph godep {" )
89- if * horizontal {
90- fmt .Println (`rankdir="LR"` )
91- }
92- fmt .Print (`splines=ortho
93- nodesep=0.4
94- ranksep=0.8
95- node [shape="box",style="rounded,filled"]
96- edge [arrowsize="0.5"]
97- ` )
99+ printer .writeHeader (* horizontal )
98100
99101 // sort packages
100102 pkgKeys := []string {}
@@ -105,27 +107,12 @@ edge [arrowsize="0.5"]
105107
106108 for _ , pkgName := range pkgKeys {
107109 pkg := pkgs [pkgName ]
108- pkgId := getId (pkgName )
109110
110111 if isIgnored (pkg ) {
111112 continue
112113 }
113114
114- var color string
115- switch {
116- case pkg .Goroot :
117- color = "palegreen"
118- case len (pkg .CgoFiles ) > 0 :
119- color = "darkgoldenrod1"
120- case isVendored (pkg .ImportPath ):
121- color = "palegoldenrod"
122- case hasBuildErrors (pkg ):
123- color = "red"
124- default :
125- color = "paleturquoise"
126- }
127-
128- fmt .Printf ("%s [label=\" %s\" color=\" %s\" URL=\" %s\" target=\" _blank\" ];\n " , pkgId , pkgName , color , pkgDocsURL (pkgName ))
115+ printer .writeNode (pkgName , pkg )
129116
130117 // Don't render imports from packages in Goroot
131118 if pkg .Goroot && ! * withGoroot {
@@ -138,11 +125,11 @@ edge [arrowsize="0.5"]
138125 continue
139126 }
140127
141- impId := getId (imp )
142- fmt .Printf ("%s -> %s;\n " , pkgId , impId )
128+ printer .writeEdge (pkgName , imp )
143129 }
144130 }
145- fmt .Println ("}" )
131+
132+ printer .writeEnd ()
146133}
147134
148135func pkgDocsURL (pkgName string ) string {
@@ -212,21 +199,6 @@ func getImports(pkg *build.Package) []string {
212199 return imports
213200}
214201
215- func deriveNodeID (packageName string ) string {
216- //TODO: improve implementation?
217- id := "\" " + packageName + "\" "
218- return id
219- }
220-
221- func getId (name string ) string {
222- id , ok := ids [name ]
223- if ! ok {
224- id = deriveNodeID (name )
225- ids [name ] = id
226- }
227- return id
228- }
229-
230202func hasPrefixes (s string , prefixes []string ) bool {
231203 for _ , p := range prefixes {
232204 if strings .HasPrefix (s , p ) {
@@ -259,14 +231,6 @@ func hasBuildErrors(pkg *build.Package) bool {
259231 return v
260232}
261233
262- func debug (args ... interface {}) {
263- fmt .Fprintln (os .Stderr , args ... )
264- }
265-
266- func debugf (s string , args ... interface {}) {
267- fmt .Fprintf (os .Stderr , s , args ... )
268- }
269-
270234func isVendored (path string ) bool {
271235 return strings .Contains (path , "/vendor/" )
272236}
@@ -275,3 +239,14 @@ func normalizeVendor(path string) string {
275239 pieces := strings .Split (path , "vendor/" )
276240 return pieces [len (pieces )- 1 ]
277241}
242+
243+ func getPrinter () (graphPrinter , error ) {
244+ switch * format {
245+ case "dot" :
246+ return newGraphvizPrinter (), nil
247+ case "mermaid" :
248+ return newMermaidPrinter (), nil
249+ default :
250+ return nil , fmt .Errorf ("invalid format flag %q, must be: dot, mermaid" , * format )
251+ }
252+ }
0 commit comments