vendor: update all dependencies

This commit is contained in:
Nick Craig-Wood 2017-07-23 08:51:42 +01:00
parent 0b6fba34a3
commit eb87cf6f12
2008 changed files with 352633 additions and 1004750 deletions

View file

@ -127,10 +127,10 @@ tree is assigned to the commander which is finally executed.
# Installing
Using Cobra is easy. First, use `go get` to install the latest version
of the library. This command will install the `cobra` generator executible
along with the library:
of the library. This command will install the `cobra` generator executable
along with the library and its dependencies:
go get -v github.com/spf13/cobra/cobra
go get -u github.com/spf13/cobra/cobra
Next, include Cobra in your application:
@ -140,8 +140,8 @@ import "github.com/spf13/cobra"
# Getting Started
While you are welcome to provide your own organization, typically a Cobra based
application will follow the following organizational structure.
While you are welcome to provide your own organization, typically a Cobra-based
application will follow the following organizational structure:
```
▾ appName/
@ -153,7 +153,7 @@ application will follow the following organizational structure.
main.go
```
In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra.
In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra.
```go
package main
@ -216,10 +216,11 @@ cobra add create -p 'configCmd'
```
*Note: Use camelCase (not snake_case/snake-case) for command names.
Otherwise, you will become unexpected errors.
Otherwise, you will encounter errors.
For example, `cobra add add-user` is incorrect, but `cobra add addUser` is valid.*
Once you have run these three commands you would have an app structure that would look like:
Once you have run these three commands you would have an app structure similar to
the following:
```
▾ app/
@ -230,16 +231,16 @@ Once you have run these three commands you would have an app structure that woul
main.go
```
at this point you can run `go run main.go` and it would run your app. `go run
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.
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.
Obviously you haven't added your own code to these yet. The commands are ready
for you to give them their tasks. Have fun!
### Configuring the cobra generator
The cobra generator will be easier to use if you provide a simple configuration
The Cobra generator will be easier to use if you provide a simple configuration
file which will help you eliminate providing a bunch of repeated information in
flags over and over.
@ -269,14 +270,13 @@ You can also use built-in licenses. For example, **GPLv2**, **GPLv3**, **LGPL**,
## Manually implementing Cobra
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.
### Create the root command
The root command represents your binary itself.
#### Manually create rootCmd
Cobra doesn't require any special constructors. Simply create your commands.
@ -298,9 +298,18 @@ var RootCmd = &cobra.Command{
You will additionally define flags and handle configuration in your init() function.
for example cmd/root.go:
For example cmd/root.go:
```go
import (
"fmt"
"os"
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func init() {
cobra.OnInitialize(initConfig)
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
@ -314,6 +323,34 @@ func init() {
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache")
}
func Execute() {
RootCmd.Execute()
}
func initConfig() {
// Don't forget to read config either from cfgFile or from home directory!
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// Search config in home directory with name ".cobra" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".cobra")
}
if err := viper.ReadInConfig(); err != nil {
fmt.Println("Can't read config:", err)
os.Exit(1)
}
}
```
### Create your main.go
@ -341,7 +378,6 @@ func main() {
}
```
### Create additional commands
Additional commands can be defined and typically are each given their own file
@ -431,6 +467,23 @@ A flag can also be assigned locally which will only apply to that specific comma
RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
```
### Bind Flags with Config
You can also bind your flags with [viper](https://github.com/spf13/viper):
```go
var author string
func init() {
RootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author"))
}
```
In this example the persistent flag `author` is bound with `viper`.
**Note**, that the variable `author` will not be set to the value from config,
when the `--author` flag is not provided by user.
More in [viper documentation](https://github.com/spf13/viper#working-with-flags).
## Example

View file

@ -1,6 +1,7 @@
package cobra
import (
"bytes"
"fmt"
"io"
"os"
@ -18,12 +19,9 @@ const (
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
)
func preamble(out io.Writer, name string) error {
_, err := fmt.Fprintf(out, "# bash completion for %-36s -*- shell-script -*-\n", name)
if err != nil {
return err
}
preamStr := `
func writePreamble(buf *bytes.Buffer, name string) {
buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
buf.WriteString(`
__debug()
{
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
@ -134,7 +132,10 @@ __handle_reply()
declare -F __custom_func >/dev/null && __custom_func
fi
__ltrim_colon_completions "$cur"
# available in bash-completion >= 2, not always present on macOS
if declare -F __ltrim_colon_completions >/dev/null; then
__ltrim_colon_completions "$cur"
fi
}
# The arguments should be in the form "ext1|ext2|extn"
@ -247,18 +248,13 @@ __handle_word()
__handle_word
}
`
_, err = fmt.Fprint(out, preamStr)
return err
`)
}
func postscript(w io.Writer, name string) error {
func writePostscript(buf *bytes.Buffer, name string) {
name = strings.Replace(name, ":", "__", -1)
_, err := fmt.Fprintf(w, "__start_%s()\n", name)
if err != nil {
return err
}
_, err = fmt.Fprintf(w, `{
buf.WriteString(fmt.Sprintf("__start_%s()\n", name))
buf.WriteString(fmt.Sprintf(`{
local cur prev words cword
declare -A flaghash 2>/dev/null || :
if declare -F _init_completion >/dev/null 2>&1; then
@ -282,197 +278,132 @@ func postscript(w io.Writer, name string) error {
__handle_word
}
`, name)
if err != nil {
return err
}
_, err = fmt.Fprintf(w, `if [[ $(type -t compopt) = "builtin" ]]; then
`, name))
buf.WriteString(fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then
complete -o default -F __start_%s %s
else
complete -o default -o nospace -F __start_%s %s
fi
`, name, name, name, name)
if err != nil {
return err
}
_, err = fmt.Fprintf(w, "# ex: ts=4 sw=4 et filetype=sh\n")
return err
`, name, name, name, name))
buf.WriteString("# ex: ts=4 sw=4 et filetype=sh\n")
}
func writeCommands(cmd *Command, w io.Writer) error {
if _, err := fmt.Fprintf(w, " commands=()\n"); err != nil {
return err
}
func writeCommands(buf *bytes.Buffer, cmd *Command) {
buf.WriteString(" commands=()\n")
for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() || c == cmd.helpCommand {
continue
}
if _, err := fmt.Fprintf(w, " commands+=(%q)\n", c.Name()); err != nil {
return err
}
buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name()))
}
_, err := fmt.Fprintf(w, "\n")
return err
buf.WriteString("\n")
}
func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) error {
func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string) {
for key, value := range annotations {
switch key {
case BashCompFilenameExt:
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
if err != nil {
return err
}
buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
var ext string
if len(value) > 0 {
ext := "__handle_filename_extension_flag " + strings.Join(value, "|")
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
ext = "__handle_filename_extension_flag " + strings.Join(value, "|")
} else {
ext := "_filedir"
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
}
if err != nil {
return err
ext = "_filedir"
}
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext))
case BashCompCustom:
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
if err != nil {
return err
}
buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
if len(value) > 0 {
handlers := strings.Join(value, "; ")
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", handlers)
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", handlers))
} else {
_, err = fmt.Fprintf(w, " flags_completion+=(:)\n")
}
if err != nil {
return err
buf.WriteString(" flags_completion+=(:)\n")
}
case BashCompSubdirsInDir:
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
var ext string
if len(value) == 1 {
ext := "__handle_subdirs_in_dir_flag " + value[0]
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
ext = "__handle_subdirs_in_dir_flag " + value[0]
} else {
ext := "_filedir -d"
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
}
if err != nil {
return err
ext = "_filedir -d"
}
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext))
}
}
return nil
}
func writeShortFlag(flag *pflag.Flag, w io.Writer) error {
b := (len(flag.NoOptDefVal) > 0)
func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag) {
name := flag.Shorthand
format := " "
if !b {
if len(flag.NoOptDefVal) == 0 {
format += "two_word_"
}
format += "flags+=(\"-%s\")\n"
if _, err := fmt.Fprintf(w, format, name); err != nil {
return err
}
return writeFlagHandler("-"+name, flag.Annotations, w)
buf.WriteString(fmt.Sprintf(format, name))
writeFlagHandler(buf, "-"+name, flag.Annotations)
}
func writeFlag(flag *pflag.Flag, w io.Writer) error {
b := (len(flag.NoOptDefVal) > 0)
func writeFlag(buf *bytes.Buffer, flag *pflag.Flag) {
name := flag.Name
format := " flags+=(\"--%s"
if !b {
if len(flag.NoOptDefVal) == 0 {
format += "="
}
format += "\")\n"
if _, err := fmt.Fprintf(w, format, name); err != nil {
return err
}
return writeFlagHandler("--"+name, flag.Annotations, w)
buf.WriteString(fmt.Sprintf(format, name))
writeFlagHandler(buf, "--"+name, flag.Annotations)
}
func writeLocalNonPersistentFlag(flag *pflag.Flag, w io.Writer) error {
b := (len(flag.NoOptDefVal) > 0)
func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) {
name := flag.Name
format := " local_nonpersistent_flags+=(\"--%s"
if !b {
if len(flag.NoOptDefVal) == 0 {
format += "="
}
format += "\")\n"
_, err := fmt.Fprintf(w, format, name)
return err
buf.WriteString(fmt.Sprintf(format, name))
}
func writeFlags(cmd *Command, w io.Writer) error {
_, err := fmt.Fprintf(w, ` flags=()
func writeFlags(buf *bytes.Buffer, cmd *Command) {
buf.WriteString(` flags=()
two_word_flags=()
local_nonpersistent_flags=()
flags_with_completion=()
flags_completion=()
`)
if err != nil {
return err
}
localNonPersistentFlags := cmd.LocalNonPersistentFlags()
var visitErr error
cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
if nonCompletableFlag(flag) {
return
}
if err := writeFlag(flag, w); err != nil {
visitErr = err
return
}
writeFlag(buf, flag)
if len(flag.Shorthand) > 0 {
if err := writeShortFlag(flag, w); err != nil {
visitErr = err
return
}
writeShortFlag(buf, flag)
}
if localNonPersistentFlags.Lookup(flag.Name) != nil {
if err := writeLocalNonPersistentFlag(flag, w); err != nil {
visitErr = err
return
}
writeLocalNonPersistentFlag(buf, flag)
}
})
if visitErr != nil {
return visitErr
}
cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
if nonCompletableFlag(flag) {
return
}
if err := writeFlag(flag, w); err != nil {
visitErr = err
return
}
writeFlag(buf, flag)
if len(flag.Shorthand) > 0 {
if err := writeShortFlag(flag, w); err != nil {
visitErr = err
return
}
writeShortFlag(buf, flag)
}
})
if visitErr != nil {
return visitErr
}
_, err = fmt.Fprintf(w, "\n")
return err
buf.WriteString("\n")
}
func writeRequiredFlag(cmd *Command, w io.Writer) error {
if _, err := fmt.Fprintf(w, " must_have_one_flag=()\n"); err != nil {
return err
}
func writeRequiredFlag(buf *bytes.Buffer, cmd *Command) {
buf.WriteString(" must_have_one_flag=()\n")
flags := cmd.NonInheritedFlags()
var visitErr error
flags.VisitAll(func(flag *pflag.Flag) {
if nonCompletableFlag(flag) {
return
@ -481,107 +412,68 @@ func writeRequiredFlag(cmd *Command, w io.Writer) error {
switch key {
case BashCompOneRequiredFlag:
format := " must_have_one_flag+=(\"--%s"
b := (flag.Value.Type() == "bool")
if !b {
if flag.Value.Type() != "bool" {
format += "="
}
format += "\")\n"
if _, err := fmt.Fprintf(w, format, flag.Name); err != nil {
visitErr = err
return
}
buf.WriteString(fmt.Sprintf(format, flag.Name))
if len(flag.Shorthand) > 0 {
if _, err := fmt.Fprintf(w, " must_have_one_flag+=(\"-%s\")\n", flag.Shorthand); err != nil {
visitErr = err
return
}
buf.WriteString(fmt.Sprintf(" must_have_one_flag+=(\"-%s\")\n", flag.Shorthand))
}
}
}
})
return visitErr
}
func writeRequiredNouns(cmd *Command, w io.Writer) error {
if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil {
return err
}
func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) {
buf.WriteString(" must_have_one_noun=()\n")
sort.Sort(sort.StringSlice(cmd.ValidArgs))
for _, value := range cmd.ValidArgs {
if _, err := fmt.Fprintf(w, " must_have_one_noun+=(%q)\n", value); err != nil {
return err
}
buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value))
}
return nil
}
func writeArgAliases(cmd *Command, w io.Writer) error {
if _, err := fmt.Fprintf(w, " noun_aliases=()\n"); err != nil {
return err
}
func writeArgAliases(buf *bytes.Buffer, cmd *Command) {
buf.WriteString(" noun_aliases=()\n")
sort.Sort(sort.StringSlice(cmd.ArgAliases))
for _, value := range cmd.ArgAliases {
if _, err := fmt.Fprintf(w, " noun_aliases+=(%q)\n", value); err != nil {
return err
}
buf.WriteString(fmt.Sprintf(" noun_aliases+=(%q)\n", value))
}
return nil
}
func gen(cmd *Command, w io.Writer) error {
func gen(buf *bytes.Buffer, cmd *Command) {
for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() || c == cmd.helpCommand {
continue
}
if err := gen(c, w); err != nil {
return err
}
gen(buf, c)
}
commandName := cmd.CommandPath()
commandName = strings.Replace(commandName, " ", "_", -1)
commandName = strings.Replace(commandName, ":", "__", -1)
if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil {
return err
}
if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil {
return err
}
if err := writeCommands(cmd, w); err != nil {
return err
}
if err := writeFlags(cmd, w); err != nil {
return err
}
if err := writeRequiredFlag(cmd, w); err != nil {
return err
}
if err := writeRequiredNouns(cmd, w); err != nil {
return err
}
if err := writeArgAliases(cmd, w); err != nil {
return err
}
if _, err := fmt.Fprintf(w, "}\n\n"); err != nil {
return err
}
return nil
buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName))
buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName))
writeCommands(buf, cmd)
writeFlags(buf, cmd)
writeRequiredFlag(buf, cmd)
writeRequiredNouns(buf, cmd)
writeArgAliases(buf, cmd)
buf.WriteString("}\n\n")
}
// GenBashCompletion generates bash completion file and writes to the passed writer.
func (cmd *Command) GenBashCompletion(w io.Writer) error {
if err := preamble(w, cmd.Name()); err != nil {
return err
}
buf := new(bytes.Buffer)
writePreamble(buf, cmd.Name())
if len(cmd.BashCompletionFunction) > 0 {
if _, err := fmt.Fprintf(w, "%s\n", cmd.BashCompletionFunction); err != nil {
return err
}
buf.WriteString(cmd.BashCompletionFunction + "\n")
}
if err := gen(cmd, w); err != nil {
return err
}
return postscript(w, cmd.Name())
gen(buf, cmd)
writePostscript(buf, cmd.Name())
_, err := buf.WriteTo(w)
return err
}
func nonCompletableFlag(flag *pflag.Flag) bool {

View file

@ -2,16 +2,12 @@ package cobra
import (
"bytes"
"fmt"
"os"
"os/exec"
"strings"
"testing"
)
var _ = fmt.Println
var _ = os.Stderr
func checkOmit(t *testing.T, found, unexpected string) {
if strings.Contains(found, unexpected) {
t.Errorf("Unexpected response.\nGot: %q\nBut should not have!\n", unexpected)
@ -178,3 +174,19 @@ func TestBashCompletionDeprecatedFlag(t *testing.T) {
t.Errorf("expected completion to not include %q flag: Got %v", flagName, bashCompletion)
}
}
func BenchmarkBashCompletion(b *testing.B) {
c := initializeWithRootCmd()
cmdEcho.AddCommand(cmdTimes)
c.AddCommand(cmdEcho, cmdPrint, cmdDeprecated, cmdColon)
buf := new(bytes.Buffer)
b.ResetTimer()
for i := 0; i < b.N; i++ {
buf.Reset()
if err := c.GenBashCompletion(buf); err != nil {
b.Fatal(err)
}
}
}

View file

@ -47,6 +47,15 @@ var EnablePrefixMatching = false
// To disable sorting, set it to false.
var EnableCommandSorting = true
// MousetrapHelpText enables an information splash screen on Windows
// if the CLI is started from explorer.exe.
// To disable the mousetrap, just set this variable to blank string ("").
// Works only on Microsoft Windows.
var MousetrapHelpText string = `This is a command line tool.
You need to open cmd.exe and run it from there.
`
// AddTemplateFunc adds a template function that's available to Usage and Help
// template generation.
func AddTemplateFunc(name string, tmplFunc interface{}) {

View file

@ -23,10 +23,11 @@ import (
)
func init() {
addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)")
addCmd.Flags().StringVarP(&parentName, "parent", "p", "RootCmd", "name of parent command for this command")
}
var parentName string
var packageName, parentName string
var addCmd = &cobra.Command{
Use: "add [command name]",
@ -45,11 +46,17 @@ Example: cobra add server -> resulting in a new cmd/server.go`,
if len(args) < 1 {
er("add needs a name for the command")
}
wd, err := os.Getwd()
if err != nil {
er(err)
var project *Project
if packageName != "" {
project = NewProject(packageName)
} else {
wd, err := os.Getwd()
if err != nil {
er(err)
}
project = NewProjectFromPath(wd)
}
project := NewProjectFromPath(wd)
cmdName := validateCmdName(args[0])
cmdPath := filepath.Join(project.CmdPath(), cmdName+".go")

View file

@ -23,19 +23,16 @@ import (
"text/template"
)
var projectPath string
var cmdDirs = [...]string{"cmd", "cmds", "command", "commands"}
var srcPaths []string
func init() {
// Initialize goPaths and srcPaths
// Initialize srcPaths.
envGoPath := os.Getenv("GOPATH")
if envGoPath == "" {
goPaths := filepath.SplitList(envGoPath)
if len(goPaths) == 0 {
er("$GOPATH is not set")
}
goPaths := filepath.SplitList(envGoPath)
srcPaths = make([]string, 0, len(goPaths))
for _, goPath := range goPaths {
srcPaths = append(srcPaths, filepath.Join(goPath, "src"))
@ -48,24 +45,34 @@ func er(msg interface{}) {
}
// isEmpty checks if a given path is empty.
// Hidden files in path are ignored.
func isEmpty(path string) bool {
fi, err := os.Stat(path)
if err != nil {
er(err)
}
if fi.IsDir() {
f, err := os.Open(path)
if err != nil {
er(err)
}
defer f.Close()
dirs, err := f.Readdirnames(1)
if err != nil && err != io.EOF {
er(err)
}
return len(dirs) == 0
if !fi.IsDir() {
return fi.Size() == 0
}
return fi.Size() == 0
f, err := os.Open(path)
if err != nil {
er(err)
}
defer f.Close()
names, err := f.Readdirnames(-1)
if err != nil && err != io.EOF {
er(err)
}
for _, name := range names {
if len(name) > 0 && name[0] != '.' {
return false
}
}
return true
}
// exists checks if a file or directory exists.

View file

@ -59,7 +59,7 @@ Init will not use an existing directory with contents.`,
project = NewProject(arg)
}
} else {
er("please enter the name")
er("please provide only one argument")
}
initializeProject(project)
@ -142,13 +142,13 @@ package cmd
import (
"fmt"
"os"
{{if .viper}}
homedir "github.com/mitchellh/go-homedir"{{end}}
"github.com/spf13/cobra"{{if .viper}}
"github.com/spf13/viper"{{end}}
){{if .viper}}
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
{{if .viper}} "github.com/spf13/viper"{{end}}
)
{{if .viper}}var cfgFile string{{end}}
var cfgFile string{{end}}
// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
@ -165,7 +165,7 @@ to quickly create a Cobra application.` + "`" + `,
// Run: func(cmd *cobra.Command, args []string) { },
}
// Execute adds all child commands to the root command sets flags appropriately.
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := RootCmd.Execute(); err != nil {
@ -174,9 +174,9 @@ func Execute() {
}
}
func init() {
{{if .viper}} cobra.OnInitialize(initConfig){{end}}
func init() { {{if .viper}}
cobra.OnInitialize(initConfig)
{{end}}
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.{{ if .viper }}
@ -197,13 +197,13 @@ func initConfig() {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(home)
fmt.Println(err)
os.Exit(1)
}
// Search config in home directory with name ".cobra" (without extension).
// Search config in home directory with name ".{{ .appName }}" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".cobra")
viper.SetConfigName(".{{ .appName }}")
}
viper.AutomaticEnv() // read in environment variables that match

View file

@ -54,7 +54,9 @@ func TestGoldenInitCmd(t *testing.T) {
if err != nil {
return err
}
ioutil.WriteFile(goldenPath, got, 0644)
if err := ioutil.WriteFile(goldenPath, got, 0644); err != nil {
t.Fatal("Error while updating file:", err)
}
}
return compareFiles(path, goldenPath)
}

View file

@ -3,6 +3,7 @@ package cmd
import (
"os"
"path/filepath"
"runtime"
"strings"
)
@ -37,7 +38,7 @@ func NewProject(projectName string) *Project {
}
for _, srcPath := range srcPaths {
goPath := filepath.Dir(srcPath)
if filepath.HasPrefix(wd, goPath) {
if filepathHasPrefix(wd, goPath) {
p.absPath = filepath.Join(srcPath, projectName)
break
}
@ -90,7 +91,7 @@ func NewProjectFromPath(absPath string) *Project {
func trimSrcPath(absPath, srcPath string) string {
relPath, err := filepath.Rel(srcPath, absPath)
if err != nil {
er("Cobra supports project only within $GOPATH")
er("Cobra supports project only within $GOPATH: " + err.Error())
}
return relPath
}
@ -172,7 +173,7 @@ func (p *Project) SrcPath() string {
}
for _, srcPath := range srcPaths {
if strings.HasPrefix(p.absPath, srcPath) {
if filepathHasPrefix(p.absPath, srcPath) {
p.srcPath = srcPath
break
}
@ -180,3 +181,15 @@ func (p *Project) SrcPath() string {
return p.srcPath
}
func filepathHasPrefix(path string, prefix string) bool {
if len(path) <= len(prefix) {
return false
}
if runtime.GOOS == "windows" {
// Paths in windows are case-insensitive.
return strings.EqualFold(path[0:len(prefix)], prefix)
}
return path[0:len(prefix)] == prefix
}

View file

@ -1,7 +1,6 @@
package cmd
import (
"path/filepath"
"testing"
)
@ -17,7 +16,7 @@ func TestFindExistingPackage(t *testing.T) {
func hasGoPathPrefix(path string) bool {
for _, srcPath := range srcPaths {
if filepath.HasPrefix(path, srcPath) {
if filepathHasPrefix(path, srcPath) {
return true
}
}

View file

@ -15,48 +15,44 @@ package cmd
import (
"fmt"
"os"
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var cfgFile, projectBase, userLicense string // are used for flags
var (
// Used for flags.
cfgFile, userLicense string
var rootCmd = &cobra.Command{
Use: "cobra",
Short: "A generator for Cobra based Applications",
Long: `Cobra is a CLI library for Go that empowers applications.
rootCmd = &cobra.Command{
Use: "cobra",
Short: "A generator for Cobra based Applications",
Long: `Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
}
}
)
// Execute executes the root command.
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
rootCmd.Execute()
}
func init() {
initViper()
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
rootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory, e.g. github.com/spf13/")
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 `license` in config)")
rootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
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")
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase"))
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache")
rootCmd.AddCommand(initCmd)
rootCmd.AddCommand(addCmd)
rootCmd.AddCommand(initCmd)
}
func initViper() {
@ -67,8 +63,7 @@ func initViper() {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(home)
os.Exit(1)
er(err)
}
// Search config in home directory with name ".cobra" (without extension).

View file

@ -39,7 +39,7 @@ to quickly create a Cobra application.`,
// Run: func(cmd *cobra.Command, args []string) { },
}
// Execute adds all child commands to the root command sets flags appropriately.
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := RootCmd.Execute(); err != nil {
@ -48,7 +48,7 @@ func Execute() {
}
}
func init() {
func init() {
cobra.OnInitialize(initConfig)
// Here you will define your flags and configuration settings.
@ -70,13 +70,13 @@ func initConfig() {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(home)
fmt.Println(err)
os.Exit(1)
}
// Search config in home directory with name ".cobra" (without extension).
// Search config in home directory with name ".testproject" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".cobra")
viper.SetConfigName(".testproject")
}
viper.AutomaticEnv() // read in environment variables that match

View file

@ -13,13 +13,12 @@ import (
"github.com/spf13/pflag"
)
var tp, te, tt, t1, tr []string
var tp, te, tt, tr []string
var rootPersPre, echoPre, echoPersPre, timesPersPre []string
var flagb1, flagb2, flagb3, flagbr, flagbp bool
var flags1, flags2a, flags2b, flags3, outs string
var flagi1, flagi2, flagi3, flagi4, flagir int
var globalFlag1 bool
var flagEcho, rootcalled bool
var rootcalled bool
var versionUsed int
const strtwoParentHelp = "help message for parent flag strtwo"
@ -227,36 +226,36 @@ type resulter struct {
Command *Command
}
func fullSetupTest(input string) resulter {
func fullSetupTest(args ...string) resulter {
c := initializeWithRootCmd()
return fullTester(c, input)
return fullTester(c, args...)
}
func noRRSetupTestSilenced(input string) resulter {
func noRRSetupTestSilenced(args ...string) resulter {
c := initialize()
c.SilenceErrors = true
c.SilenceUsage = true
return fullTester(c, input)
return fullTester(c, args...)
}
func noRRSetupTest(input string) resulter {
func noRRSetupTest(args ...string) resulter {
c := initialize()
return fullTester(c, input)
return fullTester(c, args...)
}
func rootOnlySetupTest(input string) resulter {
func rootOnlySetupTest(args ...string) resulter {
c := initializeWithRootCmd()
return simpleTester(c, input)
return simpleTester(c, args...)
}
func simpleTester(c *Command, input string) resulter {
func simpleTester(c *Command, args ...string) resulter {
buf := new(bytes.Buffer)
// Testing flag with invalid input
c.SetOutput(buf)
c.SetArgs(strings.Split(input, " "))
c.SetArgs(args)
err := c.Execute()
output := buf.String()
@ -264,11 +263,11 @@ func simpleTester(c *Command, input string) resulter {
return resulter{err, output, c}
}
func simpleTesterC(c *Command, input string) resulter {
func simpleTesterC(c *Command, args ...string) resulter {
buf := new(bytes.Buffer)
// Testing flag with invalid input
c.SetOutput(buf)
c.SetArgs(strings.Split(input, " "))
c.SetArgs(args)
cmd, err := c.ExecuteC()
output := buf.String()
@ -276,13 +275,13 @@ func simpleTesterC(c *Command, input string) resulter {
return resulter{err, output, cmd}
}
func fullTester(c *Command, input string) resulter {
func fullTester(c *Command, args ...string) resulter {
buf := new(bytes.Buffer)
// Testing flag with invalid input
c.SetOutput(buf)
cmdEcho.AddCommand(cmdTimes)
c.AddCommand(cmdPrint, cmdEcho, cmdSubNoRun, cmdCustomFlags, cmdDeprecated)
c.SetArgs(strings.Split(input, " "))
c.SetArgs(args)
err := c.Execute()
output := buf.String()
@ -332,7 +331,7 @@ func checkOutputContains(t *testing.T, c *Command, check string) {
}
func TestSingleCommand(t *testing.T) {
noRRSetupTest("print one two")
noRRSetupTest("print", "one", "two")
if te != nil || tt != nil {
t.Error("Wrong command called")
@ -346,7 +345,7 @@ func TestSingleCommand(t *testing.T) {
}
func TestChildCommand(t *testing.T) {
noRRSetupTest("echo times one two")
noRRSetupTest("echo", "times", "one", "two")
if te != nil || tp != nil {
t.Error("Wrong command called")
@ -360,7 +359,7 @@ func TestChildCommand(t *testing.T) {
}
func TestCommandAlias(t *testing.T) {
noRRSetupTest("say times one two")
noRRSetupTest("say", "times", "one", "two")
if te != nil || tp != nil {
t.Error("Wrong command called")
@ -375,7 +374,7 @@ func TestCommandAlias(t *testing.T) {
func TestPrefixMatching(t *testing.T) {
EnablePrefixMatching = true
noRRSetupTest("ech times one two")
noRRSetupTest("ech", "times", "one", "two")
if te != nil || tp != nil {
t.Error("Wrong command called")
@ -393,7 +392,7 @@ func TestPrefixMatching(t *testing.T) {
func TestNoPrefixMatching(t *testing.T) {
EnablePrefixMatching = false
noRRSetupTest("ech times one two")
noRRSetupTest("ech", "times", "one", "two")
if !(tt == nil && te == nil && tp == nil) {
t.Error("Wrong command called")
@ -402,7 +401,7 @@ func TestNoPrefixMatching(t *testing.T) {
func TestAliasPrefixMatching(t *testing.T) {
EnablePrefixMatching = true
noRRSetupTest("sa times one two")
noRRSetupTest("sa", "times", "one", "two")
if te != nil || tp != nil {
t.Error("Wrong command called")
@ -419,7 +418,7 @@ func TestAliasPrefixMatching(t *testing.T) {
func TestChildSameName(t *testing.T) {
c := initializeWithSameName()
c.AddCommand(cmdPrint, cmdEcho)
c.SetArgs(strings.Split("print one two", " "))
c.SetArgs([]string{"print", "one", "two"})
c.Execute()
if te != nil || tt != nil {
@ -437,7 +436,7 @@ func TestGrandChildSameName(t *testing.T) {
c := initializeWithSameName()
cmdTimes.AddCommand(cmdPrint)
c.AddCommand(cmdTimes)
c.SetArgs(strings.Split("times print one two", " "))
c.SetArgs([]string{"times", "print", "one", "two"})
c.Execute()
if te != nil || tt != nil {
@ -454,13 +453,13 @@ func TestGrandChildSameName(t *testing.T) {
func TestUsage(t *testing.T) {
x := fullSetupTest("help")
checkResultContains(t, x, cmdRootWithRun.Use+" [flags]")
x = fullSetupTest("help customflags")
x = fullSetupTest("help", "customflags")
checkResultContains(t, x, cmdCustomFlags.Use)
checkResultOmits(t, x, cmdCustomFlags.Use+" [flags]")
}
func TestFlagLong(t *testing.T) {
noRRSetupTest("echo --intone=13 something -- here")
noRRSetupTest("echo", "--intone=13", "something", "--", "here")
if cmdEcho.ArgsLenAtDash() != 1 {
t.Errorf("expected argsLenAtDash: %d but got %d", 1, cmdRootNoRun.ArgsLenAtDash())
@ -477,7 +476,7 @@ func TestFlagLong(t *testing.T) {
}
func TestFlagShort(t *testing.T) {
noRRSetupTest("echo -i13 -- something here")
noRRSetupTest("echo", "-i13", "--", "something", "here")
if cmdEcho.ArgsLenAtDash() != 0 {
t.Errorf("expected argsLenAtDash: %d but got %d", 0, cmdRootNoRun.ArgsLenAtDash())
@ -492,7 +491,7 @@ func TestFlagShort(t *testing.T) {
t.Errorf("default flag value changed, 234 expected, %d given", flagi2)
}
noRRSetupTest("echo -i 13 something here")
noRRSetupTest("echo", "-i", "13", "something", "here")
if strings.Join(te, " ") != "something here" {
t.Errorf("flags didn't leave proper args remaining..%s given", te)
@ -504,7 +503,7 @@ func TestFlagShort(t *testing.T) {
t.Errorf("default flag value changed, 234 expected, %d given", flagi2)
}
noRRSetupTest("print -i99 one two")
noRRSetupTest("print", "-i99", "one", "two")
if strings.Join(tp, " ") != "one two" {
t.Errorf("flags didn't leave proper args remaining..%s given", tp)
@ -518,14 +517,14 @@ func TestFlagShort(t *testing.T) {
}
func TestChildCommandFlags(t *testing.T) {
noRRSetupTest("echo times -j 99 one two")
noRRSetupTest("echo", "times", "-j", "99", "one", "two")
if strings.Join(tt, " ") != "one two" {
t.Errorf("flags didn't leave proper args remaining..%s given", tt)
}
// Testing with flag that shouldn't be persistent
r := noRRSetupTest("echo times -j 99 -i77 one two")
r := noRRSetupTest("echo", "times", "-j", "99", "-i77", "one", "two")
if r.Error == nil {
t.Errorf("invalid flag should generate error")
@ -544,7 +543,7 @@ func TestChildCommandFlags(t *testing.T) {
}
// Testing with flag only existing on child
r = noRRSetupTest("echo -j 99 -i77 one two")
r = noRRSetupTest("echo", "-j", "99", "-i77", "one", "two")
if r.Error == nil {
t.Errorf("invalid flag should generate error")
@ -554,7 +553,7 @@ func TestChildCommandFlags(t *testing.T) {
}
// Testing with persistent flag overwritten by child
noRRSetupTest("echo times --strtwo=child one two")
noRRSetupTest("echo", "times", "--strtwo=child", "one", "two")
if flags2b != "child" {
t.Errorf("flag value should be child, %s given", flags2b)
@ -565,7 +564,7 @@ func TestChildCommandFlags(t *testing.T) {
}
// Testing flag with invalid input
r = noRRSetupTest("echo -i10E")
r = noRRSetupTest("echo", "-i10E")
if r.Error == nil {
t.Errorf("invalid input should generate error")
@ -576,7 +575,7 @@ func TestChildCommandFlags(t *testing.T) {
}
func TestTrailingCommandFlags(t *testing.T) {
x := fullSetupTest("echo two -x")
x := fullSetupTest("echo", "two", "-x")
if x.Error == nil {
t.Errorf("invalid flag should generate error")
@ -587,7 +586,7 @@ func TestInvalidSubcommandFlags(t *testing.T) {
cmd := initializeWithRootCmd()
cmd.AddCommand(cmdTimes)
result := simpleTester(cmd, "times --inttwo=2 --badflag=bar")
result := simpleTester(cmd, "times", "--inttwo=2", "--badflag=bar")
// given that we are not checking here result.Error we check for
// stock usage message
checkResultContains(t, result, "cobra-test times [# times]")
@ -617,14 +616,14 @@ func TestSubcommandExecuteC(t *testing.T) {
cmd.AddCommand(double, echo)
result := simpleTesterC(cmd, "double hello world")
result := simpleTesterC(cmd, "double", "hello", "world")
checkResultContains(t, result, "hello world hello world")
if result.Command.Name() != "double" {
t.Errorf("invalid cmd returned from ExecuteC: should be 'double' but got %s", result.Command.Name())
}
result = simpleTesterC(cmd, "echo msg to be echoed")
result = simpleTesterC(cmd, "echo", "msg", "to", "be", "echoed")
checkResultContains(t, result, "msg to be echoed")
if result.Command.Name() != "echo" {
@ -650,16 +649,16 @@ func TestSubcommandArgEvaluation(t *testing.T) {
}
first.AddCommand(second)
result := simpleTester(cmd, "first second first third")
result := simpleTester(cmd, "first", "second", "first", "third")
expectedOutput := fmt.Sprintf("%v", []string{"first third"})
expectedOutput := fmt.Sprint([]string{"first third"})
if result.Output != expectedOutput {
t.Errorf("exptected %v, got %v", expectedOutput, result.Output)
}
}
func TestPersistentFlags(t *testing.T) {
fullSetupTest("echo -s something -p more here")
fullSetupTest("echo", "-s", "something", "-p", "more", "here")
// persistentFlag should act like normal flag on its own command
if strings.Join(te, " ") != "more here" {
@ -673,7 +672,7 @@ func TestPersistentFlags(t *testing.T) {
}
// persistentFlag should act like normal flag on its own command
fullSetupTest("echo times -s again -c -p test here")
fullSetupTest("echo", "times", "-s", "again", "-c", "-p", "test", "here")
if strings.Join(tt, " ") != "test here" {
t.Errorf("flags didn't leave proper args remaining. %s given", tt)
@ -695,17 +694,17 @@ func TestHelpCommand(t *testing.T) {
x := fullSetupTest("help")
checkResultContains(t, x, cmdRootWithRun.Long)
x = fullSetupTest("help echo")
x = fullSetupTest("help", "echo")
checkResultContains(t, x, cmdEcho.Long)
x = fullSetupTest("help echo times")
x = fullSetupTest("help", "echo", "times")
checkResultContains(t, x, cmdTimes.Long)
}
func TestChildCommandHelp(t *testing.T) {
c := noRRSetupTest("print --help")
c := noRRSetupTest("print", "--help")
checkResultContains(t, c, strtwoParentHelp)
r := noRRSetupTest("echo times --help")
r := noRRSetupTest("echo", "times", "--help")
checkResultContains(t, r, strtwoChildHelp)
}
@ -717,7 +716,7 @@ func TestNonRunChildHelp(t *testing.T) {
func TestRunnableRootCommand(t *testing.T) {
x := fullSetupTest("")
if rootcalled != true {
if !rootcalled {
t.Errorf("Root Function was not called\n out:%v", x.Error)
}
}
@ -751,7 +750,6 @@ func TestVisitParents(t *testing.T) {
}
func TestRunnableRootCommandNilInput(t *testing.T) {
var emptyArg []string
c := initializeWithRootCmd()
buf := new(bytes.Buffer)
@ -759,23 +757,20 @@ func TestRunnableRootCommandNilInput(t *testing.T) {
c.SetOutput(buf)
cmdEcho.AddCommand(cmdTimes)
c.AddCommand(cmdPrint, cmdEcho)
c.SetArgs(emptyArg)
c.SetArgs([]string{})
err := c.Execute()
if err != nil {
t.Errorf("Execute() failed with %v", err)
}
if rootcalled != true {
if !rootcalled {
t.Errorf("Root Function was not called")
}
}
func TestRunnableRootCommandEmptyInput(t *testing.T) {
args := make([]string, 3)
args[0] = ""
args[1] = "--introot=12"
args[2] = ""
args := []string{"", "--introot=12", ""}
c := initializeWithRootCmd()
buf := new(bytes.Buffer)
@ -787,13 +782,13 @@ func TestRunnableRootCommandEmptyInput(t *testing.T) {
c.Execute()
if rootcalled != true {
t.Errorf("Root Function was not called.\n\nOutput was:\n\n%s\n", buf)
if !rootcalled {
t.Errorf("Root Function was not called.\nOutput was:\n%s\n", buf)
}
}
func TestInvalidSubcommandWhenArgsAllowed(t *testing.T) {
fullSetupTest("echo invalid-sub")
fullSetupTest("echo", "invalid-sub")
if te[0] != "invalid-sub" {
t.Errorf("Subcommand didn't work...")
@ -801,9 +796,9 @@ func TestInvalidSubcommandWhenArgsAllowed(t *testing.T) {
}
func TestRootFlags(t *testing.T) {
fullSetupTest("-i 17 -b")
fullSetupTest("-i", "17", "-b")
if flagbr != true {
if !flagbr {
t.Errorf("flag value should be true, %v given", flagbr)
}
@ -826,7 +821,7 @@ func TestRootHelp(t *testing.T) {
t.Errorf("--help shouldn't display subcommand's usage, Got: \n %s", x.Output)
}
x = fullSetupTest("echo --help")
x = fullSetupTest("echo", "--help")
if strings.Contains(x.Output, cmdTimes.Use) {
t.Errorf("--help shouldn't display subsubcommand's usage, Got: \n %s", x.Output)
@ -861,7 +856,6 @@ func TestFlagAccess(t *testing.T) {
}
func TestNoNRunnableRootCommandNilInput(t *testing.T) {
var args []string
c := initialize()
buf := new(bytes.Buffer)
@ -869,7 +863,7 @@ func TestNoNRunnableRootCommandNilInput(t *testing.T) {
c.SetOutput(buf)
cmdEcho.AddCommand(cmdTimes)
c.AddCommand(cmdPrint, cmdEcho)
c.SetArgs(args)
c.SetArgs([]string{})
c.Execute()
@ -888,7 +882,7 @@ func TestRootNoCommandHelp(t *testing.T) {
t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
}
x = rootOnlySetupTest("echo --help")
x = rootOnlySetupTest("echo", "--help")
checkResultOmits(t, x, "Available Commands:")
checkResultOmits(t, x, "for more information about a command")
@ -906,7 +900,7 @@ func TestRootUnknownCommand(t *testing.T) {
t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", s, r.Output)
}
r = noRRSetupTest("--strtwo=a bogus")
r = noRRSetupTest("--strtwo=a", "bogus")
if r.Output != s {
t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", s, r.Output)
}
@ -919,7 +913,7 @@ func TestRootUnknownCommandSilenced(t *testing.T) {
t.Errorf("Unexpected response.\nExpecting to be: \n\"\"\n Got:\n %q\n", r.Output)
}
r = noRRSetupTestSilenced("--strtwo=a bogus")
r = noRRSetupTestSilenced("--strtwo=a", "bogus")
if r.Output != "" {
t.Errorf("Unexpected response.\nExpecting to be:\n\"\"\nGot:\n %q\n", r.Output)
}
@ -966,56 +960,27 @@ func TestRootSuggestions(t *testing.T) {
func TestFlagsBeforeCommand(t *testing.T) {
// short without space
x := fullSetupTest("-i10 echo")
x := fullSetupTest("-i10", "echo")
if x.Error != nil {
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
}
// short (int) with equals
// It appears that pflags doesn't support this...
// Commenting out until support can be added
//x = noRRSetupTest("echo -i=10")
//if x.Error != nil {
//t.Errorf("Valid Input shouldn't have errors, got:\n %s", x.Error)
//}
x = noRRSetupTest("echo", "-i=10")
if x.Error != nil {
t.Errorf("Valid Input shouldn't have errors, got:\n %s", x.Error)
}
// long with equals
x = noRRSetupTest("--intone=123 echo one two")
x = noRRSetupTest("--intone=123", "echo", "one", "two")
if x.Error != nil {
t.Errorf("Valid Input shouldn't have errors, got:\n %s", x.Error)
}
// With parsing error properly reported
x = fullSetupTest("-i10E echo")
x = fullSetupTest("-i10E", "echo")
if !strings.Contains(x.Error.Error(), "invalid syntax") {
t.Errorf("Wrong error message displayed, \n %s", x.Error)
}
//With quotes
x = fullSetupTest("-s=\"walking\" echo")
if x.Error != nil {
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
}
//With quotes and space
x = fullSetupTest("-s=\"walking fast\" echo")
if x.Error != nil {
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
}
//With inner quote
x = fullSetupTest("-s=\"walking \\\"Inner Quote\\\" fast\" echo")
if x.Error != nil {
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
}
//With quotes and space
x = fullSetupTest("-s=\"walking \\\"Inner Quote\\\" fast\" echo")
if x.Error != nil {
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
}
}
func TestRemoveCommand(t *testing.T) {
@ -1081,7 +1046,7 @@ func TestDeprecatedSub(t *testing.T) {
}
func TestPreRun(t *testing.T) {
noRRSetupTest("echo one two")
noRRSetupTest("echo", "one", "two")
if echoPre == nil || echoPersPre == nil {
t.Error("PreRun or PersistentPreRun not called")
}
@ -1089,7 +1054,7 @@ func TestPreRun(t *testing.T) {
t.Error("Wrong *Pre functions called!")
}
noRRSetupTest("echo times one two")
noRRSetupTest("echo", "times", "one", "two")
if timesPersPre == nil {
t.Error("PreRun or PersistentPreRun not called")
}
@ -1097,7 +1062,7 @@ func TestPreRun(t *testing.T) {
t.Error("Wrong *Pre functions called!")
}
noRRSetupTest("print one two")
noRRSetupTest("print", "one", "two")
if rootPersPre == nil {
t.Error("Parent PersistentPreRun not called but should not have been")
}
@ -1115,10 +1080,10 @@ func TestPeristentPreRunPropagation(t *testing.T) {
// Now add cmdPrint to rootCmd
rootCmd.AddCommand(cmdPrint)
rootCmd.SetArgs(strings.Split("print echosub lala", " "))
rootCmd.SetArgs([]string{"print", "echosub", "lala"})
rootCmd.Execute()
if rootPersPre == nil || len(rootPersPre) == 0 || rootPersPre[0] != "lala" {
if len(rootPersPre) == 0 || rootPersPre[0] != "lala" {
t.Error("RootCmd PersistentPreRun not called but should have been")
}
}

View file

@ -430,37 +430,28 @@ func stripFlags(args []string, c *Command) []string {
c.mergePersistentFlags()
commands := []string{}
inQuote := false
flags := c.Flags()
Loop:
for len(args) > 0 {
s := args[0]
args = args[1:]
if !inQuote {
switch {
case strings.HasPrefix(s, "\"") || strings.Contains(s, "=\""):
inQuote = true
case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
// If '--flag arg' then
// delete arg from args.
fallthrough // (do the same as below)
case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
// If '-f arg' then
// delete 'arg' from args or break the loop if len(args) <= 1.
if len(args) <= 1 {
break Loop
} else {
args = args[1:]
continue
}
case s != "" && !strings.HasPrefix(s, "-"):
commands = append(commands, s)
switch {
case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
// If '--flag arg' then
// delete arg from args.
fallthrough // (do the same as below)
case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
// If '-f arg' then
// delete 'arg' from args or break the loop if len(args) <= 1.
if len(args) <= 1 {
break Loop
} else {
args = args[1:]
continue
}
}
if strings.HasSuffix(s, "\"") && !strings.HasSuffix(s, "\\\"") {
inQuote = false
case s != "" && !strings.HasPrefix(s, "-"):
commands = append(commands, s)
}
}
@ -687,7 +678,7 @@ func (c *Command) preRun() {
}
}
// Execute Call execute to use the args (os.Args[1:] by default)
// Execute uses the args (os.Args[1:] by default)
// and run through the command tree finding appropriate matches
// for commands and then corresponding flags.
func (c *Command) Execute() error {
@ -709,7 +700,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
// initialize help as the last point possible to allow for user
// overriding
c.initHelpCmd()
c.InitDefaultHelpCmd()
var args []string
@ -752,9 +743,8 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
if !cmd.SilenceUsage && !c.SilenceUsage {
c.Println(cmd.UsageString())
}
return cmd, err
}
return cmd, nil
return cmd, err
}
// InitDefaultHelpFlag adds default help flag to c.
@ -773,19 +763,20 @@ func (c *Command) InitDefaultHelpFlag() {
}
}
func (c *Command) initHelpCmd() {
if c.helpCommand == nil {
if !c.HasSubCommands() {
return
}
// InitDefaultHelpCmd adds default help command to c.
// 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.
func (c *Command) InitDefaultHelpCmd() {
if !c.HasSubCommands() {
return
}
if c.helpCommand == nil {
c.helpCommand = &Command{
Use: "help [command]",
Short: "Help about any command",
Long: `Help provides help for any command in the application.
Simply type ` + c.Name() + ` help [path to command] for full details.`,
PersistentPreRun: func(cmd *Command, args []string) {},
PersistentPostRun: func(cmd *Command, args []string) {},
Simply type ` + c.Name() + ` help [path to command] for full details.`,
Run: func(c *Command, args []string) {
cmd, _, e := c.Root().Find(args)
@ -1258,13 +1249,20 @@ func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
}
// ParseFlags parses persistent flag tree and local flags.
func (c *Command) ParseFlags(args []string) (err error) {
func (c *Command) ParseFlags(args []string) error {
if c.DisableFlagParsing {
return nil
}
beforeErrorBufLen := c.flagErrorBuf.Len()
c.mergePersistentFlags()
err = c.Flags().Parse(args)
return
err := c.Flags().Parse(args)
// Print warnings if they occurred (e.g. deprecated flag messages).
if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil {
c.Print(c.flagErrorBuf.String())
}
return err
}
// Parent returns a commands parent command.

View file

@ -120,7 +120,6 @@ func TestStripFlags(t *testing.T) {
}
func TestDisableFlagParsing(t *testing.T) {
as := []string{"-v", "-race", "-file", "foo.go"}
targs := []string{}
cmdPrint := &Command{
DisableFlagParsing: true,
@ -128,14 +127,14 @@ func TestDisableFlagParsing(t *testing.T) {
targs = args
},
}
osargs := []string{"cmd"}
os.Args = append(osargs, as...)
args := []string{"cmd", "-v", "-race", "-file", "foo.go"}
cmdPrint.SetArgs(args)
err := cmdPrint.Execute()
if err != nil {
t.Error(err)
}
if !reflect.DeepEqual(as, targs) {
t.Errorf("expected: %v, got: %v", as, targs)
if !reflect.DeepEqual(args, targs) {
t.Errorf("expected: %v, got: %v", args, targs)
}
}
@ -298,3 +297,53 @@ func TestMergeCommandLineToFlags(t *testing.T) {
// Reset pflag.CommandLine flagset.
pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
}
// TestUseDeprecatedFlags checks,
// if cobra.Execute() prints a message, if a deprecated flag is used.
// Related to https://github.com/spf13/cobra/issues/463.
func TestUseDeprecatedFlags(t *testing.T) {
c := &Command{Use: "c", Run: func(*Command, []string) {}}
output := new(bytes.Buffer)
c.SetOutput(output)
c.Flags().BoolP("deprecated", "d", false, "deprecated flag")
c.Flags().MarkDeprecated("deprecated", "This flag is deprecated")
c.SetArgs([]string{"c", "-d"})
if err := c.Execute(); err != nil {
t.Error("Unexpected error:", err)
}
if !strings.Contains(output.String(), "This flag is deprecated") {
t.Errorf("Expected to contain deprecated message, but got %q", output.String())
}
}
// TestSetHelpCommand checks, if SetHelpCommand works correctly.
func TestSetHelpCommand(t *testing.T) {
c := &Command{Use: "c", Run: func(*Command, []string) {}}
output := new(bytes.Buffer)
c.SetOutput(output)
c.SetArgs([]string{"help"})
// Help will not be shown, if c has no subcommands.
c.AddCommand(&Command{
Use: "empty",
Run: func(cmd *Command, args []string) {},
})
correctMessage := "WORKS"
c.SetHelpCommand(&Command{
Use: "help [command]",
Short: "Help about any command",
Long: `Help provides help for any command in the application.
Simply type ` + c.Name() + ` help [path to command] for full details.`,
Run: func(c *Command, args []string) { c.Print(correctMessage) },
})
if err := c.Execute(); err != nil {
t.Error("Unexpected error:", err)
}
if output.String() != correctMessage {
t.Errorf("Expected to contain %q message, but got %q", correctMessage, output.String())
}
}

View file

@ -11,14 +11,8 @@ import (
var preExecHookFn = preExecHook
// enables an information splash screen on Windows if the CLI is started from explorer.exe.
var MousetrapHelpText string = `This is a command line tool
You need to open cmd.exe and run it from there.
`
func preExecHook(c *Command) {
if mousetrap.StartedByExplorer() {
if MousetrapHelpText != "" && mousetrap.StartedByExplorer() {
c.Print(MousetrapHelpText)
time.Sleep(5 * time.Second)
os.Exit(1)

View file

@ -190,6 +190,9 @@ func manPrintOptions(buf *bytes.Buffer, command *cobra.Command) {
}
func genMan(cmd *cobra.Command, header *GenManHeader) []byte {
cmd.InitDefaultHelpCmd()
cmd.InitDefaultHelpFlag()
// something like `rootcmd-subcmd1-subcmd2`
dashCommandName := strings.Replace(cmd.CommandPath(), " ", "-", -1)

View file

@ -52,6 +52,9 @@ func GenMarkdown(cmd *cobra.Command, w io.Writer) error {
// GenMarkdownCustom creates custom markdown output.
func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {
cmd.InitDefaultHelpCmd()
cmd.InitDefaultHelpFlag()
buf := new(bytes.Buffer)
name := cmd.CommandPath()

View file

@ -89,6 +89,9 @@ func GenYaml(cmd *cobra.Command, w io.Writer) error {
// GenYamlCustom creates custom yaml output.
func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {
cmd.InitDefaultHelpCmd()
cmd.InitDefaultHelpFlag()
yamlDoc := cmdDoc{}
yamlDoc.Name = cmd.CommandPath()