/
main.go
147 lines (128 loc) · 3.29 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
147
package main
import (
"errors"
"fmt"
"os"
"strings"
"text/template"
"github.com/spf13/cobra"
"github.com/natefinch/graffiti/tags"
)
func main() {
if err := makeCmd().Execute(); err != nil {
os.Exit(1)
}
}
func makeCmd() *cobra.Command {
base := &cobra.Command{
Use: "graffiti",
Short: "generate struct tags",
Long: "Graffiti generates struct tags for your go code.",
}
// Order here determines order in help output.
base.AddCommand(genCmd())
base.AddCommand(runCmd())
addtopics(base)
return base
}
func genCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "gen <tags> [target]",
Short: "Generate struct tags for go structs in a file or directory.",
Long: genUsage,
}
var types, mapping string
var isTempl, dryRun bool
cmd.Flags().StringVarP(&types, "types", "t", "", "Generate tags only for these types (comma separated list).")
cmd.Flags().StringVarP(&mapping, "map", "m", "", "Map field names to alternate tag names (see help mappings).")
cmd.Flags().BoolVarP(&isTempl, "format", "f", false, "If set, tags is a go template (see help templates).")
cmd.Flags().BoolVarP(&dryRun, "dryrun", "d", false, "If set, changes are written to stdout instead of to the files.")
addtopics(cmd)
cmd.Run = func(cmd *cobra.Command, args []string) {
opt, err := makeOptions(types, mapping, isTempl, dryRun, args)
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
if err := tags.Generate(opt); err != nil {
fmt.Println(err)
os.Exit(-1)
}
}
return cmd
}
func makeOptions(types, mapping string, isTempl, dryRun bool, args []string) (tags.Options, error) {
// Tags is required, target is optional
if len(args) != 2 && len(args) != 1 {
return tags.Options{}, fmt.Errorf("Wrong number of arguments, expected 1 or 2, got %d", len(args))
}
opt := tags.Options{DryRun: dryRun}
if len(args) > 1 {
opt.Target = args[1]
} else {
opt.Target = "."
}
if mapping != "" {
m, err := makeMap(mapping)
if err != nil {
return tags.Options{}, err
}
opt.Mapping = m
}
if types != "" {
opt.Types = strings.Split(types, ",")
}
if !isTempl {
opt.Tags = strings.Split(args[0], ",")
} else {
t, err := template.New("tag template").Parse(args[0])
if err != nil {
return tags.Options{}, err
}
opt.Template = t
}
return opt, nil
}
func makeMap(val string) (map[string]string, error) {
maps := strings.Split(val, ";")
mapping := map[string]string{}
for _, m := range maps {
parts := strings.SplitN(m, "=", 2)
if len(parts) != 2 {
return nil, errors.New("badly formatted mapping: " + m)
}
mapping[parts[0]] = parts[1]
}
return mapping, nil
}
func runCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "run <file>",
Short: "Run graffiti commands embedded in a go file.",
Long: runUsage,
}
cmd.Run = func(cmd *cobra.Command, args []string) {
// File is required.
if len(args) != 1 {
fmt.Printf("Wrong number of arguments, expected 1, got %d", len(args))
os.Exit(-1)
}
if err := run(args[0]); err != nil {
fmt.Println(err)
os.Exit(-1)
}
}
return cmd
}
func addtopics(base *cobra.Command) {
base.AddCommand(&cobra.Command{
Use: "mappings",
Short: "description of field name mappings",
Long: mappings,
})
base.AddCommand(&cobra.Command{
Use: "templates",
Short: "how to use templated output",
Long: gotemplate,
})
}