github.com/ngocphuongnb/tetua@v0.0.7-alpha/packages/jade/main.go (about) 1 // https://github.com/Joker/jade/blob/master/cmd/jade/main.go 2 3 package jadecmd 4 5 import ( 6 "bytes" 7 "flag" 8 "fmt" 9 "go/ast" 10 "go/parser" 11 "go/printer" 12 "go/token" 13 "io/ioutil" 14 "log" 15 "os" 16 "path/filepath" 17 "regexp" 18 "strconv" 19 20 "github.com/Joker/jade" 21 "golang.org/x/tools/imports" 22 ) 23 24 var ( 25 dict = map[string]string{} 26 lib_name = "" 27 outdir string 28 basedir string 29 pkg_name string 30 stdlib bool 31 stdbuf bool 32 writer bool 33 inline bool 34 format bool 35 ns_files = map[string]bool{} 36 ) 37 38 func use() { 39 fmt.Printf("Usage: %s [OPTION]... [FILE]... \n", os.Args[0]) 40 flag.PrintDefaults() 41 } 42 func init() { 43 flag.StringVar(&outdir, "d", "./", `directory for generated .go files`) 44 flag.StringVar(&basedir, "basedir", "./", `base directory for templates`) 45 flag.StringVar(&pkg_name, "pkg", "jade", `package name for generated files`) 46 flag.BoolVar(&format, "fmt", false, `HTML pretty print output for generated functions`) 47 flag.BoolVar(&inline, "inline", false, `inline HTML in generated functions`) 48 flag.BoolVar(&stdlib, "stdlib", false, `use stdlib functions`) 49 flag.BoolVar(&stdbuf, "stdbuf", false, `use bytes.Buffer [default bytebufferpool.ByteBuffer]`) 50 flag.BoolVar(&writer, "writer", false, `use io.Writer for output`) 51 } 52 53 // 54 55 type goAST struct { 56 node *ast.File 57 fset *token.FileSet 58 } 59 60 func (a *goAST) bytes(bb *bytes.Buffer) []byte { 61 printer.Fprint(bb, a.fset, a.node) 62 return bb.Bytes() 63 } 64 65 func parseGoSrc(fileName string, GoSrc interface{}) (out goAST, err error) { 66 out.fset = token.NewFileSet() 67 out.node, err = parser.ParseFile(out.fset, fileName, GoSrc, parser.ParseComments) 68 return 69 } 70 71 func goImports(absPath string, src []byte) []byte { 72 fmtOut, err := imports.Process(absPath, src, &imports.Options{TabWidth: 4, TabIndent: true, Comments: true, Fragment: true}) 73 if err != nil { 74 log.Fatalln("goImports(): ", err) 75 } 76 77 return fmtOut 78 } 79 80 // 81 82 func genFile(path, outdir, pkg_name string) { 83 log.Printf("\nfile: %q\n", path) 84 85 var ( 86 dir, fname = filepath.Split(path) 87 outPath = outdir + "/" + fname 88 rx, _ = regexp.Compile("[^a-zA-Z0-9]+") 89 constName = rx.ReplaceAllString(fname[:len(fname)-4], "") 90 ) 91 92 wd, err := os.Getwd() 93 if err == nil && wd != dir && dir != "" { 94 os.Chdir(dir) 95 defer os.Chdir(wd) 96 } 97 98 if _, ok := ns_files[fname]; ok { 99 sfx := "_" + strconv.Itoa(len(ns_files)) 100 ns_files[fname+sfx] = true 101 outPath += sfx 102 constName += sfx 103 } else { 104 ns_files[fname] = true 105 } 106 107 fl, err := ioutil.ReadFile(fname) 108 if err != nil { 109 log.Fatalln("cmd/jade: ReadFile(): ", err) 110 } 111 112 // 113 114 jst, err := jade.New(path).Parse(fl) 115 if err != nil { 116 log.Fatalln("cmd/jade: jade.New(path).Parse(): ", err) 117 } 118 119 var ( 120 bb = new(bytes.Buffer) 121 tpl = newLayout(constName) 122 ) 123 tpl.writeBefore(bb) 124 before := bb.Len() 125 jst.WriteIn(bb) 126 if before == bb.Len() { 127 fmt.Print("generated: skipped (empty output) done.\n\n") 128 return 129 } 130 tpl.writeAfter(bb) 131 132 // 133 134 gst, err := parseGoSrc(outPath, bb) 135 if err != nil { 136 // TODO 137 bb.WriteString("\n\nERROR: parseGoSrc(): ") 138 bb.WriteString(err.Error()) 139 ioutil.WriteFile(outPath+"__Error.go", bb.Bytes(), 0644) 140 log.Fatalln("cmd/jade: parseGoSrc(): ", err) 141 } 142 143 gst.collapseWriteString(inline, constName) 144 gst.checkType() 145 gst.checkUnresolvedBlock() 146 147 bb.Reset() 148 fmtOut := goImports(outPath, gst.bytes(bb)) 149 150 // 151 152 err = ioutil.WriteFile(outPath+".go", fmtOut, 0644) 153 if err != nil { 154 log.Fatalln("cmd/jade: WriteFile(): ", err) 155 } 156 fmt.Printf("generated: %s.go done.\n\n", outPath) 157 } 158 159 func genDir(dir, outdir, pkg_name string) { 160 err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { 161 if err != nil { 162 return fmt.Errorf("prevent panic by handling failure accessing a path %q: %v\n", dir, err) 163 } 164 165 if ext := filepath.Ext(info.Name()); ext == ".jade" || ext == ".pug" { 166 genFile(path, outdir, pkg_name) 167 } 168 return nil 169 }) 170 if err != nil { 171 log.Fatalln(err) 172 } 173 } 174 175 // 176 177 func main() { 178 flag.Usage = use 179 flag.Parse() 180 if len(flag.Args()) == 0 { 181 use() 182 return 183 } 184 185 jade.Config(golang) 186 187 if _, err := os.Stat(outdir); os.IsNotExist(err) { 188 os.MkdirAll(outdir, 0755) 189 } 190 outdir, _ = filepath.Abs(outdir) 191 192 if _, err := os.Stat(basedir); !os.IsNotExist(err) && basedir != "./" { 193 os.Chdir(basedir) 194 } 195 196 for _, jadePath := range flag.Args() { 197 fmt.Println(jadePath) 198 stat, err := os.Stat(jadePath) 199 if err != nil { 200 log.Fatalln(err) 201 } 202 203 absPath, _ := filepath.Abs(jadePath) 204 if stat.IsDir() { 205 genDir(absPath, outdir, pkg_name) 206 } else { 207 genFile(absPath, outdir, pkg_name) 208 } 209 if !stdlib { 210 makeJfile(stdbuf) 211 } 212 } 213 }