/
snaker.go
163 lines (146 loc) · 3.95 KB
/
snaker.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
159
160
161
162
163
// Package snaker provides methods to convert CamelCase to and from snake_case.
//
// Correctly recognizes common (Go idiomatic) initialisms (HTTP, XML, etc) and
// provides a mechanism to override/set recognized initialisms.
package snaker
import (
"regexp"
"strings"
"unicode"
)
func init() {
// initialize common default initialisms.
DefaultInitialisms = NewDefaultInitialisms()
}
// CommonInitialisms returns the set of common initialisms.
//
// Originally built from the list in golang.org/x/lint @ 738671d.
//
// Note: golang.org/x/lint has since been deprecated, and some additional
// initialisms have since been added.
func CommonInitialisms() []string {
return []string{
"ACL",
"API",
"ASCII",
"CPU",
"CSS",
"DNS",
"EOF",
"GUID",
"HTML",
"HTTPS",
"HTTP",
"ID",
"IP",
"JSON",
"LHS",
"QPS",
"RAM",
"RHS",
"RPC",
"SLA",
"SMTP",
"SQL",
"SSH",
"TCP",
"TLS",
"TTL",
"UDP",
"UID",
"UI",
"URI",
"URL",
"UTC",
"UTF8",
"UUID",
"VM",
"XML",
"XMPP",
"XSRF",
"XSS",
"YAML",
}
}
// DefaultInitialisms is a set of default (common) initialisms.
var DefaultInitialisms *Initialisms
// CamelToSnake converts name from camel case ("AnIdentifier") to snake case
// ("an_identifier").
func CamelToSnake(name string) string {
return DefaultInitialisms.CamelToSnake(name)
}
// CamelToSnakeIdentifier converts name from camel case to a snake case
// identifier.
func CamelToSnakeIdentifier(name string) string {
return DefaultInitialisms.CamelToSnakeIdentifier(name)
}
// SnakeToCamel converts name to CamelCase.
func SnakeToCamel(name string) string {
return DefaultInitialisms.SnakeToCamel(name)
}
// SnakeToCamelIdentifier converts name to its CamelCase identifier (first
// letter is capitalized).
func SnakeToCamelIdentifier(name string) string {
return DefaultInitialisms.SnakeToCamelIdentifier(name)
}
// ForceCamelIdentifier forces name to its CamelCase specific to Go
// ("AnIdentifier").
func ForceCamelIdentifier(name string) string {
return DefaultInitialisms.ForceCamelIdentifier(name)
}
// ForceLowerCamelIdentifier forces the first portion of an identifier to be
// lower case ("anIdentifier").
func ForceLowerCamelIdentifier(name string) string {
return DefaultInitialisms.ForceLowerCamelIdentifier(name)
}
// Peek returns the next longest possible initialism in r.
func Peek(r []rune) string {
return DefaultInitialisms.Peek(r)
}
// IsInitialism indicates whether or not s is a registered initialism.
func IsInitialism(s string) bool {
return DefaultInitialisms.IsInitialism(s)
}
// IsIdentifierChar determines if ch is a valid character for a Go identifier.
//
// See: go/src/go/scanner/scanner.go
func IsIdentifierChar(ch rune) bool {
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch) ||
'0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
}
// ToIdentifier cleans s so that it is usable as an identifier.
//
// Substitutes invalid characters with an underscore, removes any leading
// numbers/underscores, and removes trailing underscores.
//
// Additionally collapses multiple underscores to a single underscore.
//
// Makes no changes to case.
func ToIdentifier(s string) string {
// replace bad chars with _
s = subUnderscores(strings.TrimSpace(s))
// fix 2 or more __ and remove leading numbers/underscores
s = underscoreRE.ReplaceAllString(s, "_")
s = leadingRE.ReplaceAllString(s, "_")
// remove leading/trailing underscores
s = strings.TrimLeft(s, "_")
s = strings.TrimRight(s, "_")
return s
}
// underscoreRE matches underscores.
var underscoreRE = regexp.MustCompile(`_+`)
// leadingRE matches leading numbers.
var leadingRE = regexp.MustCompile(`^[0-9_]+`)
// subUnderscores substitues underscrose in place of runes that are invalid for
// Go identifiers.
func subUnderscores(s string) string {
var r []rune
for _, c := range s {
if IsIdentifierChar(c) {
r = append(r, c)
} else {
r = append(r, '_')
}
}
return string(r)
}