Merge pull request #836 from urfave/flag-type-generation-golang

Flag Generation in the CLI
main
Ajitem Sahasrabuddhe 5 years ago committed by GitHub
commit b6f7dd9359
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

1
.gitignore vendored

@ -1,2 +1,3 @@
*.coverprofile
node_modules/
vendor

@ -2,26 +2,33 @@ language: go
sudo: false
dist: trusty
osx_image: xcode8.3
go: 1.11.x
go:
- 1.11.x
- 1.12.x
os:
- linux
- osx
- linux
- osx
cache:
directories:
- node_modules
- node_modules
before_script:
- go get github.com/urfave/gfmrun/... || true
- go get golang.org/x/tools/cmd/goimports
- if [ ! -f node_modules/.bin/markdown-toc ] ; then
npm install markdown-toc ;
fi
- go get github.com/shurcooL/vfsgen || true
- go get github.com/shurcooL/httpfs/union || true
- go get github.com/urfave/gfmrun/... || true
- go get golang.org/x/tools/cmd/goimports
- if [ ! -f node_modules/.bin/markdown-toc ] ; then
npm install markdown-toc ;
fi
script:
- ./runtests gen
- ./runtests vet
- ./runtests test
- ./runtests gfmrun
- ./runtests toc
- go run build.go generate
- go run build.go vet
- go run build.go test
- go run build.go gfmrun
- go run build.go toc
after_success:
- bash <(curl -s https://codecov.io/bash)

@ -3,6 +3,7 @@ cli
[![Build Status](https://travis-ci.org/urfave/cli.svg?branch=master)](https://travis-ci.org/urfave/cli)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/rtgk5xufi932pb2v?svg=true)](https://ci.appveyor.com/project/urfave/cli)
[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://godoc.org/github.com/urfave/cli)
[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli)
[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli)
@ -888,7 +889,9 @@ Calling `App.Run` will not automatically call `os.Exit`, which means that by
default the exit code will "fall through" to being `0`. An explicit exit code
may be set by returning a non-nil error that fulfills `cli.ExitCoder`, *or* a
`cli.MultiError` that includes an error that fulfills `cli.ExitCoder`, e.g.:
<!-- {
"error": "Ginger croutons are not in the soup"
} -->
``` go
package main

@ -1,3 +0,0 @@
package altsrc
//go:generate python ../generate-flag-types altsrc -i ../flag-types.json -o flag_generated.go

@ -1,13 +1,12 @@
// Code generated by fg; DO NOT EDIT.
package altsrc
import (
"flag"
"github.com/urfave/cli"
)
// WARNING: This file is generated!
// BoolFlag is the flag type that wraps cli.BoolFlag to allow
// for other values to be specified
type BoolFlag struct {
@ -17,18 +16,18 @@ type BoolFlag struct {
// NewBoolFlag creates a new BoolFlag
func NewBoolFlag(fl cli.BoolFlag) *BoolFlag {
return &BoolFlag{BoolFlag: fl, set: nil}
return &BoolFlag{ BoolFlag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped BoolFlag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped BoolFlag.Apply
func (f *BoolFlag) Apply(set *flag.FlagSet) {
f.set = set
f.BoolFlag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped BoolFlag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped BoolFlag.ApplyWithError
func (f *BoolFlag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.BoolFlag.ApplyWithError(set)
@ -43,18 +42,18 @@ type BoolTFlag struct {
// NewBoolTFlag creates a new BoolTFlag
func NewBoolTFlag(fl cli.BoolTFlag) *BoolTFlag {
return &BoolTFlag{BoolTFlag: fl, set: nil}
return &BoolTFlag{ BoolTFlag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped BoolTFlag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped BoolTFlag.Apply
func (f *BoolTFlag) Apply(set *flag.FlagSet) {
f.set = set
f.BoolTFlag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped BoolTFlag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped BoolTFlag.ApplyWithError
func (f *BoolTFlag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.BoolTFlag.ApplyWithError(set)
@ -69,18 +68,18 @@ type DurationFlag struct {
// NewDurationFlag creates a new DurationFlag
func NewDurationFlag(fl cli.DurationFlag) *DurationFlag {
return &DurationFlag{DurationFlag: fl, set: nil}
return &DurationFlag{ DurationFlag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped DurationFlag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped DurationFlag.Apply
func (f *DurationFlag) Apply(set *flag.FlagSet) {
f.set = set
f.DurationFlag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped DurationFlag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped DurationFlag.ApplyWithError
func (f *DurationFlag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.DurationFlag.ApplyWithError(set)
@ -95,18 +94,18 @@ type Float64Flag struct {
// NewFloat64Flag creates a new Float64Flag
func NewFloat64Flag(fl cli.Float64Flag) *Float64Flag {
return &Float64Flag{Float64Flag: fl, set: nil}
return &Float64Flag{ Float64Flag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped Float64Flag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped Float64Flag.Apply
func (f *Float64Flag) Apply(set *flag.FlagSet) {
f.set = set
f.Float64Flag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped Float64Flag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped Float64Flag.ApplyWithError
func (f *Float64Flag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.Float64Flag.ApplyWithError(set)
@ -121,18 +120,18 @@ type GenericFlag struct {
// NewGenericFlag creates a new GenericFlag
func NewGenericFlag(fl cli.GenericFlag) *GenericFlag {
return &GenericFlag{GenericFlag: fl, set: nil}
return &GenericFlag{ GenericFlag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped GenericFlag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped GenericFlag.Apply
func (f *GenericFlag) Apply(set *flag.FlagSet) {
f.set = set
f.GenericFlag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped GenericFlag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped GenericFlag.ApplyWithError
func (f *GenericFlag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.GenericFlag.ApplyWithError(set)
@ -147,18 +146,18 @@ type Int64Flag struct {
// NewInt64Flag creates a new Int64Flag
func NewInt64Flag(fl cli.Int64Flag) *Int64Flag {
return &Int64Flag{Int64Flag: fl, set: nil}
return &Int64Flag{ Int64Flag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped Int64Flag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped Int64Flag.Apply
func (f *Int64Flag) Apply(set *flag.FlagSet) {
f.set = set
f.Int64Flag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped Int64Flag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped Int64Flag.ApplyWithError
func (f *Int64Flag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.Int64Flag.ApplyWithError(set)
@ -173,18 +172,18 @@ type IntFlag struct {
// NewIntFlag creates a new IntFlag
func NewIntFlag(fl cli.IntFlag) *IntFlag {
return &IntFlag{IntFlag: fl, set: nil}
return &IntFlag{ IntFlag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped IntFlag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped IntFlag.Apply
func (f *IntFlag) Apply(set *flag.FlagSet) {
f.set = set
f.IntFlag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped IntFlag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped IntFlag.ApplyWithError
func (f *IntFlag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.IntFlag.ApplyWithError(set)
@ -199,18 +198,18 @@ type IntSliceFlag struct {
// NewIntSliceFlag creates a new IntSliceFlag
func NewIntSliceFlag(fl cli.IntSliceFlag) *IntSliceFlag {
return &IntSliceFlag{IntSliceFlag: fl, set: nil}
return &IntSliceFlag{ IntSliceFlag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped IntSliceFlag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped IntSliceFlag.Apply
func (f *IntSliceFlag) Apply(set *flag.FlagSet) {
f.set = set
f.IntSliceFlag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped IntSliceFlag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped IntSliceFlag.ApplyWithError
func (f *IntSliceFlag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.IntSliceFlag.ApplyWithError(set)
@ -225,18 +224,18 @@ type Int64SliceFlag struct {
// NewInt64SliceFlag creates a new Int64SliceFlag
func NewInt64SliceFlag(fl cli.Int64SliceFlag) *Int64SliceFlag {
return &Int64SliceFlag{Int64SliceFlag: fl, set: nil}
return &Int64SliceFlag{ Int64SliceFlag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped Int64SliceFlag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped Int64SliceFlag.Apply
func (f *Int64SliceFlag) Apply(set *flag.FlagSet) {
f.set = set
f.Int64SliceFlag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped Int64SliceFlag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped Int64SliceFlag.ApplyWithError
func (f *Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.Int64SliceFlag.ApplyWithError(set)
@ -251,18 +250,18 @@ type StringFlag struct {
// NewStringFlag creates a new StringFlag
func NewStringFlag(fl cli.StringFlag) *StringFlag {
return &StringFlag{StringFlag: fl, set: nil}
return &StringFlag{ StringFlag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped StringFlag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped StringFlag.Apply
func (f *StringFlag) Apply(set *flag.FlagSet) {
f.set = set
f.StringFlag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped StringFlag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped StringFlag.ApplyWithError
func (f *StringFlag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.StringFlag.ApplyWithError(set)
@ -277,18 +276,18 @@ type StringSliceFlag struct {
// NewStringSliceFlag creates a new StringSliceFlag
func NewStringSliceFlag(fl cli.StringSliceFlag) *StringSliceFlag {
return &StringSliceFlag{StringSliceFlag: fl, set: nil}
return &StringSliceFlag{ StringSliceFlag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped StringSliceFlag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped StringSliceFlag.Apply
func (f *StringSliceFlag) Apply(set *flag.FlagSet) {
f.set = set
f.StringSliceFlag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped StringSliceFlag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped StringSliceFlag.ApplyWithError
func (f *StringSliceFlag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.StringSliceFlag.ApplyWithError(set)
@ -303,18 +302,18 @@ type Uint64Flag struct {
// NewUint64Flag creates a new Uint64Flag
func NewUint64Flag(fl cli.Uint64Flag) *Uint64Flag {
return &Uint64Flag{Uint64Flag: fl, set: nil}
return &Uint64Flag{ Uint64Flag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped Uint64Flag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped Uint64Flag.Apply
func (f *Uint64Flag) Apply(set *flag.FlagSet) {
f.set = set
f.Uint64Flag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped Uint64Flag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped Uint64Flag.ApplyWithError
func (f *Uint64Flag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.Uint64Flag.ApplyWithError(set)
@ -329,18 +328,18 @@ type UintFlag struct {
// NewUintFlag creates a new UintFlag
func NewUintFlag(fl cli.UintFlag) *UintFlag {
return &UintFlag{UintFlag: fl, set: nil}
return &UintFlag{ UintFlag: fl, set: nil }
}
// Apply saves the flagSet for later usage calls, then calls the
// wrapped UintFlag.Apply
// Apply saves the flagSet for later usage calls, then calls
// the wrapped UintFlag.Apply
func (f *UintFlag) Apply(set *flag.FlagSet) {
f.set = set
f.UintFlag.Apply(set)
}
// ApplyWithError saves the flagSet for later usage calls, then calls the
// wrapped UintFlag.ApplyWithError
// ApplyWithError saves the flagSet for later usage calls, then calls
// the wrapped UintFlag.ApplyWithError
func (f *UintFlag) ApplyWithError(set *flag.FlagSet) error {
f.set = set
return f.UintFlag.ApplyWithError(set)

@ -8,19 +8,19 @@ clone_folder: c:\gopath\src\github.com\urfave\cli
environment:
GOPATH: C:\gopath
GOVERSION: 1.8.x
PYTHON: C:\Python36-x64
PYTHON_VERSION: 3.6.x
PYTHON_ARCH: 64
GOVERSION: 1.11.x
install:
- set PATH=%GOPATH%\bin;C:\go\bin;%PATH%
- go version
- go env
- go get github.com/urfave/gfmrun/...
- go get -v -t ./...
- set PATH=%GOPATH%\bin;C:\go\bin;%PATH%
- go version
- go env
- go get github.com/shurcooL/vfsgen
- go get github.com/shurcooL/httpfs/union
- go get github.com/urfave/gfmrun/...
- go get -v -t ./...
build_script:
- python runtests vet
- python runtests test
- python runtests gfmrun
- go run build.go generate
- go run build.go vet
- go run build.go test
- go run build.go gfmrun

@ -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
}

@ -19,4 +19,4 @@
// }
package cli
//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go
//go:generate go run flag-gen/main.go flag-gen/assets_vfsdata.go

@ -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,214 @@
// Code generated by vfsgen; DO NOT EDIT.
package main
import (
"bytes"
"compress/gzip"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
pathpkg "path"
"time"
)
// assets statically implements the virtual filesystem provided to vfsgen.
var assets = func() http.FileSystem {
fs := vfsgen۰FS{
"/": &vfsgen۰DirInfo{
name: "/",
modTime: time.Time{},
},
"/source": &vfsgen۰DirInfo{
name: "source",
modTime: time.Time{},
},
"/source/flag-types.json": &vfsgen۰CompressedFileInfo{
name: "flag-types.json",
modTime: time.Time{},
uncompressedSize: 2559,
compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x94\xc1\x6e\x9c\x30\x10\x86\xef\x3c\xc5\xc8\xbd\x40\xb5\x82\x1c\x56\x7b\xd8\x63\x55\xb5\xda\x5b\xa5\x34\xbd\x24\x51\xe4\x80\x21\x56\x1d\x1b\xd9\x43\xd4\x28\xca\xbb\x57\xf6\x2e\xbb\x60\x0c\x62\x5b\x2d\xb9\xfe\x23\x98\xef\x9b\xb1\xe6\x36\x02\x78\x8b\x00\x00\x88\xa4\xcf\x8c\x6c\x81\x7c\x51\x4a\x90\xd5\x3e\xc3\xd7\xda\x65\x8f\x9d\xec\x85\x8a\xc6\x86\x25\x15\x86\x1d\xb2\x82\x19\x24\x5b\x40\xdd\xb4\x49\xae\x24\xb2\x3f\xf8\x50\xb0\x92\x36\xc2\x16\x89\xfb\xa0\xfd\x4b\x4d\xb5\x61\xda\xc6\x06\x75\xae\xe4\x4b\xfa\xc3\x26\xb6\x79\x5c\xa6\xbf\x6c\x8f\xf4\x1a\x35\x97\x55\x9c\x24\x24\x02\x78\x5f\x85\x51\x7f\xfe\x3f\x6b\xa1\x72\xa4\x5c\xd8\x8f\x01\x9f\x28\x02\x37\xae\x0c\x8f\xaf\xd0\xf2\x2f\xa9\xf5\xb5\xd1\x14\xb9\x92\xbe\x19\xf2\x67\x96\xfa\xc5\x56\xb1\xeb\x33\x69\x18\x1b\xc6\xe0\x09\xb1\x36\xdb\x2c\xab\x94\xa0\xb2\x4a\x95\xae\xb2\xfa\x77\x95\xd9\x0e\xd9\x27\x87\xdc\xf6\x49\x26\xd4\xaf\x86\xda\x8e\xb1\xf7\x83\xf9\xde\xdf\x84\xa2\xb8\x59\xfb\xda\x65\x3f\x9e\x25\x3c\x0f\xb6\xb7\x23\xd7\x7d\x00\xbb\x82\xcd\x7a\x14\xf8\x3b\x93\x4c\xf3\xdc\x07\xf6\xe2\x71\xe0\xee\xb3\x0c\x10\x4b\x2e\xfc\xe1\xb7\x2d\xb8\x44\xa6\x4b\x9a\xb3\xb7\xf7\x31\xb8\x9d\x0c\xcc\x92\xcb\x05\x26\xb9\x93\xa1\x39\x5e\x4d\x8e\x72\x27\x31\xc0\xfa\xa1\xa4\xbd\x4f\x1f\x72\xea\xfa\x59\xaa\xd8\x45\xc5\x94\xcb\xb5\xe0\x39\xf3\x85\x3e\xfb\x85\x4b\xbc\x8c\xdb\xfb\xce\xdc\x4e\xda\x47\xcd\xf8\x48\x91\x24\xfb\xc8\x2a\x33\xad\x95\x8e\x25\x17\x53\x52\x9b\xf5\xa8\x96\x57\xba\x98\xd8\xe9\xf1\x8e\xa9\x1d\x48\xce\x93\xdb\xef\xde\x17\x33\xbd\xf4\x5f\xdf\xe0\x1d\xb9\x23\x43\xe8\xe1\xab\x9b\x4b\x19\xde\x41\xa0\x76\x99\x25\xf4\x87\x12\xdc\x42\x87\xe5\xbc\x35\xdc\xf0\xd0\xcd\x6a\x16\x39\x5a\xb6\xf7\xd9\x57\xeb\x86\x0f\xcf\x56\xb3\xc0\xdd\x9a\x86\x0d\x1f\xae\xc6\xbf\x5c\xd1\x7d\xf4\x37\x00\x00\xff\xff\x66\x52\x85\x44\xff\x09\x00\x00"),
},
"/templates": &vfsgen۰DirInfo{
name: "templates",
modTime: time.Time{},
},
"/templates/altsrc_flags_generated.gotpl": &vfsgen۰CompressedFileInfo{
name: "altsrc_flags_generated.gotpl",
modTime: time.Time{},
uncompressedSize: 1044,
compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x92\x4f\x8b\xdb\x30\x10\xc5\xcf\xd6\xa7\x78\x84\xa5\xc4\x4b\xb0\xef\x29\x7b\x28\xdd\x2d\xf4\x92\x2d\xec\x42\xcf\x8a\x3c\xb2\x45\x15\xdb\x48\xe3\x84\x20\xfc\xdd\xcb\x38\x61\xfb\x4f\x29\xbd\xf4\x66\x69\xf4\xde\x9b\xdf\x8c\xeb\x1a\x1f\x87\x86\xd0\x52\x4f\x41\x33\x35\xd8\x9f\x61\xdb\xf7\x78\x7c\xc6\xee\xf9\x15\x4f\x8f\x9f\x5f\x2b\xa5\x46\x6d\xbe\xe9\x96\x90\x12\xaa\x2f\x97\xef\x9d\x3e\x10\xe6\x59\x29\x77\x18\x87\xc0\x58\xab\x62\x65\xbd\x6e\x57\xaa\x58\xb5\x8e\xbb\x69\x5f\x99\xe1\x50\x4f\xc1\xea\x23\xd5\xc6\xbb\x95\x2a\x55\x4a\x08\xba\x6f\x09\x77\x6e\x83\x3b\x79\x8e\xed\x03\xaa\x4f\x5e\xb7\x51\xcc\xea\x5a\x22\x96\x42\x75\x0d\x90\x1a\x5c\x04\x77\x84\x45\xc0\xe7\x91\xc0\x9d\x66\x9c\x82\x1e\x23\x8c\x77\x55\x56\xc4\x03\xb4\xf7\xc3\x49\x5c\xed\x10\x30\x70\x47\x01\x47\xed\x27\x8a\x52\xdc\x13\xe2\x48\xc6\x59\x47\x8d\x5a\x5c\xb3\x36\x91\xc3\x64\x18\x49\x15\xb7\x92\x54\x11\x89\x71\xbf\x5c\xcb\xf9\x85\x58\xcd\x4a\x62\x77\x74\xca\x7a\x9a\x40\x9a\x29\x42\xa3\xa7\x53\x36\x56\xd9\xa9\x37\xb7\xf4\x6b\xeb\x6f\x62\x97\xb8\xcf\x46\x26\x55\x04\xe2\x29\xf4\x78\x97\xab\xa7\x6c\x17\x5b\x58\xbf\x41\x24\xde\xa2\x77\x1e\xf3\x15\xeb\xc3\x38\xfa\x33\xa2\x3e\xd2\x8f\xbd\xbc\x10\x2f\x53\xf6\x9a\x29\x60\x8a\xf2\xbb\x18\xed\x7d\xdc\xc8\x93\xfe\xf2\x2d\x62\x11\xc8\xe6\x46\x6a\xb2\x99\xd5\xe2\x7e\xe1\x5f\xdb\x3c\x4d\x79\x69\x61\xfd\xc7\xdc\x4b\xe1\xb4\x95\xdc\x3f\x48\xdf\x72\xb8\x1d\x22\xfa\xf2\x67\xa6\xaf\x8e\xbb\xa7\x10\x86\xf0\x7f\xe1\xde\x62\xfe\x89\xf2\xed\x75\x0e\x97\x96\x6e\x7f\x87\xbe\x6e\xfa\x6f\xec\xbf\xb8\xca\x10\x52\x02\xf5\x0d\xe6\xf9\x7b\x00\x00\x00\xff\xff\x6d\x3d\x9e\xe0\x14\x04\x00\x00"),
},
"/templates/cli_flags_generated.gotpl": &vfsgen۰CompressedFileInfo{
name: "cli_flags_generated.gotpl",
modTime: time.Time{},
uncompressedSize: 2102,
compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x54\xc1\x52\xdb\x30\x10\x3d\xdb\x5f\xb1\xcd\x70\xb0\x99\x34\xb9\x97\xe1\x44\xa0\x65\xa6\x03\x4c\xa1\xdc\x15\x7b\xe5\x68\x10\x52\x90\xd6\x50\x26\x93\x7f\xef\xac\x24\x3b\x4e\x48\x21\x17\x7a\xd3\x6a\x9f\xde\x7b\x7a\x5a\x7b\x3a\x85\x33\x5b\x23\x34\x68\xd0\x09\xc2\x1a\xe6\xaf\x20\x9b\x13\x98\x5d\xc3\xd5\xf5\x1d\x9c\xcf\x2e\xef\x26\x79\xbe\x14\xd5\x83\x68\x10\x56\x2b\x98\xdc\xc4\xf5\x95\x78\x44\x58\xaf\xf3\x5c\x3d\x2e\xad\x23\x28\xf2\x6c\x24\xb5\x68\x46\x79\x36\xf2\xe4\x2a\x6b\x9e\x79\x49\xea\x11\x47\x79\x99\xaf\x56\xe0\x84\x69\x10\x8e\xd4\x18\x8e\x18\x08\xdf\x4e\x61\x72\xa1\x45\xe3\x99\x66\x3a\x65\xf2\xd0\x98\x24\x6a\xee\x81\xf2\x20\x20\xc0\x5f\x14\x2d\x80\x5e\x97\xb8\x01\xde\x71\xb5\x5e\xf7\xf5\xcc\x56\x24\x94\x66\xbe\x6d\xe0\x90\xd1\x93\x6b\x2b\x82\x55\x9e\xf1\x6e\x96\x79\x72\xca\x34\x79\xf6\xdb\x8b\x66\x50\x9e\x9b\xe7\x7b\xe1\x36\xf5\x85\xd2\x78\x23\x68\xd1\x6f\xfc\xc2\xa7\x56\x39\xac\xb3\xb9\xb5\x3a\xcf\x7e\xa8\xba\x46\x93\xa5\x6a\xb5\xfa\x0a\x4a\x02\x3e\x25\x03\xf7\x42\xb7\x08\xe4\xda\x90\x59\x16\xca\x6c\xf7\x1e\xf1\x18\x9a\xba\x5f\x0f\x29\x66\xe8\x49\x19\x41\xca\x9a\x0d\xd1\x60\x33\x3b\x7e\x97\x6f\x9d\x73\xc6\xb7\xc1\x3c\x38\xa4\xd6\x19\x8e\xd6\xa1\xa8\xc5\x5c\x23\x38\x5c\x3a\xf4\x68\x28\x2a\x58\x09\xb4\x50\x1e\x9e\xd9\x29\x9f\x2c\xa4\x75\xd0\x72\x46\x50\xa3\x14\xad\x26\x5f\xe6\xb2\x35\x15\x14\x72\x6f\xd0\x65\x12\x2b\x4a\x88\x91\x71\xe4\x51\x18\xb8\x1f\xbb\xe8\x0a\x59\x26\x73\xdf\x91\xc2\xf9\xce\x1d\x2d\x10\x0c\x6f\x04\x33\x18\xc6\xe0\x03\xc9\x44\xb1\x4f\x53\x06\x64\x92\xba\xf4\xdd\xf3\xf5\x6a\x2f\x0b\xa4\x05\x3a\xb0\x0e\x8c\xa5\x5e\x90\x27\xd0\x25\xec\x07\xe2\x1b\xd2\xa2\x04\x9e\x83\x2d\xf5\xae\x97\x1c\xec\x52\x80\xb6\xf6\xc1\x43\xbb\x0c\xca\x21\x76\xbe\xb7\x00\x6d\x2b\xa1\xf7\x2a\x8e\x3b\xef\x5b\x7c\x67\xd6\x10\xfe\xa1\x59\x7c\x24\x66\x56\x32\xdc\x48\xda\xd6\x74\x57\xa8\xe0\x38\xe1\xca\x37\xd4\x45\xc8\x3c\xe6\x17\xba\x7c\x1e\xa1\x23\x0e\xc3\x35\x1a\x0d\xbf\xbb\x61\x27\x6c\xa3\xf6\x5b\x1f\x66\xdf\xe9\xc6\x71\x90\x0c\xdf\xbb\x5d\xee\x35\x31\x86\x6a\xc2\x9b\xb7\x48\xfd\x8c\x68\x3b\x17\xfa\xe0\xf0\x9a\x00\xff\xcc\xf4\xf6\x1b\xfa\x5f\x19\x2a\x09\xd2\xf3\x9f\x34\xa6\x18\xcd\x5c\xc4\xc8\xba\x08\xcb\x13\xc6\x7c\x39\x05\xa3\xc2\x44\x1e\x14\xbc\xf4\x65\x9e\xad\xfb\x47\xfa\x77\x3e\xfc\x2e\x21\x95\x77\xe8\x52\x10\x63\xf0\x48\x70\x1c\xda\xc9\xe3\x67\x66\x23\x39\x17\x8f\x34\xf9\x19\x9c\x05\x27\x65\x8c\x6c\x98\xc6\xc6\xc0\x8d\x70\x1e\x5d\xd4\x5e\xf2\xba\x1e\x03\x3a\xc7\x34\xbd\x52\xc2\x0c\x5d\xec\x40\x65\xfc\xd9\x87\xda\xba\xc2\x28\x5d\x32\x36\xfd\xd5\x59\x9e\x81\x03\x03\x07\x64\x9c\xf1\x53\xbc\x71\x7a\x26\x3c\x45\xb7\xbb\x0c\x83\xfe\xd0\x69\x82\x45\xc3\x03\x53\x07\xbe\x73\x7f\xe2\x6f\x00\x00\x00\xff\xff\x9b\xde\x9c\x04\x36\x08\x00\x00"),
},
}
fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
fs["/source"].(os.FileInfo),
fs["/templates"].(os.FileInfo),
}
fs["/source"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
fs["/source/flag-types.json"].(os.FileInfo),
}
fs["/templates"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
fs["/templates/altsrc_flags_generated.gotpl"].(os.FileInfo),
fs["/templates/cli_flags_generated.gotpl"].(os.FileInfo),
}
return fs
}()
type vfsgen۰FS map[string]interface{}
func (fs vfsgen۰FS) Open(path string) (http.File, error) {
path = pathpkg.Clean("/" + path)
f, ok := fs[path]
if !ok {
return nil, &os.PathError{Op: "open", Path: path, Err: os.ErrNotExist}
}
switch f := f.(type) {
case *vfsgen۰CompressedFileInfo:
gr, err := gzip.NewReader(bytes.NewReader(f.compressedContent))
if err != nil {
// This should never happen because we generate the gzip bytes such that they are always valid.
panic("unexpected error reading own gzip compressed bytes: " + err.Error())
}
return &vfsgen۰CompressedFile{
vfsgen۰CompressedFileInfo: f,
gr: gr,
}, nil
case *vfsgen۰DirInfo:
return &vfsgen۰Dir{
vfsgen۰DirInfo: f,
}, nil
default:
// This should never happen because we generate only the above types.
panic(fmt.Sprintf("unexpected type %T", f))
}
}
// vfsgen۰CompressedFileInfo is a static definition of a gzip compressed file.
type vfsgen۰CompressedFileInfo struct {
name string
modTime time.Time
compressedContent []byte
uncompressedSize int64
}
func (f *vfsgen۰CompressedFileInfo) Readdir(count int) ([]os.FileInfo, error) {
return nil, fmt.Errorf("cannot Readdir from file %s", f.name)
}
func (f *vfsgen۰CompressedFileInfo) Stat() (os.FileInfo, error) { return f, nil }
func (f *vfsgen۰CompressedFileInfo) GzipBytes() []byte {
return f.compressedContent
}
func (f *vfsgen۰CompressedFileInfo) Name() string { return f.name }
func (f *vfsgen۰CompressedFileInfo) Size() int64 { return f.uncompressedSize }
func (f *vfsgen۰CompressedFileInfo) Mode() os.FileMode { return 0444 }
func (f *vfsgen۰CompressedFileInfo) ModTime() time.Time { return f.modTime }
func (f *vfsgen۰CompressedFileInfo) IsDir() bool { return false }
func (f *vfsgen۰CompressedFileInfo) Sys() interface{} { return nil }
// vfsgen۰CompressedFile is an opened compressedFile instance.
type vfsgen۰CompressedFile struct {
*vfsgen۰CompressedFileInfo
gr *gzip.Reader
grPos int64 // Actual gr uncompressed position.
seekPos int64 // Seek uncompressed position.
}
func (f *vfsgen۰CompressedFile) Read(p []byte) (n int, err error) {
if f.grPos > f.seekPos {
// Rewind to beginning.
err = f.gr.Reset(bytes.NewReader(f.compressedContent))
if err != nil {
return 0, err
}
f.grPos = 0
}
if f.grPos < f.seekPos {
// Fast-forward.
_, err = io.CopyN(ioutil.Discard, f.gr, f.seekPos-f.grPos)
if err != nil {
return 0, err
}
f.grPos = f.seekPos
}
n, err = f.gr.Read(p)
f.grPos += int64(n)
f.seekPos = f.grPos
return n, err
}
func (f *vfsgen۰CompressedFile) Seek(offset int64, whence int) (int64, error) {
switch whence {
case io.SeekStart:
f.seekPos = 0 + offset
case io.SeekCurrent:
f.seekPos += offset
case io.SeekEnd:
f.seekPos = f.uncompressedSize + offset
default:
panic(fmt.Errorf("invalid whence value: %v", whence))
}
return f.seekPos, nil
}
func (f *vfsgen۰CompressedFile) Close() error {
return f.gr.Close()
}
// vfsgen۰DirInfo is a static definition of a directory.
type vfsgen۰DirInfo struct {
name string
modTime time.Time
entries []os.FileInfo
}
func (d *vfsgen۰DirInfo) Read([]byte) (int, error) {
return 0, fmt.Errorf("cannot Read from directory %s", d.name)
}
func (d *vfsgen۰DirInfo) Close() error { return nil }
func (d *vfsgen۰DirInfo) Stat() (os.FileInfo, error) { return d, nil }
func (d *vfsgen۰DirInfo) Name() string { return d.name }
func (d *vfsgen۰DirInfo) Size() int64 { return 0 }
func (d *vfsgen۰DirInfo) Mode() os.FileMode { return 0755 | os.ModeDir }
func (d *vfsgen۰DirInfo) ModTime() time.Time { return d.modTime }
func (d *vfsgen۰DirInfo) IsDir() bool { return true }
func (d *vfsgen۰DirInfo) Sys() interface{} { return nil }
// vfsgen۰Dir is an opened dir instance.
type vfsgen۰Dir struct {
*vfsgen۰DirInfo
pos int // Position within entries for Seek and Readdir.
}
func (d *vfsgen۰Dir) Seek(offset int64, whence int) (int64, error) {
if offset == 0 && whence == io.SeekStart {
d.pos = 0
return 0, nil
}
return 0, fmt.Errorf("unsupported Seek in directory %s", d.name)
}
func (d *vfsgen۰Dir) Readdir(count int) ([]os.FileInfo, error) {
if d.pos >= len(d.entries) && count > 0 {
return nil, io.EOF
}
if count <= 0 || count > len(d.entries)-d.pos {
count = len(d.entries) - d.pos
}
e := d.entries[d.pos : d.pos+count]
d.pos += count
return e, nil
}

@ -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
}

@ -3,6 +3,7 @@
"name": "Bool",
"type": "bool",
"value": false,
"dest": true,
"context_default": "false",
"parser": "strconv.ParseBool(f.Value.String())"
},
@ -10,6 +11,7 @@
"name": "BoolT",
"type": "bool",
"value": false,
"dest": true,
"doctail": " that is true by default",
"context_default": "false",
"parser": "strconv.ParseBool(f.Value.String())"
@ -17,6 +19,8 @@
{
"name": "Duration",
"type": "time.Duration",
"value": true,
"dest": true,
"doctail": " (see https://golang.org/pkg/time/#ParseDuration)",
"context_default": "0",
"parser": "time.ParseDuration(f.Value.String())"
@ -24,12 +28,15 @@
{
"name": "Float64",
"type": "float64",
"value": true,
"dest": true,
"context_default": "0",
"parser": "strconv.ParseFloat(f.Value.String(), 64)"
},
{
"name": "Generic",
"type": "Generic",
"value": true,
"dest": false,
"context_default": "nil",
"context_type": "interface{}"
@ -37,12 +44,16 @@
{
"name": "Int64",
"type": "int64",
"value": true,
"dest": true,
"context_default": "0",
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)"
},
{
"name": "Int",
"type": "int",
"value": true,
"dest": true,
"context_default": "0",
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)",
"parser_cast": "int(parsed)"
@ -50,6 +61,7 @@
{
"name": "IntSlice",
"type": "*IntSlice",
"value": true,
"dest": false,
"context_default": "nil",
"context_type": "[]int",
@ -58,6 +70,7 @@
{
"name": "Int64Slice",
"type": "*Int64Slice",
"value": true,
"dest": false,
"context_default": "nil",
"context_type": "[]int64",
@ -66,12 +79,15 @@
{
"name": "String",
"type": "string",
"value": true,
"dest": true,
"context_default": "\"\"",
"parser": "f.Value.String(), error(nil)"
},
{
"name": "StringSlice",
"type": "*StringSlice",
"value": true,
"dest": false,
"context_default": "nil",
"context_type": "[]string",
@ -80,12 +96,16 @@
{
"name": "Uint64",
"type": "uint64",
"value": true,
"dest": true,
"context_default": "0",
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)"
},
{
"name": "Uint",
"type": "uint",
"value": true,
"dest": true,
"context_default": "0",
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)",
"parser_cast": "uint(parsed)"

@ -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,3 +1,5 @@
// Code generated by fg; DO NOT EDIT.
package cli
import (
@ -6,17 +8,15 @@ import (
"time"
)
// WARNING: This file is generated!
// BoolFlag is a flag with type bool
type BoolFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Destination *bool
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Destination *bool
}
// String returns a readable representation of this value
@ -30,7 +30,7 @@ func (f BoolFlag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f BoolFlag) IsRequired() bool {
return f.Required
}
@ -64,13 +64,13 @@ func lookupBool(name string, set *flag.FlagSet) bool {
// BoolTFlag is a flag with type bool that is true by default
type BoolTFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Destination *bool
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Destination *bool
}
// String returns a readable representation of this value
@ -84,7 +84,7 @@ func (f BoolTFlag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f BoolTFlag) IsRequired() bool {
return f.Required
}
@ -118,14 +118,14 @@ func lookupBoolT(name string, set *flag.FlagSet) bool {
// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration)
type DurationFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value time.Duration
Destination *time.Duration
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value time.Duration
Destination *time.Duration
}
// String returns a readable representation of this value
@ -139,7 +139,7 @@ func (f DurationFlag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f DurationFlag) IsRequired() bool {
return f.Required
}
@ -173,14 +173,14 @@ func lookupDuration(name string, set *flag.FlagSet) time.Duration {
// Float64Flag is a flag with type float64
type Float64Flag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value float64
Destination *float64
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value float64
Destination *float64
}
// String returns a readable representation of this value
@ -194,7 +194,7 @@ func (f Float64Flag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f Float64Flag) IsRequired() bool {
return f.Required
}
@ -228,13 +228,13 @@ func lookupFloat64(name string, set *flag.FlagSet) float64 {
// GenericFlag is a flag with type Generic
type GenericFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value Generic
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value Generic
}
// String returns a readable representation of this value
@ -248,7 +248,7 @@ func (f GenericFlag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f GenericFlag) IsRequired() bool {
return f.Required
}
@ -282,14 +282,14 @@ func lookupGeneric(name string, set *flag.FlagSet) interface{} {
// Int64Flag is a flag with type int64
type Int64Flag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value int64
Destination *int64
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value int64
Destination *int64
}
// String returns a readable representation of this value
@ -303,7 +303,7 @@ func (f Int64Flag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f Int64Flag) IsRequired() bool {
return f.Required
}
@ -337,14 +337,14 @@ func lookupInt64(name string, set *flag.FlagSet) int64 {
// IntFlag is a flag with type int
type IntFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value int
Destination *int
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value int
Destination *int
}
// String returns a readable representation of this value
@ -358,7 +358,7 @@ func (f IntFlag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f IntFlag) IsRequired() bool {
return f.Required
}
@ -392,13 +392,13 @@ func lookupInt(name string, set *flag.FlagSet) int {
// IntSliceFlag is a flag with type *IntSlice
type IntSliceFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value *IntSlice
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value *IntSlice
}
// String returns a readable representation of this value
@ -412,7 +412,7 @@ func (f IntSliceFlag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f IntSliceFlag) IsRequired() bool {
return f.Required
}
@ -446,13 +446,13 @@ func lookupIntSlice(name string, set *flag.FlagSet) []int {
// Int64SliceFlag is a flag with type *Int64Slice
type Int64SliceFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value *Int64Slice
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value *Int64Slice
}
// String returns a readable representation of this value
@ -466,7 +466,7 @@ func (f Int64SliceFlag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f Int64SliceFlag) IsRequired() bool {
return f.Required
}
@ -500,14 +500,14 @@ func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
// StringFlag is a flag with type string
type StringFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value string
Destination *string
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value string
Destination *string
}
// String returns a readable representation of this value
@ -521,7 +521,7 @@ func (f StringFlag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f StringFlag) IsRequired() bool {
return f.Required
}
@ -555,13 +555,13 @@ func lookupString(name string, set *flag.FlagSet) string {
// StringSliceFlag is a flag with type *StringSlice
type StringSliceFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value *StringSlice
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value *StringSlice
}
// String returns a readable representation of this value
@ -575,7 +575,7 @@ func (f StringSliceFlag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f StringSliceFlag) IsRequired() bool {
return f.Required
}
@ -609,14 +609,14 @@ func lookupStringSlice(name string, set *flag.FlagSet) []string {
// Uint64Flag is a flag with type uint64
type Uint64Flag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value uint64
Destination *uint64
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value uint64
Destination *uint64
}
// String returns a readable representation of this value
@ -630,7 +630,7 @@ func (f Uint64Flag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f Uint64Flag) IsRequired() bool {
return f.Required
}
@ -664,14 +664,14 @@ func lookupUint64(name string, set *flag.FlagSet) uint64 {
// UintFlag is a flag with type uint
type UintFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value uint
Destination *uint
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value uint
Destination *uint
}
// String returns a readable representation of this value
@ -685,7 +685,7 @@ func (f UintFlag) GetName() string {
return f.Name
}
// IsRequired returns the whether or not the flag is required
// IsRequired returns whether or not the flag is required
func (f UintFlag) IsRequired() bool {
return f.Required
}

@ -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())

@ -4,5 +4,7 @@ go 1.12
require (
github.com/BurntSushi/toml v0.3.1
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd // indirect
gopkg.in/yaml.v2 v2.2.2
)

@ -1,5 +1,9 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
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=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=

@ -34,10 +34,6 @@ def main(sysargs=sys.argv[:]):
def _test():
if check_output('go version'.split()).split()[2] < 'go1.2':
_run('go test -v .')
return
coverprofiles = []
for subpackage in ['', 'altsrc']:
coverprofile = 'cli.coverprofile'
@ -57,10 +53,6 @@ def _test():
def _gfmrun():
go_version = check_output('go version'.split()).split()[2]
if go_version < 'go1.3':
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
return
_run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md'])
@ -74,11 +66,6 @@ def _toc():
def _gen():
go_version = check_output('go version'.split()).split()[2]
if go_version < 'go1.5':
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
return
_run('go generate ./...')
_run('git diff --exit-code')

Loading…
Cancel
Save