github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/ss/s.go (about) 1 package ss 2 3 import ( 4 "strings" 5 ) 6 7 // Left returns the left n runes of s at most. 8 func Left(s string, n int) string { 9 if n <= len(s) { 10 return s[:n] 11 } 12 13 return s 14 } 15 16 func IsDigits(s string) bool { 17 for _, c := range s { 18 if c < '0' || c > '9' { 19 return false 20 } 21 } 22 return true 23 } 24 25 // Repeat repeats s with separator seq for n times. 26 func Repeat(s, sep string, n int) string { 27 result := "" 28 for i := 0; i < n; i++ { 29 if i == 0 { 30 result = s 31 } else { 32 result += sep + s 33 } 34 } 35 36 return result 37 } 38 39 // FirstWord returns the first word of the SQL statement s. 40 func FirstWord(s string) string { 41 if v := FieldsN(strings.TrimSpace(s), 2); len(v) > 0 { 42 return v[0] 43 } 44 45 return "" 46 } 47 48 func RemoveAll(s, old string) string { return strings.ReplaceAll(s, old, "") } 49 50 func Ori(a, b int) int { 51 if a == 0 { 52 return b 53 } 54 55 return a 56 } 57 58 func Or(a, b string) string { 59 if a == "" { 60 return b 61 } 62 63 return a 64 } 65 66 func Ifi(b bool, s1, s2 int) int { 67 if b { 68 return s1 69 } 70 71 return s2 72 } 73 74 func If(b bool, s1, s2 string) string { 75 if b { 76 return s1 77 } 78 79 return s2 80 } 81 82 func ContainsFold(s string, ss ...string) bool { 83 s = strings.ToLower(s) 84 for _, of := range ss { 85 of = strings.ToLower(of) 86 if strings.Contains(s, of) { 87 return true 88 } 89 } 90 return false 91 } 92 93 func Contains(s string, ss ...string) bool { 94 for _, of := range ss { 95 if strings.Contains(s, of) { 96 return true 97 } 98 } 99 return false 100 } 101 102 func AnyOf(s string, ss ...string) bool { 103 for _, of := range ss { 104 if s == of { 105 return true 106 } 107 } 108 return false 109 } 110 111 func AnyOfFold(s string, ss ...string) bool { 112 s = strings.ToLower(s) 113 for _, of := range ss { 114 if s == strings.ToLower(of) { 115 return true 116 } 117 } 118 return false 119 } 120 121 func HasPrefix(s string, ss ...string) bool { 122 for _, one := range ss { 123 if strings.HasPrefix(s, one) { 124 return true 125 } 126 } 127 return false 128 } 129 130 func HasSuffix(s string, ss ...string) bool { 131 for _, one := range ss { 132 if strings.HasSuffix(s, one) { 133 return true 134 } 135 } 136 return false 137 } 138 139 //func Jsonify(v interface{}) string { 140 // b := &bytes.Buffer{} 141 // encoder := json.NewEncoder(b) 142 // encoder.SetEscapeHTML(false) 143 // if err := encoder.Encode(v); err != nil { 144 // return err.Error() 145 // } 146 // 147 // return b.String() 148 //} 149 150 func ToSet(v []string) map[string]bool { 151 m := make(map[string]bool) 152 for _, s := range v { 153 m[s] = true 154 } 155 return m 156 } 157 158 type Case int 159 160 const ( 161 CaseUnchanged Case = iota 162 CaseLower 163 CaseUpper 164 ) 165 166 type SplitConfig struct { 167 Separators string 168 IgnoreEmpty bool 169 TrimSpace bool 170 Case Case 171 N int 172 } 173 174 type SplitOption func(*SplitConfig) 175 176 func WithConfig(v SplitConfig) SplitOption { return func(c *SplitConfig) { *c = v } } 177 func WithSeps(v string) SplitOption { return func(c *SplitConfig) { c.Separators = v } } 178 func WithN(v int) SplitOption { return func(c *SplitConfig) { c.N = v } } 179 func WithIgnoreEmpty(v bool) SplitOption { return func(c *SplitConfig) { c.IgnoreEmpty = v } } 180 func WithTrimSpace(v bool) SplitOption { return func(c *SplitConfig) { c.TrimSpace = v } } 181 func WithCase(v Case) SplitOption { return func(c *SplitConfig) { c.Case = v } } 182 183 func Split(s string, options ...SplitOption) []string { 184 v := make([]string, 0) 185 c := createConfig(options) 186 187 ff := FieldsFuncN(s, c.N, func(r rune) bool { 188 return strings.ContainsRune(c.Separators, r) 189 }) 190 191 for _, f := range ff { 192 if c.TrimSpace { 193 f = strings.TrimSpace(f) 194 } 195 if c.IgnoreEmpty && f == "" { 196 continue 197 } 198 switch c.Case { 199 case CaseLower: 200 f = strings.ToLower(f) 201 case CaseUpper: 202 f = strings.ToUpper(f) 203 } 204 205 v = append(v, f) 206 } 207 208 return v 209 } 210 211 func createConfig(options []SplitOption) *SplitConfig { 212 c := &SplitConfig{TrimSpace: true, IgnoreEmpty: true} 213 for _, o := range options { 214 o(c) 215 } 216 217 if c.Separators == "" { 218 c.Separators = ", " 219 } 220 221 return c 222 } 223 224 func ToLowerKebab(name string) string { 225 var sb strings.Builder 226 227 isUpper := func(c uint8) bool { return 'A' <= c && c <= 'Z' } 228 229 for i := 0; i < len(name); i++ { 230 c := name[i] 231 if isUpper(c) { 232 if sb.Len() > 0 { 233 if i+1 < len(name) && (!(i-1 >= 0 && isUpper(name[i-1])) || !isUpper(name[i+1])) { 234 sb.WriteByte('-') 235 } 236 } 237 sb.WriteByte(c - 'A' + 'a') 238 } else { 239 sb.WriteByte(c) 240 } 241 } 242 243 return sb.String() 244 }