-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
146 lines (133 loc) · 4.02 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Package main is a tool to automate the creation of code init function.
// Inspired by `github.com/golang/tools/cmd/stringer`.
package main
import (
"flag"
"fmt"
"github.com/go-leo/gors/cmd/internal"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
)
var (
typeNames = flag.String("type", "", "comma-separated list of type names; must be set")
output = flag.String("output", "", "output file name; default srcdir/<type>_generated.go")
trimprefix = flag.String("trimprefix", "", "trim the `prefix` from the generated constant names")
buildTags = flag.String("tags", "", "comma-separated list of build tags to apply")
doc = flag.Bool("doc", false, "if true only generate error code documentation in markdown format")
docoutput = flag.String("docoutput", "", "doc output file name; default srcdir/<type>_generated.md")
)
// Usage is a replacement usage function for the flags package.
func Usage() {
fmt.Fprintf(os.Stderr, "Usage of codegen:\n")
fmt.Fprintf(os.Stderr, "\tgors-error [flags] -type T [directory]\n")
fmt.Fprintf(os.Stderr, "\tgors-error [flags] -type T files... # Must be a single package\n")
fmt.Fprintf(os.Stderr, "Flags:\n")
flag.PrintDefaults()
}
func main() {
log.SetFlags(0)
log.SetPrefix("gors-error: ")
flag.Usage = Usage
flag.Parse()
showVersion := flag.Bool("version", false, "print the version and exit")
if *showVersion {
fmt.Printf("gors-error %v\n", internal.Version)
return
}
if len(*typeNames) == 0 {
flag.Usage()
os.Exit(2)
}
types := strings.Split(*typeNames, ",")
var tags []string
if len(*buildTags) > 0 {
tags = strings.Split(*buildTags, ",")
}
// We accept either one directory or a list of files. Which do we have?
args := flag.Args()
if len(args) == 0 {
// Default: process whole package in current directory.
args = []string{"."}
}
// Parse the package once.
var dir string
g := Generator{
trimPrefix: *trimprefix,
}
// TODO(suzmue): accept other patterns for packages (directories, list of files, import paths, etc).
if len(args) == 1 && isDirectory(args[0]) {
dir = args[0]
} else {
if len(tags) != 0 {
log.Fatal("-tags option applies only to directories, not when files are specified")
}
dir = filepath.Dir(args[0])
}
g.parsePackage(dir, args, tags)
// Run generate for each type.
var (
codeSrc []byte
docSrc []byte
)
for _, typeName := range types {
// Print the header and package clause.
g.Printf("// Code generated by \"gors-error -type=int %s\"; DO NOT EDIT.\n", " ")
g.Printf("package %s", g.pkg.name)
g.Printf("\n")
g.Printf("import %s", "\"github.com/go-leo/gors\"\n")
g.generate(typeName)
// Format the output.
codeSrc = g.format()
if *doc {
g.buf.Reset()
g.generateDocs(typeName)
docSrc = g.buf.Bytes()
}
}
// Write to file.
codeOutputName := *output
docOutputName := *docoutput
if codeOutputName == "" {
absDir, _ := filepath.Abs(dir)
baseName := fmt.Sprintf("%s_generated.go", strings.ReplaceAll(filepath.Base(absDir), "-", "_"))
if len(flag.Args()) == 1 {
baseName = fmt.Sprintf(
"%s_generated.go",
strings.ReplaceAll(filepath.Base(strings.TrimSuffix(flag.Args()[0], ".go")), "-", "_"),
)
}
codeOutputName = filepath.Join(dir, strings.ToLower(baseName))
}
if docOutputName == "" {
absDir, _ := filepath.Abs(dir)
baseName := fmt.Sprintf("%s_generated.md", strings.ReplaceAll(filepath.Base(absDir), "-", "_"))
if len(flag.Args()) == 1 {
baseName = fmt.Sprintf(
"%s_generated.md",
strings.ReplaceAll(filepath.Base(strings.TrimSuffix(flag.Args()[0], ".md")), "-", "_"),
)
}
docOutputName = filepath.Join(dir, strings.ToLower(baseName))
}
err := ioutil.WriteFile(codeOutputName, codeSrc, 0o600)
if err != nil {
log.Fatalf("writing output: %s", err)
}
if *doc {
err = ioutil.WriteFile(docOutputName, docSrc, 0o600)
if err != nil {
log.Fatalf("writing output: %s", err)
}
}
}
// isDirectory reports whether the named file is a directory.
func isDirectory(name string) bool {
info, err := os.Stat(name)
if err != nil {
log.Fatal(err)
}
return info.IsDir()
}