list.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. package sprig
  2. import (
  3. "fmt"
  4. "reflect"
  5. "sort"
  6. )
  7. // Reflection is used in these functions so that slices and arrays of strings,
  8. // ints, and other types not implementing []interface{} can be worked with.
  9. // For example, this is useful if you need to work on the output of regexs.
  10. func list(v ...interface{}) []interface{} {
  11. return v
  12. }
  13. func push(list interface{}, v interface{}) []interface{} {
  14. tp := reflect.TypeOf(list).Kind()
  15. switch tp {
  16. case reflect.Slice, reflect.Array:
  17. l2 := reflect.ValueOf(list)
  18. l := l2.Len()
  19. nl := make([]interface{}, l)
  20. for i := 0; i < l; i++ {
  21. nl[i] = l2.Index(i).Interface()
  22. }
  23. return append(nl, v)
  24. default:
  25. panic(fmt.Sprintf("Cannot push on type %s", tp))
  26. }
  27. }
  28. func prepend(list interface{}, v interface{}) []interface{} {
  29. //return append([]interface{}{v}, list...)
  30. tp := reflect.TypeOf(list).Kind()
  31. switch tp {
  32. case reflect.Slice, reflect.Array:
  33. l2 := reflect.ValueOf(list)
  34. l := l2.Len()
  35. nl := make([]interface{}, l)
  36. for i := 0; i < l; i++ {
  37. nl[i] = l2.Index(i).Interface()
  38. }
  39. return append([]interface{}{v}, nl...)
  40. default:
  41. panic(fmt.Sprintf("Cannot prepend on type %s", tp))
  42. }
  43. }
  44. func last(list interface{}) interface{} {
  45. tp := reflect.TypeOf(list).Kind()
  46. switch tp {
  47. case reflect.Slice, reflect.Array:
  48. l2 := reflect.ValueOf(list)
  49. l := l2.Len()
  50. if l == 0 {
  51. return nil
  52. }
  53. return l2.Index(l - 1).Interface()
  54. default:
  55. panic(fmt.Sprintf("Cannot find last on type %s", tp))
  56. }
  57. }
  58. func first(list interface{}) interface{} {
  59. tp := reflect.TypeOf(list).Kind()
  60. switch tp {
  61. case reflect.Slice, reflect.Array:
  62. l2 := reflect.ValueOf(list)
  63. l := l2.Len()
  64. if l == 0 {
  65. return nil
  66. }
  67. return l2.Index(0).Interface()
  68. default:
  69. panic(fmt.Sprintf("Cannot find first on type %s", tp))
  70. }
  71. }
  72. func rest(list interface{}) []interface{} {
  73. tp := reflect.TypeOf(list).Kind()
  74. switch tp {
  75. case reflect.Slice, reflect.Array:
  76. l2 := reflect.ValueOf(list)
  77. l := l2.Len()
  78. if l == 0 {
  79. return nil
  80. }
  81. nl := make([]interface{}, l-1)
  82. for i := 1; i < l; i++ {
  83. nl[i-1] = l2.Index(i).Interface()
  84. }
  85. return nl
  86. default:
  87. panic(fmt.Sprintf("Cannot find rest on type %s", tp))
  88. }
  89. }
  90. func initial(list interface{}) []interface{} {
  91. tp := reflect.TypeOf(list).Kind()
  92. switch tp {
  93. case reflect.Slice, reflect.Array:
  94. l2 := reflect.ValueOf(list)
  95. l := l2.Len()
  96. if l == 0 {
  97. return nil
  98. }
  99. nl := make([]interface{}, l-1)
  100. for i := 0; i < l-1; i++ {
  101. nl[i] = l2.Index(i).Interface()
  102. }
  103. return nl
  104. default:
  105. panic(fmt.Sprintf("Cannot find initial on type %s", tp))
  106. }
  107. }
  108. func sortAlpha(list interface{}) []string {
  109. k := reflect.Indirect(reflect.ValueOf(list)).Kind()
  110. switch k {
  111. case reflect.Slice, reflect.Array:
  112. a := strslice(list)
  113. s := sort.StringSlice(a)
  114. s.Sort()
  115. return s
  116. }
  117. return []string{strval(list)}
  118. }
  119. func reverse(v interface{}) []interface{} {
  120. tp := reflect.TypeOf(v).Kind()
  121. switch tp {
  122. case reflect.Slice, reflect.Array:
  123. l2 := reflect.ValueOf(v)
  124. l := l2.Len()
  125. // We do not sort in place because the incoming array should not be altered.
  126. nl := make([]interface{}, l)
  127. for i := 0; i < l; i++ {
  128. nl[l-i-1] = l2.Index(i).Interface()
  129. }
  130. return nl
  131. default:
  132. panic(fmt.Sprintf("Cannot find reverse on type %s", tp))
  133. }
  134. }
  135. func compact(list interface{}) []interface{} {
  136. tp := reflect.TypeOf(list).Kind()
  137. switch tp {
  138. case reflect.Slice, reflect.Array:
  139. l2 := reflect.ValueOf(list)
  140. l := l2.Len()
  141. nl := []interface{}{}
  142. var item interface{}
  143. for i := 0; i < l; i++ {
  144. item = l2.Index(i).Interface()
  145. if !empty(item) {
  146. nl = append(nl, item)
  147. }
  148. }
  149. return nl
  150. default:
  151. panic(fmt.Sprintf("Cannot compact on type %s", tp))
  152. }
  153. }
  154. func uniq(list interface{}) []interface{} {
  155. tp := reflect.TypeOf(list).Kind()
  156. switch tp {
  157. case reflect.Slice, reflect.Array:
  158. l2 := reflect.ValueOf(list)
  159. l := l2.Len()
  160. dest := []interface{}{}
  161. var item interface{}
  162. for i := 0; i < l; i++ {
  163. item = l2.Index(i).Interface()
  164. if !inList(dest, item) {
  165. dest = append(dest, item)
  166. }
  167. }
  168. return dest
  169. default:
  170. panic(fmt.Sprintf("Cannot find uniq on type %s", tp))
  171. }
  172. }
  173. func inList(haystack []interface{}, needle interface{}) bool {
  174. for _, h := range haystack {
  175. if reflect.DeepEqual(needle, h) {
  176. return true
  177. }
  178. }
  179. return false
  180. }
  181. func without(list interface{}, omit ...interface{}) []interface{} {
  182. tp := reflect.TypeOf(list).Kind()
  183. switch tp {
  184. case reflect.Slice, reflect.Array:
  185. l2 := reflect.ValueOf(list)
  186. l := l2.Len()
  187. res := []interface{}{}
  188. var item interface{}
  189. for i := 0; i < l; i++ {
  190. item = l2.Index(i).Interface()
  191. if !inList(omit, item) {
  192. res = append(res, item)
  193. }
  194. }
  195. return res
  196. default:
  197. panic(fmt.Sprintf("Cannot find without on type %s", tp))
  198. }
  199. }
  200. func has(needle interface{}, haystack interface{}) bool {
  201. if haystack == nil {
  202. return false
  203. }
  204. tp := reflect.TypeOf(haystack).Kind()
  205. switch tp {
  206. case reflect.Slice, reflect.Array:
  207. l2 := reflect.ValueOf(haystack)
  208. var item interface{}
  209. l := l2.Len()
  210. for i := 0; i < l; i++ {
  211. item = l2.Index(i).Interface()
  212. if reflect.DeepEqual(needle, item) {
  213. return true
  214. }
  215. }
  216. return false
  217. default:
  218. panic(fmt.Sprintf("Cannot find has on type %s", tp))
  219. }
  220. }
  221. // $list := [1, 2, 3, 4, 5]
  222. // slice $list -> list[0:5] = list[:]
  223. // slice $list 0 3 -> list[0:3] = list[:3]
  224. // slice $list 3 5 -> list[3:5]
  225. // slice $list 3 -> list[3:5] = list[3:]
  226. func slice(list interface{}, indices ...interface{}) interface{} {
  227. tp := reflect.TypeOf(list).Kind()
  228. switch tp {
  229. case reflect.Slice, reflect.Array:
  230. l2 := reflect.ValueOf(list)
  231. l := l2.Len()
  232. if l == 0 {
  233. return nil
  234. }
  235. var start, end int
  236. if len(indices) > 0 {
  237. start = toInt(indices[0])
  238. }
  239. if len(indices) < 2 {
  240. end = l
  241. } else {
  242. end = toInt(indices[1])
  243. }
  244. return l2.Slice(start, end).Interface()
  245. default:
  246. panic(fmt.Sprintf("list should be type of slice or array but %s", tp))
  247. }
  248. }
  249. func concat(lists ...interface{}) interface{} {
  250. var res []interface{}
  251. for _, list := range lists {
  252. tp := reflect.TypeOf(list).Kind()
  253. switch tp {
  254. case reflect.Slice, reflect.Array:
  255. l2 := reflect.ValueOf(list)
  256. for i := 0; i < l2.Len(); i++ {
  257. res = append(res, l2.Index(i).Interface())
  258. }
  259. default:
  260. panic(fmt.Sprintf("Cannot concat type %s as list", tp))
  261. }
  262. }
  263. return res
  264. }