2015-07-25 04:35:07 -04:00
|
|
|
// Package stringutils provides helper functions for dealing with strings.
|
2015-03-24 07:25:26 -04:00
|
|
|
package stringutils
|
|
|
|
|
|
|
|
import (
|
2015-03-29 17:17:23 -04:00
|
|
|
"bytes"
|
2015-05-19 15:32:40 -04:00
|
|
|
"math/rand"
|
2015-03-29 17:17:23 -04:00
|
|
|
"strings"
|
2015-03-24 07:25:26 -04:00
|
|
|
)
|
|
|
|
|
2015-07-25 04:35:07 -04:00
|
|
|
// GenerateRandomAlphaOnlyString generates an alphabetical random string with length n.
|
2015-03-24 07:25:26 -04:00
|
|
|
func GenerateRandomAlphaOnlyString(n int) string {
|
|
|
|
// make a really long string
|
|
|
|
letters := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
|
|
b := make([]byte, n)
|
|
|
|
for i := range b {
|
2017-05-08 20:02:02 -04:00
|
|
|
b[i] = letters[rand.Intn(len(letters))]
|
2015-03-24 07:25:26 -04:00
|
|
|
}
|
|
|
|
return string(b)
|
|
|
|
}
|
|
|
|
|
2016-04-09 09:18:15 -04:00
|
|
|
// GenerateRandomASCIIString generates an ASCII random string with length n.
|
2015-07-25 04:35:07 -04:00
|
|
|
func GenerateRandomASCIIString(n int) string {
|
2015-03-24 07:25:26 -04:00
|
|
|
chars := "abcdefghijklmnopqrstuvwxyz" +
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
|
|
|
|
"~!@#$%^&*()-_+={}[]\\|<,>.?/\"';:` "
|
|
|
|
res := make([]byte, n)
|
|
|
|
for i := 0; i < n; i++ {
|
2015-05-19 15:32:40 -04:00
|
|
|
res[i] = chars[rand.Intn(len(chars))]
|
2015-03-24 07:25:26 -04:00
|
|
|
}
|
|
|
|
return string(res)
|
|
|
|
}
|
2015-03-29 17:17:23 -04:00
|
|
|
|
2016-08-10 09:54:14 -04:00
|
|
|
// Ellipsis truncates a string to fit within maxlen, and appends ellipsis (...).
|
|
|
|
// For maxlen of 3 and lower, no ellipsis is appended.
|
|
|
|
func Ellipsis(s string, maxlen int) string {
|
|
|
|
r := []rune(s)
|
|
|
|
if len(r) <= maxlen {
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
if maxlen <= 3 {
|
|
|
|
return string(r[:maxlen])
|
|
|
|
}
|
|
|
|
return string(r[:maxlen-3]) + "..."
|
|
|
|
}
|
|
|
|
|
2015-07-25 04:35:07 -04:00
|
|
|
// Truncate truncates a string to maxlen.
|
2015-03-29 17:17:23 -04:00
|
|
|
func Truncate(s string, maxlen int) string {
|
2016-08-10 09:54:14 -04:00
|
|
|
r := []rune(s)
|
|
|
|
if len(r) <= maxlen {
|
2015-03-29 17:17:23 -04:00
|
|
|
return s
|
|
|
|
}
|
2016-08-10 09:54:14 -04:00
|
|
|
return string(r[:maxlen])
|
2015-03-29 17:17:23 -04:00
|
|
|
}
|
|
|
|
|
2015-07-25 04:35:07 -04:00
|
|
|
// InSlice tests whether a string is contained in a slice of strings or not.
|
2015-03-29 17:17:23 -04:00
|
|
|
// Comparison is case insensitive
|
|
|
|
func InSlice(slice []string, s string) bool {
|
|
|
|
for _, ss := range slice {
|
|
|
|
if strings.ToLower(s) == strings.ToLower(ss) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func quote(word string, buf *bytes.Buffer) {
|
|
|
|
// Bail out early for "simple" strings
|
|
|
|
if word != "" && !strings.ContainsAny(word, "\\'\"`${[|&;<>()~*?! \t\n") {
|
|
|
|
buf.WriteString(word)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.WriteString("'")
|
|
|
|
|
|
|
|
for i := 0; i < len(word); i++ {
|
|
|
|
b := word[i]
|
|
|
|
if b == '\'' {
|
2016-12-19 01:45:48 -05:00
|
|
|
// Replace literal ' with a close ', a \', and an open '
|
2015-03-29 17:17:23 -04:00
|
|
|
buf.WriteString("'\\''")
|
|
|
|
} else {
|
|
|
|
buf.WriteByte(b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.WriteString("'")
|
|
|
|
}
|
|
|
|
|
2015-07-25 04:35:07 -04:00
|
|
|
// ShellQuoteArguments takes a list of strings and escapes them so they will be
|
2016-04-09 09:18:15 -04:00
|
|
|
// handled right when passed as arguments to a program via a shell
|
2015-03-29 17:17:23 -04:00
|
|
|
func ShellQuoteArguments(args []string) string {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
for i, arg := range args {
|
|
|
|
if i != 0 {
|
|
|
|
buf.WriteByte(' ')
|
|
|
|
}
|
|
|
|
quote(arg, &buf)
|
|
|
|
}
|
|
|
|
return buf.String()
|
|
|
|
}
|