2019-03-06 15:04:18 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2019-08-03 16:18:48 +00:00
|
|
|
"encoding/json"
|
2019-03-06 15:04:18 +00:00
|
|
|
"github.com/urfave/cli"
|
|
|
|
"log"
|
|
|
|
"os"
|
2019-08-03 16:18:48 +00:00
|
|
|
"text/template"
|
2019-03-06 15:04:18 +00:00
|
|
|
)
|
|
|
|
|
2019-08-03 16:18:48 +00:00
|
|
|
type CliFlagInfo struct {
|
|
|
|
PackageName string
|
|
|
|
Flags []FlagType
|
|
|
|
}
|
|
|
|
|
|
|
|
type FlagType struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Type string `json:"type"`
|
|
|
|
Value bool `json:"value"`
|
|
|
|
Destination bool `json:"dest"`
|
|
|
|
Doctail string `json:"doctail"`
|
|
|
|
ContextDefault string `json:"context_default"`
|
|
|
|
ContextType string `json:"context_type"`
|
|
|
|
Parser string `json:"parser"`
|
|
|
|
ParserCast string `json:"parser_cast"`
|
|
|
|
}
|
|
|
|
|
|
|
|
var cliFlagTemplate = `// Code generated by fg; DO NOT EDIT.
|
|
|
|
|
|
|
|
package {{ .PackageName }}
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
{{ range $i, $flag := .Flags }}
|
|
|
|
// {{ $flag.Name }}Flag is a flag with type {{ $flag.Type }}{{ $flag.Doctail }}
|
|
|
|
type {{ $flag.Name }}Flag struct {
|
|
|
|
Name string
|
|
|
|
Usage string
|
|
|
|
EnvVar string
|
|
|
|
FilePath string
|
|
|
|
Required bool
|
|
|
|
Hidden bool
|
|
|
|
{{- if eq $flag.Value true }}
|
|
|
|
Value {{ $flag.Type }}
|
|
|
|
{{- end }}
|
|
|
|
{{- if eq $flag.Destination true }}
|
|
|
|
Destination *{{ $flag.Type }}
|
|
|
|
{{- end }}
|
|
|
|
}
|
|
|
|
|
|
|
|
// String returns a readable representation of this value
|
|
|
|
// (for usage defaults)
|
|
|
|
func (f {{ $flag.Name }}Flag) String() string {
|
|
|
|
return FlagStringer(f)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetName returns the name of the flag
|
|
|
|
func (f {{ $flag.Name }}Flag) GetName() string {
|
|
|
|
return f.Name
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsRequired returns whether or not the flag is required
|
|
|
|
func (f {{ $flag.Name }}Flag) IsRequired() bool {
|
|
|
|
return f.Required
|
|
|
|
}
|
|
|
|
|
|
|
|
// {{ $flag.Name }} looks up the value of a local {{ $flag.Name }}Flag, returns
|
|
|
|
// {{ $flag.ContextDefault }} if not found
|
|
|
|
func (c *Context) {{ $flag.Name }}(name string) {{ if ne .ContextType "" }} {{ $flag.ContextType }} {{ else }} {{ $flag.Type }} {{- end }} {
|
|
|
|
return lookup{{ $flag.Name }}(name, c.flagSet)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Global{{ $flag.Name }} looks up the value of a global {{ $flag.Name }}Flag, returns
|
|
|
|
// {{ $flag.ContextDefault }} if not found
|
|
|
|
func (c *Context) Global{{ $flag.Name }}(name string) {{ if ne .ContextType "" }} {{ $flag.ContextType }} {{ else }} {{ $flag.Type }} {{- end }} {
|
|
|
|
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
|
|
return lookup{{ $flag.Name }}(name, fs)
|
|
|
|
}
|
|
|
|
return {{ $flag.ContextDefault }}
|
|
|
|
}
|
|
|
|
|
|
|
|
func lookup{{ $flag.Name }}(name string, set *flag.FlagSet) {{ if ne .ContextType "" }} {{ $flag.ContextType }} {{ else }} {{ $flag.Type }} {{- end }} {
|
|
|
|
f := set.Lookup(name)
|
|
|
|
if f != nil {
|
|
|
|
{{ if ne .Parser "" }}parsed, err := {{ $flag.Parser }}{{ else }}parsed, err := f.Value, error(nil){{ end }}
|
|
|
|
if err != nil {
|
|
|
|
return {{ $flag.ContextDefault }}
|
|
|
|
}
|
|
|
|
{{ if ne .ParserCast "" }}return {{ $flag.ParserCast }}{{ else }}return parsed{{ end }}
|
|
|
|
}
|
|
|
|
return {{ $flag.ContextDefault }}
|
|
|
|
}
|
|
|
|
{{- end }}`
|
|
|
|
|
2019-03-06 15:04:18 +00:00
|
|
|
func main() {
|
2019-08-03 16:18:48 +00:00
|
|
|
var packageName, inputPath, outputPath string
|
|
|
|
|
2019-03-06 15:04:18 +00:00
|
|
|
app := cli.NewApp()
|
|
|
|
|
2019-08-03 16:18:48 +00:00
|
|
|
app.Name = "fg"
|
2019-03-06 15:04:18 +00:00
|
|
|
app.Usage = "Generate flag type code!"
|
2019-08-03 16:18:48 +00:00
|
|
|
app.Version = "v0.1.0"
|
2019-03-06 15:04:18 +00:00
|
|
|
|
|
|
|
app.Flags = []cli.Flag{
|
|
|
|
cli.StringFlag{
|
2019-08-03 16:18:48 +00:00
|
|
|
Name: "package, p",
|
|
|
|
Value: "cli",
|
|
|
|
Usage: "`PACKAGE` for which the flag types will be generated",
|
|
|
|
Destination: &packageName,
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "input, i",
|
|
|
|
Usage: "path to the `INPUT JSON FILE` which defines each type to be generated",
|
|
|
|
Destination: &inputPath,
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "output, o",
|
|
|
|
Usage: "path to the `OUTPUT GO FILE` which will contain the flag types",
|
|
|
|
Destination: &outputPath,
|
2019-03-06 15:04:18 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-08-03 16:18:48 +00:00
|
|
|
app.Action = func(c *cli.Context) error {
|
|
|
|
var info CliFlagInfo
|
|
|
|
info.PackageName = packageName
|
|
|
|
|
|
|
|
inFile, err := os.Open(inputPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
defer inFile.Close()
|
|
|
|
|
|
|
|
decoder := json.NewDecoder(inFile)
|
|
|
|
|
|
|
|
err = decoder.Decode(&info.Flags)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
tpl := template.Must(template.New("").Parse(cliFlagTemplate))
|
|
|
|
|
|
|
|
outFile, err := os.Create(outputPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
defer outFile.Close()
|
|
|
|
|
|
|
|
err = tpl.Execute(outFile, info)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-03-06 15:04:18 +00:00
|
|
|
err := app.Run(os.Args)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|