Skip to content

Commit 1e2c502

Browse files
committed
feat: Add -casesensitive flag
Fixes #40
1 parent bcbe617 commit 1e2c502

File tree

3 files changed

+69
-43
lines changed

3 files changed

+69
-43
lines changed

enumer.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ func %[1]sString(s string) (%[1]s, error) {
1818
}
1919
`
2020

21+
// Arguments to format are:
22+
// [1]: type name
23+
const stringNameToValueMethodCaseSensitive = `// %[1]sString retrieves an enum value from the enum constants string name.
24+
// Throws an error if the param is not part of the enum.
25+
func %[1]sString(s string) (%[1]s, error) {
26+
if val, ok := _%[1]sNameToValueMap[s]; ok {
27+
return val, nil
28+
}
29+
return 0, fmt.Errorf("%%s does not belong to %[1]s values", s)
30+
}
31+
`
32+
2133
// Arguments to format are:
2234
// [1]: type name
2335
const stringValuesMethod = `// %[1]sValues returns all values of the enum
@@ -70,7 +82,7 @@ func (g *Generator) buildAltStringValuesMethod(typeName string) {
7082
g.Printf(altStringValuesMethod, typeName)
7183
}
7284

73-
func (g *Generator) buildBasicExtras(runs [][]Value, typeName string, runsThreshold int) {
85+
func (g *Generator) buildBasicExtras(runs [][]Value, typeName string, runsThreshold int, caseSensitive bool) {
7486
// At this moment, either "g.declareIndexAndNameVars()" or "g.declareNameVars()" has been called
7587

7688
// Print the slice of values
@@ -83,13 +95,17 @@ func (g *Generator) buildBasicExtras(runs [][]Value, typeName string, runsThresh
8395
g.Printf("}\n\n")
8496

8597
// Print the map between name and value
86-
g.printValueMap(runs, typeName, runsThreshold)
98+
g.printValueMap(runs, typeName, runsThreshold, caseSensitive)
8799

88100
// Print the slice of names
89101
g.printNamesSlice(runs, typeName, runsThreshold)
90102

91103
// Print the basic extra methods
92-
g.Printf(stringNameToValueMethod, typeName)
104+
if caseSensitive {
105+
g.Printf(stringNameToValueMethodCaseSensitive, typeName)
106+
} else {
107+
g.Printf(stringNameToValueMethod, typeName)
108+
}
93109
g.Printf(stringValuesMethod, typeName)
94110
g.Printf(stringsMethod, typeName)
95111
if len(runs) <= runsThreshold {
@@ -99,7 +115,7 @@ func (g *Generator) buildBasicExtras(runs [][]Value, typeName string, runsThresh
99115
}
100116
}
101117

102-
func (g *Generator) printValueMap(runs [][]Value, typeName string, runsThreshold int) {
118+
func (g *Generator) printValueMap(runs [][]Value, typeName string, runsThreshold int, caseSensitive bool) {
103119
thereAreRuns := len(runs) > 1 && len(runs) <= runsThreshold
104120
g.Printf("\nvar _%sNameToValueMap = map[string]%s{\n", typeName, typeName)
105121

@@ -115,7 +131,9 @@ func (g *Generator) printValueMap(runs [][]Value, typeName string, runsThreshold
115131

116132
for _, value := range values {
117133
g.Printf("\t_%sName%s[%d:%d]: %s,\n", typeName, runID, n, n+len(value.name), value.originalName)
118-
g.Printf("\t_%sLowerName%s[%d:%d]: %s,\n", typeName, runID, n, n+len(value.name), value.originalName)
134+
if !caseSensitive {
135+
g.Printf("\t_%sLowerName%s[%d:%d]: %s,\n", typeName, runID, n, n+len(value.name), value.originalName)
136+
}
119137
n += len(value.name)
120138
}
121139
}

golden_test.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -315,45 +315,45 @@ const (
315315

316316
func TestGolden(t *testing.T) {
317317
for _, test := range golden {
318-
runGoldenTest(t, test, false, false, false, false, false, false, true, "", "")
318+
runGoldenTest(t, test, false, false, false, false, false, false, true, false, "", "")
319319
}
320320
for _, test := range goldenJSON {
321-
runGoldenTest(t, test, true, false, false, false, false, false, false, "", "")
321+
runGoldenTest(t, test, true, false, false, false, false, false, false, false, "", "")
322322
}
323323
for _, test := range goldenText {
324-
runGoldenTest(t, test, false, false, false, true, false, false, false, "", "")
324+
runGoldenTest(t, test, false, false, false, true, false, false, false, false, "", "")
325325
}
326326
for _, test := range goldenYAML {
327-
runGoldenTest(t, test, false, true, false, false, false, false, false, "", "")
327+
runGoldenTest(t, test, false, true, false, false, false, false, false, false, "", "")
328328
}
329329
for _, test := range goldenSQL {
330-
runGoldenTest(t, test, false, false, true, false, false, false, false, "", "")
330+
runGoldenTest(t, test, false, false, true, false, false, false, false, false, "", "")
331331
}
332332
for _, test := range goldenJSONAndSQL {
333-
runGoldenTest(t, test, true, false, true, false, false, false, false, "", "")
333+
runGoldenTest(t, test, true, false, true, false, false, false, false, false, "", "")
334334
}
335335
for _, test := range goldenGQLGen {
336-
runGoldenTest(t, test, false, false, false, false, false, true, false, "", "")
336+
runGoldenTest(t, test, false, false, false, false, false, true, false, false, "", "")
337337
}
338338
for _, test := range goldenTrimPrefix {
339-
runGoldenTest(t, test, false, false, false, false, false, false, false, "Day", "")
339+
runGoldenTest(t, test, false, false, false, false, false, false, false, false, "Day", "")
340340
}
341341
for _, test := range goldenTrimPrefixMultiple {
342-
runGoldenTest(t, test, false, false, false, false, false, false, false, "Day,Night", "")
342+
runGoldenTest(t, test, false, false, false, false, false, false, false, false, "Day,Night", "")
343343
}
344344
for _, test := range goldenWithPrefix {
345-
runGoldenTest(t, test, false, false, false, false, false, false, false, "", "Day")
345+
runGoldenTest(t, test, false, false, false, false, false, false, false, false, "", "Day")
346346
}
347347
for _, test := range goldenTrimAndAddPrefix {
348-
runGoldenTest(t, test, false, false, false, false, false, false, false, "Day", "Night")
348+
runGoldenTest(t, test, false, false, false, false, false, false, false, false, "Day", "Night")
349349
}
350350
for _, test := range goldenLinecomment {
351-
runGoldenTest(t, test, false, false, false, false, true, false, false, "", "")
351+
runGoldenTest(t, test, false, false, false, false, true, false, false, false, "", "")
352352
}
353353
}
354354

355355
func runGoldenTest(t *testing.T, test Golden,
356-
generateJSON, generateYAML, generateSQL, generateText, linecomment, generateGQLGen, generateValuesMethod bool,
356+
generateJSON, generateYAML, generateSQL, generateText, linecomment, generateGQLGen, generateValuesMethod, caseSensitive bool,
357357
trimPrefix string, prefix string) {
358358

359359
var g Generator
@@ -382,7 +382,7 @@ func runGoldenTest(t *testing.T, test Golden,
382382
if len(tokens) != 3 {
383383
t.Fatalf("%s: need type declaration on first line", test.name)
384384
}
385-
g.generate(tokens[1], generateJSON, generateYAML, generateSQL, generateText, generateGQLGen, "noop", trimPrefix, prefix, linecomment, generateValuesMethod)
385+
g.generate(tokens[1], generateJSON, generateYAML, generateSQL, generateText, generateGQLGen, "noop", trimPrefix, prefix, linecomment, generateValuesMethod, caseSensitive)
386386
got := string(g.format())
387387
if got != loadGolden(test.name) {
388388
// Use this to help build a golden text when changes are needed

stringer.go

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ var (
5656
trimPrefix = flag.String("trimprefix", "", "transform each item name by removing a prefix or comma separated list of prefixes. Default: \"\"")
5757
addPrefix = flag.String("addprefix", "", "transform each item name by adding a prefix. Default: \"\"")
5858
linecomment = flag.Bool("linecomment", false, "use line comment text as printed text when present")
59+
caseSensitive = flag.Bool("casesensitive", false, "preserve case when creating a value from a string")
5960
)
6061

6162
var comments arrayFlags
@@ -135,7 +136,7 @@ func main() {
135136

136137
// Run generate for each type.
137138
for _, typeName := range typs {
138-
g.generate(typeName, *json, *yaml, *sql, *text, *gqlgen, *transformMethod, *trimPrefix, *addPrefix, *linecomment, *altValuesFunc)
139+
g.generate(typeName, *json, *yaml, *sql, *text, *gqlgen, *transformMethod, *trimPrefix, *addPrefix, *linecomment, *altValuesFunc, *caseSensitive)
139140
}
140141

141142
// Format the output.
@@ -415,7 +416,8 @@ func (g *Generator) prefixValueNames(values []Value, prefix string) {
415416
// generate produces the String method for the named type.
416417
func (g *Generator) generate(typeName string,
417418
includeJSON, includeYAML, includeSQL, includeText, includeGQLGen bool,
418-
transformMethod string, trimPrefix string, addPrefix string, lineComment bool, includeValuesMethod bool) {
419+
transformMethod string, trimPrefix string, addPrefix string, lineComment bool, includeValuesMethod bool,
420+
caseSensitive bool) {
419421
values := make([]Value, 0, 100)
420422
for _, file := range g.pkg.files {
421423
file.lineComment = lineComment
@@ -456,19 +458,19 @@ func (g *Generator) generate(typeName string,
456458
const runsThreshold = 10
457459
switch {
458460
case len(runs) == 1:
459-
g.buildOneRun(runs, typeName)
461+
g.buildOneRun(runs, typeName, caseSensitive)
460462
case len(runs) <= runsThreshold:
461-
g.buildMultipleRuns(runs, typeName)
463+
g.buildMultipleRuns(runs, typeName, caseSensitive)
462464
default:
463-
g.buildMap(runs, typeName)
465+
g.buildMap(runs, typeName, caseSensitive)
464466
}
465467
if includeValuesMethod {
466468
g.buildAltStringValuesMethod(typeName)
467469
}
468470

469471
g.buildNoOpOrderChangeDetect(runs, typeName)
470472

471-
g.buildBasicExtras(runs, typeName, runsThreshold)
473+
g.buildBasicExtras(runs, typeName, runsThreshold, caseSensitive)
472474
if includeJSON {
473475
g.buildJSONMethods(runs, typeName, runsThreshold)
474476
}
@@ -663,14 +665,16 @@ func usize(n int) int {
663665

664666
// declareIndexAndNameVars declares the index slices and concatenated names
665667
// strings representing the runs of values.
666-
func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {
668+
func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string, caseSensitive bool) {
667669
var indexes, names []string
668670
for i, run := range runs {
669671
index, n := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
670672
indexes = append(indexes, index)
671673
names = append(names, n)
672-
_, n = g.createLowerIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
673-
names = append(names, n)
674+
if !caseSensitive {
675+
_, n = g.createLowerIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
676+
names = append(names, n)
677+
}
674678
}
675679
g.Printf("const (\n")
676680
for _, n := range names {
@@ -685,12 +689,14 @@ func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {
685689
}
686690

687691
// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars
688-
func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) {
692+
func (g *Generator) declareIndexAndNameVar(run []Value, typeName string, caseSensitive bool) {
689693
index, n := g.createIndexAndNameDecl(run, typeName, "")
690694
g.Printf("const %s\n", n)
691695
g.Printf("var %s\n", index)
692-
index, n = g.createLowerIndexAndNameDecl(run, typeName, "")
693-
g.Printf("const %s\n", n)
696+
if !caseSensitive {
697+
index, n = g.createLowerIndexAndNameDecl(run, typeName, "")
698+
g.Printf("const %s\n", n)
699+
}
694700
//g.Printf("var %s\n", index)
695701
}
696702

@@ -739,28 +745,30 @@ func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix
739745
}
740746

741747
// declareNameVars declares the concatenated names string representing all the values in the runs.
742-
func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) {
748+
func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string, caseSensitive bool) {
743749
g.Printf("const _%sName%s = \"", typeName, suffix)
744750
for _, run := range runs {
745751
for i := range run {
746752
g.Printf("%s", run[i].name)
747753
}
748754
}
749755
g.Printf("\"\n")
750-
g.Printf("const _%sLowerName%s = \"", typeName, suffix)
751-
for _, run := range runs {
752-
for i := range run {
753-
g.Printf("%s", strings.ToLower(run[i].name))
756+
if !caseSensitive {
757+
g.Printf("const _%sLowerName%s = \"", typeName, suffix)
758+
for _, run := range runs {
759+
for i := range run {
760+
g.Printf("%s", strings.ToLower(run[i].name))
761+
}
754762
}
763+
g.Printf("\"\n")
755764
}
756-
g.Printf("\"\n")
757765
}
758766

759767
// buildOneRun generates the variables and String method for a single run of contiguous values.
760-
func (g *Generator) buildOneRun(runs [][]Value, typeName string) {
768+
func (g *Generator) buildOneRun(runs [][]Value, typeName string, caseSensitive bool) {
761769
values := runs[0]
762770
g.Printf("\n")
763-
g.declareIndexAndNameVar(values, typeName)
771+
g.declareIndexAndNameVar(values, typeName, caseSensitive)
764772
// The generated code is simple enough to write as a Printf format.
765773
lessThanZero := ""
766774
if values[0].signed {
@@ -801,9 +809,9 @@ const stringOneRunWithOffset = `func (i %[1]s) String() string {
801809

802810
// buildMultipleRuns generates the variables and String method for multiple runs of contiguous values.
803811
// For this pattern, a single Printf format won't do.
804-
func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) {
812+
func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string, caseSensitive bool) {
805813
g.Printf("\n")
806-
g.declareIndexAndNameVars(runs, typeName)
814+
g.declareIndexAndNameVars(runs, typeName, caseSensitive)
807815
g.Printf("func (i %s) String() string {\n", typeName)
808816
g.Printf("\tswitch {\n")
809817
for i, values := range runs {
@@ -827,9 +835,9 @@ func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) {
827835

828836
// buildMap handles the case where the space is so sparse a map is a reasonable fallback.
829837
// It's a rare situation but has simple code.
830-
func (g *Generator) buildMap(runs [][]Value, typeName string) {
838+
func (g *Generator) buildMap(runs [][]Value, typeName string, caseSensitive bool) {
831839
g.Printf("\n")
832-
g.declareNameVars(runs, typeName, "")
840+
g.declareNameVars(runs, typeName, "", caseSensitive)
833841
g.Printf("\nvar _%sMap = map[%s]string{\n", typeName, typeName)
834842
n := 0
835843
for _, values := range runs {

0 commit comments

Comments
 (0)