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 {
name = newIdentifier(token.val)
case itemDot:
name = newDot()
+ case itemVariable:
+ name = t.useVar(token.val)
case itemField:
name = newField(token.val)
case itemString, itemRawString:
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:
}
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
+}
`[({{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, ""},
{"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, ""},
}
{"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.