Commit 41efecf5 authored by Rob Pike's avatar Rob Pike

exp/template: allow variables as template names.

Just an oversight it wasn't already there.
Thanks to islandberry@live.com for pointing out the omission.

R=golang-dev, dsymonds
CC=golang-dev, islandberry
https://golang.org/cl/4703043
parent c1c8d46d
...@@ -33,11 +33,6 @@ func (t *Template) Name() string { ...@@ -33,11 +33,6 @@ func (t *Template) Name() string {
return t.name return t.name
} }
// popVars trims the variable list to the specified length
func (t *Template) popVars(n int) {
t.vars = t.vars[:n]
}
// next returns the next token. // next returns the next token.
func (t *Template) next() item { func (t *Template) next() item {
if t.peekCount > 0 { if t.peekCount > 0 {
...@@ -814,6 +809,8 @@ func (t *Template) templateControl() node { ...@@ -814,6 +809,8 @@ func (t *Template) templateControl() node {
name = newIdentifier(token.val) name = newIdentifier(token.val)
case itemDot: case itemDot:
name = newDot() name = newDot()
case itemVariable:
name = t.useVar(token.val)
case itemField: case itemField:
name = newField(token.val) name = newField(token.val)
case itemString, itemRawString: case itemString, itemRawString:
...@@ -857,18 +854,7 @@ Loop: ...@@ -857,18 +854,7 @@ Loop:
case itemDot: case itemDot:
cmd.append(newDot()) cmd.append(newDot())
case itemVariable: case itemVariable:
v := newVariable(token.val) cmd.append(t.useVar(token.val))
found := false
for _, varName := range t.vars {
if varName == v.ident[0] {
found = true
break
}
}
if !found {
t.errorf("undefined variable %q", token.val)
}
cmd.append(v)
case itemField: case itemField:
cmd.append(newField(token.val)) cmd.append(newField(token.val))
case itemBool: case itemBool:
...@@ -894,3 +880,21 @@ Loop: ...@@ -894,3 +880,21 @@ Loop:
} }
return cmd return cmd
} }
// popVars trims the variable list to the specified length
func (t *Template) popVars(n int) {
t.vars = t.vars[:n]
}
// useVar returns a node for a variable reference. It errors if the
// variable is not defined.
func (t *Template) useVar(name string) node {
v := newVariable(name)
for _, varName := range t.vars {
if varName == v.ident[0] {
return v
}
}
t.errorf("undefined variable %q", v.ident[0])
return nil
}
...@@ -211,6 +211,8 @@ var parseTests = []parseTest{ ...@@ -211,6 +211,8 @@ var parseTests = []parseTest{
`[({{with [(command: [F=[X]])]}} [(text: "hello")])]`}, `[({{with [(command: [F=[X]])]}} [(text: "hello")])]`},
{"with with else", "{{with .X}}hello{{else}}goodbye{{end}}", noError, {"with with else", "{{with .X}}hello{{else}}goodbye{{end}}", noError,
`[({{with [(command: [F=[X]])]}} [(text: "hello")] {{else}} [(text: "goodbye")])]`}, `[({{with [(command: [F=[X]])]}} [(text: "hello")] {{else}} [(text: "goodbye")])]`},
{"variable in template", "{{with $v := `hi`}}{{template $v}}{{end}}", noError,
"[({{with [$v] := [(command: [S=`hi`])]}} [{{template V=[$v]}}])]"},
// Errors. // Errors.
{"unclosed action", "hello{{range", hasError, ""}, {"unclosed action", "hello{{range", hasError, ""},
{"unmatched end", "{{end}}", hasError, ""}, {"unmatched end", "{{end}}", hasError, ""},
...@@ -219,6 +221,7 @@ var parseTests = []parseTest{ ...@@ -219,6 +221,7 @@ var parseTests = []parseTest{
{"undefined function", "hello{{undefined}}", hasError, ""}, {"undefined function", "hello{{undefined}}", hasError, ""},
{"undefined variable", "{{$x}}", hasError, ""}, {"undefined variable", "{{$x}}", hasError, ""},
{"variable undefined after end", "{{with $x := 4}}{{end}}{{$x}}", hasError, ""}, {"variable undefined after end", "{{with $x := 4}}{{end}}{{$x}}", hasError, ""},
{"variable undefined in template", "{{template $v}}", hasError, ""},
{"declare with field", "{{with $x.Y := 4}}{{end}}", hasError, ""}, {"declare with field", "{{with $x.Y := 4}}{{end}}", hasError, ""},
} }
......
...@@ -84,6 +84,7 @@ var setExecTests = []execTest{ ...@@ -84,6 +84,7 @@ var setExecTests = []execTest{
{"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true}, {"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
{"invoke template by field", `{{template .X}}`, "TEXT", tVal, true}, {"invoke template by field", `{{template .X}}`, "TEXT", tVal, true},
{"invoke template by template", `{{template .Tmpl}}`, "test template", tVal, true}, {"invoke template by template", `{{template .Tmpl}}`, "test template", tVal, true},
{"invoke template by variable", `{{with $t := "x"}}{{template $t}}{{end}}`, "TEXT", tVal, true},
{"invalid: invoke template by []int", `{{template .SI}}`, "", tVal, false}, {"invalid: invoke template by []int", `{{template .SI}}`, "", tVal, false},
// User-defined function: test argument evaluator. // User-defined function: test argument evaluator.
......
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