Commit 2e9388e3 authored by Rob Pike's avatar Rob Pike

exp/template: add Set.AddSet and Set.Union.

Document and test that Set.Parse can be called multiple times.

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/4703044
parent 41efecf5
......@@ -259,6 +259,10 @@ when it is executed.
The second way to build a template set is to use the Add method of Set to bind
a template to a set. A template may be bound to multiple sets.
Set.Parse may be called multiple times on different inputs to construct the set.
Two sets may therefore be constructed with a common base set of templates plus,
through a second Parse call each, specializations for some elements.
When templates are executed via Template.Execute, no set is defined and so no
template invocations are possible. The method Template.ExecuteInSet provides a
way to specify a template set when executing a template directly.
......
......@@ -38,7 +38,7 @@ func (s *Set) Funcs(funcMap FuncMap) *Set {
}
// Add adds the argument templates to the set. It panics if the call
// attempts to reuse a name defined in the template.
// attempts to reuse a name defined in the set.
// The return value is the set, so calls can be chained.
func (s *Set) Add(templates ...*Template) *Set {
for _, t := range templates {
......@@ -50,6 +50,30 @@ func (s *Set) Add(templates ...*Template) *Set {
return s
}
// AddSet adds the templates from the provided set to the to the receiver.
// It panics if the call attempts to reuse a name defined in the set.
// The return value is the set, so calls can be chained.
func (s *Set) AddSet(set *Set) *Set {
for _, t := range set.tmpl {
if _, ok := s.tmpl[t.name]; ok {
panic(fmt.Errorf("template: %q already defined in set", t.name))
}
s.tmpl[t.name] = t
}
return s
}
// Union adds the templates from the provided set to the to the receiver.
// Unlike AddSet, it does not panic if a name is reused; instead the old
// template is replaced.
// The return value is the set, so calls can be chained.
func (s *Set) Union(set *Set) *Set {
for _, t := range set.tmpl {
s.tmpl[t.name] = t
}
return s
}
// Template returns the template with the given name in the set,
// or nil if there is no such template.
func (s *Set) Template(name string) *Template {
......@@ -81,7 +105,10 @@ func (s *Set) recover(errp *os.Error) {
return
}
// Parse parses a string into a set of named templates.
// Parse parses a string into a set of named templates. Parse may be called
// multiple times for a given set, adding the templates defined in the string
// to the set. If a template is redefined, the element in the set is
// overwritten with the new definition.
func (s *Set) Parse(text string) (err os.Error) {
defer s.recover(&err)
lex := lex("set", text)
......
......@@ -92,9 +92,12 @@ var setExecTests = []execTest{
{"testFunc .", `{{oneArg .}}`, "oneArg=joe", "joe", true},
}
const setText = `
const setText1 = `
{{define "x"}}TEXT{{end}}
{{define "dotV"}}{{.V}}{{end}}
`
const setText2 = `
{{define "dot"}}{{.}}{{end}}
{{define "nested"}}{{template "dot" .}}{{end}}
`
......@@ -102,7 +105,11 @@ const setText = `
func TestSetExecute(t *testing.T) {
// Declare a set with a couple of templates first.
set := NewSet()
err := set.Parse(setText)
err := set.Parse(setText1)
if err != nil {
t.Fatalf("error parsing set: %s", err)
}
err = set.Parse(setText2)
if err != nil {
t.Fatalf("error parsing set: %s", err)
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment