diff --git a/README.md b/README.md index 3463ad3..1ce1548 100644 --- a/README.md +++ b/README.md @@ -104,10 +104,14 @@ the JSON related methods will be generated. Similarly if the yaml flag is set to the YAML related methods will be generated. And if the sql flag is set to true, the Scanner and Valuer interface will be implemented to seamlessly use the enum in a database model. -For enum string representation transformation `transform` flag was added (i.e. `enumer -type=MyType -json -transform=snake`). -Possible values are `snake` and `kebab` for transformation to snake_case and kebab-case accordingly. +For enum string representation transformation the `transform` and `trimprefix` flags +were added (i.e. `enumer -type=MyType -json -transform=snake`). +Possible transform values are `snake` and `kebab` for transformation to snake_case and kebab-case accordingly. The default value for `transform` flag is `noop` which means no transformation will be performed. +If a prefix is provided via the `trimprefix` flag that will be trimmed from the start of each name (before +it is transformed). If a name doesn't have the prefix it will be passed unchanged. + ## Inspiring projects * [Stringer](https://godoc.org/golang.org/x/tools/cmd/stringer) * [jsonenums](https://github.com/campoy/jsonenums) diff --git a/golden_test.go b/golden_test.go index ce5651f..1d1ac46 100644 --- a/golden_test.go +++ b/golden_test.go @@ -46,6 +46,10 @@ var goldenJSONAndSQL = []Golden{ {"prime", prime_json_and_sql_in, prime_json_and_sql_out}, } +var goldenPrefix = []Golden{ + {"prefix", prefix_in, day_out}, +} + // Each example starts with "type XXX [u]int", with a single space separating them. // Simple test: enumeration of type int starting at 0. @@ -83,6 +87,8 @@ var _DayNameToValueMap = map[string]Day{ _DayName[44:50]: 6, } +// DayString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. func DayString(s string) (Day, error) { if val, ok := _DayNameToValueMap[s]; ok { return val, nil @@ -122,6 +128,8 @@ var _NumberNameToValueMap = map[string]Number{ _NumberName[6:11]: 3, } +// NumberString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. func NumberString(s string) (Number, error) { if val, ok := _NumberNameToValueMap[s]; ok { return val, nil @@ -183,6 +191,8 @@ var _GapNameToValueMap = map[string]Gap{ _GapName_2[0:6]: 11, } +// GapString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. func GapString(s string) (Gap, error) { if val, ok := _GapNameToValueMap[s]; ok { return val, nil @@ -223,6 +233,8 @@ var _NumNameToValueMap = map[string]Num{ _NumName[10:12]: 2, } +// NumString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. func NumString(s string) (Num, error) { if val, ok := _NumNameToValueMap[s]; ok { return val, nil @@ -276,6 +288,8 @@ var _UnumNameToValueMap = map[string]Unum{ _UnumName_1[3:6]: 254, } +// UnumString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. func UnumString(s string) (Unum, error) { if val, ok := _UnumNameToValueMap[s]; ok { return val, nil @@ -347,6 +361,8 @@ var _PrimeNameToValueMap = map[string]Prime{ _PrimeName[32:35]: 43, } +// PrimeString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. func PrimeString(s string) (Prime, error) { if val, ok := _PrimeNameToValueMap[s]; ok { return val, nil @@ -415,6 +431,8 @@ var _PrimeNameToValueMap = map[string]Prime{ _PrimeName[32:35]: 43, } +// PrimeString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. func PrimeString(s string) (Prime, error) { if val, ok := _PrimeNameToValueMap[s]; ok { return val, nil @@ -499,6 +517,8 @@ var _PrimeNameToValueMap = map[string]Prime{ _PrimeName[32:35]: 43, } +// PrimeString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. func PrimeString(s string) (Prime, error) { if val, ok := _PrimeNameToValueMap[s]; ok { return val, nil @@ -583,6 +603,8 @@ var _PrimeNameToValueMap = map[string]Prime{ _PrimeName[32:35]: 43, } +// PrimeString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. func PrimeString(s string) (Prime, error) { if val, ok := _PrimeNameToValueMap[s]; ok { return val, nil @@ -680,6 +702,8 @@ var _PrimeNameToValueMap = map[string]Prime{ _PrimeName[32:35]: 43, } +// PrimeString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. func PrimeString(s string) (Prime, error) { if val, ok := _PrimeNameToValueMap[s]; ok { return val, nil @@ -731,25 +755,40 @@ func (i *Prime) Scan(value interface{}) error { } ` +const prefix_in = `type Day int +const ( + DayMonday Day = iota + DayTuesday + DayWednesday + DayThursday + DayFriday + DaySaturday + DaySunday +) +` + func TestGolden(t *testing.T) { for _, test := range golden { - runGoldenTest(t, test, false, false, false) + runGoldenTest(t, test, false, false, false, "") } for _, test := range goldenJSON { - runGoldenTest(t, test, true, false, false) + runGoldenTest(t, test, true, false, false, "") } for _, test := range goldenYAML { - runGoldenTest(t, test, false, true, false) + runGoldenTest(t, test, false, true, false, "") } for _, test := range goldenSQL { - runGoldenTest(t, test, false, false, true) + runGoldenTest(t, test, false, false, true, "") } for _, test := range goldenJSONAndSQL { - runGoldenTest(t, test, true, false, true) + runGoldenTest(t, test, true, false, true, "") + } + for _, test := range goldenPrefix { + runGoldenTest(t, test, false, false, false, "Day") } } -func runGoldenTest(t *testing.T, test Golden, generateJSON, generateYAML, generateSQL bool) { +func runGoldenTest(t *testing.T, test Golden, generateJSON, generateYAML, generateSQL bool, prefix string) { var g Generator input := "package test\n" + test.input file := test.name + ".go" @@ -759,7 +798,7 @@ func runGoldenTest(t *testing.T, test Golden, generateJSON, generateYAML, genera if len(tokens) != 3 { t.Fatalf("%s: need type declaration on first line", test.name) } - g.generate(tokens[1], generateJSON, generateYAML, generateSQL, "noop") + g.generate(tokens[1], generateJSON, generateYAML, generateSQL, "noop", prefix) got := string(g.format()) if got != test.output { t.Errorf("%s: got\n====\n%s====\nexpected\n====%s", test.name, got, test.output) diff --git a/stringer.go b/stringer.go index 0354caa..b257965 100644 --- a/stringer.go +++ b/stringer.go @@ -93,6 +93,7 @@ var ( yaml = flag.Bool("yaml", false, "if true, yaml marshaling methods will be generated. Default: false") output = flag.String("output", "", "output file name; default srcdir/_string.go") transformMethod = flag.String("transform", "noop", "enum item name transformation method. Default: noop") + trimPrefix = flag.String("trimprefix", "", "transform each item name by removing a prefix. Default: \"\"") ) // Usage is a replacement usage function for the flags package. @@ -155,7 +156,7 @@ func main() { // Run generate for each type. for _, typeName := range types { - g.generate(typeName, *json, *yaml, *sql, *transformMethod) + g.generate(typeName, *json, *yaml, *sql, *transformMethod, *trimPrefix) } // Format the output. @@ -306,8 +307,15 @@ func (g *Generator) transformValueNames(values []Value, transformMethod string) } } +// trimValueNames removes a prefix from each name +func (g *Generator) trimValueNames(values []Value, prefix string) { + for i := range values { + values[i].name = strings.TrimPrefix(values[i].name, prefix) + } +} + // generate produces the String method for the named type. -func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeSQL bool, transformMethod string) { +func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeSQL bool, transformMethod string, trimPrefix string) { values := make([]Value, 0, 100) for _, file := range g.pkg.files { // Set the state for this run of the walker. @@ -323,6 +331,8 @@ func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeS log.Fatalf("no values defined for type %s", typeName) } + g.trimValueNames(values, trimPrefix) + g.transformValueNames(values, transformMethod) runs := splitIntoRuns(values)