diff --git a/docs/v2/examples/flags.md b/docs/v2/examples/flags.md index 2e79d3460f..f3792bff4b 100644 --- a/docs/v2/examples/flags.md +++ b/docs/v2/examples/flags.md @@ -470,6 +470,8 @@ func main() { } ``` +When `Value` is not set for the flag, but a matching environment variable is found, the value from the environment will be used in the generated docs as the default value. + #### Values from files You can also have the default value set from file via `FilePath`. e.g. diff --git a/go.mod b/go.mod index 584c2c04e1..0543455d11 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/BurntSushi/toml v1.3.2 github.com/cpuguy83/go-md2man/v2 v2.0.4 - github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index fef97ed608..c7f6ef0ab4 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= -github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/godoc-current.txt b/godoc-current.txt index 4b620feeb0..3e29faabac 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -35,7 +35,7 @@ var AppHelpTemplate = `NAME: {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}}[arguments...]{{end}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Args}} [arguments...]{{end}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} @@ -136,7 +136,7 @@ var SubcommandHelpTemplate = `NAME: {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}}[arguments...]{{end}}{{end}}{{end}}{{if .Description}} + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}command [command options]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Args}} [arguments...]{{end}}{{end}}{{end}}{{if .Description}} DESCRIPTION: {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} diff --git a/help.go b/help.go index 640e290452..874be941c0 100644 --- a/help.go +++ b/help.go @@ -248,7 +248,6 @@ func ShowCommandHelpAndExit(c *Context, command string, code int) { // ShowCommandHelp prints help for the given command func ShowCommandHelp(ctx *Context, command string) error { - commands := ctx.App.Commands if ctx.Command.Subcommands != nil { commands = ctx.Command.Subcommands @@ -337,7 +336,6 @@ func ShowCommandCompletions(ctx *Context, command string) { DefaultCompleteWithFlags(c)(ctx) } } - } // printHelpCustom is the default implementation of HelpPrinterCustom. @@ -345,7 +343,6 @@ func ShowCommandCompletions(ctx *Context, command string) { // The customFuncs map will be combined with a default template.FuncMap to // allow using arbitrary functions in template rendering. func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs map[string]interface{}) { - const maxLineLength = 10000 funcMap := template.FuncMap{ @@ -450,6 +447,15 @@ func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { return false, arguments } + for _, arg := range arguments { + // If arguments include "--", shell completion is disabled + // because after "--" only positional arguments are accepted. + // https://unix.stackexchange.com/a/11382 + if arg == "--" { + return false, arguments + } + } + return true, arguments[:pos] } @@ -499,7 +505,6 @@ func wrap(input string, offset int, wrapAt int) string { ss = append(ss, wrapped) } else { ss = append(ss, padding+wrapped) - } } diff --git a/help_test.go b/help_test.go index a39f818798..8a856258ae 100644 --- a/help_test.go +++ b/help_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "os" + "reflect" "runtime" "strings" "testing" @@ -1349,7 +1350,6 @@ func TestWrap(t *testing.T) { } func TestWrappedHelp(t *testing.T) { - // Reset HelpPrinter after this test. defer func(old helpPrinter) { HelpPrinter = old @@ -1359,7 +1359,8 @@ func TestWrappedHelp(t *testing.T) { app := &App{ Writer: output, Flags: []Flag{ - &BoolFlag{Name: "foo", + &BoolFlag{ + Name: "foo", Aliases: []string{"h"}, Usage: "here's a really long help text line, let's see where it wraps. blah blah blah and so on.", }, @@ -1443,7 +1444,6 @@ COPYRIGHT: } func TestWrappedCommandHelp(t *testing.T) { - // Reset HelpPrinter after this test. defer func(old helpPrinter) { HelpPrinter = old @@ -1504,7 +1504,6 @@ OPTIONS: } func TestWrappedSubcommandHelp(t *testing.T) { - // Reset HelpPrinter after this test. defer func(old helpPrinter) { HelpPrinter = old @@ -1573,7 +1572,6 @@ OPTIONS: } func TestWrappedHelpSubcommand(t *testing.T) { - // Reset HelpPrinter after this test. defer func(old helpPrinter) { HelpPrinter = old @@ -1714,3 +1712,65 @@ GLOBAL OPTIONS: output.String(), expected) } } + +func Test_checkShellCompleteFlag(t *testing.T) { + t.Parallel() + tests := []struct { + name string + app *App + arguments []string + wantShellCompletion bool + wantArgs []string + }{ + { + name: "disable bash completion", + arguments: []string{"--generate-bash-completion"}, + app: &App{}, + wantShellCompletion: false, + wantArgs: []string{"--generate-bash-completion"}, + }, + { + name: "--generate-bash-completion isn't used", + arguments: []string{"foo"}, + app: &App{ + EnableBashCompletion: true, + }, + wantShellCompletion: false, + wantArgs: []string{"foo"}, + }, + { + name: "arguments include double dash", + arguments: []string{"--", "foo", "--generate-bash-completion"}, + app: &App{ + EnableBashCompletion: true, + }, + wantShellCompletion: false, + wantArgs: []string{"--", "foo", "--generate-bash-completion"}, + }, + { + name: "--generate-bash-completion", + arguments: []string{"foo", "--generate-bash-completion"}, + app: &App{ + EnableBashCompletion: true, + }, + wantShellCompletion: true, + wantArgs: []string{"foo"}, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + shellCompletion, args := checkShellCompleteFlag(tt.app, tt.arguments) + if tt.wantShellCompletion != shellCompletion { + t.Errorf("Unexpected shell completion, got:\n%v\nexpected: %v", + shellCompletion, tt.wantShellCompletion) + } + if !reflect.DeepEqual(tt.wantArgs, args) { + t.Errorf("Unexpected arguments, got:\n%v\nexpected: %v", + args, tt.wantArgs) + } + }) + } +} diff --git a/template.go b/template.go index 5748f4c201..8abc5ba421 100644 --- a/template.go +++ b/template.go @@ -1,7 +1,7 @@ package cli var helpNameTemplate = `{{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}` -var usageTemplate = `{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}}{{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}} [arguments...]{{end}}{{end}}{{end}}` +var usageTemplate = `{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Args}} [arguments...]{{end}}{{end}}{{end}}` var descriptionTemplate = `{{wrap .Description 3}}` var authorsTemplate = `{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: {{range $index, $author := .Authors}}{{if $index}} @@ -35,7 +35,7 @@ var AppHelpTemplate = `NAME: {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}}[arguments...]{{end}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Args}} [arguments...]{{end}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} @@ -83,7 +83,7 @@ var SubcommandHelpTemplate = `NAME: {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}}[arguments...]{{end}}{{end}}{{end}}{{if .Description}} + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}command [command options]{{end}}{{if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{if .Args}} [arguments...]{{end}}{{end}}{{end}}{{if .Description}} DESCRIPTION: {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}}