forked from tcnksm/gcli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.go
112 lines (92 loc) · 2.4 KB
/
template.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package skeleton
import (
"bytes"
"io"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/tcnksm/gcli/helper"
)
// Template stores meta data of template
type Template struct {
// Path is the path to this template.
Path string
// OutputPathTmpl is the template for outputPath.
OutputPathTmpl string
}
// Exec evaluate this template and write it to provided file.
// At First, it reads template content.
// Then, it generates output file path from output path template and its data.
// Then, it creates directory if not exist from output path.
// Then, it opens output file.
// Finally, it evaluates template contents and generate it to output file.
// If output file is gocode, run go fmt.
//
// It returns an error if any.
func (t *Template) Exec(data interface{}) (string, error) {
// Asset function is generated by go-bindata
contents, err := Asset(t.Path)
if err != nil {
return "", err
}
outputPath, err := processPathTmpl(t.OutputPathTmpl, data)
if err != nil {
return "", err
}
// Create directory if necessary
dir, _ := filepath.Split(outputPath)
if dir != "" {
if err := mkdir(dir); err != nil {
return "", err
}
}
wr, err := os.Create(outputPath)
if err != nil {
return "", err
}
if err := execute(string(contents), wr, data); err != nil {
return "", err
}
if strings.HasSuffix(outputPath, ".go") {
helper.GoFmt(outputPath, nil)
}
return outputPath, nil
}
// processPathTmpl evaluates output path template string
// and generate real absolute path. Any errors that occur are returned.
func processPathTmpl(pathTmpl string, data interface{}) (string, error) {
var outputPathBuf bytes.Buffer
if err := execute(pathTmpl, &outputPathBuf, data); err != nil {
return "", err
}
return outputPathBuf.String(), nil
}
// mkdir makes the named directory.
func mkdir(dir string) error {
if _, err := os.Stat(dir); err == nil {
return nil
}
return os.MkdirAll(dir, 0777)
}
// execute evaluates template content with data
// and write them to writer.
func execute(content string, wr io.Writer, data interface{}) error {
name := ""
funcs := funcMap()
tmpl, err := template.New(name).Funcs(funcs).Parse(content)
if err != nil {
return err
}
if err := tmpl.Execute(wr, data); err != nil {
return err
}
return nil
}
func funcMap() template.FuncMap {
return template.FuncMap{
"date": dateFunc(),
"title": strings.Title,
"toUpper": strings.ToUpper,
}
}