Run Format

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

     1	// Copyright 2012 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	package template_test
     6	
     7	import (
     8		"io"
     9		"io/ioutil"
    10		"log"
    11		"os"
    12		"path/filepath"
    13		"text/template"
    14	)
    15	
    16	// templateFile defines the contents of a template to be stored in a file, for testing.
    17	type templateFile struct {
    18		name     string
    19		contents string
    20	}
    21	
    22	func createTestDir(files []templateFile) string {
    23		dir, err := ioutil.TempDir("", "template")
    24		if err != nil {
    25			log.Fatal(err)
    26		}
    27		for _, file := range files {
    28			f, err := os.Create(filepath.Join(dir, file.name))
    29			if err != nil {
    30				log.Fatal(err)
    31			}
    32			defer f.Close()
    33			_, err = io.WriteString(f, file.contents)
    34			if err != nil {
    35				log.Fatal(err)
    36			}
    37		}
    38		return dir
    39	}
    40	
    41	// Here we demonstrate loading a set of templates from a directory.
    42	func ExampleTemplate_glob() {
    43		// Here we create a temporary directory and populate it with our sample
    44		// template definition files; usually the template files would already
    45		// exist in some location known to the program.
    46		dir := createTestDir([]templateFile{
    47			// T0.tmpl is a plain template file that just invokes T1.
    48			{"T0.tmpl", `T0 invokes T1: ({{template "T1"}})`},
    49			// T1.tmpl defines a template, T1 that invokes T2.
    50			{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
    51			// T2.tmpl defines a template T2.
    52			{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
    53		})
    54		// Clean up after the test; another quirk of running as an example.
    55		defer os.RemoveAll(dir)
    56	
    57		// pattern is the glob pattern used to find all the template files.
    58		pattern := filepath.Join(dir, "*.tmpl")
    59	
    60		// Here starts the example proper.
    61		// T0.tmpl is the first name matched, so it becomes the starting template,
    62		// the value returned by ParseGlob.
    63		tmpl := template.Must(template.ParseGlob(pattern))
    64	
    65		err := tmpl.Execute(os.Stdout, nil)
    66		if err != nil {
    67			log.Fatalf("template execution: %s", err)
    68		}
    69		// Output:
    70		// T0 invokes T1: (T1 invokes T2: (This is T2))
    71	}
    72	
    73	// This example demonstrates one way to share some templates
    74	// and use them in different contexts. In this variant we add multiple driver
    75	// templates by hand to an existing bundle of templates.
    76	func ExampleTemplate_helpers() {
    77		// Here we create a temporary directory and populate it with our sample
    78		// template definition files; usually the template files would already
    79		// exist in some location known to the program.
    80		dir := createTestDir([]templateFile{
    81			// T1.tmpl defines a template, T1 that invokes T2.
    82			{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
    83			// T2.tmpl defines a template T2.
    84			{"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
    85		})
    86		// Clean up after the test; another quirk of running as an example.
    87		defer os.RemoveAll(dir)
    88	
    89		// pattern is the glob pattern used to find all the template files.
    90		pattern := filepath.Join(dir, "*.tmpl")
    91	
    92		// Here starts the example proper.
    93		// Load the helpers.
    94		templates := template.Must(template.ParseGlob(pattern))
    95		// Add one driver template to the bunch; we do this with an explicit template definition.
    96		_, err := templates.Parse("{{define `driver1`}}Driver 1 calls T1: ({{template `T1`}})\n{{end}}")
    97		if err != nil {
    98			log.Fatal("parsing driver1: ", err)
    99		}
   100		// Add another driver template.
   101		_, err = templates.Parse("{{define `driver2`}}Driver 2 calls T2: ({{template `T2`}})\n{{end}}")
   102		if err != nil {
   103			log.Fatal("parsing driver2: ", err)
   104		}
   105		// We load all the templates before execution. This package does not require
   106		// that behavior but html/template's escaping does, so it's a good habit.
   107		err = templates.ExecuteTemplate(os.Stdout, "driver1", nil)
   108		if err != nil {
   109			log.Fatalf("driver1 execution: %s", err)
   110		}
   111		err = templates.ExecuteTemplate(os.Stdout, "driver2", nil)
   112		if err != nil {
   113			log.Fatalf("driver2 execution: %s", err)
   114		}
   115		// Output:
   116		// Driver 1 calls T1: (T1 invokes T2: (This is T2))
   117		// Driver 2 calls T2: (This is T2)
   118	}
   119	
   120	// This example demonstrates how to use one group of driver
   121	// templates with distinct sets of helper templates.
   122	func ExampleTemplate_share() {
   123		// Here we create a temporary directory and populate it with our sample
   124		// template definition files; usually the template files would already
   125		// exist in some location known to the program.
   126		dir := createTestDir([]templateFile{
   127			// T0.tmpl is a plain template file that just invokes T1.
   128			{"T0.tmpl", "T0 ({{.}} version) invokes T1: ({{template `T1`}})\n"},
   129			// T1.tmpl defines a template, T1 that invokes T2. Note T2 is not defined
   130			{"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
   131		})
   132		// Clean up after the test; another quirk of running as an example.
   133		defer os.RemoveAll(dir)
   134	
   135		// pattern is the glob pattern used to find all the template files.
   136		pattern := filepath.Join(dir, "*.tmpl")
   137	
   138		// Here starts the example proper.
   139		// Load the drivers.
   140		drivers := template.Must(template.ParseGlob(pattern))
   141	
   142		// We must define an implementation of the T2 template. First we clone
   143		// the drivers, then add a definition of T2 to the template name space.
   144	
   145		// 1. Clone the helper set to create a new name space from which to run them.
   146		first, err := drivers.Clone()
   147		if err != nil {
   148			log.Fatal("cloning helpers: ", err)
   149		}
   150		// 2. Define T2, version A, and parse it.
   151		_, err = first.Parse("{{define `T2`}}T2, version A{{end}}")
   152		if err != nil {
   153			log.Fatal("parsing T2: ", err)
   154		}
   155	
   156		// Now repeat the whole thing, using a different version of T2.
   157		// 1. Clone the drivers.
   158		second, err := drivers.Clone()
   159		if err != nil {
   160			log.Fatal("cloning drivers: ", err)
   161		}
   162		// 2. Define T2, version B, and parse it.
   163		_, err = second.Parse("{{define `T2`}}T2, version B{{end}}")
   164		if err != nil {
   165			log.Fatal("parsing T2: ", err)
   166		}
   167	
   168		// Execute the templates in the reverse order to verify the
   169		// first is unaffected by the second.
   170		err = second.ExecuteTemplate(os.Stdout, "T0.tmpl", "second")
   171		if err != nil {
   172			log.Fatalf("second execution: %s", err)
   173		}
   174		err = first.ExecuteTemplate(os.Stdout, "T0.tmpl", "first")
   175		if err != nil {
   176			log.Fatalf("first: execution: %s", err)
   177		}
   178	
   179		// Output:
   180		// T0 (second version) invokes T1: (T1 invokes T2: (T2, version B))
   181		// T0 (first version) invokes T1: (T1 invokes T2: (T2, version A))
   182	}

View as plain text