You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
5.1 KiB

package main
import (
"encoding/json"
"github.com/urfave/cli"
"log"
"os"
"text/template"
)
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 flagTemplate = `// Code generated by fg; DO NOT EDIT.
package {{ .PackageName }}
{{ if eq .PackageName "cli" }}
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 }}
{{ else }}
import (
"flag"
"github.com/urfave/cli"
)
{{ range $i, $flag := .Flags }}
// {{ $flag.Name }}Flag is the flag type that wraps cli.{{ $flag.Name }}Flag to allow
// for other values to be specified
type {{ $flag.Name }}Flag struct {
cli.{{ $flag.Name }}Flag
set *flag.FlagSet
}
// New{{ $flag.Name }}Flag creates a new {{ $flag.Name }}Flag
func New{{ $flag.Name }}Flag(fl cli.{{ $flag.Name }}Flag) *{{ $flag.Name }}Flag {
return &{{ $flag.Name }}Flag{ {{ $flag.Name }}Flag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped {{ $flag.Name }}Flag.Apply
func (f *{{ $flag.Name }}Flag) Apply(set *flag.FlagSet) {
f.set = set
f.{{ $flag.Name }}Flag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped {{ $flag.Name }}Flag.ApplyWithError
func (f *{{ $flag.Name }}Flag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.{{ $flag.Name }}Flag.ApplyWithError(set)
}
{{- end }}
{{- end }}
`
func main() {
var packageName, inputPath, outputPath string
app := cli.NewApp()
app.Name = "fg"
app.Usage = "Generate flag type code!"
app.Version = "v0.1.0"
app.Flags = []cli.Flag{
cli.StringFlag{
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,
},
}
app.Action = func(c *cli.Context) error {
var info CliFlagInfo
var tpl *template.Template
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(flagTemplate))
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
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}