Use golangci-lint (#1044)
Use golangci-lint. Repair warnings and errors resulting from linting.
This commit is contained in:
parent
1d71ff0270
commit
652c755d37
48
.golangci.yml
Normal file
48
.golangci.yml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
run:
|
||||||
|
deadline: 5m
|
||||||
|
|
||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
#- bodyclose
|
||||||
|
- deadcode
|
||||||
|
#- depguard
|
||||||
|
#- dogsled
|
||||||
|
#- dupl
|
||||||
|
- errcheck
|
||||||
|
#- exhaustive
|
||||||
|
#- funlen
|
||||||
|
- gas
|
||||||
|
#- gochecknoinits
|
||||||
|
- goconst
|
||||||
|
#- gocritic
|
||||||
|
#- gocyclo
|
||||||
|
#- gofmt
|
||||||
|
- goimports
|
||||||
|
- golint
|
||||||
|
#- gomnd
|
||||||
|
#- goprintffuncname
|
||||||
|
#- gosec
|
||||||
|
#- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- interfacer
|
||||||
|
#- lll
|
||||||
|
- maligned
|
||||||
|
- megacheck
|
||||||
|
#- misspell
|
||||||
|
#- nakedret
|
||||||
|
#- noctx
|
||||||
|
#- nolintlint
|
||||||
|
#- rowserrcheck
|
||||||
|
#- scopelint
|
||||||
|
#- staticcheck
|
||||||
|
- structcheck
|
||||||
|
#- stylecheck
|
||||||
|
#- typecheck
|
||||||
|
- unconvert
|
||||||
|
#- unparam
|
||||||
|
#- unused
|
||||||
|
- varcheck
|
||||||
|
#- whitespace
|
||||||
|
fast: false
|
@ -1,7 +1,6 @@
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- diff
|
|
||||||
- test
|
- test
|
||||||
- build
|
- build
|
||||||
|
|
||||||
@ -10,20 +9,20 @@ go:
|
|||||||
- 1.15.x
|
- 1.15.x
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
|
env: GO111MODULE=on
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- go get -u github.com/kyoh86/richgo
|
- go get -u github.com/kyoh86/richgo
|
||||||
- go get -u github.com/mitchellh/gox
|
- go get -u github.com/mitchellh/gox
|
||||||
|
- curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin latest
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- go: tip
|
- go: tip
|
||||||
include:
|
include:
|
||||||
- stage: diff
|
|
||||||
go: 1.14.x
|
|
||||||
script: make fmt
|
|
||||||
- stage: build
|
- stage: build
|
||||||
go: 1.14.x
|
go: 1.14.x
|
||||||
script: make cobra_generator
|
script: make cobra_generator
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- make test
|
- make test
|
||||||
|
18
Makefile
18
Makefile
@ -1,21 +1,29 @@
|
|||||||
BIN="./bin"
|
BIN="./bin"
|
||||||
SRC=$(shell find . -name "*.go")
|
SRC=$(shell find . -name "*.go")
|
||||||
|
|
||||||
|
ifeq (, $(shell which golangci-lint))
|
||||||
|
$(warning "could not find golangci-lint in $(PATH), run: curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh")
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq (, $(shell which richgo))
|
ifeq (, $(shell which richgo))
|
||||||
$(warning "could not find richgo in $(PATH), run: go get github.com/kyoh86/richgo")
|
$(warning "could not find richgo in $(PATH), run: go get github.com/kyoh86/richgo")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: fmt vet test cobra_generator install_deps clean
|
.PHONY: fmt lint test cobra_generator install_deps clean
|
||||||
|
|
||||||
default: all
|
default: all
|
||||||
|
|
||||||
all: fmt vet test cobra_generator
|
all: fmt test cobra_generator
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
$(info ******************** checking formatting ********************)
|
$(info ******************** checking formatting ********************)
|
||||||
@test -z $(shell gofmt -l $(SRC)) || (gofmt -d $(SRC); exit 1)
|
@test -z $(shell gofmt -l $(SRC)) || (gofmt -d $(SRC); exit 1)
|
||||||
|
|
||||||
test: install_deps vet
|
lint:
|
||||||
|
$(info ******************** running lint tools ********************)
|
||||||
|
golangci-lint run -v
|
||||||
|
|
||||||
|
test: install_deps lint
|
||||||
$(info ******************** running tests ********************)
|
$(info ******************** running tests ********************)
|
||||||
richgo test -v ./...
|
richgo test -v ./...
|
||||||
|
|
||||||
@ -28,9 +36,5 @@ install_deps:
|
|||||||
$(info ******************** downloading dependencies ********************)
|
$(info ******************** downloading dependencies ********************)
|
||||||
go get -v ./...
|
go get -v ./...
|
||||||
|
|
||||||
vet:
|
|
||||||
$(info ******************** vetting ********************)
|
|
||||||
go vet ./...
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BIN)
|
rm -rf $(BIN)
|
||||||
|
@ -234,11 +234,6 @@ func init() {
|
|||||||
rootCmd.AddCommand(initCmd)
|
rootCmd.AddCommand(initCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func er(msg interface{}) {
|
|
||||||
fmt.Println("Error:", msg)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func initConfig() {
|
func initConfig() {
|
||||||
if cfgFile != "" {
|
if cfgFile != "" {
|
||||||
// Use config file from the flag.
|
// Use config file from the flag.
|
||||||
@ -246,9 +241,7 @@ func initConfig() {
|
|||||||
} else {
|
} else {
|
||||||
// Find home directory.
|
// Find home directory.
|
||||||
home, err := homedir.Dir()
|
home, err := homedir.Dir()
|
||||||
if err != nil {
|
cobra.CheckErr(err)
|
||||||
er(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search config in home directory with name ".cobra" (without extension).
|
// Search config in home directory with name ".cobra" (without extension).
|
||||||
viper.AddConfigPath(home)
|
viper.AddConfigPath(home)
|
||||||
|
@ -19,9 +19,9 @@ const (
|
|||||||
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
|
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
|
||||||
)
|
)
|
||||||
|
|
||||||
func writePreamble(buf *bytes.Buffer, name string) {
|
func writePreamble(buf io.StringWriter, name string) {
|
||||||
buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
|
WriteStringAndCheck(buf, fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
|
||||||
buf.WriteString(fmt.Sprintf(`
|
WriteStringAndCheck(buf, fmt.Sprintf(`
|
||||||
__%[1]s_debug()
|
__%[1]s_debug()
|
||||||
{
|
{
|
||||||
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
|
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
|
||||||
@ -380,10 +380,10 @@ __%[1]s_handle_word()
|
|||||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
|
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePostscript(buf *bytes.Buffer, name string) {
|
func writePostscript(buf io.StringWriter, name string) {
|
||||||
name = strings.Replace(name, ":", "__", -1)
|
name = strings.Replace(name, ":", "__", -1)
|
||||||
buf.WriteString(fmt.Sprintf("__start_%s()\n", name))
|
WriteStringAndCheck(buf, fmt.Sprintf("__start_%s()\n", name))
|
||||||
buf.WriteString(fmt.Sprintf(`{
|
WriteStringAndCheck(buf, fmt.Sprintf(`{
|
||||||
local cur prev words cword
|
local cur prev words cword
|
||||||
declare -A flaghash 2>/dev/null || :
|
declare -A flaghash 2>/dev/null || :
|
||||||
declare -A aliashash 2>/dev/null || :
|
declare -A aliashash 2>/dev/null || :
|
||||||
@ -410,33 +410,33 @@ func writePostscript(buf *bytes.Buffer, name string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
`, name))
|
`, name))
|
||||||
buf.WriteString(fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then
|
WriteStringAndCheck(buf, fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
complete -o default -F __start_%s %s
|
complete -o default -F __start_%s %s
|
||||||
else
|
else
|
||||||
complete -o default -o nospace -F __start_%s %s
|
complete -o default -o nospace -F __start_%s %s
|
||||||
fi
|
fi
|
||||||
|
|
||||||
`, name, name, name, name))
|
`, name, name, name, name))
|
||||||
buf.WriteString("# ex: ts=4 sw=4 et filetype=sh\n")
|
WriteStringAndCheck(buf, "# ex: ts=4 sw=4 et filetype=sh\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeCommands(buf *bytes.Buffer, cmd *Command) {
|
func writeCommands(buf io.StringWriter, cmd *Command) {
|
||||||
buf.WriteString(" commands=()\n")
|
WriteStringAndCheck(buf, " commands=()\n")
|
||||||
for _, c := range cmd.Commands() {
|
for _, c := range cmd.Commands() {
|
||||||
if !c.IsAvailableCommand() && c != cmd.helpCommand {
|
if !c.IsAvailableCommand() && c != cmd.helpCommand {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name()))
|
WriteStringAndCheck(buf, fmt.Sprintf(" commands+=(%q)\n", c.Name()))
|
||||||
writeCmdAliases(buf, c)
|
writeCmdAliases(buf, c)
|
||||||
}
|
}
|
||||||
buf.WriteString("\n")
|
WriteStringAndCheck(buf, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string, cmd *Command) {
|
func writeFlagHandler(buf io.StringWriter, name string, annotations map[string][]string, cmd *Command) {
|
||||||
for key, value := range annotations {
|
for key, value := range annotations {
|
||||||
switch key {
|
switch key {
|
||||||
case BashCompFilenameExt:
|
case BashCompFilenameExt:
|
||||||
buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
|
WriteStringAndCheck(buf, fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
|
||||||
|
|
||||||
var ext string
|
var ext string
|
||||||
if len(value) > 0 {
|
if len(value) > 0 {
|
||||||
@ -444,17 +444,18 @@ func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]s
|
|||||||
} else {
|
} else {
|
||||||
ext = "_filedir"
|
ext = "_filedir"
|
||||||
}
|
}
|
||||||
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext))
|
WriteStringAndCheck(buf, fmt.Sprintf(" flags_completion+=(%q)\n", ext))
|
||||||
case BashCompCustom:
|
case BashCompCustom:
|
||||||
buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
|
WriteStringAndCheck(buf, fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
|
||||||
|
|
||||||
if len(value) > 0 {
|
if len(value) > 0 {
|
||||||
handlers := strings.Join(value, "; ")
|
handlers := strings.Join(value, "; ")
|
||||||
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", handlers))
|
WriteStringAndCheck(buf, fmt.Sprintf(" flags_completion+=(%q)\n", handlers))
|
||||||
} else {
|
} else {
|
||||||
buf.WriteString(" flags_completion+=(:)\n")
|
WriteStringAndCheck(buf, " flags_completion+=(:)\n")
|
||||||
}
|
}
|
||||||
case BashCompSubdirsInDir:
|
case BashCompSubdirsInDir:
|
||||||
buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
|
WriteStringAndCheck(buf, fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
|
||||||
|
|
||||||
var ext string
|
var ext string
|
||||||
if len(value) == 1 {
|
if len(value) == 1 {
|
||||||
@ -462,46 +463,48 @@ func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]s
|
|||||||
} else {
|
} else {
|
||||||
ext = "_filedir -d"
|
ext = "_filedir -d"
|
||||||
}
|
}
|
||||||
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext))
|
WriteStringAndCheck(buf, fmt.Sprintf(" flags_completion+=(%q)\n", ext))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) {
|
const cbn = "\")\n"
|
||||||
|
|
||||||
|
func writeShortFlag(buf io.StringWriter, flag *pflag.Flag, cmd *Command) {
|
||||||
name := flag.Shorthand
|
name := flag.Shorthand
|
||||||
format := " "
|
format := " "
|
||||||
if len(flag.NoOptDefVal) == 0 {
|
if len(flag.NoOptDefVal) == 0 {
|
||||||
format += "two_word_"
|
format += "two_word_"
|
||||||
}
|
}
|
||||||
format += "flags+=(\"-%s\")\n"
|
format += "flags+=(\"-%s" + cbn
|
||||||
buf.WriteString(fmt.Sprintf(format, name))
|
WriteStringAndCheck(buf, fmt.Sprintf(format, name))
|
||||||
writeFlagHandler(buf, "-"+name, flag.Annotations, cmd)
|
writeFlagHandler(buf, "-"+name, flag.Annotations, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) {
|
func writeFlag(buf io.StringWriter, flag *pflag.Flag, cmd *Command) {
|
||||||
name := flag.Name
|
name := flag.Name
|
||||||
format := " flags+=(\"--%s"
|
format := " flags+=(\"--%s"
|
||||||
if len(flag.NoOptDefVal) == 0 {
|
if len(flag.NoOptDefVal) == 0 {
|
||||||
format += "="
|
format += "="
|
||||||
}
|
}
|
||||||
format += "\")\n"
|
format += cbn
|
||||||
buf.WriteString(fmt.Sprintf(format, name))
|
WriteStringAndCheck(buf, fmt.Sprintf(format, name))
|
||||||
if len(flag.NoOptDefVal) == 0 {
|
if len(flag.NoOptDefVal) == 0 {
|
||||||
format = " two_word_flags+=(\"--%s\")\n"
|
format = " two_word_flags+=(\"--%s" + cbn
|
||||||
buf.WriteString(fmt.Sprintf(format, name))
|
WriteStringAndCheck(buf, fmt.Sprintf(format, name))
|
||||||
}
|
}
|
||||||
writeFlagHandler(buf, "--"+name, flag.Annotations, cmd)
|
writeFlagHandler(buf, "--"+name, flag.Annotations, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) {
|
||||||
name := flag.Name
|
name := flag.Name
|
||||||
format := " local_nonpersistent_flags+=(\"--%[1]s\")\n"
|
format := " local_nonpersistent_flags+=(\"--%[1]s" + cbn
|
||||||
if len(flag.NoOptDefVal) == 0 {
|
if len(flag.NoOptDefVal) == 0 {
|
||||||
format += " local_nonpersistent_flags+=(\"--%[1]s=\")\n"
|
format += " local_nonpersistent_flags+=(\"--%[1]s=" + cbn
|
||||||
}
|
}
|
||||||
buf.WriteString(fmt.Sprintf(format, name))
|
WriteStringAndCheck(buf, fmt.Sprintf(format, name))
|
||||||
if len(flag.Shorthand) > 0 {
|
if len(flag.Shorthand) > 0 {
|
||||||
buf.WriteString(fmt.Sprintf(" local_nonpersistent_flags+=(\"-%s\")\n", flag.Shorthand))
|
WriteStringAndCheck(buf, fmt.Sprintf(" local_nonpersistent_flags+=(\"-%s\")\n", flag.Shorthand))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,9 +522,9 @@ func prepareCustomAnnotationsForFlags(cmd *Command) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlags(buf *bytes.Buffer, cmd *Command) {
|
func writeFlags(buf io.StringWriter, cmd *Command) {
|
||||||
prepareCustomAnnotationsForFlags(cmd)
|
prepareCustomAnnotationsForFlags(cmd)
|
||||||
buf.WriteString(` flags=()
|
WriteStringAndCheck(buf, ` flags=()
|
||||||
two_word_flags=()
|
two_word_flags=()
|
||||||
local_nonpersistent_flags=()
|
local_nonpersistent_flags=()
|
||||||
flags_with_completion=()
|
flags_with_completion=()
|
||||||
@ -553,11 +556,11 @@ func writeFlags(buf *bytes.Buffer, cmd *Command) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
buf.WriteString("\n")
|
WriteStringAndCheck(buf, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeRequiredFlag(buf *bytes.Buffer, cmd *Command) {
|
func writeRequiredFlag(buf io.StringWriter, cmd *Command) {
|
||||||
buf.WriteString(" must_have_one_flag=()\n")
|
WriteStringAndCheck(buf, " must_have_one_flag=()\n")
|
||||||
flags := cmd.NonInheritedFlags()
|
flags := cmd.NonInheritedFlags()
|
||||||
flags.VisitAll(func(flag *pflag.Flag) {
|
flags.VisitAll(func(flag *pflag.Flag) {
|
||||||
if nonCompletableFlag(flag) {
|
if nonCompletableFlag(flag) {
|
||||||
@ -570,55 +573,55 @@ func writeRequiredFlag(buf *bytes.Buffer, cmd *Command) {
|
|||||||
if flag.Value.Type() != "bool" {
|
if flag.Value.Type() != "bool" {
|
||||||
format += "="
|
format += "="
|
||||||
}
|
}
|
||||||
format += "\")\n"
|
format += cbn
|
||||||
buf.WriteString(fmt.Sprintf(format, flag.Name))
|
WriteStringAndCheck(buf, fmt.Sprintf(format, flag.Name))
|
||||||
|
|
||||||
if len(flag.Shorthand) > 0 {
|
if len(flag.Shorthand) > 0 {
|
||||||
buf.WriteString(fmt.Sprintf(" must_have_one_flag+=(\"-%s\")\n", flag.Shorthand))
|
WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_flag+=(\"-%s"+cbn, flag.Shorthand))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) {
|
func writeRequiredNouns(buf io.StringWriter, cmd *Command) {
|
||||||
buf.WriteString(" must_have_one_noun=()\n")
|
WriteStringAndCheck(buf, " must_have_one_noun=()\n")
|
||||||
sort.Sort(sort.StringSlice(cmd.ValidArgs))
|
sort.Strings(cmd.ValidArgs)
|
||||||
for _, value := range cmd.ValidArgs {
|
for _, value := range cmd.ValidArgs {
|
||||||
// Remove any description that may be included following a tab character.
|
// Remove any description that may be included following a tab character.
|
||||||
// Descriptions are not supported by bash completion.
|
// Descriptions are not supported by bash completion.
|
||||||
value = strings.Split(value, "\t")[0]
|
value = strings.Split(value, "\t")[0]
|
||||||
buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value))
|
WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_noun+=(%q)\n", value))
|
||||||
}
|
}
|
||||||
if cmd.ValidArgsFunction != nil {
|
if cmd.ValidArgsFunction != nil {
|
||||||
buf.WriteString(" has_completion_function=1\n")
|
WriteStringAndCheck(buf, " has_completion_function=1\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeCmdAliases(buf *bytes.Buffer, cmd *Command) {
|
func writeCmdAliases(buf io.StringWriter, cmd *Command) {
|
||||||
if len(cmd.Aliases) == 0 {
|
if len(cmd.Aliases) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Sort(sort.StringSlice(cmd.Aliases))
|
sort.Strings(cmd.Aliases)
|
||||||
|
|
||||||
buf.WriteString(fmt.Sprint(` if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then`, "\n"))
|
WriteStringAndCheck(buf, fmt.Sprint(` if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then`, "\n"))
|
||||||
for _, value := range cmd.Aliases {
|
for _, value := range cmd.Aliases {
|
||||||
buf.WriteString(fmt.Sprintf(" command_aliases+=(%q)\n", value))
|
WriteStringAndCheck(buf, fmt.Sprintf(" command_aliases+=(%q)\n", value))
|
||||||
buf.WriteString(fmt.Sprintf(" aliashash[%q]=%q\n", value, cmd.Name()))
|
WriteStringAndCheck(buf, fmt.Sprintf(" aliashash[%q]=%q\n", value, cmd.Name()))
|
||||||
}
|
}
|
||||||
buf.WriteString(` fi`)
|
WriteStringAndCheck(buf, ` fi`)
|
||||||
buf.WriteString("\n")
|
WriteStringAndCheck(buf, "\n")
|
||||||
}
|
}
|
||||||
func writeArgAliases(buf *bytes.Buffer, cmd *Command) {
|
func writeArgAliases(buf io.StringWriter, cmd *Command) {
|
||||||
buf.WriteString(" noun_aliases=()\n")
|
WriteStringAndCheck(buf, " noun_aliases=()\n")
|
||||||
sort.Sort(sort.StringSlice(cmd.ArgAliases))
|
sort.Strings(cmd.ArgAliases)
|
||||||
for _, value := range cmd.ArgAliases {
|
for _, value := range cmd.ArgAliases {
|
||||||
buf.WriteString(fmt.Sprintf(" noun_aliases+=(%q)\n", value))
|
WriteStringAndCheck(buf, fmt.Sprintf(" noun_aliases+=(%q)\n", value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func gen(buf *bytes.Buffer, cmd *Command) {
|
func gen(buf io.StringWriter, cmd *Command) {
|
||||||
for _, c := range cmd.Commands() {
|
for _, c := range cmd.Commands() {
|
||||||
if !c.IsAvailableCommand() && c != cmd.helpCommand {
|
if !c.IsAvailableCommand() && c != cmd.helpCommand {
|
||||||
continue
|
continue
|
||||||
@ -630,22 +633,22 @@ func gen(buf *bytes.Buffer, cmd *Command) {
|
|||||||
commandName = strings.Replace(commandName, ":", "__", -1)
|
commandName = strings.Replace(commandName, ":", "__", -1)
|
||||||
|
|
||||||
if cmd.Root() == cmd {
|
if cmd.Root() == cmd {
|
||||||
buf.WriteString(fmt.Sprintf("_%s_root_command()\n{\n", commandName))
|
WriteStringAndCheck(buf, fmt.Sprintf("_%s_root_command()\n{\n", commandName))
|
||||||
} else {
|
} else {
|
||||||
buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName))
|
WriteStringAndCheck(buf, fmt.Sprintf("_%s()\n{\n", commandName))
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName))
|
WriteStringAndCheck(buf, fmt.Sprintf(" last_command=%q\n", commandName))
|
||||||
buf.WriteString("\n")
|
WriteStringAndCheck(buf, "\n")
|
||||||
buf.WriteString(" command_aliases=()\n")
|
WriteStringAndCheck(buf, " command_aliases=()\n")
|
||||||
buf.WriteString("\n")
|
WriteStringAndCheck(buf, "\n")
|
||||||
|
|
||||||
writeCommands(buf, cmd)
|
writeCommands(buf, cmd)
|
||||||
writeFlags(buf, cmd)
|
writeFlags(buf, cmd)
|
||||||
writeRequiredFlag(buf, cmd)
|
writeRequiredFlag(buf, cmd)
|
||||||
writeRequiredNouns(buf, cmd)
|
writeRequiredNouns(buf, cmd)
|
||||||
writeArgAliases(buf, cmd)
|
writeArgAliases(buf, cmd)
|
||||||
buf.WriteString("}\n\n")
|
WriteStringAndCheck(buf, "}\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenBashCompletion generates bash completion file and writes to the passed writer.
|
// GenBashCompletion generates bash completion file and writes to the passed writer.
|
||||||
|
@ -40,10 +40,9 @@ func checkRegex(t *testing.T, found, pattern string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runShellCheck(s string) error {
|
func runShellCheck(s string) error {
|
||||||
excluded := []string{
|
cmd := exec.Command("shellcheck", "-s", "bash", "-", "-e",
|
||||||
"SC2034", // PREFIX appears unused. Verify it or export it.
|
"SC2034", // PREFIX appears unused. Verify it or export it.
|
||||||
}
|
)
|
||||||
cmd := exec.Command("shellcheck", "-s", "bash", "-", "-e", strings.Join(excluded, ","))
|
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
|
|
||||||
@ -52,7 +51,9 @@ func runShellCheck(s string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
stdin.Write([]byte(s))
|
_, err := stdin.Write([]byte(s))
|
||||||
|
CheckErr(err)
|
||||||
|
|
||||||
stdin.Close()
|
stdin.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -74,26 +75,26 @@ func TestBashCompletions(t *testing.T) {
|
|||||||
Run: emptyRun,
|
Run: emptyRun,
|
||||||
}
|
}
|
||||||
rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot")
|
rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot")
|
||||||
rootCmd.MarkFlagRequired("introot")
|
assertNoErr(t, rootCmd.MarkFlagRequired("introot"))
|
||||||
|
|
||||||
// Filename.
|
// Filename.
|
||||||
rootCmd.Flags().String("filename", "", "Enter a filename")
|
rootCmd.Flags().String("filename", "", "Enter a filename")
|
||||||
rootCmd.MarkFlagFilename("filename", "json", "yaml", "yml")
|
assertNoErr(t, rootCmd.MarkFlagFilename("filename", "json", "yaml", "yml"))
|
||||||
|
|
||||||
// Persistent filename.
|
// Persistent filename.
|
||||||
rootCmd.PersistentFlags().String("persistent-filename", "", "Enter a filename")
|
rootCmd.PersistentFlags().String("persistent-filename", "", "Enter a filename")
|
||||||
rootCmd.MarkPersistentFlagFilename("persistent-filename")
|
assertNoErr(t, rootCmd.MarkPersistentFlagFilename("persistent-filename"))
|
||||||
rootCmd.MarkPersistentFlagRequired("persistent-filename")
|
assertNoErr(t, rootCmd.MarkPersistentFlagRequired("persistent-filename"))
|
||||||
|
|
||||||
// Filename extensions.
|
// Filename extensions.
|
||||||
rootCmd.Flags().String("filename-ext", "", "Enter a filename (extension limited)")
|
rootCmd.Flags().String("filename-ext", "", "Enter a filename (extension limited)")
|
||||||
rootCmd.MarkFlagFilename("filename-ext")
|
assertNoErr(t, rootCmd.MarkFlagFilename("filename-ext"))
|
||||||
rootCmd.Flags().String("custom", "", "Enter a filename (extension limited)")
|
rootCmd.Flags().String("custom", "", "Enter a filename (extension limited)")
|
||||||
rootCmd.MarkFlagCustom("custom", "__complete_custom")
|
assertNoErr(t, rootCmd.MarkFlagCustom("custom", "__complete_custom"))
|
||||||
|
|
||||||
// Subdirectories in a given directory.
|
// Subdirectories in a given directory.
|
||||||
rootCmd.Flags().String("theme", "", "theme to use (located in /themes/THEMENAME/)")
|
rootCmd.Flags().String("theme", "", "theme to use (located in /themes/THEMENAME/)")
|
||||||
rootCmd.Flags().SetAnnotation("theme", BashCompSubdirsInDir, []string{"themes"})
|
assertNoErr(t, rootCmd.Flags().SetAnnotation("theme", BashCompSubdirsInDir, []string{"themes"}))
|
||||||
|
|
||||||
// For two word flags check
|
// For two word flags check
|
||||||
rootCmd.Flags().StringP("two", "t", "", "this is two word flags")
|
rootCmd.Flags().StringP("two", "t", "", "this is two word flags")
|
||||||
@ -109,9 +110,9 @@ func TestBashCompletions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
echoCmd.Flags().String("filename", "", "Enter a filename")
|
echoCmd.Flags().String("filename", "", "Enter a filename")
|
||||||
echoCmd.MarkFlagFilename("filename", "json", "yaml", "yml")
|
assertNoErr(t, echoCmd.MarkFlagFilename("filename", "json", "yaml", "yml"))
|
||||||
echoCmd.Flags().String("config", "", "config to use (located in /config/PROFILE/)")
|
echoCmd.Flags().String("config", "", "config to use (located in /config/PROFILE/)")
|
||||||
echoCmd.Flags().SetAnnotation("config", BashCompSubdirsInDir, []string{"config"})
|
assertNoErr(t, echoCmd.Flags().SetAnnotation("config", BashCompSubdirsInDir, []string{"config"}))
|
||||||
|
|
||||||
printCmd := &Command{
|
printCmd := &Command{
|
||||||
Use: "print [string to print]",
|
Use: "print [string to print]",
|
||||||
@ -149,7 +150,7 @@ func TestBashCompletions(t *testing.T) {
|
|||||||
rootCmd.AddCommand(echoCmd, printCmd, deprecatedCmd, colonCmd)
|
rootCmd.AddCommand(echoCmd, printCmd, deprecatedCmd, colonCmd)
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
rootCmd.GenBashCompletion(buf)
|
assertNoErr(t, rootCmd.GenBashCompletion(buf))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
check(t, output, "_root")
|
check(t, output, "_root")
|
||||||
@ -216,10 +217,10 @@ func TestBashCompletionHiddenFlag(t *testing.T) {
|
|||||||
|
|
||||||
const flagName = "hiddenFlag"
|
const flagName = "hiddenFlag"
|
||||||
c.Flags().Bool(flagName, false, "")
|
c.Flags().Bool(flagName, false, "")
|
||||||
c.Flags().MarkHidden(flagName)
|
assertNoErr(t, c.Flags().MarkHidden(flagName))
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
c.GenBashCompletion(buf)
|
assertNoErr(t, c.GenBashCompletion(buf))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
if strings.Contains(output, flagName) {
|
if strings.Contains(output, flagName) {
|
||||||
@ -232,10 +233,10 @@ func TestBashCompletionDeprecatedFlag(t *testing.T) {
|
|||||||
|
|
||||||
const flagName = "deprecated-flag"
|
const flagName = "deprecated-flag"
|
||||||
c.Flags().Bool(flagName, false, "")
|
c.Flags().Bool(flagName, false, "")
|
||||||
c.Flags().MarkDeprecated(flagName, "use --not-deprecated instead")
|
assertNoErr(t, c.Flags().MarkDeprecated(flagName, "use --not-deprecated instead"))
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
c.GenBashCompletion(buf)
|
assertNoErr(t, c.GenBashCompletion(buf))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
if strings.Contains(output, flagName) {
|
if strings.Contains(output, flagName) {
|
||||||
@ -250,7 +251,7 @@ func TestBashCompletionTraverseChildren(t *testing.T) {
|
|||||||
c.Flags().BoolP("bool-flag", "b", false, "bool flag")
|
c.Flags().BoolP("bool-flag", "b", false, "bool flag")
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
c.GenBashCompletion(buf)
|
assertNoErr(t, c.GenBashCompletion(buf))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
// check that local nonpersistent flag are not set since we have TraverseChildren set to true
|
// check that local nonpersistent flag are not set since we have TraverseChildren set to true
|
||||||
|
15
cobra.go
15
cobra.go
@ -19,6 +19,7 @@ package cobra
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -205,3 +206,17 @@ func stringInSlice(a string, list []string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckErr prints the msg with the prefix 'Error:' and exits with error code 1. If the msg is nil, it does nothing.
|
||||||
|
func CheckErr(msg interface{}) {
|
||||||
|
if msg != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "Error:", msg)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteStringAndCheck writes a string into a buffer, and checks if the error is not nil.
|
||||||
|
func WriteStringAndCheck(b io.StringWriter, s string) {
|
||||||
|
_, err := b.WriteString(s)
|
||||||
|
CheckErr(err)
|
||||||
|
}
|
||||||
|
@ -40,13 +40,11 @@ Example: cobra add server -> resulting in a new cmd/server.go`,
|
|||||||
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
er("add needs a name for the command")
|
cobra.CheckErr(fmt.Errorf("add needs a name for the command"))
|
||||||
}
|
}
|
||||||
|
|
||||||
wd, err := os.Getwd()
|
wd, err := os.Getwd()
|
||||||
if err != nil {
|
cobra.CheckErr(err)
|
||||||
er(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
commandName := validateCmdName(args[0])
|
commandName := validateCmdName(args[0])
|
||||||
command := &Command{
|
command := &Command{
|
||||||
@ -59,10 +57,7 @@ Example: cobra add server -> resulting in a new cmd/server.go`,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = command.Create()
|
cobra.CheckErr(command.Create())
|
||||||
if err != nil {
|
|
||||||
er(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("%s created at %s\n", command.CmdName, command.AbsolutePath)
|
fmt.Printf("%s created at %s\n", command.CmdName, command.AbsolutePath)
|
||||||
},
|
},
|
||||||
@ -72,7 +67,7 @@ Example: cobra add server -> resulting in a new cmd/server.go`,
|
|||||||
func init() {
|
func init() {
|
||||||
addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)")
|
addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)")
|
||||||
addCmd.Flags().StringVarP(&parentName, "parent", "p", "rootCmd", "variable name of parent command for this command")
|
addCmd.Flags().StringVarP(&parentName, "parent", "p", "rootCmd", "variable name of parent command for this command")
|
||||||
addCmd.Flags().MarkDeprecated("package", "this operation has been removed.")
|
cobra.CheckErr(addCmd.Flags().MarkDeprecated("package", "this operation has been removed."))
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateCmdName returns source without any dashes and underscore.
|
// validateCmdName returns source without any dashes and underscore.
|
||||||
|
@ -14,10 +14,8 @@ func TestGoldenAddCmd(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer os.RemoveAll(command.AbsolutePath)
|
defer os.RemoveAll(command.AbsolutePath)
|
||||||
|
|
||||||
command.Project.Create()
|
assertNoErr(t, command.Project.Create())
|
||||||
if err := command.Create(); err != nil {
|
assertNoErr(t, command.Create())
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
generatedFile := fmt.Sprintf("%s/cmd/%s.go", command.AbsolutePath, command.CmdName)
|
generatedFile := fmt.Sprintf("%s/cmd/%s.go", command.AbsolutePath, command.CmdName)
|
||||||
goldenFile := fmt.Sprintf("testdata/%s.go.golden", command.CmdName)
|
goldenFile := fmt.Sprintf("testdata/%s.go.golden", command.CmdName)
|
||||||
|
@ -3,14 +3,11 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
var update = flag.Bool("update", false, "update .golden files")
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Mute commands.
|
// Mute commands.
|
||||||
addCmd.SetOut(new(bytes.Buffer))
|
addCmd.SetOut(new(bytes.Buffer))
|
||||||
@ -58,27 +55,3 @@ func compareFiles(pathA, pathB string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkLackFiles checks if all elements of expected are in got.
|
|
||||||
func checkLackFiles(expected, got []string) error {
|
|
||||||
lacks := make([]string, 0, len(expected))
|
|
||||||
for _, ev := range expected {
|
|
||||||
if !stringInStringSlice(ev, got) {
|
|
||||||
lacks = append(lacks, ev)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(lacks) > 0 {
|
|
||||||
return fmt.Errorf("Lack %v file(s): %v", len(lacks), lacks)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// stringInStringSlice checks if s is an element of slice.
|
|
||||||
func stringInStringSlice(s string, slice []string) bool {
|
|
||||||
for _, v := range slice {
|
|
||||||
if s == v {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
@ -14,14 +14,12 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var srcPaths []string
|
var srcPaths []string
|
||||||
@ -43,14 +41,12 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
out, err := exec.Command(goExecutable, "env", "GOPATH").Output()
|
out, err := exec.Command(goExecutable, "env", "GOPATH").Output()
|
||||||
if err != nil {
|
cobra.CheckErr(err)
|
||||||
er(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
toolchainGoPath := strings.TrimSpace(string(out))
|
toolchainGoPath := strings.TrimSpace(string(out))
|
||||||
goPaths = filepath.SplitList(toolchainGoPath)
|
goPaths = filepath.SplitList(toolchainGoPath)
|
||||||
if len(goPaths) == 0 {
|
if len(goPaths) == 0 {
|
||||||
er("$GOPATH is not set")
|
cobra.CheckErr("$GOPATH is not set")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
srcPaths = make([]string, 0, len(goPaths))
|
srcPaths = make([]string, 0, len(goPaths))
|
||||||
@ -58,111 +54,3 @@ func init() {
|
|||||||
srcPaths = append(srcPaths, filepath.Join(goPath, "src"))
|
srcPaths = append(srcPaths, filepath.Join(goPath, "src"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func er(msg interface{}) {
|
|
||||||
fmt.Println("Error:", msg)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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() {
|
|
||||||
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.
|
|
||||||
func exists(path string) bool {
|
|
||||||
if path == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
_, err := os.Stat(path)
|
|
||||||
if err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
er(err)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func executeTemplate(tmplStr string, data interface{}) (string, error) {
|
|
||||||
tmpl, err := template.New("").Funcs(template.FuncMap{"comment": commentifyString}).Parse(tmplStr)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
err = tmpl.Execute(buf, data)
|
|
||||||
return buf.String(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeStringToFile(path string, s string) error {
|
|
||||||
return writeToFile(path, strings.NewReader(s))
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeToFile writes r to file with path only
|
|
||||||
// if file/directory on given path doesn't exist.
|
|
||||||
func writeToFile(path string, r io.Reader) error {
|
|
||||||
if exists(path) {
|
|
||||||
return fmt.Errorf("%v already exists", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
dir := filepath.Dir(path)
|
|
||||||
if dir != "" {
|
|
||||||
if err := os.MkdirAll(dir, 0777); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.Create(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(file, r)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// commentfyString comments every line of in.
|
|
||||||
func commentifyString(in string) string {
|
|
||||||
var newlines []string
|
|
||||||
lines := strings.Split(in, "\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
if strings.HasPrefix(line, "//") {
|
|
||||||
newlines = append(newlines, line)
|
|
||||||
} else {
|
|
||||||
if line == "" {
|
|
||||||
newlines = append(newlines, "//")
|
|
||||||
} else {
|
|
||||||
newlines = append(newlines, "// "+line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.Join(newlines, "\n")
|
|
||||||
}
|
|
||||||
|
9
cobra/cmd/helpers_test.go
Normal file
9
cobra/cmd/helpers_test.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func assertNoErr(t *testing.T, e error) {
|
||||||
|
if e != nil {
|
||||||
|
t.Error(e)
|
||||||
|
}
|
||||||
|
}
|
@ -39,9 +39,7 @@ and the appropriate structure for a Cobra-based CLI application.
|
|||||||
Run: func(_ *cobra.Command, args []string) {
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
|
||||||
projectPath, err := initializeProject(args)
|
projectPath, err := initializeProject(args)
|
||||||
if err != nil {
|
cobra.CheckErr(err)
|
||||||
er(err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Your Cobra application is ready at\n%s\n", projectPath)
|
fmt.Printf("Your Cobra application is ready at\n%s\n", projectPath)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -49,7 +47,7 @@ and the appropriate structure for a Cobra-based CLI application.
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
initCmd.Flags().StringVar(&pkgName, "pkg-name", "", "fully qualified pkg name")
|
initCmd.Flags().StringVar(&pkgName, "pkg-name", "", "fully qualified pkg name")
|
||||||
initCmd.MarkFlagRequired("pkg-name")
|
cobra.CheckErr(initCmd.MarkFlagRequired("pkg-name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func initializeProject(args []string) (string, error) {
|
func initializeProject(args []string) (string, error) {
|
||||||
|
@ -59,7 +59,7 @@ func TestGoldenInitCmd(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
||||||
initCmd.Flags().Set("pkg-name", tt.pkgName)
|
assertNoErr(t, initCmd.Flags().Set("pkg-name", tt.pkgName))
|
||||||
viper.Set("useViper", true)
|
viper.Set("useViper", true)
|
||||||
projectPath, err := initializeProject(tt.args)
|
projectPath, err := initializeProject(tt.args)
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -16,9 +16,11 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -92,7 +94,7 @@ func copyrightLine() string {
|
|||||||
func findLicense(name string) License {
|
func findLicense(name string) License {
|
||||||
found := matchLicense(name)
|
found := matchLicense(name)
|
||||||
if found == "" {
|
if found == "" {
|
||||||
er("unknown license: " + name)
|
cobra.CheckErr(fmt.Errorf("unknown license: " + name))
|
||||||
}
|
}
|
||||||
return Licenses[found]
|
return Licenses[found]
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/cobra/cobra/tpl"
|
"github.com/spf13/cobra/cobra/tpl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ func (p *Project) Create() error {
|
|||||||
|
|
||||||
// create cmd/root.go
|
// create cmd/root.go
|
||||||
if _, err = os.Stat(fmt.Sprintf("%s/cmd", p.AbsolutePath)); os.IsNotExist(err) {
|
if _, err = os.Stat(fmt.Sprintf("%s/cmd", p.AbsolutePath)); os.IsNotExist(err) {
|
||||||
os.Mkdir(fmt.Sprintf("%s/cmd", p.AbsolutePath), 0751)
|
cobra.CheckErr(os.Mkdir(fmt.Sprintf("%s/cmd", p.AbsolutePath), 0751))
|
||||||
}
|
}
|
||||||
rootFile, err := os.Create(fmt.Sprintf("%s/cmd/root.go", p.AbsolutePath))
|
rootFile, err := os.Create(fmt.Sprintf("%s/cmd/root.go", p.AbsolutePath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -47,8 +47,8 @@ func init() {
|
|||||||
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
|
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
|
||||||
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
|
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", true, "use Viper for configuration")
|
||||||
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
cobra.CheckErr(viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")))
|
||||||
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
|
cobra.CheckErr(viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper")))
|
||||||
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
||||||
viper.SetDefault("license", "apache")
|
viper.SetDefault("license", "apache")
|
||||||
|
|
||||||
@ -63,9 +63,7 @@ func initConfig() {
|
|||||||
} else {
|
} else {
|
||||||
// Find home directory.
|
// Find home directory.
|
||||||
home, err := homedir.Dir()
|
home, err := homedir.Dir()
|
||||||
if err != nil {
|
cobra.CheckErr(err)
|
||||||
er(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search config in home directory with name ".cobra" (without extension).
|
// Search config in home directory with name ".cobra" (without extension).
|
||||||
viper.AddConfigPath(home)
|
viper.AddConfigPath(home)
|
||||||
|
16
cobra/cmd/testdata/root.go.golden
vendored
16
cobra/cmd/testdata/root.go.golden
vendored
@ -17,8 +17,8 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"os"
|
"os"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@ -38,16 +38,13 @@ This application is a tool to generate the needed files
|
|||||||
to quickly create a Cobra application.`,
|
to quickly create a Cobra application.`,
|
||||||
// Uncomment the following line if your bare application
|
// Uncomment the following line if your bare application
|
||||||
// has an action associated with it:
|
// has an action associated with it:
|
||||||
// Run: func(cmd *cobra.Command, args []string) { },
|
// Run: func(cmd *cobra.Command, args []string) { },
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute adds all child commands to the root command and 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.
|
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||||
func Execute() {
|
func Execute() {
|
||||||
if err := rootCmd.Execute(); err != nil {
|
cobra.CheckErr(rootCmd.Execute())
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -72,10 +69,7 @@ func initConfig() {
|
|||||||
} else {
|
} else {
|
||||||
// Find home directory.
|
// Find home directory.
|
||||||
home, err := homedir.Dir()
|
home, err := homedir.Dir()
|
||||||
if err != nil {
|
cobra.CheckErr(err)
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search config in home directory with name ".testproject" (without extension).
|
// Search config in home directory with name ".testproject" (without extension).
|
||||||
viper.AddConfigPath(home)
|
viper.AddConfigPath(home)
|
||||||
@ -86,6 +80,6 @@ func initConfig() {
|
|||||||
|
|
||||||
// If a config file is found, read it in.
|
// If a config file is found, read it in.
|
||||||
if err := viper.ReadInConfig(); err == nil {
|
if err := viper.ReadInConfig(); err == nil {
|
||||||
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,11 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"os"
|
"os"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
{{ if .Viper }}
|
{{ if .Viper }}
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"{{ end }}
|
||||||
{{ end -}}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
{{ if .Viper -}}
|
{{ if .Viper -}}
|
||||||
@ -48,16 +47,13 @@ This application is a tool to generate the needed files
|
|||||||
to quickly create a Cobra application.` + "`" + `,
|
to quickly create a Cobra application.` + "`" + `,
|
||||||
// Uncomment the following line if your bare application
|
// Uncomment the following line if your bare application
|
||||||
// has an action associated with it:
|
// has an action associated with it:
|
||||||
// Run: func(cmd *cobra.Command, args []string) { },
|
// Run: func(cmd *cobra.Command, args []string) { },
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute adds all child commands to the root command and 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.
|
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||||
func Execute() {
|
func Execute() {
|
||||||
if err := rootCmd.Execute(); err != nil {
|
cobra.CheckErr(rootCmd.Execute())
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -86,10 +82,7 @@ func initConfig() {
|
|||||||
} else {
|
} else {
|
||||||
// Find home directory.
|
// Find home directory.
|
||||||
home, err := homedir.Dir()
|
home, err := homedir.Dir()
|
||||||
if err != nil {
|
cobra.CheckErr(err)
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search config in home directory with name ".{{ .AppName }}" (without extension).
|
// Search config in home directory with name ".{{ .AppName }}" (without extension).
|
||||||
viper.AddConfigPath(home)
|
viper.AddConfigPath(home)
|
||||||
@ -100,7 +93,7 @@ func initConfig() {
|
|||||||
|
|
||||||
// If a config file is found, read it in.
|
// If a config file is found, read it in.
|
||||||
if err := viper.ReadInConfig(); err == nil {
|
if err := viper.ReadInConfig(); err == nil {
|
||||||
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
@ -5,6 +5,12 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func assertNoErr(t *testing.T, e error) {
|
||||||
|
if e != nil {
|
||||||
|
t.Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAddTemplateFunctions(t *testing.T) {
|
func TestAddTemplateFunctions(t *testing.T) {
|
||||||
AddTemplateFunc("t", func() bool { return true })
|
AddTemplateFunc("t", func() bool { return true })
|
||||||
AddTemplateFuncs(template.FuncMap{
|
AddTemplateFuncs(template.FuncMap{
|
||||||
|
112
command.go
112
command.go
@ -84,9 +84,6 @@ type Command struct {
|
|||||||
// Deprecated defines, if this command is deprecated and should print this string when used.
|
// Deprecated defines, if this command is deprecated and should print this string when used.
|
||||||
Deprecated string
|
Deprecated string
|
||||||
|
|
||||||
// Hidden defines, if this command is hidden and should NOT show up in the list of available commands.
|
|
||||||
Hidden bool
|
|
||||||
|
|
||||||
// Annotations are key/value pairs that can be used by applications to identify or
|
// Annotations are key/value pairs that can be used by applications to identify or
|
||||||
// group commands.
|
// group commands.
|
||||||
Annotations map[string]string
|
Annotations map[string]string
|
||||||
@ -126,55 +123,6 @@ type Command struct {
|
|||||||
// PersistentPostRunE: PersistentPostRun but returns an error.
|
// PersistentPostRunE: PersistentPostRun but returns an error.
|
||||||
PersistentPostRunE func(cmd *Command, args []string) error
|
PersistentPostRunE func(cmd *Command, args []string) error
|
||||||
|
|
||||||
// SilenceErrors is an option to quiet errors down stream.
|
|
||||||
SilenceErrors bool
|
|
||||||
|
|
||||||
// SilenceUsage is an option to silence usage when an error occurs.
|
|
||||||
SilenceUsage bool
|
|
||||||
|
|
||||||
// DisableFlagParsing disables the flag parsing.
|
|
||||||
// If this is true all flags will be passed to the command as arguments.
|
|
||||||
DisableFlagParsing bool
|
|
||||||
|
|
||||||
// DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...")
|
|
||||||
// will be printed by generating docs for this command.
|
|
||||||
DisableAutoGenTag bool
|
|
||||||
|
|
||||||
// DisableFlagsInUseLine will disable the addition of [flags] to the usage
|
|
||||||
// line of a command when printing help or generating docs
|
|
||||||
DisableFlagsInUseLine bool
|
|
||||||
|
|
||||||
// DisableSuggestions disables the suggestions based on Levenshtein distance
|
|
||||||
// that go along with 'unknown command' messages.
|
|
||||||
DisableSuggestions bool
|
|
||||||
// SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions.
|
|
||||||
// Must be > 0.
|
|
||||||
SuggestionsMinimumDistance int
|
|
||||||
|
|
||||||
// TraverseChildren parses flags on all parents before executing child command.
|
|
||||||
TraverseChildren bool
|
|
||||||
|
|
||||||
// FParseErrWhitelist flag parse errors to be ignored
|
|
||||||
FParseErrWhitelist FParseErrWhitelist
|
|
||||||
|
|
||||||
ctx context.Context
|
|
||||||
|
|
||||||
// commands is the list of commands supported by this program.
|
|
||||||
commands []*Command
|
|
||||||
// parent is a parent command for this command.
|
|
||||||
parent *Command
|
|
||||||
// Max lengths of commands' string lengths for use in padding.
|
|
||||||
commandsMaxUseLen int
|
|
||||||
commandsMaxCommandPathLen int
|
|
||||||
commandsMaxNameLen int
|
|
||||||
// commandsAreSorted defines, if command slice are sorted or not.
|
|
||||||
commandsAreSorted bool
|
|
||||||
// commandCalledAs is the name or alias value used to call this command.
|
|
||||||
commandCalledAs struct {
|
|
||||||
name string
|
|
||||||
called bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// args is actual args parsed from flags.
|
// args is actual args parsed from flags.
|
||||||
args []string
|
args []string
|
||||||
// flagErrorBuf contains all error messages from pflag.
|
// flagErrorBuf contains all error messages from pflag.
|
||||||
@ -216,6 +164,60 @@ type Command struct {
|
|||||||
outWriter io.Writer
|
outWriter io.Writer
|
||||||
// errWriter is a writer defined by the user that replaces stderr
|
// errWriter is a writer defined by the user that replaces stderr
|
||||||
errWriter io.Writer
|
errWriter io.Writer
|
||||||
|
|
||||||
|
//FParseErrWhitelist flag parse errors to be ignored
|
||||||
|
FParseErrWhitelist FParseErrWhitelist
|
||||||
|
|
||||||
|
// commandsAreSorted defines, if command slice are sorted or not.
|
||||||
|
commandsAreSorted bool
|
||||||
|
// commandCalledAs is the name or alias value used to call this command.
|
||||||
|
commandCalledAs struct {
|
||||||
|
name string
|
||||||
|
called bool
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
|
|
||||||
|
// commands is the list of commands supported by this program.
|
||||||
|
commands []*Command
|
||||||
|
// parent is a parent command for this command.
|
||||||
|
parent *Command
|
||||||
|
// Max lengths of commands' string lengths for use in padding.
|
||||||
|
commandsMaxUseLen int
|
||||||
|
commandsMaxCommandPathLen int
|
||||||
|
commandsMaxNameLen int
|
||||||
|
|
||||||
|
// TraverseChildren parses flags on all parents before executing child command.
|
||||||
|
TraverseChildren bool
|
||||||
|
|
||||||
|
// Hidden defines, if this command is hidden and should NOT show up in the list of available commands.
|
||||||
|
Hidden bool
|
||||||
|
|
||||||
|
// SilenceErrors is an option to quiet errors down stream.
|
||||||
|
SilenceErrors bool
|
||||||
|
|
||||||
|
// SilenceUsage is an option to silence usage when an error occurs.
|
||||||
|
SilenceUsage bool
|
||||||
|
|
||||||
|
// DisableFlagParsing disables the flag parsing.
|
||||||
|
// If this is true all flags will be passed to the command as arguments.
|
||||||
|
DisableFlagParsing bool
|
||||||
|
|
||||||
|
// DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...")
|
||||||
|
// will be printed by generating docs for this command.
|
||||||
|
DisableAutoGenTag bool
|
||||||
|
|
||||||
|
// DisableFlagsInUseLine will disable the addition of [flags] to the usage
|
||||||
|
// line of a command when printing help or generating docs
|
||||||
|
DisableFlagsInUseLine bool
|
||||||
|
|
||||||
|
// DisableSuggestions disables the suggestions based on Levenshtein distance
|
||||||
|
// that go along with 'unknown command' messages.
|
||||||
|
DisableSuggestions bool
|
||||||
|
|
||||||
|
// SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions.
|
||||||
|
// Must be > 0.
|
||||||
|
SuggestionsMinimumDistance int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context returns underlying command context. If command wasn't
|
// Context returns underlying command context. If command wasn't
|
||||||
@ -418,7 +420,7 @@ func (c *Command) UsageString() string {
|
|||||||
c.outWriter = bb
|
c.outWriter = bb
|
||||||
c.errWriter = bb
|
c.errWriter = bb
|
||||||
|
|
||||||
c.Usage()
|
CheckErr(c.Usage())
|
||||||
|
|
||||||
// Setting things back to normal
|
// Setting things back to normal
|
||||||
c.outWriter = tmpOutput
|
c.outWriter = tmpOutput
|
||||||
@ -1087,10 +1089,10 @@ Simply type ` + c.Name() + ` help [path to command] for full details.`,
|
|||||||
cmd, _, e := c.Root().Find(args)
|
cmd, _, e := c.Root().Find(args)
|
||||||
if cmd == nil || e != nil {
|
if cmd == nil || e != nil {
|
||||||
c.Printf("Unknown help topic %#q\n", args)
|
c.Printf("Unknown help topic %#q\n", args)
|
||||||
c.Root().Usage()
|
CheckErr(c.Root().Usage())
|
||||||
} else {
|
} else {
|
||||||
cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown
|
cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown
|
||||||
cmd.Help()
|
CheckErr(cmd.Help())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
199
command_test.go
199
command_test.go
@ -58,6 +58,8 @@ func checkStringOmits(t *testing.T, got, expected string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onetwo = "one two"
|
||||||
|
|
||||||
func TestSingleCommand(t *testing.T) {
|
func TestSingleCommand(t *testing.T) {
|
||||||
var rootCmdArgs []string
|
var rootCmdArgs []string
|
||||||
rootCmd := &Command{
|
rootCmd := &Command{
|
||||||
@ -78,9 +80,8 @@ func TestSingleCommand(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(rootCmdArgs, " ")
|
got := strings.Join(rootCmdArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("rootCmdArgs expected: %q, got: %q", onetwo, got)
|
||||||
t.Errorf("rootCmdArgs expected: %q, got: %q", expected, got)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,9 +105,8 @@ func TestChildCommand(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(child1CmdArgs, " ")
|
got := strings.Join(child1CmdArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("child1CmdArgs expected: %q, got: %q", onetwo, got)
|
||||||
t.Errorf("child1CmdArgs expected: %q, got: %q", expected, got)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ func TestSubcommandExecuteC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.Name() != "child" {
|
if c.Name() != "child" {
|
||||||
t.Errorf(`invalid command returned from ExecuteC: expected "child"', got %q`, c.Name())
|
t.Errorf(`invalid command returned from ExecuteC: expected "child"', got: %q`, c.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,9 +243,8 @@ func TestCommandAlias(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(timesCmdArgs, " ")
|
got := strings.Join(timesCmdArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("timesCmdArgs expected: %v, got: %v", onetwo, got)
|
||||||
t.Errorf("timesCmdArgs expected: %v, got: %v", expected, got)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,9 +270,8 @@ func TestEnablePrefixMatching(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(aCmdArgs, " ")
|
got := strings.Join(aCmdArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("aCmdArgs expected: %q, got: %q", onetwo, got)
|
||||||
t.Errorf("aCmdArgs expected: %q, got: %q", expected, got)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EnablePrefixMatching = false
|
EnablePrefixMatching = false
|
||||||
@ -307,9 +305,8 @@ func TestAliasPrefixMatching(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(timesCmdArgs, " ")
|
got := strings.Join(timesCmdArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("timesCmdArgs expected: %v, got: %v", onetwo, got)
|
||||||
t.Errorf("timesCmdArgs expected: %v, got: %v", expected, got)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EnablePrefixMatching = false
|
EnablePrefixMatching = false
|
||||||
@ -338,9 +335,8 @@ func TestChildSameName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(fooCmdArgs, " ")
|
got := strings.Join(fooCmdArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("fooCmdArgs expected: %v, got: %v", onetwo, got)
|
||||||
t.Errorf("fooCmdArgs expected: %v, got: %v", expected, got)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,9 +364,8 @@ func TestGrandChildSameName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(fooCmdArgs, " ")
|
got := strings.Join(fooCmdArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("fooCmdArgs expected: %v, got: %v", onetwo, got)
|
||||||
t.Errorf("fooCmdArgs expected: %v, got: %v", expected, got)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,9 +401,8 @@ func TestFlagLong(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(cArgs, " ")
|
got := strings.Join(cArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("rootCmdArgs expected: %q, got: %q", onetwo, got)
|
||||||
t.Errorf("Expected arguments: %q, got %q", expected, got)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,9 +435,8 @@ func TestFlagShort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(cArgs, " ")
|
got := strings.Join(cArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("rootCmdArgs expected: %q, got: %q", onetwo, got)
|
||||||
t.Errorf("Expected arguments: %q, got %q", expected, got)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,9 +638,8 @@ func TestPersistentFlagsOnSameCommand(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(rootCmdArgs, " ")
|
got := strings.Join(rootCmdArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("rootCmdArgs expected: %q, got %q", onetwo, got)
|
||||||
t.Errorf("rootCmdArgs expected: %q, got %q", expected, got)
|
|
||||||
}
|
}
|
||||||
if flagValue != 7 {
|
if flagValue != 7 {
|
||||||
t.Errorf("flagValue expected: %v, got %v", 7, flagValue)
|
t.Errorf("flagValue expected: %v, got %v", 7, flagValue)
|
||||||
@ -731,9 +723,8 @@ func TestPersistentFlagsOnChild(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
got := strings.Join(childCmdArgs, " ")
|
got := strings.Join(childCmdArgs, " ")
|
||||||
expected := "one two"
|
if got != onetwo {
|
||||||
if got != expected {
|
t.Errorf("rootCmdArgs expected: %q, got: %q", onetwo, got)
|
||||||
t.Errorf("childCmdArgs expected: %q, got %q", expected, got)
|
|
||||||
}
|
}
|
||||||
if parentFlagValue != 8 {
|
if parentFlagValue != 8 {
|
||||||
t.Errorf("parentFlagValue expected: %v, got %v", 8, parentFlagValue)
|
t.Errorf("parentFlagValue expected: %v, got %v", 8, parentFlagValue)
|
||||||
@ -746,9 +737,9 @@ func TestPersistentFlagsOnChild(t *testing.T) {
|
|||||||
func TestRequiredFlags(t *testing.T) {
|
func TestRequiredFlags(t *testing.T) {
|
||||||
c := &Command{Use: "c", Run: emptyRun}
|
c := &Command{Use: "c", Run: emptyRun}
|
||||||
c.Flags().String("foo1", "", "")
|
c.Flags().String("foo1", "", "")
|
||||||
c.MarkFlagRequired("foo1")
|
assertNoErr(t, c.MarkFlagRequired("foo1"))
|
||||||
c.Flags().String("foo2", "", "")
|
c.Flags().String("foo2", "", "")
|
||||||
c.MarkFlagRequired("foo2")
|
assertNoErr(t, c.MarkFlagRequired("foo2"))
|
||||||
c.Flags().String("bar", "", "")
|
c.Flags().String("bar", "", "")
|
||||||
|
|
||||||
expected := fmt.Sprintf("required flag(s) %q, %q not set", "foo1", "foo2")
|
expected := fmt.Sprintf("required flag(s) %q, %q not set", "foo1", "foo2")
|
||||||
@ -764,16 +755,16 @@ func TestRequiredFlags(t *testing.T) {
|
|||||||
func TestPersistentRequiredFlags(t *testing.T) {
|
func TestPersistentRequiredFlags(t *testing.T) {
|
||||||
parent := &Command{Use: "parent", Run: emptyRun}
|
parent := &Command{Use: "parent", Run: emptyRun}
|
||||||
parent.PersistentFlags().String("foo1", "", "")
|
parent.PersistentFlags().String("foo1", "", "")
|
||||||
parent.MarkPersistentFlagRequired("foo1")
|
assertNoErr(t, parent.MarkPersistentFlagRequired("foo1"))
|
||||||
parent.PersistentFlags().String("foo2", "", "")
|
parent.PersistentFlags().String("foo2", "", "")
|
||||||
parent.MarkPersistentFlagRequired("foo2")
|
assertNoErr(t, parent.MarkPersistentFlagRequired("foo2"))
|
||||||
parent.Flags().String("foo3", "", "")
|
parent.Flags().String("foo3", "", "")
|
||||||
|
|
||||||
child := &Command{Use: "child", Run: emptyRun}
|
child := &Command{Use: "child", Run: emptyRun}
|
||||||
child.Flags().String("bar1", "", "")
|
child.Flags().String("bar1", "", "")
|
||||||
child.MarkFlagRequired("bar1")
|
assertNoErr(t, child.MarkFlagRequired("bar1"))
|
||||||
child.Flags().String("bar2", "", "")
|
child.Flags().String("bar2", "", "")
|
||||||
child.MarkFlagRequired("bar2")
|
assertNoErr(t, child.MarkFlagRequired("bar2"))
|
||||||
child.Flags().String("bar3", "", "")
|
child.Flags().String("bar3", "", "")
|
||||||
|
|
||||||
parent.AddCommand(child)
|
parent.AddCommand(child)
|
||||||
@ -793,7 +784,7 @@ func TestPersistentRequiredFlagsWithDisableFlagParsing(t *testing.T) {
|
|||||||
parent := &Command{Use: "parent", Run: emptyRun}
|
parent := &Command{Use: "parent", Run: emptyRun}
|
||||||
parent.PersistentFlags().Bool("foo", false, "")
|
parent.PersistentFlags().Bool("foo", false, "")
|
||||||
flag := parent.PersistentFlags().Lookup("foo")
|
flag := parent.PersistentFlags().Lookup("foo")
|
||||||
parent.MarkPersistentFlagRequired("foo")
|
assertNoErr(t, parent.MarkPersistentFlagRequired("foo"))
|
||||||
|
|
||||||
child := &Command{Use: "child", Run: emptyRun}
|
child := &Command{Use: "child", Run: emptyRun}
|
||||||
child.DisableFlagParsing = true
|
child.DisableFlagParsing = true
|
||||||
@ -1299,20 +1290,19 @@ func TestHooks(t *testing.T) {
|
|||||||
t.Errorf("Unexpected error: %v", err)
|
t.Errorf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if persPreArgs != "one two" {
|
for _, v := range []struct {
|
||||||
t.Errorf("Expected persPreArgs %q, got %q", "one two", persPreArgs)
|
name string
|
||||||
}
|
got string
|
||||||
if preArgs != "one two" {
|
}{
|
||||||
t.Errorf("Expected preArgs %q, got %q", "one two", preArgs)
|
{"persPreArgs", persPreArgs},
|
||||||
}
|
{"preArgs", preArgs},
|
||||||
if runArgs != "one two" {
|
{"runArgs", runArgs},
|
||||||
t.Errorf("Expected runArgs %q, got %q", "one two", runArgs)
|
{"postArgs", postArgs},
|
||||||
}
|
{"persPostArgs", persPostArgs},
|
||||||
if postArgs != "one two" {
|
} {
|
||||||
t.Errorf("Expected postArgs %q, got %q", "one two", postArgs)
|
if v.got != onetwo {
|
||||||
}
|
t.Errorf("Expected %s %q, got %q", v.name, onetwo, v.got)
|
||||||
if persPostArgs != "one two" {
|
}
|
||||||
t.Errorf("Expected persPostArgs %q, got %q", "one two", persPostArgs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1380,44 +1370,42 @@ func TestPersistentHooks(t *testing.T) {
|
|||||||
t.Errorf("Unexpected error: %v", err)
|
t.Errorf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: currently PersistenPreRun* defined in parent does not
|
for _, v := range []struct {
|
||||||
// run if the matchin child subcommand has PersistenPreRun.
|
name string
|
||||||
// If the behavior changes (https://github.com/spf13/cobra/issues/252)
|
got string
|
||||||
// this test must be fixed.
|
}{
|
||||||
if parentPersPreArgs != "" {
|
// TODO: currently PersistenPreRun* defined in parent does not
|
||||||
t.Errorf("Expected blank parentPersPreArgs, got %q", parentPersPreArgs)
|
// run if the matchin child subcommand has PersistenPreRun.
|
||||||
}
|
// If the behavior changes (https://github.com/spf13/cobra/issues/252)
|
||||||
if parentPreArgs != "" {
|
// this test must be fixed.
|
||||||
t.Errorf("Expected blank parentPreArgs, got %q", parentPreArgs)
|
{"parentPersPreArgs", parentPersPreArgs},
|
||||||
}
|
{"parentPreArgs", parentPreArgs},
|
||||||
if parentRunArgs != "" {
|
{"parentRunArgs", parentRunArgs},
|
||||||
t.Errorf("Expected blank parentRunArgs, got %q", parentRunArgs)
|
{"parentPostArgs", parentPostArgs},
|
||||||
}
|
// TODO: currently PersistenPostRun* defined in parent does not
|
||||||
if parentPostArgs != "" {
|
// run if the matchin child subcommand has PersistenPostRun.
|
||||||
t.Errorf("Expected blank parentPostArgs, got %q", parentPostArgs)
|
// If the behavior changes (https://github.com/spf13/cobra/issues/252)
|
||||||
}
|
// this test must be fixed.
|
||||||
// TODO: currently PersistenPostRun* defined in parent does not
|
{"parentPersPostArgs", parentPersPostArgs},
|
||||||
// run if the matchin child subcommand has PersistenPostRun.
|
} {
|
||||||
// If the behavior changes (https://github.com/spf13/cobra/issues/252)
|
if v.got != "" {
|
||||||
// this test must be fixed.
|
t.Errorf("Expected blank %s, got %q", v.name, v.got)
|
||||||
if parentPersPostArgs != "" {
|
}
|
||||||
t.Errorf("Expected blank parentPersPostArgs, got %q", parentPersPostArgs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if childPersPreArgs != "one two" {
|
for _, v := range []struct {
|
||||||
t.Errorf("Expected childPersPreArgs %q, got %q", "one two", childPersPreArgs)
|
name string
|
||||||
}
|
got string
|
||||||
if childPreArgs != "one two" {
|
}{
|
||||||
t.Errorf("Expected childPreArgs %q, got %q", "one two", childPreArgs)
|
{"childPersPreArgs", childPersPreArgs},
|
||||||
}
|
{"childPreArgs", childPreArgs},
|
||||||
if childRunArgs != "one two" {
|
{"childRunArgs", childRunArgs},
|
||||||
t.Errorf("Expected childRunArgs %q, got %q", "one two", childRunArgs)
|
{"childPostArgs", childPostArgs},
|
||||||
}
|
{"childPersPostArgs", childPersPostArgs},
|
||||||
if childPostArgs != "one two" {
|
} {
|
||||||
t.Errorf("Expected childPostArgs %q, got %q", "one two", childPostArgs)
|
if v.got != onetwo {
|
||||||
}
|
t.Errorf("Expected %s %q, got %q", v.name, onetwo, v.got)
|
||||||
if childPersPostArgs != "one two" {
|
}
|
||||||
t.Errorf("Expected childPersPostArgs %q, got %q", "one two", childPersPostArgs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1741,7 +1729,7 @@ func TestMergeCommandLineToFlags(t *testing.T) {
|
|||||||
func TestUseDeprecatedFlags(t *testing.T) {
|
func TestUseDeprecatedFlags(t *testing.T) {
|
||||||
c := &Command{Use: "c", Run: emptyRun}
|
c := &Command{Use: "c", Run: emptyRun}
|
||||||
c.Flags().BoolP("deprecated", "d", false, "deprecated flag")
|
c.Flags().BoolP("deprecated", "d", false, "deprecated flag")
|
||||||
c.Flags().MarkDeprecated("deprecated", "This flag is deprecated")
|
assertNoErr(t, c.Flags().MarkDeprecated("deprecated", "This flag is deprecated"))
|
||||||
|
|
||||||
output, err := executeCommand(c, "c", "-d")
|
output, err := executeCommand(c, "c", "-d")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1868,7 +1856,6 @@ type calledAsTestcase struct {
|
|||||||
call string
|
call string
|
||||||
want string
|
want string
|
||||||
epm bool
|
epm bool
|
||||||
tc bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *calledAsTestcase) test(t *testing.T) {
|
func (tc *calledAsTestcase) test(t *testing.T) {
|
||||||
@ -1890,7 +1877,7 @@ func (tc *calledAsTestcase) test(t *testing.T) {
|
|||||||
parent.SetOut(output)
|
parent.SetOut(output)
|
||||||
parent.SetErr(output)
|
parent.SetErr(output)
|
||||||
|
|
||||||
parent.Execute()
|
_ = parent.Execute()
|
||||||
|
|
||||||
if called == nil {
|
if called == nil {
|
||||||
if tc.call != "" {
|
if tc.call != "" {
|
||||||
@ -1908,18 +1895,18 @@ func (tc *calledAsTestcase) test(t *testing.T) {
|
|||||||
|
|
||||||
func TestCalledAs(t *testing.T) {
|
func TestCalledAs(t *testing.T) {
|
||||||
tests := map[string]calledAsTestcase{
|
tests := map[string]calledAsTestcase{
|
||||||
"find/no-args": {nil, "parent", "parent", false, false},
|
"find/no-args": {nil, "parent", "parent", false},
|
||||||
"find/real-name": {[]string{"child1"}, "child1", "child1", false, false},
|
"find/real-name": {[]string{"child1"}, "child1", "child1", false},
|
||||||
"find/full-alias": {[]string{"that"}, "child2", "that", false, false},
|
"find/full-alias": {[]string{"that"}, "child2", "that", false},
|
||||||
"find/part-no-prefix": {[]string{"thi"}, "", "", false, false},
|
"find/part-no-prefix": {[]string{"thi"}, "", "", false},
|
||||||
"find/part-alias": {[]string{"thi"}, "child1", "this", true, false},
|
"find/part-alias": {[]string{"thi"}, "child1", "this", true},
|
||||||
"find/conflict": {[]string{"th"}, "", "", true, false},
|
"find/conflict": {[]string{"th"}, "", "", true},
|
||||||
"traverse/no-args": {nil, "parent", "parent", false, true},
|
"traverse/no-args": {nil, "parent", "parent", false},
|
||||||
"traverse/real-name": {[]string{"child1"}, "child1", "child1", false, true},
|
"traverse/real-name": {[]string{"child1"}, "child1", "child1", false},
|
||||||
"traverse/full-alias": {[]string{"that"}, "child2", "that", false, true},
|
"traverse/full-alias": {[]string{"that"}, "child2", "that", false},
|
||||||
"traverse/part-no-prefix": {[]string{"thi"}, "", "", false, true},
|
"traverse/part-no-prefix": {[]string{"thi"}, "", "", false},
|
||||||
"traverse/part-alias": {[]string{"thi"}, "child1", "this", true, true},
|
"traverse/part-alias": {[]string{"thi"}, "child1", "this", true},
|
||||||
"traverse/conflict": {[]string{"th"}, "", "", true, true},
|
"traverse/conflict": {[]string{"th"}, "", "", true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tc := range tests {
|
for name, tc := range tests {
|
||||||
|
@ -527,13 +527,13 @@ func CompDebug(msg string, printToStdErr bool) {
|
|||||||
os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
f.WriteString(msg)
|
WriteStringAndCheck(f, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if printToStdErr {
|
if printToStdErr {
|
||||||
// Must print to stderr for this not to be read by the completion script.
|
// Must print to stderr for this not to be read by the completion script.
|
||||||
fmt.Fprintf(os.Stderr, msg)
|
fmt.Fprint(os.Stderr, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -780,17 +780,17 @@ func TestRequiredFlagNameCompletionInGo(t *testing.T) {
|
|||||||
rootCmd.AddCommand(childCmd)
|
rootCmd.AddCommand(childCmd)
|
||||||
|
|
||||||
rootCmd.Flags().IntP("requiredFlag", "r", -1, "required flag")
|
rootCmd.Flags().IntP("requiredFlag", "r", -1, "required flag")
|
||||||
rootCmd.MarkFlagRequired("requiredFlag")
|
assertNoErr(t, rootCmd.MarkFlagRequired("requiredFlag"))
|
||||||
requiredFlag := rootCmd.Flags().Lookup("requiredFlag")
|
requiredFlag := rootCmd.Flags().Lookup("requiredFlag")
|
||||||
|
|
||||||
rootCmd.PersistentFlags().IntP("requiredPersistent", "p", -1, "required persistent")
|
rootCmd.PersistentFlags().IntP("requiredPersistent", "p", -1, "required persistent")
|
||||||
rootCmd.MarkPersistentFlagRequired("requiredPersistent")
|
assertNoErr(t, rootCmd.MarkPersistentFlagRequired("requiredPersistent"))
|
||||||
requiredPersistent := rootCmd.PersistentFlags().Lookup("requiredPersistent")
|
requiredPersistent := rootCmd.PersistentFlags().Lookup("requiredPersistent")
|
||||||
|
|
||||||
rootCmd.Flags().StringP("release", "R", "", "Release name")
|
rootCmd.Flags().StringP("release", "R", "", "Release name")
|
||||||
|
|
||||||
childCmd.Flags().BoolP("subRequired", "s", false, "sub required flag")
|
childCmd.Flags().BoolP("subRequired", "s", false, "sub required flag")
|
||||||
childCmd.MarkFlagRequired("subRequired")
|
assertNoErr(t, childCmd.MarkFlagRequired("subRequired"))
|
||||||
childCmd.Flags().BoolP("subNotRequired", "n", false, "sub not required flag")
|
childCmd.Flags().BoolP("subNotRequired", "n", false, "sub not required flag")
|
||||||
|
|
||||||
// Test that a required flag is suggested even without the - prefix
|
// Test that a required flag is suggested even without the - prefix
|
||||||
@ -964,19 +964,19 @@ func TestFlagFileExtFilterCompletionInGo(t *testing.T) {
|
|||||||
|
|
||||||
// No extensions. Should be ignored.
|
// No extensions. Should be ignored.
|
||||||
rootCmd.Flags().StringP("file", "f", "", "file flag")
|
rootCmd.Flags().StringP("file", "f", "", "file flag")
|
||||||
rootCmd.MarkFlagFilename("file")
|
assertNoErr(t, rootCmd.MarkFlagFilename("file"))
|
||||||
|
|
||||||
// Single extension
|
// Single extension
|
||||||
rootCmd.Flags().StringP("log", "l", "", "log flag")
|
rootCmd.Flags().StringP("log", "l", "", "log flag")
|
||||||
rootCmd.MarkFlagFilename("log", "log")
|
assertNoErr(t, rootCmd.MarkFlagFilename("log", "log"))
|
||||||
|
|
||||||
// Multiple extensions
|
// Multiple extensions
|
||||||
rootCmd.Flags().StringP("yaml", "y", "", "yaml flag")
|
rootCmd.Flags().StringP("yaml", "y", "", "yaml flag")
|
||||||
rootCmd.MarkFlagFilename("yaml", "yaml", "yml")
|
assertNoErr(t, rootCmd.MarkFlagFilename("yaml", "yaml", "yml"))
|
||||||
|
|
||||||
// Directly using annotation
|
// Directly using annotation
|
||||||
rootCmd.Flags().StringP("text", "t", "", "text flag")
|
rootCmd.Flags().StringP("text", "t", "", "text flag")
|
||||||
rootCmd.Flags().SetAnnotation("text", BashCompFilenameExt, []string{"txt"})
|
assertNoErr(t, rootCmd.Flags().SetAnnotation("text", BashCompFilenameExt, []string{"txt"}))
|
||||||
|
|
||||||
// Test that the completion logic returns the proper info for the completion
|
// Test that the completion logic returns the proper info for the completion
|
||||||
// script to handle the file filtering
|
// script to handle the file filtering
|
||||||
@ -1086,15 +1086,15 @@ func TestFlagDirFilterCompletionInGo(t *testing.T) {
|
|||||||
|
|
||||||
// Filter directories
|
// Filter directories
|
||||||
rootCmd.Flags().StringP("dir", "d", "", "dir flag")
|
rootCmd.Flags().StringP("dir", "d", "", "dir flag")
|
||||||
rootCmd.MarkFlagDirname("dir")
|
assertNoErr(t, rootCmd.MarkFlagDirname("dir"))
|
||||||
|
|
||||||
// Filter directories within a directory
|
// Filter directories within a directory
|
||||||
rootCmd.Flags().StringP("subdir", "s", "", "subdir")
|
rootCmd.Flags().StringP("subdir", "s", "", "subdir")
|
||||||
rootCmd.Flags().SetAnnotation("subdir", BashCompSubdirsInDir, []string{"themes"})
|
assertNoErr(t, rootCmd.Flags().SetAnnotation("subdir", BashCompSubdirsInDir, []string{"themes"}))
|
||||||
|
|
||||||
// Multiple directory specification get ignored
|
// Multiple directory specification get ignored
|
||||||
rootCmd.Flags().StringP("manydir", "m", "", "manydir")
|
rootCmd.Flags().StringP("manydir", "m", "", "manydir")
|
||||||
rootCmd.Flags().SetAnnotation("manydir", BashCompSubdirsInDir, []string{"themes", "colors"})
|
assertNoErr(t, rootCmd.Flags().SetAnnotation("manydir", BashCompSubdirsInDir, []string{"themes", "colors"}))
|
||||||
|
|
||||||
// Test that the completion logic returns the proper info for the completion
|
// Test that the completion logic returns the proper info for the completion
|
||||||
// script to handle the directory filtering
|
// script to handle the directory filtering
|
||||||
@ -1430,7 +1430,7 @@ func TestValidArgsFuncInBashScript(t *testing.T) {
|
|||||||
rootCmd.AddCommand(child)
|
rootCmd.AddCommand(child)
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
rootCmd.GenBashCompletion(buf)
|
assertNoErr(t, rootCmd.GenBashCompletion(buf))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
check(t, output, "has_completion_function=1")
|
check(t, output, "has_completion_function=1")
|
||||||
@ -1445,7 +1445,7 @@ func TestNoValidArgsFuncInBashScript(t *testing.T) {
|
|||||||
rootCmd.AddCommand(child)
|
rootCmd.AddCommand(child)
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
rootCmd.GenBashCompletion(buf)
|
assertNoErr(t, rootCmd.GenBashCompletion(buf))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
checkOmit(t, output, "has_completion_function=1")
|
checkOmit(t, output, "has_completion_function=1")
|
||||||
@ -1461,7 +1461,7 @@ func TestCompleteCmdInBashScript(t *testing.T) {
|
|||||||
rootCmd.AddCommand(child)
|
rootCmd.AddCommand(child)
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
rootCmd.GenBashCompletion(buf)
|
assertNoErr(t, rootCmd.GenBashCompletion(buf))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
check(t, output, ShellCompNoDescRequestCmd)
|
check(t, output, ShellCompNoDescRequestCmd)
|
||||||
@ -1477,7 +1477,7 @@ func TestCompleteNoDesCmdInZshScript(t *testing.T) {
|
|||||||
rootCmd.AddCommand(child)
|
rootCmd.AddCommand(child)
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
rootCmd.GenZshCompletionNoDesc(buf)
|
assertNoErr(t, rootCmd.GenZshCompletionNoDesc(buf))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
check(t, output, ShellCompNoDescRequestCmd)
|
check(t, output, ShellCompNoDescRequestCmd)
|
||||||
@ -1493,7 +1493,7 @@ func TestCompleteCmdInZshScript(t *testing.T) {
|
|||||||
rootCmd.AddCommand(child)
|
rootCmd.AddCommand(child)
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
rootCmd.GenZshCompletion(buf)
|
assertNoErr(t, rootCmd.GenZshCompletion(buf))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
check(t, output, ShellCompRequestCmd)
|
check(t, output, ShellCompRequestCmd)
|
||||||
@ -1506,7 +1506,7 @@ func TestFlagCompletionInGo(t *testing.T) {
|
|||||||
Run: emptyRun,
|
Run: emptyRun,
|
||||||
}
|
}
|
||||||
rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot")
|
rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot")
|
||||||
rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
assertNoErr(t, rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||||||
completions := []string{}
|
completions := []string{}
|
||||||
for _, comp := range []string{"1\tThe first", "2\tThe second", "10\tThe tenth"} {
|
for _, comp := range []string{"1\tThe first", "2\tThe second", "10\tThe tenth"} {
|
||||||
if strings.HasPrefix(comp, toComplete) {
|
if strings.HasPrefix(comp, toComplete) {
|
||||||
@ -1514,9 +1514,9 @@ func TestFlagCompletionInGo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return completions, ShellCompDirectiveDefault
|
return completions, ShellCompDirectiveDefault
|
||||||
})
|
}))
|
||||||
rootCmd.Flags().String("filename", "", "Enter a filename")
|
rootCmd.Flags().String("filename", "", "Enter a filename")
|
||||||
rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
assertNoErr(t, rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||||||
completions := []string{}
|
completions := []string{}
|
||||||
for _, comp := range []string{"file.yaml\tYAML format", "myfile.json\tJSON format", "file.xml\tXML format"} {
|
for _, comp := range []string{"file.yaml\tYAML format", "myfile.json\tJSON format", "file.xml\tXML format"} {
|
||||||
if strings.HasPrefix(comp, toComplete) {
|
if strings.HasPrefix(comp, toComplete) {
|
||||||
@ -1524,7 +1524,7 @@ func TestFlagCompletionInGo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return completions, ShellCompDirectiveNoSpace | ShellCompDirectiveNoFileComp
|
return completions, ShellCompDirectiveNoSpace | ShellCompDirectiveNoFileComp
|
||||||
})
|
}))
|
||||||
|
|
||||||
// Test completing an empty string
|
// Test completing an empty string
|
||||||
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "--introot", "")
|
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "--introot", "")
|
||||||
@ -1703,7 +1703,7 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) {
|
|||||||
Run: emptyRun,
|
Run: emptyRun,
|
||||||
}
|
}
|
||||||
rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot")
|
rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot")
|
||||||
rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
assertNoErr(t, rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||||||
completions := []string{}
|
completions := []string{}
|
||||||
for _, comp := range []string{"1\tThe first", "2\tThe second", "10\tThe tenth"} {
|
for _, comp := range []string{"1\tThe first", "2\tThe second", "10\tThe tenth"} {
|
||||||
if strings.HasPrefix(comp, toComplete) {
|
if strings.HasPrefix(comp, toComplete) {
|
||||||
@ -1711,9 +1711,9 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return completions, ShellCompDirectiveDefault
|
return completions, ShellCompDirectiveDefault
|
||||||
})
|
}))
|
||||||
rootCmd.Flags().String("filename", "", "Enter a filename")
|
rootCmd.Flags().String("filename", "", "Enter a filename")
|
||||||
rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
assertNoErr(t, rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||||||
completions := []string{}
|
completions := []string{}
|
||||||
for _, comp := range []string{"file.yaml\tYAML format", "myfile.json\tJSON format", "file.xml\tXML format"} {
|
for _, comp := range []string{"file.yaml\tYAML format", "myfile.json\tJSON format", "file.xml\tXML format"} {
|
||||||
if strings.HasPrefix(comp, toComplete) {
|
if strings.HasPrefix(comp, toComplete) {
|
||||||
@ -1721,7 +1721,7 @@ func TestFlagCompletionInGoWithDesc(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return completions, ShellCompDirectiveNoSpace | ShellCompDirectiveNoFileComp
|
return completions, ShellCompDirectiveNoSpace | ShellCompDirectiveNoFileComp
|
||||||
})
|
}))
|
||||||
|
|
||||||
// Test completing an empty string
|
// Test completing an empty string
|
||||||
output, err := executeCommand(rootCmd, ShellCompRequestCmd, "--introot", "")
|
output, err := executeCommand(rootCmd, ShellCompRequestCmd, "--introot", "")
|
||||||
|
@ -139,23 +139,23 @@ func fillHeader(header *GenManHeader, name string, disableAutoGen bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func manPreamble(buf *bytes.Buffer, header *GenManHeader, cmd *cobra.Command, dashedName string) {
|
func manPreamble(buf io.StringWriter, header *GenManHeader, cmd *cobra.Command, dashedName string) {
|
||||||
description := cmd.Long
|
description := cmd.Long
|
||||||
if len(description) == 0 {
|
if len(description) == 0 {
|
||||||
description = cmd.Short
|
description = cmd.Short
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.WriteString(fmt.Sprintf(`%% "%s" "%s" "%s" "%s" "%s"
|
cobra.WriteStringAndCheck(buf, fmt.Sprintf(`%% "%s" "%s" "%s" "%s" "%s"
|
||||||
# NAME
|
# NAME
|
||||||
`, header.Title, header.Section, header.date, header.Source, header.Manual))
|
`, header.Title, header.Section, header.date, header.Source, header.Manual))
|
||||||
buf.WriteString(fmt.Sprintf("%s \\- %s\n\n", dashedName, cmd.Short))
|
cobra.WriteStringAndCheck(buf, fmt.Sprintf("%s \\- %s\n\n", dashedName, cmd.Short))
|
||||||
buf.WriteString("# SYNOPSIS\n")
|
cobra.WriteStringAndCheck(buf, "# SYNOPSIS\n")
|
||||||
buf.WriteString(fmt.Sprintf("**%s**\n\n", cmd.UseLine()))
|
cobra.WriteStringAndCheck(buf, fmt.Sprintf("**%s**\n\n", cmd.UseLine()))
|
||||||
buf.WriteString("# DESCRIPTION\n")
|
cobra.WriteStringAndCheck(buf, "# DESCRIPTION\n")
|
||||||
buf.WriteString(description + "\n\n")
|
cobra.WriteStringAndCheck(buf, description+"\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func manPrintFlags(buf *bytes.Buffer, flags *pflag.FlagSet) {
|
func manPrintFlags(buf io.StringWriter, flags *pflag.FlagSet) {
|
||||||
flags.VisitAll(func(flag *pflag.Flag) {
|
flags.VisitAll(func(flag *pflag.Flag) {
|
||||||
if len(flag.Deprecated) > 0 || flag.Hidden {
|
if len(flag.Deprecated) > 0 || flag.Hidden {
|
||||||
return
|
return
|
||||||
@ -179,22 +179,22 @@ func manPrintFlags(buf *bytes.Buffer, flags *pflag.FlagSet) {
|
|||||||
format += "]"
|
format += "]"
|
||||||
}
|
}
|
||||||
format += "\n\t%s\n\n"
|
format += "\n\t%s\n\n"
|
||||||
buf.WriteString(fmt.Sprintf(format, flag.DefValue, flag.Usage))
|
cobra.WriteStringAndCheck(buf, fmt.Sprintf(format, flag.DefValue, flag.Usage))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func manPrintOptions(buf *bytes.Buffer, command *cobra.Command) {
|
func manPrintOptions(buf io.StringWriter, command *cobra.Command) {
|
||||||
flags := command.NonInheritedFlags()
|
flags := command.NonInheritedFlags()
|
||||||
if flags.HasAvailableFlags() {
|
if flags.HasAvailableFlags() {
|
||||||
buf.WriteString("# OPTIONS\n")
|
cobra.WriteStringAndCheck(buf, "# OPTIONS\n")
|
||||||
manPrintFlags(buf, flags)
|
manPrintFlags(buf, flags)
|
||||||
buf.WriteString("\n")
|
cobra.WriteStringAndCheck(buf, "\n")
|
||||||
}
|
}
|
||||||
flags = command.InheritedFlags()
|
flags = command.InheritedFlags()
|
||||||
if flags.HasAvailableFlags() {
|
if flags.HasAvailableFlags() {
|
||||||
buf.WriteString("# OPTIONS INHERITED FROM PARENT COMMANDS\n")
|
cobra.WriteStringAndCheck(buf, "# OPTIONS INHERITED FROM PARENT COMMANDS\n")
|
||||||
manPrintFlags(buf, flags)
|
manPrintFlags(buf, flags)
|
||||||
buf.WriteString("\n")
|
cobra.WriteStringAndCheck(buf, "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,12 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func assertNoErr(t *testing.T, e error) {
|
||||||
|
if e != nil {
|
||||||
|
t.Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func translate(in string) string {
|
func translate(in string) string {
|
||||||
return strings.Replace(in, "-", "\\-", -1)
|
return strings.Replace(in, "-", "\\-", -1)
|
||||||
}
|
}
|
||||||
@ -133,7 +139,7 @@ func TestGenManSeeAlso(t *testing.T) {
|
|||||||
func TestManPrintFlagsHidesShortDeperecated(t *testing.T) {
|
func TestManPrintFlagsHidesShortDeperecated(t *testing.T) {
|
||||||
c := &cobra.Command{}
|
c := &cobra.Command{}
|
||||||
c.Flags().StringP("foo", "f", "default", "Foo flag")
|
c.Flags().StringP("foo", "f", "default", "Foo flag")
|
||||||
c.Flags().MarkShorthandDeprecated("foo", "don't use it no more")
|
assertNoErr(t, c.Flags().MarkShorthandDeprecated("foo", "don't use it no more"))
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
manPrintFlags(buf, c.Flags())
|
manPrintFlags(buf, c.Flags())
|
||||||
|
@ -17,7 +17,7 @@ func ExampleGenManTree() {
|
|||||||
Title: "MINE",
|
Title: "MINE",
|
||||||
Section: "3",
|
Section: "3",
|
||||||
}
|
}
|
||||||
doc.GenManTree(cmd, header, "/tmp")
|
cobra.CheckErr(doc.GenManTree(cmd, header, "/tmp"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleGenMan() {
|
func ExampleGenMan() {
|
||||||
@ -30,6 +30,6 @@ func ExampleGenMan() {
|
|||||||
Section: "3",
|
Section: "3",
|
||||||
}
|
}
|
||||||
out := new(bytes.Buffer)
|
out := new(bytes.Buffer)
|
||||||
doc.GenMan(cmd, header, out)
|
cobra.CheckErr(doc.GenMan(cmd, header, out))
|
||||||
fmt.Print(out.String())
|
fmt.Print(out.String())
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func genFishComp(buf *bytes.Buffer, name string, includeDesc bool) {
|
func genFishComp(buf io.StringWriter, name string, includeDesc bool) {
|
||||||
// Variables should not contain a '-' or ':' character
|
// Variables should not contain a '-' or ':' character
|
||||||
nameForVar := name
|
nameForVar := name
|
||||||
nameForVar = strings.Replace(nameForVar, "-", "_", -1)
|
nameForVar = strings.Replace(nameForVar, "-", "_", -1)
|
||||||
@ -18,8 +18,8 @@ func genFishComp(buf *bytes.Buffer, name string, includeDesc bool) {
|
|||||||
if !includeDesc {
|
if !includeDesc {
|
||||||
compCmd = ShellCompNoDescRequestCmd
|
compCmd = ShellCompNoDescRequestCmd
|
||||||
}
|
}
|
||||||
buf.WriteString(fmt.Sprintf("# fish completion for %-36s -*- shell-script -*-\n", name))
|
WriteStringAndCheck(buf, fmt.Sprintf("# fish completion for %-36s -*- shell-script -*-\n", name))
|
||||||
buf.WriteString(fmt.Sprintf(`
|
WriteStringAndCheck(buf, fmt.Sprintf(`
|
||||||
function __%[1]s_debug
|
function __%[1]s_debug
|
||||||
set file "$BASH_COMP_DEBUG_FILE"
|
set file "$BASH_COMP_DEBUG_FILE"
|
||||||
if test -n "$file"
|
if test -n "$file"
|
||||||
|
@ -15,7 +15,7 @@ func TestCompleteNoDesCmdInFishScript(t *testing.T) {
|
|||||||
rootCmd.AddCommand(child)
|
rootCmd.AddCommand(child)
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
rootCmd.GenFishCompletion(buf, false)
|
assertNoErr(t, rootCmd.GenFishCompletion(buf, false))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
check(t, output, ShellCompNoDescRequestCmd)
|
check(t, output, ShellCompNoDescRequestCmd)
|
||||||
@ -31,7 +31,7 @@ func TestCompleteCmdInFishScript(t *testing.T) {
|
|||||||
rootCmd.AddCommand(child)
|
rootCmd.AddCommand(child)
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
rootCmd.GenFishCompletion(buf, true)
|
assertNoErr(t, rootCmd.GenFishCompletion(buf, true))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
check(t, output, ShellCompRequestCmd)
|
check(t, output, ShellCompRequestCmd)
|
||||||
@ -41,7 +41,7 @@ func TestCompleteCmdInFishScript(t *testing.T) {
|
|||||||
func TestProgWithDash(t *testing.T) {
|
func TestProgWithDash(t *testing.T) {
|
||||||
rootCmd := &Command{Use: "root-dash", Args: NoArgs, Run: emptyRun}
|
rootCmd := &Command{Use: "root-dash", Args: NoArgs, Run: emptyRun}
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
rootCmd.GenFishCompletion(buf, false)
|
assertNoErr(t, rootCmd.GenFishCompletion(buf, false))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
// Functions name should have replace the '-'
|
// Functions name should have replace the '-'
|
||||||
@ -56,7 +56,7 @@ func TestProgWithDash(t *testing.T) {
|
|||||||
func TestProgWithColon(t *testing.T) {
|
func TestProgWithColon(t *testing.T) {
|
||||||
rootCmd := &Command{Use: "root:colon", Args: NoArgs, Run: emptyRun}
|
rootCmd := &Command{Use: "root:colon", Args: NoArgs, Run: emptyRun}
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
rootCmd.GenFishCompletion(buf, false)
|
assertNoErr(t, rootCmd.GenFishCompletion(buf, false))
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
// Functions name should have replace the ':'
|
// Functions name should have replace the ':'
|
||||||
|
@ -10,12 +10,12 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func genPowerShellComp(buf *bytes.Buffer, name string, includeDesc bool) {
|
func genPowerShellComp(buf io.StringWriter, name string, includeDesc bool) {
|
||||||
compCmd := ShellCompRequestCmd
|
compCmd := ShellCompRequestCmd
|
||||||
if !includeDesc {
|
if !includeDesc {
|
||||||
compCmd = ShellCompNoDescRequestCmd
|
compCmd = ShellCompNoDescRequestCmd
|
||||||
}
|
}
|
||||||
buf.WriteString(fmt.Sprintf(`# powershell completion for %-36[1]s -*- shell-script -*-
|
WriteStringAndCheck(buf, fmt.Sprintf(`# powershell completion for %-36[1]s -*- shell-script -*-
|
||||||
|
|
||||||
function __%[1]s_debug {
|
function __%[1]s_debug {
|
||||||
if ($env:BASH_COMP_DEBUG_FILE) {
|
if ($env:BASH_COMP_DEBUG_FILE) {
|
||||||
@ -46,12 +46,12 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
|
|||||||
# We need to trigger completion from the $CursorPosition location, so we need
|
# We need to trigger completion from the $CursorPosition location, so we need
|
||||||
# to truncate the command-line ($Command) up to the $CursorPosition location.
|
# to truncate the command-line ($Command) up to the $CursorPosition location.
|
||||||
# Make sure the $Command is longer then the $CursorPosition before we truncate.
|
# Make sure the $Command is longer then the $CursorPosition before we truncate.
|
||||||
# This happens because the $Command does not include the last space.
|
# This happens because the $Command does not include the last space.
|
||||||
if ($Command.Length -gt $CursorPosition) {
|
if ($Command.Length -gt $CursorPosition) {
|
||||||
$Command=$Command.Substring(0,$CursorPosition)
|
$Command=$Command.Substring(0,$CursorPosition)
|
||||||
}
|
}
|
||||||
__%[1]s_debug "Truncated command: $Command"
|
__%[1]s_debug "Truncated command: $Command"
|
||||||
|
|
||||||
$ShellCompDirectiveError=%[3]d
|
$ShellCompDirectiveError=%[3]d
|
||||||
$ShellCompDirectiveNoSpace=%[4]d
|
$ShellCompDirectiveNoSpace=%[4]d
|
||||||
$ShellCompDirectiveNoFileComp=%[5]d
|
$ShellCompDirectiveNoFileComp=%[5]d
|
||||||
@ -64,7 +64,7 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
|
|||||||
$RequestComp="$Program %[2]s $Arguments"
|
$RequestComp="$Program %[2]s $Arguments"
|
||||||
__%[1]s_debug "RequestComp: $RequestComp"
|
__%[1]s_debug "RequestComp: $RequestComp"
|
||||||
|
|
||||||
# we cannot use $WordToComplete because it
|
# we cannot use $WordToComplete because it
|
||||||
# has the wrong values if the cursor was moved
|
# has the wrong values if the cursor was moved
|
||||||
# so use the last argument
|
# so use the last argument
|
||||||
if ($WordToComplete -ne "" ) {
|
if ($WordToComplete -ne "" ) {
|
||||||
@ -102,7 +102,7 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
|
|||||||
$Directive = 0
|
$Directive = 0
|
||||||
}
|
}
|
||||||
__%[1]s_debug "The completion directive is: $Directive"
|
__%[1]s_debug "The completion directive is: $Directive"
|
||||||
|
|
||||||
# remove directive (last element) from out
|
# remove directive (last element) from out
|
||||||
$Out = $Out | Where-Object { $_ -ne $Out[-1] }
|
$Out = $Out | Where-Object { $_ -ne $Out[-1] }
|
||||||
__%[1]s_debug "The completions are: $Out"
|
__%[1]s_debug "The completions are: $Out"
|
||||||
@ -142,18 +142,18 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
|
|||||||
|
|
||||||
if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {
|
if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {
|
||||||
__%[1]s_debug "ShellCompDirectiveNoFileComp is called"
|
__%[1]s_debug "ShellCompDirectiveNoFileComp is called"
|
||||||
|
|
||||||
if ($Values.Length -eq 0) {
|
if ($Values.Length -eq 0) {
|
||||||
# Just print an empty string here so the
|
# Just print an empty string here so the
|
||||||
# shell does not start to complete paths.
|
# shell does not start to complete paths.
|
||||||
# We cannot use CompletionResult here because
|
# We cannot use CompletionResult here because
|
||||||
# it does not accept an empty string as argument.
|
# it does not accept an empty string as argument.
|
||||||
""
|
""
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or
|
if ((($Directive -band $ShellCompDirectiveFilterFileExt) -ne 0 ) -or
|
||||||
(($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) {
|
(($Directive -band $ShellCompDirectiveFilterDirs) -ne 0 )) {
|
||||||
__%[1]s_debug "ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported"
|
__%[1]s_debug "ShellCompDirectiveFilterFileExt ShellCompDirectiveFilterDirs are not supported"
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
|
|||||||
__%[1]s_debug "Join the equal sign flag back to the completion value"
|
__%[1]s_debug "Join the equal sign flag back to the completion value"
|
||||||
$_.Name = $Flag + "=" + $_.Name
|
$_.Name = $Flag + "=" + $_.Name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get the current mode
|
# Get the current mode
|
||||||
$Mode = (Get-PSReadLineKeyHandler | Where-Object {$_.Key -eq "Tab" }).Function
|
$Mode = (Get-PSReadLineKeyHandler | Where-Object {$_.Key -eq "Tab" }).Function
|
||||||
@ -224,14 +224,14 @@ Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock {
|
|||||||
# zsh like
|
# zsh like
|
||||||
"MenuComplete" {
|
"MenuComplete" {
|
||||||
# insert space after value
|
# insert space after value
|
||||||
# MenuComplete will automatically show the ToolTip of
|
# MenuComplete will automatically show the ToolTip of
|
||||||
# the highlighted value at the bottom of the suggestions.
|
# the highlighted value at the bottom of the suggestions.
|
||||||
[System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
|
[System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars) + $Space, "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
|
||||||
}
|
}
|
||||||
|
|
||||||
# TabCompleteNext and in case we get something unknown
|
# TabCompleteNext and in case we get something unknown
|
||||||
Default {
|
Default {
|
||||||
# Like MenuComplete but we don't want to add a space here because
|
# Like MenuComplete but we don't want to add a space here because
|
||||||
# the user need to press space anyway to get the completion.
|
# the user need to press space anyway to get the completion.
|
||||||
# Description will not be shown because thats not possible with TabCompleteNext
|
# Description will not be shown because thats not possible with TabCompleteNext
|
||||||
[System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars), "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
|
[System.Management.Automation.CompletionResult]::new($($comp.Name | __%[1]s_escapeStringWithSpecialChars), "$($comp.Name)", 'ParameterValue', "$($comp.Description)")
|
||||||
|
@ -99,8 +99,7 @@ cmd := &cobra.Command{
|
|||||||
Long: get_long,
|
Long: get_long,
|
||||||
Example: get_example,
|
Example: get_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunGet(f, out, cmd, args)
|
cobra.CheckErr(RunGet(f, out, cmd, args))
|
||||||
util.CheckErr(err)
|
|
||||||
},
|
},
|
||||||
ValidArgs: validArgs,
|
ValidArgs: validArgs,
|
||||||
}
|
}
|
||||||
@ -132,7 +131,7 @@ the completion algorithm if entered manually, e.g. in:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ kubectl get rc [tab][tab]
|
$ kubectl get rc [tab][tab]
|
||||||
backend frontend database
|
backend frontend database
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that without declaring `rc` as an alias, the completion algorithm would not know to show the list of
|
Note that without declaring `rc` as an alias, the completion algorithm would not know to show the list of
|
||||||
@ -254,7 +253,7 @@ and you'll get something like
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ kubectl exec [tab][tab]
|
$ kubectl exec [tab][tab]
|
||||||
-c --container= -p --pod=
|
-c --container= -p --pod=
|
||||||
```
|
```
|
||||||
|
|
||||||
### Specify dynamic flag completion
|
### Specify dynamic flag completion
|
||||||
|
@ -70,12 +70,12 @@ func (c *Command) genZshCompletion(w io.Writer, includeDesc bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func genZshComp(buf *bytes.Buffer, name string, includeDesc bool) {
|
func genZshComp(buf io.StringWriter, name string, includeDesc bool) {
|
||||||
compCmd := ShellCompRequestCmd
|
compCmd := ShellCompRequestCmd
|
||||||
if !includeDesc {
|
if !includeDesc {
|
||||||
compCmd = ShellCompNoDescRequestCmd
|
compCmd = ShellCompNoDescRequestCmd
|
||||||
}
|
}
|
||||||
buf.WriteString(fmt.Sprintf(`#compdef _%[1]s %[1]s
|
WriteStringAndCheck(buf, fmt.Sprintf(`#compdef _%[1]s %[1]s
|
||||||
|
|
||||||
# zsh completion for %-36[1]s -*- shell-script -*-
|
# zsh completion for %-36[1]s -*- shell-script -*-
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user