diff --git a/README.md b/README.md index ff00948..1ce1548 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ 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 the `transform`, `trimprefix` and `autotrimprefix` flags +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. @@ -112,8 +112,6 @@ The default value for `transform` flag is `noop` which means no transformation w 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. -If the `autotrimprefix` flag is set then if all the names in an enum have a common prefix that prefix will be removed. - ## 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 d016548..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. @@ -751,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" @@ -779,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 9c36959..b257965 100644 --- a/stringer.go +++ b/stringer.go @@ -94,7 +94,6 @@ var ( 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: \"\"") - autoTrimPrefix = flag.Bool("autotrimprefix", false, "if true, remove a common prefix from each item name. Default: false") ) // Usage is a replacement usage function for the flags package. @@ -157,7 +156,7 @@ func main() { // Run generate for each type. for _, typeName := range types { - g.generate(typeName, *json, *yaml, *sql, *transformMethod, *trimPrefix, *autoTrimPrefix) + g.generate(typeName, *json, *yaml, *sql, *transformMethod, *trimPrefix) } // Format the output. @@ -308,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, trimPrefix string, autoTrimPrefix bool) { +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. @@ -327,10 +333,6 @@ func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeS g.trimValueNames(values, trimPrefix) - if autoTrimPrefix { - g.autoTrimValueNames(values) - } - g.transformValueNames(values, transformMethod) runs := splitIntoRuns(values) diff --git a/trim.go b/trim.go deleted file mode 100644 index 2fb2af0..0000000 --- a/trim.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import "strings" - -func longestCommonPrefix(values []Value) string { - // LCP of min and max (lexigraphically) - // is the LCP of the whole set. - min := values[0].name - max := min - for _, s := range values[1:] { - switch { - case s.name < min: - min = s.name - case s.name > max: - max = s.name - } - } - for i := 0; i < len(min) && i < len(max); i++ { - if min[i] != max[i] { - return min[:i] - } - } - // If all the bytes are equal but the lengths aren't then - // min is a prefix of max, and hence the lcp - return min -} - -func autoPrefix(values []Value) string { - // Can't trim a single value - if len(values) < 2 { - return "" - } - prefix := longestCommonPrefix(values) - - return prefix -} - -func (g *Generator) trimValueNames(values []Value, prefix string) { - for i := range values { - values[i].name = strings.TrimPrefix(values[i].name, prefix) - } -} - -func (g *Generator) autoTrimValueNames(values []Value) { - prefix := autoPrefix(values) - g.trimValueNames(values, prefix) -} diff --git a/trim_test.go b/trim_test.go deleted file mode 100644 index d1b79e6..0000000 --- a/trim_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import "testing" - -var lcpTests = []struct { - expected string - in []string -}{ - {"Proto", []string{"ProtoOne", "ProtoTwo", "ProtoThree"}}, - // An empty string is OK when one value is the prefix - {"Proto", []string{"Proto", "ProtoLonger"}}, - {"", []string{}}, - {"", []string{"aardvark"}}, - {"", []string{"abc", "def", "deg"}}, - {"ab", []string{"ab", "abc", "abcd"}}, -} - -// TestLcp checks that the longest common prefix is generated correctly -func TestLcp(t *testing.T) { - for _, tt := range lcpTests { - values := make([]Value, len(tt.in)) - for i := range tt.in { - values[i] = Value{ - name: tt.in[i], - } - } - prefix := autoPrefix(values) - if prefix != tt.expected { - t.Errorf("%q => %s, expected %s", tt.in, tt.expected, prefix) - } - } -}