Exemplo n.º 1
0
// clone clones a template Node.
func clone(n parse.Node) parse.Node {
	switch t := n.(type) {
	case *parse.ActionNode:
		return cloneAction(t)
	case *parse.IfNode:
		b := new(parse.IfNode)
		copyBranch(&b.BranchNode, &t.BranchNode)
		return b
	case *parse.ListNode:
		return cloneList(t)
	case *parse.RangeNode:
		b := new(parse.RangeNode)
		copyBranch(&b.BranchNode, &t.BranchNode)
		return b
	case *parse.TemplateNode:
		return cloneTemplate(t)
	case *parse.TextNode:
		return cloneText(t)
	case *parse.WithNode:
		b := new(parse.WithNode)
		copyBranch(&b.BranchNode, &t.BranchNode)
		return b
	}
	panic("cloning " + n.String() + " is unimplemented")
}
Exemplo n.º 2
0
// Walk functions step through the major pieces of the template structure,
// generating output as they go.
func (s *state) walk(dot reflect.Value, node parse.Node) {
	s.at(node)
	switch node := node.(type) {
	case *parse.ActionNode:
		// Do not pop variables so they persist until next end.
		// Also, if the action declares variables, don't print the result.
		val := s.evalPipeline(dot, node.Pipe)
		if len(node.Pipe.Decl) == 0 {
			s.visitValue(node, val)
		}
	case *parse.IfNode:
		s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
	case *parse.ListNode:
		for _, node := range node.Nodes {
			s.walk(dot, node)
		}
	case *parse.RangeNode:
		s.walkRange(dot, node)
	case *parse.TemplateNode:
		s.walkTemplate(dot, node)
	case *parse.TextNode:
		s.v.Visit(node.String())
	case *parse.WithNode:
		s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
	default:
		s.errorf("unknown node: %s", node)
	}
}
Exemplo n.º 3
0
// escape escapes a template node.
func (e *escaper) escape(c context, n parse.Node) context {
	switch n := n.(type) {
	case *parse.ActionNode:
		return e.escapeAction(c, n)
	case *parse.IfNode:
		return e.escapeBranch(c, &n.BranchNode, "if")
	case *parse.ListNode:
		return e.escapeList(c, n)
	case *parse.RangeNode:
		return e.escapeBranch(c, &n.BranchNode, "range")
	case *parse.TemplateNode:
		return e.escapeTemplate(c, n)
	case *parse.TextNode:
		return e.escapeText(c, n)
	case *parse.WithNode:
		return e.escapeBranch(c, &n.BranchNode, "with")
	}
	panic("escaping " + n.String() + " is unimplemented")
}
Exemplo n.º 4
0
// IsPseudoFunction returns true iff n is a *parse.ActionNode
// consisting solely of a fn call without any arguments.
func IsPseudoFunction(n parse.Node, fn string) bool {
	return n.Type() == parse.NodeAction && n.String() == leftDelim+fn+rightDelim
}
Exemplo n.º 5
0
func DataNode(root *template.Template, node parse.Node, data *Dotted, vars map[string][]string, prefixwords []string) {
	if true {
		switch node.Type() {
		case parse.NodeWith:
			withNode := node.(*parse.WithNode)
			arg0 := withNode.Pipe.Cmds[0].Args[0].String()
			var withv string
			if len(arg0) > 0 && arg0[0] == '.' {
				if decl := withNode.Pipe.Decl; len(decl) > 0 {
					// just {{with $ := ...}} cases

					withv = decl[0].Ident[0]
					words := strings.Split(arg0[1:], ".")
					vars[withv] = words
					data.Append(words, prefixwords)
				}
			}
			if withNode.List != nil {
				for _, n := range withNode.List.Nodes {
					DataNode(root, n, data, vars, prefixwords)
				}
			}
			if withNode.ElseList != nil {
				for _, n := range withNode.ElseList.Nodes {
					DataNode(root, n, data, vars, prefixwords)
				}
			}
			if withv != "" {
				delete(vars, withv)
			}
		case parse.NodeTemplate:
			tnode := node.(*parse.TemplateNode)
			var tawords []string
			for _, arg := range tnode.Pipe.Cmds[0].Args {
				s := arg.String()
				if len(s) > 1 && s[0] == '.' {
					tawords = strings.Split(s[1:], ".")
					data.Append(tawords, prefixwords)
					break // just one argument (pipeline) to "{{template}}" allowed anyway
				}
			}
			if sub := root.Lookup(tnode.Name); sub != nil && sub.Tree != nil && sub.Tree.Root != nil {
				for _, n := range sub.Tree.Root.Nodes {
					pw := prefixwords
					if tawords != nil {
						pw = append(prefixwords, tawords...)
					}
					DataNode(root, n, data, vars, pw)
				}
			}
		case parse.NodeAction:
			actionNode := node.(*parse.ActionNode)
			decl := actionNode.Pipe.Decl

			for _, cmd := range actionNode.Pipe.Cmds {
				if cmd.NodeType != parse.NodeCommand {
					continue
				}
				for _, arg := range cmd.Args {
					var ident []string
					switch arg.Type() {
					case parse.NodeChain:
						chain := arg.(*parse.ChainNode)
						if chain.Node.Type() == parse.NodePipe {
							pipe := chain.Node.(*parse.PipeNode)
							for _, arg := range pipe.Cmds[0].Args {
								if arg.Type() == parse.NodeField {
									w := arg.String()
									if len(w) > 0 && w[0] == '.' {
										data.Append(strings.Split(w[1:], "."), prefixwords)
									}
								}
							}
						}
					case parse.NodeField:
						ident = arg.(*parse.FieldNode).Ident

						if len(decl) > 0 && len(decl[0].Ident) > 0 {
							vars[decl[0].Ident[0]] = ident
						}
						data.Append(ident, prefixwords)

					case parse.NodeVariable:
						ident = arg.(*parse.VariableNode).Ident

						if words, ok := vars[ident[0]]; ok {
							words := append(words, ident[1:]...)
							data.Append(words, prefixwords)
							if len(decl) > 0 && len(decl[0].Ident) > 0 {
								vars[decl[0].Ident[0]] = words
							}
						}
					}
				}
			}
		case parse.NodeRange:
			rangeNode := node.(*parse.RangeNode)
			decl := rangeNode.Pipe.Decl[len(rangeNode.Pipe.Decl)-1].String()
			keys := []string{}

			for _, ifnode := range rangeNode.List.Nodes {
				switch ifnode.Type() {
				case parse.NodeAction:
					keys = append(keys, getKeys(decl, ifnode)...)
				case parse.NodeIf:
					for _, z := range ifnode.(*parse.IfNode).List.Nodes {
						if z.Type() == parse.NodeAction {
							keys = append(keys, getKeys(decl, z)...)
						}
					}
				case parse.NodeTemplate:
					// DataNode(root, ifnode, data, vars, prefixwords)
					arg0 := ifnode.(*parse.TemplateNode).Pipe.Cmds[0].Args[0]
					if arg0.Type() == parse.NodePipe {
						cmd0 := arg0.(*parse.PipeNode).Cmds[0]
						if cmd0.Type() == parse.NodeCommand {
							for _, a := range cmd0.Args {
								if s, prefix := a.String(), decl+"."; strings.HasPrefix(s, prefix) {
									keys = append(keys, strings.Split(strings.TrimPrefix(s, prefix), ".")...)
								}
							}
						}
					} else if arg0.Type() == parse.NodeVariable {
						keys = append(keys, arg0.(*parse.VariableNode).Ident[1:]...)
					}
				}
			}

			// fml
			arg0 := rangeNode.Pipe.Cmds[0].Args[0].String()
			words, ok := vars[arg0]
			if !ok && len(arg0) > 0 && arg0[0] == '.' {
				words = strings.Split(arg0[1:], ".")
				data.Append(words, prefixwords)
				ok = true
			}
			if ok {
				if leaf := data.Find(words); leaf != nil {
					leaf.Ranged = true
					leaf.Keys = append(leaf.Keys, keys...)
					leaf.Decl = decl // redefined $
				}
			}
		}
	}
}
Exemplo n.º 6
0
func templatePosition(name string, text string, n parse.Node) *token.Position {
	return &token.Position{
		Filename: name,
		Line:     strings.Count(text[:int(n.Position())], "\n") + 1,
	}
}