mirror of
https://github.com/fumiama/terasu-cloudflared.git
synced 2026-06-29 00:20:26 +08:00
194 lines
4.5 KiB
Go
194 lines
4.5 KiB
Go
// +build mktemplates
|
|
// Build tag so that users who run `go get zombiezen.com/go/capnproto2/...` don't install this command.
|
|
// cd internal/cmd/mktemplates && go build -tags=mktemplates
|
|
|
|
// mktemplates is a command to regenerate capnpc-go/templates.go.
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"go/format"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"text/template/parse"
|
|
)
|
|
|
|
func main() {
|
|
if len(os.Args) != 3 {
|
|
fmt.Fprintln(os.Stderr, "usage: mktemplates OUT DIR")
|
|
os.Exit(64)
|
|
}
|
|
dir := os.Args[2]
|
|
names, err := listdir(dir)
|
|
if err != nil {
|
|
fatalln(err)
|
|
}
|
|
ts := make([]template, len(names))
|
|
for i, name := range names {
|
|
src, err := ioutil.ReadFile(filepath.Join(dir, name))
|
|
if err != nil {
|
|
fatalf("reading template %s: %v", name, err)
|
|
}
|
|
compiled, err := compileTemplate(name, string(src))
|
|
if err != nil {
|
|
fatalf("compiling template %s: %v", name, err)
|
|
}
|
|
ts[i] = template{
|
|
name: name,
|
|
content: compiled,
|
|
}
|
|
}
|
|
genbuf := new(bytes.Buffer)
|
|
err = generateGo(genbuf, os.Args, ts)
|
|
if err != nil {
|
|
fatalln("generating code:", err)
|
|
}
|
|
code, err := format.Source(genbuf.Bytes())
|
|
if err != nil {
|
|
fatalln("formatting code:", err)
|
|
}
|
|
outname := os.Args[1]
|
|
out, err := os.Create(outname)
|
|
if err != nil {
|
|
fatalf("opening destination %s: %v", outname, err)
|
|
}
|
|
_, err = out.Write(code)
|
|
cerr := out.Close()
|
|
if err != nil {
|
|
fatalf("write to %s: %v", outname, err)
|
|
}
|
|
if cerr != nil {
|
|
fatalln(err)
|
|
}
|
|
}
|
|
|
|
func compileTemplate(name, src string) (string, error) {
|
|
tset, err := parse.Parse(name, src, "{{", "}}", funcStubs)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return tset[name].Root.String(), nil
|
|
}
|
|
|
|
func generateGo(w io.Writer, args []string, ts []template) error {
|
|
src := new(bytes.Buffer)
|
|
for _, t := range ts {
|
|
fmt.Fprintf(src, "{{define %q}}", t.name)
|
|
src.WriteString(t.content)
|
|
src.WriteString("{{end}}")
|
|
}
|
|
|
|
// TODO(light): collect errors
|
|
fmt.Fprintln(w, "// Code generated from templates directory. DO NOT EDIT.")
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "//go:generate", strings.Join(args, " "))
|
|
fmt.Fprintln(w)
|
|
fmt.Fprintln(w, "package main")
|
|
fmt.Fprintln(w, "import (")
|
|
fmt.Fprintln(w, "\t\"strings\"")
|
|
fmt.Fprintln(w, "\t\"text/template\"")
|
|
fmt.Fprintln(w, ")")
|
|
fmt.Fprintln(w, "var templates = template.Must(template.New(\"\").Funcs(template.FuncMap{")
|
|
fmt.Fprintln(w, "\t\"title\": strings.Title,")
|
|
fmt.Fprintf(w, "}).Parse(\n\t%q))\n", src.Bytes())
|
|
for _, t := range ts {
|
|
if strings.HasPrefix(t.name, "_") {
|
|
continue
|
|
}
|
|
fmt.Fprintf(w, "func render%s(r renderer, p %sParams) error {\n\treturn r.Render(%[2]q, p)\n}\n", strings.Title(t.name), t.name)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type template struct {
|
|
name string
|
|
content string
|
|
}
|
|
|
|
func listdir(name string) ([]string, error) {
|
|
f, err := os.Open(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
names, err := f.Readdirnames(-1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
n := 0
|
|
for _, name := range names {
|
|
if !strings.HasPrefix(name, ".") {
|
|
names[n] = name
|
|
n++
|
|
}
|
|
}
|
|
names = names[:n]
|
|
sort.Strings(names)
|
|
return names, nil
|
|
}
|
|
|
|
func fatalln(args ...interface{}) {
|
|
var buf bytes.Buffer
|
|
buf.WriteString("mktemplates: ")
|
|
fmt.Fprintln(&buf, args...)
|
|
os.Stderr.Write(buf.Bytes())
|
|
os.Exit(1)
|
|
}
|
|
|
|
func fatalf(format string, args ...interface{}) {
|
|
var buf bytes.Buffer
|
|
buf.WriteString("mktemplates: ")
|
|
fmt.Fprintf(&buf, format, args...)
|
|
if !bytes.HasSuffix(buf.Bytes(), []byte{'\n'}) {
|
|
buf.Write([]byte{'\n'})
|
|
}
|
|
os.Stderr.Write(buf.Bytes())
|
|
os.Exit(1)
|
|
}
|
|
|
|
var funcStubs = map[string]interface{}{
|
|
// Built-ins
|
|
"and": variadicBoolStub,
|
|
"call": func(interface{}, ...interface{}) (interface{}, error) { return nil, nil },
|
|
"eq": func(arg0 interface{}, args ...interface{}) (bool, error) { return false, nil },
|
|
"ge": cmpStub,
|
|
"gt": cmpStub,
|
|
"html": escaperStub,
|
|
"index": func(interface{}, ...interface{}) (interface{}, error) { return nil, nil },
|
|
"js": escaperStub,
|
|
"le": cmpStub,
|
|
"len": func(interface{}) (int, error) { return 0, nil },
|
|
"lt": cmpStub,
|
|
"ne": cmpStub,
|
|
"not": func(interface{}) bool { return false },
|
|
"or": variadicBoolStub,
|
|
"print": fmt.Sprint,
|
|
"printf": fmt.Sprintf,
|
|
"println": fmt.Sprintln,
|
|
"urlquery": escaperStub,
|
|
|
|
// App-specific
|
|
"title": strings.Title,
|
|
}
|
|
|
|
func variadicBoolStub(arg0 interface{}, args ...interface{}) interface{} {
|
|
return arg0
|
|
}
|
|
|
|
func cmpStub(interface{}, interface{}) (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
func escaperStub(...interface{}) string {
|
|
return ""
|
|
}
|
|
|
|
func importStub() string {
|
|
return ""
|
|
}
|