]> Cypherpunks repositories - gostls13.git/commitdiff
exp/template: allow variables as template names.
authorRob Pike <r@golang.org>
Wed, 13 Jul 2011 03:21:18 +0000 (13:21 +1000)
committerRob Pike <r@golang.org>
Wed, 13 Jul 2011 03:21:18 +0000 (13:21 +1000)
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

src/pkg/exp/template/parse.go
src/pkg/exp/template/parse_test.go
src/pkg/exp/template/set_test.go

index 774a7dd84b933d9b7baa5043fff013009e9a9039..91d19e5f673f46e93f2904279246710d5947575b 100644 (file)
@@ -33,11 +33,6 @@ func (t *Template) Name() string {
        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.
 func (t *Template) next() item {
        if t.peekCount > 0 {
@@ -814,6 +809,8 @@ func (t *Template) templateControl() node {
                name = newIdentifier(token.val)
        case itemDot:
                name = newDot()
+       case itemVariable:
+               name = t.useVar(token.val)
        case itemField:
                name = newField(token.val)
        case itemString, itemRawString:
@@ -857,18 +854,7 @@ Loop:
                case itemDot:
                        cmd.append(newDot())
                case itemVariable:
-                       v := newVariable(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)
+                       cmd.append(t.useVar(token.val))
                case itemField:
                        cmd.append(newField(token.val))
                case itemBool:
@@ -894,3 +880,21 @@ Loop:
        }
        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
+}
index 2a2fa648d7e69063ae6392b204b245ed9b8814ea..10be3cbb236a5023e1b3922072aec0a25f9c46cc 100644 (file)
@@ -211,6 +211,8 @@ var parseTests = []parseTest{
                `[({{with [(command: [F=[X]])]}} [(text: "hello")])]`},
        {"with with else", "{{with .X}}hello{{else}}goodbye{{end}}", noError,
                `[({{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.
        {"unclosed action", "hello{{range", hasError, ""},
        {"unmatched end", "{{end}}", hasError, ""},
@@ -219,6 +221,7 @@ var parseTests = []parseTest{
        {"undefined function", "hello{{undefined}}", hasError, ""},
        {"undefined variable", "{{$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, ""},
 }
 
index 99310b62349e47eaa453ad99ea74104fa04f30ae..83088af973831e667d78cf8ff36444229152cf66 100644 (file)
@@ -84,6 +84,7 @@ var setExecTests = []execTest{
        {"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
        {"invoke template by field", `{{template .X}}`, "TEXT", 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},
 
        // User-defined function: test argument evaluator.