123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- package templatelib
- import (
- "encoding/json"
- "fmt"
- "os"
- "reflect"
- "strings"
- "text/template"
- )
- func swapStringsFuncBoolArgsOrder(a func(string, string) bool) func(string, string) bool {
- return func(str1 string, str2 string) bool {
- return a(str2, str1)
- }
- }
- func thingsActionFactory(name string, actOnFirst bool, action func([]interface{}, interface{}) interface{}) func(args ...interface{}) interface{} {
- return func(args ...interface{}) interface{} {
- if len(args) < 1 {
- panic(fmt.Sprintf(`%q requires at least one argument`, name))
- }
- actArgs := []interface{}{}
- for _, val := range args {
- v := reflect.ValueOf(val)
- switch v.Kind() {
- case reflect.Slice, reflect.Array:
- for i := 0; i < v.Len(); i++ {
- actArgs = append(actArgs, v.Index(i).Interface())
- }
- default:
- actArgs = append(actArgs, v.Interface())
- }
- }
- var arg interface{}
- if actOnFirst {
- arg = actArgs[0]
- actArgs = actArgs[1:]
- } else {
- arg = actArgs[len(actArgs)-1]
- actArgs = actArgs[:len(actArgs)-1]
- }
- return action(actArgs, arg)
- }
- }
- func stringsActionFactory(name string, actOnFirst bool, action func([]string, string) string) func(args ...interface{}) interface{} {
- return thingsActionFactory(name, actOnFirst, func(args []interface{}, arg interface{}) interface{} {
- str := arg.(string)
- strs := []string{}
- for _, val := range args {
- strs = append(strs, val.(string))
- }
- return action(strs, str)
- })
- }
- func stringsModifierActionFactory(a func(string, string) string) func([]string, string) string {
- return func(strs []string, str string) string {
- for _, mod := range strs {
- str = a(str, mod)
- }
- return str
- }
- }
- var FuncMap = template.FuncMap{
- // {{- $isGitHub := hasPrefix "https://github.com/" $url -}}
- // {{- $isHtml := hasSuffix ".html" $url -}}
- "hasPrefix": swapStringsFuncBoolArgsOrder(strings.HasPrefix),
- "hasSuffix": swapStringsFuncBoolArgsOrder(strings.HasSuffix),
- // {{- $hugeIfTrue := .SomeValue | ternary "HUGE" "not so huge" -}}
- // if .SomeValue is truthy, $hugeIfTrue will be "HUGE"
- // (otherwise, "not so huge")
- "ternary": func(truthy interface{}, falsey interface{}, val interface{}) interface{} {
- if t, ok := template.IsTrue(val); !ok {
- panic(fmt.Sprintf(`template.IsTrue(%+v) says things are NOT OK`, val))
- } else if t {
- return truthy
- } else {
- return falsey
- }
- },
- // First Tag: {{- .Tags | first -}}
- // Last Tag: {{- .Tags | last -}}
- "first": thingsActionFactory("first", true, func(args []interface{}, arg interface{}) interface{} { return arg }),
- "last": thingsActionFactory("last", false, func(args []interface{}, arg interface{}) interface{} { return arg }),
- // JSON data dump: {{ json . }}
- // (especially nice for taking data and piping it to "jq")
- // (ie "some-tool inspect --format '{{ json . }}' some-things | jq .")
- "json": func(v interface{}) (string, error) {
- j, err := json.Marshal(v)
- return string(j), err
- },
- // Everybody: {{- join ", " .Names -}}
- // Concat: {{- join "/" "https://github.com" "jsmith" "some-repo" -}}
- "join": stringsActionFactory("join", true, strings.Join),
- // {{- $mungedUrl := $url | replace "git://" "https://" | trimSuffixes ".git" -}}
- // turns: git://github.com/jsmith/some-repo.git
- // into: https://github.com/jsmith/some-repo
- "trimPrefixes": stringsActionFactory("trimPrefixes", false, stringsModifierActionFactory(strings.TrimPrefix)),
- "trimSuffixes": stringsActionFactory("trimSuffixes", false, stringsModifierActionFactory(strings.TrimSuffix)),
- "replace": stringsActionFactory("replace", false, func(strs []string, str string) string {
- return strings.NewReplacer(strs...).Replace(str)
- }),
- // {{- getenv "PATH" -}}
- // {{- getenv "HOME" "no HOME set" -}}
- // {{- getenv "HOME" "is set" "is NOT set (or is empty)" -}}
- "getenv": thingsActionFactory("getenv", true, func(args []interface{}, arg interface{}) interface{} {
- var (
- val = os.Getenv(arg.(string))
- setVal interface{} = val
- unsetVal interface{} = ""
- )
- if len(args) == 2 {
- setVal, unsetVal = args[0], args[1]
- } else if len(args) == 1 {
- unsetVal = args[0]
- } else if len(args) != 0 {
- panic(fmt.Sprintf(`expected between 1 and 3 arguments to "getenv", got %d`, len(args)+1))
- }
- if val != "" {
- return setVal
- } else {
- return unsetVal
- }
- }),
- }
|