-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
138 lines (125 loc) · 3.1 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
// Copyright (C) 2015 A.Newman
//
package main
import (
"flag"
"fmt"
"os"
"os/user"
"path/filepath"
"strings"
"time"
)
func main() {
genScan := flag.Bool("fmt-scanner", false, "Generate a fmt.Scanner Scan() method.")
genDatabaseSQL := flag.Bool("sql-scanner", false, "Generate a sql.Scanner Scan() method.")
genEncodingJSON := flag.Bool("json", false, "Output JSON marshal/unmarshal methods.")
genEncodingXML := flag.Bool("xml", false, "Output XML marshal/unmarshal methods.")
flag.Usage = usage
flag.Parse()
var generator CodeGenerator
// Check if more than one option was supplied and
// set our generator while we're at it. If more
// than generator was requested we'll create more
// than one but then exit with an error.
//
ngen := 0
if *genScan {
ngen++
generator = NewGenerator("scan", scanTemplate, []string{"fmt"})
}
if *genDatabaseSQL {
ngen++
generator = NewGenerator("sql", sqlTemplate, []string{"fmt"})
}
if *genEncodingJSON {
ngen++
generator = NewGenerator("json", jsonTemplate, []string{"encoding/json"})
}
if *genEncodingXML {
ngen++
generator = NewGenerator("xml", xmlTemplate, []string{"encoding/xml"})
}
switch {
case ngen == 0:
generator = NewGenerator("std", stdTemplate, []string{})
case ngen > 1:
usage()
os.Exit(1)
}
processAll := func(filenames []string) error {
for _, filename := range filenames {
if err := process(filename, generator); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
return err
}
}
return nil
}
var err error
if flag.NArg() > 0 {
err = processAll(flag.Args())
} else {
var filenames []string
if filenames, err = filepath.Glob("*.enum"); err == nil {
err = processAll(filenames)
}
}
if err != nil {
fmt.Fprintln(os.Stderr, "enums:", err)
os.Exit(1)
}
}
func process(filename string, generator CodeGenerator) error {
e, err := parse(filename, generator)
if err == nil {
err = gen(e, filename, generator)
}
return err
}
func parse(filename string, generator CodeGenerator) (Enums, error) {
var e Enums
e.Filename = filename
e.Time = time.Now().Format(time.ANSIC)
e.User = "unknown"
u, err := user.Current()
if err == nil {
e.User = u.Username
}
if file, err := os.Open(filename); err != nil {
return Enums{}, err
} else if err = ParseToEnd(file, &e); err != nil {
return Enums{}, err
}
e.Imports = append(e.Imports, generator.Imports()...)
return e, nil
}
func gen(e Enums, filename string, generator CodeGenerator) error {
path := strings.TrimSuffix(filename, filepath.Ext(filename)) + ".go"
if file, err := os.Create(path); err == nil {
defer func() {
if err != nil {
os.Remove(path)
}
}()
if err = generator.Generate(e, file); err != nil {
_ = file.Close()
return err
}
err = file.Close()
return err
} else {
return err
}
}
func usage() {
fmt.Fprintln(os.Stderr, `usage: enums [option] [filename...]
A single option may be supplied to control code generation.
Option may be one of:
`)
flag.PrintDefaults()
fmt.Fprintln(os.Stderr, `
In all cases the basic implementation of an enumerated type
is generated along with a String() method for textual output.
`)
}