mirror of
https://github.com/golang/go
synced 2024-11-22 13:14:55 -07:00
exp/template: construct sets from plain template files
This is the last piece (I hope) of the set creation code. These helpers create sets from files containing individual template definitions, free of {{define}} clauses. This design is helpful if the templates live one per file, undecorated. R=golang-dev, dsymonds CC=golang-dev https://golang.org/cl/4801052
This commit is contained in:
parent
3ddaa95d71
commit
2d972ad493
@ -13,6 +13,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Functions and methods to parse a single template.
|
||||||
|
|
||||||
// MustParse parses the template definition string to construct an internal
|
// MustParse parses the template definition string to construct an internal
|
||||||
// representation of the template for execution.
|
// representation of the template for execution.
|
||||||
// It panics if the template cannot be parsed.
|
// It panics if the template cannot be parsed.
|
||||||
@ -57,6 +59,8 @@ func MustParseFile(filename string) *Template {
|
|||||||
return New(filepath.Base(filename)).MustParseFile(filename)
|
return New(filepath.Base(filename)).MustParseFile(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Functions and methods to parse a set.
|
||||||
|
|
||||||
// MustParse parses a string into a set of named templates.
|
// MustParse parses a string into a set of named templates.
|
||||||
// It panics if the set cannot be parsed.
|
// It panics if the set cannot be parsed.
|
||||||
func (s *Set) MustParse(text string) *Set {
|
func (s *Set) MustParse(text string) *Set {
|
||||||
@ -160,3 +164,146 @@ func MustParseSetFiles(pattern string) *Set {
|
|||||||
}
|
}
|
||||||
return set
|
return set
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Functions and methods to parse stand-alone template files into a set.
|
||||||
|
|
||||||
|
// ParseTemplateFile parses the named template files and adds
|
||||||
|
// them to the set. Each template will named the base name of
|
||||||
|
// its file.
|
||||||
|
// Unlike with ParseFile, each file should be a stand-alone template
|
||||||
|
// definition suitable for Template.Parse (not Set.Parse); that is, the
|
||||||
|
// file does not contain {{define}} clauses. ParseTemplateFile is
|
||||||
|
// therefore equivalent to calling the ParseFile function to create
|
||||||
|
// individual templates, which are then added to the set.
|
||||||
|
// Each file must be parseable by itself. Parsing stops if an error is
|
||||||
|
// encountered.
|
||||||
|
func (s *Set) ParseTemplateFile(filenames ...string) os.Error {
|
||||||
|
for _, filename := range filenames {
|
||||||
|
t, err := ParseFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.add(t); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParseTemplateFile is like ParseTemplateFile but
|
||||||
|
// panics if there is an error.
|
||||||
|
func (s *Set) MustParseTemplateFile(filenames ...string) {
|
||||||
|
err := s.ParseTemplateFile(filenames...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseTemplateFiles parses the template files matched by the
|
||||||
|
// patern and adds them to the set. Each template will named
|
||||||
|
// the base name of its file.
|
||||||
|
// Unlike with ParseFiles, each file should be a stand-alone template
|
||||||
|
// definition suitable for Template.Parse (not Set.Parse); that is, the
|
||||||
|
// file does not contain {{define}} clauses. ParseTemplateFiles is
|
||||||
|
// therefore equivalent to calling the ParseFile function to create
|
||||||
|
// individual templates, which are then added to the set.
|
||||||
|
// Each file must be parseable by itself. Parsing stops if an error is
|
||||||
|
// encountered.
|
||||||
|
func (s *Set) ParseTemplateFiles(pattern string) os.Error {
|
||||||
|
filenames, err := filepath.Glob(pattern)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, filename := range filenames {
|
||||||
|
t, err := ParseFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.add(t); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParseTemplateFile is like ParseTemplateFiles but
|
||||||
|
// panics if there is an error.
|
||||||
|
func (s *Set) MustParseTemplateFiles(pattern string) {
|
||||||
|
err := s.ParseTemplateFiles(pattern)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseTemplateFile creates a set by parsing the named files,
|
||||||
|
// each of which defines a single template. Each template will
|
||||||
|
// named the base name of its file.
|
||||||
|
// Unlike with ParseFile, each file should be a stand-alone template
|
||||||
|
// definition suitable for Template.Parse (not Set.Parse); that is, the
|
||||||
|
// file does not contain {{define}} clauses. ParseTemplateFile is
|
||||||
|
// therefore equivalent to calling the ParseFile function to create
|
||||||
|
// individual templates, which are then added to the set.
|
||||||
|
// Each file must be parseable by itself. Parsing stops if an error is
|
||||||
|
// encountered.
|
||||||
|
func ParseTemplateFile(filenames ...string) (*Set, os.Error) {
|
||||||
|
set := new(Set)
|
||||||
|
for _, filename := range filenames {
|
||||||
|
t, err := ParseFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := set.add(t); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParseTemplateFile is like ParseTemplateFile but
|
||||||
|
// panics if there is an error.
|
||||||
|
func MustParseTemplateFile(filenames ...string) *Set {
|
||||||
|
set, err := ParseTemplateFile(filenames...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseTemplateFiles creates a set by parsing the files matched
|
||||||
|
// by the pattern, each of which defines a single template. Each
|
||||||
|
// template will named the base name of its file.
|
||||||
|
// Unlike with ParseFiles, each file should be a stand-alone template
|
||||||
|
// definition suitable for Template.Parse (not Set.Parse); that is, the
|
||||||
|
// file does not contain {{define}} clauses. ParseTemplateFiles is
|
||||||
|
// therefore equivalent to calling the ParseFile function to create
|
||||||
|
// individual templates, which are then added to the set.
|
||||||
|
// Each file must be parseable by itself. Parsing stops if an error is
|
||||||
|
// encountered.
|
||||||
|
func ParseTemplateFiles(pattern string) (*Set, os.Error) {
|
||||||
|
filenames, err := filepath.Glob(pattern)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
set := new(Set)
|
||||||
|
for _, filename := range filenames {
|
||||||
|
t, err := ParseFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := set.add(t); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParseTemplateFiles is like ParseTemplateFiles but
|
||||||
|
// panics if there is a parse error or other problem
|
||||||
|
// constructing the set.
|
||||||
|
func MustParseTemplateFiles(pattern string) *Set {
|
||||||
|
set, err := ParseTemplateFiles(pattern)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
@ -43,18 +43,26 @@ func (s *Set) Funcs(funcMap FuncMap) *Set {
|
|||||||
// a set.
|
// a set.
|
||||||
// The return value is the set, so calls can be chained.
|
// The return value is the set, so calls can be chained.
|
||||||
func (s *Set) Add(templates ...*Template) *Set {
|
func (s *Set) Add(templates ...*Template) *Set {
|
||||||
s.init()
|
|
||||||
for _, t := range templates {
|
for _, t := range templates {
|
||||||
|
if err := s.add(t); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// add adds the argument template to the set.
|
||||||
|
func (s *Set) add(t *Template) os.Error {
|
||||||
|
s.init()
|
||||||
if t.set != nil {
|
if t.set != nil {
|
||||||
panic(fmt.Errorf("template: %q already in a set", t.name))
|
return fmt.Errorf("template: %q already in a set", t.name)
|
||||||
}
|
}
|
||||||
if _, ok := s.tmpl[t.name]; ok {
|
if _, ok := s.tmpl[t.name]; ok {
|
||||||
panic(fmt.Errorf("template: %q already defined in set", t.name))
|
return fmt.Errorf("template: %q already defined in set", t.name)
|
||||||
}
|
}
|
||||||
s.tmpl[t.name] = t
|
s.tmpl[t.name] = t
|
||||||
t.set = s
|
t.set = s
|
||||||
}
|
return nil
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Template returns the template with the given name in the set,
|
// Template returns the template with the given name in the set,
|
||||||
|
@ -138,6 +138,23 @@ func TestParseSetFile(t *testing.T) {
|
|||||||
testExecute(setExecTests, set, t)
|
testExecute(setExecTests, set, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSetParseFiles(t *testing.T) {
|
||||||
|
set := new(Set)
|
||||||
|
err := set.ParseFiles("DOES NOT EXIST")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error for non-existent file; got none")
|
||||||
|
}
|
||||||
|
err = set.ParseFiles("[x")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error for bad pattern; got none")
|
||||||
|
}
|
||||||
|
err = set.ParseFiles("testdata/file*.tmpl")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error parsing files: %v", err)
|
||||||
|
}
|
||||||
|
testExecute(setExecTests, set, t)
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseSetFiles(t *testing.T) {
|
func TestParseSetFiles(t *testing.T) {
|
||||||
set, err := ParseSetFiles("DOES NOT EXIST")
|
set, err := ParseSetFiles("DOES NOT EXIST")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -147,9 +164,71 @@ func TestParseSetFiles(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("expected error for bad pattern; got none")
|
t.Error("expected error for bad pattern; got none")
|
||||||
}
|
}
|
||||||
set, err = ParseSetFiles("testdata/*.tmpl")
|
set, err = ParseSetFiles("testdata/file*.tmpl")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error parsing files: %v", err)
|
t.Fatalf("error parsing files: %v", err)
|
||||||
}
|
}
|
||||||
testExecute(setExecTests, set, t)
|
testExecute(setExecTests, set, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var templateFileExecTests = []execTest{
|
||||||
|
{"teset", `{{template "tmpl1.tmpl"}}{{template "tmpl2.tmpl"}}`, "template1\ntemplate2\n", 0, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetParseTemplateFile(t *testing.T) {
|
||||||
|
set := new(Set)
|
||||||
|
err := set.ParseTemplateFile("DOES NOT EXIST")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error for non-existent file; got none")
|
||||||
|
}
|
||||||
|
err = set.ParseTemplateFile("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error parsing files: %v", err)
|
||||||
|
}
|
||||||
|
testExecute(templateFileExecTests, set, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseTemplateFile(t *testing.T) {
|
||||||
|
set, err := ParseTemplateFile("DOES NOT EXIST")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error for non-existent file; got none")
|
||||||
|
}
|
||||||
|
set, err = ParseTemplateFile("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error parsing files: %v", err)
|
||||||
|
}
|
||||||
|
testExecute(templateFileExecTests, set, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetParseTemplateFiles(t *testing.T) {
|
||||||
|
set := new(Set)
|
||||||
|
err := set.ParseTemplateFiles("DOES NOT EXIST")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error for non-existent file; got none")
|
||||||
|
}
|
||||||
|
err = set.ParseTemplateFiles("[x")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error for bad pattern; got none")
|
||||||
|
}
|
||||||
|
err = set.ParseTemplateFiles("testdata/tmpl*.tmpl")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error parsing files: %v", err)
|
||||||
|
}
|
||||||
|
testExecute(templateFileExecTests, set, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseTemplateFiles(t *testing.T) {
|
||||||
|
set, err := ParseTemplateFiles("DOES NOT EXIST")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error for non-existent file; got none")
|
||||||
|
}
|
||||||
|
set, err = ParseTemplateFiles("[x")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("expected error for bad pattern; got none")
|
||||||
|
}
|
||||||
|
set, err = ParseTemplateFiles("testdata/tmpl*.tmpl")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error parsing files: %v", err)
|
||||||
|
}
|
||||||
|
testExecute(templateFileExecTests, set, t)
|
||||||
|
}
|
||||||
|
1
src/pkg/exp/template/testdata/tmpl1.tmpl
vendored
Normal file
1
src/pkg/exp/template/testdata/tmpl1.tmpl
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
template1
|
1
src/pkg/exp/template/testdata/tmpl2.tmpl
vendored
Normal file
1
src/pkg/exp/template/testdata/tmpl2.tmpl
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
template2
|
Loading…
Reference in New Issue
Block a user