summaryrefslogtreecommitdiff
path: root/src/pkg/exp/template/funcs.go
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-08-10 15:05:15 +0200
committerOndřej Surý <ondrej@sury.org>2011-08-10 15:05:15 +0200
commit825e92f34920934f09dbf4c614dbd2913ba464cb (patch)
tree2af4eb446f544e17f65b34ad2b9668d2bb8ab78b /src/pkg/exp/template/funcs.go
parente6b380032482808aee5e4c5222b6d7390f468e74 (diff)
downloadgolang-825e92f34920934f09dbf4c614dbd2913ba464cb.tar.gz
Imported Upstream version 2011.08.10upstream-weekly/2011.08.10
Diffstat (limited to 'src/pkg/exp/template/funcs.go')
-rw-r--r--src/pkg/exp/template/funcs.go73
1 files changed, 53 insertions, 20 deletions
diff --git a/src/pkg/exp/template/funcs.go b/src/pkg/exp/template/funcs.go
index 58b2bafd8..579c70099 100644
--- a/src/pkg/exp/template/funcs.go
+++ b/src/pkg/exp/template/funcs.go
@@ -7,6 +7,7 @@ package template
import (
"bytes"
"fmt"
+ "http"
"io"
"os"
"reflect"
@@ -21,21 +22,31 @@ import (
// during execution, execution terminates and Execute returns an error.
type FuncMap map[string]interface{}
-var funcs = map[string]reflect.Value{
- "and": reflect.ValueOf(and),
- "html": reflect.ValueOf(HTMLEscaper),
- "index": reflect.ValueOf(index),
- "js": reflect.ValueOf(JSEscaper),
- "not": reflect.ValueOf(not),
- "or": reflect.ValueOf(or),
- "print": reflect.ValueOf(fmt.Sprint),
- "printf": reflect.ValueOf(fmt.Sprintf),
- "println": reflect.ValueOf(fmt.Sprintln),
+var builtins = FuncMap{
+ "and": and,
+ "html": HTMLEscaper,
+ "index": index,
+ "js": JSEscaper,
+ "not": not,
+ "or": or,
+ "print": fmt.Sprint,
+ "printf": fmt.Sprintf,
+ "println": fmt.Sprintln,
+ "url": URLEscaper,
}
-// addFuncs adds to values the functions in funcs, converting them to reflect.Values.
-func addFuncs(values map[string]reflect.Value, funcMap FuncMap) {
- for name, fn := range funcMap {
+var builtinFuncs = createValueFuncs(builtins)
+
+// createValueFuncs turns a FuncMap into a map[string]reflect.Value
+func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
+ m := make(map[string]reflect.Value)
+ addValueFuncs(m, funcMap)
+ return m
+}
+
+// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
+func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
+ for name, fn := range in {
v := reflect.ValueOf(fn)
if v.Kind() != reflect.Func {
panic("value for " + name + " not a function")
@@ -43,7 +54,15 @@ func addFuncs(values map[string]reflect.Value, funcMap FuncMap) {
if !goodFunc(v.Type()) {
panic(fmt.Errorf("can't handle multiple results from method/function %q", name))
}
- values[name] = v
+ out[name] = v
+ }
+}
+
+// addFuncs adds to values the functions in funcs. It does no checking of the input -
+// call addValueFuncs first.
+func addFuncs(out, in FuncMap) {
+ for name, fn := range in {
+ out[name] = fn
}
}
@@ -62,16 +81,16 @@ func goodFunc(typ reflect.Type) bool {
// findFunction looks for a function in the template, set, and global map.
func findFunction(name string, tmpl *Template, set *Set) (reflect.Value, bool) {
if tmpl != nil {
- if fn := tmpl.funcs[name]; fn.IsValid() {
+ if fn := tmpl.execFuncs[name]; fn.IsValid() {
return fn, true
}
}
if set != nil {
- if fn := set.funcs[name]; fn.IsValid() {
+ if fn := set.execFuncs[name]; fn.IsValid() {
return fn, true
}
}
- if fn := funcs[name]; fn.IsValid() {
+ if fn := builtinFuncs[name]; fn.IsValid() {
return fn, true
}
return reflect.Value{}, false
@@ -109,9 +128,10 @@ func index(item interface{}, indices ...interface{}) (interface{}, os.Error) {
if !index.Type().AssignableTo(v.Type().Key()) {
return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
}
- v = v.MapIndex(index)
- if !v.IsValid() {
- return nil, fmt.Errorf("index %v not present in map", index.Interface())
+ if x := v.MapIndex(index); x.IsValid() {
+ v = x
+ } else {
+ v = reflect.Zero(v.Type().Key())
}
default:
return nil, fmt.Errorf("can't index item of type %s", index.Type())
@@ -317,3 +337,16 @@ func JSEscaper(args ...interface{}) string {
}
return JSEscapeString(s)
}
+
+// URLEscaper returns the escaped value of the textual representation of its
+// arguments in a form suitable for embedding in a URL.
+func URLEscaper(args ...interface{}) string {
+ s, ok := "", false
+ if len(args) == 1 {
+ s, ok = args[0].(string)
+ }
+ if !ok {
+ s = fmt.Sprint(args...)
+ }
+ return http.URLEscape(s)
+}