diff options
| author | Ondřej Surý <ondrej@sury.org> | 2011-08-10 15:05:15 +0200 |
|---|---|---|
| committer | Ondřej Surý <ondrej@sury.org> | 2011-08-10 15:05:15 +0200 |
| commit | 825e92f34920934f09dbf4c614dbd2913ba464cb (patch) | |
| tree | 2af4eb446f544e17f65b34ad2b9668d2bb8ab78b /src/pkg/exp/template/funcs.go | |
| parent | e6b380032482808aee5e4c5222b6d7390f468e74 (diff) | |
| download | golang-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.go | 73 |
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) +} |
