diff --git a/.travis.yml b/.travis.yml index 08c0563..d12ddbb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,15 +23,11 @@ matrix: - go: 1.6.2 os: osx env: pip_install="sudo pip install" - - go: 1.1.2 - install: go get -v . - before_script: echo skipping gfmxr on ${TRAVIS_GO_VERSION} - script: - - ./runtests vet - - ./runtests test before_script: - $pip_install flake8 +- go get github.com/urfave/gfmxr/... +- go get golang.org/x/tools/cmd/goimports - if [ ! -f node_modules/.bin/markdown-toc ] ; then npm install markdown-toc ; fi @@ -43,6 +39,7 @@ before_script: script: - flake8 runtests cli-v1-to-v2 +- ./runtests gen - ./runtests vet - ./runtests test - ./runtests gfmxr diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d3424d..febed88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,13 @@ ## [Unreleased] - (1.x series) ### Added +- Flag type code generation via `go generate` + +### Changed +- Raise minimum tested/supported Go version to 1.2+ + +## [1.18.0] - 2016-06-27 +### Added - `./runtests` test runner with coverage tracking by default - testing on OS X - testing on Windows @@ -46,6 +53,9 @@ ### Fixed - Printing of command aliases in help text - Printing of visible flags for both struct and struct pointer flags +- Display the `help` subcommand when using `CommandCategories` +- No longer swallows `panic`s that occur within the `Action`s themselves when + detecting the signature of the `Action` field ## [1.17.0] - 2016-05-09 ### Added @@ -326,7 +336,8 @@ signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`. ### Added - Initial implementation. -[Unreleased]: https://github.com/urfave/cli/compare/v1.17.0...HEAD +[Unreleased]: https://github.com/urfave/cli/compare/v1.18.0...HEAD +[1.18.0]: https://github.com/urfave/cli/compare/v1.17.0...v1.18.0 [1.17.0]: https://github.com/urfave/cli/compare/v1.16.0...v1.17.0 [1.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0 [1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0 diff --git a/README.md b/README.md index 0b2a858..1b29c86 100644 --- a/README.md +++ b/README.md @@ -60,18 +60,16 @@ organized, and expressive! ## Installation -Make sure you have a working Go environment. Go version 1.1+ is required for -core cli, whereas use of the [`./altsrc`](./altsrc) input extensions requires Go -version 1.2+. [See the install -instructions](http://golang.org/doc/install.html). +Make sure you have a working Go environment. Go version 1.2+ is supported. [See +the install instructions for Go](http://golang.org/doc/install.html). To install cli, simply run: ``` $ go get github.com/urfave/cli ``` -Make sure your `PATH` includes to the `$GOPATH/bin` directory so your commands -can be easily used: +Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can +be easily used: ``` export PATH=$PATH:$GOPATH/bin ``` diff --git a/altsrc/altsrc.go b/altsrc/altsrc.go new file mode 100644 index 0000000..ac34bf6 --- /dev/null +++ b/altsrc/altsrc.go @@ -0,0 +1,3 @@ +package altsrc + +//go:generate python ../generate-flag-types altsrc -i ../flag-types.json -o flag_generated.go diff --git a/altsrc/flag.go b/altsrc/flag.go index f14ea1c..c378ac4 100644 --- a/altsrc/flag.go +++ b/altsrc/flag.go @@ -1,7 +1,6 @@ package altsrc import ( - "flag" "fmt" "os" "strconv" @@ -62,18 +61,6 @@ func InitInputSourceWithContext(flags []cli.Flag, createInputSource func(context } } -// GenericFlag is the flag type that wraps *cli.GenericFlag to allow -// for other values to be specified -type GenericFlag struct { - *cli.GenericFlag - set *flag.FlagSet -} - -// NewGenericFlag creates a new GenericFlag -func NewGenericFlag(flag *cli.GenericFlag) *GenericFlag { - return &GenericFlag{GenericFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a generic value to the flagSet if required func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -93,25 +80,6 @@ func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourc return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped GenericFlag.Apply -func (f *GenericFlag) Apply(set *flag.FlagSet) { - f.set = set - f.GenericFlag.Apply(set) -} - -// StringSliceFlag is the flag type that wraps *cli.StringSliceFlag to allow -// for other values to be specified -type StringSliceFlag struct { - *cli.StringSliceFlag - set *flag.FlagSet -} - -// NewStringSliceFlag creates a new StringSliceFlag -func NewStringSliceFlag(flag *cli.StringSliceFlag) *StringSliceFlag { - return &StringSliceFlag{StringSliceFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a StringSlice value to the flagSet if required func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -134,25 +102,6 @@ func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputS return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped StringSliceFlag.Apply -func (f *StringSliceFlag) Apply(set *flag.FlagSet) { - f.set = set - f.StringSliceFlag.Apply(set) -} - -// IntSliceFlag is the flag type that wraps *cli.IntSliceFlag to allow -// for other values to be specified -type IntSliceFlag struct { - *cli.IntSliceFlag - set *flag.FlagSet -} - -// NewIntSliceFlag creates a new IntSliceFlag -func NewIntSliceFlag(flag *cli.IntSliceFlag) *IntSliceFlag { - return &IntSliceFlag{IntSliceFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a IntSlice value if required func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -175,25 +124,6 @@ func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSour return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped IntSliceFlag.Apply -func (f *IntSliceFlag) Apply(set *flag.FlagSet) { - f.set = set - f.IntSliceFlag.Apply(set) -} - -// BoolFlag is the flag type that wraps *cli.BoolFlag to allow -// for other values to be specified -type BoolFlag struct { - *cli.BoolFlag - set *flag.FlagSet -} - -// NewBoolFlag creates a new BoolFlag -func NewBoolFlag(flag *cli.BoolFlag) *BoolFlag { - return &BoolFlag{BoolFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a Bool value to the flagSet if required func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -212,25 +142,6 @@ func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceCo return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped BoolFlag.Apply -func (f *BoolFlag) Apply(set *flag.FlagSet) { - f.set = set - f.BoolFlag.Apply(set) -} - -// StringFlag is the flag type that wraps *cli.StringFlag to allow -// for other values to be specified -type StringFlag struct { - *cli.StringFlag - set *flag.FlagSet -} - -// NewStringFlag creates a new StringFlag -func NewStringFlag(flag *cli.StringFlag) *StringFlag { - return &StringFlag{StringFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a String value to the flagSet if required func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -249,26 +160,6 @@ func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSource return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped StringFlag.Apply -func (f *StringFlag) Apply(set *flag.FlagSet) { - f.set = set - - f.StringFlag.Apply(set) -} - -// IntFlag is the flag type that wraps *cli.IntFlag to allow -// for other values to be specified -type IntFlag struct { - *cli.IntFlag - set *flag.FlagSet -} - -// NewIntFlag creates a new IntFlag -func NewIntFlag(flag *cli.IntFlag) *IntFlag { - return &IntFlag{IntFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a int value to the flagSet if required func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -287,25 +178,6 @@ func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceCon return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped IntFlag.Apply -func (f *IntFlag) Apply(set *flag.FlagSet) { - f.set = set - f.IntFlag.Apply(set) -} - -// DurationFlag is the flag type that wraps *cli.DurationFlag to allow -// for other values to be specified -type DurationFlag struct { - *cli.DurationFlag - set *flag.FlagSet -} - -// NewDurationFlag creates a new DurationFlag -func NewDurationFlag(flag *cli.DurationFlag) *DurationFlag { - return &DurationFlag{DurationFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a Duration value to the flagSet if required func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -324,26 +196,6 @@ func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSour return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped DurationFlag.Apply -func (f *DurationFlag) Apply(set *flag.FlagSet) { - f.set = set - - f.DurationFlag.Apply(set) -} - -// Float64Flag is the flag type that wraps *cli.Float64Flag to allow -// for other values to be specified -type Float64Flag struct { - *cli.Float64Flag - set *flag.FlagSet -} - -// NewFloat64Flag creates a new Float64Flag -func NewFloat64Flag(flag *cli.Float64Flag) *Float64Flag { - return &Float64Flag{Float64Flag: flag, set: nil} -} - // ApplyInputSourceValue applies a Float64 value to the flagSet if required func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -363,14 +215,6 @@ func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourc return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped Float64Flag.Apply -func (f *Float64Flag) Apply(set *flag.FlagSet) { - f.set = set - - f.Float64Flag.Apply(set) -} - func isEnvVarSet(envVars []string) bool { for _, envVar := range envVars { if envVal := os.Getenv(envVar); envVal != "" { diff --git a/altsrc/flag_generated.go b/altsrc/flag_generated.go new file mode 100644 index 0000000..4edb0a7 --- /dev/null +++ b/altsrc/flag_generated.go @@ -0,0 +1,256 @@ +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 { + *cli.BoolFlag + set *flag.FlagSet +} + +// NewBoolFlag creates a new BoolFlag +func NewBoolFlag(fl *cli.BoolFlag) *BoolFlag { + return &BoolFlag{BoolFlag: fl, set: nil} +} + +// 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) +} + +// DurationFlag is the flag type that wraps cli.DurationFlag to allow +// for other values to be specified +type DurationFlag struct { + *cli.DurationFlag + set *flag.FlagSet +} + +// NewDurationFlag creates a new DurationFlag +func NewDurationFlag(fl *cli.DurationFlag) *DurationFlag { + return &DurationFlag{DurationFlag: fl, set: nil} +} + +// 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) +} + +// Float64Flag is the flag type that wraps cli.Float64Flag to allow +// for other values to be specified +type Float64Flag struct { + *cli.Float64Flag + set *flag.FlagSet +} + +// NewFloat64Flag creates a new Float64Flag +func NewFloat64Flag(fl *cli.Float64Flag) *Float64Flag { + return &Float64Flag{Float64Flag: fl, set: nil} +} + +// 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) +} + +// GenericFlag is the flag type that wraps cli.GenericFlag to allow +// for other values to be specified +type GenericFlag struct { + *cli.GenericFlag + set *flag.FlagSet +} + +// NewGenericFlag creates a new GenericFlag +func NewGenericFlag(fl *cli.GenericFlag) *GenericFlag { + return &GenericFlag{GenericFlag: fl, set: nil} +} + +// 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) +} + +// Int64Flag is the flag type that wraps cli.Int64Flag to allow +// for other values to be specified +type Int64Flag struct { + *cli.Int64Flag + set *flag.FlagSet +} + +// NewInt64Flag creates a new Int64Flag +func NewInt64Flag(fl *cli.Int64Flag) *Int64Flag { + return &Int64Flag{Int64Flag: fl, set: nil} +} + +// 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) +} + +// IntFlag is the flag type that wraps cli.IntFlag to allow +// for other values to be specified +type IntFlag struct { + *cli.IntFlag + set *flag.FlagSet +} + +// NewIntFlag creates a new IntFlag +func NewIntFlag(fl *cli.IntFlag) *IntFlag { + return &IntFlag{IntFlag: fl, set: nil} +} + +// 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) +} + +// IntSliceFlag is the flag type that wraps cli.IntSliceFlag to allow +// for other values to be specified +type IntSliceFlag struct { + *cli.IntSliceFlag + set *flag.FlagSet +} + +// NewIntSliceFlag creates a new IntSliceFlag +func NewIntSliceFlag(fl *cli.IntSliceFlag) *IntSliceFlag { + return &IntSliceFlag{IntSliceFlag: fl, set: nil} +} + +// 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) +} + +// Int64SliceFlag is the flag type that wraps cli.Int64SliceFlag to allow +// for other values to be specified +type Int64SliceFlag struct { + *cli.Int64SliceFlag + set *flag.FlagSet +} + +// NewInt64SliceFlag creates a new Int64SliceFlag +func NewInt64SliceFlag(fl *cli.Int64SliceFlag) *Int64SliceFlag { + return &Int64SliceFlag{Int64SliceFlag: fl, set: nil} +} + +// 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) +} + +// Float64SliceFlag is the flag type that wraps cli.Float64SliceFlag to allow +// for other values to be specified +type Float64SliceFlag struct { + *cli.Float64SliceFlag + set *flag.FlagSet +} + +// NewFloat64SliceFlag creates a new Float64SliceFlag +func NewFloat64SliceFlag(fl *cli.Float64SliceFlag) *Float64SliceFlag { + return &Float64SliceFlag{Float64SliceFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped Float64SliceFlag.Apply +func (f *Float64SliceFlag) Apply(set *flag.FlagSet) { + f.set = set + f.Float64SliceFlag.Apply(set) +} + +// StringFlag is the flag type that wraps cli.StringFlag to allow +// for other values to be specified +type StringFlag struct { + *cli.StringFlag + set *flag.FlagSet +} + +// NewStringFlag creates a new StringFlag +func NewStringFlag(fl *cli.StringFlag) *StringFlag { + return &StringFlag{StringFlag: fl, set: nil} +} + +// 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) +} + +// StringSliceFlag is the flag type that wraps cli.StringSliceFlag to allow +// for other values to be specified +type StringSliceFlag struct { + *cli.StringSliceFlag + set *flag.FlagSet +} + +// NewStringSliceFlag creates a new StringSliceFlag +func NewStringSliceFlag(fl *cli.StringSliceFlag) *StringSliceFlag { + return &StringSliceFlag{StringSliceFlag: fl, set: nil} +} + +// 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) +} + +// Uint64Flag is the flag type that wraps cli.Uint64Flag to allow +// for other values to be specified +type Uint64Flag struct { + *cli.Uint64Flag + set *flag.FlagSet +} + +// NewUint64Flag creates a new Uint64Flag +func NewUint64Flag(fl *cli.Uint64Flag) *Uint64Flag { + return &Uint64Flag{Uint64Flag: fl, set: nil} +} + +// 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) +} + +// UintFlag is the flag type that wraps cli.UintFlag to allow +// for other values to be specified +type UintFlag struct { + *cli.UintFlag + set *flag.FlagSet +} + +// NewUintFlag creates a new UintFlag +func NewUintFlag(fl *cli.UintFlag) *UintFlag { + return &UintFlag{UintFlag: fl, set: nil} +} + +// 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) +} diff --git a/app.go b/app.go index 88cdfb9..290d3bb 100644 --- a/app.go +++ b/app.go @@ -149,6 +149,10 @@ func (a *App) Setup() { a.Categories.AddCommand(command.Category, command) } sort.Sort(a.Categories.(*commandCategories)) + + if a.Metadata == nil { + a.Metadata = make(map[string]interface{}) + } } // Run is the entry point to the cli app. Parses the arguments slice and routes diff --git a/app_test.go b/app_test.go index 25def4a..7056097 100644 --- a/app_test.go +++ b/app_test.go @@ -896,6 +896,7 @@ func TestApp_Run_CommandWithSubcommandHasHelpTopic(t *testing.T) { Name: "foo", Description: "descriptive wall of text about how it does foo things", Subcommands: []*Command{subCmdBar, subCmdBaz}, + Action: func(c *Context) error { return nil }, } app.Commands = []*Command{cmd} diff --git a/cli.go b/cli.go index b2b612f..d5e3d54 100644 --- a/cli.go +++ b/cli.go @@ -18,3 +18,5 @@ // app.Run(os.Args) // } package cli + +//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go diff --git a/command_test.go b/command_test.go index 7c5bdfd..d13bc1f 100644 --- a/command_test.go +++ b/command_test.go @@ -73,6 +73,55 @@ func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) { } } +func TestCommand_Run_BeforeSavesMetadata(t *testing.T) { + var receivedMsgFromAction string + var receivedMsgFromAfter string + + app := &App{ + Commands: []*Command{ + { + Name: "bar", + Before: func(c *Context) error { + c.App.Metadata["msg"] = "hello world" + return nil + }, + Action: func(c *Context) error { + msg, ok := c.App.Metadata["msg"] + if !ok { + return errors.New("msg not found") + } + receivedMsgFromAction = msg.(string) + return nil + }, + After: func(c *Context) error { + msg, ok := c.App.Metadata["msg"] + if !ok { + return errors.New("msg not found") + } + receivedMsgFromAfter = msg.(string) + return nil + }, + }, + }, + } + + err := app.Run([]string{"foo", "bar"}) + if err != nil { + t.Fatalf("expected no error from Run, got %s", err) + } + + expectedMsg := "hello world" + + if receivedMsgFromAction != expectedMsg { + t.Fatalf("expected msg from Action to match. Given: %q\nExpected: %q", + receivedMsgFromAction, expectedMsg) + } + if receivedMsgFromAfter != expectedMsg { + t.Fatalf("expected msg from After to match. Given: %q\nExpected: %q", + receivedMsgFromAction, expectedMsg) + } +} + func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) { app := &App{ Commands: []*Command{ diff --git a/context.go b/context.go index 21a6b67..19e2d5e 100644 --- a/context.go +++ b/context.go @@ -3,9 +3,7 @@ package cli import ( "errors" "flag" - "strconv" "strings" - "time" ) // Context is a type that is passed through to @@ -25,117 +23,6 @@ func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { return &Context{App: app, flagSet: set, parentContext: parentCtx} } -// Int looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Int(name string) int { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupInt(name, fs) - } - return 0 -} - -// Int64 looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Int64(name string) int64 { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupInt64(name, fs) - } - return 0 -} - -// Uint looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Uint(name string) uint { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupUint(name, fs) - } - return 0 -} - -// Uint64 looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Uint64(name string) uint64 { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupUint64(name, fs) - } - return 0 -} - -// Duration looks up the value of a local time.Duration flag, returns 0 if no -// time.Duration flag exists -func (c *Context) Duration(name string) time.Duration { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupDuration(name, fs) - } - return 0 -} - -// Float64 looks up the value of a local float64 flag, returns 0 if no float64 -// flag exists -func (c *Context) Float64(name string) float64 { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupFloat64(name, fs) - } - return 0 -} - -// Int64Slice looks up the value of a local int slice flag, returns nil if no int -// slice flag exists -func (c *Context) Int64Slice(name string) []int64 { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupInt64Slice(name, fs) - } - return nil -} - -// Float64Slice looks up the value of a local float64 slice flag, returns nil if no float -// slice flag exists -func (c *Context) Float64Slice(name string) []float64 { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupFloat64Slice(name, fs) - } - return nil -} - -// Bool looks up the value of a local bool flag, returns false if no bool flag exists -func (c *Context) Bool(name string) bool { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupBool(name, fs) - } - return false -} - -// String looks up the value of a local string flag, returns "" if no string flag exists -func (c *Context) String(name string) string { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupString(name, fs) - } - return "" -} - -// StringSlice looks up the value of a local string slice flag, returns nil if no -// string slice flag exists -func (c *Context) StringSlice(name string) []string { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupStringSlice(name, fs) - } - return nil -} - -// IntSlice looks up the value of a local int slice flag, returns nil if no int -// slice flag exists -func (c *Context) IntSlice(name string) []int { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupIntSlice(name, fs) - } - return nil -} - -// Generic looks up the value of a local generic flag, returns nil if no generic -// flag exists -func (c *Context) Generic(name string) interface{} { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupGeneric(name, fs) - } - return nil -} - // NumFlags returns the number of flags set func (c *Context) NumFlags() int { return c.flagSet.NFlag() @@ -210,151 +97,6 @@ func lookupFlagSet(name string, ctx *Context) *flag.FlagSet { return nil } -func lookupInt(name string, set *flag.FlagSet) int { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseInt(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return int(val) - } - - return 0 -} - -func lookupInt64(name string, set *flag.FlagSet) int64 { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseInt(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return val - } - - return 0 -} - -func lookupUint(name string, set *flag.FlagSet) uint { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseUint(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return uint(val) - } - - return 0 -} - -func lookupUint64(name string, set *flag.FlagSet) uint64 { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseUint(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return val - } - - return 0 -} - -func lookupDuration(name string, set *flag.FlagSet) time.Duration { - f := set.Lookup(name) - if f != nil { - val, err := time.ParseDuration(f.Value.String()) - if err == nil { - return val - } - } - - return 0 -} - -func lookupFloat64(name string, set *flag.FlagSet) float64 { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseFloat(f.Value.String(), 64) - if err != nil { - return 0 - } - return val - } - - return 0 -} - -func lookupString(name string, set *flag.FlagSet) string { - f := set.Lookup(name) - if f != nil { - return f.Value.String() - } - - return "" -} - -func lookupStringSlice(name string, set *flag.FlagSet) []string { - f := set.Lookup(name) - if f != nil { - return (f.Value.(*StringSlice)).Value() - - } - - return nil -} - -func lookupIntSlice(name string, set *flag.FlagSet) []int { - f := set.Lookup(name) - if f != nil { - return (f.Value.(*IntSlice)).Value() - - } - - return nil -} - -func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { - f := set.Lookup(name) - if f != nil { - return (f.Value.(*Int64Slice)).Value() - - } - - return nil -} - -func lookupFloat64Slice(name string, set *flag.FlagSet) []float64 { - f := set.Lookup(name) - if f != nil { - return (f.Value.(*Float64Slice)).Value() - } - return nil -} - -func lookupGeneric(name string, set *flag.FlagSet) interface{} { - f := set.Lookup(name) - if f != nil { - return f.Value - } - return nil -} - -func lookupBool(name string, set *flag.FlagSet) bool { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseBool(f.Value.String()) - if err != nil { - return false - } - return val - } - - return false -} - func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { switch ff.Value.(type) { case Serializeder: diff --git a/flag-types.json b/flag-types.json new file mode 100644 index 0000000..f609e07 --- /dev/null +++ b/flag-types.json @@ -0,0 +1,92 @@ +[ + { + "name": "Bool", + "type": "bool", + "context_default": "false", + "parser": "strconv.ParseBool(f.Value.String())" + }, + { + "name": "Duration", + "type": "time.Duration", + "doctail": " (see https://golang.org/pkg/time/#ParseDuration)", + "context_default": "0", + "parser": "time.ParseDuration(f.Value.String())" + }, + { + "name": "Float64", + "type": "float64", + "context_default": "0", + "parser": "strconv.ParseFloat(f.Value.String(), 64)" + }, + { + "name": "Generic", + "type": "Generic", + "dest": false, + "context_default": "nil", + "context_type": "interface{}" + }, + { + "name": "Int64", + "type": "int64", + "context_default": "0", + "parser": "strconv.ParseInt(f.Value.String(), 0, 64)" + }, + { + "name": "Int", + "type": "int", + "context_default": "0", + "parser": "strconv.ParseInt(f.Value.String(), 0, 64)", + "parser_cast": "int(parsed)" + }, + { + "name": "IntSlice", + "type": "*IntSlice", + "dest": false, + "context_default": "nil", + "context_type": "[]int", + "parser": "(f.Value.(*IntSlice)).Value(), error(nil)" + }, + { + "name": "Int64Slice", + "type": "*Int64Slice", + "dest": false, + "context_default": "nil", + "context_type": "[]int64", + "parser": "(f.Value.(*Int64Slice)).Value(), error(nil)" + }, + { + "name": "Float64Slice", + "type": "*Float64Slice", + "dest": false, + "context_default": "nil", + "context_type": "[]float64", + "parser": "(f.Value.(*Float64Slice)).Value(), error(nil)" + }, + { + "name": "String", + "type": "string", + "context_default": "\"\"", + "parser": "f.Value.String(), error(nil)" + }, + { + "name": "StringSlice", + "type": "*StringSlice", + "dest": false, + "context_default": "nil", + "context_type": "[]string", + "parser": "(f.Value.(*StringSlice)).Value(), error(nil)" + }, + { + "name": "Uint64", + "type": "uint64", + "context_default": "0", + "parser": "strconv.ParseUint(f.Value.String(), 0, 64)" + }, + { + "name": "Uint", + "type": "uint", + "context_default": "0", + "parser": "strconv.ParseUint(f.Value.String(), 0, 64)", + "parser_cast": "uint(parsed)" + } +] diff --git a/flag.go b/flag.go index 2a587da..807c95f 100644 --- a/flag.go +++ b/flag.go @@ -77,23 +77,6 @@ type Generic interface { String() string } -// GenericFlag is the flag type for types implementing Generic -type GenericFlag struct { - Name string - Aliases []string - Value Generic - Usage string - EnvVars []string - Hidden bool -} - -// String returns the string representation of the generic flag to display the -// help text to the user (uses the String() method of the generic flag to show -// the value) -func (f *GenericFlag) String() string { - return FlagStringer(f) -} - // Apply takes the flagset and calls Set on the generic flag with the value // provided by the user for parsing by the flag func (f *GenericFlag) Apply(set *flag.FlagSet) { @@ -112,11 +95,6 @@ func (f *GenericFlag) Apply(set *flag.FlagSet) { } } -// Names returns the names of a flag. -func (f *GenericFlag) Names() []string { - return flagNames(f) -} - // StringSlice wraps a []string to satisfy flag.Value type StringSlice struct { slice []string @@ -162,22 +140,6 @@ func (f *StringSlice) Value() []string { return f.slice } -// StringSliceFlag is a string flag that can be specified multiple times on the -// command-line -type StringSliceFlag struct { - Name string - Aliases []string - Value *StringSlice - Usage string - EnvVars []string - Hidden bool -} - -// String returns the usage -func (f *StringSliceFlag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *StringSliceFlag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -203,11 +165,6 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) { } } -// Names returns the name of a flag. -func (f *StringSliceFlag) Names() []string { - return flagNames(f) -} - // IntSlice wraps an []int to satisfy flag.Value type IntSlice struct { slice []int @@ -273,22 +230,6 @@ func (i *IntSlice) Value() []int { return i.slice } -// IntSliceFlag is an int flag that can be specified multiple times on the -// command-line -type IntSliceFlag struct { - Name string - Aliases []string - Value *IntSlice - Usage string - EnvVars []string - Hidden bool -} - -// String returns the usage -func (f *IntSliceFlag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *IntSliceFlag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -317,11 +258,6 @@ func (f *IntSliceFlag) Apply(set *flag.FlagSet) { } } -// Names returns the name of the flag. -func (f *IntSliceFlag) Names() []string { - return flagNames(f) -} - // Int64Slice is an opaque type for []int to satisfy flag.Value type Int64Slice struct { slice []int64 @@ -367,22 +303,6 @@ func (f *Int64Slice) Value() []int64 { return f.slice } -// Int64SliceFlag is an int flag that can be specified multiple times on the -// command-line -type Int64SliceFlag struct { - Name string - Aliases []string - Value *Int64Slice - Usage string - EnvVars []string - Hidden bool -} - -// String returns the usage -func (f *Int64SliceFlag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *Int64SliceFlag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -411,27 +331,6 @@ func (f *Int64SliceFlag) Apply(set *flag.FlagSet) { } } -// Names returns the names of the flag. -func (f *Int64SliceFlag) Names() []string { - return flagNames(f) -} - -// BoolFlag is a switch that defaults to false -type BoolFlag struct { - Name string - Aliases []string - Value bool - Usage string - EnvVars []string - Destination *bool - Hidden bool -} - -// String returns a readable representation of this value (for usage defaults) -func (f *BoolFlag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *BoolFlag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -455,27 +354,6 @@ func (f *BoolFlag) Apply(set *flag.FlagSet) { } } -// Names returns the name of the flag. -func (f *BoolFlag) Names() []string { - return flagNames(f) -} - -// StringFlag represents a flag that takes as string value -type StringFlag struct { - Name string - Aliases []string - Value string - Usage string - EnvVars []string - Destination *string - Hidden bool -} - -// String returns the usage -func (f *StringFlag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *StringFlag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -496,27 +374,6 @@ func (f *StringFlag) Apply(set *flag.FlagSet) { } } -// Names returns the name of the flag. -func (f *StringFlag) Names() []string { - return flagNames(f) -} - -// IntFlag is a flag that takes an integer -type IntFlag struct { - Name string - Aliases []string - Value int - Usage string - EnvVars []string - Destination *int - Hidden bool -} - -// String returns the usage -func (f *IntFlag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *IntFlag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -540,27 +397,6 @@ func (f *IntFlag) Apply(set *flag.FlagSet) { } } -// Names returns the name of the flag. -func (f *IntFlag) Names() []string { - return flagNames(f) -} - -// Int64Flag is a flag that takes a 64-bit integer -type Int64Flag struct { - Name string - Aliases []string - Value int64 - Usage string - EnvVars []string - Destination *int64 - Hidden bool -} - -// String returns the usage -func (f *Int64Flag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *Int64Flag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -584,27 +420,6 @@ func (f *Int64Flag) Apply(set *flag.FlagSet) { } } -// Names returns the names of the flag. -func (f *Int64Flag) Names() []string { - return flagNames(f) -} - -// UintFlag is a flag that takes an unsigned integer -type UintFlag struct { - Name string - Aliases []string - Value uint - Usage string - EnvVars []string - Destination *uint - Hidden bool -} - -// String returns the usage -func (f *UintFlag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *UintFlag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -628,27 +443,6 @@ func (f *UintFlag) Apply(set *flag.FlagSet) { } } -// Names returns the names of the flag. -func (f *UintFlag) Names() []string { - return flagNames(f) -} - -// Uint64Flag is a flag that takes an unsigned 64-bit integer -type Uint64Flag struct { - Name string - Aliases []string - Value uint64 - Usage string - EnvVars []string - Destination *uint64 - Hidden bool -} - -// String returns the usage -func (f *Uint64Flag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *Uint64Flag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -672,28 +466,6 @@ func (f *Uint64Flag) Apply(set *flag.FlagSet) { } } -// Names returns the names of the flag. -func (f *Uint64Flag) Names() []string { - return flagNames(f) -} - -// DurationFlag is a flag that takes a duration specified in Go's duration -// format: https://golang.org/pkg/time/#ParseDuration -type DurationFlag struct { - Name string - Aliases []string - Value time.Duration - Usage string - EnvVars []string - Destination *time.Duration - Hidden bool -} - -// String returns a readable representation of this value (for usage defaults) -func (f *DurationFlag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *DurationFlag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -717,27 +489,6 @@ func (f *DurationFlag) Apply(set *flag.FlagSet) { } } -// Names returns the name of the flag. -func (f *DurationFlag) Names() []string { - return flagNames(f) -} - -// Float64Flag is a flag that takes an float value -type Float64Flag struct { - Name string - Aliases []string - Value float64 - Usage string - EnvVars []string - Destination *float64 - Hidden bool -} - -// String returns the usage -func (f *Float64Flag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *Float64Flag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -760,20 +511,11 @@ func (f *Float64Flag) Apply(set *flag.FlagSet) { } } -// Names returns the name of the flag. -func (f *Float64Flag) Names() []string { - return flagNames(f) -} - - - - // NewFloat64Slice makes a *Float64Slice with default values func NewFloat64Slice(defaults ...float64) *Float64Slice { return &Float64Slice{slice: append([]float64{}, defaults...)} } - // Float64Slice is an opaque type for []float64 to satisfy flag.Value type Float64Slice struct { slice []float64 @@ -819,22 +561,6 @@ func (f *Float64Slice) Value() []float64 { return f.slice } -// Float64SliceFlag is a float64 flag that can be specified multiple times on the -// command-line -type Float64SliceFlag struct { - Name string - Aliases []string - Value *Float64Slice - Usage string - EnvVars []string - Hidden bool -} - -// String returns the usage -func (f *Float64SliceFlag) String() string { - return FlagStringer(f) -} - // Apply populates the flag given the flag set and environment func (f *Float64SliceFlag) Apply(set *flag.FlagSet) { if f.EnvVars != nil { @@ -863,13 +589,6 @@ func (f *Float64SliceFlag) Apply(set *flag.FlagSet) { } } -// Names returns the names of the flag. -func (f *Float64SliceFlag) Names() []string { - return flagNames(f) -} - - - func visibleFlags(fl []Flag) []Flag { visible := []Flag{} for _, flag := range fl { diff --git a/flag_generated.go b/flag_generated.go new file mode 100644 index 0000000..626ec78 --- /dev/null +++ b/flag_generated.go @@ -0,0 +1,524 @@ +package cli + +import ( + "flag" + "strconv" + "time" +) + +// WARNING: This file is generated! + +// BoolFlag is a flag with type bool +type BoolFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value bool + Destination *bool +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *BoolFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *BoolFlag) Names() []string { + return flagNames(f) +} + +// Bool looks up the value of a local BoolFlag, returns +// false if not found +func (c *Context) Bool(name string) bool { + return lookupBool(name, c.flagSet) +} + +func lookupBool(name string, set *flag.FlagSet) bool { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseBool(f.Value.String()) + if err != nil { + return false + } + return parsed + } + return false +} + +// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration) +type DurationFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value time.Duration + Destination *time.Duration +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *DurationFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *DurationFlag) Names() []string { + return flagNames(f) +} + +// Duration looks up the value of a local DurationFlag, returns +// 0 if not found +func (c *Context) Duration(name string) time.Duration { + return lookupDuration(name, c.flagSet) +} + +func lookupDuration(name string, set *flag.FlagSet) time.Duration { + f := set.Lookup(name) + if f != nil { + parsed, err := time.ParseDuration(f.Value.String()) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// Float64Flag is a flag with type float64 +type Float64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value float64 + Destination *float64 +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Float64Flag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Float64Flag) Names() []string { + return flagNames(f) +} + +// Float64 looks up the value of a local Float64Flag, returns +// 0 if not found +func (c *Context) Float64(name string) float64 { + return lookupFloat64(name, c.flagSet) +} + +func lookupFloat64(name string, set *flag.FlagSet) float64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseFloat(f.Value.String(), 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// GenericFlag is a flag with type Generic +type GenericFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value Generic +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *GenericFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *GenericFlag) Names() []string { + return flagNames(f) +} + +// Generic looks up the value of a local GenericFlag, returns +// nil if not found +func (c *Context) Generic(name string) interface{} { + return lookupGeneric(name, c.flagSet) +} + +func lookupGeneric(name string, set *flag.FlagSet) interface{} { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value, error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// Int64Flag is a flag with type int64 +type Int64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value int64 + Destination *int64 +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Int64Flag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Int64Flag) Names() []string { + return flagNames(f) +} + +// Int64 looks up the value of a local Int64Flag, returns +// 0 if not found +func (c *Context) Int64(name string) int64 { + return lookupInt64(name, c.flagSet) +} + +func lookupInt64(name string, set *flag.FlagSet) int64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// IntFlag is a flag with type int +type IntFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value int + Destination *int +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *IntFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *IntFlag) Names() []string { + return flagNames(f) +} + +// Int looks up the value of a local IntFlag, returns +// 0 if not found +func (c *Context) Int(name string) int { + return lookupInt(name, c.flagSet) +} + +func lookupInt(name string, set *flag.FlagSet) int { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return int(parsed) + } + return 0 +} + +// IntSliceFlag is a flag with type *IntSlice +type IntSliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value *IntSlice +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *IntSliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *IntSliceFlag) Names() []string { + return flagNames(f) +} + +// IntSlice looks up the value of a local IntSliceFlag, returns +// nil if not found +func (c *Context) IntSlice(name string) []int { + return lookupIntSlice(name, c.flagSet) +} + +func lookupIntSlice(name string, set *flag.FlagSet) []int { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*IntSlice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// Int64SliceFlag is a flag with type *Int64Slice +type Int64SliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value *Int64Slice +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Int64SliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Int64SliceFlag) Names() []string { + return flagNames(f) +} + +// Int64Slice looks up the value of a local Int64SliceFlag, returns +// nil if not found +func (c *Context) Int64Slice(name string) []int64 { + return lookupInt64Slice(name, c.flagSet) +} + +func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// Float64SliceFlag is a flag with type *Float64Slice +type Float64SliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value *Float64Slice +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Float64SliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Float64SliceFlag) Names() []string { + return flagNames(f) +} + +// Float64Slice looks up the value of a local Float64SliceFlag, returns +// nil if not found +func (c *Context) Float64Slice(name string) []float64 { + return lookupFloat64Slice(name, c.flagSet) +} + +func lookupFloat64Slice(name string, set *flag.FlagSet) []float64 { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*Float64Slice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// StringFlag is a flag with type string +type StringFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value string + Destination *string +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *StringFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *StringFlag) Names() []string { + return flagNames(f) +} + +// String looks up the value of a local StringFlag, returns +// "" if not found +func (c *Context) String(name string) string { + return lookupString(name, c.flagSet) +} + +func lookupString(name string, set *flag.FlagSet) string { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value.String(), error(nil) + if err != nil { + return "" + } + return parsed + } + return "" +} + +// StringSliceFlag is a flag with type *StringSlice +type StringSliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value *StringSlice +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *StringSliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *StringSliceFlag) Names() []string { + return flagNames(f) +} + +// StringSlice looks up the value of a local StringSliceFlag, returns +// nil if not found +func (c *Context) StringSlice(name string) []string { + return lookupStringSlice(name, c.flagSet) +} + +func lookupStringSlice(name string, set *flag.FlagSet) []string { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*StringSlice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// Uint64Flag is a flag with type uint64 +type Uint64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value uint64 + Destination *uint64 +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Uint64Flag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Uint64Flag) Names() []string { + return flagNames(f) +} + +// Uint64 looks up the value of a local Uint64Flag, returns +// 0 if not found +func (c *Context) Uint64(name string) uint64 { + return lookupUint64(name, c.flagSet) +} + +func lookupUint64(name string, set *flag.FlagSet) uint64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// UintFlag is a flag with type uint +type UintFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + Hidden bool + Value uint + Destination *uint +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *UintFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *UintFlag) Names() []string { + return flagNames(f) +} + +// Uint looks up the value of a local UintFlag, returns +// 0 if not found +func (c *Context) Uint(name string) uint { + return lookupUint(name, c.flagSet) +} + +func lookupUint(name string, set *flag.FlagSet) uint { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return uint(parsed) + } + return 0 +} diff --git a/generate-flag-types b/generate-flag-types new file mode 100755 index 0000000..28069b3 --- /dev/null +++ b/generate-flag-types @@ -0,0 +1,231 @@ +#!/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('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 + Aliases []string + Usage string + EnvVars []string + Hidden bool + 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) + }} + + // Names returns the names of the flag + func (f *{name}Flag) Names() []string {{ + return flagNames(f) + }} + + // {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) + }} + + 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 + + // 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) + }} + """.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()) diff --git a/runtests b/runtests index 5b903e6..c5612b1 100755 --- a/runtests +++ b/runtests @@ -38,7 +38,7 @@ def _target(func): @_target def _test(): if check_output('go version'.split()).split()[2] < 'go1.2': - _run('go test -v .'.split()) + _run('go test -v .') return coverprofiles = [] @@ -55,7 +55,7 @@ def _test(): ]) combined_name = _combine_coverprofiles(coverprofiles) - _run('go tool cover -func={}'.format(combined_name).split()) + _run('go tool cover -func={}'.format(combined_name)) os.remove(combined_name) @@ -66,7 +66,7 @@ def _gfmxr(): @_target def _vet(): - _run('go vet ./...'.split()) + _run('go vet ./...') @_target @@ -101,10 +101,23 @@ def _toc(): os.path.join('node_modules', '.bin', 'markdown-toc'), '-i', 'README.md' ]) - _run(['git', 'diff', '--quiet']) + _run('git diff --exit-code') + + +@_target +def _gen(): + go_version = check_output('go version'.split()).split()[2] + if go_version < 'go1.4': + print('runtests: skip on {}'.format(go_version), file=sys.stderr) + return + + _run('go generate ./...') + _run('git diff --exit-code') def _run(command): + if hasattr(command, 'split'): + command = command.split() print('runtests: {}'.format(' '.join(command)), file=sys.stderr) sys.stderr.flush() check_call(command)