~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/exp/template/set.go

  • Committer: Bazaar Package Importer
  • Author(s): Ondřej Surý
  • Date: 2011-08-03 17:04:59 UTC
  • mfrom: (14.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20110803170459-wzd99m3567y80ila
Tags: 1:59-1
* Imported Upstream version 59
* Refresh patches to a new release
* Fix FTBFS on ARM (Closes: #634270)
* Update version.bash to work with Debian packaging and not hg
  repository

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2011 The Go Authors. All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
package template
 
6
 
 
7
import (
 
8
        "fmt"
 
9
        "io"
 
10
        "os"
 
11
        "reflect"
 
12
        "runtime"
 
13
        "strconv"
 
14
)
 
15
 
 
16
// Set holds a set of related templates that can refer to one another by name.
 
17
// A template may be a member of multiple sets.
 
18
type Set struct {
 
19
        tmpl  map[string]*Template
 
20
        funcs map[string]reflect.Value
 
21
}
 
22
 
 
23
// NewSet allocates a new, empty template set.
 
24
func NewSet() *Set {
 
25
        return &Set{
 
26
                tmpl:  make(map[string]*Template),
 
27
                funcs: make(map[string]reflect.Value),
 
28
        }
 
29
}
 
30
 
 
31
// Funcs adds to the set's function map the elements of the
 
32
// argument map.   It panics if a value in the map is not a function
 
33
// with appropriate return type.
 
34
// The return value is the set, so calls can be chained.
 
35
func (s *Set) Funcs(funcMap FuncMap) *Set {
 
36
        addFuncs(s.funcs, funcMap)
 
37
        return s
 
38
}
 
39
 
 
40
// Add adds the argument templates to the set. It panics if the call
 
41
// attempts to reuse a name defined in the template.
 
42
// The return value is the set, so calls can be chained.
 
43
func (s *Set) Add(templates ...*Template) *Set {
 
44
        for _, t := range templates {
 
45
                if _, ok := s.tmpl[t.name]; ok {
 
46
                        panic(fmt.Errorf("template: %q already defined in set", t.name))
 
47
                }
 
48
                s.tmpl[t.name] = t
 
49
        }
 
50
        return s
 
51
}
 
52
 
 
53
// Template returns the template with the given name in the set,
 
54
// or nil if there is no such template.
 
55
func (s *Set) Template(name string) *Template {
 
56
        return s.tmpl[name]
 
57
}
 
58
 
 
59
// Execute looks for the named template in the set and then applies that
 
60
// template to the specified data object, writing the output to wr.  Nested
 
61
// template invocations will be resolved from the set.
 
62
func (s *Set) Execute(name string, wr io.Writer, data interface{}) os.Error {
 
63
        tmpl := s.tmpl[name]
 
64
        if tmpl == nil {
 
65
                return fmt.Errorf("template: no template %q in set", name)
 
66
        }
 
67
        return tmpl.ExecuteInSet(wr, data, s)
 
68
}
 
69
 
 
70
// recover is the handler that turns panics into returns from the top
 
71
// level of Parse.
 
72
func (s *Set) recover(errp *os.Error) {
 
73
        e := recover()
 
74
        if e != nil {
 
75
                if _, ok := e.(runtime.Error); ok {
 
76
                        panic(e)
 
77
                }
 
78
                s.tmpl = nil
 
79
                *errp = e.(os.Error)
 
80
        }
 
81
        return
 
82
}
 
83
 
 
84
// Parse parses the file into a set of named templates.
 
85
func (s *Set) Parse(text string) (err os.Error) {
 
86
        defer s.recover(&err)
 
87
        lex := lex("set", text)
 
88
        const context = "define clause"
 
89
        for {
 
90
                t := New("set") // name will be updated once we know it.
 
91
                t.startParse(s, lex)
 
92
                // Expect EOF or "{{ define name }}".
 
93
                if t.atEOF() {
 
94
                        return
 
95
                }
 
96
                t.expect(itemLeftDelim, context)
 
97
                t.expect(itemDefine, context)
 
98
                name := t.expect(itemString, context)
 
99
                t.name, err = strconv.Unquote(name.val)
 
100
                if err != nil {
 
101
                        t.error(err)
 
102
                }
 
103
                t.expect(itemRightDelim, context)
 
104
                end := t.parse(false)
 
105
                if end == nil {
 
106
                        t.errorf("unexpected EOF in %s", context)
 
107
                }
 
108
                if end.typ() != nodeEnd {
 
109
                        t.errorf("unexpected %s in %s", end, context)
 
110
                }
 
111
                t.stopParse()
 
112
                s.tmpl[t.name] = t
 
113
        }
 
114
        return nil
 
115
}