mirror of https://github.com/docker/cli.git
Bump spf13/cobra to v0.0.3, spf13/pflag to v1.0.1
Use a tagged release of Cobra Relevant changes: - spf13/cobra#567 Add `CalledAs` method to cobra.Command - spf13/cobra#580 Update error message for missing required flags - spf13/cobra#584 Add support for --version flag - spf13/cobra#614 If user has a project in symlink, just use its destination folder and work there - spf13/cobra#649 terminates the flags when -- is found in commandline - spf13/cobra#662 Add support for ignoring parse errors - spf13/cobra#686 doc: hide hidden parent flags Also various improvements were added for generating Bash completion scripts (currently not used by us) Bump spf13/pflag to v1.0.1 Relevant changes: - spf13/pflag#122 DurationSlice: implementation and tests - spf13/pflag#115 Implement BytesHex type of argument - spf13/pflag#150 Add uintSlice and boolSlice to name prettifier - spf13/pflag#155 Add multiline wrapping support - spf13/pflag#158 doc: clarify difference between string slice vs. array - spf13/pflag#160 add ability to ignore unknown flags - spf13/pflag#163 Allow Users To Show Deprecated Flags Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
824ce49aff
commit
0acb2522bd
|
@ -64,8 +64,8 @@ github.com/PuerkitoBio/urlesc 5bd2802263f21d8788851d5305584c82a5c75d7e
|
||||||
github.com/russross/blackfriday 1d6b8e9301e720b08a8938b8c25c018285885438
|
github.com/russross/blackfriday 1d6b8e9301e720b08a8938b8c25c018285885438
|
||||||
github.com/shurcooL/sanitized_anchor_name 10ef21a441db47d8b13ebcc5fd2310f636973c77
|
github.com/shurcooL/sanitized_anchor_name 10ef21a441db47d8b13ebcc5fd2310f636973c77
|
||||||
github.com/sirupsen/logrus v1.0.3
|
github.com/sirupsen/logrus v1.0.3
|
||||||
github.com/spf13/cobra 34ceca591bcf34a17a8b7bad5b3ce5f9c165bee5
|
github.com/spf13/cobra v0.0.3
|
||||||
github.com/spf13/pflag 97afa5e7ca8a08a383cb259e06636b5e2cc7897f
|
github.com/spf13/pflag v1.0.1
|
||||||
github.com/theupdateframework/notary v0.6.1
|
github.com/theupdateframework/notary v0.6.1
|
||||||
github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2
|
github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2
|
||||||
github.com/xeipuuv/gojsonpointer e0fe6f68307607d540ed8eac07a342c33fa1b54a
|
github.com/xeipuuv/gojsonpointer e0fe6f68307607d540ed8eac07a342c33fa1b54a
|
||||||
|
|
|
@ -20,6 +20,7 @@ Many of the most widely used Go projects are built using Cobra including:
|
||||||
* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
|
* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
|
||||||
* [rclone](http://rclone.org/)
|
* [rclone](http://rclone.org/)
|
||||||
* [nehm](https://github.com/bogem/nehm)
|
* [nehm](https://github.com/bogem/nehm)
|
||||||
|
* [Pouch](https://github.com/alibaba/pouch)
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra)
|
[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra)
|
||||||
[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra)
|
[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra)
|
||||||
|
@ -158,10 +159,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if err := cmd.RootCmd.Execute(); err != nil {
|
cmd.Execute()
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -174,7 +172,7 @@ commands you want. It's the easiest way to incorporate Cobra into your applicati
|
||||||
|
|
||||||
## Using the Cobra Library
|
## Using the Cobra Library
|
||||||
|
|
||||||
To manually implement Cobra you need to create a bare main.go file and a RootCmd file.
|
To manually implement Cobra you need to create a bare main.go file and a rootCmd file.
|
||||||
You will optionally provide additional commands as you see fit.
|
You will optionally provide additional commands as you see fit.
|
||||||
|
|
||||||
### Create rootCmd
|
### Create rootCmd
|
||||||
|
@ -184,7 +182,7 @@ Cobra doesn't require any special constructors. Simply create your commands.
|
||||||
Ideally you place this in app/cmd/root.go:
|
Ideally you place this in app/cmd/root.go:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
var RootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "hugo",
|
Use: "hugo",
|
||||||
Short: "Hugo is a very fast static site generator",
|
Short: "Hugo is a very fast static site generator",
|
||||||
Long: `A Fast and Flexible Static Site Generator built with
|
Long: `A Fast and Flexible Static Site Generator built with
|
||||||
|
@ -194,6 +192,13 @@ var RootCmd = &cobra.Command{
|
||||||
// Do Stuff Here
|
// Do Stuff Here
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Execute() {
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You will additionally define flags and handle configuration in your init() function.
|
You will additionally define flags and handle configuration in your init() function.
|
||||||
|
@ -212,14 +217,14 @@ import (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cobra.OnInitialize(initConfig)
|
cobra.OnInitialize(initConfig)
|
||||||
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
|
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
|
||||||
RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
|
rootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
|
||||||
RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
|
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
|
||||||
RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
|
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
|
||||||
RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
|
rootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
|
||||||
viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author"))
|
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
||||||
viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase"))
|
viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase"))
|
||||||
viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper"))
|
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
|
||||||
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
||||||
viper.SetDefault("license", "apache")
|
viper.SetDefault("license", "apache")
|
||||||
}
|
}
|
||||||
|
@ -267,10 +272,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if err := cmd.RootCmd.Execute(); err != nil {
|
cmd.Execute()
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -286,12 +288,13 @@ populate it with the following:
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RootCmd.AddCommand(versionCmd)
|
rootCmd.AddCommand(versionCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
var versionCmd = &cobra.Command{
|
var versionCmd = &cobra.Command{
|
||||||
|
@ -328,7 +331,7 @@ command it's assigned to as well as every command under that command. For
|
||||||
global flags, assign a flag as a persistent flag on the root.
|
global flags, assign a flag as a persistent flag on the root.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
|
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Local Flags
|
### Local Flags
|
||||||
|
@ -336,7 +339,7 @@ RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose out
|
||||||
A flag can also be assigned locally which will only apply to that specific command.
|
A flag can also be assigned locally which will only apply to that specific command.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
|
rootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Local Flag on Parent Commands
|
### Local Flag on Parent Commands
|
||||||
|
@ -359,8 +362,8 @@ You can also bind your flags with [viper](https://github.com/spf13/viper):
|
||||||
var author string
|
var author string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
|
rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
|
||||||
viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author"))
|
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -370,6 +373,15 @@ when the `--author` flag is not provided by user.
|
||||||
|
|
||||||
More in [viper documentation](https://github.com/spf13/viper#working-with-flags).
|
More in [viper documentation](https://github.com/spf13/viper#working-with-flags).
|
||||||
|
|
||||||
|
### Required flags
|
||||||
|
|
||||||
|
Flags are optional by default. If instead you wish your command to report an error
|
||||||
|
when a flag has not been set, mark it as required:
|
||||||
|
```go
|
||||||
|
rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
|
||||||
|
rootCmd.MarkFlagRequired("region")
|
||||||
|
```
|
||||||
|
|
||||||
## Positional and Custom Arguments
|
## Positional and Custom Arguments
|
||||||
|
|
||||||
Validation of positional arguments can be specified using the `Args` field
|
Validation of positional arguments can be specified using the `Args` field
|
||||||
|
@ -565,6 +577,13 @@ cmd.SetUsageFunc(f func(*Command) error)
|
||||||
cmd.SetUsageTemplate(s string)
|
cmd.SetUsageTemplate(s string)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Version Flag
|
||||||
|
|
||||||
|
Cobra adds a top-level '--version' flag if the Version field is set on the root command.
|
||||||
|
Running an application with the '--version' flag will print the version to stdout using
|
||||||
|
the version template. The template can be customized using the
|
||||||
|
`cmd.SetVersionTemplate(s string)` function.
|
||||||
|
|
||||||
## PreRun and PostRun Hooks
|
## PreRun and PostRun Hooks
|
||||||
|
|
||||||
It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order:
|
It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order:
|
||||||
|
|
|
@ -21,8 +21,8 @@ const (
|
||||||
|
|
||||||
func writePreamble(buf *bytes.Buffer, name string) {
|
func writePreamble(buf *bytes.Buffer, name string) {
|
||||||
buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
|
buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
|
||||||
buf.WriteString(`
|
buf.WriteString(fmt.Sprintf(`
|
||||||
__debug()
|
__%[1]s_debug()
|
||||||
{
|
{
|
||||||
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
|
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
|
||||||
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
|
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
|
||||||
|
@ -31,13 +31,13 @@ __debug()
|
||||||
|
|
||||||
# Homebrew on Macs have version 1.3 of bash-completion which doesn't include
|
# 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.
|
# _init_completion. This is a very minimal version of that function.
|
||||||
__my_init_completion()
|
__%[1]s_init_completion()
|
||||||
{
|
{
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
_get_comp_words_by_ref "$@" cur prev words cword
|
_get_comp_words_by_ref "$@" cur prev words cword
|
||||||
}
|
}
|
||||||
|
|
||||||
__index_of_word()
|
__%[1]s_index_of_word()
|
||||||
{
|
{
|
||||||
local w word=$1
|
local w word=$1
|
||||||
shift
|
shift
|
||||||
|
@ -49,7 +49,7 @@ __index_of_word()
|
||||||
index=-1
|
index=-1
|
||||||
}
|
}
|
||||||
|
|
||||||
__contains_word()
|
__%[1]s_contains_word()
|
||||||
{
|
{
|
||||||
local w word=$1; shift
|
local w word=$1; shift
|
||||||
for w in "$@"; do
|
for w in "$@"; do
|
||||||
|
@ -58,9 +58,9 @@ __contains_word()
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
__handle_reply()
|
__%[1]s_handle_reply()
|
||||||
{
|
{
|
||||||
__debug "${FUNCNAME[0]}"
|
__%[1]s_debug "${FUNCNAME[0]}"
|
||||||
case $cur in
|
case $cur in
|
||||||
-*)
|
-*)
|
||||||
if [[ $(type -t compopt) = "builtin" ]]; then
|
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
|
@ -85,7 +85,7 @@ __handle_reply()
|
||||||
|
|
||||||
local index flag
|
local index flag
|
||||||
flag="${cur%%=*}"
|
flag="${cur%%=*}"
|
||||||
__index_of_word "${flag}" "${flags_with_completion[@]}"
|
__%[1]s_index_of_word "${flag}" "${flags_with_completion[@]}"
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
if [[ ${index} -ge 0 ]]; then
|
if [[ ${index} -ge 0 ]]; then
|
||||||
PREFIX=""
|
PREFIX=""
|
||||||
|
@ -103,7 +103,7 @@ __handle_reply()
|
||||||
|
|
||||||
# check if we are handling a flag with special work handling
|
# check if we are handling a flag with special work handling
|
||||||
local index
|
local index
|
||||||
__index_of_word "${prev}" "${flags_with_completion[@]}"
|
__%[1]s_index_of_word "${prev}" "${flags_with_completion[@]}"
|
||||||
if [[ ${index} -ge 0 ]]; then
|
if [[ ${index} -ge 0 ]]; then
|
||||||
${flags_completion[${index}]}
|
${flags_completion[${index}]}
|
||||||
return
|
return
|
||||||
|
@ -136,24 +136,30 @@ __handle_reply()
|
||||||
if declare -F __ltrim_colon_completions >/dev/null; then
|
if declare -F __ltrim_colon_completions >/dev/null; then
|
||||||
__ltrim_colon_completions "$cur"
|
__ltrim_colon_completions "$cur"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# If there is only 1 completion and it is a flag with an = it will be completed
|
||||||
|
# but we don't want a space after the =
|
||||||
|
if [[ "${#COMPREPLY[@]}" -eq "1" ]] && [[ $(type -t compopt) = "builtin" ]] && [[ "${COMPREPLY[0]}" == --*= ]]; then
|
||||||
|
compopt -o nospace
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# The arguments should be in the form "ext1|ext2|extn"
|
# The arguments should be in the form "ext1|ext2|extn"
|
||||||
__handle_filename_extension_flag()
|
__%[1]s_handle_filename_extension_flag()
|
||||||
{
|
{
|
||||||
local ext="$1"
|
local ext="$1"
|
||||||
_filedir "@(${ext})"
|
_filedir "@(${ext})"
|
||||||
}
|
}
|
||||||
|
|
||||||
__handle_subdirs_in_dir_flag()
|
__%[1]s_handle_subdirs_in_dir_flag()
|
||||||
{
|
{
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&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()
|
# if a command required a flag, and we found it, unset must_have_one_flag()
|
||||||
local flagname=${words[c]}
|
local flagname=${words[c]}
|
||||||
|
@ -164,17 +170,19 @@ __handle_flag()
|
||||||
flagname=${flagname%%=*} # strip everything after the =
|
flagname=${flagname%%=*} # strip everything after the =
|
||||||
flagname="${flagname}=" # but put the = back
|
flagname="${flagname}=" # but put the = back
|
||||||
fi
|
fi
|
||||||
__debug "${FUNCNAME[0]}: looking for ${flagname}"
|
__%[1]s_debug "${FUNCNAME[0]}: looking for ${flagname}"
|
||||||
if __contains_word "${flagname}" "${must_have_one_flag[@]}"; then
|
if __%[1]s_contains_word "${flagname}" "${must_have_one_flag[@]}"; then
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# if you set a flag which only applies to this command, don't show subcommands
|
# 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=()
|
commands=()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# keep flag value with flagname as flaghash
|
# keep flag value with flagname as flaghash
|
||||||
|
# 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
|
if [ -n "${flagvalue}" ] ; then
|
||||||
flaghash[${flagname}]=${flagvalue}
|
flaghash[${flagname}]=${flagvalue}
|
||||||
elif [ -n "${words[ $((c+1)) ]}" ] ; then
|
elif [ -n "${words[ $((c+1)) ]}" ] ; then
|
||||||
|
@ -182,9 +190,10 @@ __handle_flag()
|
||||||
else
|
else
|
||||||
flaghash[${flagname}]="true" # pad "true" for bool flag
|
flaghash[${flagname}]="true" # pad "true" for bool flag
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# skip the argument to a two word flag
|
# 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))
|
c=$((c+1))
|
||||||
# if we are looking for a flags value, don't show commands
|
# if we are looking for a flags value, don't show commands
|
||||||
if [[ $c -eq $cword ]]; then
|
if [[ $c -eq $cword ]]; then
|
||||||
|
@ -196,13 +205,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=()
|
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=()
|
must_have_one_noun=()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -210,45 +219,53 @@ __handle_noun()
|
||||||
c=$((c+1))
|
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
|
local next_command
|
||||||
if [[ -n ${last_command} ]]; then
|
if [[ -n ${last_command} ]]; then
|
||||||
next_command="_${last_command}_${words[c]//:/__}"
|
next_command="_${last_command}_${words[c]//:/__}"
|
||||||
else
|
else
|
||||||
if [[ $c -eq 0 ]]; then
|
if [[ $c -eq 0 ]]; then
|
||||||
next_command="_$(basename "${words[c]//:/__}")"
|
next_command="_%[1]s_root_command"
|
||||||
else
|
else
|
||||||
next_command="_${words[c]//:/__}"
|
next_command="_${words[c]//:/__}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
c=$((c+1))
|
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
|
declare -F "$next_command" >/dev/null && $next_command
|
||||||
}
|
}
|
||||||
|
|
||||||
__handle_word()
|
__%[1]s_handle_word()
|
||||||
{
|
{
|
||||||
if [[ $c -ge $cword ]]; then
|
if [[ $c -ge $cword ]]; then
|
||||||
__handle_reply
|
__%[1]s_handle_reply
|
||||||
return
|
return
|
||||||
fi
|
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
|
if [[ "${words[c]}" == -* ]]; then
|
||||||
__handle_flag
|
__%[1]s_handle_flag
|
||||||
elif __contains_word "${words[c]}" "${commands[@]}"; then
|
elif __%[1]s_contains_word "${words[c]}" "${commands[@]}"; then
|
||||||
__handle_command
|
__%[1]s_handle_command
|
||||||
elif [[ $c -eq 0 ]] && __contains_word "$(basename "${words[c]}")" "${commands[@]}"; then
|
elif [[ $c -eq 0 ]]; then
|
||||||
__handle_command
|
__%[1]s_handle_command
|
||||||
|
elif __%[1]s_contains_word "${words[c]}" "${command_aliases[@]}"; then
|
||||||
|
# aliashash variable is an associative array which is only supported in bash > 3.
|
||||||
|
if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then
|
||||||
|
words[c]=${aliashash[${words[c]}]}
|
||||||
|
__%[1]s_handle_command
|
||||||
else
|
else
|
||||||
__handle_noun
|
__%[1]s_handle_noun
|
||||||
fi
|
fi
|
||||||
__handle_word
|
else
|
||||||
|
__%[1]s_handle_noun
|
||||||
|
fi
|
||||||
|
__%[1]s_handle_word
|
||||||
}
|
}
|
||||||
|
|
||||||
`)
|
`, name))
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePostscript(buf *bytes.Buffer, name string) {
|
func writePostscript(buf *bytes.Buffer, name string) {
|
||||||
|
@ -257,10 +274,11 @@ func writePostscript(buf *bytes.Buffer, name string) {
|
||||||
buf.WriteString(fmt.Sprintf(`{
|
buf.WriteString(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 || :
|
||||||
if declare -F _init_completion >/dev/null 2>&1; then
|
if declare -F _init_completion >/dev/null 2>&1; then
|
||||||
_init_completion -s || return
|
_init_completion -s || return
|
||||||
else
|
else
|
||||||
__my_init_completion -n "=" || return
|
__%[1]s_init_completion -n "=" || return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local c=0
|
local c=0
|
||||||
|
@ -269,13 +287,13 @@ func writePostscript(buf *bytes.Buffer, name string) {
|
||||||
local local_nonpersistent_flags=()
|
local local_nonpersistent_flags=()
|
||||||
local flags_with_completion=()
|
local flags_with_completion=()
|
||||||
local flags_completion=()
|
local flags_completion=()
|
||||||
local commands=("%s")
|
local commands=("%[1]s")
|
||||||
local must_have_one_flag=()
|
local must_have_one_flag=()
|
||||||
local must_have_one_noun=()
|
local must_have_one_noun=()
|
||||||
local last_command
|
local last_command
|
||||||
local nouns=()
|
local nouns=()
|
||||||
|
|
||||||
__handle_word
|
__%[1]s_handle_word
|
||||||
}
|
}
|
||||||
|
|
||||||
`, name))
|
`, name))
|
||||||
|
@ -296,11 +314,12 @@ func writeCommands(buf *bytes.Buffer, cmd *Command) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name()))
|
buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name()))
|
||||||
|
writeCmdAliases(buf, c)
|
||||||
}
|
}
|
||||||
buf.WriteString("\n")
|
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 {
|
for key, value := range annotations {
|
||||||
switch key {
|
switch key {
|
||||||
case BashCompFilenameExt:
|
case BashCompFilenameExt:
|
||||||
|
@ -308,7 +327,7 @@ func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]s
|
||||||
|
|
||||||
var ext string
|
var ext string
|
||||||
if len(value) > 0 {
|
if len(value) > 0 {
|
||||||
ext = "__handle_filename_extension_flag " + strings.Join(value, "|")
|
ext = fmt.Sprintf("__%s_handle_filename_extension_flag ", cmd.Root().Name()) + strings.Join(value, "|")
|
||||||
} else {
|
} else {
|
||||||
ext = "_filedir"
|
ext = "_filedir"
|
||||||
}
|
}
|
||||||
|
@ -326,7 +345,7 @@ func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]s
|
||||||
|
|
||||||
var ext string
|
var ext string
|
||||||
if len(value) == 1 {
|
if len(value) == 1 {
|
||||||
ext = "__handle_subdirs_in_dir_flag " + value[0]
|
ext = fmt.Sprintf("__%s_handle_subdirs_in_dir_flag ", cmd.Root().Name()) + value[0]
|
||||||
} else {
|
} else {
|
||||||
ext = "_filedir -d"
|
ext = "_filedir -d"
|
||||||
}
|
}
|
||||||
|
@ -335,7 +354,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
|
name := flag.Shorthand
|
||||||
format := " "
|
format := " "
|
||||||
if len(flag.NoOptDefVal) == 0 {
|
if len(flag.NoOptDefVal) == 0 {
|
||||||
|
@ -343,10 +362,10 @@ func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
||||||
}
|
}
|
||||||
format += "flags+=(\"-%s\")\n"
|
format += "flags+=(\"-%s\")\n"
|
||||||
buf.WriteString(fmt.Sprintf(format, name))
|
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
|
name := flag.Name
|
||||||
format := " flags+=(\"--%s"
|
format := " flags+=(\"--%s"
|
||||||
if len(flag.NoOptDefVal) == 0 {
|
if len(flag.NoOptDefVal) == 0 {
|
||||||
|
@ -354,7 +373,7 @@ func writeFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
||||||
}
|
}
|
||||||
format += "\")\n"
|
format += "\")\n"
|
||||||
buf.WriteString(fmt.Sprintf(format, name))
|
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) {
|
func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
||||||
|
@ -380,9 +399,9 @@ func writeFlags(buf *bytes.Buffer, cmd *Command) {
|
||||||
if nonCompletableFlag(flag) {
|
if nonCompletableFlag(flag) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeFlag(buf, flag)
|
writeFlag(buf, flag, cmd)
|
||||||
if len(flag.Shorthand) > 0 {
|
if len(flag.Shorthand) > 0 {
|
||||||
writeShortFlag(buf, flag)
|
writeShortFlag(buf, flag, cmd)
|
||||||
}
|
}
|
||||||
if localNonPersistentFlags.Lookup(flag.Name) != nil {
|
if localNonPersistentFlags.Lookup(flag.Name) != nil {
|
||||||
writeLocalNonPersistentFlag(buf, flag)
|
writeLocalNonPersistentFlag(buf, flag)
|
||||||
|
@ -392,9 +411,9 @@ func writeFlags(buf *bytes.Buffer, cmd *Command) {
|
||||||
if nonCompletableFlag(flag) {
|
if nonCompletableFlag(flag) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeFlag(buf, flag)
|
writeFlag(buf, flag, cmd)
|
||||||
if len(flag.Shorthand) > 0 {
|
if len(flag.Shorthand) > 0 {
|
||||||
writeShortFlag(buf, flag)
|
writeShortFlag(buf, flag, cmd)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -434,6 +453,21 @@ func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeCmdAliases(buf *bytes.Buffer, cmd *Command) {
|
||||||
|
if len(cmd.Aliases) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(sort.StringSlice(cmd.Aliases))
|
||||||
|
|
||||||
|
buf.WriteString(fmt.Sprint(` if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then`, "\n"))
|
||||||
|
for _, value := range cmd.Aliases {
|
||||||
|
buf.WriteString(fmt.Sprintf(" command_aliases+=(%q)\n", value))
|
||||||
|
buf.WriteString(fmt.Sprintf(" aliashash[%q]=%q\n", value, cmd.Name()))
|
||||||
|
}
|
||||||
|
buf.WriteString(` fi`)
|
||||||
|
buf.WriteString("\n")
|
||||||
|
}
|
||||||
func writeArgAliases(buf *bytes.Buffer, cmd *Command) {
|
func writeArgAliases(buf *bytes.Buffer, cmd *Command) {
|
||||||
buf.WriteString(" noun_aliases=()\n")
|
buf.WriteString(" noun_aliases=()\n")
|
||||||
sort.Sort(sort.StringSlice(cmd.ArgAliases))
|
sort.Sort(sort.StringSlice(cmd.ArgAliases))
|
||||||
|
@ -452,8 +486,18 @@ func gen(buf *bytes.Buffer, cmd *Command) {
|
||||||
commandName := cmd.CommandPath()
|
commandName := cmd.CommandPath()
|
||||||
commandName = strings.Replace(commandName, " ", "_", -1)
|
commandName = strings.Replace(commandName, " ", "_", -1)
|
||||||
commandName = strings.Replace(commandName, ":", "__", -1)
|
commandName = strings.Replace(commandName, ":", "__", -1)
|
||||||
|
|
||||||
|
if cmd.Root() == cmd {
|
||||||
|
buf.WriteString(fmt.Sprintf("_%s_root_command()\n{\n", commandName))
|
||||||
|
} else {
|
||||||
buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName))
|
buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName))
|
||||||
|
}
|
||||||
|
|
||||||
buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName))
|
buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName))
|
||||||
|
buf.WriteString("\n")
|
||||||
|
buf.WriteString(" command_aliases=()\n")
|
||||||
|
buf.WriteString("\n")
|
||||||
|
|
||||||
writeCommands(buf, cmd)
|
writeCommands(buf, cmd)
|
||||||
writeFlags(buf, cmd)
|
writeFlags(buf, cmd)
|
||||||
writeRequiredFlag(buf, cmd)
|
writeRequiredFlag(buf, cmd)
|
||||||
|
@ -491,17 +535,20 @@ func (c *Command) GenBashCompletionFile(filename string) error {
|
||||||
return c.GenBashCompletion(outFile)
|
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 {
|
func (c *Command) MarkFlagRequired(name string) error {
|
||||||
return MarkFlagRequired(c.Flags(), name)
|
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 {
|
func (c *Command) MarkPersistentFlagRequired(name string) error {
|
||||||
return MarkFlagRequired(c.PersistentFlags(), name)
|
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 {
|
func MarkFlagRequired(flags *pflag.FlagSet, name string) error {
|
||||||
return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"})
|
return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"})
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,8 @@ func AddTemplateFuncs(tmplFuncs template.FuncMap) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnInitialize takes a series of func() arguments and appends them to a slice of func().
|
// OnInitialize sets the passed functions to be run when each command's
|
||||||
|
// Execute method is called.
|
||||||
func OnInitialize(y ...func()) {
|
func OnInitialize(y ...func()) {
|
||||||
initializers = append(initializers, y...)
|
initializers = append(initializers, y...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,9 @@ import (
|
||||||
flag "github.com/spf13/pflag"
|
flag "github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FParseErrWhitelist configures Flag parse errors to be ignored
|
||||||
|
type FParseErrWhitelist flag.ParseErrorsWhitelist
|
||||||
|
|
||||||
// Command is just that, a command for your application.
|
// Command is just that, a command for your application.
|
||||||
// E.g. 'go run ...' - 'run' is the command. Cobra requires
|
// E.g. 'go run ...' - 'run' is the command. Cobra requires
|
||||||
// you to define the usage and description as part of your command
|
// you to define the usage and description as part of your command
|
||||||
|
@ -75,6 +78,11 @@ type Command struct {
|
||||||
// group commands.
|
// group commands.
|
||||||
Annotations map[string]string
|
Annotations map[string]string
|
||||||
|
|
||||||
|
// Version defines the version for this command. If this value is non-empty and the command does not
|
||||||
|
// define a "version" flag, a "version" boolean flag will be added to the command and, if specified,
|
||||||
|
// will print content of the "Version" variable.
|
||||||
|
Version string
|
||||||
|
|
||||||
// The *Run functions are executed in the following order:
|
// The *Run functions are executed in the following order:
|
||||||
// * PersistentPreRun()
|
// * PersistentPreRun()
|
||||||
// * PreRun()
|
// * PreRun()
|
||||||
|
@ -132,6 +140,9 @@ type Command struct {
|
||||||
// TraverseChildren parses flags on all parents before executing child command.
|
// TraverseChildren parses flags on all parents before executing child command.
|
||||||
TraverseChildren bool
|
TraverseChildren bool
|
||||||
|
|
||||||
|
//FParseErrWhitelist flag parse errors to be ignored
|
||||||
|
FParseErrWhitelist FParseErrWhitelist
|
||||||
|
|
||||||
// commands is the list of commands supported by this program.
|
// commands is the list of commands supported by this program.
|
||||||
commands []*Command
|
commands []*Command
|
||||||
// parent is a parent command for this command.
|
// parent is a parent command for this command.
|
||||||
|
@ -142,6 +153,11 @@ type Command struct {
|
||||||
commandsMaxNameLen int
|
commandsMaxNameLen int
|
||||||
// commandsAreSorted defines, if command slice are sorted or not.
|
// commandsAreSorted defines, if command slice are sorted or not.
|
||||||
commandsAreSorted bool
|
commandsAreSorted bool
|
||||||
|
// commandCalledAs is the name or alias value used to call this command.
|
||||||
|
commandCalledAs struct {
|
||||||
|
name string
|
||||||
|
called bool
|
||||||
|
}
|
||||||
|
|
||||||
// args is actual args parsed from flags.
|
// args is actual args parsed from flags.
|
||||||
args []string
|
args []string
|
||||||
|
@ -177,6 +193,8 @@ type Command struct {
|
||||||
// helpCommand is command with usage 'help'. If it's not defined by user,
|
// helpCommand is command with usage 'help'. If it's not defined by user,
|
||||||
// cobra uses default help command.
|
// cobra uses default help command.
|
||||||
helpCommand *Command
|
helpCommand *Command
|
||||||
|
// versionTemplate is the version template defined by user.
|
||||||
|
versionTemplate string
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
|
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
|
||||||
|
@ -222,6 +240,11 @@ func (c *Command) SetHelpTemplate(s string) {
|
||||||
c.helpTemplate = s
|
c.helpTemplate = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetVersionTemplate sets version template to be used. Application can use it to set custom template.
|
||||||
|
func (c *Command) SetVersionTemplate(s string) {
|
||||||
|
c.versionTemplate = s
|
||||||
|
}
|
||||||
|
|
||||||
// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.
|
// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.
|
||||||
// The user should not have a cyclic dependency on commands.
|
// The user should not have a cyclic dependency on commands.
|
||||||
func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
|
func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
|
||||||
|
@ -411,6 +434,19 @@ func (c *Command) HelpTemplate() string {
|
||||||
{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
|
{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VersionTemplate return version template for the command.
|
||||||
|
func (c *Command) VersionTemplate() string {
|
||||||
|
if c.versionTemplate != "" {
|
||||||
|
return c.versionTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.HasParent() {
|
||||||
|
return c.parent.VersionTemplate()
|
||||||
|
}
|
||||||
|
return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
|
func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
|
||||||
flag := fs.Lookup(name)
|
flag := fs.Lookup(name)
|
||||||
if flag == nil {
|
if flag == nil {
|
||||||
|
@ -445,6 +481,9 @@ Loop:
|
||||||
s := args[0]
|
s := args[0]
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
switch {
|
switch {
|
||||||
|
case s == "--":
|
||||||
|
// "--" terminates the flags
|
||||||
|
break Loop
|
||||||
case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
|
case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
|
||||||
// If '--flag arg' then
|
// If '--flag arg' then
|
||||||
// delete arg from args.
|
// delete arg from args.
|
||||||
|
@ -532,6 +571,7 @@ func (c *Command) findNext(next string) *Command {
|
||||||
matches := make([]*Command, 0)
|
matches := make([]*Command, 0)
|
||||||
for _, cmd := range c.commands {
|
for _, cmd := range c.commands {
|
||||||
if cmd.Name() == next || cmd.HasAlias(next) {
|
if cmd.Name() == next || cmd.HasAlias(next) {
|
||||||
|
cmd.commandCalledAs.name = next
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) {
|
if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) {
|
||||||
|
@ -542,6 +582,7 @@ func (c *Command) findNext(next string) *Command {
|
||||||
if len(matches) == 1 {
|
if len(matches) == 1 {
|
||||||
return matches[0]
|
return matches[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,9 +681,10 @@ func (c *Command) execute(a []string) (err error) {
|
||||||
c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated)
|
c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize help flag as the last point possible to allow for user
|
// initialize help and version flag at the last point possible to allow for user
|
||||||
// overriding
|
// overriding
|
||||||
c.InitDefaultHelpFlag()
|
c.InitDefaultHelpFlag()
|
||||||
|
c.InitDefaultVersionFlag()
|
||||||
|
|
||||||
err = c.ParseFlags(a)
|
err = c.ParseFlags(a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -659,7 +701,27 @@ func (c *Command) execute(a []string) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if helpVal || !c.Runnable() {
|
if helpVal {
|
||||||
|
return flag.ErrHelp
|
||||||
|
}
|
||||||
|
|
||||||
|
// for back-compat, only add version flag behavior if version is defined
|
||||||
|
if c.Version != "" {
|
||||||
|
versionVal, err := c.Flags().GetBool("version")
|
||||||
|
if err != nil {
|
||||||
|
c.Println("\"version\" flag declared as non-bool. Please correct your code")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if versionVal {
|
||||||
|
err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c)
|
||||||
|
if err != nil {
|
||||||
|
c.Println(err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.Runnable() {
|
||||||
return flag.ErrHelp
|
return flag.ErrHelp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,6 +844,11 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd.commandCalledAs.called = true
|
||||||
|
if cmd.commandCalledAs.name == "" {
|
||||||
|
cmd.commandCalledAs.name = cmd.Name()
|
||||||
|
}
|
||||||
|
|
||||||
err = cmd.execute(flags)
|
err = cmd.execute(flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Always show help if requested, even if SilenceErrors is in
|
// Always show help if requested, even if SilenceErrors is in
|
||||||
|
@ -827,7 +894,7 @@ func (c *Command) validateRequiredFlags() error {
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(missingFlagNames) > 0 {
|
if len(missingFlagNames) > 0 {
|
||||||
return fmt.Errorf(`Required flag(s) "%s" have/has not been set`, strings.Join(missingFlagNames, `", "`))
|
return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -848,6 +915,27 @@ func (c *Command) InitDefaultHelpFlag() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InitDefaultVersionFlag adds default version flag to c.
|
||||||
|
// It is called automatically by executing the c.
|
||||||
|
// If c already has a version flag, it will do nothing.
|
||||||
|
// If c.Version is empty, it will do nothing.
|
||||||
|
func (c *Command) InitDefaultVersionFlag() {
|
||||||
|
if c.Version == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.mergePersistentFlags()
|
||||||
|
if c.Flags().Lookup("version") == nil {
|
||||||
|
usage := "version for "
|
||||||
|
if c.Name() == "" {
|
||||||
|
usage += "this command"
|
||||||
|
} else {
|
||||||
|
usage += c.Name()
|
||||||
|
}
|
||||||
|
c.Flags().Bool("version", false, usage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// InitDefaultHelpCmd adds default help command to c.
|
// InitDefaultHelpCmd adds default help command to c.
|
||||||
// It is called automatically by executing the c or by calling help and usage.
|
// It is called automatically by executing the c or by calling help and usage.
|
||||||
// If c already has help command or c has no subcommands, it will do nothing.
|
// If c already has help command or c has no subcommands, it will do nothing.
|
||||||
|
@ -1068,14 +1156,25 @@ func (c *Command) HasAlias(s string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CalledAs returns the command name or alias that was used to invoke
|
||||||
|
// this command or an empty string if the command has not been called.
|
||||||
|
func (c *Command) CalledAs() string {
|
||||||
|
if c.commandCalledAs.called {
|
||||||
|
return c.commandCalledAs.name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// hasNameOrAliasPrefix returns true if the Name or any of aliases start
|
// hasNameOrAliasPrefix returns true if the Name or any of aliases start
|
||||||
// with prefix
|
// with prefix
|
||||||
func (c *Command) hasNameOrAliasPrefix(prefix string) bool {
|
func (c *Command) hasNameOrAliasPrefix(prefix string) bool {
|
||||||
if strings.HasPrefix(c.Name(), prefix) {
|
if strings.HasPrefix(c.Name(), prefix) {
|
||||||
|
c.commandCalledAs.name = c.Name()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
for _, alias := range c.Aliases {
|
for _, alias := range c.Aliases {
|
||||||
if strings.HasPrefix(alias, prefix) {
|
if strings.HasPrefix(alias, prefix) {
|
||||||
|
c.commandCalledAs.name = alias
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1178,7 +1277,7 @@ func (c *Command) HasParent() bool {
|
||||||
return c.parent != nil
|
return c.parent != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GlobalNormalizationFunc returns the global normalization function or nil if doesn't exists.
|
// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist.
|
||||||
func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName {
|
func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName {
|
||||||
return c.globNormFunc
|
return c.globNormFunc
|
||||||
}
|
}
|
||||||
|
@ -1370,6 +1469,10 @@ func (c *Command) ParseFlags(args []string) error {
|
||||||
}
|
}
|
||||||
beforeErrorBufLen := c.flagErrorBuf.Len()
|
beforeErrorBufLen := c.flagErrorBuf.Len()
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
|
|
||||||
|
//do it here after merging all flags and just before parse
|
||||||
|
c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
|
||||||
|
|
||||||
err := c.Flags().Parse(args)
|
err := c.Flags().Parse(args)
|
||||||
// Print warnings if they occurred (e.g. deprecated flag messages).
|
// Print warnings if they occurred (e.g. deprecated flag messages).
|
||||||
if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil {
|
if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil {
|
||||||
|
|
|
@ -176,13 +176,13 @@ func manPrintFlags(buf *bytes.Buffer, flags *pflag.FlagSet) {
|
||||||
|
|
||||||
func manPrintOptions(buf *bytes.Buffer, command *cobra.Command) {
|
func manPrintOptions(buf *bytes.Buffer, command *cobra.Command) {
|
||||||
flags := command.NonInheritedFlags()
|
flags := command.NonInheritedFlags()
|
||||||
if flags.HasFlags() {
|
if flags.HasAvailableFlags() {
|
||||||
buf.WriteString("# OPTIONS\n")
|
buf.WriteString("# OPTIONS\n")
|
||||||
manPrintFlags(buf, flags)
|
manPrintFlags(buf, flags)
|
||||||
buf.WriteString("\n")
|
buf.WriteString("\n")
|
||||||
}
|
}
|
||||||
flags = command.InheritedFlags()
|
flags = command.InheritedFlags()
|
||||||
if flags.HasFlags() {
|
if flags.HasAvailableFlags() {
|
||||||
buf.WriteString("# OPTIONS INHERITED FROM PARENT COMMANDS\n")
|
buf.WriteString("# OPTIONS INHERITED FROM PARENT COMMANDS\n")
|
||||||
manPrintFlags(buf, flags)
|
manPrintFlags(buf, flags)
|
||||||
buf.WriteString("\n")
|
buf.WriteString("\n")
|
||||||
|
|
|
@ -29,7 +29,7 @@ import (
|
||||||
func printOptions(buf *bytes.Buffer, cmd *cobra.Command, name string) error {
|
func printOptions(buf *bytes.Buffer, cmd *cobra.Command, name string) error {
|
||||||
flags := cmd.NonInheritedFlags()
|
flags := cmd.NonInheritedFlags()
|
||||||
flags.SetOutput(buf)
|
flags.SetOutput(buf)
|
||||||
if flags.HasFlags() {
|
if flags.HasAvailableFlags() {
|
||||||
buf.WriteString("### Options\n\n```\n")
|
buf.WriteString("### Options\n\n```\n")
|
||||||
flags.PrintDefaults()
|
flags.PrintDefaults()
|
||||||
buf.WriteString("```\n\n")
|
buf.WriteString("```\n\n")
|
||||||
|
@ -37,7 +37,7 @@ func printOptions(buf *bytes.Buffer, cmd *cobra.Command, name string) error {
|
||||||
|
|
||||||
parentFlags := cmd.InheritedFlags()
|
parentFlags := cmd.InheritedFlags()
|
||||||
parentFlags.SetOutput(buf)
|
parentFlags.SetOutput(buf)
|
||||||
if parentFlags.HasFlags() {
|
if parentFlags.HasAvailableFlags() {
|
||||||
buf.WriteString("### Options inherited from parent commands\n\n```\n")
|
buf.WriteString("### Options inherited from parent commands\n\n```\n")
|
||||||
parentFlags.PrintDefaults()
|
parentFlags.PrintDefaults()
|
||||||
buf.WriteString("```\n\n")
|
buf.WriteString("```\n\n")
|
||||||
|
@ -67,7 +67,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string)
|
||||||
buf.WriteString("## " + name + "\n\n")
|
buf.WriteString("## " + name + "\n\n")
|
||||||
buf.WriteString(short + "\n\n")
|
buf.WriteString(short + "\n\n")
|
||||||
buf.WriteString("### Synopsis\n\n")
|
buf.WriteString("### Synopsis\n\n")
|
||||||
buf.WriteString("\n" + long + "\n\n")
|
buf.WriteString(long + "\n\n")
|
||||||
|
|
||||||
if cmd.Runnable() {
|
if cmd.Runnable() {
|
||||||
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine()))
|
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine()))
|
||||||
|
@ -82,7 +82,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if hasSeeAlso(cmd) {
|
if hasSeeAlso(cmd) {
|
||||||
buf.WriteString("### SEE ALSO\n")
|
buf.WriteString("### SEE ALSO\n\n")
|
||||||
if cmd.HasParent() {
|
if cmd.HasParent() {
|
||||||
parent := cmd.Parent()
|
parent := cmd.Parent()
|
||||||
pname := parent.CommandPath()
|
pname := parent.CommandPath()
|
||||||
|
|
|
@ -29,7 +29,7 @@ import (
|
||||||
func printOptionsReST(buf *bytes.Buffer, cmd *cobra.Command, name string) error {
|
func printOptionsReST(buf *bytes.Buffer, cmd *cobra.Command, name string) error {
|
||||||
flags := cmd.NonInheritedFlags()
|
flags := cmd.NonInheritedFlags()
|
||||||
flags.SetOutput(buf)
|
flags.SetOutput(buf)
|
||||||
if flags.HasFlags() {
|
if flags.HasAvailableFlags() {
|
||||||
buf.WriteString("Options\n")
|
buf.WriteString("Options\n")
|
||||||
buf.WriteString("~~~~~~~\n\n::\n\n")
|
buf.WriteString("~~~~~~~\n\n::\n\n")
|
||||||
flags.PrintDefaults()
|
flags.PrintDefaults()
|
||||||
|
@ -38,7 +38,7 @@ func printOptionsReST(buf *bytes.Buffer, cmd *cobra.Command, name string) error
|
||||||
|
|
||||||
parentFlags := cmd.InheritedFlags()
|
parentFlags := cmd.InheritedFlags()
|
||||||
parentFlags.SetOutput(buf)
|
parentFlags.SetOutput(buf)
|
||||||
if parentFlags.HasFlags() {
|
if parentFlags.HasAvailableFlags() {
|
||||||
buf.WriteString("Options inherited from parent commands\n")
|
buf.WriteString("Options inherited from parent commands\n")
|
||||||
buf.WriteString("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n")
|
buf.WriteString("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n")
|
||||||
parentFlags.PrintDefaults()
|
parentFlags.PrintDefaults()
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BytesHex adapts []byte for use as a flag. Value of flag is HEX encoded
|
||||||
|
type bytesHexValue []byte
|
||||||
|
|
||||||
|
func (bytesHex bytesHexValue) String() string {
|
||||||
|
return fmt.Sprintf("%X", []byte(bytesHex))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bytesHex *bytesHexValue) Set(value string) error {
|
||||||
|
bin, err := hex.DecodeString(strings.TrimSpace(value))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*bytesHex = bin
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*bytesHexValue) Type() string {
|
||||||
|
return "bytesHex"
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBytesHexValue(val []byte, p *[]byte) *bytesHexValue {
|
||||||
|
*p = val
|
||||||
|
return (*bytesHexValue)(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bytesHexConv(sval string) (interface{}, error) {
|
||||||
|
|
||||||
|
bin, err := hex.DecodeString(sval)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return bin, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBytesHex return the []byte value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetBytesHex(name string) ([]byte, error) {
|
||||||
|
val, err := f.getFlagType(name, "bytesHex", bytesHexConv)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return val.([]byte), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesHexVar defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to an []byte variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) BytesHexVar(p *[]byte, name string, value []byte, usage string) {
|
||||||
|
f.VarP(newBytesHexValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesHexVarP is like BytesHexVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) BytesHexVarP(p *[]byte, name, shorthand string, value []byte, usage string) {
|
||||||
|
f.VarP(newBytesHexValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesHexVar defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to an []byte variable in which to store the value of the flag.
|
||||||
|
func BytesHexVar(p *[]byte, name string, value []byte, usage string) {
|
||||||
|
CommandLine.VarP(newBytesHexValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesHexVarP is like BytesHexVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func BytesHexVarP(p *[]byte, name, shorthand string, value []byte, usage string) {
|
||||||
|
CommandLine.VarP(newBytesHexValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesHex defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of an []byte variable that stores the value of the flag.
|
||||||
|
func (f *FlagSet) BytesHex(name string, value []byte, usage string) *[]byte {
|
||||||
|
p := new([]byte)
|
||||||
|
f.BytesHexVarP(p, name, "", value, usage)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesHexP is like BytesHex, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
|
||||||
|
p := new([]byte)
|
||||||
|
f.BytesHexVarP(p, name, shorthand, value, usage)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesHex defines an []byte flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of an []byte variable that stores the value of the flag.
|
||||||
|
func BytesHex(name string, value []byte, usage string) *[]byte {
|
||||||
|
return CommandLine.BytesHexP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesHexP is like BytesHex, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
|
||||||
|
return CommandLine.BytesHexP(name, shorthand, value, usage)
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- durationSlice Value
|
||||||
|
type durationSliceValue struct {
|
||||||
|
value *[]time.Duration
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDurationSliceValue(val []time.Duration, p *[]time.Duration) *durationSliceValue {
|
||||||
|
dsv := new(durationSliceValue)
|
||||||
|
dsv.value = p
|
||||||
|
*dsv.value = val
|
||||||
|
return dsv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *durationSliceValue) Set(val string) error {
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]time.Duration, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
var err error
|
||||||
|
out[i], err = time.ParseDuration(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *durationSliceValue) Type() string {
|
||||||
|
return "durationSlice"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *durationSliceValue) String() string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = fmt.Sprintf("%s", d)
|
||||||
|
}
|
||||||
|
return "[" + strings.Join(out, ",") + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func durationSliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []time.Duration{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]time.Duration, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
var err error
|
||||||
|
out[i], err = time.ParseDuration(d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDurationSlice returns the []time.Duration value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetDurationSlice(name string) ([]time.Duration, error) {
|
||||||
|
val, err := f.getFlagType(name, "durationSlice", durationSliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []time.Duration{}, err
|
||||||
|
}
|
||||||
|
return val.([]time.Duration), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationSliceVar defines a durationSlice flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []time.Duration variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) DurationSliceVar(p *[]time.Duration, name string, value []time.Duration, usage string) {
|
||||||
|
f.VarP(newDurationSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationSliceVarP is like DurationSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) DurationSliceVarP(p *[]time.Duration, name, shorthand string, value []time.Duration, usage string) {
|
||||||
|
f.VarP(newDurationSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationSliceVar defines a duration[] flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a duration[] variable in which to store the value of the flag.
|
||||||
|
func DurationSliceVar(p *[]time.Duration, name string, value []time.Duration, usage string) {
|
||||||
|
CommandLine.VarP(newDurationSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationSliceVarP is like DurationSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func DurationSliceVarP(p *[]time.Duration, name, shorthand string, value []time.Duration, usage string) {
|
||||||
|
CommandLine.VarP(newDurationSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []time.Duration variable that stores the value of the flag.
|
||||||
|
func (f *FlagSet) DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration {
|
||||||
|
p := []time.Duration{}
|
||||||
|
f.DurationSliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationSliceP is like DurationSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) DurationSliceP(name, shorthand string, value []time.Duration, usage string) *[]time.Duration {
|
||||||
|
p := []time.Duration{}
|
||||||
|
f.DurationSliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []time.Duration variable that stores the value of the flag.
|
||||||
|
func DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration {
|
||||||
|
return CommandLine.DurationSliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationSliceP is like DurationSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func DurationSliceP(name, shorthand string, value []time.Duration, usage string) *[]time.Duration {
|
||||||
|
return CommandLine.DurationSliceP(name, shorthand, value, usage)
|
||||||
|
}
|
|
@ -101,6 +101,7 @@ package pflag
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
goflag "flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -123,6 +124,12 @@ const (
|
||||||
PanicOnError
|
PanicOnError
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ParseErrorsWhitelist defines the parsing errors that can be ignored
|
||||||
|
type ParseErrorsWhitelist struct {
|
||||||
|
// UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags
|
||||||
|
UnknownFlags bool
|
||||||
|
}
|
||||||
|
|
||||||
// NormalizedName is a flag name that has been normalized according to rules
|
// NormalizedName is a flag name that has been normalized according to rules
|
||||||
// for the FlagSet (e.g. making '-' and '_' equivalent).
|
// for the FlagSet (e.g. making '-' and '_' equivalent).
|
||||||
type NormalizedName string
|
type NormalizedName string
|
||||||
|
@ -138,6 +145,9 @@ type FlagSet struct {
|
||||||
// help/usage messages.
|
// help/usage messages.
|
||||||
SortFlags bool
|
SortFlags bool
|
||||||
|
|
||||||
|
// ParseErrorsWhitelist is used to configure a whitelist of errors
|
||||||
|
ParseErrorsWhitelist ParseErrorsWhitelist
|
||||||
|
|
||||||
name string
|
name string
|
||||||
parsed bool
|
parsed bool
|
||||||
actual map[NormalizedName]*Flag
|
actual map[NormalizedName]*Flag
|
||||||
|
@ -153,6 +163,8 @@ type FlagSet struct {
|
||||||
output io.Writer // nil means stderr; use out() accessor
|
output io.Writer // nil means stderr; use out() accessor
|
||||||
interspersed bool // allow interspersed option/non-option args
|
interspersed bool // allow interspersed option/non-option args
|
||||||
normalizeNameFunc func(f *FlagSet, name string) NormalizedName
|
normalizeNameFunc func(f *FlagSet, name string) NormalizedName
|
||||||
|
|
||||||
|
addedGoFlagSets []*goflag.FlagSet
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Flag represents the state of a flag.
|
// A Flag represents the state of a flag.
|
||||||
|
@ -267,16 +279,16 @@ func (f *FlagSet) VisitAll(fn func(*Flag)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasFlags returns a bool to indicate if the FlagSet has any flags definied.
|
// HasFlags returns a bool to indicate if the FlagSet has any flags defined.
|
||||||
func (f *FlagSet) HasFlags() bool {
|
func (f *FlagSet) HasFlags() bool {
|
||||||
return len(f.formal) > 0
|
return len(f.formal) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasAvailableFlags returns a bool to indicate if the FlagSet has any flags
|
// HasAvailableFlags returns a bool to indicate if the FlagSet has any flags
|
||||||
// definied that are not hidden or deprecated.
|
// that are not hidden.
|
||||||
func (f *FlagSet) HasAvailableFlags() bool {
|
func (f *FlagSet) HasAvailableFlags() bool {
|
||||||
for _, flag := range f.formal {
|
for _, flag := range f.formal {
|
||||||
if !flag.Hidden && len(flag.Deprecated) == 0 {
|
if !flag.Hidden {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -386,6 +398,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
|
||||||
return fmt.Errorf("deprecated message for flag %q must be set", name)
|
return fmt.Errorf("deprecated message for flag %q must be set", name)
|
||||||
}
|
}
|
||||||
flag.Deprecated = usageMessage
|
flag.Deprecated = usageMessage
|
||||||
|
flag.Hidden = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,6 +581,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
|
||||||
name = "strings"
|
name = "strings"
|
||||||
case "intSlice":
|
case "intSlice":
|
||||||
name = "ints"
|
name = "ints"
|
||||||
|
case "uintSlice":
|
||||||
|
name = "uints"
|
||||||
|
case "boolSlice":
|
||||||
|
name = "bools"
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -582,11 +599,14 @@ func wrapN(i, slop int, s string) (string, string) {
|
||||||
return s, ""
|
return s, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
w := strings.LastIndexAny(s[:i], " \t")
|
w := strings.LastIndexAny(s[:i], " \t\n")
|
||||||
if w <= 0 {
|
if w <= 0 {
|
||||||
return s, ""
|
return s, ""
|
||||||
}
|
}
|
||||||
|
nlPos := strings.LastIndex(s[:i], "\n")
|
||||||
|
if nlPos > 0 && nlPos < w {
|
||||||
|
return s[:nlPos], s[nlPos+1:]
|
||||||
|
}
|
||||||
return s[:w], s[w+1:]
|
return s[:w], s[w+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +615,7 @@ func wrapN(i, slop int, s string) (string, string) {
|
||||||
// caller). Pass `w` == 0 to do no wrapping
|
// caller). Pass `w` == 0 to do no wrapping
|
||||||
func wrap(i, w int, s string) string {
|
func wrap(i, w int, s string) string {
|
||||||
if w == 0 {
|
if w == 0 {
|
||||||
return s
|
return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// space between indent i and end of line width w into which
|
// space between indent i and end of line width w into which
|
||||||
|
@ -613,7 +633,7 @@ func wrap(i, w int, s string) string {
|
||||||
}
|
}
|
||||||
// If still not enough space then don't even try to wrap.
|
// If still not enough space then don't even try to wrap.
|
||||||
if wrap < 24 {
|
if wrap < 24 {
|
||||||
return s
|
return strings.Replace(s, "\n", r, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to avoid short orphan words on the final line, by
|
// Try to avoid short orphan words on the final line, by
|
||||||
|
@ -625,14 +645,14 @@ func wrap(i, w int, s string) string {
|
||||||
// Handle first line, which is indented by the caller (or the
|
// Handle first line, which is indented by the caller (or the
|
||||||
// special case above)
|
// special case above)
|
||||||
l, s = wrapN(wrap, slop, s)
|
l, s = wrapN(wrap, slop, s)
|
||||||
r = r + l
|
r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1)
|
||||||
|
|
||||||
// Now wrap the rest
|
// Now wrap the rest
|
||||||
for s != "" {
|
for s != "" {
|
||||||
var t string
|
var t string
|
||||||
|
|
||||||
t, s = wrapN(wrap, slop, s)
|
t, s = wrapN(wrap, slop, s)
|
||||||
r = r + "\n" + strings.Repeat(" ", i) + t
|
r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
@ -649,7 +669,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
||||||
|
|
||||||
maxlen := 0
|
maxlen := 0
|
||||||
f.VisitAll(func(flag *Flag) {
|
f.VisitAll(func(flag *Flag) {
|
||||||
if flag.Deprecated != "" || flag.Hidden {
|
if flag.Hidden {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,6 +716,9 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
||||||
line += fmt.Sprintf(" (default %s)", flag.DefValue)
|
line += fmt.Sprintf(" (default %s)", flag.DefValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(flag.Deprecated) != 0 {
|
||||||
|
line += fmt.Sprintf(" (DEPRECATED: %s)", flag.Deprecated)
|
||||||
|
}
|
||||||
|
|
||||||
lines = append(lines, line)
|
lines = append(lines, line)
|
||||||
})
|
})
|
||||||
|
@ -892,6 +915,25 @@ func (f *FlagSet) usage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--unknown (args will be empty)
|
||||||
|
//--unknown --next-flag ... (args will be --next-flag ...)
|
||||||
|
//--unknown arg ... (args will be arg ...)
|
||||||
|
func stripUnknownFlagValue(args []string) []string {
|
||||||
|
if len(args) == 0 {
|
||||||
|
//--unknown
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
first := args[0]
|
||||||
|
if first[0] == '-' {
|
||||||
|
//--unknown --next-flag ...
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
//--unknown arg ... (args will be arg ...)
|
||||||
|
return args[1:]
|
||||||
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||||
a = args
|
a = args
|
||||||
name := s[2:]
|
name := s[2:]
|
||||||
|
@ -903,14 +945,25 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
||||||
split := strings.SplitN(name, "=", 2)
|
split := strings.SplitN(name, "=", 2)
|
||||||
name = split[0]
|
name = split[0]
|
||||||
flag, exists := f.formal[f.normalizeFlagName(name)]
|
flag, exists := f.formal[f.normalizeFlagName(name)]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
if name == "help" { // special case for nice help message.
|
switch {
|
||||||
|
case name == "help":
|
||||||
f.usage()
|
f.usage()
|
||||||
return a, ErrHelp
|
return a, ErrHelp
|
||||||
|
case f.ParseErrorsWhitelist.UnknownFlags:
|
||||||
|
// --unknown=unknownval arg ...
|
||||||
|
// we do not want to lose arg in this case
|
||||||
|
if len(split) >= 2 {
|
||||||
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return stripUnknownFlagValue(a), nil
|
||||||
|
default:
|
||||||
err = f.failf("unknown flag: --%s", name)
|
err = f.failf("unknown flag: --%s", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var value string
|
var value string
|
||||||
if len(split) == 2 {
|
if len(split) == 2 {
|
||||||
|
@ -947,14 +1000,26 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
|
||||||
|
|
||||||
flag, exists := f.shorthands[c]
|
flag, exists := f.shorthands[c]
|
||||||
if !exists {
|
if !exists {
|
||||||
if c == 'h' { // special case for nice help message.
|
switch {
|
||||||
|
case c == 'h':
|
||||||
f.usage()
|
f.usage()
|
||||||
err = ErrHelp
|
err = ErrHelp
|
||||||
return
|
return
|
||||||
|
case f.ParseErrorsWhitelist.UnknownFlags:
|
||||||
|
// '-f=arg arg ...'
|
||||||
|
// we do not want to lose arg in this case
|
||||||
|
if len(shorthands) > 2 && shorthands[1] == '=' {
|
||||||
|
outShorts = ""
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outArgs = stripUnknownFlagValue(outArgs)
|
||||||
|
return
|
||||||
|
default:
|
||||||
err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
|
err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var value string
|
var value string
|
||||||
if len(shorthands) > 2 && shorthands[1] == '=' {
|
if len(shorthands) > 2 && shorthands[1] == '=' {
|
||||||
|
@ -1040,6 +1105,11 @@ func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
|
||||||
// are defined and before flags are accessed by the program.
|
// are defined and before flags are accessed by the program.
|
||||||
// The return value will be ErrHelp if -help was set but not defined.
|
// The return value will be ErrHelp if -help was set but not defined.
|
||||||
func (f *FlagSet) Parse(arguments []string) error {
|
func (f *FlagSet) Parse(arguments []string) error {
|
||||||
|
if f.addedGoFlagSets != nil {
|
||||||
|
for _, goFlagSet := range f.addedGoFlagSets {
|
||||||
|
goFlagSet.Parse(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
f.parsed = true
|
f.parsed = true
|
||||||
|
|
||||||
if len(arguments) < 0 {
|
if len(arguments) < 0 {
|
||||||
|
|
|
@ -98,4 +98,8 @@ func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {
|
||||||
newSet.VisitAll(func(goflag *goflag.Flag) {
|
newSet.VisitAll(func(goflag *goflag.Flag) {
|
||||||
f.AddGoFlag(goflag)
|
f.AddGoFlag(goflag)
|
||||||
})
|
})
|
||||||
|
if f.addedGoFlagSets == nil {
|
||||||
|
f.addedGoFlagSets = make([]*goflag.FlagSet, 0)
|
||||||
|
}
|
||||||
|
f.addedGoFlagSets = append(f.addedGoFlagSets, newSet)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ func (f *FlagSet) GetStringArray(name string) ([]string, error) {
|
||||||
|
|
||||||
// StringArrayVar defines a string flag with specified name, default value, and usage string.
|
// StringArrayVar defines a string flag with specified name, default value, and usage string.
|
||||||
// The argument p points to a []string variable in which to store the values of the multiple flags.
|
// The argument p points to a []string variable in which to store the values of the multiple flags.
|
||||||
// The value of each argument will not try to be separated by comma
|
// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
|
||||||
func (f *FlagSet) StringArrayVar(p *[]string, name string, value []string, usage string) {
|
func (f *FlagSet) StringArrayVar(p *[]string, name string, value []string, usage string) {
|
||||||
f.VarP(newStringArrayValue(value, p), name, "", usage)
|
f.VarP(newStringArrayValue(value, p), name, "", usage)
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ func (f *FlagSet) StringArrayVarP(p *[]string, name, shorthand string, value []s
|
||||||
|
|
||||||
// StringArrayVar defines a string flag with specified name, default value, and usage string.
|
// StringArrayVar defines a string flag with specified name, default value, and usage string.
|
||||||
// The argument p points to a []string variable in which to store the value of the flag.
|
// The argument p points to a []string variable in which to store the value of the flag.
|
||||||
// The value of each argument will not try to be separated by comma
|
// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
|
||||||
func StringArrayVar(p *[]string, name string, value []string, usage string) {
|
func StringArrayVar(p *[]string, name string, value []string, usage string) {
|
||||||
CommandLine.VarP(newStringArrayValue(value, p), name, "", usage)
|
CommandLine.VarP(newStringArrayValue(value, p), name, "", usage)
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ func StringArrayVarP(p *[]string, name, shorthand string, value []string, usage
|
||||||
|
|
||||||
// StringArray defines a string flag with specified name, default value, and usage string.
|
// StringArray defines a string flag with specified name, default value, and usage string.
|
||||||
// The return value is the address of a []string variable that stores the value of the flag.
|
// The return value is the address of a []string variable that stores the value of the flag.
|
||||||
// The value of each argument will not try to be separated by comma
|
// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
|
||||||
func (f *FlagSet) StringArray(name string, value []string, usage string) *[]string {
|
func (f *FlagSet) StringArray(name string, value []string, usage string) *[]string {
|
||||||
p := []string{}
|
p := []string{}
|
||||||
f.StringArrayVarP(&p, name, "", value, usage)
|
f.StringArrayVarP(&p, name, "", value, usage)
|
||||||
|
@ -92,7 +92,7 @@ func (f *FlagSet) StringArrayP(name, shorthand string, value []string, usage str
|
||||||
|
|
||||||
// StringArray defines a string flag with specified name, default value, and usage string.
|
// StringArray defines a string flag with specified name, default value, and usage string.
|
||||||
// The return value is the address of a []string variable that stores the value of the flag.
|
// The return value is the address of a []string variable that stores the value of the flag.
|
||||||
// The value of each argument will not try to be separated by comma
|
// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
|
||||||
func StringArray(name string, value []string, usage string) *[]string {
|
func StringArray(name string, value []string, usage string) *[]string {
|
||||||
return CommandLine.StringArrayP(name, "", value, usage)
|
return CommandLine.StringArrayP(name, "", value, usage)
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,11 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
|
||||||
|
|
||||||
// StringSliceVar defines a string flag with specified name, default value, and usage string.
|
// StringSliceVar defines a string flag with specified name, default value, and usage string.
|
||||||
// The argument p points to a []string variable in which to store the value of the flag.
|
// The argument p points to a []string variable in which to store the value of the flag.
|
||||||
|
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||||
|
// For example:
|
||||||
|
// --ss="v1,v2" -ss="v3"
|
||||||
|
// will result in
|
||||||
|
// []string{"v1", "v2", "v3"}
|
||||||
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
|
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
|
||||||
f.VarP(newStringSliceValue(value, p), name, "", usage)
|
f.VarP(newStringSliceValue(value, p), name, "", usage)
|
||||||
}
|
}
|
||||||
|
@ -93,6 +98,11 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s
|
||||||
|
|
||||||
// StringSliceVar defines a string flag with specified name, default value, and usage string.
|
// StringSliceVar defines a string flag with specified name, default value, and usage string.
|
||||||
// The argument p points to a []string variable in which to store the value of the flag.
|
// The argument p points to a []string variable in which to store the value of the flag.
|
||||||
|
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||||
|
// For example:
|
||||||
|
// --ss="v1,v2" -ss="v3"
|
||||||
|
// will result in
|
||||||
|
// []string{"v1", "v2", "v3"}
|
||||||
func StringSliceVar(p *[]string, name string, value []string, usage string) {
|
func StringSliceVar(p *[]string, name string, value []string, usage string) {
|
||||||
CommandLine.VarP(newStringSliceValue(value, p), name, "", usage)
|
CommandLine.VarP(newStringSliceValue(value, p), name, "", usage)
|
||||||
}
|
}
|
||||||
|
@ -104,6 +114,11 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage
|
||||||
|
|
||||||
// StringSlice defines a string flag with specified name, default value, and usage string.
|
// StringSlice defines a string flag with specified name, default value, and usage string.
|
||||||
// The return value is the address of a []string variable that stores the value of the flag.
|
// The return value is the address of a []string variable that stores the value of the flag.
|
||||||
|
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||||
|
// For example:
|
||||||
|
// --ss="v1,v2" -ss="v3"
|
||||||
|
// will result in
|
||||||
|
// []string{"v1", "v2", "v3"}
|
||||||
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
|
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
|
||||||
p := []string{}
|
p := []string{}
|
||||||
f.StringSliceVarP(&p, name, "", value, usage)
|
f.StringSliceVarP(&p, name, "", value, usage)
|
||||||
|
@ -119,6 +134,11 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str
|
||||||
|
|
||||||
// StringSlice defines a string flag with specified name, default value, and usage string.
|
// StringSlice defines a string flag with specified name, default value, and usage string.
|
||||||
// The return value is the address of a []string variable that stores the value of the flag.
|
// The return value is the address of a []string variable that stores the value of the flag.
|
||||||
|
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||||
|
// For example:
|
||||||
|
// --ss="v1,v2" -ss="v3"
|
||||||
|
// will result in
|
||||||
|
// []string{"v1", "v2", "v3"}
|
||||||
func StringSlice(name string, value []string, usage string) *[]string {
|
func StringSlice(name string, value []string, usage string) *[]string {
|
||||||
return CommandLine.StringSliceP(name, "", value, usage)
|
return CommandLine.StringSliceP(name, "", value, usage)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue