...

Source file src/pkg/text/template/helper.go

     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	// Helper functions to make constructing templates easier.
     6	
     7	package template
     8	
     9	import (
    10		"fmt"
    11		"io/ioutil"
    12		"path/filepath"
    13	)
    14	
    15	// Functions and methods to parse templates.
    16	
    17	// Must is a helper that wraps a call to a function returning (*Template, error)
    18	// and panics if the error is non-nil. It is intended for use in variable
    19	// initializations such as
    20	//	var t = template.Must(template.New("name").Parse("text"))
    21	func Must(t *Template, err error) *Template {
    22		if err != nil {
    23			panic(err)
    24		}
    25		return t
    26	}
    27	
    28	// ParseFiles creates a new Template and parses the template definitions from
    29	// the named files. The returned template's name will have the base name and
    30	// parsed contents of the first file. There must be at least one file.
    31	// If an error occurs, parsing stops and the returned *Template is nil.
    32	//
    33	// When parsing multiple files with the same name in different directories,
    34	// the last one mentioned will be the one that results.
    35	// For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template
    36	// named "foo", while "a/foo" is unavailable.
    37	func ParseFiles(filenames ...string) (*Template, error) {
    38		return parseFiles(nil, filenames...)
    39	}
    40	
    41	// ParseFiles parses the named files and associates the resulting templates with
    42	// t. If an error occurs, parsing stops and the returned template is nil;
    43	// otherwise it is t. There must be at least one file.
    44	// Since the templates created by ParseFiles are named by the base
    45	// names of the argument files, t should usually have the name of one
    46	// of the (base) names of the files. If it does not, depending on t's
    47	// contents before calling ParseFiles, t.Execute may fail. In that
    48	// case use t.ExecuteTemplate to execute a valid template.
    49	//
    50	// When parsing multiple files with the same name in different directories,
    51	// the last one mentioned will be the one that results.
    52	func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
    53		t.init()
    54		return parseFiles(t, filenames...)
    55	}
    56	
    57	// parseFiles is the helper for the method and function. If the argument
    58	// template is nil, it is created from the first file.
    59	func parseFiles(t *Template, filenames ...string) (*Template, error) {
    60		if len(filenames) == 0 {
    61			// Not really a problem, but be consistent.
    62			return nil, fmt.Errorf("template: no files named in call to ParseFiles")
    63		}
    64		for _, filename := range filenames {
    65			b, err := ioutil.ReadFile(filename)
    66			if err != nil {
    67				return nil, err
    68			}
    69			s := string(b)
    70			name := filepath.Base(filename)
    71			// First template becomes return value if not already defined,
    72			// and we use that one for subsequent New calls to associate
    73			// all the templates together. Also, if this file has the same name
    74			// as t, this file becomes the contents of t, so
    75			//  t, err := New(name).Funcs(xxx).ParseFiles(name)
    76			// works. Otherwise we create a new template associated with t.
    77			var tmpl *Template
    78			if t == nil {
    79				t = New(name)
    80			}
    81			if name == t.Name() {
    82				tmpl = t
    83			} else {
    84				tmpl = t.New(name)
    85			}
    86			_, err = tmpl.Parse(s)
    87			if err != nil {
    88				return nil, err
    89			}
    90		}
    91		return t, nil
    92	}
    93	
    94	// ParseGlob creates a new Template and parses the template definitions from
    95	// the files identified by the pattern. The files are matched according to the
    96	// semantics of filepath.Match, and the pattern must match at least one file.
    97	// The returned template will have the (base) name and (parsed) contents of the
    98	// first file matched by the pattern. ParseGlob is equivalent to calling
    99	// ParseFiles with the list of files matched by the pattern.
   100	//
   101	// When parsing multiple files with the same name in different directories,
   102	// the last one mentioned will be the one that results.
   103	func ParseGlob(pattern string) (*Template, error) {
   104		return parseGlob(nil, pattern)
   105	}
   106	
   107	// ParseGlob parses the template definitions in the files identified by the
   108	// pattern and associates the resulting templates with t. The files are matched
   109	// according to the semantics of filepath.Match, and the pattern must match at
   110	// least one file. ParseGlob is equivalent to calling t.ParseFiles with the
   111	// list of files matched by the pattern.
   112	//
   113	// When parsing multiple files with the same name in different directories,
   114	// the last one mentioned will be the one that results.
   115	func (t *Template) ParseGlob(pattern string) (*Template, error) {
   116		t.init()
   117		return parseGlob(t, pattern)
   118	}
   119	
   120	// parseGlob is the implementation of the function and method ParseGlob.
   121	func parseGlob(t *Template, pattern string) (*Template, error) {
   122		filenames, err := filepath.Glob(pattern)
   123		if err != nil {
   124			return nil, err
   125		}
   126		if len(filenames) == 0 {
   127			return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
   128		}
   129		return parseFiles(t, filenames...)
   130	}
   131	

View as plain text