This repository has been archived by the owner on Nov 16, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.go
104 lines (89 loc) · 2.89 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
embd is a tool to help embed various files into go source code.
It has signature
embd [options] file
The options are
Example: 'embd a.sql' creates a.sql.go which which has 'const a = "...contents of a.sql..."'
Example: 'embd a.sql -n foo' creates a.sql.go with 'const foo = ...'
Options:
-n string
name of the variable to generate (default <filename>)
For example suppose `schema.sql` contains the schema for some
database and we want to use. We can't read the file at runtime like this:
ioutil.ReadAll("schema.sql")
unless the server is running from the source directory, which is usually
not the case. An easier workaround is to copy and paste the contents of
`schema.sql` into the source code via declaring some variable
const schema = "...sql code..."
That is what `embd` does for you. It also works great for embedding
any small text~ish files like `JSON`, `YAML`, `SQL`, `CSS`, `HTML`, etc.
I wrote it because I missed the ability to `require("really.anything")` from `webpack`
in the javascript ecosystem.
Note: this tool always saves the generated file in the directory where it was called.
So `embd foo/bar.txt` generates `./bar.txt.go`.
*/
package main
import (
"flag"
"fmt"
"go/format"
"go/parser"
"go/token"
"io/ioutil"
"path/filepath"
"strings"
)
func main() {
fileName, variableName := parseArgs()
packageName := getPackageName(".")
writeEmbedding(fileName, variableName, packageName)
}
func parseArgs() (fileName, variableName string) {
// step 1: read input
flag.CommandLine.Usage = func() {
fmt.Println(`embed a file into go source code
Example: 'embd a.sql' creates a.sql.go which which has 'const a = "...contents of a.sql..."'
Example: 'embd a.sql -n foo' creates a.sql.go with 'const foo = ...'
Options:`)
flag.CommandLine.PrintDefaults()
}
flag.StringVar(&variableName, "n", "", "name of the variable to generate (default <filename>)")
flag.Parse()
fileName = flag.Arg(0)
if variableName == "" {
// TODO replace bad file name characters
// also maybe use full file name and replace . with _
_, s := filepath.Split(fileName)
variableName = strings.Split(s, ".")[0]
}
return
}
func getPackageName(directory string) (packageName string) {
packageMap, err := parser.ParseDir(token.NewFileSet(), directory, nil, parser.PackageClauseOnly)
if err != nil {
panic(err)
}
for packageName = range packageMap {
break
}
if packageName == "" {
panic("could not find package name")
}
return packageName
}
func writeEmbedding(fileName, variableName, packageName string) {
s, err := ioutil.ReadFile(fileName)
if err != nil {
panic(err)
}
_, outputFile := filepath.Split(fileName)
outputFile += ".go"
out := fmt.Sprintln("package " + packageName)
out += fmt.Sprintln("//generated by embd")
out += fmt.Sprintf("const %s = %q", variableName, s)
fmtout, err := format.Source([]byte(out))
if err != nil {
panic(err)
}
ioutil.WriteFile(outputFile, fmtout, 0666)
}