-
Notifications
You must be signed in to change notification settings - Fork 3
/
adjnoun.go
158 lines (137 loc) · 4.29 KB
/
adjnoun.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package randname
import (
"bytes"
"crypto/rand"
"fmt"
"io"
"math/big"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"sync"
"github.com/marstr/collection"
)
// AdjNounFormat is a type of function that aggregates an Adjective, Noun, and Digit into a single formatted string.
type AdjNounFormat func(string, string, int) string
// AdjNoun creates a random name of the form adjectiveNameDigit
type AdjNoun struct {
Adjectives *collection.Dictionary
Format AdjNounFormat
Nouns *collection.Dictionary
RandGenerator io.Reader
}
// NewAdjNoun creates a new instance of AdjNoun that is populated with all of the defaults.
func NewAdjNoun() *AdjNoun {
return &AdjNoun{
RandGenerator: rand.Reader,
Format: GeneratePascalCaseAdjNoun,
}
}
func defaultBuilder(subPath string) func() *collection.Dictionary {
_, callerFile, _, _ := runtime.Caller(0)
// try to be as flexible as possible about how folks have included this library and still have default libraries populated.
searchLocations := []string{
subPath,
path.Base(subPath),
path.Join(filepath.Dir(callerFile), subPath),
}
var loader sync.Once
defaultDictionary := &collection.Dictionary{}
return func() *collection.Dictionary {
loader.Do(func() {
var targetFile string
for _, loc := range searchLocations {
if _, err := os.Stat(loc); err == nil {
targetFile = loc
break
}
}
reader := FileDictionaryBuilder{
Target: targetFile,
}
reader.Build(defaultDictionary)
})
return defaultDictionary
}
}
var getDefaultAdjectives = defaultBuilder("adjectives.txt")
var getDefaultNouns = defaultBuilder("nouns.txt")
// generate fetches a random name of the default format and strategy.
func Generate() string {
return AdjNoun{}.Generate()
}
// Generate creates a new randomly generated name with the
func (adNoun AdjNoun) Generate() string {
if adNoun.Format == nil {
adNoun.Format = GeneratePascalCaseAdjNoun
}
return adNoun.Format(adNoun.getAdjective(), adNoun.getNoun(), adNoun.getDigit())
}
func (adNoun AdjNoun) getAdjective() string {
if adNoun.Adjectives == nil {
adNoun.Adjectives = getDefaultAdjectives()
}
if collection.Any(adNoun.Adjectives) {
if adNoun.RandGenerator == nil {
adNoun.RandGenerator = rand.Reader
}
randomLocation, _ := rand.Int(adNoun.RandGenerator, big.NewInt(adNoun.Adjectives.Size()))
return collection.ElementAt(adNoun.Adjectives, uint(randomLocation.Uint64())).(string)
}
return ""
}
func (adNoun AdjNoun) getNoun() string {
if adNoun.Nouns == nil {
adNoun.Nouns = getDefaultNouns()
}
if collection.Any(adNoun.Nouns) {
if adNoun.RandGenerator == nil {
adNoun.RandGenerator = rand.Reader
}
position, _ := rand.Int(adNoun.RandGenerator, big.NewInt(adNoun.Nouns.Size()))
return collection.ElementAt(adNoun.Nouns, uint(position.Uint64())).(string)
}
return ""
}
func (adNoun AdjNoun) getDigit() int {
if adNoun.RandGenerator == nil {
adNoun.RandGenerator = rand.Reader
}
result, _ := rand.Int(adNoun.RandGenerator, big.NewInt(100))
return int(result.Int64())
}
// GenerateCamelCaseAdjNoun formats an adjective, noun, and digit in the following way: bigCloud9
func GenerateCamelCaseAdjNoun(adjective, noun string, digit int) string {
pascal := GeneratePascalCaseAdjNoun(adjective, noun, digit)
return strings.ToLower(pascal[:1]) + pascal[1:]
}
// GeneratePascalCaseAdjNoun formats an adjective, noun, and digit in the following way: BigCloud9
func GeneratePascalCaseAdjNoun(adjective, noun string, digit int) string {
builder := bytes.Buffer{}
if len(adjective) > 0 {
builder.WriteString(strings.ToUpper(adjective[:1]))
builder.WriteString(strings.ToLower(adjective[1:]))
}
if len(noun) > 0 {
builder.WriteString(strings.ToUpper(noun[:1]))
builder.WriteString(strings.ToLower(noun[1:]))
}
builder.WriteString(fmt.Sprintf("%02d", digit))
return builder.String()
}
// GenerateHyphenedAdjNoun formats an adjective, noun, and digit in the following way: big-cloud-9
func GenerateHyphenedAdjNoun(adjective, noun string, digit int) string {
builder := bytes.Buffer{}
if len(adjective) > 0 {
builder.WriteString(strings.ToLower(adjective))
}
builder.WriteRune('-')
if len(adjective) > 0 {
builder.WriteString(strings.ToLower(noun))
}
builder.WriteRune('-')
builder.WriteString(fmt.Sprintf("%02d", digit))
return builder.String()
}