internal/cldrtree: add EnumFunc option

Change-Id: I12d61cb1e67da1e682b9a3a04826988d8c0b7cd0
Reviewed-on: https://go-review.googlesource.com/73010
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/internal/cldrtree/cldrtree_test.go b/internal/cldrtree/cldrtree_test.go
index 6907ee6..232fb46 100644
--- a/internal/cldrtree/cldrtree_test.go
+++ b/internal/cldrtree/cldrtree_test.go
@@ -12,6 +12,7 @@
 	"path/filepath"
 	"reflect"
 	"regexp"
+	"strings"
 	"testing"
 
 	"golang.org/x/text/internal/gen"
@@ -326,9 +327,18 @@
 	}
 
 	context := Enum("context")
-	// Align era with width values.
-	width := Enum("width", "abbreviated", "narrow", "wide")
-	eraType := Enum("era", "eraAbbr", "eraNarrow", "eraNames")
+	widthMap := func(s string) string {
+		// Align era with width values.
+		if r, ok := map[string]string{
+			"eraAbbr":   "abbreviated",
+			"eraNarrow": "narrow",
+			"eraNames":  "wide",
+		}[s]; ok {
+			s = r
+		}
+		return "w" + strings.Title(s)
+	}
+	width := EnumFunc("width", widthMap, "abbreviated", "narrow", "wide")
 	r := rand.New(rand.NewSource(0))
 
 	for _, loc := range data.Locales() {
@@ -364,7 +374,7 @@
 					}
 				}
 				if x := x.Index(cal.Eras); x != nil {
-					opts := []Option{eraType, SharedType()}
+					opts := []Option{width, SharedType()}
 					if x := x.Index(cal.Eras.EraNames, opts...); x != nil {
 						for _, e := range cal.Eras.EraNames.Era {
 							x.IndexFromAlt(e).SetValue(e.Type, e)
diff --git a/internal/cldrtree/option.go b/internal/cldrtree/option.go
index 069d560..f91e250 100644
--- a/internal/cldrtree/option.go
+++ b/internal/cldrtree/option.go
@@ -43,7 +43,12 @@
 // position (starting at 0). Other values may still be added and will be
 // assigned to subsequent values.
 func Enum(name string, value ...string) Option {
-	enum := &enum{name: name, keyMap: map[string]enumIndex{}}
+	return EnumFunc(name, nil, value...)
+}
+
+// EnumFunc is like Enum but also takes a function that allows rewriting keys.
+func EnumFunc(name string, rename func(string) string, value ...string) Option {
+	enum := &enum{name: name, rename: rename, keyMap: map[string]enumIndex{}}
 	for _, e := range value {
 		enum.lookup(e)
 	}
@@ -62,13 +67,6 @@
 	}
 }
 
-// TODO:
-// // RenameFunc renames enum values. This is mostly used to sanitize enum values
-// // to make them proper identifiers.
-// func RenameFunc(rename func(string) string) Option {
-// 	return nil
-// }
-
 // SharedType returns an option which causes all Indexes to which this option is
 // passed to have the same type.
 func SharedType() Option {
diff --git a/internal/cldrtree/testdata/test1/output.go b/internal/cldrtree/testdata/test1/output.go
index 1a03679..effda4c 100755
--- a/internal/cldrtree/testdata/test1/output.go
+++ b/internal/cldrtree/testdata/test1/output.go
@@ -11,9 +11,9 @@
 //   - format
 //   - stand-alone
 // <width>
-//   - abbreviated
-//   - narrow
-//   - wide
+//   - wAbbreviated
+//   - wNarrow
+//   - wWide
 //
 // - calendars
 //   - chinese
@@ -43,9 +43,9 @@
 type width int
 
 const (
-	abbreviated width = iota
-	narrow
-	wide
+	wAbbreviated width = iota
+	wNarrow
+	wWide
 )
 
 var locales = []uint32{ // 754 elements
diff --git a/internal/cldrtree/testdata/test2/output.go b/internal/cldrtree/testdata/test2/output.go
index 469d065..aea79c8 100755
--- a/internal/cldrtree/testdata/test2/output.go
+++ b/internal/cldrtree/testdata/test2/output.go
@@ -7,17 +7,13 @@
 var tree = &cldrtree.Tree{locales, indices, buckets}
 
 // Path values:
-// <era>
-//   - eraAbbr
-//   - eraNarrow
-//   - eraNames
+// <width>
+//   - wAbbreviated
+//   - wNarrow
+//   - wWide
 // <context>
 //   - format
 //   - stand-alone
-// <width>
-//   - abbreviated
-//   - narrow
-//   - wide
 //
 // - calendars
 //   - buddhist
@@ -40,7 +36,7 @@
 //           - 1..13
 //           - 7leap
 //     - eras
-//       - <era>
+//       - <width>
 //         - ""
 //         - variant
 //           - 0..1
@@ -79,13 +75,13 @@
 // total string size:  9931
 // bucket waste:       0
 
-// era specifies a property of a CLDR field.
-type era int
+// width specifies a property of a CLDR field.
+type width int
 
 const (
-	eraAbbr era = iota
-	eraNarrow
-	eraNames
+	wAbbreviated width = iota
+	wNarrow
+	wWide
 )
 
 // context specifies a property of a CLDR field.
@@ -96,15 +92,6 @@
 	standAlone
 )
 
-// width specifies a property of a CLDR field.
-type width int
-
-const (
-	abbreviated width = iota
-	narrow
-	wide
-)
-
 var locales = []uint32{ // 754 elements
 	// Entry 0 - 1F
 	0x00000000, 0x00000000, 0x0000026b, 0x00000000,
diff --git a/internal/cldrtree/type.go b/internal/cldrtree/type.go
index b0809ab..a7897c6 100644
--- a/internal/cldrtree/type.go
+++ b/internal/cldrtree/type.go
@@ -10,6 +10,7 @@
 // An enum is a collection of enum values.
 type enum struct {
 	name   string // the Go type of the enum
+	rename func(string) string
 	keyMap map[string]enumIndex
 	keys   []string
 }
@@ -17,6 +18,9 @@
 // lookup returns the index for the enum corresponding to the string. If s
 // currently does not exist it will add the entry.
 func (e *enum) lookup(s string) enumIndex {
+	if e.rename != nil {
+		s = e.rename(s)
+	}
 	x, ok := e.keyMap[s]
 	if !ok {
 		if e.keyMap == nil {
@@ -49,7 +53,7 @@
 		}
 	}
 	if opts.sharedEnums != nil && t.enum != opts.sharedEnums {
-		panic("incompatible enumss defined")
+		panic("incompatible enums defined")
 	}
 	x = t.enum.lookup(s)
 	if t.entries == nil {