2021-01-06 20:43:58 +00:00
|
|
|
package strings
|
|
|
|
|
2021-01-19 18:56:43 +00:00
|
|
|
import (
|
|
|
|
"bufio"
|
2023-08-15 09:24:37 +00:00
|
|
|
"log"
|
2021-01-25 20:44:44 +00:00
|
|
|
"net/url"
|
2022-01-08 15:42:54 +00:00
|
|
|
"regexp"
|
2021-01-25 21:57:12 +00:00
|
|
|
"strconv"
|
2021-01-19 18:56:43 +00:00
|
|
|
"strings"
|
|
|
|
)
|
2021-01-06 20:43:58 +00:00
|
|
|
|
|
|
|
// Prepend prefixes each lines of a string with the given prefix.
|
|
|
|
// It can be used to indent or quote (> ) a paragraph, for example.
|
|
|
|
func Prepend(text string, prefix string) string {
|
|
|
|
if text == "" || prefix == "" {
|
|
|
|
return text
|
|
|
|
}
|
|
|
|
|
|
|
|
lines := strings.SplitAfter(text, "\n")
|
|
|
|
if len(lines[len(lines)-1]) == 0 {
|
|
|
|
lines = lines[:len(lines)-1]
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.Join(append([]string{""}, lines...), prefix)
|
|
|
|
}
|
2021-01-15 21:21:33 +00:00
|
|
|
|
|
|
|
// Pluralize adds an `s` at the end of word if the count is more than 1.
|
|
|
|
func Pluralize(word string, count int) string {
|
|
|
|
if word == "" || (count >= -1 && count <= 1) {
|
|
|
|
return word
|
|
|
|
} else {
|
|
|
|
return word + "s"
|
|
|
|
}
|
|
|
|
}
|
2021-01-19 18:56:43 +00:00
|
|
|
|
|
|
|
// SplitLines splits a string by the newlines character in a portable way
|
|
|
|
// Using only `strings.Split(s, "\n")` doesn't work on Windows.
|
|
|
|
func SplitLines(s string) []string {
|
|
|
|
var lines []string
|
|
|
|
scanner := bufio.NewScanner(strings.NewReader(s))
|
2023-08-15 09:24:37 +00:00
|
|
|
// increase the buffer size to 2Mb
|
|
|
|
buf := []byte{}
|
|
|
|
scanner.Buffer(buf, 2048*1024)
|
2021-01-19 18:56:43 +00:00
|
|
|
for scanner.Scan() {
|
|
|
|
lines = append(lines, scanner.Text())
|
|
|
|
}
|
2023-08-15 09:24:37 +00:00
|
|
|
if err := scanner.Err(); err != nil {
|
|
|
|
log.Fatalf("error while scanning text: %v", err)
|
|
|
|
}
|
2021-01-19 18:56:43 +00:00
|
|
|
return lines
|
|
|
|
}
|
|
|
|
|
|
|
|
// JoinLines joins each lines of the given string by replacing the newlines by
|
|
|
|
// a single space.
|
|
|
|
func JoinLines(s string) string {
|
|
|
|
return strings.Join(SplitLines(s), " ")
|
|
|
|
}
|
2021-01-25 20:44:44 +00:00
|
|
|
|
2021-01-25 21:57:12 +00:00
|
|
|
// JoinInt64 joins a list of int64 into a single string with the given
|
|
|
|
// delimiter.
|
|
|
|
func JoinInt64(ints []int64, delimiter string) string {
|
|
|
|
strs := make([]string, 0)
|
|
|
|
for _, i := range ints {
|
|
|
|
strs = append(strs, strconv.FormatInt(i, 10))
|
|
|
|
}
|
|
|
|
return strings.Join(strs, delimiter)
|
|
|
|
}
|
|
|
|
|
2021-01-25 20:44:44 +00:00
|
|
|
// IsURL returns whether the given string is a valid URL.
|
|
|
|
func IsURL(s string) bool {
|
|
|
|
_, err := url.ParseRequestURI(s)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
u, err := url.Parse(s)
|
|
|
|
if err != nil || u.Scheme == "" || u.Host == "" {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
2021-01-31 11:24:33 +00:00
|
|
|
|
|
|
|
// RemoveDuplicates keeps only unique strings in the source.
|
|
|
|
func RemoveDuplicates(strings []string) []string {
|
2021-03-06 18:38:52 +00:00
|
|
|
if strings == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-01-31 11:24:33 +00:00
|
|
|
check := make(map[string]bool)
|
|
|
|
res := make([]string, 0)
|
|
|
|
for _, val := range strings {
|
|
|
|
if _, ok := check[val]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
check[val] = true
|
|
|
|
res = append(res, val)
|
|
|
|
}
|
|
|
|
|
|
|
|
return res
|
|
|
|
}
|
2021-03-24 20:06:32 +00:00
|
|
|
|
2021-11-14 08:50:13 +00:00
|
|
|
// RemoveBlank keeps only non-empty strings in the source.
|
|
|
|
func RemoveBlank(strs []string) []string {
|
|
|
|
if strs == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
res := make([]string, 0)
|
|
|
|
for _, val := range strs {
|
|
|
|
if strings.TrimSpace(val) != "" {
|
|
|
|
res = append(res, val)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2021-06-20 19:08:18 +00:00
|
|
|
// Expand literal escaped whitespace characters in the given string to their
|
|
|
|
// actual character.
|
|
|
|
func ExpandWhitespaceLiterals(s string) string {
|
|
|
|
s = strings.ReplaceAll(s, `\n`, "\n")
|
|
|
|
s = strings.ReplaceAll(s, `\t`, "\t")
|
|
|
|
return s
|
|
|
|
}
|
2021-12-11 17:25:40 +00:00
|
|
|
|
|
|
|
// Contains returns whether the given slice of strings contains the given
|
|
|
|
// string.
|
|
|
|
func Contains(s []string, e string) bool {
|
|
|
|
for _, a := range s {
|
|
|
|
if a == e {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
2022-01-08 15:42:54 +00:00
|
|
|
|
|
|
|
// WordAt returns the word found at the given character position.
|
|
|
|
// Credit https://github.com/aca/neuron-language-server/blob/450a7cff71c14e291ee85ff8a0614fa9d4dd5145/utils.go#L13
|
|
|
|
func WordAt(str string, index int) string {
|
|
|
|
wordIdxs := wordRegex.FindAllStringIndex(str, -1)
|
|
|
|
for _, wordIdx := range wordIdxs {
|
|
|
|
if wordIdx[0] <= index && index <= wordIdx[1] {
|
|
|
|
return str[wordIdx[0]:wordIdx[1]]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
var wordRegex = regexp.MustCompile(`[^ \t\n\f\r,;\[\]\"\']+`)
|
|
|
|
|
|
|
|
func CopyList(list []string) []string {
|
|
|
|
out := make([]string, len(list))
|
|
|
|
copy(out, list)
|
|
|
|
return out
|
|
|
|
}
|
2022-07-10 18:53:06 +00:00
|
|
|
|
|
|
|
func ByteIndexToRuneIndex(s string, i int) int {
|
|
|
|
res := 0
|
|
|
|
for j, _ := range s {
|
|
|
|
if j >= i {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
res += 1
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|