gotygen/pkg/strcase/camel.go

94 lines
1.7 KiB
Go

package strcase
import (
"regexp"
"strings"
)
var (
splitRE = regexp.MustCompile(`_+|-+|\s+`)
allCapsRE = regexp.MustCompile(`^[A-Z]{2,}\d*$`)
capitalizedRE = regexp.MustCompile(`[A-Z][a-z]+\d*`)
)
type CamelContext interface {
UseCaps(a []string) CamelContext
HasCaps(w string) bool
Find(s string) (string, bool)
Save(s, r string)
}
type camelContext struct {
allCaps map[string]bool
cache map[string]string
}
func (c *camelContext) UseCaps(a []string) CamelContext {
if c.allCaps == nil {
c.allCaps = make(map[string]bool, len(a))
}
for _, s := range a {
c.allCaps[s] = true
}
return c
}
func (c *camelContext) HasCaps(w string) (ok bool) {
if c.allCaps != nil {
_, ok = c.allCaps[w]
}
return
}
func (c *camelContext) Find(s string) (r string, ok bool) {
if c.cache != nil {
r, ok = c.cache[s]
}
return
}
func (c *camelContext) Save(s, r string) {
if c.cache == nil {
c.cache = make(map[string]string)
}
c.cache[s] = r
}
func NewCamelContext(caps []string) CamelContext {
return new(camelContext).UseCaps(caps)
}
func ToCamel(s string, c ...CamelContext) (r string) {
var ctx CamelContext
if len(c) > 0 {
ctx = c[0]
}
if ctx != nil {
var ok bool
if r, ok = ctx.Find(s); ok {
return
}
}
words := splitRE.Split(s, -1)
for i, word := range words {
if len(word) != 0 {
if allCapsRE.MatchString(word) {
words[i] = word[:1] + strings.ToLower(word[1:])
} else {
words[i] = strings.ToUpper(word[:1]) + word[1:]
}
}
}
if ctx != nil {
r = capitalizedRE.ReplaceAllStringFunc(strings.Join(words, ""), func(s string) string {
if w := strings.ToUpper(s); ctx.HasCaps(w) {
return w
}
return s
})
ctx.Save(s, r)
} else {
r = strings.Join(words, "")
}
return
}