forked from gookit/goutil
-
Notifications
You must be signed in to change notification settings - Fork 0
/
strutil.go
184 lines (163 loc) · 3.94 KB
/
strutil.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
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Package strutil provide some string,char,byte util functions
package strutil
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"strings"
"text/template"
"github.com/gookit/goutil/comdef"
)
// OrCond return s1 on cond is True, OR return s2.
// Like: cond ? s1 : s2
func OrCond(cond bool, s1, s2 string) string {
if cond {
return s1
}
return s2
}
// BlankOr return default value on val is blank, else return val
func BlankOr(val, defVal string) string {
val = strings.TrimSpace(val)
if val != "" {
return val
}
return defVal
}
// ZeroOr return default value on val is zero, else return val. same of OrElse()
func ZeroOr[T ~string](val, defVal T) T {
if val != "" {
return val
}
return defVal
}
// OrElse return default value on val is zero, else return s
func OrElse(s, orVal string) string {
if s != "" {
return s
}
return orVal
}
// OrHandle return fn(s) on s is not empty.
func OrHandle(s string, fn comdef.StringHandleFunc) string {
if s != "" {
return fn(s)
}
return s
}
// Valid return first not empty element.
func Valid(ss ...string) string {
for _, s := range ss {
if s != "" {
return s
}
}
return ""
}
// Replaces replace multi strings
//
// pairs: {old1: new1, old2: new2, ...}
//
// Can also use:
//
// strings.NewReplacer("old1", "new1", "old2", "new2").Replace(str)
func Replaces(str string, pairs map[string]string) string {
return NewReplacer(pairs).Replace(str)
}
// NewReplacer instance
func NewReplacer(pairs map[string]string) *strings.Replacer {
ss := make([]string, len(pairs)*2)
for old, newVal := range pairs {
ss = append(ss, old, newVal)
}
return strings.NewReplacer(ss...)
}
// PrettyJSON get pretty Json string
// Deprecated: please use fmtutil.PrettyJSON() or jsonutil.Pretty() instead it
func PrettyJSON(v any) (string, error) {
out, err := json.MarshalIndent(v, "", " ")
return string(out), err
}
// RenderTemplate render text template
func RenderTemplate(input string, data any, fns template.FuncMap, isFile ...bool) string {
return RenderText(input, data, fns, isFile...)
}
// RenderText render text template
func RenderText(input string, data any, fns template.FuncMap, isFile ...bool) string {
t := template.New("simple-text")
t.Funcs(template.FuncMap{
// don't escape content
"raw": func(s string) string {
return s
},
"trim": func(s string) string {
return strings.TrimSpace(s)
},
// join strings
"join": func(ss []string, sep string) string {
return strings.Join(ss, sep)
},
// lower first char
"lcFirst": func(s string) string {
return LowerFirst(s)
},
// upper first char
"upFirst": func(s string) string {
return UpperFirst(s)
},
})
// add custom template functions
if len(fns) > 0 {
t.Funcs(fns)
}
if len(isFile) > 0 && isFile[0] {
template.Must(t.ParseFiles(input))
} else {
template.Must(t.Parse(input))
}
// use buffer receive rendered content
buf := new(bytes.Buffer)
if err := t.Execute(buf, data); err != nil {
panic(err)
}
return buf.String()
}
// WrapTag for given string.
func WrapTag(s, tag string) string {
if s == "" {
return s
}
return fmt.Sprintf("<%s>%s</%s>", tag, s, tag)
}
// SubstrCount returns the number of times the substr substring occurs in the s string.
// Actually, it comes from strings.Count().
// s The string to search in
// substr The substring to search for
// params[0] The offset where to start counting.
// params[1] The maximum length after the specified offset to search for the substring.
func SubstrCount(s, substr string, params ...uint64) (int, error) {
larg := len(params)
hasArgs := larg != 0
if hasArgs && larg > 2 {
return 0, errors.New("too many parameters")
}
if !hasArgs {
return strings.Count(s, substr), nil
}
strlen := len(s)
offset := 0
end := strlen
if hasArgs {
offset = int(params[0])
if larg == 2 {
length := int(params[1])
end = offset + length
}
if end > strlen {
end = strlen
}
}
s = string([]rune(s)[offset:end])
return strings.Count(s, substr), nil
}