diff options
Diffstat (limited to 'libgo/go/text/template')
-rw-r--r-- | libgo/go/text/template/doc.go | 24 | ||||
-rw-r--r-- | libgo/go/text/template/exec.go | 10 | ||||
-rw-r--r-- | libgo/go/text/template/exec_test.go | 8 | ||||
-rw-r--r-- | libgo/go/text/template/multi_test.go | 2 | ||||
-rw-r--r-- | libgo/go/text/template/parse/parse.go | 6 | ||||
-rw-r--r-- | libgo/go/text/template/template.go | 8 |
6 files changed, 47 insertions, 11 deletions
diff --git a/libgo/go/text/template/doc.go b/libgo/go/text/template/doc.go index 35c4c681183..ae91f4a5419 100644 --- a/libgo/go/text/template/doc.go +++ b/libgo/go/text/template/doc.go @@ -22,6 +22,20 @@ Actions may not span newlines, although comments can. Once constructed, a template may be executed safely in parallel. +Here is a trivial example that prints "17 items are made of wool". + + type Inventory struct { + Material string + Count uint + } + sweaters := Inventory{"wool", 17} + tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}") + if err != nil { panic(err) } + err = tmpl.Execute(os.Stdout, sweaters) + if err != nil { panic(err) } + +More intricate examples appear below. + Actions Here is the list of actions. "Arguments" and "pipelines" are evaluations of @@ -128,6 +142,11 @@ An argument is a simple value, denoted by one of the following. .Field1.Key1.Method1.Field2.Key2.Method2 Methods can also be evaluated on variables, including chaining: $x.Method1.Field + - The name of a niladic function-valued struct field of the data, + preceded by a period, such as + .Function + Function-valued fields behave like methods (of structs) but do not + pass a receiver. - The name of a niladic function, such as fun The result is the value of invoking the function, fun(). The return @@ -148,6 +167,9 @@ value (argument) or a function or method call, possibly with multiple arguments: The result is the value of calling the method with the arguments: dot.Method(Argument1, etc.) + .Function [Argument...] + A function-valued field of a struct works like a method but does + not pass the receiver. functionName [Argument...] The result is the value of calling the function associated with the name: @@ -303,7 +325,7 @@ produce the text By construction, a template may reside in only one association. If it's necessary to have a template addressable from multiple associations, the template definition must be parsed multiple times to create distinct *Template -values. +values, or must be copied with the Clone or AddParseTree method. Parse may be called multiple times to assemble the various associated templates; see the ParseFiles and ParseGlob functions and methods for simple ways to parse diff --git a/libgo/go/text/template/exec.go b/libgo/go/text/template/exec.go index 973189a8a62..af745286c0b 100644 --- a/libgo/go/text/template/exec.go +++ b/libgo/go/text/template/exec.go @@ -419,10 +419,14 @@ func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node tField, ok := receiver.Type().FieldByName(fieldName) if ok { field := receiver.FieldByIndex(tField.Index) - if hasArgs { - s.errorf("%s is not a method but has arguments", fieldName) - } if tField.PkgPath == "" { // field is exported + // If it's a function, we must call it. + if field.Type().Kind() == reflect.Func { + return s.evalCall(dot, field, fieldName, args, final) + } + if hasArgs { + s.errorf("%s is not a method or function but has arguments", fieldName) + } return field } } diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go index 9bb55e48aac..159cf5100d9 100644 --- a/libgo/go/text/template/exec_test.go +++ b/libgo/go/text/template/exec_test.go @@ -59,6 +59,8 @@ type T struct { PI *int PSI *[]int NIL *int + // Function (not method) + Func func(...string) string // Template to test evaluation of templates. Tmpl *Template } @@ -118,6 +120,7 @@ var tVal = &T{ Err: errors.New("erroozle"), PI: newInt(23), PSI: newIntSlice(21, 22, 23), + Func: func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") }, Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X } @@ -297,8 +300,13 @@ var execTests = []execTest{ "{{with $x := .}}{{with .SI}}{{$.GetU.TrueFalse $.True}}{{end}}{{end}}", "true", tVal, true}, + // Function call + {".Func", "-{{.Func}}-", "-<>-", tVal, true}, + {".Func2", "-{{.Func `he` `llo`}}-", "-<he+llo>-", tVal, true}, + // Pipelines. {"pipeline", "-{{.Method0 | .Method2 .U16}}-", "-Method2: 16 M0-", tVal, true}, + {"pipeline func", "-{{.Func `llo` | .Func `he` }}-", "-<he+<llo>>-", tVal, true}, // If. {"if true", "{{if true}}TRUE{{end}}", "TRUE", tVal, true}, diff --git a/libgo/go/text/template/multi_test.go b/libgo/go/text/template/multi_test.go index 274f5ef1477..f205e6be1b4 100644 --- a/libgo/go/text/template/multi_test.go +++ b/libgo/go/text/template/multi_test.go @@ -193,7 +193,7 @@ func TestClone(t *testing.T) { if err != nil { t.Fatal(err) } - clone := root.Clone() + clone := Must(root.Clone()) // Add variants to both. _, err = root.Parse(cloneText3) if err != nil { diff --git a/libgo/go/text/template/parse/parse.go b/libgo/go/text/template/parse/parse.go index 4da756657d5..35194f7dfdb 100644 --- a/libgo/go/text/template/parse/parse.go +++ b/libgo/go/text/template/parse/parse.go @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package parse builds parse trees for templates. The grammar is defined -// in the documents for the template package. +// Package parse builds parse trees for templates as defined by text/template +// and html/template. Clients should use those packages to construct templates +// rather than this one, which provides shared internal data structures not +// intended for general use. package parse import ( diff --git a/libgo/go/text/template/template.go b/libgo/go/text/template/template.go index 87e39d3af74..7494f9d8c45 100644 --- a/libgo/go/text/template/template.go +++ b/libgo/go/text/template/template.go @@ -69,9 +69,9 @@ func (t *Template) init() { // templates. The actual representation is not copied, but the name space of // associated templates is, so further calls to Parse in the copy will add // templates to the copy but not to the original. Clone can be used to prepare -// common templates and use them with variant definitions for other templates by -// adding the variants after the clone is made. -func (t *Template) Clone() *Template { +// common templates and use them with variant definitions for other templates +// by adding the variants after the clone is made. +func (t *Template) Clone() (*Template, error) { nt := t.copy(nil) nt.init() nt.tmpl[t.name] = nt @@ -89,7 +89,7 @@ func (t *Template) Clone() *Template { for k, v := range t.execFuncs { nt.execFuncs[k] = v } - return nt + return nt, nil } // copy returns a shallow copy of t, with common set to the argument. |