Unverified Commit 308647b0 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #60135 from superbrothers/fix-completion-error-in-bash-3

Automatic merge from submit-queue (batch tested with PRs 60346, 60135, 60289, 59643, 52640). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Update vendor spf13/cobra to fix completion error in bash 3 **What this PR does / why we need it**: This PR updates vendor spf13/cobra to fix completion error in bash 3. /ref spf13/cobra#628 /cc @eparis **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: Fixes kubernetes/kubectl#121, kubernetes/kubernetes#29322, kubernetes/kubernetes#32676. **Special notes for your reviewer**: **Release note**: ```release-note NONE ```
parents 71c2135c e604a7fd
...@@ -2567,13 +2567,13 @@ ...@@ -2567,13 +2567,13 @@
}, },
{ {
"ImportPath": "github.com/spf13/cobra", "ImportPath": "github.com/spf13/cobra",
"Comment": "v0.0.1-10-g19e54c4", "Comment": "v0.0.1-28-gfd32f09",
"Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f" "Rev": "fd32f09af19efc9b1279c54e0d8ed23f66232a15"
}, },
{ {
"ImportPath": "github.com/spf13/cobra/doc", "ImportPath": "github.com/spf13/cobra/doc",
"Comment": "v0.0.1-10-g19e54c4", "Comment": "v0.0.1-28-gfd32f09",
"Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f" "Rev": "fd32f09af19efc9b1279c54e0d8ed23f66232a15"
}, },
{ {
"ImportPath": "github.com/spf13/jwalterweatherman", "ImportPath": "github.com/spf13/jwalterweatherman",
......
...@@ -584,7 +584,7 @@ ...@@ -584,7 +584,7 @@
}, },
{ {
"ImportPath": "github.com/spf13/cobra", "ImportPath": "github.com/spf13/cobra",
"Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f" "Rev": "fd32f09af19efc9b1279c54e0d8ed23f66232a15"
}, },
{ {
"ImportPath": "github.com/spf13/pflag", "ImportPath": "github.com/spf13/pflag",
......
...@@ -268,7 +268,7 @@ ...@@ -268,7 +268,7 @@
}, },
{ {
"ImportPath": "github.com/spf13/cobra", "ImportPath": "github.com/spf13/cobra",
"Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f" "Rev": "fd32f09af19efc9b1279c54e0d8ed23f66232a15"
}, },
{ {
"ImportPath": "github.com/spf13/pflag", "ImportPath": "github.com/spf13/pflag",
......
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
}, },
{ {
"ImportPath": "github.com/spf13/cobra", "ImportPath": "github.com/spf13/cobra",
"Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f" "Rev": "fd32f09af19efc9b1279c54e0d8ed23f66232a15"
}, },
{ {
"ImportPath": "github.com/spf13/pflag", "ImportPath": "github.com/spf13/pflag",
......
...@@ -20,6 +20,7 @@ Many of the most widely used Go projects are built using Cobra including: ...@@ -20,6 +20,7 @@ Many of the most widely used Go projects are built using Cobra including:
* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) * [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
* [rclone](http://rclone.org/) * [rclone](http://rclone.org/)
* [nehm](https://github.com/bogem/nehm) * [nehm](https://github.com/bogem/nehm)
* [Pouch](https://github.com/alibaba/pouch)
[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra) [![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra)
[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra) [![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra)
...@@ -158,10 +159,7 @@ import ( ...@@ -158,10 +159,7 @@ import (
) )
func main() { func main() {
if err := cmd.RootCmd.Execute(); err != nil { cmd.Execute()
fmt.Println(err)
os.Exit(1)
}
} }
``` ```
...@@ -174,7 +172,7 @@ commands you want. It's the easiest way to incorporate Cobra into your applicati ...@@ -174,7 +172,7 @@ commands you want. It's the easiest way to incorporate Cobra into your applicati
## Using the Cobra Library ## Using the Cobra Library
To manually implement Cobra you need to create a bare main.go file and a RootCmd file. To manually implement Cobra you need to create a bare main.go file and a rootCmd file.
You will optionally provide additional commands as you see fit. You will optionally provide additional commands as you see fit.
### Create rootCmd ### Create rootCmd
...@@ -184,7 +182,7 @@ Cobra doesn't require any special constructors. Simply create your commands. ...@@ -184,7 +182,7 @@ Cobra doesn't require any special constructors. Simply create your commands.
Ideally you place this in app/cmd/root.go: Ideally you place this in app/cmd/root.go:
```go ```go
var RootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
Use: "hugo", Use: "hugo",
Short: "Hugo is a very fast static site generator", Short: "Hugo is a very fast static site generator",
Long: `A Fast and Flexible Static Site Generator built with Long: `A Fast and Flexible Static Site Generator built with
...@@ -194,6 +192,13 @@ var RootCmd = &cobra.Command{ ...@@ -194,6 +192,13 @@ var RootCmd = &cobra.Command{
// Do Stuff Here // Do Stuff Here
}, },
} }
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
``` ```
You will additionally define flags and handle configuration in your init() function. You will additionally define flags and handle configuration in your init() function.
...@@ -212,14 +217,14 @@ import ( ...@@ -212,14 +217,14 @@ import (
func init() { func init() {
cobra.OnInitialize(initConfig) cobra.OnInitialize(initConfig)
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/") rootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)") rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration") rootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author")) viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase")) viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase"))
viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper")) viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>") viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache") viper.SetDefault("license", "apache")
} }
...@@ -267,10 +272,7 @@ import ( ...@@ -267,10 +272,7 @@ import (
) )
func main() { func main() {
if err := cmd.RootCmd.Execute(); err != nil { cmd.Execute()
fmt.Println(err)
os.Exit(1)
}
} }
``` ```
...@@ -286,12 +288,13 @@ populate it with the following: ...@@ -286,12 +288,13 @@ populate it with the following:
package cmd package cmd
import ( import (
"github.com/spf13/cobra"
"fmt" "fmt"
"github.com/spf13/cobra"
) )
func init() { func init() {
RootCmd.AddCommand(versionCmd) rootCmd.AddCommand(versionCmd)
} }
var versionCmd = &cobra.Command{ var versionCmd = &cobra.Command{
...@@ -328,7 +331,7 @@ command it's assigned to as well as every command under that command. For ...@@ -328,7 +331,7 @@ command it's assigned to as well as every command under that command. For
global flags, assign a flag as a persistent flag on the root. global flags, assign a flag as a persistent flag on the root.
```go ```go
RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
``` ```
### Local Flags ### Local Flags
...@@ -336,7 +339,7 @@ RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose out ...@@ -336,7 +339,7 @@ RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose out
A flag can also be assigned locally which will only apply to that specific command. A flag can also be assigned locally which will only apply to that specific command.
```go ```go
RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") rootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
``` ```
### Local Flag on Parent Commands ### Local Flag on Parent Commands
...@@ -359,8 +362,8 @@ You can also bind your flags with [viper](https://github.com/spf13/viper): ...@@ -359,8 +362,8 @@ You can also bind your flags with [viper](https://github.com/spf13/viper):
var author string var author string
func init() { func init() {
RootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution") rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author")) viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
} }
``` ```
...@@ -370,6 +373,15 @@ when the `--author` flag is not provided by user. ...@@ -370,6 +373,15 @@ when the `--author` flag is not provided by user.
More in [viper documentation](https://github.com/spf13/viper#working-with-flags). More in [viper documentation](https://github.com/spf13/viper#working-with-flags).
### Required flags
Flags are optional by default. If instead you wish your command to report an error
when a flag has not been set, mark it as required:
```go
rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkFlagRequired("region")
```
## Positional and Custom Arguments ## Positional and Custom Arguments
Validation of positional arguments can be specified using the `Args` field Validation of positional arguments can be specified using the `Args` field
...@@ -565,6 +577,13 @@ cmd.SetUsageFunc(f func(*Command) error) ...@@ -565,6 +577,13 @@ cmd.SetUsageFunc(f func(*Command) error)
cmd.SetUsageTemplate(s string) cmd.SetUsageTemplate(s string)
``` ```
## Version Flag
Cobra adds a top-level '--version' flag if the Version field is set on the root command.
Running an application with the '--version' flag will print the version to stdout using
the version template. The template can be customized using the
`cmd.SetVersionTemplate(s string)` function.
## PreRun and PostRun Hooks ## PreRun and PostRun Hooks
It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order: It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order:
......
...@@ -173,9 +173,9 @@ hello.yml test.json ...@@ -173,9 +173,9 @@ hello.yml test.json
So while there are many other files in the CWD it only shows me subdirs and those with valid extensions. So while there are many other files in the CWD it only shows me subdirs and those with valid extensions.
# Specifiy custom flag completion # Specify custom flag completion
Similar to the filename completion and filtering using cobra.BashCompFilenameExt, you can specifiy Similar to the filename completion and filtering using cobra.BashCompFilenameExt, you can specify
a custom flag completion function with cobra.BashCompCustom: a custom flag completion function with cobra.BashCompCustom:
```go ```go
......
...@@ -70,7 +70,8 @@ func AddTemplateFuncs(tmplFuncs template.FuncMap) { ...@@ -70,7 +70,8 @@ func AddTemplateFuncs(tmplFuncs template.FuncMap) {
} }
} }
// OnInitialize takes a series of func() arguments and appends them to a slice of func(). // OnInitialize sets the passed functions to be run when each command's
// Execute method is called.
func OnInitialize(y ...func()) { func OnInitialize(y ...func()) {
initializers = append(initializers, y...) initializers = append(initializers, y...)
} }
......
...@@ -75,6 +75,11 @@ type Command struct { ...@@ -75,6 +75,11 @@ type Command struct {
// group commands. // group commands.
Annotations map[string]string Annotations map[string]string
// Version defines the version for this command. If this value is non-empty and the command does not
// define a "version" flag, a "version" boolean flag will be added to the command and, if specified,
// will print content of the "Version" variable.
Version string
// The *Run functions are executed in the following order: // The *Run functions are executed in the following order:
// * PersistentPreRun() // * PersistentPreRun()
// * PreRun() // * PreRun()
...@@ -142,6 +147,11 @@ type Command struct { ...@@ -142,6 +147,11 @@ type Command struct {
commandsMaxNameLen int commandsMaxNameLen int
// commandsAreSorted defines, if command slice are sorted or not. // commandsAreSorted defines, if command slice are sorted or not.
commandsAreSorted bool commandsAreSorted bool
// commandCalledAs is the name or alias value used to call this command.
commandCalledAs struct {
name string
called bool
}
// args is actual args parsed from flags. // args is actual args parsed from flags.
args []string args []string
...@@ -177,6 +187,8 @@ type Command struct { ...@@ -177,6 +187,8 @@ type Command struct {
// helpCommand is command with usage 'help'. If it's not defined by user, // helpCommand is command with usage 'help'. If it's not defined by user,
// cobra uses default help command. // cobra uses default help command.
helpCommand *Command helpCommand *Command
// versionTemplate is the version template defined by user.
versionTemplate string
} }
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden // SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
...@@ -222,6 +234,11 @@ func (c *Command) SetHelpTemplate(s string) { ...@@ -222,6 +234,11 @@ func (c *Command) SetHelpTemplate(s string) {
c.helpTemplate = s c.helpTemplate = s
} }
// SetVersionTemplate sets version template to be used. Application can use it to set custom template.
func (c *Command) SetVersionTemplate(s string) {
c.versionTemplate = s
}
// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. // SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.
// The user should not have a cyclic dependency on commands. // The user should not have a cyclic dependency on commands.
func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) { func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
...@@ -411,6 +428,19 @@ func (c *Command) HelpTemplate() string { ...@@ -411,6 +428,19 @@ func (c *Command) HelpTemplate() string {
{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
} }
// VersionTemplate return version template for the command.
func (c *Command) VersionTemplate() string {
if c.versionTemplate != "" {
return c.versionTemplate
}
if c.HasParent() {
return c.parent.VersionTemplate()
}
return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}
`
}
func hasNoOptDefVal(name string, fs *flag.FlagSet) bool { func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
flag := fs.Lookup(name) flag := fs.Lookup(name)
if flag == nil { if flag == nil {
...@@ -532,6 +562,7 @@ func (c *Command) findNext(next string) *Command { ...@@ -532,6 +562,7 @@ func (c *Command) findNext(next string) *Command {
matches := make([]*Command, 0) matches := make([]*Command, 0)
for _, cmd := range c.commands { for _, cmd := range c.commands {
if cmd.Name() == next || cmd.HasAlias(next) { if cmd.Name() == next || cmd.HasAlias(next) {
cmd.commandCalledAs.name = next
return cmd return cmd
} }
if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) { if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) {
...@@ -542,6 +573,7 @@ func (c *Command) findNext(next string) *Command { ...@@ -542,6 +573,7 @@ func (c *Command) findNext(next string) *Command {
if len(matches) == 1 { if len(matches) == 1 {
return matches[0] return matches[0]
} }
return nil return nil
} }
...@@ -640,9 +672,10 @@ func (c *Command) execute(a []string) (err error) { ...@@ -640,9 +672,10 @@ func (c *Command) execute(a []string) (err error) {
c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated) c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated)
} }
// initialize help flag as the last point possible to allow for user // initialize help and version flag at the last point possible to allow for user
// overriding // overriding
c.InitDefaultHelpFlag() c.InitDefaultHelpFlag()
c.InitDefaultVersionFlag()
err = c.ParseFlags(a) err = c.ParseFlags(a)
if err != nil { if err != nil {
...@@ -659,7 +692,27 @@ func (c *Command) execute(a []string) (err error) { ...@@ -659,7 +692,27 @@ func (c *Command) execute(a []string) (err error) {
return err return err
} }
if helpVal || !c.Runnable() { if helpVal {
return flag.ErrHelp
}
// for back-compat, only add version flag behavior if version is defined
if c.Version != "" {
versionVal, err := c.Flags().GetBool("version")
if err != nil {
c.Println("\"version\" flag declared as non-bool. Please correct your code")
return err
}
if versionVal {
err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c)
if err != nil {
c.Println(err)
}
return err
}
}
if !c.Runnable() {
return flag.ErrHelp return flag.ErrHelp
} }
...@@ -782,6 +835,11 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { ...@@ -782,6 +835,11 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
return c, err return c, err
} }
cmd.commandCalledAs.called = true
if cmd.commandCalledAs.name == "" {
cmd.commandCalledAs.name = cmd.Name()
}
err = cmd.execute(flags) err = cmd.execute(flags)
if err != nil { if err != nil {
// Always show help if requested, even if SilenceErrors is in // Always show help if requested, even if SilenceErrors is in
...@@ -848,6 +906,27 @@ func (c *Command) InitDefaultHelpFlag() { ...@@ -848,6 +906,27 @@ func (c *Command) InitDefaultHelpFlag() {
} }
} }
// InitDefaultVersionFlag adds default version flag to c.
// It is called automatically by executing the c.
// If c already has a version flag, it will do nothing.
// If c.Version is empty, it will do nothing.
func (c *Command) InitDefaultVersionFlag() {
if c.Version == "" {
return
}
c.mergePersistentFlags()
if c.Flags().Lookup("version") == nil {
usage := "version for "
if c.Name() == "" {
usage += "this command"
} else {
usage += c.Name()
}
c.Flags().Bool("version", false, usage)
}
}
// InitDefaultHelpCmd adds default help command to c. // InitDefaultHelpCmd adds default help command to c.
// It is called automatically by executing the c or by calling help and usage. // It is called automatically by executing the c or by calling help and usage.
// If c already has help command or c has no subcommands, it will do nothing. // If c already has help command or c has no subcommands, it will do nothing.
...@@ -1068,14 +1147,25 @@ func (c *Command) HasAlias(s string) bool { ...@@ -1068,14 +1147,25 @@ func (c *Command) HasAlias(s string) bool {
return false return false
} }
// CalledAs returns the command name or alias that was used to invoke
// this command or an empty string if the command has not been called.
func (c *Command) CalledAs() string {
if c.commandCalledAs.called {
return c.commandCalledAs.name
}
return ""
}
// hasNameOrAliasPrefix returns true if the Name or any of aliases start // hasNameOrAliasPrefix returns true if the Name or any of aliases start
// with prefix // with prefix
func (c *Command) hasNameOrAliasPrefix(prefix string) bool { func (c *Command) hasNameOrAliasPrefix(prefix string) bool {
if strings.HasPrefix(c.Name(), prefix) { if strings.HasPrefix(c.Name(), prefix) {
c.commandCalledAs.name = c.Name()
return true return true
} }
for _, alias := range c.Aliases { for _, alias := range c.Aliases {
if strings.HasPrefix(alias, prefix) { if strings.HasPrefix(alias, prefix) {
c.commandCalledAs.name = alias
return true return true
} }
} }
...@@ -1178,7 +1268,7 @@ func (c *Command) HasParent() bool { ...@@ -1178,7 +1268,7 @@ func (c *Command) HasParent() bool {
return c.parent != nil return c.parent != nil
} }
// GlobalNormalizationFunc returns the global normalization function or nil if doesn't exists. // GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist.
func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName { func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName {
return c.globNormFunc return c.globNormFunc
} }
......
...@@ -67,7 +67,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) ...@@ -67,7 +67,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string)
buf.WriteString("## " + name + "\n\n") buf.WriteString("## " + name + "\n\n")
buf.WriteString(short + "\n\n") buf.WriteString(short + "\n\n")
buf.WriteString("### Synopsis\n\n") buf.WriteString("### Synopsis\n\n")
buf.WriteString("\n" + long + "\n\n") buf.WriteString(long + "\n\n")
if cmd.Runnable() { if cmd.Runnable() {
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine())) buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine()))
...@@ -82,7 +82,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) ...@@ -82,7 +82,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string)
return err return err
} }
if hasSeeAlso(cmd) { if hasSeeAlso(cmd) {
buf.WriteString("### SEE ALSO\n") buf.WriteString("### SEE ALSO\n\n")
if cmd.HasParent() { if cmd.HasParent() {
parent := cmd.Parent() parent := cmd.Parent()
pname := parent.CommandPath() pname := parent.CommandPath()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment