strings.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package sprig
  2. import (
  3. "encoding/base32"
  4. "encoding/base64"
  5. "fmt"
  6. "reflect"
  7. "strconv"
  8. "strings"
  9. util "github.com/Masterminds/goutils"
  10. )
  11. func base64encode(v string) string {
  12. return base64.StdEncoding.EncodeToString([]byte(v))
  13. }
  14. func base64decode(v string) string {
  15. data, err := base64.StdEncoding.DecodeString(v)
  16. if err != nil {
  17. return err.Error()
  18. }
  19. return string(data)
  20. }
  21. func base32encode(v string) string {
  22. return base32.StdEncoding.EncodeToString([]byte(v))
  23. }
  24. func base32decode(v string) string {
  25. data, err := base32.StdEncoding.DecodeString(v)
  26. if err != nil {
  27. return err.Error()
  28. }
  29. return string(data)
  30. }
  31. func abbrev(width int, s string) string {
  32. if width < 4 {
  33. return s
  34. }
  35. r, _ := util.Abbreviate(s, width)
  36. return r
  37. }
  38. func abbrevboth(left, right int, s string) string {
  39. if right < 4 || left > 0 && right < 7 {
  40. return s
  41. }
  42. r, _ := util.AbbreviateFull(s, left, right)
  43. return r
  44. }
  45. func initials(s string) string {
  46. // Wrap this just to eliminate the var args, which templates don't do well.
  47. return util.Initials(s)
  48. }
  49. func randAlphaNumeric(count int) string {
  50. // It is not possible, it appears, to actually generate an error here.
  51. r, _ := util.CryptoRandomAlphaNumeric(count)
  52. return r
  53. }
  54. func randAlpha(count int) string {
  55. r, _ := util.CryptoRandomAlphabetic(count)
  56. return r
  57. }
  58. func randAscii(count int) string {
  59. r, _ := util.CryptoRandomAscii(count)
  60. return r
  61. }
  62. func randNumeric(count int) string {
  63. r, _ := util.CryptoRandomNumeric(count)
  64. return r
  65. }
  66. func untitle(str string) string {
  67. return util.Uncapitalize(str)
  68. }
  69. func quote(str ...interface{}) string {
  70. out := make([]string, 0, len(str))
  71. for _, s := range str {
  72. if s != nil {
  73. out = append(out, fmt.Sprintf("%q", strval(s)))
  74. }
  75. }
  76. return strings.Join(out, " ")
  77. }
  78. func squote(str ...interface{}) string {
  79. out := make([]string, 0, len(str))
  80. for _, s := range str {
  81. if s != nil {
  82. out = append(out, fmt.Sprintf("'%v'", s))
  83. }
  84. }
  85. return strings.Join(out, " ")
  86. }
  87. func cat(v ...interface{}) string {
  88. v = removeNilElements(v)
  89. r := strings.TrimSpace(strings.Repeat("%v ", len(v)))
  90. return fmt.Sprintf(r, v...)
  91. }
  92. func indent(spaces int, v string) string {
  93. pad := strings.Repeat(" ", spaces)
  94. return pad + strings.Replace(v, "\n", "\n"+pad, -1)
  95. }
  96. func nindent(spaces int, v string) string {
  97. return "\n" + indent(spaces, v)
  98. }
  99. func replace(old, new, src string) string {
  100. return strings.Replace(src, old, new, -1)
  101. }
  102. func plural(one, many string, count int) string {
  103. if count == 1 {
  104. return one
  105. }
  106. return many
  107. }
  108. func strslice(v interface{}) []string {
  109. switch v := v.(type) {
  110. case []string:
  111. return v
  112. case []interface{}:
  113. b := make([]string, 0, len(v))
  114. for _, s := range v {
  115. if s != nil {
  116. b = append(b, strval(s))
  117. }
  118. }
  119. return b
  120. default:
  121. val := reflect.ValueOf(v)
  122. switch val.Kind() {
  123. case reflect.Array, reflect.Slice:
  124. l := val.Len()
  125. b := make([]string, 0, l)
  126. for i := 0; i < l; i++ {
  127. value := val.Index(i).Interface()
  128. if value != nil {
  129. b = append(b, strval(value))
  130. }
  131. }
  132. return b
  133. default:
  134. if v == nil {
  135. return []string{}
  136. } else {
  137. return []string{strval(v)}
  138. }
  139. }
  140. }
  141. }
  142. func removeNilElements(v []interface{}) []interface{} {
  143. newSlice := make([]interface{}, 0, len(v))
  144. for _, i := range v {
  145. if i != nil {
  146. newSlice = append(newSlice, i)
  147. }
  148. }
  149. return newSlice
  150. }
  151. func strval(v interface{}) string {
  152. switch v := v.(type) {
  153. case string:
  154. return v
  155. case []byte:
  156. return string(v)
  157. case error:
  158. return v.Error()
  159. case fmt.Stringer:
  160. return v.String()
  161. default:
  162. return fmt.Sprintf("%v", v)
  163. }
  164. }
  165. func trunc(c int, s string) string {
  166. if len(s) <= c {
  167. return s
  168. }
  169. return s[0:c]
  170. }
  171. func join(sep string, v interface{}) string {
  172. return strings.Join(strslice(v), sep)
  173. }
  174. func split(sep, orig string) map[string]string {
  175. parts := strings.Split(orig, sep)
  176. res := make(map[string]string, len(parts))
  177. for i, v := range parts {
  178. res["_"+strconv.Itoa(i)] = v
  179. }
  180. return res
  181. }
  182. func splitn(sep string, n int, orig string) map[string]string {
  183. parts := strings.SplitN(orig, sep, n)
  184. res := make(map[string]string, len(parts))
  185. for i, v := range parts {
  186. res["_"+strconv.Itoa(i)] = v
  187. }
  188. return res
  189. }
  190. // substring creates a substring of the given string.
  191. //
  192. // If start is < 0, this calls string[:end].
  193. //
  194. // If start is >= 0 and end < 0 or end bigger than s length, this calls string[start:]
  195. //
  196. // Otherwise, this calls string[start, end].
  197. func substring(start, end int, s string) string {
  198. if start < 0 {
  199. return s[:end]
  200. }
  201. if end < 0 || end > len(s) {
  202. return s[start:]
  203. }
  204. return s[start:end]
  205. }