LEFT | RIGHT |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package template | 5 package template |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "fmt" | 9 "fmt" |
10 "reflect" | 10 "reflect" |
(...skipping 26 matching lines...) Expand all Loading... |
37 return &Template{ | 37 return &Template{ |
38 name: name, | 38 name: name, |
39 } | 39 } |
40 } | 40 } |
41 | 41 |
42 // Name returns the name of the template. | 42 // Name returns the name of the template. |
43 func (t *Template) Name() string { | 43 func (t *Template) Name() string { |
44 return t.name | 44 return t.name |
45 } | 45 } |
46 | 46 |
47 // newTemplate allocates a new template associated with the given one and with t
he same | 47 // New allocates a new template associated with the given one and with the same |
48 // delimiters. The association, which is transitive, allows one template to | 48 // delimiters. The association, which is transitive, allows one template to |
49 // invoke another with a {{template}} action. | 49 // invoke another with a {{template}} action. |
50 func (t *Template) newTemplate(name string) *Template { | 50 func (t *Template) New(name string) *Template { |
51 t.init() | 51 t.init() |
52 return &Template{ | 52 return &Template{ |
53 name: name, | 53 name: name, |
54 common: t.common, | 54 common: t.common, |
55 leftDelim: t.leftDelim, | 55 leftDelim: t.leftDelim, |
56 rightDelim: t.rightDelim, | 56 rightDelim: t.rightDelim, |
57 } | 57 } |
58 } | 58 } |
59 | 59 |
60 func (t *Template) init() { | 60 func (t *Template) init() { |
61 if t.common == nil { | 61 if t.common == nil { |
62 t.common = new(common) | 62 t.common = new(common) |
63 t.tmpl = make(map[string]*Template) | 63 t.tmpl = make(map[string]*Template) |
64 t.parseFuncs = make(FuncMap) | 64 t.parseFuncs = make(FuncMap) |
65 t.execFuncs = make(map[string]reflect.Value) | 65 t.execFuncs = make(map[string]reflect.Value) |
66 } | 66 } |
67 } | 67 } |
68 | 68 |
69 // Template returns a slice of the templates associated with t, including t itse
lf. | 69 // Clone returns a duplicate of the template, including all associated |
| 70 // templates. The actual representation is not copied, but the name space of |
| 71 // associated templates is, so further calls to Parse in the copy will add |
| 72 // templates to the copy but not to the original. Clone can be used to prepare |
| 73 // common templates and use them with variant definitions for other templates by |
| 74 // adding the variants after the clone is made. |
| 75 func (t *Template) Clone() *Template { |
| 76 » nt := t.copy() |
| 77 » nt.init() |
| 78 » for k, v := range t.tmpl { |
| 79 » » // The associated templates share nt's common structure. |
| 80 » » tmpl := v.copy() |
| 81 » » tmpl.common = nt.common |
| 82 » » nt.tmpl[k] = tmpl |
| 83 » } |
| 84 » for k, v := range t.parseFuncs { |
| 85 » » nt.parseFuncs[k] = v |
| 86 » } |
| 87 » for k, v := range t.execFuncs { |
| 88 » » nt.execFuncs[k] = v |
| 89 » } |
| 90 » return nt |
| 91 } |
| 92 |
| 93 // copy returns a shallow copy of t, with common set to nil. |
| 94 func (t *Template) copy() *Template { |
| 95 » nt := New(t.name) |
| 96 » nt.Tree = t.Tree |
| 97 » nt.leftDelim = t.leftDelim |
| 98 » nt.rightDelim = t.rightDelim |
| 99 » return nt |
| 100 } |
| 101 |
| 102 // Templates returns a slice of the templates associated with t, including t |
| 103 // itself. |
70 func (t *Template) Templates() []*Template { | 104 func (t *Template) Templates() []*Template { |
71 // Return a slice so we don't expose the map. | 105 // Return a slice so we don't expose the map. |
72 m := make([]*Template, 0, len(t.tmpl)) | 106 m := make([]*Template, 0, len(t.tmpl)) |
73 for _, v := range t.tmpl { | 107 for _, v := range t.tmpl { |
74 m = append(m, v) | 108 m = append(m, v) |
75 } | 109 } |
76 return m | 110 return m |
77 } | 111 } |
78 | 112 |
79 // Delims sets the action delimiters to the specified strings, to be used in | 113 // Delims sets the action delimiters to the specified strings, to be used in |
(...skipping 20 matching lines...) Expand all Loading... |
100 | 134 |
101 // Template returns the template with the given name that is associated with t, | 135 // Template returns the template with the given name that is associated with t, |
102 // or nil if there is no such template. | 136 // or nil if there is no such template. |
103 func (t *Template) Template(name string) *Template { | 137 func (t *Template) Template(name string) *Template { |
104 return t.tmpl[name] | 138 return t.tmpl[name] |
105 } | 139 } |
106 | 140 |
107 // Parse parses a string into a template. Nested template definitions will be | 141 // Parse parses a string into a template. Nested template definitions will be |
108 // associated with the top-level template t. Parse may be called multiple times | 142 // associated with the top-level template t. Parse may be called multiple times |
109 // to parse definitions of templates to associate with t. It is an error if a | 143 // to parse definitions of templates to associate with t. It is an error if a |
110 // resulting template is non-trivial (contains content other than template | 144 // resulting template is non-empty (contains content other than template |
111 // definitions) and would replace a non-trivial template with the same name. | 145 // definitions) and would replace a non-empty template with the same name. |
| 146 // (In multiple calls to Parse with the same receiver template, only one call |
| 147 // can contain text other than space, comments, and template definitions.) |
112 func (t *Template) Parse(text string) (*Template, error) { | 148 func (t *Template) Parse(text string) (*Template, error) { |
113 t.init() | 149 t.init() |
114 trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.par
seFuncs, builtins) | 150 trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.par
seFuncs, builtins) |
115 if err != nil { | 151 if err != nil { |
116 return nil, err | 152 return nil, err |
117 } | 153 } |
118 // Add the newly parsed trees, including the one for t, into our common
structure. | 154 // Add the newly parsed trees, including the one for t, into our common
structure. |
119 for name, tree := range trees { | 155 for name, tree := range trees { |
120 » » // The receiver template should rewritten not recreated. | 156 » » // If the name we parsed is the name of this template, overwrite
this template. |
| 157 » » // The associate method checks it's not a redefinition. |
121 tmpl := t | 158 tmpl := t |
122 if name != t.name { | 159 if name != t.name { |
123 » » » tmpl = New(name) | 160 » » » tmpl = t.New(name) |
124 » » » tmpl.common = t.common | 161 » » } |
125 » » } | 162 » » // Even if t == tmpl, we need to install it in the common.tmpl m
ap. |
126 if err := t.associate(tmpl); err != nil { | 163 if err := t.associate(tmpl); err != nil { |
127 return nil, err | 164 return nil, err |
128 } | 165 } |
129 tmpl.Tree = tree | 166 tmpl.Tree = tree |
130 tmpl.leftDelim = t.leftDelim | 167 tmpl.leftDelim = t.leftDelim |
131 tmpl.rightDelim = t.rightDelim | 168 tmpl.rightDelim = t.rightDelim |
132 } | 169 } |
133 return t, nil | 170 return t, nil |
134 } | 171 } |
135 | 172 |
136 // associate installs the new template into the group of templates associated | 173 // associate installs the new template into the group of templates associated |
137 // with t. It is an error to reuse a name except to overwrite an empty | 174 // with t. It is an error to reuse a name except to overwrite an empty |
138 // template. | 175 // template. The two are already known to share the common structure. |
139 func (t *Template) associate(new *Template) error { | 176 func (t *Template) associate(new *Template) error { |
| 177 if new.common != t.common { |
| 178 panic("internal error: associate not common") |
| 179 } |
140 name := new.name | 180 name := new.name |
141 if old := t.tmpl[name]; old != nil { | 181 if old := t.tmpl[name]; old != nil { |
142 oldIsEmpty := isEmpty(old.Root) | 182 oldIsEmpty := isEmpty(old.Root) |
143 newIsEmpty := isEmpty(new.Root) | 183 newIsEmpty := isEmpty(new.Root) |
144 if !oldIsEmpty && !newIsEmpty { | 184 if !oldIsEmpty && !newIsEmpty { |
145 return fmt.Errorf("template: redefinition of template %q
", name) | 185 return fmt.Errorf("template: redefinition of template %q
", name) |
146 } | 186 } |
147 if newIsEmpty { | 187 if newIsEmpty { |
148 // Whether old is empty or not, new is empty; no reason
to replace old. | 188 // Whether old is empty or not, new is empty; no reason
to replace old. |
149 return nil | 189 return nil |
150 } | 190 } |
151 } | 191 } |
152 t.tmpl[name] = new | 192 t.tmpl[name] = new |
153 new.common = t.common | |
154 return nil | 193 return nil |
155 } | 194 } |
156 | 195 |
157 // isEmpty reports whether this tree (node) is empty of everything but space. | 196 // isEmpty reports whether this tree (node) is empty of everything but space. |
158 func isEmpty(n parse.Node) bool { | 197 func isEmpty(n parse.Node) bool { |
159 switch n := n.(type) { | 198 switch n := n.(type) { |
160 case *parse.ActionNode: | 199 case *parse.ActionNode: |
161 case *parse.IfNode: | 200 case *parse.IfNode: |
162 case *parse.ListNode: | 201 case *parse.ListNode: |
163 for _, node := range n.Nodes { | 202 for _, node := range n.Nodes { |
164 if !isEmpty(node) { | 203 if !isEmpty(node) { |
165 return false | 204 return false |
166 } | 205 } |
167 } | 206 } |
168 return true | 207 return true |
169 case *parse.RangeNode: | 208 case *parse.RangeNode: |
170 case *parse.TemplateNode: | 209 case *parse.TemplateNode: |
171 case *parse.TextNode: | 210 case *parse.TextNode: |
172 return len(bytes.TrimSpace(n.Text)) == 0 | 211 return len(bytes.TrimSpace(n.Text)) == 0 |
173 case *parse.WithNode: | 212 case *parse.WithNode: |
174 default: | 213 default: |
175 panic("unknown node: " + n.String()) | 214 panic("unknown node: " + n.String()) |
176 } | 215 } |
177 return false | 216 return false |
178 } | 217 } |
LEFT | RIGHT |