Commit 222450ad authored by Rob Pike's avatar Rob Pike

exp/template: add globbing helpers to load groups of files into sets.

Also make the Set.Parse methods variadic so you can parse static lists of files without loops.

R=rsc, dsymonds, r
CC=golang-dev
https://golang.org/cl/4802051
parent 99e5d48e
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package template package template
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
...@@ -65,34 +66,97 @@ func (s *Set) MustParse(text string) *Set { ...@@ -65,34 +66,97 @@ func (s *Set) MustParse(text string) *Set {
return s return s
} }
// ParseFile parses the named file into a set of named templates. // ParseFile parses the named files into a set of named templates.
func (s *Set) ParseFile(filename string) os.Error { // Each file must be parseable by itself. Parsing stops if an error is
// encountered.
func (s *Set) ParseFile(filenames ...string) os.Error {
for _, filename := range filenames {
b, err := ioutil.ReadFile(filename) b, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return err return err
} }
return s.Parse(string(b)) err = s.Parse(string(b))
if err != nil {
return err
}
}
return nil
} }
// MustParseFile parses the named file into a set of named templates. // MustParseFile parses the named file into a set of named templates.
// It panics if the file cannot be read or the set cannot be parsed. // Each file must be parseable by itself.
func (s *Set) MustParseFile(filename string) *Set { // MustParseFile panics if any file cannot be read or parsed.
if err := s.ParseFile(filename); err != nil { func (s *Set) MustParseFile(filenames ...string) *Set {
err := s.ParseFile(filenames...)
if err != nil {
panic(err) panic(err)
} }
return s return s
} }
// ParseSetFile creates a new Set and parses the set definition from the // ParseSetFile creates a new Set and parses the set definition from the
// named file. // named files. Each file must be individually parseable.
func ParseSetFile(filename string) (*Set, os.Error) { func ParseSetFile(filenames ...string) (set *Set, err os.Error) {
s := new(Set) s := new(Set)
return s, s.ParseFile(filename) var b []byte
for _, filename := range filenames {
b, err = ioutil.ReadFile(filename)
if err != nil {
return
}
err = s.Parse(string(b))
if err != nil {
return
}
}
return s, nil
} }
// MustParseSetFile creates a new Set and parses the set definition from the // MustParseSetFile creates a new Set and parses the set definition from the
// named file. // named files. Each file must be individually parseable.
// It panics if the file cannot be read or the set cannot be parsed. // MustParseSetFile panics if any file cannot be read or parsed.
func MustParseSetFile(filename string) *Set { func MustParseSetFile(filenames ...string) *Set {
return new(Set).MustParseFile(filename) s, err := ParseSetFile(filenames...)
if err != nil {
panic(err)
}
return s
}
// ParseFiles parses the set definition from the files identified by the
// pattern. The pattern is processed by filepath.Glob and must match at
// least one file.
func (s *Set) ParseFiles(pattern string) os.Error {
filenames, err := filepath.Glob(pattern)
if err != nil {
return err
}
if len(filenames) == 0 {
return fmt.Errorf("pattern matches no files: %#q", pattern)
}
return s.ParseFile(filenames...)
}
// ParseSetFiles creates a new Set and parses the set definition from the
// files identified by the pattern. The pattern is processed by filepath.Glob
// and must match at least one file.
func ParseSetFiles(pattern string) (*Set, os.Error) {
set := new(Set)
err := set.ParseFiles(pattern)
if err != nil {
return nil, err
}
return set, nil
}
// MustParseSetFiles creates a new Set and parses the set definition from the
// files identified by the pattern. The pattern is processed by filepath.Glob.
// MustParseSetFiles panics if the pattern is invalid or a matched file cannot be
// read or parsed.
func MustParseSetFiles(pattern string) *Set {
set, err := ParseSetFiles(pattern)
if err != nil {
panic(err)
}
return set
} }
...@@ -88,6 +88,7 @@ var setExecTests = []execTest{ ...@@ -88,6 +88,7 @@ var setExecTests = []execTest{
{"testFunc .", `{{oneArg .}}`, "oneArg=joe", "joe", true}, {"testFunc .", `{{oneArg .}}`, "oneArg=joe", "joe", true},
} }
// These strings are also in testdata/*.
const setText1 = ` const setText1 = `
{{define "x"}}TEXT{{end}} {{define "x"}}TEXT{{end}}
{{define "dotV"}}{{.V}}{{end}} {{define "dotV"}}{{.V}}{{end}}
...@@ -111,3 +112,44 @@ func TestSetExecute(t *testing.T) { ...@@ -111,3 +112,44 @@ func TestSetExecute(t *testing.T) {
} }
testExecute(setExecTests, set, t) testExecute(setExecTests, set, t)
} }
func TestSetParseFile(t *testing.T) {
set := new(Set)
err := set.ParseFile("DOES NOT EXIST")
if err == nil {
t.Error("expected error for non-existent file; got none")
}
err = set.ParseFile("testdata/file1.tmpl", "testdata/file2.tmpl")
if err != nil {
t.Fatalf("error parsing files: %v", err)
}
testExecute(setExecTests, set, t)
}
func TestParseSetFile(t *testing.T) {
set, err := ParseSetFile("DOES NOT EXIST")
if err == nil {
t.Error("expected error for non-existent file; got none")
}
set, err = ParseSetFile("testdata/file1.tmpl", "testdata/file2.tmpl")
if err != nil {
t.Fatalf("error parsing files: %v", err)
}
testExecute(setExecTests, set, t)
}
func TestParseSetFiles(t *testing.T) {
set, err := ParseSetFiles("NO SUCH FILE")
if err == nil {
t.Error("expected error for empty file list; got none")
}
set, err = ParseSetFiles("[x")
if err == nil {
t.Error("expected error for bad pattern; got none")
}
set, err = ParseSetFiles("testdata/*.tmpl")
if err != nil {
t.Fatalf("error parsing files: %v", err)
}
testExecute(setExecTests, set, t)
}
{{define "x"}}TEXT{{end}}
{{define "dotV"}}{{.V}}{{end}}
{{define "dot"}}{{.}}{{end}}
{{define "nested"}}{{template "dot" .}}{{end}}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment