github.com/mattn/anko@v0.1.10/cmd/anko-package-gen/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "go/ast" 6 "go/parser" 7 "go/token" 8 "log" 9 "os" 10 "os/exec" 11 "path/filepath" 12 "sort" 13 "strings" 14 ) 15 16 func pkgName(f string) string { 17 file, err := parser.ParseFile(token.NewFileSet(), f, nil, parser.PackageClauseOnly) 18 if err != nil || file == nil { 19 return "" 20 } 21 return file.Name.Name 22 } 23 24 func isGoFile(dir os.FileInfo) bool { 25 return !dir.IsDir() && 26 !strings.HasPrefix(dir.Name(), ".") && // ignore .files 27 filepath.Ext(dir.Name()) == ".go" 28 } 29 30 func isPkgFile(dir os.FileInfo) bool { 31 return isGoFile(dir) && !strings.HasSuffix(dir.Name(), "_test.go") // ignore test files 32 } 33 34 func parseDir(p string) (map[string]*ast.Package, error) { 35 isGoFile := func(d os.FileInfo) bool { 36 return !d.IsDir() && !strings.HasSuffix(d.Name(), "_test.go") && !strings.HasPrefix(d.Name(), "example_") 37 } 38 39 pkgs, err := parser.ParseDir(token.NewFileSet(), p, isGoFile, parser.ParseComments) 40 if err != nil { 41 return nil, err 42 } 43 return pkgs, nil 44 } 45 46 func main() { 47 pkg := "flag" 48 if len(os.Args) == 2 { 49 pkg = os.Args[1] 50 } 51 b, err := exec.Command("go", "env", "GOROOT").CombinedOutput() 52 if err != nil { 53 log.Fatal(err) 54 } 55 paths := []string{filepath.Join(strings.TrimSpace(string(b)), "src")} 56 b, err = exec.Command("go", "env", "GOPATH").CombinedOutput() 57 if err != nil { 58 log.Fatal(err) 59 } 60 for _, p := range strings.Split(strings.TrimSpace(string(b)), string(filepath.ListSeparator)) { 61 paths = append(paths, filepath.Join(p, "src")) 62 } 63 for _, p := range paths { 64 pp := filepath.Join(p, pkg) 65 pkgs, err := parseDir(pp) 66 if err != nil || len(pkgs) == 0 { 67 continue 68 } 69 names := map[string]bool{} 70 pn := pkg 71 for _, pp := range pkgs { 72 pn = pp.Name 73 for _, f := range pp.Files { 74 for _, d := range f.Decls { 75 switch decl := d.(type) { 76 case *ast.GenDecl: 77 for _, spec := range decl.Specs { 78 if vspec, ok := spec.(*ast.ValueSpec); ok { 79 for _, n := range vspec.Names { 80 c := n.Name[0] 81 if c < 'A' || c > 'Z' { 82 continue 83 } 84 names[n.Name] = true 85 } 86 } 87 } 88 case *ast.FuncDecl: 89 if decl.Recv != nil { 90 continue 91 } 92 c := decl.Name.Name[0] 93 if c < 'A' || c > 'Z' { 94 continue 95 } 96 names[decl.Name.Name] = true 97 } 98 } 99 } 100 } 101 keys := []string{} 102 for k := range names { 103 keys = append(keys, k) 104 } 105 sort.Strings(keys) 106 fmt.Printf(`// Package %s implements %s interface for anko script. 107 package %s 108 109 import ( 110 "%s" 111 ) 112 113 func init() { 114 Packages["%s"] = map[string]interface{}{ 115 `, pn, pkg, pn, pkg, pn) 116 for _, k := range keys { 117 fmt.Printf(` "%s": %s.%s,`+"\n", k, pn, k) 118 } 119 fmt.Println(` } 120 }`) 121 } 122 }