Merge pull request #483 from urfave/merging-from-v1

Merging from v1
This commit is contained in:
Jesse Szwedko 2016-07-14 19:22:57 -07:00 committed by GitHub
commit 40a9813f6f
16 changed files with 1198 additions and 712 deletions

View File

@ -23,15 +23,11 @@ matrix:
- go: 1.6.2 - go: 1.6.2
os: osx os: osx
env: pip_install="sudo pip install" 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: before_script:
- $pip_install flake8 - $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 - if [ ! -f node_modules/.bin/markdown-toc ] ; then
npm install markdown-toc ; npm install markdown-toc ;
fi fi
@ -43,6 +39,7 @@ before_script:
script: script:
- flake8 runtests cli-v1-to-v2 - flake8 runtests cli-v1-to-v2
- ./runtests gen
- ./runtests vet - ./runtests vet
- ./runtests test - ./runtests test
- ./runtests gfmxr - ./runtests gfmxr

View File

@ -34,6 +34,13 @@
## [Unreleased] - (1.x series) ## [Unreleased] - (1.x series)
### Added ### 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 - `./runtests` test runner with coverage tracking by default
- testing on OS X - testing on OS X
- testing on Windows - testing on Windows
@ -46,6 +53,9 @@
### Fixed ### Fixed
- Printing of command aliases in help text - Printing of command aliases in help text
- Printing of visible flags for both struct and struct pointer flags - 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 ## [1.17.0] - 2016-05-09
### Added ### Added
@ -326,7 +336,8 @@ signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
### Added ### Added
- Initial implementation. - 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.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.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 [1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0

View File

@ -60,18 +60,16 @@ organized, and expressive!
## Installation ## Installation
Make sure you have a working Go environment. Go version 1.1+ is required for Make sure you have a working Go environment. Go version 1.2+ is supported. [See
core cli, whereas use of the [`./altsrc`](./altsrc) input extensions requires Go the install instructions for Go](http://golang.org/doc/install.html).
version 1.2+. [See the install
instructions](http://golang.org/doc/install.html).
To install cli, simply run: To install cli, simply run:
``` ```
$ go get github.com/urfave/cli $ go get github.com/urfave/cli
``` ```
Make sure your `PATH` includes to the `$GOPATH/bin` directory so your commands Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can
can be easily used: be easily used:
``` ```
export PATH=$PATH:$GOPATH/bin export PATH=$PATH:$GOPATH/bin
``` ```

3
altsrc/altsrc.go Normal file
View File

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

View File

@ -1,7 +1,6 @@
package altsrc package altsrc
import ( import (
"flag"
"fmt" "fmt"
"os" "os"
"strconv" "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 // ApplyInputSourceValue applies a generic value to the flagSet if required
func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
if f.set != nil { if f.set != nil {
@ -93,25 +80,6 @@ func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourc
return nil 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 // ApplyInputSourceValue applies a StringSlice value to the flagSet if required
func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
if f.set != nil { if f.set != nil {
@ -134,25 +102,6 @@ func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputS
return nil 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 // ApplyInputSourceValue applies a IntSlice value if required
func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
if f.set != nil { if f.set != nil {
@ -175,25 +124,6 @@ func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSour
return nil 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 // ApplyInputSourceValue applies a Bool value to the flagSet if required
func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
if f.set != nil { if f.set != nil {
@ -212,25 +142,6 @@ func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceCo
return nil 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 // ApplyInputSourceValue applies a String value to the flagSet if required
func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
if f.set != nil { if f.set != nil {
@ -249,26 +160,6 @@ func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSource
return nil 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 // ApplyInputSourceValue applies a int value to the flagSet if required
func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
if f.set != nil { if f.set != nil {
@ -287,25 +178,6 @@ func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceCon
return nil 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 // ApplyInputSourceValue applies a Duration value to the flagSet if required
func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
if f.set != nil { if f.set != nil {
@ -324,26 +196,6 @@ func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSour
return nil 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 // ApplyInputSourceValue applies a Float64 value to the flagSet if required
func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
if f.set != nil { if f.set != nil {
@ -363,14 +215,6 @@ func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourc
return nil 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 { func isEnvVarSet(envVars []string) bool {
for _, envVar := range envVars { for _, envVar := range envVars {
if envVal := os.Getenv(envVar); envVal != "" { if envVal := os.Getenv(envVar); envVal != "" {

256
altsrc/flag_generated.go Normal file
View File

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

4
app.go
View File

@ -149,6 +149,10 @@ func (a *App) Setup() {
a.Categories.AddCommand(command.Category, command) a.Categories.AddCommand(command.Category, command)
} }
sort.Sort(a.Categories.(*commandCategories)) 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 // Run is the entry point to the cli app. Parses the arguments slice and routes

View File

@ -896,6 +896,7 @@ func TestApp_Run_CommandWithSubcommandHasHelpTopic(t *testing.T) {
Name: "foo", Name: "foo",
Description: "descriptive wall of text about how it does foo things", Description: "descriptive wall of text about how it does foo things",
Subcommands: []*Command{subCmdBar, subCmdBaz}, Subcommands: []*Command{subCmdBar, subCmdBaz},
Action: func(c *Context) error { return nil },
} }
app.Commands = []*Command{cmd} app.Commands = []*Command{cmd}

2
cli.go
View File

@ -18,3 +18,5 @@
// app.Run(os.Args) // app.Run(os.Args)
// } // }
package cli package cli
//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go

View File

@ -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) { func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) {
app := &App{ app := &App{
Commands: []*Command{ Commands: []*Command{

View File

@ -3,9 +3,7 @@ package cli
import ( import (
"errors" "errors"
"flag" "flag"
"strconv"
"strings" "strings"
"time"
) )
// Context is a type that is passed through to // 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} 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 // NumFlags returns the number of flags set
func (c *Context) NumFlags() int { func (c *Context) NumFlags() int {
return c.flagSet.NFlag() return c.flagSet.NFlag()
@ -210,151 +97,6 @@ func lookupFlagSet(name string, ctx *Context) *flag.FlagSet {
return nil 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) { func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
switch ff.Value.(type) { switch ff.Value.(type) {
case Serializeder: case Serializeder:

92
flag-types.json Normal file
View File

@ -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)"
}
]

281
flag.go
View File

@ -77,23 +77,6 @@ type Generic interface {
String() string 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 // Apply takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag // provided by the user for parsing by the flag
func (f *GenericFlag) Apply(set *flag.FlagSet) { 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 // StringSlice wraps a []string to satisfy flag.Value
type StringSlice struct { type StringSlice struct {
slice []string slice []string
@ -162,22 +140,6 @@ func (f *StringSlice) Value() []string {
return f.slice 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 // Apply populates the flag given the flag set and environment
func (f *StringSliceFlag) Apply(set *flag.FlagSet) { func (f *StringSliceFlag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // IntSlice wraps an []int to satisfy flag.Value
type IntSlice struct { type IntSlice struct {
slice []int slice []int
@ -273,22 +230,6 @@ func (i *IntSlice) Value() []int {
return i.slice 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 // Apply populates the flag given the flag set and environment
func (f *IntSliceFlag) Apply(set *flag.FlagSet) { func (f *IntSliceFlag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // Int64Slice is an opaque type for []int to satisfy flag.Value
type Int64Slice struct { type Int64Slice struct {
slice []int64 slice []int64
@ -367,22 +303,6 @@ func (f *Int64Slice) Value() []int64 {
return f.slice 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 // Apply populates the flag given the flag set and environment
func (f *Int64SliceFlag) Apply(set *flag.FlagSet) { func (f *Int64SliceFlag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // Apply populates the flag given the flag set and environment
func (f *BoolFlag) Apply(set *flag.FlagSet) { func (f *BoolFlag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // Apply populates the flag given the flag set and environment
func (f *StringFlag) Apply(set *flag.FlagSet) { func (f *StringFlag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // Apply populates the flag given the flag set and environment
func (f *IntFlag) Apply(set *flag.FlagSet) { func (f *IntFlag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // Apply populates the flag given the flag set and environment
func (f *Int64Flag) Apply(set *flag.FlagSet) { func (f *Int64Flag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // Apply populates the flag given the flag set and environment
func (f *UintFlag) Apply(set *flag.FlagSet) { func (f *UintFlag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // Apply populates the flag given the flag set and environment
func (f *Uint64Flag) Apply(set *flag.FlagSet) { func (f *Uint64Flag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // Apply populates the flag given the flag set and environment
func (f *DurationFlag) Apply(set *flag.FlagSet) { func (f *DurationFlag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // Apply populates the flag given the flag set and environment
func (f *Float64Flag) Apply(set *flag.FlagSet) { func (f *Float64Flag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 // NewFloat64Slice makes a *Float64Slice with default values
func NewFloat64Slice(defaults ...float64) *Float64Slice { func NewFloat64Slice(defaults ...float64) *Float64Slice {
return &Float64Slice{slice: append([]float64{}, defaults...)} return &Float64Slice{slice: append([]float64{}, defaults...)}
} }
// Float64Slice is an opaque type for []float64 to satisfy flag.Value // Float64Slice is an opaque type for []float64 to satisfy flag.Value
type Float64Slice struct { type Float64Slice struct {
slice []float64 slice []float64
@ -819,22 +561,6 @@ func (f *Float64Slice) Value() []float64 {
return f.slice 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 // Apply populates the flag given the flag set and environment
func (f *Float64SliceFlag) Apply(set *flag.FlagSet) { func (f *Float64SliceFlag) Apply(set *flag.FlagSet) {
if f.EnvVars != nil { 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 { func visibleFlags(fl []Flag) []Flag {
visible := []Flag{} visible := []Flag{}
for _, flag := range fl { for _, flag := range fl {

524
flag_generated.go Normal file
View File

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

231
generate-flag-types Executable file
View File

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

View File

@ -38,7 +38,7 @@ def _target(func):
@_target @_target
def _test(): def _test():
if check_output('go version'.split()).split()[2] < 'go1.2': if check_output('go version'.split()).split()[2] < 'go1.2':
_run('go test -v .'.split()) _run('go test -v .')
return return
coverprofiles = [] coverprofiles = []
@ -55,7 +55,7 @@ def _test():
]) ])
combined_name = _combine_coverprofiles(coverprofiles) 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) os.remove(combined_name)
@ -66,7 +66,7 @@ def _gfmxr():
@_target @_target
def _vet(): def _vet():
_run('go vet ./...'.split()) _run('go vet ./...')
@_target @_target
@ -101,10 +101,23 @@ def _toc():
os.path.join('node_modules', '.bin', 'markdown-toc'), os.path.join('node_modules', '.bin', 'markdown-toc'),
'-i', 'README.md' '-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): def _run(command):
if hasattr(command, 'split'):
command = command.split()
print('runtests: {}'.format(' '.join(command)), file=sys.stderr) print('runtests: {}'.format(' '.join(command)), file=sys.stderr)
sys.stderr.flush() sys.stderr.flush()
check_call(command) check_call(command)