diff --git a/CHANGELOG.md b/CHANGELOG.md index b1924f520d..1a4b1d36ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,10 +20,10 @@ To migrate to the new API, you may choose to run [the migrator (python) script](./cli-v1-to-v2). - The optimistic reordering of arguments and flags introduced by - https://github.com/codegangsta/cli/pull/36. This behavior only worked when + https://github.com/urfave/cli/pull/36. This behavior only worked when all arguments appeared before all flags, but caused [weird issues with boolean - flags](https://github.com/codegangsta/cli/issues/103) and [reordering of the - arguments](https://github.com/codegangsta/cli/issues/355) when the user + flags](https://github.com/urfave/cli/issues/103) and [reordering of the + arguments](https://github.com/urfave/cli/issues/355) when the user attempted to mix flags and arguments. Given the trade-offs we removed support for this reordering. - adapter code for deprecated `Action` func signature diff --git a/README.md b/README.md index d7cee581a3..c701b36217 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ applications in an expressive way. - [Installation](#installation) * [Supported platforms](#supported-platforms) * [Using the `v2` branch](#using-the-v2-branch) - * [Pinning to the `v1` releases](#pinning-to-the-v1-releases) + * [Using `v1` releases](#using-v1-releases) - [Getting Started](#getting-started) - [Examples](#examples) * [Arguments](#arguments) @@ -104,9 +104,6 @@ import ( ... ``` -**NOTE**: There is a [migrator (python) script](./cli-v1-to-v2) available to aid -with the transition from the v1 to v2 API. - ### Pinning to the `v1` releases Similarly to the section above describing use of the `v2` branch, if one wants @@ -120,7 +117,7 @@ $ go get github.com/urfave/cli ```go ... import ( - "github.com/urfave/cli/v2" + "github.com/urfave/cli" ) ... ``` @@ -710,11 +707,10 @@ Here is a more complete sample of a command using YAML support: "output": "--test value.*default: 0" } --> ``` go -package notmain +package main import ( "fmt" - "log" "os" "github.com/urfave/cli/v2" @@ -735,7 +731,7 @@ func main() { Before: altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load")), Flags: flags, } - + app.Run(os.Args) } ``` @@ -949,7 +945,7 @@ func main() { }, Action: func(ctx *cli.Context) error { if !ctx.Bool("ginger-crouton") { - return cli.Exit(Ginger croutons are not in the soup, 86) + return cli.Exit("Ginger croutons are not in the soup", 86) } return nil }, @@ -986,7 +982,7 @@ import ( "fmt" "log" "os" - + "github.com/urfave/cli/v2" ) diff --git a/altsrc/json_source_context.go b/altsrc/json_source_context.go index 41602ad242..6f66aa3356 100644 --- a/altsrc/json_source_context.go +++ b/altsrc/json_source_context.go @@ -66,10 +66,10 @@ func (x *jsonSource) Int(name string) (int, error) { return 0, fmt.Errorf("unexpected type %T for %q", i, name) case int: return v, nil - case float64: - return int(v), nil case float32: return int(v), nil + case float64: + return int(v), nil } } @@ -203,5 +203,6 @@ func jsonGetValue(key string, m map[string]interface{}) (interface{}, error) { type jsonSource struct { file string - deserialized map[string]interface{} + deserialized map[string]interface { + } } diff --git a/altsrc/toml_command_test.go b/altsrc/toml_command_test.go index 84558aa19b..9c96dcef95 100644 --- a/altsrc/toml_command_test.go +++ b/altsrc/toml_command_test.go @@ -241,7 +241,7 @@ func TestCommandTomlFileTestDefaultValueFileWinsNested(t *testing.T) { } func TestCommandTomlFileFlagHasDefaultGlobalEnvTomlSetGlobalEnvWins(t *testing.T) { - app := (&cli.App{}) + app := &cli.App{} set := flag.NewFlagSet("test", 0) _ = ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) defer os.Remove("current.toml") diff --git a/app.go b/app.go index f0c6ac939d..767b1f1679 100644 --- a/app.go +++ b/app.go @@ -11,16 +11,14 @@ import ( "time" ) -var ( - changeLogURL = "https://github.com/urfave/cli/blob/master/CHANGELOG.md" - appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL) - - contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you." - - errInvalidActionType = NewExitError("ERROR invalid Action type. "+ - fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+ - fmt.Sprintf("See %s", appActionDeprecationURL), 2) -) +//var ( +// changeLogURL = "https://github.com/urfave/cli/blob/master/CHANGELOG.md" +// appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL) +// contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you." +// errInvalidActionType = NewExitError("ERROR invalid Action type. "+ +// fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+ +// fmt.Sprintf("See %s", appActionDeprecationURL), 2) +//) // App is the main structure of a cli application. It is recommended that // an app be created with the cli.NewApp() function @@ -534,28 +532,3 @@ func (a *Author) String() string { return fmt.Sprintf("%v%v", a.Name, e) } - -// DefaultAppComplete returns an ActionFunc to run a default command if non were passed. -// Usage: `app.Action = cli.DefaultCommand("command")` -func DefaultCommand(name string) ActionFunc { - return func(ctx *Context) error { - return ctx.App.Command(name).Run(ctx) - } -} - -// HandleAction attempts to figure out which Action signature was used. If -// it's an ActionFunc or a func with the legacy signature for Action, the func -// is run! -func HandleAction(action interface{}, context *Context) (err error) { - switch a := action.(type) { - case ActionFunc: - return a(context) - case func(*Context) error: - return a(context) - case func(*Context): // deprecated function signature - a(context) - return nil - } - - return errInvalidActionType -} diff --git a/app_test.go b/app_test.go index 2d1d656173..7a737241c9 100644 --- a/app_test.go +++ b/app_test.go @@ -445,63 +445,6 @@ func TestApp_Setup_defaultsWriter(t *testing.T) { expect(t, app.Writer, os.Stdout) } - -//func TestApp_CommandWithArgBeforeFlags(t *testing.T) { -// var parsedOption, firstArg string -// -// app := NewApp() -// command := &Command{ -// Name: "cmd", -// Flags: []Flag{ -// &StringFlag{Name: "option", Value: "", Usage: "some option"}, -// }, -// Action: func(c *Context) error { -// parsedOption = c.String("option") -// firstArg = c.Args().First() -// return nil -// }, -// } -// app.Commands = []*Command{command} -// -// _ = app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"}) -// -// expect(t, parsedOption, "my-option") -// expect(t, firstArg, "my-arg") -//} -// -//func TestApp_CommandWithArgBeforeBoolFlags(t *testing.T) { -// var parsedOption, parsedSecondOption, firstArg string -// var parsedBool, parsedSecondBool bool -// -// app := NewApp() -// command := &Command{ -// Name: "cmd", -// Flags: []Flag{ -// &StringFlag{Name: "option", Value: "", Usage: "some option"}, -// &StringFlag{Name: "secondOption", Value: "", Usage: "another option"}, -// &BoolFlag{Name: "boolflag", Usage: "some bool"}, -// &BoolFlag{Name: "b", Usage: "another bool"}, -// }, -// Action: func(c *Context) error { -// parsedOption = c.String("option") -// parsedSecondOption = c.String("secondOption") -// parsedBool = c.Bool("boolflag") -// parsedSecondBool = c.Bool("b") -// firstArg = c.Args().First() -// return nil -// }, -// } -// app.Commands = []*Command{command} -// -// _ = app.Run([]string{"", "cmd", "my-arg", "--boolflag", "--option", "my-option", "-b", "--secondOption", "fancy-option"}) -// -// expect(t, parsedOption, "my-option") -// expect(t, parsedSecondOption, "fancy-option") -// expect(t, parsedBool, true) -// expect(t, parsedSecondBool, true) -// expect(t, firstArg, "my-arg") -//} - func TestApp_RunAsSubcommandParseFlags(t *testing.T) { var context *Context @@ -2073,23 +2016,6 @@ func TestHandleExitCoder_Custom(t *testing.T) { } } -func TestHandleAction_WithUnknownPanic(t *testing.T) { - defer func() { refute(t, recover(), nil) }() - - var fn ActionFunc - - app := NewApp() - app.Action = func(ctx *Context) error { - _ = fn(ctx) - return nil - } - fs, err := flagSet(app.Name, app.Flags) - if err != nil { - t.Errorf("error creating FlagSet: %s", err) - } - _ = HandleAction(app.Action, NewContext(app, fs, nil)) -} - func TestShellCompletionForIncompleteFlags(t *testing.T) { app := &App{ Flags: []Flag{ diff --git a/appveyor.yml b/appveyor.yml index 4c3d669735..1f30f3b640 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,4 +26,3 @@ build_script: - go run build.go vet - go run build.go test - go run build.go gfmrun - diff --git a/command.go b/command.go index af86824900..3a1f21bcc2 100644 --- a/command.go +++ b/command.go @@ -184,10 +184,6 @@ func (c *Command) parseFlags(args Args) (*flag.FlagSet, error) { return set, set.Parse(append([]string{"--"}, args.Tail()...)) } - //if !c.SkipArgReorder { - // args = reorderArgs(args) - //} - set, err := parseIter(c, args.Tail()) if err != nil { return nil, err diff --git a/command_test.go b/command_test.go index 5d910318ea..25e1ca5146 100644 --- a/command_test.go +++ b/command_test.go @@ -28,7 +28,7 @@ func TestCommandFlagParsing(t *testing.T) { for _, c := range cases { app := &App{Writer: ioutil.Discard} set := flag.NewFlagSet("test", 0) - set.Parse(c.testArgs) + _ = set.Parse(c.testArgs) context := NewContext(app, set, nil) diff --git a/context.go b/context.go index 66dcdd63e4..70af324dd6 100644 --- a/context.go +++ b/context.go @@ -74,40 +74,11 @@ func (c *Context) IsSet(name string) bool { } } - // XXX hack to support IsSet for flags with EnvVar - // - // There isn't an easy way to do this with the current implementation since - // whether a flag was set via an environment variable is very difficult to - // determine here. Instead, we intend to introduce a backwards incompatible - // change in version 2 to add `IsSet` to the Flag interface to push the - // responsibility closer to where the information required to determine - // whether a flag is set by non-standard means such as environment - // variables is available. - // - // See https://github.com/urfave/cli/issues/294 for additional discussion f := lookupFlag(name, c) if f == nil { return false } - //val := reflect.ValueOf(f) - //if val.Kind() == reflect.Ptr { - // val = val.Elem() - //} - // - //filePathValue := val.FieldByName("FilePath") - //if !filePathValue.IsValid() { - // return false - //} - // - //envVarValues := val.FieldByName("EnvVars") - //if !envVarValues.IsValid() { - // return false - //} - // - //_, ok := flagFromEnvOrFile(envVarValues.Interface().([]string), filePathValue.Interface().(string)) - //return ok - return f.IsSet() } @@ -132,30 +103,6 @@ func (c *Context) FlagNames() []string { return names } -// FlagNames returns a slice of flag names used in this context. -//func (c *Context) FlagNames() (names []string) { -// for _, f := range c.Command.Flags { -// name := strings.Split(f.GetName(), ",")[0] -// if name == "help" { -// continue -// } -// names = append(names, name) -// } -// return -//} - -// GlobalFlagNames returns a slice of global flag names used by the app. -//func (c *Context) GlobalFlagNames() (names []string) { -// for _, f := range c.App.Flags { -// name := strings.Split(f.GetName(), ",")[0] -// if name == "help" || name == "version" { -// continue -// } -// names = append(names, name) -// } -// return names -//} - // Lineage returns *this* context and all of its ancestor contexts in order from // child to parent func (c *Context) Lineage() []*Context { @@ -310,6 +257,7 @@ func checkRequiredFlags(flags []Flag, context *Context) requiredFlagsErr { if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() { var flagPresent bool var flagName string + for _, key := range f.Names() { if len(key) > 1 { flagName = key diff --git a/context_test.go b/context_test.go index fef4945066..081a8c43b9 100644 --- a/context_test.go +++ b/context_test.go @@ -3,12 +3,9 @@ package cli import ( "context" "flag" - "sort" - "os" "strings" - "testing" "time" ) @@ -462,6 +459,7 @@ func TestCheckRequiredFlags(t *testing.T) { parseInput: []string{"-n", "asd", "-n", "qwe"}, }, } + for _, test := range tdata { t.Run(test.testCase, func(t *testing.T) { // setup diff --git a/flag.go b/flag.go index 701ef317b0..fac1172190 100644 --- a/flag.go +++ b/flag.go @@ -314,7 +314,7 @@ func stringifyIntSliceFlag(f *IntSliceFlag) string { var defaultVals []string if f.Value != nil && len(f.Value.Value()) > 0 { for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, fmt.Sprintf("%d", i)) + defaultVals = append(defaultVals, strconv.Itoa(i)) } } @@ -346,7 +346,6 @@ func stringifyFloat64SliceFlag(f *Float64SliceFlag) string { func stringifyStringSliceFlag(f *StringSliceFlag) string { var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { for _, s := range f.Value.Value() { if len(s) > 0 { diff --git a/flag_int64.go b/flag_int64.go index 1f4cefd2f4..c979119f8e 100644 --- a/flag_int64.go +++ b/flag_int64.go @@ -80,7 +80,6 @@ func (f *Int64Flag) Apply(set *flag.FlagSet) error { } set.Int64(name, f.Value, f.Usage) } - return nil } diff --git a/flag_int_slice.go b/flag_int_slice.go index d4f934ed8e..9388978421 100644 --- a/flag_int_slice.go +++ b/flag_int_slice.go @@ -50,6 +50,7 @@ func (i *IntSlice) Set(value string) error { } i.slice = append(i.slice, int(tmp)) + return nil } diff --git a/flag_string_slice.go b/flag_string_slice.go index a3a263b2d0..0835833e0e 100644 --- a/flag_string_slice.go +++ b/flag_string_slice.go @@ -132,7 +132,6 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { } set.Var(f.Value, name, f.Usage) } - return nil } diff --git a/flag_test.go b/flag_test.go index cfc5ca89c2..b4b27396f0 100644 --- a/flag_test.go +++ b/flag_test.go @@ -346,7 +346,6 @@ var stringSliceFlagTests = []struct { value *StringSlice expected string }{ - {"foo", nil, NewStringSlice(""), "--foo value\t"}, {"f", nil, NewStringSlice(""), "-f value\t"}, {"f", nil, NewStringSlice("Lipstick"), "-f value\t(default: \"Lipstick\")"}, @@ -1572,7 +1571,6 @@ func TestParseGenericFromEnv(t *testing.T) { os.Clearenv() _ = os.Setenv("APP_SERVE", "20,30") _ = (&App{ - Flags: []Flag{ &GenericFlag{ Name: "serve", diff --git a/help.go b/help.go index 33238171c4..2940e076ef 100644 --- a/help.go +++ b/help.go @@ -243,6 +243,7 @@ func ShowCommandCompletions(ctx *Context, command string) { DefaultCompleteWithFlags(c)(ctx) } } + } func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) { diff --git a/template.go b/template.go index 558ab504e1..78e182f5c4 100644 --- a/template.go +++ b/template.go @@ -62,9 +62,10 @@ USAGE: {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}} COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{end}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}} -{{end}}{{if .VisibleFlags}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + OPTIONS: {{range .VisibleFlags}}{{.}} {{end}}{{end}}