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)
}
|