]> Cypherpunks repositories - gostls13.git/commitdiff
exp/template: add builtin len function
authorRob Pike <r@golang.org>
Fri, 12 Aug 2011 01:47:44 +0000 (11:47 +1000)
committerRob Pike <r@golang.org>
Fri, 12 Aug 2011 01:47:44 +0000 (11:47 +1000)
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/4868045

src/pkg/exp/template/doc.go
src/pkg/exp/template/exec_test.go
src/pkg/exp/template/funcs.go

index ef9e1563b950a23de555729409e7f0c06a187245..ed0172ac8e6b64e3d1cadd5169a92fd43d6b6e97 100644 (file)
@@ -232,6 +232,8 @@ Predefined global functions are named as follows.
        js
                Returns the escaped JavaScript equivalent of the textual
                representation of its arguments.
+       len
+               Returns the integer length of its argument.
        not
                Returns the boolean negation of its single argument.
        or
index 18dbcee3ea034b60a6c878fe2278ad341780376a..50f159190681b5f4545f29ff79cc74b246619820 100644 (file)
@@ -331,6 +331,12 @@ var execTests = []execTest{
        {"map[WRONG]", "{{index .MSI 10}}", "", tVal, false},
        {"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true},
 
+       // Len.
+       {"slice", "{{len .SI}}", "3", tVal, true},
+       {"map", "{{len .MSI }}", "3", tVal, true},
+       {"len of int", "{{len 3}}", "", tVal, false},
+       {"len of nothing", "{{len .Empty0}}", "", tVal, false},
+
        // With.
        {"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true},
        {"with false", "{{with false}}{{.}}{{else}}FALSE{{end}}", "FALSE", tVal, true},
index 579c70099cbb54e3968bfbb3c37f1bec517ef938..b2878a161b3de2b1555e755449e2fd1c57fed737 100644 (file)
@@ -27,6 +27,7 @@ var builtins = FuncMap{
        "html":    HTMLEscaper,
        "index":   index,
        "js":      JSEscaper,
+       "len":     length,
        "not":     not,
        "or":      or,
        "print":   fmt.Sprint,
@@ -140,6 +141,21 @@ func index(item interface{}, indices ...interface{}) (interface{}, os.Error) {
        return v.Interface(), nil
 }
 
+// Length
+
+// length returns the length of the item, with an error if it has no defined length.
+func length(item interface{}) (int, os.Error) {
+       v, isNil := indirect(reflect.ValueOf(item))
+       if isNil {
+               return 0, fmt.Errorf("len of nil pointer")
+       }
+       switch v.Kind() {
+       case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
+               return v.Len(), nil
+       }
+       return 0, fmt.Errorf("len of type %s", v.Type())
+}
+
 // Boolean logic.
 
 func truth(a interface{}) bool {