...
Run Format

Source file src/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 the
    95	// files identified by the pattern, which must match at least one file. The
    96	// returned template will have the (base) name and (parsed) contents of the
    97	// first file matched by the pattern. ParseGlob is equivalent to calling
    98	// ParseFiles with the list of files matched by the pattern.
    99	//
   100	// When parsing multiple files with the same name in different directories,
   101	// the last one mentioned will be the one that results.
   102	func ParseGlob(pattern string) (*Template, error) {
   103		return parseGlob(nil, pattern)
   104	}
   105	
   106	// ParseGlob parses the template definitions in the files identified by the
   107	// pattern and associates the resulting templates with t. The pattern is
   108	// processed by filepath.Glob and must match at least one file. ParseGlob is
   109	// equivalent to calling t.ParseFiles with the list of files matched by the
   110	// pattern.
   111	//
   112	// When parsing multiple files with the same name in different directories,
   113	// the last one mentioned will be the one that results.
   114	func (t *Template) ParseGlob(pattern string) (*Template, error) {
   115		t.init()
   116		return parseGlob(t, pattern)
   117	}
   118	
   119	// parseGlob is the implementation of the function and method ParseGlob.
   120	func parseGlob(t *Template, pattern string) (*Template, error) {
   121		filenames, err := filepath.Glob(pattern)
   122		if err != nil {
   123			return nil, err
   124		}
   125		if len(filenames) == 0 {
   126			return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
   127		}
   128		return parseFiles(t, filenames...)
   129	}
   130	

View as plain text