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  }