1
2
3
4 package ident
5
6 import (
7 "strings"
8 "unicode"
9 "unicode/utf8"
10 )
11
12
13
14
15 func ParseMixedCaps(name string) Name {
16 var words Name
17
18
19
20 runes := []rune(name)
21 w, i := 0, 0
22 for i+1 <= len(runes) {
23 eow := false
24 if i+1 == len(runes) {
25 eow = true
26 } else if unicode.IsLower(runes[i]) && unicode.IsUpper(runes[i+1]) {
27
28 eow = true
29 } else if i+2 < len(runes) && unicode.IsUpper(runes[i]) && unicode.IsUpper(runes[i+1]) && unicode.IsLower(runes[i+2]) {
30
31 eow = true
32
33 if string(runes[i:i+3]) == "IDs" {
34 eow = false
35 }
36 }
37 i++
38 if !eow {
39 continue
40 }
41
42
43 word := string(runes[w:i])
44 if initialism, ok := isInitialism(word); ok {
45 words = append(words, initialism)
46 } else if i1, i2, ok := isTwoInitialisms(word); ok {
47 words = append(words, i1, i2)
48 } else {
49 words = append(words, word)
50 }
51 w = i
52 }
53 return words
54 }
55
56
57
58
59 func ParseLowerCamelCase(name string) Name {
60 var words Name
61
62
63 runes := []rune(name)
64 w, i := 0, 0
65 for i+1 <= len(runes) {
66 eow := false
67 if i+1 == len(runes) {
68 eow = true
69 } else if unicode.IsUpper(runes[i+1]) {
70
71 eow = true
72 }
73 i++
74 if !eow {
75 continue
76 }
77
78
79 words = append(words, string(runes[w:i]))
80 w = i
81 }
82 return words
83 }
84
85
86
87
88 func ParseScreamingSnakeCase(name string) Name {
89 var words Name
90
91
92 runes := []rune(name)
93 w, i := 0, 0
94 for i+1 <= len(runes) {
95 eow := false
96 if i+1 == len(runes) {
97 eow = true
98 } else if runes[i+1] == '_' {
99
100 eow = true
101 }
102 i++
103 if !eow {
104 continue
105 }
106
107
108 words = append(words, string(runes[w:i]))
109 if i < len(runes) && runes[i] == '_' {
110
111 i++
112 }
113 w = i
114 }
115 return words
116 }
117
118
119 type Name []string
120
121
122
123
124 func (n Name) ToMixedCaps() string {
125 for i, word := range n {
126 if strings.EqualFold(word, "IDs") {
127 n[i] = "IDs"
128 continue
129 }
130 if initialism, ok := isInitialism(word); ok {
131 n[i] = initialism
132 continue
133 }
134 if brand, ok := isBrand(word); ok {
135 n[i] = brand
136 continue
137 }
138 r, size := utf8.DecodeRuneInString(word)
139 n[i] = string(unicode.ToUpper(r)) + strings.ToLower(word[size:])
140 }
141 return strings.Join(n, "")
142 }
143
144
145
146
147 func (n Name) ToLowerCamelCase() string {
148 for i, word := range n {
149 if i == 0 {
150 n[i] = strings.ToLower(word)
151 continue
152 }
153 r, size := utf8.DecodeRuneInString(word)
154 n[i] = string(unicode.ToUpper(r)) + strings.ToLower(word[size:])
155 }
156 return strings.Join(n, "")
157 }
158
159
160 func isInitialism(word string) (string, bool) {
161 initialism := strings.ToUpper(word)
162 _, ok := initialisms[initialism]
163 return initialism, ok
164 }
165
166
167 func isTwoInitialisms(word string) (string, string, bool) {
168 word = strings.ToUpper(word)
169 for i := 2; i <= len(word)-2; i++ {
170 _, ok1 := initialisms[word[:i]]
171 _, ok2 := initialisms[word[i:]]
172 if ok1 && ok2 {
173 return word[:i], word[i:], true
174 }
175 }
176 return "", "", false
177 }
178
179
180
181
182 var initialisms = map[string]struct{}{
183
184
185 "ACL": {},
186 "API": {},
187 "ASCII": {},
188 "CPU": {},
189 "CSS": {},
190 "DNS": {},
191 "EOF": {},
192 "GUID": {},
193 "HTML": {},
194 "HTTP": {},
195 "HTTPS": {},
196 "ID": {},
197 "IP": {},
198 "JSON": {},
199 "LHS": {},
200 "QPS": {},
201 "RAM": {},
202 "RHS": {},
203 "RPC": {},
204 "SLA": {},
205 "SMTP": {},
206 "SQL": {},
207 "SSH": {},
208 "TCP": {},
209 "TLS": {},
210 "TTL": {},
211 "UDP": {},
212 "UI": {},
213 "UID": {},
214 "UUID": {},
215 "URI": {},
216 "URL": {},
217 "UTF8": {},
218 "VM": {},
219 "XML": {},
220 "XMPP": {},
221 "XSRF": {},
222 "XSS": {},
223
224
225 "RSS": {},
226 }
227
228
229 func isBrand(word string) (string, bool) {
230 brand, ok := brands[strings.ToLower(word)]
231 return brand, ok
232 }
233
234
235
236
237
238 var brands = map[string]string{
239 "github": "GitHub",
240 }
241
View as plain text