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