diff options
author | Cameron Moore <moorereason@gmail.com> | 2016-03-09 14:40:00 -0600 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2016-03-10 17:47:59 +0100 |
commit | ce9ee3cf490ab5485b6ad7aa7a47d9fa9d176fa3 (patch) | |
tree | b22524babedb88d1dca06ad2e9416d8a0fb03ee4 /tpl | |
parent | 0962470850ed6802b645d5bd6663db60807c8f5b (diff) |
tpl: Add default function
Diffstat (limited to 'tpl')
-rw-r--r-- | tpl/template_funcs.go | 39 | ||||
-rw-r--r-- | tpl/template_funcs_test.go | 45 |
2 files changed, 81 insertions, 3 deletions
diff --git a/tpl/template_funcs.go b/tpl/template_funcs.go index 1cbc7d32b..8a0672726 100644 --- a/tpl/template_funcs.go +++ b/tpl/template_funcs.go @@ -1239,6 +1239,44 @@ func dateFormat(layout string, v interface{}) (string, error) { return t.Format(layout), nil } +// dfault checks whether a given value is set and returns a default value if it +// is not. "Set" in this context means true for booleans; non-zero for numeric +// types; non-zero length for strings, arrays, slices, and maps; any struct +// value; or non-nil for any other types. +func dfault(dflt, given interface{}) interface{} { + g := reflect.ValueOf(given) + if !g.IsValid() { + return dflt + } + + set := false + + switch g.Kind() { + case reflect.Bool: + set = g.Bool() + case reflect.String, reflect.Array, reflect.Slice, reflect.Map: + set = g.Len() != 0 + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + set = g.Int() != 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + set = g.Uint() != 0 + case reflect.Float32, reflect.Float64: + set = g.Float() != 0 + case reflect.Complex64, reflect.Complex128: + set = g.Complex() != 0 + case reflect.Struct: + set = true + default: + set = !g.IsNil() + } + + if set { + return given + } + + return dflt +} + // safeHTMLAttr returns a given string as html/template HTMLAttr content. // // safeHTMLAttr is currently disabled, pending further discussion @@ -1537,6 +1575,7 @@ func init() { "chomp": chomp, "countrunes": countRunes, "countwords": countWords, + "default": dfault, "dateFormat": dateFormat, "delimit": delimit, "dict": dictionary, diff --git a/tpl/template_funcs_test.go b/tpl/template_funcs_test.go index 878b31d20..ae1161f27 100644 --- a/tpl/template_funcs_test.go +++ b/tpl/template_funcs_test.go @@ -18,9 +18,6 @@ import ( "encoding/base64" "errors" "fmt" - "github.com/spf13/cast" - "github.com/spf13/viper" - "github.com/stretchr/testify/assert" "html/template" "math/rand" "path" @@ -29,6 +26,10 @@ import ( "strings" "testing" "time" + + "github.com/spf13/cast" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" ) type tstNoStringer struct { @@ -1843,6 +1844,44 @@ func TestDateFormat(t *testing.T) { } } +func TestDefault(t *testing.T) { + for i, this := range []struct { + dflt interface{} + given interface{} + expected interface{} + }{ + {"5", 0, "5"}, + + {"test1", "set", "set"}, + {"test2", "", "test2"}, + + {[2]int{10, 20}, [2]int{1, 2}, [2]int{1, 2}}, + {[2]int{10, 20}, [0]int{}, [2]int{10, 20}}, + + {[]string{"one"}, []string{"uno"}, []string{"uno"}}, + {[]string{"one"}, []string{}, []string{"one"}}, + + {map[string]int{"one": 1}, map[string]int{"uno": 1}, map[string]int{"uno": 1}}, + {map[string]int{"one": 1}, map[string]int{}, map[string]int{"one": 1}}, + + {10, 1, 1}, + {10, 0, 10}, + + {float32(10), float32(1), float32(1)}, + {float32(10), 0, float32(10)}, + + {complex(2, -2), complex(1, -1), complex(1, -1)}, + {complex(2, -2), complex(0, 0), complex(2, -2)}, + + {struct{ f string }{f: "one"}, struct{ f string }{}, struct{ f string }{}}, + } { + res := dfault(this.dflt, this.given) + if !reflect.DeepEqual(this.expected, res) { + t.Errorf("[%d] default returned %v, but expected %v", i, res, this.expected) + } + } +} + func TestSafeHTML(t *testing.T) { for i, this := range []struct { str string |