124 lines
2.4 KiB
Go
124 lines
2.4 KiB
Go
|
// Package snaker provides methods to convert CamelCase names to snake_case and back.
|
||
|
// It considers the list of allowed initialsms used by github.com/golang/lint/golint (e.g. ID or HTTP)
|
||
|
package snaker
|
||
|
|
||
|
import (
|
||
|
"strings"
|
||
|
"unicode"
|
||
|
)
|
||
|
|
||
|
// CamelToSnake converts a given string to snake case
|
||
|
func CamelToSnake(s string) string {
|
||
|
var result string
|
||
|
var words []string
|
||
|
var lastPos int
|
||
|
rs := []rune(s)
|
||
|
|
||
|
for i := 0; i < len(rs); i++ {
|
||
|
if i > 0 && unicode.IsUpper(rs[i]) {
|
||
|
if initialism := startsWithInitialism(s[lastPos:]); initialism != "" {
|
||
|
words = append(words, initialism)
|
||
|
|
||
|
i += len(initialism) - 1
|
||
|
lastPos = i
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
words = append(words, s[lastPos:i])
|
||
|
lastPos = i
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// append the last word
|
||
|
if s[lastPos:] != "" {
|
||
|
words = append(words, s[lastPos:])
|
||
|
}
|
||
|
|
||
|
for k, word := range words {
|
||
|
if k > 0 {
|
||
|
result += "_"
|
||
|
}
|
||
|
|
||
|
result += strings.ToLower(word)
|
||
|
}
|
||
|
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
// SnakeToCamel returns a string converted from snake case to uppercase
|
||
|
func SnakeToCamel(s string) string {
|
||
|
var result string
|
||
|
|
||
|
words := strings.Split(s, "_")
|
||
|
|
||
|
for _, word := range words {
|
||
|
if upper := strings.ToUpper(word); commonInitialisms[upper] {
|
||
|
result += upper
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if len(word) > 0 {
|
||
|
w := []rune(word)
|
||
|
w[0] = unicode.ToUpper(w[0])
|
||
|
result += string(w)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
// startsWithInitialism returns the initialism if the given string begins with it
|
||
|
func startsWithInitialism(s string) string {
|
||
|
var initialism string
|
||
|
// the longest initialism is 5 char, the shortest 2
|
||
|
for i := 1; i <= 5; i++ {
|
||
|
if len(s) > i-1 && commonInitialisms[s[:i]] {
|
||
|
initialism = s[:i]
|
||
|
}
|
||
|
}
|
||
|
return initialism
|
||
|
}
|
||
|
|
||
|
// commonInitialisms, taken from
|
||
|
// https://github.com/golang/lint/blob/206c0f020eba0f7fbcfbc467a5eb808037df2ed6/lint.go#L731
|
||
|
var commonInitialisms = map[string]bool{
|
||
|
"ACL": true,
|
||
|
"API": true,
|
||
|
"ASCII": true,
|
||
|
"CPU": true,
|
||
|
"CSS": true,
|
||
|
"DNS": true,
|
||
|
"EOF": true,
|
||
|
"GUID": true,
|
||
|
"HTML": true,
|
||
|
"HTTP": true,
|
||
|
"HTTPS": true,
|
||
|
"ID": true,
|
||
|
"IP": true,
|
||
|
"JSON": true,
|
||
|
"LHS": true,
|
||
|
"QPS": true,
|
||
|
"RAM": true,
|
||
|
"RHS": true,
|
||
|
"RPC": true,
|
||
|
"SLA": true,
|
||
|
"SMTP": true,
|
||
|
"SQL": true,
|
||
|
"SSH": true,
|
||
|
"TCP": true,
|
||
|
"TLS": true,
|
||
|
"TTL": true,
|
||
|
"UDP": true,
|
||
|
"UI": true,
|
||
|
"UID": true,
|
||
|
"UUID": true,
|
||
|
"URI": true,
|
||
|
"URL": true,
|
||
|
"UTF8": true,
|
||
|
"VM": true,
|
||
|
"XML": true,
|
||
|
"XMPP": true,
|
||
|
"XSRF": true,
|
||
|
"XSS": true,
|
||
|
}
|