mirror of https://github.com/k3s-io/k3s
Merge pull request #60135 from superbrothers/fix-completion-error-in-bash-3
Automatic merge from submit-queue (batch tested with PRs 60346, 60135, 60289, 59643, 52640). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Update vendor spf13/cobra to fix completion error in bash 3 **What this PR does / why we need it**: This PR updates vendor spf13/cobra to fix completion error in bash 3. /ref spf13/cobra#628 /cc @eparis **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: Fixes kubernetes/kubectl#121, kubernetes/kubernetes#29322, kubernetes/kubernetes#32676. **Special notes for your reviewer**: **Release note**: ```release-note NONE ```pull/6/head
commit
308647b019
|
@ -2567,13 +2567,13 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/cobra",
|
||||
"Comment": "v0.0.1-10-g19e54c4",
|
||||
"Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f"
|
||||
"Comment": "v0.0.1-28-gfd32f09",
|
||||
"Rev": "fd32f09af19efc9b1279c54e0d8ed23f66232a15"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/cobra/doc",
|
||||
"Comment": "v0.0.1-10-g19e54c4",
|
||||
"Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f"
|
||||
"Comment": "v0.0.1-28-gfd32f09",
|
||||
"Rev": "fd32f09af19efc9b1279c54e0d8ed23f66232a15"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/jwalterweatherman",
|
||||
|
|
|
@ -584,7 +584,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/cobra",
|
||||
"Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f"
|
||||
"Rev": "fd32f09af19efc9b1279c54e0d8ed23f66232a15"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
|
|
|
@ -268,7 +268,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/cobra",
|
||||
"Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f"
|
||||
"Rev": "fd32f09af19efc9b1279c54e0d8ed23f66232a15"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
|
|
|
@ -252,7 +252,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/cobra",
|
||||
"Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f"
|
||||
"Rev": "fd32f09af19efc9b1279c54e0d8ed23f66232a15"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
|
|
|
@ -20,6 +20,7 @@ Many of the most widely used Go projects are built using Cobra including:
|
|||
* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
|
||||
* [rclone](http://rclone.org/)
|
||||
* [nehm](https://github.com/bogem/nehm)
|
||||
* [Pouch](https://github.com/alibaba/pouch)
|
||||
|
||||
[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra)
|
||||
[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra)
|
||||
|
@ -158,10 +159,7 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
if err := cmd.RootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cmd.Execute()
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -174,7 +172,7 @@ commands you want. It's the easiest way to incorporate Cobra into your applicati
|
|||
|
||||
## Using the Cobra Library
|
||||
|
||||
To manually implement Cobra you need to create a bare main.go file and a RootCmd file.
|
||||
To manually implement Cobra you need to create a bare main.go file and a rootCmd file.
|
||||
You will optionally provide additional commands as you see fit.
|
||||
|
||||
### Create rootCmd
|
||||
|
@ -184,7 +182,7 @@ Cobra doesn't require any special constructors. Simply create your commands.
|
|||
Ideally you place this in app/cmd/root.go:
|
||||
|
||||
```go
|
||||
var RootCmd = &cobra.Command{
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "hugo",
|
||||
Short: "Hugo is a very fast static site generator",
|
||||
Long: `A Fast and Flexible Static Site Generator built with
|
||||
|
@ -194,6 +192,13 @@ var RootCmd = &cobra.Command{
|
|||
// Do Stuff Here
|
||||
},
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You will additionally define flags and handle configuration in your init() function.
|
||||
|
@ -212,14 +217,14 @@ import (
|
|||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
|
||||
RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
|
||||
RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
|
||||
RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
|
||||
RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
|
||||
viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author"))
|
||||
viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase"))
|
||||
viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper"))
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
|
||||
rootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
|
||||
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
|
||||
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
|
||||
rootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
|
||||
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
||||
viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase"))
|
||||
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
|
||||
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
||||
viper.SetDefault("license", "apache")
|
||||
}
|
||||
|
@ -267,10 +272,7 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
if err := cmd.RootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cmd.Execute()
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -286,12 +288,13 @@ populate it with the following:
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(versionCmd)
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
|
||||
var versionCmd = &cobra.Command{
|
||||
|
@ -328,7 +331,7 @@ command it's assigned to as well as every command under that command. For
|
|||
global flags, assign a flag as a persistent flag on the root.
|
||||
|
||||
```go
|
||||
RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
|
||||
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
|
||||
```
|
||||
|
||||
### Local Flags
|
||||
|
@ -336,13 +339,13 @@ RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose out
|
|||
A flag can also be assigned locally which will only apply to that specific command.
|
||||
|
||||
```go
|
||||
RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
|
||||
rootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
|
||||
```
|
||||
|
||||
### Local Flag on Parent Commands
|
||||
|
||||
By default Cobra only parses local flags on the target command, any local flags on
|
||||
parent commands are ignored. By enabling `Command.TraverseChildren` Cobra will
|
||||
By default Cobra only parses local flags on the target command, any local flags on
|
||||
parent commands are ignored. By enabling `Command.TraverseChildren` Cobra will
|
||||
parse local flags on each command before executing the target command.
|
||||
|
||||
```go
|
||||
|
@ -359,8 +362,8 @@ You can also bind your flags with [viper](https://github.com/spf13/viper):
|
|||
var author string
|
||||
|
||||
func init() {
|
||||
RootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
|
||||
viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author"))
|
||||
rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
|
||||
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -370,6 +373,15 @@ when the `--author` flag is not provided by user.
|
|||
|
||||
More in [viper documentation](https://github.com/spf13/viper#working-with-flags).
|
||||
|
||||
### Required flags
|
||||
|
||||
Flags are optional by default. If instead you wish your command to report an error
|
||||
when a flag has not been set, mark it as required:
|
||||
```go
|
||||
rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
|
||||
rootCmd.MarkFlagRequired("region")
|
||||
```
|
||||
|
||||
## Positional and Custom Arguments
|
||||
|
||||
Validation of positional arguments can be specified using the `Args` field
|
||||
|
@ -565,6 +577,13 @@ cmd.SetUsageFunc(f func(*Command) error)
|
|||
cmd.SetUsageTemplate(s string)
|
||||
```
|
||||
|
||||
## Version Flag
|
||||
|
||||
Cobra adds a top-level '--version' flag if the Version field is set on the root command.
|
||||
Running an application with the '--version' flag will print the version to stdout using
|
||||
the version template. The template can be customized using the
|
||||
`cmd.SetVersionTemplate(s string)` function.
|
||||
|
||||
## PreRun and PostRun Hooks
|
||||
|
||||
It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order:
|
||||
|
|
|
@ -21,8 +21,8 @@ const (
|
|||
|
||||
func writePreamble(buf *bytes.Buffer, name string) {
|
||||
buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
|
||||
buf.WriteString(`
|
||||
__debug()
|
||||
buf.WriteString(fmt.Sprintf(`
|
||||
__%[1]s_debug()
|
||||
{
|
||||
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
|
||||
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
|
||||
|
@ -31,13 +31,13 @@ __debug()
|
|||
|
||||
# Homebrew on Macs have version 1.3 of bash-completion which doesn't include
|
||||
# _init_completion. This is a very minimal version of that function.
|
||||
__my_init_completion()
|
||||
__%[1]s_init_completion()
|
||||
{
|
||||
COMPREPLY=()
|
||||
_get_comp_words_by_ref "$@" cur prev words cword
|
||||
}
|
||||
|
||||
__index_of_word()
|
||||
__%[1]s_index_of_word()
|
||||
{
|
||||
local w word=$1
|
||||
shift
|
||||
|
@ -49,7 +49,7 @@ __index_of_word()
|
|||
index=-1
|
||||
}
|
||||
|
||||
__contains_word()
|
||||
__%[1]s_contains_word()
|
||||
{
|
||||
local w word=$1; shift
|
||||
for w in "$@"; do
|
||||
|
@ -58,9 +58,9 @@ __contains_word()
|
|||
return 1
|
||||
}
|
||||
|
||||
__handle_reply()
|
||||
__%[1]s_handle_reply()
|
||||
{
|
||||
__debug "${FUNCNAME[0]}"
|
||||
__%[1]s_debug "${FUNCNAME[0]}"
|
||||
case $cur in
|
||||
-*)
|
||||
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||
|
@ -85,7 +85,7 @@ __handle_reply()
|
|||
|
||||
local index flag
|
||||
flag="${cur%%=*}"
|
||||
__index_of_word "${flag}" "${flags_with_completion[@]}"
|
||||
__%[1]s_index_of_word "${flag}" "${flags_with_completion[@]}"
|
||||
COMPREPLY=()
|
||||
if [[ ${index} -ge 0 ]]; then
|
||||
PREFIX=""
|
||||
|
@ -103,7 +103,7 @@ __handle_reply()
|
|||
|
||||
# check if we are handling a flag with special work handling
|
||||
local index
|
||||
__index_of_word "${prev}" "${flags_with_completion[@]}"
|
||||
__%[1]s_index_of_word "${prev}" "${flags_with_completion[@]}"
|
||||
if [[ ${index} -ge 0 ]]; then
|
||||
${flags_completion[${index}]}
|
||||
return
|
||||
|
@ -139,21 +139,21 @@ __handle_reply()
|
|||
}
|
||||
|
||||
# The arguments should be in the form "ext1|ext2|extn"
|
||||
__handle_filename_extension_flag()
|
||||
__%[1]s_handle_filename_extension_flag()
|
||||
{
|
||||
local ext="$1"
|
||||
_filedir "@(${ext})"
|
||||
}
|
||||
|
||||
__handle_subdirs_in_dir_flag()
|
||||
__%[1]s_handle_subdirs_in_dir_flag()
|
||||
{
|
||||
local dir="$1"
|
||||
pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1
|
||||
}
|
||||
|
||||
__handle_flag()
|
||||
__%[1]s_handle_flag()
|
||||
{
|
||||
__debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||
__%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||
|
||||
# if a command required a flag, and we found it, unset must_have_one_flag()
|
||||
local flagname=${words[c]}
|
||||
|
@ -164,27 +164,30 @@ __handle_flag()
|
|||
flagname=${flagname%%=*} # strip everything after the =
|
||||
flagname="${flagname}=" # but put the = back
|
||||
fi
|
||||
__debug "${FUNCNAME[0]}: looking for ${flagname}"
|
||||
if __contains_word "${flagname}" "${must_have_one_flag[@]}"; then
|
||||
__%[1]s_debug "${FUNCNAME[0]}: looking for ${flagname}"
|
||||
if __%[1]s_contains_word "${flagname}" "${must_have_one_flag[@]}"; then
|
||||
must_have_one_flag=()
|
||||
fi
|
||||
|
||||
# if you set a flag which only applies to this command, don't show subcommands
|
||||
if __contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then
|
||||
if __%[1]s_contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then
|
||||
commands=()
|
||||
fi
|
||||
|
||||
# keep flag value with flagname as flaghash
|
||||
if [ -n "${flagvalue}" ] ; then
|
||||
flaghash[${flagname}]=${flagvalue}
|
||||
elif [ -n "${words[ $((c+1)) ]}" ] ; then
|
||||
flaghash[${flagname}]=${words[ $((c+1)) ]}
|
||||
else
|
||||
flaghash[${flagname}]="true" # pad "true" for bool flag
|
||||
# flaghash variable is an associative array which is only supported in bash > 3.
|
||||
if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then
|
||||
if [ -n "${flagvalue}" ] ; then
|
||||
flaghash[${flagname}]=${flagvalue}
|
||||
elif [ -n "${words[ $((c+1)) ]}" ] ; then
|
||||
flaghash[${flagname}]=${words[ $((c+1)) ]}
|
||||
else
|
||||
flaghash[${flagname}]="true" # pad "true" for bool flag
|
||||
fi
|
||||
fi
|
||||
|
||||
# skip the argument to a two word flag
|
||||
if __contains_word "${words[c]}" "${two_word_flags[@]}"; then
|
||||
if __%[1]s_contains_word "${words[c]}" "${two_word_flags[@]}"; then
|
||||
c=$((c+1))
|
||||
# if we are looking for a flags value, don't show commands
|
||||
if [[ $c -eq $cword ]]; then
|
||||
|
@ -196,13 +199,13 @@ __handle_flag()
|
|||
|
||||
}
|
||||
|
||||
__handle_noun()
|
||||
__%[1]s_handle_noun()
|
||||
{
|
||||
__debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||
__%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||
|
||||
if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
|
||||
if __%[1]s_contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
|
||||
must_have_one_noun=()
|
||||
elif __contains_word "${words[c]}" "${noun_aliases[@]}"; then
|
||||
elif __%[1]s_contains_word "${words[c]}" "${noun_aliases[@]}"; then
|
||||
must_have_one_noun=()
|
||||
fi
|
||||
|
||||
|
@ -210,9 +213,9 @@ __handle_noun()
|
|||
c=$((c+1))
|
||||
}
|
||||
|
||||
__handle_command()
|
||||
__%[1]s_handle_command()
|
||||
{
|
||||
__debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||
__%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||
|
||||
local next_command
|
||||
if [[ -n ${last_command} ]]; then
|
||||
|
@ -225,30 +228,30 @@ __handle_command()
|
|||
fi
|
||||
fi
|
||||
c=$((c+1))
|
||||
__debug "${FUNCNAME[0]}: looking for ${next_command}"
|
||||
__%[1]s_debug "${FUNCNAME[0]}: looking for ${next_command}"
|
||||
declare -F "$next_command" >/dev/null && $next_command
|
||||
}
|
||||
|
||||
__handle_word()
|
||||
__%[1]s_handle_word()
|
||||
{
|
||||
if [[ $c -ge $cword ]]; then
|
||||
__handle_reply
|
||||
__%[1]s_handle_reply
|
||||
return
|
||||
fi
|
||||
__debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||
__%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||
if [[ "${words[c]}" == -* ]]; then
|
||||
__handle_flag
|
||||
elif __contains_word "${words[c]}" "${commands[@]}"; then
|
||||
__handle_command
|
||||
elif [[ $c -eq 0 ]] && __contains_word "$(basename "${words[c]}")" "${commands[@]}"; then
|
||||
__handle_command
|
||||
__%[1]s_handle_flag
|
||||
elif __%[1]s_contains_word "${words[c]}" "${commands[@]}"; then
|
||||
__%[1]s_handle_command
|
||||
elif [[ $c -eq 0 ]] && __%[1]s_contains_word "$(basename "${words[c]}")" "${commands[@]}"; then
|
||||
__%[1]s_handle_command
|
||||
else
|
||||
__handle_noun
|
||||
__%[1]s_handle_noun
|
||||
fi
|
||||
__handle_word
|
||||
__%[1]s_handle_word
|
||||
}
|
||||
|
||||
`)
|
||||
`, name))
|
||||
}
|
||||
|
||||
func writePostscript(buf *bytes.Buffer, name string) {
|
||||
|
@ -260,7 +263,7 @@ func writePostscript(buf *bytes.Buffer, name string) {
|
|||
if declare -F _init_completion >/dev/null 2>&1; then
|
||||
_init_completion -s || return
|
||||
else
|
||||
__my_init_completion -n "=" || return
|
||||
__%[1]s_init_completion -n "=" || return
|
||||
fi
|
||||
|
||||
local c=0
|
||||
|
@ -269,13 +272,13 @@ func writePostscript(buf *bytes.Buffer, name string) {
|
|||
local local_nonpersistent_flags=()
|
||||
local flags_with_completion=()
|
||||
local flags_completion=()
|
||||
local commands=("%s")
|
||||
local commands=("%[1]s")
|
||||
local must_have_one_flag=()
|
||||
local must_have_one_noun=()
|
||||
local last_command
|
||||
local nouns=()
|
||||
|
||||
__handle_word
|
||||
__%[1]s_handle_word
|
||||
}
|
||||
|
||||
`, name))
|
||||
|
@ -300,7 +303,7 @@ func writeCommands(buf *bytes.Buffer, cmd *Command) {
|
|||
buf.WriteString("\n")
|
||||
}
|
||||
|
||||
func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string) {
|
||||
func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string, cmd *Command) {
|
||||
for key, value := range annotations {
|
||||
switch key {
|
||||
case BashCompFilenameExt:
|
||||
|
@ -308,7 +311,7 @@ func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]s
|
|||
|
||||
var ext string
|
||||
if len(value) > 0 {
|
||||
ext = "__handle_filename_extension_flag " + strings.Join(value, "|")
|
||||
ext = fmt.Sprintf("__%s_handle_filename_extension_flag ", cmd.Name()) + strings.Join(value, "|")
|
||||
} else {
|
||||
ext = "_filedir"
|
||||
}
|
||||
|
@ -326,7 +329,7 @@ func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]s
|
|||
|
||||
var ext string
|
||||
if len(value) == 1 {
|
||||
ext = "__handle_subdirs_in_dir_flag " + value[0]
|
||||
ext = fmt.Sprintf("__%s_handle_subdirs_in_dir_flag ", cmd.Name()) + value[0]
|
||||
} else {
|
||||
ext = "_filedir -d"
|
||||
}
|
||||
|
@ -335,7 +338,7 @@ func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]s
|
|||
}
|
||||
}
|
||||
|
||||
func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
||||
func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) {
|
||||
name := flag.Shorthand
|
||||
format := " "
|
||||
if len(flag.NoOptDefVal) == 0 {
|
||||
|
@ -343,10 +346,10 @@ func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
|||
}
|
||||
format += "flags+=(\"-%s\")\n"
|
||||
buf.WriteString(fmt.Sprintf(format, name))
|
||||
writeFlagHandler(buf, "-"+name, flag.Annotations)
|
||||
writeFlagHandler(buf, "-"+name, flag.Annotations, cmd)
|
||||
}
|
||||
|
||||
func writeFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
||||
func writeFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) {
|
||||
name := flag.Name
|
||||
format := " flags+=(\"--%s"
|
||||
if len(flag.NoOptDefVal) == 0 {
|
||||
|
@ -354,7 +357,7 @@ func writeFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
|||
}
|
||||
format += "\")\n"
|
||||
buf.WriteString(fmt.Sprintf(format, name))
|
||||
writeFlagHandler(buf, "--"+name, flag.Annotations)
|
||||
writeFlagHandler(buf, "--"+name, flag.Annotations, cmd)
|
||||
}
|
||||
|
||||
func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
||||
|
@ -380,9 +383,9 @@ func writeFlags(buf *bytes.Buffer, cmd *Command) {
|
|||
if nonCompletableFlag(flag) {
|
||||
return
|
||||
}
|
||||
writeFlag(buf, flag)
|
||||
writeFlag(buf, flag, cmd)
|
||||
if len(flag.Shorthand) > 0 {
|
||||
writeShortFlag(buf, flag)
|
||||
writeShortFlag(buf, flag, cmd)
|
||||
}
|
||||
if localNonPersistentFlags.Lookup(flag.Name) != nil {
|
||||
writeLocalNonPersistentFlag(buf, flag)
|
||||
|
@ -392,9 +395,9 @@ func writeFlags(buf *bytes.Buffer, cmd *Command) {
|
|||
if nonCompletableFlag(flag) {
|
||||
return
|
||||
}
|
||||
writeFlag(buf, flag)
|
||||
writeFlag(buf, flag, cmd)
|
||||
if len(flag.Shorthand) > 0 {
|
||||
writeShortFlag(buf, flag)
|
||||
writeShortFlag(buf, flag, cmd)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -491,17 +494,20 @@ func (c *Command) GenBashCompletionFile(filename string) error {
|
|||
return c.GenBashCompletion(outFile)
|
||||
}
|
||||
|
||||
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists.
|
||||
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists,
|
||||
// and causes your command to report an error if invoked without the flag.
|
||||
func (c *Command) MarkFlagRequired(name string) error {
|
||||
return MarkFlagRequired(c.Flags(), name)
|
||||
}
|
||||
|
||||
// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag, if it exists.
|
||||
// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag if it exists,
|
||||
// and causes your command to report an error if invoked without the flag.
|
||||
func (c *Command) MarkPersistentFlagRequired(name string) error {
|
||||
return MarkFlagRequired(c.PersistentFlags(), name)
|
||||
}
|
||||
|
||||
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists.
|
||||
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists,
|
||||
// and causes your command to report an error if invoked without the flag.
|
||||
func MarkFlagRequired(flags *pflag.FlagSet, name string) error {
|
||||
return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"})
|
||||
}
|
||||
|
|
|
@ -173,9 +173,9 @@ hello.yml test.json
|
|||
|
||||
So while there are many other files in the CWD it only shows me subdirs and those with valid extensions.
|
||||
|
||||
# Specifiy custom flag completion
|
||||
# Specify custom flag completion
|
||||
|
||||
Similar to the filename completion and filtering using cobra.BashCompFilenameExt, you can specifiy
|
||||
Similar to the filename completion and filtering using cobra.BashCompFilenameExt, you can specify
|
||||
a custom flag completion function with cobra.BashCompCustom:
|
||||
|
||||
```go
|
||||
|
|
|
@ -70,7 +70,8 @@ func AddTemplateFuncs(tmplFuncs template.FuncMap) {
|
|||
}
|
||||
}
|
||||
|
||||
// OnInitialize takes a series of func() arguments and appends them to a slice of func().
|
||||
// OnInitialize sets the passed functions to be run when each command's
|
||||
// Execute method is called.
|
||||
func OnInitialize(y ...func()) {
|
||||
initializers = append(initializers, y...)
|
||||
}
|
||||
|
|
|
@ -75,6 +75,11 @@ type Command struct {
|
|||
// group commands.
|
||||
Annotations map[string]string
|
||||
|
||||
// Version defines the version for this command. If this value is non-empty and the command does not
|
||||
// define a "version" flag, a "version" boolean flag will be added to the command and, if specified,
|
||||
// will print content of the "Version" variable.
|
||||
Version string
|
||||
|
||||
// The *Run functions are executed in the following order:
|
||||
// * PersistentPreRun()
|
||||
// * PreRun()
|
||||
|
@ -142,6 +147,11 @@ type Command struct {
|
|||
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 []string
|
||||
|
@ -177,6 +187,8 @@ type Command struct {
|
|||
// helpCommand is command with usage 'help'. If it's not defined by user,
|
||||
// cobra uses default help command.
|
||||
helpCommand *Command
|
||||
// versionTemplate is the version template defined by user.
|
||||
versionTemplate string
|
||||
}
|
||||
|
||||
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
|
||||
|
@ -222,6 +234,11 @@ func (c *Command) SetHelpTemplate(s string) {
|
|||
c.helpTemplate = s
|
||||
}
|
||||
|
||||
// SetVersionTemplate sets version template to be used. Application can use it to set custom template.
|
||||
func (c *Command) SetVersionTemplate(s string) {
|
||||
c.versionTemplate = s
|
||||
}
|
||||
|
||||
// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.
|
||||
// The user should not have a cyclic dependency on commands.
|
||||
func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
|
||||
|
@ -411,6 +428,19 @@ func (c *Command) HelpTemplate() string {
|
|||
{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
|
||||
}
|
||||
|
||||
// VersionTemplate return version template for the command.
|
||||
func (c *Command) VersionTemplate() string {
|
||||
if c.versionTemplate != "" {
|
||||
return c.versionTemplate
|
||||
}
|
||||
|
||||
if c.HasParent() {
|
||||
return c.parent.VersionTemplate()
|
||||
}
|
||||
return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}
|
||||
`
|
||||
}
|
||||
|
||||
func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
|
||||
flag := fs.Lookup(name)
|
||||
if flag == nil {
|
||||
|
@ -532,6 +562,7 @@ func (c *Command) findNext(next string) *Command {
|
|||
matches := make([]*Command, 0)
|
||||
for _, cmd := range c.commands {
|
||||
if cmd.Name() == next || cmd.HasAlias(next) {
|
||||
cmd.commandCalledAs.name = next
|
||||
return cmd
|
||||
}
|
||||
if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) {
|
||||
|
@ -542,6 +573,7 @@ func (c *Command) findNext(next string) *Command {
|
|||
if len(matches) == 1 {
|
||||
return matches[0]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -640,9 +672,10 @@ func (c *Command) execute(a []string) (err error) {
|
|||
c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated)
|
||||
}
|
||||
|
||||
// initialize help flag as the last point possible to allow for user
|
||||
// initialize help and version flag at the last point possible to allow for user
|
||||
// overriding
|
||||
c.InitDefaultHelpFlag()
|
||||
c.InitDefaultVersionFlag()
|
||||
|
||||
err = c.ParseFlags(a)
|
||||
if err != nil {
|
||||
|
@ -659,7 +692,27 @@ func (c *Command) execute(a []string) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
if helpVal || !c.Runnable() {
|
||||
if helpVal {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
// for back-compat, only add version flag behavior if version is defined
|
||||
if c.Version != "" {
|
||||
versionVal, err := c.Flags().GetBool("version")
|
||||
if err != nil {
|
||||
c.Println("\"version\" flag declared as non-bool. Please correct your code")
|
||||
return err
|
||||
}
|
||||
if versionVal {
|
||||
err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c)
|
||||
if err != nil {
|
||||
c.Println(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !c.Runnable() {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
|
@ -782,6 +835,11 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
|||
return c, err
|
||||
}
|
||||
|
||||
cmd.commandCalledAs.called = true
|
||||
if cmd.commandCalledAs.name == "" {
|
||||
cmd.commandCalledAs.name = cmd.Name()
|
||||
}
|
||||
|
||||
err = cmd.execute(flags)
|
||||
if err != nil {
|
||||
// Always show help if requested, even if SilenceErrors is in
|
||||
|
@ -848,6 +906,27 @@ func (c *Command) InitDefaultHelpFlag() {
|
|||
}
|
||||
}
|
||||
|
||||
// InitDefaultVersionFlag adds default version flag to c.
|
||||
// It is called automatically by executing the c.
|
||||
// If c already has a version flag, it will do nothing.
|
||||
// If c.Version is empty, it will do nothing.
|
||||
func (c *Command) InitDefaultVersionFlag() {
|
||||
if c.Version == "" {
|
||||
return
|
||||
}
|
||||
|
||||
c.mergePersistentFlags()
|
||||
if c.Flags().Lookup("version") == nil {
|
||||
usage := "version for "
|
||||
if c.Name() == "" {
|
||||
usage += "this command"
|
||||
} else {
|
||||
usage += c.Name()
|
||||
}
|
||||
c.Flags().Bool("version", false, usage)
|
||||
}
|
||||
}
|
||||
|
||||
// InitDefaultHelpCmd adds default help command to c.
|
||||
// It is called automatically by executing the c or by calling help and usage.
|
||||
// If c already has help command or c has no subcommands, it will do nothing.
|
||||
|
@ -1068,14 +1147,25 @@ func (c *Command) HasAlias(s string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// CalledAs returns the command name or alias that was used to invoke
|
||||
// this command or an empty string if the command has not been called.
|
||||
func (c *Command) CalledAs() string {
|
||||
if c.commandCalledAs.called {
|
||||
return c.commandCalledAs.name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// hasNameOrAliasPrefix returns true if the Name or any of aliases start
|
||||
// with prefix
|
||||
func (c *Command) hasNameOrAliasPrefix(prefix string) bool {
|
||||
if strings.HasPrefix(c.Name(), prefix) {
|
||||
c.commandCalledAs.name = c.Name()
|
||||
return true
|
||||
}
|
||||
for _, alias := range c.Aliases {
|
||||
if strings.HasPrefix(alias, prefix) {
|
||||
c.commandCalledAs.name = alias
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -1178,7 +1268,7 @@ func (c *Command) HasParent() bool {
|
|||
return c.parent != nil
|
||||
}
|
||||
|
||||
// GlobalNormalizationFunc returns the global normalization function or nil if doesn't exists.
|
||||
// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist.
|
||||
func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName {
|
||||
return c.globNormFunc
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string)
|
|||
buf.WriteString("## " + name + "\n\n")
|
||||
buf.WriteString(short + "\n\n")
|
||||
buf.WriteString("### Synopsis\n\n")
|
||||
buf.WriteString("\n" + long + "\n\n")
|
||||
buf.WriteString(long + "\n\n")
|
||||
|
||||
if cmd.Runnable() {
|
||||
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine()))
|
||||
|
@ -82,7 +82,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string)
|
|||
return err
|
||||
}
|
||||
if hasSeeAlso(cmd) {
|
||||
buf.WriteString("### SEE ALSO\n")
|
||||
buf.WriteString("### SEE ALSO\n\n")
|
||||
if cmd.HasParent() {
|
||||
parent := cmd.Parent()
|
||||
pname := parent.CommandPath()
|
||||
|
|
Loading…
Reference in New Issue