Fix all tests

This commit is contained in:
Ajitem Sahasrabuddhe 2019-09-15 14:52:46 +05:30
parent 2024bed22a
commit d870ad6ccb
No known key found for this signature in database
GPG Key ID: 782DEBC01D3967A5
24 changed files with 100 additions and 268 deletions

View File

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

View File

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

View File

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

View File

@ -60,6 +60,8 @@ type Command struct {
CustomHelpTemplate string
}
type Commands []*Command
type CommandsByName []*Command
func (c CommandsByName) Len() int {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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
View File

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

View File

@ -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") {

View File

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

View File

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