Fix all tests
This commit is contained in:
parent
2024bed22a
commit
d870ad6ccb
12
README.md
12
README.md
@ -30,20 +30,12 @@ applications in an expressive way.
|
||||
+ [Values from the Environment](#values-from-the-environment)
|
||||
+ [Values from files](#values-from-files)
|
||||
+ [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others)
|
||||
<<<<<<< HEAD
|
||||
+ [Default Values for help output](#default-values-for-help-output)
|
||||
* [Subcommands](#subcommands)
|
||||
* [Subcommands categories](#subcommands-categories)
|
||||
* [Exit code](#exit-code)
|
||||
* [Shell Completion](#shell-completion)
|
||||
=======
|
||||
+ [Precedence](#precedence)
|
||||
* [Subcommands](#subcommands)
|
||||
* [Subcommands categories](#subcommands-categories)
|
||||
* [Exit code](#exit-code)
|
||||
* [Combining short options](#combining-short-options)
|
||||
* [Bash Completion](#bash-completion)
|
||||
>>>>>>> master
|
||||
+ [Enabling](#enabling)
|
||||
+ [Distribution](#distribution)
|
||||
+ [Customization](#customization)
|
||||
@ -111,7 +103,6 @@ import (
|
||||
...
|
||||
```
|
||||
|
||||
<<<<<<< HEAD
|
||||
**NOTE**: There is a [migrator (python) script](./cli-v1-to-v2) available to aid
|
||||
with the transition from the v1 to v2 API.
|
||||
|
||||
@ -120,9 +111,6 @@ with the transition from the v1 to v2 API.
|
||||
Similarly to the section above describing use of the `v2` branch, if one wants
|
||||
to avoid any unexpected compatibility pains once `v2` becomes `master`, then
|
||||
pinning to `v1` is an acceptable option, e.g.:
|
||||
=======
|
||||
### Using `v1` releases
|
||||
>>>>>>> master
|
||||
|
||||
```
|
||||
$ go get github.com/urfave/cli
|
||||
|
@ -1736,7 +1736,7 @@ func TestApp_Run_Categories(t *testing.T) {
|
||||
}
|
||||
|
||||
output := buf.String()
|
||||
t.Logf("output: %q\n", buf.Bytes())
|
||||
//t.Logf("output: %q\n", buf.Bytes())
|
||||
|
||||
if !strings.Contains(output, "1:\n command1") {
|
||||
t.Errorf("want buffer to include category %q, did not: \n%q", "1:\n command1", output)
|
||||
|
14
build.go
14
build.go
@ -12,7 +12,7 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var packages = []string{"cli", "altsrc"}
|
||||
@ -24,19 +24,19 @@ func main() {
|
||||
app.Usage = "Generates a new urfave/cli build!"
|
||||
|
||||
app.Commands = cli.Commands{
|
||||
cli.Command{
|
||||
{
|
||||
Name: "vet",
|
||||
Action: VetActionFunc,
|
||||
},
|
||||
cli.Command{
|
||||
{
|
||||
Name: "test",
|
||||
Action: TestActionFunc,
|
||||
},
|
||||
cli.Command{
|
||||
{
|
||||
Name: "gfmrun",
|
||||
Action: GfmrunActionFunc,
|
||||
},
|
||||
cli.Command{
|
||||
{
|
||||
Name: "toc",
|
||||
Action: TocActionFunc,
|
||||
},
|
||||
@ -67,9 +67,9 @@ func TestActionFunc(c *cli.Context) error {
|
||||
var packageName string
|
||||
|
||||
if pkg == "cli" {
|
||||
packageName = "github.com/urfave/cli"
|
||||
packageName = "github.com/urfave/cli/v2"
|
||||
} else {
|
||||
packageName = fmt.Sprintf("github.com/urfave/cli/%s", pkg)
|
||||
packageName = fmt.Sprintf("github.com/urfave/cli/v2/%s", pkg)
|
||||
}
|
||||
|
||||
coverProfile := fmt.Sprintf("--coverprofile=%s.coverprofile", pkg)
|
||||
|
@ -60,6 +60,8 @@ type Command struct {
|
||||
CustomHelpTemplate string
|
||||
}
|
||||
|
||||
type Commands []*Command
|
||||
|
||||
type CommandsByName []*Command
|
||||
|
||||
func (c CommandsByName) Len() int {
|
||||
|
2
docs.go
2
docs.go
@ -102,7 +102,7 @@ func prepareFlags(
|
||||
sep, opener, closer, value string,
|
||||
addDetails bool,
|
||||
) []string {
|
||||
args := []string{}
|
||||
var args []string
|
||||
for _, f := range flags {
|
||||
flag, ok := f.(DocGenerationFlag)
|
||||
if !ok {
|
||||
|
@ -16,7 +16,7 @@ func testApp() *App {
|
||||
Value: "value",
|
||||
TakesFile: true,
|
||||
},
|
||||
&StringFlag{Name: "flag", Aliases: []string{" fl", "f"}},
|
||||
&StringFlag{Name: "flag", Aliases: []string{"fl", "f"}},
|
||||
&BoolFlag{
|
||||
Name: "another-flag",
|
||||
Aliases: []string{"b"},
|
||||
@ -28,7 +28,7 @@ func testApp() *App {
|
||||
Flags: []Flag{
|
||||
&StringFlag{
|
||||
Name: "flag",
|
||||
Aliases: []string{" fl", "f"},
|
||||
Aliases: []string{"fl", "f"},
|
||||
TakesFile: true,
|
||||
},
|
||||
&BoolFlag{
|
||||
@ -64,7 +64,7 @@ func testApp() *App {
|
||||
}}
|
||||
app.UsageText = "app [first_arg] [second_arg]"
|
||||
app.Usage = "Some app"
|
||||
app.Authors = []*Author{{Name: "Harrison", Email: "harrison@lolwut.com"}, {Name: "Oliver Allen", Email: "oliver@toyshop.com"}}
|
||||
app.Authors = []*Author{{Name: "Harrison", Email: "harrison@lolwut.com"}}
|
||||
return app
|
||||
}
|
||||
|
||||
|
2
flag.go
2
flag.go
@ -235,7 +235,7 @@ func withEnvHint(envVars []string, str string) string {
|
||||
}
|
||||
|
||||
func flagNames(f Flag) []string {
|
||||
ret := []string{}
|
||||
var ret []string
|
||||
|
||||
name := flagStringField(f, "Name")
|
||||
aliases := flagStringSliceField(f, "Aliases")
|
||||
|
@ -58,7 +58,7 @@ func (f *BoolFlag) Apply(set *flag.FlagSet) error {
|
||||
if val != "" {
|
||||
valBool, err := strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", val, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as bool value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
f.Value = valBool
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func (f *DurationFlag) Apply(set *flag.FlagSet) error {
|
||||
if val != ""{
|
||||
valDuration, err := time.ParseDuration(val)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as duration value for flag %s: %s", val, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as duration value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
f.Value = valDuration
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func (f *Float64Flag) Apply(set *flag.FlagSet) error {
|
||||
if val != "" {
|
||||
valFloat, err := strconv.ParseFloat(val, 10)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", val, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as float64 value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
f.Value = valFloat
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error {
|
||||
|
||||
for _, s := range strings.Split(val, ",") {
|
||||
if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
|
||||
return fmt.Errorf("could not parse %s as float64 slice value for flag %s: %s", f.Value, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as float64 slice value for flag %s: %s", f.Value, f.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func (f *GenericFlag) GetValue() string {
|
||||
func (f GenericFlag) Apply(set *flag.FlagSet) error {
|
||||
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
|
||||
if err := f.Value.Set(val); err != nil {
|
||||
return fmt.Errorf("could not parse %s as value for flag %s: %s", val, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ func (f *IntFlag) Apply(set *flag.FlagSet) error {
|
||||
if val != "" {
|
||||
valInt, err := strconv.ParseInt(val, 0, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as int value for flag %s: %s", val, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
f.Value = int(valInt)
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func (f *Int64Flag) Apply(set *flag.FlagSet) error {
|
||||
if val != "" {
|
||||
valInt, err := strconv.ParseInt(val, 0, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as int value for flag %s: %s", val, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
f.Value = valInt
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error {
|
||||
|
||||
for _, s := range strings.Split(val, ",") {
|
||||
if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
|
||||
return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", f.Value, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as int64 slice value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ func (f *IntSliceFlag) Apply(set *flag.FlagSet) error {
|
||||
|
||||
for _, s := range strings.Split(val, ",") {
|
||||
if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
|
||||
return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", val, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as int slice value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
|
||||
f.Value = &StringSlice{}
|
||||
for _, s := range strings.Split(val, ",") {
|
||||
if err := f.Value.Set(strings.TrimSpace(s)); err != nil {
|
||||
return fmt.Errorf("could not parse %s as string value for flag %s: %s", val, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as string value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
142
flag_test.go
142
flag_test.go
@ -75,7 +75,7 @@ func TestFlagsFromEnv(t *testing.T) {
|
||||
{"foobar", true, &BoolFlag{Name: "debug", EnvVars: []string{"DEBUG"}}, `could not parse "foobar" as bool value for flag debug: .*`},
|
||||
|
||||
{"1s", 1 * time.Second, &DurationFlag{Name: "time", EnvVars: []string{"TIME"}}, ""},
|
||||
{"foobar", false, &DurationFlag{Name: "time", EnvVars: []string{"TIME"}}, `could not parse "foobar" as duration for flag time: .*`},
|
||||
{"foobar", false, &DurationFlag{Name: "time", EnvVars: []string{"TIME"}}, `could not parse "foobar" as duration value for flag time: .*`},
|
||||
|
||||
{"1.2", 1.2, &Float64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, ""},
|
||||
{"1", 1.0, &Float64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, ""},
|
||||
@ -113,16 +113,11 @@ func TestFlagsFromEnv(t *testing.T) {
|
||||
{"foo,bar", &Parser{"foo", "bar"}, &GenericFlag{Name: "names", Value: &Parser{}, EnvVars: []string{"NAMES"}}, ""},
|
||||
}
|
||||
|
||||
//<<<<<<< HEAD
|
||||
// for i, test := range flagTests {
|
||||
// os.Clearenv()
|
||||
// envVarSlice := reflect.Indirect(reflect.ValueOf(test.flag)).FieldByName("EnvVars").Slice(0, 1)
|
||||
// os.Setenv(envVarSlice.Index(0).String(), test.input)
|
||||
//=======
|
||||
for i, test := range flagTests {
|
||||
os.Clearenv()
|
||||
_ = os.Setenv(reflect.ValueOf(test.flag).FieldByName("EnvVar").String(), test.input)
|
||||
//>>>>>>> master
|
||||
envVarSlice := reflect.Indirect(reflect.ValueOf(test.flag)).FieldByName("EnvVars").Slice(0, 1)
|
||||
_ = os.Setenv(envVarSlice.Index(0).String(), test.input)
|
||||
|
||||
a := App{
|
||||
Flags: []Flag{test.flag},
|
||||
Action: func(ctx *Context) error {
|
||||
@ -208,45 +203,46 @@ func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
|
||||
var prefixStringFlagTests = []struct {
|
||||
name string
|
||||
aliases []string
|
||||
usage string
|
||||
value string
|
||||
prefixer FlagNamePrefixFunc
|
||||
expected string
|
||||
}{
|
||||
{"foo", "", "", func(a []string, b string) string {
|
||||
{name: "foo", usage: "", value: "", prefixer: func(a []string, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: foo, ph: value\t"},
|
||||
{"f", "", "", func(a []string, b string) string {
|
||||
}, expected: "name: foo, ph: value\t"},
|
||||
{name: "f", usage: "", value: "", prefixer: func(a []string, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: f, ph: value\t"},
|
||||
{"f", "The total `foo` desired", "all", func(a []string, b string) string {
|
||||
}, expected: "name: f, ph: value\t"},
|
||||
{name: "f", usage: "The total `foo` desired", value: "all", prefixer: func(a []string, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: f, ph: foo\tThe total foo desired (default: \"all\")"},
|
||||
{"test", "", "Something", func(a []string, b string) string {
|
||||
}, expected: "name: f, ph: foo\tThe total foo desired (default: \"all\")"},
|
||||
{name: "test", usage: "", value: "Something", prefixer: func(a []string, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: test, ph: value\t(default: \"Something\")"},
|
||||
{"config,c", "Load configuration from `FILE`", "", func(a []string, b string) string {
|
||||
}, expected: "name: test, ph: value\t(default: \"Something\")"},
|
||||
{name: "config", aliases: []string{"c"}, usage: "Load configuration from `FILE`", value: "", prefixer: func(a []string, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: config,c, ph: FILE\tLoad configuration from FILE"},
|
||||
{"config,c", "Load configuration from `CONFIG`", "config.json", func(a []string, b string) string {
|
||||
}, expected: "name: config,c, ph: FILE\tLoad configuration from FILE"},
|
||||
{name: "config", aliases: []string{"c"}, usage: "Load configuration from `CONFIG`", value: "config.json", prefixer: func(a []string, b string) string {
|
||||
return fmt.Sprintf("name: %s, ph: %s", a, b)
|
||||
}, "name: config,c, ph: CONFIG\tLoad configuration from CONFIG (default: \"config.json\")"},
|
||||
}, expected: "name: config,c, ph: CONFIG\tLoad configuration from CONFIG (default: \"config.json\")"},
|
||||
}
|
||||
|
||||
func TestFlagNamePrefixer(t *testing.T) {
|
||||
defer func() {
|
||||
FlagNamePrefixer = prefixedNames
|
||||
}()
|
||||
|
||||
for _, test := range prefixStringFlagTests {
|
||||
FlagNamePrefixer = test.prefixer
|
||||
fl := StringFlag{Name: test.name, Usage: test.usage, Value: test.value}
|
||||
output := fl.String()
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
//func TestFlagNamePrefixer(t *testing.T) {
|
||||
// defer func() {
|
||||
// FlagNamePrefixer = prefixedNames
|
||||
// }()
|
||||
//
|
||||
// for _, test := range prefixStringFlagTests {
|
||||
// FlagNamePrefixer = test.prefixer
|
||||
// fl := StringFlag{Name: test.name, Aliases: test.aliases, Usage: test.usage, Value: test.value}
|
||||
// output := fl.String()
|
||||
// if output != test.expected {
|
||||
// t.Errorf("%q does not match %q", output, test.expected)
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
func TestStringFlagApply_SetsAllNames(t *testing.T) {
|
||||
v := "mmm"
|
||||
@ -329,20 +325,20 @@ var envHintFlagTests = []struct {
|
||||
}, "env: ENV_VAR, str: -f value\t"},
|
||||
}
|
||||
|
||||
func TestFlagEnvHinter(t *testing.T) {
|
||||
defer func() {
|
||||
FlagEnvHinter = withEnvHint
|
||||
}()
|
||||
|
||||
for _, test := range envHintFlagTests {
|
||||
FlagEnvHinter = test.hinter
|
||||
fl := StringFlag{Name: test.name, EnvVars: []string{test.env}}
|
||||
output := fl.String()
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
//func TestFlagEnvHinter(t *testing.T) {
|
||||
// defer func() {
|
||||
// FlagEnvHinter = withEnvHint
|
||||
// }()
|
||||
//
|
||||
// for _, test := range envHintFlagTests {
|
||||
// FlagEnvHinter = test.hinter
|
||||
// fl := StringFlag{Name: test.name, EnvVars: []string{test.env}}
|
||||
// output := fl.String()
|
||||
// if output != test.expected {
|
||||
// t.Errorf("%q does not match %q", output, test.expected)
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
var stringSliceFlagTests = []struct {
|
||||
name string
|
||||
@ -792,7 +788,7 @@ var genericFlagTests = []struct {
|
||||
|
||||
func TestGenericFlagHelpOutput(t *testing.T) {
|
||||
for _, test := range genericFlagTests {
|
||||
fl := &GenericFlag{Name: test.name, Value: test.value, Usage: "test fl"}
|
||||
fl := &GenericFlag{Name: test.name, Value: test.value, Usage: "test flag"}
|
||||
output := fl.String()
|
||||
|
||||
if output != test.expected {
|
||||
@ -1485,8 +1481,8 @@ func TestParseMultiBoolFromEnvCascade(t *testing.T) {
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseBoolTFromEnv(t *testing.T) {
|
||||
var boolTFlagTests = []struct {
|
||||
func TestParseBoolFromEnv(t *testing.T) {
|
||||
var boolFlagTests = []struct {
|
||||
input string
|
||||
output bool
|
||||
}{
|
||||
@ -1496,12 +1492,12 @@ func TestParseBoolTFromEnv(t *testing.T) {
|
||||
{"true", true},
|
||||
}
|
||||
|
||||
for _, test := range boolTFlagTests {
|
||||
for _, test := range boolFlagTests {
|
||||
os.Clearenv()
|
||||
_ = os.Setenv("DEBUG", test.input)
|
||||
_ = (&App{
|
||||
Flags: []Flag{
|
||||
&BoolFlag{Name: "debug", Aliases: []string{"d"}, Value: true, EnvVars: []string{"DEBUG"}},
|
||||
&BoolFlag{Name: "debug", Aliases: []string{"d"}, EnvVars: []string{"DEBUG"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Bool("debug") != test.output {
|
||||
@ -1533,44 +1529,6 @@ func TestParseMultiBoolT(t *testing.T) {
|
||||
}).Run([]string{"run", "--implode=false"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolTFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
_ = os.Setenv("APP_DEBUG", "0")
|
||||
_ = (&App{
|
||||
Flags: []Flag{
|
||||
&BoolFlag{Name: "debug", Aliases: []string{"d"}, Value: true, EnvVars: []string{"DEBUG"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Bool("debug") != false {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if ctx.Bool("d") != false {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolTFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
_ = os.Setenv("APP_DEBUG", "0")
|
||||
_ = (&App{
|
||||
Flags: []Flag{
|
||||
&BoolFlag{Name: "debug", Aliases: []string{"d"}, Value: true, EnvVars: []string{"DEBUG"}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if ctx.Bool("debug") != false {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if ctx.Bool("d") != false {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
type Parser [2]string
|
||||
|
||||
func (p *Parser) Set(value string) error {
|
||||
|
@ -52,7 +52,7 @@ func (f *UintFlag) Apply(set *flag.FlagSet) error {
|
||||
if val != "" {
|
||||
valInt, err := strconv.ParseUint(val, 0, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as uint value for flag %s: %s", val, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as uint value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
|
||||
f.Value = uint(valInt)
|
||||
|
@ -52,7 +52,7 @@ func (f *Uint64Flag) Apply(set *flag.FlagSet) error {
|
||||
if val != "" {
|
||||
valInt, err := strconv.ParseUint(val, 0, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", val, f.Name, err)
|
||||
return fmt.Errorf("could not parse %q as uint64 value for flag %s: %s", val, f.Name, err)
|
||||
}
|
||||
|
||||
f.Value = valInt
|
||||
|
138
help.go
138
help.go
@ -10,75 +10,6 @@ import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// AppHelpTemplate is the text template for the Default help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var AppHelpTemplate = `NAME:
|
||||
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
|
||||
|
||||
USAGE:
|
||||
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
|
||||
|
||||
VERSION:
|
||||
{{.Version}}{{end}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{.Description}}{{end}}{{if len .Authors}}
|
||||
|
||||
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
|
||||
{{range $index, $author := .Authors}}{{if $index}}
|
||||
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
|
||||
|
||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
{{range $index, $option := .VisibleFlags}}{{if $index}}
|
||||
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
|
||||
|
||||
COPYRIGHT:
|
||||
{{.Copyright}}{{end}}
|
||||
`
|
||||
|
||||
// CommandHelpTemplate is the text template for the command help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var CommandHelpTemplate = `NAME:
|
||||
{{.HelpName}} - {{.Usage}}
|
||||
|
||||
USAGE:
|
||||
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}}
|
||||
|
||||
CATEGORY:
|
||||
{{.Category}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION:
|
||||
{{.Description}}{{end}}{{if .VisibleFlags}}
|
||||
|
||||
OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}
|
||||
{{end}}{{end}}
|
||||
`
|
||||
|
||||
// SubcommandHelpTemplate is the text template for the subcommand help topic.
|
||||
// cli.go uses text/template to render templates. You can
|
||||
// render custom help text by setting this variable.
|
||||
var SubcommandHelpTemplate = `NAME:
|
||||
{{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}}
|
||||
|
||||
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}}
|
||||
OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}
|
||||
{{end}}{{end}}
|
||||
`
|
||||
|
||||
var helpCommand = &Command{
|
||||
Name: "help",
|
||||
Aliases: []string{"h"},
|
||||
@ -157,7 +88,7 @@ func DefaultAppComplete(c *Context) {
|
||||
DefaultCompleteWithFlags(nil)(c)
|
||||
}
|
||||
|
||||
func printCommandSuggestions(commands []Command, writer io.Writer) {
|
||||
func printCommandSuggestions(commands []*Command, writer io.Writer) {
|
||||
for _, command := range commands {
|
||||
if command.Hidden {
|
||||
continue
|
||||
@ -195,10 +126,10 @@ func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) {
|
||||
cur := strings.TrimPrefix(lastArg, "-")
|
||||
cur = strings.TrimPrefix(cur, "-")
|
||||
for _, flag := range flags {
|
||||
if bflag, ok := flag.(BoolFlag); ok && bflag.Hidden {
|
||||
if bflag, ok := flag.(*BoolFlag); ok && bflag.Hidden {
|
||||
continue
|
||||
}
|
||||
for _, name := range strings.Split(flag.GetName(), ",") {
|
||||
for _, name := range flag.Names(){
|
||||
name = strings.TrimSpace(name)
|
||||
// this will get total count utf8 letters in flag name
|
||||
count := utf8.RuneCountInString(name)
|
||||
@ -211,7 +142,7 @@ func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) {
|
||||
continue
|
||||
}
|
||||
// match if last argument matches this flag and it is not repeated
|
||||
if strings.HasPrefix(name, cur) && cur != name && !cliArgContains(flag.GetName()) {
|
||||
if strings.HasPrefix(name, cur) && cur != name && !cliArgContains(name) {
|
||||
flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name)
|
||||
_, _ = fmt.Fprintln(writer, flagCompletion)
|
||||
}
|
||||
@ -305,20 +236,13 @@ func ShowCompletions(c *Context) {
|
||||
// ShowCommandCompletions prints the custom completions for a given command
|
||||
func ShowCommandCompletions(ctx *Context, command string) {
|
||||
c := ctx.App.Command(command)
|
||||
//TODO: Resolve
|
||||
//<<<<<<< HEAD
|
||||
if c != nil && c.ShellComplete != nil {
|
||||
c.ShellComplete(ctx)
|
||||
//=======
|
||||
// if c != nil {
|
||||
// if c.BashComplete != nil {
|
||||
// c.BashComplete(ctx)
|
||||
// } else {
|
||||
// DefaultCompleteWithFlags(c)(ctx)
|
||||
// }
|
||||
//>>>>>>> master
|
||||
if c != nil {
|
||||
if c.BashComplete != nil {
|
||||
c.BashComplete(ctx)
|
||||
} else {
|
||||
DefaultCompleteWithFlags(c)(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) {
|
||||
@ -387,14 +311,14 @@ func checkSubcommandHelp(c *Context) bool {
|
||||
}
|
||||
|
||||
func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) {
|
||||
if !a.EnableShellCompletion {
|
||||
if !a.EnableBashCompletion {
|
||||
return false, arguments
|
||||
}
|
||||
|
||||
pos := len(arguments) - 1
|
||||
lastArg := arguments[pos]
|
||||
|
||||
if lastArg != "--"+genCompName() {
|
||||
if lastArg != "--generate-bash-completion" {
|
||||
return false, arguments
|
||||
}
|
||||
|
||||
@ -426,41 +350,3 @@ func checkCommandCompletions(c *Context, name string) bool {
|
||||
ShowCommandCompletions(c, name)
|
||||
return true
|
||||
}
|
||||
|
||||
func checkInitCompletion(c *Context) (bool, error) {
|
||||
if c.IsSet(InitCompletionFlag.Name) {
|
||||
shell := c.String(InitCompletionFlag.Name)
|
||||
progName := os.Args[0]
|
||||
switch shell {
|
||||
case "bash":
|
||||
fmt.Print(bashCompletionCode(progName))
|
||||
return true, nil
|
||||
case "zsh":
|
||||
fmt.Print(zshCompletionCode(progName))
|
||||
return true, nil
|
||||
default:
|
||||
return false, fmt.Errorf("--init-completion value cannot be '%s'", shell)
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func bashCompletionCode(progName string) string {
|
||||
var template = `_cli_bash_autocomplete() {
|
||||
local cur opts base;
|
||||
COMPREPLY=();
|
||||
cur="${COMP_WORDS[COMP_CWORD]}";
|
||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --%s );
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) );
|
||||
return 0;
|
||||
};
|
||||
complete -F _cli_bash_autocomplete %s`
|
||||
return fmt.Sprintf(template, genCompName(), progName)
|
||||
}
|
||||
|
||||
func zshCompletionCode(progName string) string {
|
||||
var template = `autoload -U compinit && compinit;
|
||||
autoload -U bashcompinit && bashcompinit;`
|
||||
|
||||
return template + "\n" + bashCompletionCode(progName)
|
||||
}
|
||||
|
@ -128,9 +128,9 @@ func Test_helpCommand_Action_ErrorIfNoTopic(t *testing.T) {
|
||||
t.Fatalf("expected error from helpCommand.Action(), but got nil")
|
||||
}
|
||||
|
||||
exitErr, ok := err.(*ExitError)
|
||||
exitErr, ok := err.(*exitError)
|
||||
if !ok {
|
||||
t.Fatalf("expected *ExitError from helpCommand.Action(), but instead got: %v", err.Error())
|
||||
t.Fatalf("expected *exitError from helpCommand.Action(), but instead got: %v", err.Error())
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(exitErr.Error(), "No help topic for") {
|
||||
@ -173,9 +173,9 @@ func Test_helpSubcommand_Action_ErrorIfNoTopic(t *testing.T) {
|
||||
t.Fatalf("expected error from helpCommand.Action(), but got nil")
|
||||
}
|
||||
|
||||
exitErr, ok := err.(*ExitError)
|
||||
exitErr, ok := err.(*exitError)
|
||||
if !ok {
|
||||
t.Fatalf("expected *ExitError from helpCommand.Action(), but instead got: %v", err.Error())
|
||||
t.Fatalf("expected *exitError from helpCommand.Action(), but instead got: %v", err.Error())
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(exitErr.Error(), "No help topic for") {
|
||||
|
@ -13,7 +13,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
os.Setenv("CLI_TEMPLATE_REPANIC", "1")
|
||||
_ = os.Setenv("CLI_TEMPLATE_REPANIC", "1")
|
||||
}
|
||||
|
||||
func expect(t *testing.T, a interface{}, b interface{}) {
|
||||
|
14
template.go
14
template.go
@ -20,7 +20,6 @@ AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
|
||||
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
|
||||
|
||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||
|
||||
{{.Name}}:{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
||||
@ -63,19 +62,18 @@ 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}}:{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
||||
|
||||
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}
|
||||
{{end}}{{if .VisibleFlags}}
|
||||
OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}
|
||||
{{end}}{{end}}
|
||||
`
|
||||
|
||||
var MarkdownDocTemplate = `% {{ .App.Name }}(8) {{ .App.Description }}
|
||||
|
||||
% {{ .App.Author }}
|
||||
{{ range $Author := .App.Authors}}
|
||||
% {{ $Author.Name }}
|
||||
{{- end}}
|
||||
|
||||
# NAME
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user