@@ -6,10 +6,22 @@ import (
66 "math/rand"
77 "strings"
88 "time"
9+
10+ "golang.org/x/text/cases"
11+ "golang.org/x/text/language"
12+ )
13+
14+ type Casing string
15+
16+ const (
17+ Lower Casing = "lower"
18+ Upper Casing = "upper"
19+ Title Casing = "title"
920)
1021
1122// Generator is a random name generator.
1223type Generator struct {
24+ casing Casing
1325 dict * Dictionary
1426 delimiter string
1527 rand * rand.Rand
@@ -19,61 +31,100 @@ type Generator struct {
1931// GeneratorOption is a function that configures a Generator.
2032type GeneratorOption func (* Generator )
2133
34+ // WithCasing sets the casing used to format the generated name.
35+ func WithCasing (casing Casing ) GeneratorOption {
36+ return func (g * Generator ) {
37+ g .casing = casing
38+ }
39+ }
40+
2241// WithDelimiter sets the delimiter used to join words.
2342func WithDelimiter (delimiter string ) GeneratorOption {
24- return func (r * Generator ) {
25- r .delimiter = delimiter
43+ return func (g * Generator ) {
44+ g .delimiter = delimiter
2645 }
2746}
2847
2948// WithSeed sets the seed used to generate random numbers.
3049func WithSeed (seed int64 ) GeneratorOption {
31- return func (r * Generator ) {
32- r .rand .Seed (seed )
50+ return func (g * Generator ) {
51+ g .rand .Seed (seed )
3352 }
3453}
3554
3655// WithSize sets the number of words in the generated name.
3756func WithSize (size uint ) GeneratorOption {
38- return func (r * Generator ) {
39- r .size = size
57+ return func (g * Generator ) {
58+ g .size = size
4059 }
4160}
4261
4362// NewGenerator creates a new Generator.
4463func NewGenerator (opts ... GeneratorOption ) * Generator {
45- r := & Generator {
64+ g := & Generator {
65+ casing : Lower ,
4666 dict : NewDictionary (),
4767 delimiter : "-" ,
4868 rand : rand .New (rand .NewSource (time .Now ().UnixNano ())),
4969 size : 2 ,
5070 }
5171 for _ , opt := range opts {
52- opt (r )
72+ opt (g )
5373 }
54- return r
74+ return g
5575}
5676
5777// Generate generates a random name.
58- func (r * Generator ) Generate () (string , error ) {
78+ func (g * Generator ) Generate () (string , error ) {
5979 // TODO: address case where adjective and noun are the same, such as "orange-orange" or "sound-sound"
60- adjective := r .dict .adectives [r .rand .Intn (r .dict .LengthAdjective ())]
61- noun := r .dict .nouns [r .rand .Intn (r .dict .LengthNoun ())]
80+ adjective := g .dict .adectives [g .rand .Intn (g .dict .LengthAdjective ())]
81+ noun := g .dict .nouns [g .rand .Intn (g .dict .LengthNoun ())]
6282 words := []string {adjective , noun }
6383
64- switch r .size {
84+ switch g .size {
6585 case 2 :
66- return strings . Join ( words , r . delimiter ), nil
86+ // do nothing
6787 case 3 :
68- verb := r .dict .verbs [r .rand .Intn (r .dict .LengthVerb ())]
88+ verb := g .dict .verbs [g .rand .Intn (g .dict .LengthVerb ())]
6989 words = append (words , verb )
7090 case 4 :
71- verb := r .dict .verbs [r .rand .Intn (r .dict .LengthVerb ())]
91+ verb := g .dict .verbs [g .rand .Intn (g .dict .LengthVerb ())]
7292 words = append (words , verb )
73- adverb := r .dict .adverbs [r .rand .Intn (r .dict .LengthAdverb ())]
93+ adverb := g .dict .adverbs [g .rand .Intn (g .dict .LengthAdverb ())]
7494 words = append (words , adverb )
7595 default :
76- return "" , fmt .Errorf ("invalid size: %d" , r .size )
96+ return "" , fmt .Errorf ("invalid size: %d" , g .size )
97+ }
98+ return strings .Join (g .applyCasing (words ... ), g .delimiter ), nil
99+ }
100+
101+ // ParseCasing parses a string into a casing.
102+ func ParseCasing (casing string ) (Casing , error ) {
103+ switch casing {
104+ case "lower" :
105+ return Lower , nil
106+ case "upper" :
107+ return Upper , nil
108+ case "title" :
109+ return Title , nil
110+ default :
111+ return "" , fmt .Errorf ("invalid casing: %s" , casing )
112+ }
113+ }
114+
115+ var titleCaser = cases .Title (language .English )
116+
117+ var casingMap = map [Casing ]func (string ) string {
118+ Lower : strings .ToLower ,
119+ Upper : strings .ToUpper ,
120+ Title : titleCaser .String ,
121+ }
122+
123+ func (g * Generator ) applyCasing (words ... string ) []string {
124+ if fn , ok := casingMap [g .casing ]; ok {
125+ for i , word := range words {
126+ words [i ] = fn (word )
127+ }
77128 }
78- return strings . Join ( words , r . delimiter ), nil
129+ return words
79130}
0 commit comments