commit
b6f7dd9359
@ -1,2 +1,3 @@
|
|||||||
*.coverprofile
|
*.coverprofile
|
||||||
node_modules/
|
node_modules/
|
||||||
|
vendor
|
@ -1,3 +0,0 @@
|
|||||||
package altsrc
|
|
||||||
|
|
||||||
//go:generate python ../generate-flag-types altsrc -i ../flag-types.json -o flag_generated.go
|
|
@ -0,0 +1,179 @@
|
|||||||
|
//+build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var packages = []string{"cli", "altsrc"}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := cli.NewApp()
|
||||||
|
|
||||||
|
app.Name = "builder"
|
||||||
|
app.Usage = "Generates a new urfave/cli build!"
|
||||||
|
|
||||||
|
app.Commands = cli.Commands{
|
||||||
|
cli.Command{
|
||||||
|
Name: "vet",
|
||||||
|
Action: VetActionFunc,
|
||||||
|
},
|
||||||
|
cli.Command{
|
||||||
|
Name: "test",
|
||||||
|
Action: TestActionFunc,
|
||||||
|
},
|
||||||
|
cli.Command{
|
||||||
|
Name: "gfmrun",
|
||||||
|
Action: GfmrunActionFunc,
|
||||||
|
},
|
||||||
|
cli.Command{
|
||||||
|
Name: "toc",
|
||||||
|
Action: TocActionFunc,
|
||||||
|
},
|
||||||
|
cli.Command{
|
||||||
|
Name: "generate",
|
||||||
|
Action: GenActionFunc,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := app.Run(os.Args)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func VetActionFunc(_ *cli.Context) error {
|
||||||
|
return exec.Command("go", "vet").Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestActionFunc(c *cli.Context) error {
|
||||||
|
for _, pkg := range packages {
|
||||||
|
var packageName string
|
||||||
|
|
||||||
|
if pkg == "cli" {
|
||||||
|
packageName = "github.com/urfave/cli"
|
||||||
|
} else {
|
||||||
|
packageName = fmt.Sprintf("github.com/urfave/cli/%s", pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
coverProfile := fmt.Sprintf("--coverprofile=%s.coverprofile", pkg)
|
||||||
|
|
||||||
|
err := exec.Command(
|
||||||
|
"go", "test", "-v", coverProfile, packageName,
|
||||||
|
).Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return testCleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCleanup() error {
|
||||||
|
var out bytes.Buffer
|
||||||
|
|
||||||
|
for _, pkg := range packages {
|
||||||
|
file, err := os.Open(fmt.Sprintf("%s.coverprofile", pkg))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
out.Write(b)
|
||||||
|
err = file.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Remove(fmt.Sprintf("%s.coverprofile", pkg))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile, err := os.Create("coverage.txt")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = out.WriteTo(outFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = outFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GfmrunActionFunc(_ *cli.Context) error {
|
||||||
|
file, err := os.Open("README.md")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var counter int
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
if strings.Contains(scanner.Text(), "package main") {
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = scanner.Err()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return exec.Command("gfmrun", "-c", fmt.Sprint(counter), "-s", "README.md").Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TocActionFunc(_ *cli.Context) error {
|
||||||
|
err := exec.Command("node_modules/.bin/markdown-toc", "-i", "README.md").Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = exec.Command("git", "diff", "--exit-code").Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenActionFunc(_ *cli.Context) error {
|
||||||
|
err := exec.Command("go", "generate", "flag-gen/main.go").Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = exec.Command("go", "generate", "cli.go").Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = exec.Command("git", "diff", "--exit-code").Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
vendor
|
@ -0,0 +1,55 @@
|
|||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/shurcooL/httpfs/union"
|
||||||
|
"github.com/shurcooL/vfsgen"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// zeroModTimeFileSystem is an http.FileSystem wrapper.
|
||||||
|
// It exposes a filesystem exactly like Source, except
|
||||||
|
// all file modification times are changed to zero.
|
||||||
|
// See https://github.com/shurcooL/vfsgen/pull/40#issuecomment-355416103
|
||||||
|
type zeroModTimeFileSystem struct {
|
||||||
|
Source http.FileSystem
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs zeroModTimeFileSystem) Open(name string) (http.File, error) {
|
||||||
|
f, err := fs.Source.Open(name)
|
||||||
|
return file{f}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type file struct {
|
||||||
|
http.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f file) Stat() (os.FileInfo, error) {
|
||||||
|
fi, err := f.File.Stat()
|
||||||
|
return fileInfo{fi}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileInfo struct {
|
||||||
|
os.FileInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fi fileInfo) ModTime() time.Time { return time.Time{} }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fs := zeroModTimeFileSystem{
|
||||||
|
Source: union.New(map[string]http.FileSystem{
|
||||||
|
"/templates": http.Dir("templates"),
|
||||||
|
"/source": http.Dir("source"),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := vfsgen.Generate(fs, vfsgen.Options{})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
module github.com/urfave/cli/flag-generator
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
|
||||||
|
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
|
||||||
|
github.com/urfave/cli v1.21.0
|
||||||
|
)
|
@ -0,0 +1,9 @@
|
|||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=
|
||||||
|
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||||
|
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0=
|
||||||
|
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||||
|
github.com/urfave/cli v1.21.0 h1:wYSSj06510qPIzGSua9ZqsncMmWE3Zr55KBERygyrxE=
|
||||||
|
github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
@ -0,0 +1,113 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
//go:generate go run assets_generate.go
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
"io/ioutil"
|
||||||
|
"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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := cli.NewApp()
|
||||||
|
|
||||||
|
app.Name = "flag-generator"
|
||||||
|
app.Usage = "Generate flag type code!"
|
||||||
|
|
||||||
|
app.Action = ActionFunc
|
||||||
|
|
||||||
|
err := app.Run(os.Args)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ActionFunc(_ *cli.Context) error {
|
||||||
|
var info CliFlagInfo
|
||||||
|
var tpl *template.Template
|
||||||
|
|
||||||
|
inFile, err := assets.Open("/source/flag-types.json")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(inFile)
|
||||||
|
err = decoder.Decode(&info.Flags)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = inFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, packageName := range []string{"cli", "altsrc"} {
|
||||||
|
info.PackageName = packageName
|
||||||
|
|
||||||
|
bytes, err := ReadTemplate(packageName)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tpl = template.Must(template.New("").Parse(string(bytes)))
|
||||||
|
|
||||||
|
var outFile *os.File
|
||||||
|
|
||||||
|
if packageName == "cli" {
|
||||||
|
outFile, err = os.Create("flag_generated.go")
|
||||||
|
} else {
|
||||||
|
outFile, err = os.Create("altsrc/flag_generated.go")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tpl.Execute(outFile, info)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = outFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadTemplate(packageName string) ([]byte, error) {
|
||||||
|
templateFile, err := assets.Open(fmt.Sprintf("/templates/%s_flags_generated.gotpl", packageName))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
templateFileBytes, err := ioutil.ReadAll(templateFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return templateFileBytes, nil
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
// Code generated by fg; DO NOT EDIT.
|
||||||
|
|
||||||
|
package {{ .PackageName }}
|
||||||
|
|
||||||
|
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 }}
|
@ -0,0 +1,69 @@
|
|||||||
|
// 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 }}
|
@ -1,262 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""
|
|
||||||
The flag types that ship with the cli library have many things in common, and
|
|
||||||
so we can take advantage of the `go generate` command to create much of the
|
|
||||||
source code from a list of definitions. These definitions attempt to cover
|
|
||||||
the parts that vary between flag types, and should evolve as needed.
|
|
||||||
|
|
||||||
An example of the minimum definition needed is:
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "SomeType",
|
|
||||||
"type": "sometype",
|
|
||||||
"context_default": "nil"
|
|
||||||
}
|
|
||||||
|
|
||||||
In this example, the code generated for the `cli` package will include a type
|
|
||||||
named `SomeTypeFlag` that is expected to wrap a value of type `sometype`.
|
|
||||||
Fetching values by name via `*cli.Context` will default to a value of `nil`.
|
|
||||||
|
|
||||||
A more complete, albeit somewhat redundant, example showing all available
|
|
||||||
definition keys is:
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "VeryMuchType",
|
|
||||||
"type": "*VeryMuchType",
|
|
||||||
"value": true,
|
|
||||||
"dest": false,
|
|
||||||
"doctail": " which really only wraps a []float64, oh well!",
|
|
||||||
"context_type": "[]float64",
|
|
||||||
"context_default": "nil",
|
|
||||||
"parser": "parseVeryMuchType(f.Value.String())",
|
|
||||||
"parser_cast": "[]float64(parsed)"
|
|
||||||
}
|
|
||||||
|
|
||||||
The meaning of each field is as follows:
|
|
||||||
|
|
||||||
name (string) - The type "name", which will be suffixed with
|
|
||||||
`Flag` when generating the type definition
|
|
||||||
for `cli` and the wrapper type for `altsrc`
|
|
||||||
type (string) - The type that the generated `Flag` type for `cli`
|
|
||||||
is expected to "contain" as its `.Value` member
|
|
||||||
value (bool) - Should the generated `cli` type have a `Value`
|
|
||||||
member?
|
|
||||||
dest (bool) - Should the generated `cli` type support a
|
|
||||||
destination pointer?
|
|
||||||
doctail (string) - Additional docs for the `cli` flag type comment
|
|
||||||
context_type (string) - The literal type used in the `*cli.Context`
|
|
||||||
reader func signature
|
|
||||||
context_default (string) - The literal value used as the default by the
|
|
||||||
`*cli.Context` reader funcs when no value is
|
|
||||||
present
|
|
||||||
parser (string) - Literal code used to parse the flag `f`,
|
|
||||||
expected to have a return signature of
|
|
||||||
(value, error)
|
|
||||||
parser_cast (string) - Literal code used to cast the `parsed` value
|
|
||||||
returned from the `parser` code
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import print_function, unicode_literals
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
|
|
||||||
class _FancyFormatter(argparse.ArgumentDefaultsHelpFormatter,
|
|
||||||
argparse.RawDescriptionHelpFormatter):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def main(sysargs=sys.argv[:]):
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description='Generate flag type code!',
|
|
||||||
formatter_class=_FancyFormatter)
|
|
||||||
parser.add_argument(
|
|
||||||
'package',
|
|
||||||
type=str, default='cli', choices=_WRITEFUNCS.keys(),
|
|
||||||
help='Package for which flag types will be generated'
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
'-i', '--in-json',
|
|
||||||
type=argparse.FileType('r'),
|
|
||||||
default=sys.stdin,
|
|
||||||
help='Input JSON file which defines each type to be generated'
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
'-o', '--out-go',
|
|
||||||
type=argparse.FileType('w'),
|
|
||||||
default=sys.stdout,
|
|
||||||
help='Output file/stream to which generated source will be written'
|
|
||||||
)
|
|
||||||
parser.epilog = __doc__
|
|
||||||
|
|
||||||
args = parser.parse_args(sysargs[1:])
|
|
||||||
_generate_flag_types(_WRITEFUNCS[args.package], args.out_go, args.in_json)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def _generate_flag_types(writefunc, output_go, input_json):
|
|
||||||
types = json.load(input_json)
|
|
||||||
|
|
||||||
tmp = tempfile.NamedTemporaryFile(suffix='.go', delete=False)
|
|
||||||
writefunc(tmp, types)
|
|
||||||
tmp.close()
|
|
||||||
|
|
||||||
new_content = subprocess.check_output(
|
|
||||||
['goimports', tmp.name]
|
|
||||||
).decode('utf-8')
|
|
||||||
|
|
||||||
print(new_content, file=output_go, end='')
|
|
||||||
output_go.flush()
|
|
||||||
os.remove(tmp.name)
|
|
||||||
|
|
||||||
|
|
||||||
def _set_typedef_defaults(typedef):
|
|
||||||
typedef.setdefault('doctail', '')
|
|
||||||
typedef.setdefault('context_type', typedef['type'])
|
|
||||||
typedef.setdefault('dest', True)
|
|
||||||
typedef.setdefault('value', True)
|
|
||||||
typedef.setdefault('parser', 'f.Value, error(nil)')
|
|
||||||
typedef.setdefault('parser_cast', 'parsed')
|
|
||||||
|
|
||||||
|
|
||||||
def _write_cli_flag_types(outfile, types):
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
package cli
|
|
||||||
|
|
||||||
// WARNING: This file is generated!
|
|
||||||
|
|
||||||
""")
|
|
||||||
|
|
||||||
for typedef in types:
|
|
||||||
_set_typedef_defaults(typedef)
|
|
||||||
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
// {name}Flag is a flag with type {type}{doctail}
|
|
||||||
type {name}Flag struct {{
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
FilePath string
|
|
||||||
Required bool
|
|
||||||
Hidden bool
|
|
||||||
""".format(**typedef))
|
|
||||||
|
|
||||||
if typedef['value']:
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
Value {type}
|
|
||||||
""".format(**typedef))
|
|
||||||
|
|
||||||
if typedef['dest']:
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
Destination *{type}
|
|
||||||
""".format(**typedef))
|
|
||||||
|
|
||||||
_fwrite(outfile, "\n}\n\n")
|
|
||||||
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f {name}Flag) String() string {{
|
|
||||||
return FlagStringer(f)
|
|
||||||
}}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f {name}Flag) GetName() string {{
|
|
||||||
return f.Name
|
|
||||||
}}
|
|
||||||
|
|
||||||
// IsRequired returns the whether or not the flag is required
|
|
||||||
func (f {name}Flag) IsRequired() bool {{
|
|
||||||
return f.Required
|
|
||||||
}}
|
|
||||||
|
|
||||||
// {name} looks up the value of a local {name}Flag, returns
|
|
||||||
// {context_default} if not found
|
|
||||||
func (c *Context) {name}(name string) {context_type} {{
|
|
||||||
return lookup{name}(name, c.flagSet)
|
|
||||||
}}
|
|
||||||
|
|
||||||
// Global{name} looks up the value of a global {name}Flag, returns
|
|
||||||
// {context_default} if not found
|
|
||||||
func (c *Context) Global{name}(name string) {context_type} {{
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {{
|
|
||||||
return lookup{name}(name, fs)
|
|
||||||
}}
|
|
||||||
return {context_default}
|
|
||||||
}}
|
|
||||||
|
|
||||||
func lookup{name}(name string, set *flag.FlagSet) {context_type} {{
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {{
|
|
||||||
parsed, err := {parser}
|
|
||||||
if err != nil {{
|
|
||||||
return {context_default}
|
|
||||||
}}
|
|
||||||
return {parser_cast}
|
|
||||||
}}
|
|
||||||
return {context_default}
|
|
||||||
}}
|
|
||||||
""".format(**typedef))
|
|
||||||
|
|
||||||
|
|
||||||
def _write_altsrc_flag_types(outfile, types):
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
package altsrc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"gopkg.in/urfave/cli.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WARNING: This file is generated!
|
|
||||||
|
|
||||||
""")
|
|
||||||
|
|
||||||
for typedef in types:
|
|
||||||
_set_typedef_defaults(typedef)
|
|
||||||
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
// {name}Flag is the flag type that wraps cli.{name}Flag to allow
|
|
||||||
// for other values to be specified
|
|
||||||
type {name}Flag struct {{
|
|
||||||
cli.{name}Flag
|
|
||||||
set *flag.FlagSet
|
|
||||||
}}
|
|
||||||
|
|
||||||
// New{name}Flag creates a new {name}Flag
|
|
||||||
func New{name}Flag(fl cli.{name}Flag) *{name}Flag {{
|
|
||||||
return &{name}Flag{{{name}Flag: fl, set: nil}}
|
|
||||||
}}
|
|
||||||
|
|
||||||
// Apply saves the flagSet for later usage calls, then calls the
|
|
||||||
// wrapped {name}Flag.Apply
|
|
||||||
func (f *{name}Flag) Apply(set *flag.FlagSet) {{
|
|
||||||
f.set = set
|
|
||||||
f.{name}Flag.Apply(set)
|
|
||||||
}}
|
|
||||||
|
|
||||||
// ApplyWithError saves the flagSet for later usage calls, then calls the
|
|
||||||
// wrapped {name}Flag.ApplyWithError
|
|
||||||
func (f *{name}Flag) ApplyWithError(set *flag.FlagSet) error {{
|
|
||||||
f.set = set
|
|
||||||
return f.{name}Flag.ApplyWithError(set)
|
|
||||||
}}
|
|
||||||
""".format(**typedef))
|
|
||||||
|
|
||||||
|
|
||||||
def _fwrite(outfile, text):
|
|
||||||
print(textwrap.dedent(text), end='', file=outfile)
|
|
||||||
|
|
||||||
|
|
||||||
_WRITEFUNCS = {
|
|
||||||
'cli': _write_cli_flag_types,
|
|
||||||
'altsrc': _write_altsrc_flag_types
|
|
||||||
}
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
Loading…
Reference in new issue