-
Notifications
You must be signed in to change notification settings - Fork 0
/
generate_cli.go
120 lines (118 loc) · 2.87 KB
/
generate_cli.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package golang
import (
"bytes"
"os"
"path/filepath"
"strconv"
)
// GenerateCLI geneates a simple Go CLI app that only calls a single func.
// The resulting command has no arguments.
// It reads function input from stdin in JSON format and writes the result to stdout in JSON format.
func GenerateCLI(srcDir, pkg, funcName, outFile string) error {
funcSignature, err := ReadFuncSignature(srcDir, pkg, funcName)
if err != nil {
return err
}
importMap := ImportMap{}
importMap.AddPackage(pkg)
importMap.AddPackage("encoding/json")
importMap.AddPackage("os")
for _, input := range funcSignature.Inputs {
for _, pkg := range input.Type.Packages() {
importMap.AddPackage(pkg)
}
}
for _, output := range funcSignature.Outputs {
for _, pkg := range output.Type.Packages() {
importMap.AddPackage(pkg)
}
}
err = os.MkdirAll(filepath.Dir(outFile), os.ModePerm)
if err != nil {
return err
}
var b bytes.Buffer
b.WriteString("package main\n\n")
importMap.Write(&b)
b.WriteString("\nfunc main() {\n")
b.WriteString("\tvar input struct {\n")
for _, input := range funcSignature.Inputs {
name, err := ParseName(input.Name)
if err != nil {
return err
}
b.WriteString("\t\t")
b.WriteString(name.PascalCase())
b.WriteString(" ")
input.Type.Write(&b)
b.WriteString(" `json:\"")
b.WriteString(name.SnakeCase())
b.WriteString("\"`\n")
}
b.WriteString("\t}\n")
b.WriteString("\tjson.NewDecoder(os.Stdin).Decode(&input)\n")
b.WriteString("\t")
if len(funcSignature.Outputs) > 0 {
for i := range funcSignature.Outputs {
if i > 0 {
b.WriteString(", ")
}
b.WriteString("out")
b.WriteString(strconv.Itoa(i + 1))
}
b.WriteString(" := ")
}
p, ok := importMap.Resolve(pkg)
if !ok {
panic("package not found")
}
b.WriteString(p)
b.WriteString(".")
b.WriteString(funcName)
b.WriteString("(")
for i, input := range funcSignature.Inputs {
name, err := ParseName(input.Name)
if err != nil {
return err
}
if i > 0 {
b.WriteString(", ")
}
b.WriteString("input.")
b.WriteString(name.PascalCase())
}
b.WriteString(")\n")
b.WriteString("\tvar output struct {\n")
for _, output := range funcSignature.Outputs {
name, err := ParseName(output.Name)
if err != nil {
return err
}
b.WriteString("\t\t")
b.WriteString(name.PascalCase())
b.WriteString(" ")
output.Type.Write(&b)
b.WriteString(" `json:\"")
b.WriteString(name.SnakeCase())
b.WriteString("\"`\n")
}
b.WriteString("\t}\n")
for i := range funcSignature.Outputs {
b.WriteString("\toutput.Out")
b.WriteString(strconv.Itoa(i + 1))
b.WriteString(" = out")
b.WriteString(strconv.Itoa(i + 1))
b.WriteString("\n")
}
b.WriteString("\tjson.NewEncoder(os.Stdout).Encode(output)\n")
b.WriteString("}\n")
err = os.WriteFile(outFile, b.Bytes(), os.ModePerm)
if err != nil {
return err
}
err = RunGoimports(outFile)
if err != nil {
return err
}
return nil
}