gitee.com/gricks/utils@v1.0.8/casee.go (about) 1 package utils 2 3 import ( 4 "strings" 5 "unicode" 6 "unicode/utf8" 7 ) 8 9 // Splitting rules 10 // 11 // 1) If string is not valid UTF-8, return it without splitting as 12 // single item array. 13 // 2) Assign all unicode characters into one of 4 sets: lower case 14 // letters, upper case letters, numbers, and all other characters. 15 // 3) Iterate through characters of string, introducing splits 16 // between adjacent characters that belong to different sets. 17 // 4) Iterate through array of split strings, and if a given string 18 // is upper case: 19 // if subsequent string is lower case: 20 // move last character of upper case string to beginning of 21 // lower case string 22 func CamelcaseSplit(src string) (entries []string) { 23 // don't split invalid utf8 24 if !utf8.ValidString(src) { 25 return []string{src} 26 } 27 entries = []string{} 28 var runes [][]rune 29 lastClass := 0 30 class := 0 31 // split into fields based on class of unicode character 32 for _, r := range src { 33 switch true { 34 case unicode.IsLower(r): 35 class = 1 36 case unicode.IsUpper(r): 37 class = 2 38 case unicode.IsDigit(r): 39 class = 3 40 default: 41 class = 4 42 } 43 if class == lastClass { 44 runes[len(runes)-1] = append(runes[len(runes)-1], r) 45 } else { 46 runes = append(runes, []rune{r}) 47 } 48 lastClass = class 49 } 50 // handle upper case -> lower case sequences, e.g. 51 // "PDFL", "oader" -> "PDF", "Loader" 52 for i := 0; i < len(runes)-1; i++ { 53 if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) { 54 runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...) 55 runes[i] = runes[i][:len(runes[i])-1] 56 } 57 } 58 // construct []string from results 59 for _, s := range runes { 60 if len(s) > 0 { 61 entries = append(entries, string(s)) 62 } 63 } 64 return 65 } 66 67 type SplitCase int 68 69 const ( 70 NoneCase SplitCase = 0 71 LowerCase SplitCase = 1 72 UpperCase SplitCase = 2 73 TitleCase SplitCase = 3 74 ) 75 76 // Split a string to fields 77 func Split2fields(s string, c SplitCase) []string { 78 fields := make([]string, 0, len([]rune(s))/3) 79 for _, sf := range strings.Fields(s) { 80 for _, su := range strings.Split(sf, "_") { 81 for _, sh := range strings.Split(su, "-") { 82 for _, sc := range CamelcaseSplit(sh) { 83 switch c { 84 case LowerCase: 85 sc = strings.ToLower(sc) 86 case UpperCase: 87 sc = strings.ToUpper(sc) 88 case TitleCase: 89 sc = strings.ToTitle(sc) 90 default: 91 } 92 fields = append(fields, strings.ToLower(sc)) 93 } 94 } 95 } 96 } 97 return fields 98 } 99 100 // Convert argument to snake_case style string. 101 func ToSnakeCase(s string) string { 102 if len(s) == 0 { 103 return s 104 } 105 return strings.Join(Split2fields(s, LowerCase), "_") 106 } 107 108 // Convert argument to chain-case style string. 109 func ToChainCase(s string) string { 110 if len(s) == 0 { 111 return s 112 } 113 return strings.Join(Split2fields(s, LowerCase), "-") 114 } 115 116 // Convert argument to PascalCase style string 117 func ToPascalCase(s string) string { 118 if len(s) == 0 { 119 return s 120 } 121 return strings.Join(Split2fields(s, TitleCase), "") 122 } 123 124 // Convert argument to camelCase style string 125 func ToCamelCase(s string) string { 126 if len(s) == 0 { 127 return s 128 } 129 fields := Split2fields(s, TitleCase) 130 if len(fields) > 0 { 131 fields[0] = strings.ToLower(fields[0]) 132 } 133 return strings.Join(fields, "") 134 }