-
Notifications
You must be signed in to change notification settings - Fork 0
/
enumeration.go
169 lines (141 loc) · 5.17 KB
/
enumeration.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package main
import (
"flag"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/rickb777/enumeration/v3/enum"
"github.com/rickb777/enumeration/v3/internal/model"
"github.com/rickb777/enumeration/v3/internal/parse"
"github.com/rickb777/enumeration/v3/internal/transform"
"github.com/rickb777/enumeration/v3/internal/util"
)
var config model.Config
var inputGo, outputGo, outputJSON, marshalTextRep, marshalJSONRep, storeRep string
var force, lowercase, uppercase, showVersion bool
func defineFlags() {
flag.StringVar(&config.MainType, "type", "", "Name of the enumeration type (required).")
flag.StringVar(&model.Prefix, "prefix", "", "Optional prefix to be stripped from the identifiers.")
flag.StringVar(&model.Suffix, "suffix", "", "Optional suffix to be stripped from the identifiers.")
flag.StringVar(&inputGo, "i", "", "Name of the input file. May be '-' for stdin. Default is enumeration type in lower case.")
flag.StringVar(&outputGo, "o", "", "Name of the output file. May be '-' for stdout. Default is enumeration type in lower case plus '_enum'.")
flag.StringVar(&config.Plural, "plural", "", "Plural name of the enumeration type (optional).")
flag.StringVar(&parse.AliasTable, "alias", "", "Uses your own map[string]Type as aliases during parsing.")
flag.StringVar(&config.Pkg, "package", "", "Name of the output package (optional). Defaults to the output directory.")
flag.StringVar(&marshalTextRep, "marshaltext", "None", "Marshal text values using Identifier or Number")
flag.StringVar(&marshalJSONRep, "marshaljson", "None", "Marshal JSON values using Identifier or Number")
flag.StringVar(&storeRep, "store", "None", "Store values in a DB using Identifier, Number or Ordinal")
flag.BoolVar(&config.Lenient, "lenient", false, "Allow parsing to yield invalid values.")
flag.BoolVar(&force, "f", false, "Force writing the output file even if up to date (not used when piping stdin or stdout).")
flag.BoolVar(&lowercase, "lc", false, "Convert strings to lowercase and ignore case when parsing")
flag.BoolVar(&uppercase, "uc", false, "Convert strings to uppercase and ignore case when parsing.")
flag.BoolVar(&config.IgnoreCase, "ic", false, "Ignore case when parsing but keep the mixed case when outputting.")
flag.BoolVar(&config.Unsnake, "unsnake", false, "Convert underscores in identifiers to spaces.")
flag.BoolVar(&config.Simple, "s", false, "Generate simple enumerations without serialising or parsing functions")
flag.BoolVar(&util.Verbose, "v", false, "Verbose progress messages.")
flag.BoolVar(&util.Dbg, "z", false, "Debug messages.")
flag.BoolVar(&showVersion, "version", false, "Print version number.")
}
func choosePackage(outputFile string) string {
wd, err := os.Getwd()
if err != nil {
util.Fail(err)
}
dir := filepath.Base(filepath.Dir(outputFile))
if dir != "." {
return dir
}
return filepath.Base(filepath.FromSlash(wd))
}
func notUpToDate() bool {
if inputGo != "-" && outputGo != "-" {
xi, err := os.Stat(inputGo)
if err == nil {
xo, err := os.Stat(outputGo)
if err == nil && xo.ModTime().After(xi.ModTime()) {
util.Info("Skipped %s.\n", outputGo)
return false
}
}
}
return true
}
func generate() {
util.Debug("ReadFile %s\n", inputGo)
var err error
config.MarshalTextRep, err = enum.AsRepresentation(marshalTextRep)
util.Must(err, "(-marshaltext)")
config.MarshalJSONRep, err = enum.AsRepresentation(marshalJSONRep)
util.Must(err, "(-marshaljson)")
config.StoreRep, err = enum.AsRepresentation(storeRep)
util.Must(err, "(-store)")
var in io.Reader = os.Stdin
if inputGo != "-" {
inf, e2 := os.Open(inputGo)
util.Must(e2)
defer inf.Close()
in = inf
}
var out model.DualWriter = os.Stdout
if outputGo == "-" {
if config.Pkg == "" {
util.Fail("-pkg is required when piping the output.")
}
} else {
outf, e2 := os.Create(outputGo)
util.Must(e2)
defer outf.Close()
out = outf
config.Pkg = choosePackage(outputGo)
util.Stdout = os.Stdout // ok because it's not going to be interleaved now
}
util.Debug("pkg=%s\n", config.Pkg)
xCase := transform.Of(lowercase, uppercase)
m, err := parse.Convert(in, inputGo, xCase, config)
util.Must(err)
units := m.BuildUnits()
model.WriteGo(units, m.SelectImports(), out)
util.Info("Generated %s.\n", outputGo)
}
func main() {
defineFlags()
flag.Parse()
doMain()
}
func doMain() {
if showVersion {
fmt.Fprintln(os.Stderr, util.Version)
os.Exit(1)
}
if config.MainType == "" {
util.Fail("Must specify -type.")
}
if config.Plural == "" {
config.Plural = config.MainType + "s"
}
if inputGo == "" {
inputGo = strings.ToLower(config.MainType) + ".go"
}
if outputGo == "" {
outputGo = strings.ToLower(config.MainType) + "_enum.go"
} else if outputGo == "-" {
util.Stdout = os.Stderr // avoiding interleaving with the output of generated code
}
if outputJSON == "" {
outputJSON = strings.ToLower(config.MainType) + "_enum.json"
}
if config.Simple {
config.IgnoreCase = false
config.Lenient = false
}
util.Debug("type=%s\n", config.MainType)
util.Debug("plural=%s\n", config.Plural)
util.Debug("inputGo=%s\n", inputGo)
util.Debug("outputGo=%s\n", outputGo)
util.Debug("outputJSON=%s\n", outputJSON)
if force || notUpToDate() {
generate()
}
}