Repository: spf13/cobra
Pull request #1436 (2021-07-01 22:27:43)

Module aware generator
The `cobra` tool needed some extra updating to make it work seamlessly within the world of Go modules. 

I've dramatically simplified it to just work within a Go module. Now within a module you can just `cobra init` and it works. No paths or module names required. 

I've also made two additional behavioral changes:
1. Viper is no longer included by default. I've heard too much feedback from users that are confused by this and don't know where Cobra ends and Viper begins. Let's simplify that experience. 
2. There is no default license. There's questionable legal ramifications with choosing a license for users without their election. Better to have them take an action to set the license. 

CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/spf13/cobra?pullRequest=1436) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/spf13/cobra?pullRequest=1436) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/spf13/cobra?pullRequest=1436) it.</sub>
spf13: > @spf13 since the documentation is changing here could you also open a PR on https://github.com/spf13/cobra.dev if you haven't made the changes there already?

I'll do that as soon as this is accepted. For that, do you want a PR or for me to just make the changes directly? Happy to do either. 



Patch:
diff --git a/README.md b/README.md
index 074e397..1ade108 100644
--- a/README.md
+++ b/README.md
@@ -11,28 +11,6 @@ name a few. [This list](./projects_using_cobra.md) contains a more extensive lis
 [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cobra)](https://goreportcard.com/report/github.com/spf13/cobra)
 [![Slack](https://img.shields.io/badge/Slack-cobra-brightgreen)](https://gophers.slack.com/archives/CD3LP1199)
 
-# Table of Contents
-
-- [Overview](#overview)
-- [Concepts](#concepts)
-  * [Commands](#commands)
-  * [Flags](#flags)
-- [Installing](#installing)
-- [Usage](#usage)
-  * [Using the Cobra Generator](user_guide.md#using-the-cobra-generator)
-  * [Using the Cobra Library](user_guide.md#using-the-cobra-library)
-  * [Working with Flags](user_guide.md#working-with-flags)
-  * [Positional and Custom Arguments](user_guide.md#positional-and-custom-arguments)
-  * [Example](user_guide.md#example)
-  * [Help Command](user_guide.md#help-command)
-  * [Usage Message](user_guide.md#usage-message)
-  * [PreRun and PostRun Hooks](user_guide.md#prerun-and-postrun-hooks)
-  * [Suggestions when "unknown command" happens](user_guide.md#suggestions-when-unknown-command-happens)
-  * [Generating documentation for your command](user_guide.md#generating-documentation-for-your-command)
-  * [Generating shell completions](user_guide.md#generating-shell-completions)
-- [Contributing](CONTRIBUTING.md)
-- [License](#license)
-
 # Overview
 
 Cobra is a library providing a simple interface to create powerful modern CLI
@@ -46,7 +24,7 @@ Cobra provides:
 * Fully POSIX-compliant flags (including short & long versions)
 * Nested subcommands
 * Global, local and cascading flags
-* Easy generation of applications & commands with `cobra init appname` & `cobra add cmdname`
+* Easy generation of applications & commands with `cobra init` & `cobra add cmdname`
 * Intelligent suggestions (`app srver`... did you mean `app server`?)
 * Automatic help generation for commands and flags
 * Automatic help flag recognition of `-h`, `--help`, etc.
@@ -54,7 +32,7 @@ Cobra provides:
 * Automatically generated man pages for your application
 * Command aliases so you can change things without breaking them
 * The flexibility to define your own help, usage, etc.
-* Optional tight integration with [viper](http://github.com/spf13/viper) for 12-factor apps
+* Optional seamless integration with [viper](http://github.com/spf13/viper) for 12-factor apps
 
 # Concepts
 
@@ -88,7 +66,7 @@ have children commands and optionally run an action.
 
 In the example above, 'server' is the command.
 
-[More about cobra.Command](https://godoc.org/github.com/spf13/cobra#Command)
+[More about cobra.Command](https://pkg.go.dev/github.com/spf13/cobra#Command)
 
 ## Flags
 
@@ -117,8 +95,12 @@ import "github.com/spf13/cobra"
 ```
 
 # Usage
+Cobra provides its own program that will create your application and add any
+commands you want. It's the easiest way to incorporate Cobra into your application.
+
+For complete details on using the Cobra generator, please read [The Cobra Generator README](https://github.com/spf13/cobra/blob/master/cobra/README.md)
 
-See [User Guide](user_guide.md).
+For complete details on using the Cobra library, please read the [The Cobra User Guide](user_guide.md).
 
 # License
 
diff --git a/bash_completions.go b/bash_completions.go
index 925e6e7..7411aba 100644
--- a/bash_completions.go
+++ b/bash_completions.go
@@ -193,7 +193,13 @@ __%[1]s_handle_reply()
                     fi
                 fi
             fi
-            return 0;
+
+            if [[ -z "${flag_parsing_disabled}" ]]; then
+                # If flag parsing is enabled, we have completed the flags and can return.
+                # If flag parsing is disabled, we may not know all (or any) of the flags, so we fallthrough
+                # to possibly call handle_go_custom_completion.
+                return 0;
+            fi
             ;;
     esac
 
@@ -394,6 +400,7 @@ func writePostscript(buf io.StringWriter, name string) {
     fi
 
     local c=0
+    local flag_parsing_disabled=
     local flags=()
     local two_word_flags=()
     local local_nonpersistent_flags=()
@@ -512,7 +519,9 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) {
 
 // Setup annotations for go completions for registered flags
 func prepareCustomAnnotationsForFlags(cmd *Command) {
-	for flag := range cmd.Root().flagCompletionFunctions {
+	flagCompletionMutex.RLock()
+	defer flagCompletionMutex.RUnlock()
+	for flag := range flagCompletionFunctions {
 		// Make sure the completion script calls the __*_go_custom_completion function for
 		// every registered flag.  We need to do this here (and not when the flag was registered
 		// for completion) so that we can know the root command name for the prefix
@@ -533,6 +542,11 @@ func writeFlags(buf io.StringWriter, cmd *Command) {
     flags_completion=()
 
 `)
+
+	if cmd.DisableFlagParsing {
+		WriteStringAndCheck(buf, "    flag_parsing_disabled=1\n")
+	}
+
 	localNonPersistentFlags := cmd.LocalNonPersistentFlags()
 	cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
 		if nonCompletableFlag(flag) {
diff --git a/cobra/README.md b/cobra/README.md
index dcaf0c5..f1a6056 100644
--- a/cobra/README.md
+++ b/cobra/README.md
@@ -3,41 +3,78 @@
 Cobra provides its own program that will create your application and add any
 commands you want. It's the easiest way to incorporate Cobra into your application.
 
-In order to use the cobra command, compile it using the following command:
+Install the cobra generator with the command `go install github.com/spf13/cobra/cobra`. 
+Go will automatically install it in your `$GOPATH/bin` directory which should be in your $PATH. 
 
-    go get github.com/spf13/cobra/cobra
+Once installed you should have the `cobra` command available. Confirm by typing `cobra` at a 
+command line. 
 
-This will create the cobra executable under your `$GOPATH/bin` directory.
+There are only two operations currently supported by the Cobra generator: 
 
 ### cobra init
 
 The `cobra init [app]` command will create your initial application code
 for you. It is a very powerful application that will populate your program with
-the right structure so you can immediately enjoy all the benefits of Cobra. It
-will also automatically apply the license you specify to your application.
+the right structure so you can immediately enjoy all the benefits of Cobra. 
+It can also apply the license you specify to your application.
 
-Cobra init is pretty smart. You can either run it in your current application directory
-or you can specify a relative path to an existing project. If the directory does not exist, it will be created for you.
+With the introduction of Go modules, the Cobra generator has been simplified to
+take advantage of modules. The Cobra generator works from within a Go module. 
 
-Updates to the Cobra generator have now decoupled it from the GOPATH.
-As such `--pkg-name` is required.
+#### Initalizing a module
 
-**Note:** init will no longer fail on non-empty directories.
+__If you already have a module, skip this step.__
 
+If you want to initialize a new Go module: 
+
+ 1. Create a new directory 
+ 2. `cd` into that directory
+ 3. run `go mod init <MODNAME>`
+
+e.g. 
 ```
-mkdir -p newApp && cd newApp
-cobra init --pkg-name github.com/spf13/newApp
+cd $HOME/code 
+mkdir myapp
+cd myapp
+go mod init github.com/spf13/myapp
 ```
 
-or
+#### Initalizing an Cobra CLI application
+
+From within a Go module run `cobra init`. This will create a new barebones project
+for you to edit. 
+
+You should be able to run your new application immediately. Try it with 
+`go run main.go`. 
+
+You will want to open up and edit 'cmd/root.go' and provide your own description and logic. 
 
+e.g.
 ```
-cobra init --pkg-name github.com/spf13/newApp path/to/newApp
+cd $HOME/code/myapp
+cobra init
+go run main.go
 ```
 
-### cobra add
+Cobra init can also be run from a subdirectory such as how the [cobra generator itself is organized](https://github.com/spf13/cobra).
+This is useful if you want to keep your application code separate from your library code.
+
+#### Optional flags:
+You can provide it your author name with the `--author` flag. 
+e.g. `cobra init --author "Steve Francia spf@spf13.com"`
+
+You can provide a license to use with `--license` 
+e.g. `cobra init --license apache`
+
+Use the `--viper` flag to automatically setup [viper](https://github.com/spf13/viper)
+
+Viper is a companion to Cobra intended to provide easy handling of environment variables and config files and seamlessly connecting them to the application flags.
+
+### Add commands to a project
+
+Once a cobra application is initialized you can continue to use the Cobra generator to 
+add additional commands to your application. The command to do this is `cobra add`. 
 
-Once an application is initialized, Cobra can create additional commands for you.
 Let's say you created an app and you wanted the following commands for it:
 
 * app serve
@@ -52,6 +89,14 @@ cobra add config
 cobra add create -p 'configCmd'
 ```
 
+`cobra add` supports all the same optional flags as `cobra init` does (described above).
+
+You'll notice that this final command has a `-p` flag. This is used to assign a
+parent command to the newly added command. In this case, we want to assign the
+"create" command to the "config" command. All commands have a default parent of rootCmd if not specified.  
+
+By default `cobra` will append `Cmd` to the name provided and uses this name for the internal variable name. When specifying a parent, be sure to match the variable name used in the code. 
+
 *Note: Use camelCase (not snake_case/kebab-case) for command names.
 Otherwise, you will encounter errors.
 For example, `cobra add add-user` is incorrect, but `cobra add addUser` is valid.*
@@ -62,9 +107,10 @@ the following:
 ```
   ▾ app/
     ▾ cmd/
-        serve.go
         config.go
         create.go
+        serve.go
+        root.go
       main.go
 ```
 
@@ -72,8 +118,11 @@ At this point you can run `go run main.go` and it would run your app. `go run
 main.go serve`, `go run main.go config`, `go run main.go config create` along
 with `go run main.go help serve`, etc. would all work.
 
-Obviously you haven't added your own code to these yet. The commands are ready
-for you to give them their tasks. Have fun!
+You now have a basic Cobra-based application up and running. Next step is to edit the files in cmd and customize them for your application.
+
+For complete details on using the Cobra library, please read the [The Cobra User Guide](https://github.com/spf13/cobra/blob/master/user_guide.md#using-the-cobra-library).
+
+Have fun!
 
 ### Configuring the cobra generator
 
@@ -86,6 +135,7 @@ An example ~/.cobra.yaml file:
 ```yaml
 author: Steve Francia <spf@spf13.com>
 license: MIT
+viper: true
 ```
 
 You can also use built-in licenses. For example, **GPLv2**, **GPLv3**, **LGPL**,
diff --git a/cobra/cmd/init.go b/cobra/cmd/init.go
index 8c0e617..dbdc25b 100644
--- a/cobra/cmd/init.go
+++ b/cobra/cmd/init.go
@@ -1,4 +1,4 @@
-// Copyright © 2015 Steve Francia <spf@spf13.com>.
+// Copyright © 2021 Steve Francia <spf@spf13.com>.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,42 +14,41 @@
 package cmd
 
 import (
+	"encoding/json"
 	"fmt"
 	"os"
+	"os/exec"
 	"path"
+	"path/filepath"
+	"strings"
 
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 )
 
 var (
-	pkgName string
-
 	initCmd = &cobra.Command{
-		Use:     "init [name]",
+		Use:     "init [path]",
 		Aliases: []string{"initialize", "initialise", "create"},
 		Short:   "Initialize a Cobra Application",
 		Long: `Initialize (cobra init) will create a new application, with a license
 and the appropriate structure for a Cobra-based CLI application.
 
-  * If a name is provided, a directory with that name will be created in the current directory;
-  * If no name is provided, the current directory will be assumed;
+Cobra init must be run inside of a go module (please run "go mod init <MODNAME>" first)
 `,
 
 		Run: func(_ *cobra.Command, args []string) {
-
 			projectPath, err := initializeProject(args)
 			cobra.CheckErr(err)
+			cobra.CheckErr(goGet("github.com/spf13/cobra"))
+			if viper.GetBool("useViper") {
+				cobra.CheckErr(goGet("github.com/spf13/viper"))
+			}
 			fmt.Printf("Your Cobra application is ready at\n%s\n", projectPath)
 		},
 	}
 )
 
-func init() {
-	initCmd.Flags().StringVar(&pkgName, "pkg-name", "", "fully qualified pkg name")
-	cobra.CheckErr(initCmd.MarkFlagRequired("pkg-name"))
-}
-
 func initializeProject(args []string) (string, error) {
 	wd, err := os.Getwd()
 	if err != nil {
@@ -62,13 +61,15 @@ func initializeProject(args []string) (string, error) {
 		}
 	}
 
+	modName := getModImportPath()
+
 	project := &Project{
 		AbsolutePath: wd,
-		PkgName:      pkgName,
+		PkgName:      modName,
 		Legal:        getLicense(),
 		Copyright:    copyrightLine(),
 		Viper:        viper.GetBool("useViper"),
-		AppName:      path.Base(pkgName),
+		AppName:      path.Base(modName),
 	}
 
 	if err := project.Create(); err != nil {
@@ -77,3 +78,51 @@ func initializeProject(args []string) (string, error) {
 
 	return project.AbsolutePath, nil
 }
+
+func getModImportPath() string {
+	mod, cd := parseModInfo()
+	return path.Join(mod.Path, fileToURL(strings.TrimPrefix(cd.Dir, mod.Dir)))
+}
+
+func fileToURL(in string) string {
+	i := strings.Split(in, string(filepath.Separator))
+	return path.Join(i...)
+}
+
+func parseModInfo() (Mod, CurDir) {
+	var mod Mod
+	var dir CurDir
+
+	m := modInfoJSON("-m")
+	cobra.CheckErr(json.Unmarshal(m, &mod))
+
+	// Unsure why, but if no module is present Path is set to this string.
+	if mod.Path == "command-line-arguments" {
+		cobra.CheckErr("Please run `go mod init <MODNAME>` before `cobra init`")
+	}
+
+	e := modInfoJSON("-e")
+	cobra.CheckErr(json.Unmarshal(e, &dir))
+
+	return mod, dir
+}
+
+type Mod struct {
+	Path, Dir, GoMod string
+}
+
+type CurDir struct {
+	Dir string
+}
+
+func goGet(mod string) error {
+	return exec.Command("go", "get", mod).Run()
+}
+
+func modInfoJSON(args ...string) []byte {
+	cmdArgs := append([]string{"list", "-json"}, args...)
+	out, err := exec.Command("go", cmdArgs...).Output()
+	cobra.CheckErr(err)
+
+	return out
+}
diff --git a/cobra/cmd/licenses.go b/cobra/cmd/licenses.go
index 2b3a424..30c7b24 100644
--- a/cobra/cmd/licenses.go
+++ b/cobra/cmd/licenses.go
@@ -1,4 +1,4 @@
-// Copyright © 2015 Steve Francia <spf@spf13.com>.
+// Copyright © 2021 Steve Francia <spf@spf13.com>.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@ func init() {
 }
 
 // getLicense returns license specified by user in flag or in config.
-// If user didn't specify the license, it returns Apache License 2.0.
+// If user didn't specify the license, it returns none
 //
 // TODO: Inspect project for existing license
 func getLicense() License {
@@ -73,8 +73,8 @@ func getLicense() License {
 		return findLicense(viper.GetString("license"))
 	}
 
-	// If user didn't set any license, use Apache 2.0 by default.
-	return Licenses["apache"]
+	// If user didn't set any license, use none by default
+	return Licenses["none"]
 }
 
 func copyrightLine() string {
diff --git a/cobra/cmd/root.go b/cobra/cmd/root.go
index 350df10..51bba2c 100644
--- a/cobra/cmd/root.go
+++ b/cobra/cmd/root.go
@@ -1,4 +1,4 @@
-// Copyright © 2015 Steve Francia <spf@spf13.com>.
+// Copyright © 2021 Steve Francia <spf@spf13.com>.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -46,11 +46,11 @@ func init() {
 	rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
 	rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
 	rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
-	rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
+	rootCmd.PersistentFlags().Bool("viper", false, "use Viper for configuration")
 	cobra.CheckErr(viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")))
 	cobra.CheckErr(viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper")))
 	viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
-	viper.SetDefault("license", "apache")
+	viper.SetDefault("license", "none")
 
 	rootCmd.AddCommand(addCmd)
 	rootCmd.AddCommand(initCmd)
diff --git a/cobra/tpl/main.go b/cobra/tpl/main.go
index ed3a98e..d2f7742 100644
--- a/cobra/tpl/main.go
+++ b/cobra/tpl/main.go
@@ -1,3 +1,16 @@
+// Copyright © 2021 Steve Francia <spf@spf13.com>.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package tpl
 
 func MainTemplate() []byte {
@@ -23,10 +36,12 @@ func RootTemplate() []byte {
 package cmd
 
 import (
+{{- if .Viper }}
 	"fmt"
 	"os"
+{{ end }}
 	"github.com/spf13/cobra"
-{{ if .Viper }}
+{{- if .Viper }}
 	"github.com/spf13/viper"{{ end }}
 )
 
diff --git a/command.go b/command.go
index 9f33a46..2cc1889 100644
--- a/command.go
+++ b/command.go
@@ -142,9 +142,6 @@ type Command struct {
 	// that we can use on every pflag set and children commands
 	globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
 
-	//flagCompletionFunctions is map of flag completion functions.
-	flagCompletionFunctions map[*flag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
-
 	// usageFunc is usage func defined by user.
 	usageFunc func(*Command) error
 	// usageTemplate is usage template defined by user.
diff --git a/command_notwin.go b/command_notwin.go
index 6159c1c..bb5dad9 100644
--- a/command_notwin.go
+++ b/command_notwin.go
@@ -1,3 +1,4 @@
+//go:build !windows
 // +build !windows
 
 package cobra
diff --git a/command_win.go b/command_win.go
index 8768b17..a84f5a8 100644
--- a/command_win.go
+++ b/command_win.go
@@ -1,3 +1,4 @@
+//go:build windows
 // +build windows
 
 package cobra
diff --git a/completions.go b/completions.go
index 4687674..7aeccb3 100644
--- a/completions.go
+++ b/completions.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"os"
 	"strings"
+	"sync"
 
 	"github.com/spf13/pflag"
 )
@@ -17,6 +18,12 @@ const (
 	ShellCompNoDescRequestCmd = "__completeNoDesc"
 )
 
+// Global map of flag completion functions. Make sure to use flagCompletionMutex before you try to read and write from it.
+var flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){}
+
+// lock for reading and writing from flagCompletionFunctions
+var flagCompletionMutex = &sync.RWMutex{}
+
 // ShellCompDirective is a bit map representing the different behaviors the shell
 // can be instructed to have once completions have been provided.
 type ShellCompDirective int
@@ -100,15 +107,13 @@ func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Comman
 	if flag == nil {
 		return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName)
 	}
+	flagCompletionMutex.Lock()
+	defer flagCompletionMutex.Unlock()
 
-	root := c.Root()
-	if _, exists := root.flagCompletionFunctions[flag]; exists {
+	if _, exists := flagCompletionFunctions[flag]; exists {
 		return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' already registered", flagName)
 	}
-	if root.flagCompletionFunctions == nil {
-		root.flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){}
-	}
-	root.flagCompletionFunctions[flag] = f
+	flagCompletionFunctions[flag] = f
 	return nil
 }
 
@@ -261,6 +266,12 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
 		}
 	}
 
+	// We only remove the flags from the arguments if DisableFlagParsing is not set.
+	// This is important for commands which have requested to do their own flag completion.
+	if !finalCmd.DisableFlagParsing {
+		finalArgs = finalCmd.Flags().Args()
+	}
+
 	if flag != nil && flagCompletion {
 		// Check if we are completing a flag value subject to annotations
 		if validExts, present := flag.Annotations[BashCompFilenameExt]; present {
@@ -285,12 +296,16 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
 		}
 	}
 
+	var completions []string
+	var directive ShellCompDirective
+
+	// Note that we want to perform flagname completion even if finalCmd.DisableFlagParsing==true;
+	// doing this allows for completion of persistant flag names even for commands that disable flag parsing.
+	//
 	// When doing completion of a flag name, as soon as an argument starts with
 	// a '-' we know it is a flag.  We cannot use isFlagArg() here as it requires
 	// the flag name to be complete
 	if flag == nil && len(toComplete) > 0 && toComplete[0] == '-' && !strings.Contains(toComplete, "=") && flagCompletion {
-		var completions []string
-
 		// First check for required flags
 		completions = completeRequireFlags(finalCmd, toComplete)
 
@@ -317,92 +332,94 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
 			})
 		}
 
-		directive := ShellCompDirectiveNoFileComp
+		directive = ShellCompDirectiveNoFileComp
 		if len(completions) == 1 && strings.HasSuffix(completions[0], "=") {
 			// If there is a single completion, the shell usually adds a space
 			// after the completion.  We don't want that if the flag ends with an =
 			directive = ShellCompDirectiveNoSpace
 		}
-		return finalCmd, completions, directive, nil
-	}
-
-	// We only remove the flags from the arguments if DisableFlagParsing is not set.
-	// This is important for commands which have requested to do their own flag completion.
-	if !finalCmd.DisableFlagParsing {
-		finalArgs = finalCmd.Flags().Args()
-	}
 
-	var completions []string
-	directive := ShellCompDirectiveDefault
-	if flag == nil {
-		foundLocalNonPersistentFlag := false
-		// If TraverseChildren is true on the root command we don't check for
-		// local flags because we can use a local flag on a parent command
-		if !finalCmd.Root().TraverseChildren {
-			// Check if there are any local, non-persistent flags on the command-line
-			localNonPersistentFlags := finalCmd.LocalNonPersistentFlags()
-			finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
-				if localNonPersistentFlags.Lookup(flag.Name) != nil && flag.Changed {
-					foundLocalNonPersistentFlag = true
-				}
-			})
+		if !finalCmd.DisableFlagParsing {
+			// If DisableFlagParsing==false, we have completed the flags as known by Cobra;
+			// we can return what we found.
+			// If DisableFlagParsing==true, Cobra may not be aware of all flags, so we
+			// let the logic continue to see if ValidArgsFunction needs to be called.
+			return finalCmd, completions, directive, nil
 		}
+	} else {
+		directive = ShellCompDirectiveDefault
+		if flag == nil {
+			foundLocalNonPersistentFlag := false
+			// If TraverseChildren is true on the root command we don't check for
+			// local flags because we can use a local flag on a parent command
+			if !finalCmd.Root().TraverseChildren {
+				// Check if there are any local, non-persistent flags on the command-line
+				localNonPersistentFlags := finalCmd.LocalNonPersistentFlags()
+				finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
+					if localNonPersistentFlags.Lookup(flag.Name) != nil && flag.Changed {
+						foundLocalNonPersistentFlag = true
+					}
+				})
+			}
 
-		// Complete subcommand names, including the help command
-		if len(finalArgs) == 0 && !foundLocalNonPersistentFlag {
-			// We only complete sub-commands if:
-			// - there are no arguments on the command-line and
-			// - there are no local, non-persistent flags on the command-line or TraverseChildren is true
-			for _, subCmd := range finalCmd.Commands() {
-				if subCmd.IsAvailableCommand() || subCmd == finalCmd.helpCommand {
-					if strings.HasPrefix(subCmd.Name(), toComplete) {
-						completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
+			// Complete subcommand names, including the help command
+			if len(finalArgs) == 0 && !foundLocalNonPersistentFlag {
+				// We only complete sub-commands if:
+				// - there are no arguments on the command-line and
+				// - there are no local, non-persistent flags on the command-line or TraverseChildren is true
+				for _, subCmd := range finalCmd.Commands() {
+					if subCmd.IsAvailableCommand() || subCmd == finalCmd.helpCommand {
+						if strings.HasPrefix(subCmd.Name(), toComplete) {
+							completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
+						}
+						directive = ShellCompDirectiveNoFileComp
 					}
-					directive = ShellCompDirectiveNoFileComp
 				}
 			}
-		}
 
-		// Complete required flags even without the '-' prefix
-		completions = append(completions, completeRequireFlags(finalCmd, toComplete)...)
-
-		// Always complete ValidArgs, even if we are completing a subcommand name.
-		// This is for commands that have both subcommands and ValidArgs.
-		if len(finalCmd.ValidArgs) > 0 {
-			if len(finalArgs) == 0 {
-				// ValidArgs are only for the first argument
-				for _, validArg := range finalCmd.ValidArgs {
-					if strings.HasPrefix(validArg, toComplete) {
-						completions = append(completions, validArg)
+			// Complete required flags even without the '-' prefix
+			completions = append(completions, completeRequireFlags(finalCmd, toComplete)...)
+
+			// Always complete ValidArgs, even if we are completing a subcommand name.
+			// This is for commands that have both subcommands and ValidArgs.
+			if len(finalCmd.ValidArgs) > 0 {
+				if len(finalArgs) == 0 {
+					// ValidArgs are only for the first argument
+					for _, validArg := range finalCmd.ValidArgs {
+						if strings.HasPrefix(validArg, toComplete) {
+							completions = append(completions, validArg)
+						}
 					}
-				}
-				directive = ShellCompDirectiveNoFileComp
-
-				// If no completions were found within commands or ValidArgs,
-				// see if there are any ArgAliases that should be completed.
-				if len(completions) == 0 {
-					for _, argAlias := range finalCmd.ArgAliases {
-						if strings.HasPrefix(argAlias, toComplete) {
-							completions = append(completions, argAlias)
+					directive = ShellCompDirectiveNoFileComp
+
+					// If no completions were found within commands or ValidArgs,
+					// see if there are any ArgAliases that should be completed.
+					if len(completions) == 0 {
+						for _, argAlias := range finalCmd.ArgAliases {
+							if strings.HasPrefix(argAlias, toComplete) {
+								completions = append(completions, argAlias)
+							}
 						}
 					}
 				}
+
+				// If there are ValidArgs specified (even if they don't match), we stop completion.
+				// Only one of ValidArgs or ValidArgsFunction can be used for a single command.
+				return finalCmd, completions, directive, nil
 			}
 
-			// If there are ValidArgs specified (even if they don't match), we stop completion.
-			// Only one of ValidArgs or ValidArgsFunction can be used for a single command.
-			return finalCmd, completions, directive, nil
+			// Let the logic continue so as to add any ValidArgsFunction completions,
+			// even if we already found sub-commands.
+			// This is for commands that have subcommands but also specify a ValidArgsFunction.
 		}
-
-		// Let the logic continue so as to add any ValidArgsFunction completions,
-		// even if we already found sub-commands.
-		// This is for commands that have subcommands but also specify a ValidArgsFunction.
 	}
 
 	// Find the completion function for the flag or command
 	var completionFn func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
 	if flag != nil && flagCompletion {
-		completionFn = c.Root().flagCompletionFunctions[flag]
+		flagCompletionMutex.RLock()
+		completionFn = flagCompletionFunctions[flag]
+		flagCompletionMutex.RUnlock()
 	} else {
 		completionFn = finalCmd.ValidArgsFunction
 	}
diff --git a/fish_completions.go b/fish_completions.go
index b0db323..bb57fd5 100644
--- a/fish_completions.go
+++ b/fish_completions.go
@@ -152,11 +152,11 @@ function __%[1]s_prepare_completions
             # We don't need descriptions anyway since there is only a single
             # real completion which the shell will expand immediately.
             set -l split (string split --max 1 \t $__%[1]s_comp_results[1])
-        
+
             # Fish won't add a space if the completion ends with any
             # of the following characters: @=/:.,
             set -l lastChar (string sub -s -1 -- $split)
-            if not string match -r -q "[@=/:.,]" -- "$lastChar"                
+            if not string match -r -q "[@=/:.,]" -- "$lastChar"
                 # In other cases, to support the "nospace" directive we trick the shell
                 # by outputting an extra, longer completion.
                 __%[1]s_debug "Adding second completion to perform nospace directive"
diff --git a/go.mod b/go.mod
index 1fb9439..97eab3c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,9 +1,9 @@
 module github.com/spf13/cobra
 
-go 1.14
+go 1.15
 
 require (
-	github.com/cpuguy83/go-md2man/v2 v2.0.0
+	github.com/cpuguy83/go-md2man/v2 v2.0.1
 	github.com/inconshreveable/mousetrap v1.0.0
 	github.com/spf13/pflag v1.0.5
 	github.com/spf13/viper v1.8.1
diff --git a/go.sum b/go.sum
index 3e22df2..6e83237 100644
--- a/go.sum
+++ b/go.sum
@@ -55,8 +55,8 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
-github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
-github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
+github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -206,12 +206,10 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
-github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
-github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
-github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
diff --git a/projects_using_cobra.md b/projects_using_cobra.md
index d98a71e..843ad9b 100644
--- a/projects_using_cobra.md
+++ b/projects_using_cobra.md
@@ -21,6 +21,7 @@
 - [Kubernetes](http://kubernetes.io/)
 - [Linkerd](https://linkerd.io/)
 - [Mattermost-server](https://github.com/mattermost/mattermost-server)
+- [Meroxa CLI](https://github.com/meroxa/cli)
 - [Metal Stack CLI](https://github.com/metal-stack/metalctl)
 - [Moby (former Docker)](https://github.com/moby/moby)
 - [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
@@ -35,4 +36,5 @@
 - [Skaffold](https://skaffold.dev/)
 - [Tendermint](https://github.com/tendermint/tendermint)
 - [Twitch CLI](https://github.com/twitchdev/twitch-cli)
+- [VMware Tanzu Community Edition](https://github.com/vmware-tanzu/community-edition)
 - [Werf](https://werf.io/)
diff --git a/user_guide.md b/user_guide.md
index 311abce..923392b 100644
--- a/user_guide.md
+++ b/user_guide.md
@@ -32,7 +32,7 @@ func main() {
 Cobra provides its own program that will create your application and add any
 commands you want. It's the easiest way to incorporate Cobra into your application.
 
-[Here](https://github.com/spf13/cobra/blob/master/cobra/README.md) you can find more information about it.
+For complete details on using the Cobra generator, please read [The Cobra Generator README](https://github.com/spf13/cobra/blob/master/cobra/README.md)
 
 ## Using the Cobra Library
 


Test patch:
diff --git a/.github/workflows/Test.yml b/.github/workflows/Test.yml
index c34c2fb..bc74803 100644
--- a/.github/workflows/Test.yml
+++ b/.github/workflows/Test.yml
@@ -18,29 +18,35 @@ jobs:
         - ubuntu
         - macOS
         go:
-        - 1.14.x
-        - 1.15.x
-    name: '${{ matrix.platform }} | ${{ matrix.go }}'
+        - 14
+        - 15
+        - 16
+        - 17
+    name: '${{ matrix.platform }} | 1.${{ matrix.go }}.x'
     runs-on: ${{ matrix.platform }}-latest
     steps:
 
     - uses: actions/setup-go@v2
       with:
-        go-version: ${{ matrix.go }}
+        go-version: 1.${{ matrix.go }}.x
 
     - uses: actions/checkout@v2
 
     - uses: actions/cache@v2
       with:
         path: ~/go/pkg/mod
-        key: ${{ runner.os }}-${{ matrix.go }}-${{ hashFiles('**/go.sum') }}
-        restore-keys: ${{ runner.os }}-${{ matrix.go }}-
+        key: ${{ runner.os }}-1.${{ matrix.go }}.x-${{ hashFiles('**/go.sum') }}
+        restore-keys: ${{ runner.os }}-1.${{ matrix.go }}.x-
 
     - run: |
         export GOBIN=$HOME/go/bin
         curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $GOBIN latest
-        go install github.com/kyoh86/richgo
-        go install github.com/mitchellh/gox
+        case "${{ matrix.go }}" in
+          16|17) _version='@latest';;
+          *) _version='';;
+        esac
+        go install github.com/kyoh86/richgo"${_version}"
+        go install github.com/mitchellh/gox"${_version}"
 
     - run: PATH=$HOME/go/bin/:$PATH make
 
diff --git a/cobra/cmd/add_test.go b/cobra/cmd/add_test.go
index 0b32ca6..20bc34f 100644
--- a/cobra/cmd/add_test.go
+++ b/cobra/cmd/add_test.go
@@ -4,9 +4,13 @@ import (
 	"fmt"
 	"os"
 	"testing"
+
+	"github.com/spf13/viper"
 )
 
 func TestGoldenAddCmd(t *testing.T) {
+	viper.Set("useViper", true)
+	viper.Set("license", "apache")
 	command := &Command{
 		CmdName:   "test",
 		CmdParent: parentName,
diff --git a/cobra/cmd/init_test.go b/cobra/cmd/init_test.go
index e364f40..930313c 100644
--- a/cobra/cmd/init_test.go
+++ b/cobra/cmd/init_test.go
@@ -16,8 +16,8 @@ func getProject() *Project {
 		AbsolutePath: fmt.Sprintf("%s/testproject", wd),
 		Legal:        getLicense(),
 		Copyright:    copyrightLine(),
-		AppName:      "testproject",
-		PkgName:      "github.com/spf13/testproject",
+		AppName:      "cmd",
+		PkgName:      "github.com/spf13/cobra/cobra/cmd/cmd",
 		Viper:        true,
 	}
 }
@@ -37,30 +37,18 @@ func TestGoldenInitCmd(t *testing.T) {
 		expectErr bool
 	}{
 		{
-			name:      "successfully creates a project with name",
+			name:      "successfully creates a project based on module",
 			args:      []string{"testproject"},
 			pkgName:   "github.com/spf13/testproject",
 			expectErr: false,
 		},
-		{
-			name:      "returns error when passing an absolute path for project",
-			args:      []string{dir},
-			pkgName:   "github.com/spf13/testproject",
-			expectErr: true,
-		},
-		{
-			name:      "returns error when passing a relative path for project",
-			args:      []string{"github.com/spf13/testproject"},
-			pkgName:   "github.com/spf13/testproject",
-			expectErr: true,
-		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 
-			assertNoErr(t, initCmd.Flags().Set("pkg-name", tt.pkgName))
 			viper.Set("useViper", true)
+			viper.Set("license", "apache")
 			projectPath, err := initializeProject(tt.args)
 			defer func() {
 				if projectPath != "" {
diff --git a/cobra/cmd/testdata/main.go.golden b/cobra/cmd/testdata/main.go.golden
index f69d34a..0af77e1 100644
--- a/cobra/cmd/testdata/main.go.golden
+++ b/cobra/cmd/testdata/main.go.golden
@@ -15,7 +15,7 @@ limitations under the License.
 */
 package main
 
-import "github.com/spf13/testproject/cmd"
+import "github.com/spf13/cobra/cobra/cmd/cmd"
 
 func main() {
 	cmd.Execute()
diff --git a/cobra/cmd/testdata/root.go.golden b/cobra/cmd/testdata/root.go.golden
index 32c1529..2adeaea 100644
--- a/cobra/cmd/testdata/root.go.golden
+++ b/cobra/cmd/testdata/root.go.golden
@@ -18,8 +18,8 @@ package cmd
 import (
 	"fmt"
 	"os"
-	"github.com/spf13/cobra"
 
+	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 )
 
@@ -27,7 +27,7 @@ var cfgFile string
 
 // rootCmd represents the base command when called without any subcommands
 var rootCmd = &cobra.Command{
-	Use:   "testproject",
+	Use:   "cmd",
 	Short: "A brief description of your application",
 	Long: `A longer description that spans multiple lines and likely contains
 examples and usage of using your application. For example:
@@ -53,7 +53,7 @@ func init() {
 	// Cobra supports persistent flags, which, if defined here,
 	// will be global for your application.
 
-	rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.testproject.yaml)")
+	rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cmd.yaml)")
 
 	// Cobra also supports local flags, which will only run
 	// when this action is called directly.
@@ -70,10 +70,10 @@ func initConfig() {
 		home, err := os.UserHomeDir()
 		cobra.CheckErr(err)
 
-		// Search config in home directory with name ".testproject" (without extension).
+		// Search config in home directory with name ".cmd" (without extension).
 		viper.AddConfigPath(home)
 		viper.SetConfigType("yaml")
-		viper.SetConfigName(".testproject")
+		viper.SetConfigName(".cmd")
 	}
 
 	viper.AutomaticEnv() // read in environment variables that match
diff --git a/completions_test.go b/completions_test.go
index aea06a2..ecbc723 100644
--- a/completions_test.go
+++ b/completions_test.go
@@ -1971,6 +1971,41 @@ func TestFlagCompletionWithNotInterspersedArgs(t *testing.T) {
 	}
 }
 
+func TestFlagCompletionWorksRootCommandAddedAfterFlags(t *testing.T) {
+	rootCmd := &Command{Use: "root", Run: emptyRun}
+	childCmd := &Command{
+		Use: "child",
+		Run: emptyRun,
+		ValidArgsFunction: func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
+			return []string{"--validarg", "test"}, ShellCompDirectiveDefault
+		},
+	}
+	childCmd.Flags().Bool("bool", false, "test bool flag")
+	childCmd.Flags().String("string", "", "test string flag")
+	_ = childCmd.RegisterFlagCompletionFunc("string", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
+		return []string{"myval"}, ShellCompDirectiveDefault
+	})
+
+	// Important: This is a test for https://github.com/spf13/cobra/issues/1437
+	// Only add the subcommand after RegisterFlagCompletionFunc was called, do not change this order!
+	rootCmd.AddCommand(childCmd)
+
+	// Test that flag completion works for the subcmd
+	output, err := executeCommand(rootCmd, ShellCompRequestCmd, "child", "--string", "")
+	if err != nil {
+		t.Errorf("Unexpected error: %v", err)
+	}
+
+	expected := strings.Join([]string{
+		"myval",
+		":0",
+		"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
+
+	if output != expected {
+		t.Errorf("expected: %q, got: %q", expected, output)
+	}
+}
+
 func TestFlagCompletionInGoWithDesc(t *testing.T) {
 	rootCmd := &Command{
 		Use: "root",
@@ -2508,3 +2543,64 @@ func TestMultipleShorthandFlagCompletion(t *testing.T) {
 		t.Errorf("expected: %q, got: %q", expected, output)
 	}
 }
+
+func TestCompleteWithDisableFlagParsing(t *testing.T) {
+
+	flagValidArgs := func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
+		return []string{"--flag", "-f"}, ShellCompDirectiveNoFileComp
+	}
+
+	rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
+	childCmd := &Command{
+		Use:                "child",
+		Run:                emptyRun,
+		DisableFlagParsing: true,
+		ValidArgsFunction:  flagValidArgs,
+	}
+	rootCmd.AddCommand(childCmd)
+
+	rootCmd.PersistentFlags().StringP("persistent", "p", "", "persistent flag")
+	childCmd.Flags().StringP("nonPersistent", "n", "", "non-persistent flag")
+
+	// Test that when DisableFlagParsing==true, ValidArgsFunction is called to complete flag names,
+	// after Cobra tried to complete the flags it knows about.
+	childCmd.DisableFlagParsing = true
+	output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "child", "-")
+	if err != nil {
+		t.Errorf("Unexpected error: %v", err)
+	}
+
+	expected := strings.Join([]string{
+		"--persistent",
+		"-p",
+		"--nonPersistent",
+		"-n",
+		"--flag",
+		"-f",
+		":4",
+		"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
+
+	if output != expected {
+		t.Errorf("expected: %q, got: %q", expected, output)
+	}
+
+	// Test that when DisableFlagParsing==false, Cobra completes the flags itself and ValidArgsFunction is not called
+	childCmd.DisableFlagParsing = false
+	output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "child", "-")
+	if err != nil {
+		t.Errorf("Unexpected error: %v", err)
+	}
+
+	// Cobra was not told of any flags, so it returns nothing
+	expected = strings.Join([]string{
+		"--persistent",
+		"-p",
+		"--nonPersistent",
+		"-n",
+		":4",
+		"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
+
+	if output != expected {
+		t.Errorf("expected: %q, got: %q", expected, output)
+	}
+}
diff --git a/doc/man_docs_test.go b/doc/man_docs_test.go
index aa3f5f2..f3fe3d6 100644
--- a/doc/man_docs_test.go
+++ b/doc/man_docs_test.go
@@ -131,7 +131,7 @@ func TestGenManSeeAlso(t *testing.T) {
 	if err := assertNextLineEquals(scanner, ".PP"); err != nil {
 		t.Fatalf("First line after SEE ALSO wasn't break-indent: %v", err)
 	}
-	if err := assertNextLineEquals(scanner, `\fBroot\-bbb(1)\fP, \fBroot\-ccc(1)\fP`); err != nil {
+	if err := assertNextLineEquals(scanner, `\fBroot-bbb(1)\fP, \fBroot-ccc(1)\fP`); err != nil {
 		t.Fatalf("Second line after SEE ALSO wasn't correct: %v", err)
 	}
 }