-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
161 lines (131 loc) · 3.49 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
"ella.to/ella/internal/compiler/ast"
"ella.to/ella/internal/compiler/gen"
"ella.to/ella/internal/compiler/parser"
)
const Version = "0.2.0"
const usage = `
███████╗██╗░░░░░██╗░░░░░░█████╗░
██╔════╝██║░░░░░██║░░░░░██╔══██╗
█████╗░░██║░░░░░██║░░░░░███████║
██╔══╝░░██║░░░░░██║░░░░░██╔══██║
███████╗███████╗███████╗██║░░██║
╚══════╝╚══════╝╚══════╝╚═╝░░╚═╝ v` + Version + `
Usage: ella [command]
Commands:
- fmt Format one or many files in place using glob pattern
ella fmt <glob path>
- gen Generate code from a folder to a file and currently
supports .go and .ts extensions
ella gen <pkg> <output path to file> <search glob paths...>
- ver Print the version of ella
example:
ella fmt "./path/to/*.ella"
ella gen rpc ./path/to/output.go "./path/to/*.ella"
ella gen rpc ./path/to/output.ts "./path/to/*.ella" "./path/to/other/*.ella"
`
func main() {
if len(os.Args) < 2 {
fmt.Print(usage)
os.Exit(0)
}
var err error
switch os.Args[1] {
case "fmt":
if len(os.Args) < 3 {
fmt.Print(usage)
os.Exit(0)
}
err = formatCmd(os.Args[2])
case "gen":
if len(os.Args) < 5 {
fmt.Print(usage)
os.Exit(0)
}
err = genCmd(os.Args[2], os.Args[3], os.Args[4:]...)
case "ver":
fmt.Println(Version)
default:
fmt.Print(usage)
os.Exit(0)
}
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func formatCmd(searchPaths ...string) error {
for _, searchPath := range searchPaths {
filenames, err := filesFromGlob(searchPath)
if err != nil {
return err
}
for _, filename := range filenames {
doc, err := parser.ParseDocument(parser.NewWithFilenames(filename))
if err != nil {
return err
}
var sb strings.Builder
doc.Format(&sb)
err = os.WriteFile(filename, []byte(sb.String()), os.ModePerm)
if err != nil {
return err
}
}
}
return nil
}
func genCmd(pkg, out string, searchPaths ...string) (err error) {
var docs []*ast.Document
for _, searchPath := range searchPaths {
filenames, err := filesFromGlob(searchPath)
if err != nil {
return err
}
for _, filename := range filenames {
doc, err := parser.ParseDocument(parser.NewWithFilenames(filename))
if err != nil {
return err
}
docs = append(docs, doc)
}
}
if err = parser.Validate(docs...); err != nil {
return err
}
return gen.Generate(pkg, out, docs)
}
// make sure only pattern is used at the end of the search path
// and only one level of search path is allowed
func filesFromGlob(searchPath string) ([]string, error) {
filenames := []string{}
dir, pattern := filepath.Split(searchPath)
if dir == "" {
dir = "."
}
if strings.Contains(dir, "*") {
return nil, fmt.Errorf("glob pattern should not be used in dir level: %s", searchPath)
}
entries, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
match, err := filepath.Match(pattern, entry.Name())
if err != nil {
return nil, err
}
if match {
filenames = append(filenames, filepath.Join(dir, entry.Name()))
}
}
return filenames, nil
}