2 Copyright 2015 The Kubernetes Authors.
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
26 // SnippetWriter is an attempt to make the template library usable.
27 // Methods are chainable, and you don't have to check Error() until you're all
29 type SnippetWriter struct {
32 // Left & right delimiters. text/template defaults to "{{" and "}}"
33 // which is totally unusable for go code based templates.
35 funcMap template.FuncMap
39 // w is the destination; left and right are the delimiters; @ and $ are both
40 // reasonable choices.
42 // c is used to make a function for every naming system, to which you can pass
43 // a type and get the corresponding name.
44 func NewSnippetWriter(w io.Writer, c *Context, left, right string) *SnippetWriter {
50 funcMap: template.FuncMap{},
52 for name, namer := range c.Namers {
53 sw.funcMap[name] = namer.Name
58 // Do parses format and runs args through it. You can have arbitrary logic in
59 // the format (see the text/template documentation), but consider running many
60 // short templaces, with ordinary go logic in between--this may be more
61 // readable. Do is chainable. Any error causes every other call to do to be
62 // ignored, and the error will be returned by Error(). So you can check it just
63 // once, at the end of your function.
65 // 'args' can be quite literally anything; read the text/template documentation
66 // for details. Maps and structs work particularly nicely. Conveniently, the
67 // types package is designed to have structs that are easily referencable from
68 // the template language.
72 // sw := generator.NewSnippetWriter(outBuffer, context, "$", "$")
73 // sw.Do(`The public type name is: $.type|public$`, map[string]interface{}{"type": t})
77 // * "$" starts a template directive
78 // * "." references the entire thing passed as args
79 // * "type" therefore sees a map and looks up the key "type"
80 // * "|" means "pass the thing on the left to the thing on the right"
81 // * "public" is the name of a naming system, so the SnippetWriter has given
82 // the template a function called "public" that takes a *types.Type and
83 // returns the naming system's name. E.g., if the type is "string" this might
85 // * the second "$" ends the template directive.
87 // The map is actually not necessary. The below does the same thing:
89 // sw.Do(`The public type name is: $.|public$`, t)
91 // You may or may not find it more readable to use the map with a descriptive
92 // key, but if you want to pass more than one arg, the map or a custom struct
93 // becomes a requirement. You can do arbitrary logic inside these templates,
94 // but you should consider doing the logic in go and stitching them together
95 // for the sake of your readers.
97 // TODO: Change Do() to optionally take a list of pairs of parameters (key, value)
98 // and have it construct a combined map with that and args.
99 func (s *SnippetWriter) Do(format string, args interface{}) *SnippetWriter {
103 // Name the template by source file:line so it can be found when
105 _, file, line, _ := runtime.Caller(1)
106 tmpl, err := template.
107 New(fmt.Sprintf("%s:%d", file, line)).
108 Delims(s.left, s.right).
115 err = tmpl.Execute(s.w, args)
122 // Args exists to make it convenient to construct arguments for
124 type Args map[interface{}]interface{}
126 // With makes a copy of a and adds the given key, value pair.
127 func (a Args) With(key, value interface{}) Args {
128 a2 := Args{key: value}
129 for k, v := range a {
135 // WithArgs makes a copy of a and adds the given arguments.
136 func (a Args) WithArgs(rhs Args) Args {
138 for k, v := range rhs {
141 for k, v := range a {
147 func (s *SnippetWriter) Out() io.Writer {
151 // Error returns any encountered error.
152 func (s *SnippetWriter) Error() error {