type SnippetWriter … // w is the destination; left and right are the delimiters; @ and $ are both // reasonable choices. // // c is used to make a function for every naming system, to which you can pass // a type and get the corresponding name. func NewSnippetWriter(w io.Writer, c *Context, left, right string) *SnippetWriter { … } // Do parses format and runs args through it. You can have arbitrary logic in // the format (see the text/template documentation), but consider running many // short templates with ordinary go logic in between--this may be more // readable. Do is chainable. Any error causes every other call to do to be // ignored, and the error will be returned by Error(). So you can check it just // once, at the end of your function. // // 'args' can be quite literally anything; read the text/template documentation // for details. Maps and structs work particularly nicely. Conveniently, the // types package is designed to have structs that are easily referencable from // the template language. // // Example: // // sw := generator.NewSnippetWriter(outBuffer, context, "$", "$") // sw.Do(`The public type name is: $.type|public$`, map[string]interface{}{"type": t}) // return sw.Error() // // Where: // - "$" starts a template directive // - "." references the entire thing passed as args // - "type" therefore sees a map and looks up the key "type" // - "|" means "pass the thing on the left to the thing on the right" // - "public" is the name of a naming system, so the SnippetWriter has given // the template a function called "public" that takes a *types.Type and // returns the naming system's name. E.g., if the type is "string" this might // return "String". // - the second "$" ends the template directive. // // The map is actually not necessary. The below does the same thing: // // sw.Do(`The public type name is: $.|public$`, t) // // You may or may not find it more readable to use the map with a descriptive // key, but if you want to pass more than one arg, the map or a custom struct // becomes a requirement. You can do arbitrary logic inside these templates, // but you should consider doing the logic in go and stitching them together // for the sake of your readers. // // TODO: Change Do() to optionally take a list of pairs of parameters (key, value) // and have it construct a combined map with that and args. func (s *SnippetWriter) Do(format string, args interface{ … } type Args … // With makes a copy of a and adds the given key, value pair. If key overlaps, // the new value wins. func (a Args) With(key, value interface{ … } // WithArgs makes a copy of a and adds the given arguments. If any keys // overlap, the values from rhs win. func (a Args) WithArgs(rhs Args) Args { … } func (s *SnippetWriter) Out() io.Writer { … } // Error returns any encountered error. func (s *SnippetWriter) Error() error { … } // Dup creates an exact duplicate SnippetWriter with a different io.Writer. func (s *SnippetWriter) Dup(w io.Writer) *SnippetWriter { … } // Append adds the contents of the io.Reader to this SnippetWriter's buffer. func (s *SnippetWriter) Append(r io.Reader) error { … }