-
Notifications
You must be signed in to change notification settings - Fork 2
/
core.go
108 lines (102 loc) · 2.91 KB
/
core.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
package go_case
import (
"strings"
"unicode"
)
var (
// ToSnakeCase converts string to snake_case.
ToSnakeCase = ToSomeCaseWithSep('_', unicode.ToLower)
// ToLowerCase is a shortcut for strings.ToLower.
ToLowerCase = strings.ToLower
// ToUrlSnakeCase works like ToSnakeCase except fills spaces with `-`.
ToUrlSnakeCase = ToSomeCaseWithSep('-', unicode.ToLower)
// ToDotSnakeCase works like ToSnakeCase except fills spaces with `.`(dot).
ToDotSnakeCase = ToSomeCaseWithSep('.', unicode.ToLower)
// ToCamelCase converts string to CamelCase. All space symbols, `_`, `.` and `-` will be removed. First symbol will be capital.
ToCamelCase = toCamelCase(true, unicode.ToUpper)
// ToCamelCase converts string to CamelCase. All space symbols, `_`, `.` and `-` will be removed. First symbol will be capital.
ToCamelCaseLowerFirst = toCamelCaseLower()
// ToNoCase returns input's string. Should be used for mocking, tests, etc.
ToNoCase = func(s string) string { return s }
)
// ToSomeCaseWithSep allow to get customized converter, that will work as ToSnakeCase, but with your rules.
func ToSomeCaseWithSep(sep rune, runeConv func(rune) rune) func(string) string {
return func(s string) string {
in := []rune(s)
n := len(in)
var runes []rune
for i, r := range in {
if isExtendedSpace(r) {
runes = append(runes, sep)
continue
}
if unicode.IsUpper(r) {
if i > 0 && sep != runes[i-1] && ((i+1 < n && unicode.IsLower(in[i+1])) || unicode.IsLower(in[i-1])) {
runes = append(runes, sep)
}
r = runeConv(r)
}
runes = append(runes, r)
}
return string(runes)
}
}
func toCamelCase(upperFirst bool, runeConv func(rune) rune) func(string) string {
return func(s string) string {
in := []rune(s)
var runes []rune
for i, r := range in {
if isExtendedSpace(r) {
continue
}
if unicode.IsUpper(r) {
runes = append(runes, r)
continue
}
if i > 0 && isExtendedSpace(in[i-1]) && unicode.IsLower(r) || i == 0 && upperFirst {
r = runeConv(r)
}
runes = append(runes, r)
}
return string(runes)
}
}
func toCamelCaseLower() func(string) string {
return func(s string) string {
in := []rune(s)
var runes []rune
max, m := len(in), 0
for i, r := range in {
if !isExtendedSpace(r) && (i+1 < max && unicode.IsUpper(in[i+1])) {
runes = append(runes, unicode.ToLower(r))
continue
}
m = i
break
}
if len(in[m:]) == 1 {
return string(append(runes, unicode.ToLower(in[m])))
}
for i, r := range in[m:] {
if isExtendedSpace(r) {
continue
}
if unicode.IsUpper(r) {
if i+m > 0 {
runes = append(runes, r)
} else {
runes = append(runes, unicode.ToLower(r))
}
continue
}
if i+m > 0 && isExtendedSpace(in[i+m-1]) && unicode.IsLower(r) {
r = unicode.ToUpper(r)
}
runes = append(runes, r)
}
return string(runes)
}
}
func isExtendedSpace(r rune) bool {
return unicode.IsSpace(r) || r == '_' || r == '-' || r == '.'
}