From 0bfc3ce4b0f2a0d607c08c57619cde480c9f2765 Mon Sep 17 00:00:00 2001 From: Christopher Ramey Date: Sat, 28 Dec 2019 10:23:14 -0900 Subject: [PATCH] complete rewrite, added basic documentation --- README.md | 28 +++++++++++ main.go | 143 +++++++++++++++++++++++------------------------------- 2 files changed, 88 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index e69de29..f058a25 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,28 @@ +togo +==== +togo converts files to Go source code as a byte array. +togo is based on (but is a complete rewrite of) +[Franco Lazzarino's togo](https://github.com/flazz/togo). + + +usage +----- +togo is designed to be embedded in your Go project for a dependency free +way to manage assets. + +First, copy `main.go` from togo into a subdirectory in your +project (for example, a subdirectory named `togo`.) + +Next, add comments to indicate to go generate that you wish to run +your local copy of togo to build assets. + + //go:generate go run ./togo -n Favicon_ico -i assets/favicon.ico -p static -o static/favicon_ico.go + +togo takes some basic arguments: + +Argument | Description +-------- | ----------- +-p | generated package name +-n | generated variable name +-i | input file name +-o | output file name diff --git a/main.go b/main.go index bac616a..6818695 100644 --- a/main.go +++ b/main.go @@ -1,111 +1,88 @@ package main import ( - "bytes" "flag" - "go/format" + "fmt" "io" - "io/ioutil" "log" "os" - "text/template" + "time" ) -const chunkSize = 0x10 - -const tmpl = ` -package {{.Pkg}} - -var {{.Name}} = []byte{ - // {{ len .Value }} bytes from {{ .InputPath }} - {{ range .Chunks -}} - {{ range . }} {{ printf "0x%02x" . }}, {{ end }} - {{ end }} -} -` - -var t *template.Template - -func init() { - t = template.Must(template.New("constfile").Parse(tmpl)) -} - -type file struct { - Pkg, Name, InputPath string - Value []byte -} - -func (f *file) Chunks() [][]byte { - return chunks(f.Value, chunkSize) -} - -func chunks(b []byte, n int) [][]byte { - var c [][]byte - - nChks := len(b) / n - - for i := 0; i < nChks; i++ { - m := i * n - c = append(c, b[m:m+n]) - } - - if r := len(b) % n; r > 0 { - m := n * nChks - c = append(c, b[m:m+r]) - } - - return c -} - -func (f *file) Read() (err error) { - f.Value, err = ioutil.ReadFile(f.InputPath) - return -} +func main() { + pkg := flag.String("p", "", "package") + name := flag.String("n", "", "const name") + inputfn := flag.String("i", "", "input file") + outputfn := flag.String("o", "", "output file") + flag.Parse() -func (f *file) Render(w io.Writer) error { - outputPath := f.InputPath + ".go" - var buf bytes.Buffer - if err := t.Execute(&buf, &f); err != nil { - return err + if *pkg == "" { + log.Fatal("pkg required") } - b, err := format.Source(buf.Bytes()) - if err != nil { - log.Fatal(err) + if *name == "" { + log.Fatal("name required") } - if err := ioutil.WriteFile(outputPath, b, os.ModePerm); err != nil { - return err + if *inputfn == "" { + log.Fatal("input file required") } - return nil -} - -func main() { - - var f file - flag.StringVar(&f.Pkg, "pkg", "", "package") - flag.StringVar(&f.Name, "name", "", "const name") - flag.StringVar(&f.InputPath, "input", "", "input file") - flag.Parse() - - if f.Pkg == "" { - log.Fatal("pkg required") + if *outputfn == "" { + *outputfn = *inputfn + ".go" } - if f.Name == "" { - log.Fatal("name required") + omod := fmod(*outputfn) + imod := fmod(*inputfn) + if omod.After(imod) { + log.Printf("Refusing to update %s\n", *outputfn) + return } - if f.InputPath == "" { - log.Fatal("input file required") + ifile, err := os.Open(*inputfn) + if err != nil { + log.Fatal(err) } + defer ifile.Close() - if err := f.Read(); err != nil { + ofile, err := os.OpenFile(*outputfn, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0660) + if err != nil { log.Fatal(err) } + defer ofile.Close() + + fmt.Fprintf(ofile, "package %s\n\nvar %s = []byte{", *pkg, *name) + + buf := make([]byte, 4096) + for c := 0; ; { + i, err := ifile.Read(buf) + if err != nil { + if err != io.EOF { + log.Fatal(err) + } + break + } + + for j := 0; j < i; j++ { + if (c % 13) == 0 { + fmt.Fprintf(ofile, "\n\t") + } else { + fmt.Fprintf(ofile, " ") + } + fmt.Fprintf(ofile, "0x%02x,", buf[j]) + c++ + } + } + fmt.Fprintf(ofile, "\n}\n") +} - if err := f.Render(os.Stdout); err != nil { +func fmod(fn string) time.Time { + fi, err := os.Stat(fn) + if err != nil { + if os.IsNotExist(err) { + return time.Time{} + } log.Fatal(err) } + return fi.ModTime() }