-
Notifications
You must be signed in to change notification settings - Fork 94
/
Copy pathtext.ab
241 lines (208 loc) Β· 7.75 KB
/
text.ab
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/// Replaces all occurences of a pattern in the content with the provided replace text.
pub fun replace(source, search, replace) {
return "\$\{source//{search}/{replace}}"
}
/// Replaces the first occurence of a pattern in the content with the provided replace text.
pub fun replace_one(source, search, replace) {
return "\$\{source/{search}/{replace}}"
}
/// Replaces all occurences of a regex pattern in the content with the provided replace text.
///
/// Function uses `sed`
pub fun replace_regex(source: Text, search: Text, replace: Text, extended: Bool = false): Text {
trust {
search = replace(search, "/", "\/")
replace = replace(replace, "/", "\/")
if extended {
// GNU sed versions 4.0 through 4.2 support extended regex syntax,
// but only via the "-r" option; use that if the version information
// contains "GNU sed".
$ re='\bCopyright\b.+\bFree Software Foundation\b'; [[ \$(sed --version 2>/dev/null) =~ \$re ]] $
let flag = status == 0 then "-r" else "-E"
return $ echo "{source}" | sed "{flag}" -e "s/{search}/{replace}/g" $
} else {
return $ echo "{source}" | sed -e "s/{search}/{replace}/g" $
}
}
}
/// Splits the input `text` into an array of substrings using the specified `delimiter`.
pub fun split(text: Text, delimiter: Text): [Text] {
let result = [Text]
trust $ IFS="{delimiter}" read -rd '' -a {nameof result} < <(printf %s "\${nameof text}") $
return result
}
/// Splits a `text` into an array of substrings based on newline characters.
pub fun split_lines(text: Text): [Text] {
return split(text, "\n")
}
/// Splits a `text` into an array of substrings based on space character.
pub fun split_words(text: Text): [Text] {
return split(text, " ")
}
/// Merges text using the delimeter specified.
pub fun join(list: [Text], delimiter: Text): Text {
return trust $ IFS="{delimiter}" ; echo "\$\{{nameof list}[*]}" $
}
/// Trims the spaces at top of the text using `sed`.
pub fun trim_left(text: Text): Text {
return trust $ echo "{text}" | sed -e 's/^[[:space:]]*//' $
}
/// Trims the spaces at end of the text using `sed`.
pub fun trim_right(text: Text): Text {
return trust $ echo "{text}" | sed -e 's/[[:space:]]*\$//' $
}
/// Trims the spaces from the text input.
pub fun trim(text: Text): Text {
return trim_left(trim_right(text))
}
/// Makes the text input lowercase using `tr`.
pub fun lowercase(text: Text): Text {
return trust $ echo "{text}" | tr '[:upper:]' '[:lower:]' $
}
/// Makes the text input uppercase using `tr`.
pub fun uppercase(text: Text): Text {
return trust $ echo "{text}" | tr '[:lower:]' '[:upper:]' $
}
/// Attempts to parse a given text into a number, returning the parsed number or zero if parsing fails.
#[allow_absurd_cast]
pub fun parse_number(text: Text): Num? {
$ [ -n "{text}" ] && [ "{text}" -eq "{text}" ] 2>/dev/null $?
return text as Num
}
/// Splits a text into an array of individual characters.
pub fun split_chars(text: Text): [Text] {
let chars = [Text]
trust $ for ((i=0; i<\$\{#{nameof text}}; i++)); do
{nameof chars}+=( "\$\{{nameof text}:\$i:1}" );
done $
return chars
}
/// Checks if some text contains a value.
pub fun text_contains(text: Text, phrase: Text): Bool {
let result = trust $ if [[ "{text}" == *"{phrase}"* ]]; then
echo 1
fi $
return result == "1"
}
/// Checks if an array value is in the text.
pub fun text_contains_any(text: Text, terms: [Text]): Bool {
for term in terms {
if text_contains(text, term) {
return true
}
}
return false
}
/// Checks if all the arrays values are in the string
pub fun text_contains_all(text: Text, terms: [Text]): Bool {
for term in terms {
if not text_contains(text, term) {
return false
}
}
return true
}
/// Match all occurences of a regex pattern.
///
/// Function uses `sed`
pub fun match_regex(source: Text, search: Text, extended: Bool = false): Bool {
trust {
search = replace(search, "/", "\/")
let output = ""
if extended {
// GNU sed versions 4.0 through 4.2 support extended regex syntax,
// but only via the "-r" option; use that if the version information
// contains "GNU sed".
$ re='\bCopyright\b.+\bFree Software Foundation\b'; [[ \$(sed --version 2>/dev/null) =~ \$re ]] $
let flag = status == 0 then "-r" else "-E"
output = $ echo "{source}" | sed "{flag}" -ne "/{search}/p" $
} else {
output = $ echo "{source}" | sed -ne "/{search}/p" $
}
if output != "" {
return true
}
}
return false
}
/// Checks if an array value (with regular expression) is in the text.
pub fun match_regex_any(text: Text, terms: [Text]): Bool {
for term in terms {
if match_regex(text, term, false) {
return true
}
}
return false
}
/// Reverses text using `rev`.
pub fun reversed(text: Text): Text {
return trust $ echo "{text}" | rev $
}
/// Checks if text starts with a value.
pub fun starts_with(text: Text, prefix: Text): Bool {
let result = trust $ if [[ "{text}" == "{prefix}"* ]]; then
echo 1
fi $
return result == "1"
}
/// Checks if text ends with a value.
pub fun ends_with(text: Text, suffix: Text): Bool {
let result = trust $ if [[ "{text}" == *"{suffix}" ]]; then
echo 1
fi $
return result == "1"
}
/// Returns a substring from `text` starting at the given `index` (0-based).
///
/// If `index` is negative, the substring starts from the end of `text` based on the absolute value of `index`.
/// If `length` is provided, the substring will include `length` characters; otherwise, it slices to the end of `text`.
/// If `length` is negative, an empty string is returned.
pub fun slice(text: Text, index: Num, length: Num = 0): Text {
if length == 0: length = len(text) - index
if length <= 0: return ""
return trust $ printf "%.{length}s" "\$\{text:{index}}" $
}
/// Returns the character from `text` at the specified `index` (0-based).
///
/// If `index` is negative, the substring starts from the end of `text` based on the absolute value of `index`.
pub fun char_at(text: Text, index: Num): Text {
return trust $ printf "%.1s" "\$\{text:{index}}" $
}
/// Capitalize the first letter of the given `text`.
#[allow_absurd_cast]
pub fun capitalized(text: Text): Text {
trust {
if len(text) == 0 {
return text
}
const bash_version = $ echo \"\$\{BASH_VERSINFO[0]}\" $ as Num
if bash_version >= 4 {
return $ echo \"\$\{text^}\" $
}
// GNU sed supports \U
$ re='\bCopyright\b.+\bFree Software Foundation\b'; [[ \$(sed --version 2>/dev/null) =~ \$re ]] $
if status == 0 {
return $ echo "{text}" | sed "s/^\(.\)/\U\1/" $
}
const first_letter = uppercase(char_at(text, 0))
return first_letter + slice(text, 1)
}
}
/// Pads `text` with the specified `pad` character on left until it reaches the desired `length`.
pub fun lpad(text: Text, pad: Text, length: Num): Text {
if length <= len(text): return text
length = len(text) - length
pad = trust $ printf "%{length}s" "" | tr " " "{pad}" $
return pad + text
}
/// Pads `text` with the specified `pad` character on the right until it reaches the desired `length`.
pub fun rpad(text: Text, pad: Text, length: Num): Text {
if length <= len(text): return text
length = len(text) - length
pad = trust $ printf "%{length}s" "" | tr " " "{pad}" $
return text + pad
}
/// Pads `text` with zeros on the left until it reaches the desired `length`.
pub fun zfill(text: Text, length: Num): Text {
return lpad(text, "0", length)
}