From 218df6ac6103aaefa45be436679b9278538146d0 Mon Sep 17 00:00:00 2001 From: bryanl <bryanliles@gmail.com> Date: Sun, 25 Feb 2018 12:37:10 -0500 Subject: [PATCH] upgrading cobra Signed-off-by: bryanl <bryanliles@gmail.com> --- Gopkg.lock | 4 +- Gopkg.toml | 7 +- docs/cli-reference/ks.md | 7 +- docs/cli-reference/ks_apply.md | 5 +- docs/cli-reference/ks_component.md | 10 +- docs/cli-reference/ks_component_list.md | 10 +- docs/cli-reference/ks_component_rm.md | 5 +- docs/cli-reference/ks_delete.md | 5 +- docs/cli-reference/ks_diff.md | 5 +- docs/cli-reference/ks_env.md | 5 +- docs/cli-reference/ks_env_add.md | 5 +- docs/cli-reference/ks_env_list.md | 10 +- docs/cli-reference/ks_env_rm.md | 10 +- docs/cli-reference/ks_env_set.md | 5 +- docs/cli-reference/ks_generate.md | 10 +- docs/cli-reference/ks_init.md | 3 +- docs/cli-reference/ks_param.md | 10 +- docs/cli-reference/ks_param_diff.md | 5 +- docs/cli-reference/ks_param_list.md | 5 +- docs/cli-reference/ks_param_set.md | 5 +- docs/cli-reference/ks_pkg.md | 10 +- docs/cli-reference/ks_pkg_describe.md | 10 +- docs/cli-reference/ks_pkg_install.md | 5 +- docs/cli-reference/ks_pkg_list.md | 10 +- docs/cli-reference/ks_prototype.md | 10 +- docs/cli-reference/ks_prototype_describe.md | 10 +- docs/cli-reference/ks_prototype_list.md | 10 +- docs/cli-reference/ks_prototype_preview.md | 10 +- docs/cli-reference/ks_prototype_search.md | 10 +- docs/cli-reference/ks_prototype_use.md | 10 +- docs/cli-reference/ks_registry.md | 10 +- docs/cli-reference/ks_registry_add.md | 5 +- docs/cli-reference/ks_registry_describe.md | 10 +- docs/cli-reference/ks_registry_list.md | 10 +- docs/cli-reference/ks_show.md | 5 +- docs/cli-reference/ks_validate.md | 5 +- docs/cli-reference/ks_version.md | 10 +- vendor/github.com/spf13/cobra/.travis.yml | 4 +- vendor/github.com/spf13/cobra/README.md | 855 +++++++----------- vendor/github.com/spf13/cobra/args.go | 89 ++ .../spf13/cobra/bash_completions.go | 410 ++++----- .../spf13/cobra/bash_completions.md | 18 +- vendor/github.com/spf13/cobra/cobra.go | 21 +- .../spf13/cobra/cobra/cmd/license_agpl.go | 3 +- .../spf13/cobra/cobra/cmd/license_apache_2.go | 3 +- .../cobra/cobra/cmd/license_bsd_clause_2.go | 3 +- .../cobra/cobra/cmd/license_bsd_clause_3.go | 3 +- .../spf13/cobra/cobra/cmd/license_gpl_2.go | 27 +- .../spf13/cobra/cobra/cmd/license_gpl_3.go | 3 +- .../spf13/cobra/cobra/cmd/license_lgpl.go | 3 +- .../spf13/cobra/cobra/cmd/license_mit.go | 2 +- .../spf13/cobra/cobra/cmd/licenses.go | 8 +- vendor/github.com/spf13/cobra/command.go | 414 ++++++--- vendor/github.com/spf13/cobra/command_win.go | 8 +- vendor/github.com/spf13/cobra/doc/man_docs.go | 3 + vendor/github.com/spf13/cobra/doc/md_docs.go | 7 +- .../github.com/spf13/cobra/doc/rest_docs.go | 185 ++++ .../github.com/spf13/cobra/doc/rest_docs.md | 114 +++ .../github.com/spf13/cobra/doc/yaml_docs.go | 3 + .../github.com/spf13/cobra/zsh_completions.go | 126 +++ 60 files changed, 1622 insertions(+), 971 deletions(-) create mode 100644 vendor/github.com/spf13/cobra/args.go create mode 100644 vendor/github.com/spf13/cobra/doc/rest_docs.go create mode 100644 vendor/github.com/spf13/cobra/doc/rest_docs.md create mode 100644 vendor/github.com/spf13/cobra/zsh_completions.go diff --git a/Gopkg.lock b/Gopkg.lock index aef4d06c..2d315d0b 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -349,7 +349,7 @@ ".", "doc" ] - revision = "4673102358fdd630e3bb0eb6dee96e4b533d53ec" + revision = "a1e4933ab784095895e33dbe9f001ba10cfe2060" [[projects]] name = "github.com/spf13/pflag" @@ -600,6 +600,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "3ec216adf8721873a210ca86de7f6477993f990d180563ba88a2e167a0b7be88" + inputs-digest = "2d8337f0b0870fb8b2c0a041d7b5e3e77b66b414fe9c2d7962ee5c5842bb94e0" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 2029db92..af3ba07a 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -78,7 +78,7 @@ [[constraint]] name = "github.com/spf13/cobra" - revision = "4673102358fdd630e3bb0eb6dee96e4b533d53ec" + revision = "a1e4933ab784095895e33dbe9f001ba10cfe2060" [[constraint]] name = "github.com/spf13/pflag" @@ -114,4 +114,7 @@ [[constraint]] name = "k8s.io/client-go" - version = "5.0.0" \ No newline at end of file + version = "5.0.0" +[[constraint]] + branch = "master" + name = "github.com/shibukawa/configdir" diff --git a/docs/cli-reference/ks.md b/docs/cli-reference/ks.md index 23cd79af..041bc8b5 100644 --- a/docs/cli-reference/ks.md +++ b/docs/cli-reference/ks.md @@ -5,20 +5,25 @@ Configure your application to deploy to a Kubernetes cluster ### Synopsis - You can use the `ks` commands to write, share, and deploy your Kubernetes application configuration to remote clusters. ---- +``` +ks [flags] +``` + ### Options ``` + -h, --help help for ks -v, --verbose count[=-1] Increase verbosity. May be given multiple times. ``` ### SEE ALSO + * [ks apply](ks_apply.md) - Apply local Kubernetes manifests (components) to remote clusters * [ks component](ks_component.md) - Manage ksonnet components * [ks delete](ks_delete.md) - Remove component-specified Kubernetes resources from remote clusters diff --git a/docs/cli-reference/ks_apply.md b/docs/cli-reference/ks_apply.md index 155f443f..58aaabf7 100644 --- a/docs/cli-reference/ks_apply.md +++ b/docs/cli-reference/ks_apply.md @@ -5,7 +5,6 @@ Apply local Kubernetes manifests (components) to remote clusters ### Synopsis - The `apply`command uses local manifest(s) to update (and optionally create) Kubernetes resources on a remote cluster. This cluster is determined by the mandatory `<env-name>` argument. @@ -28,7 +27,7 @@ Note that this command needs to be run *within* a ksonnet app directory. ``` -ks apply <env-name> [-c <component-name>] [--dry-run] +ks apply <env-name> [-c <component-name>] [--dry-run] [flags] ``` ### Examples @@ -78,6 +77,7 @@ ks apply dev -c guestbook-ui -c nginx-depl --create false -V, --ext-str stringSlice Values of external variables --ext-str-file stringSlice Read external variable from a file --gc-tag string A tag that's (1) added to all updated objects (2) used to garbage collect existing objects that are no longer in the manifest + -h, --help help for apply --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure -J, --jpath stringSlice Additional jsonnet library search path --kubeconfig string Path to a kubeconfig file. Alternative to env var $KUBECONFIG. @@ -102,5 +102,6 @@ ks apply dev -c guestbook-ui -c nginx-depl --create false ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster diff --git a/docs/cli-reference/ks_component.md b/docs/cli-reference/ks_component.md index 1ccdd345..43b1dbb7 100644 --- a/docs/cli-reference/ks_component.md +++ b/docs/cli-reference/ks_component.md @@ -4,11 +4,16 @@ Manage ksonnet components ### Synopsis - Manage ksonnet components ``` -ks component +ks component [flags] +``` + +### Options + +``` + -h, --help help for component ``` ### Options inherited from parent commands @@ -18,6 +23,7 @@ ks component ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster * [ks component list](ks_component_list.md) - List known components * [ks component rm](ks_component_rm.md) - Delete a component from the ksonnet application diff --git a/docs/cli-reference/ks_component_list.md b/docs/cli-reference/ks_component_list.md index 0f7722cb..fc11a006 100644 --- a/docs/cli-reference/ks_component_list.md +++ b/docs/cli-reference/ks_component_list.md @@ -5,14 +5,13 @@ List known components ### Synopsis - The `list` command displays all known components. ### Syntax ``` -ks component list +ks component list [flags] ``` ### Examples @@ -23,6 +22,12 @@ ks component list ks component list ``` +### Options + +``` + -h, --help help for list +``` + ### Options inherited from parent commands ``` @@ -30,5 +35,6 @@ ks component list ``` ### SEE ALSO + * [ks component](ks_component.md) - Manage ksonnet components diff --git a/docs/cli-reference/ks_component_rm.md b/docs/cli-reference/ks_component_rm.md index f5664af2..2200d252 100644 --- a/docs/cli-reference/ks_component_rm.md +++ b/docs/cli-reference/ks_component_rm.md @@ -4,13 +4,12 @@ Delete a component from the ksonnet application ### Synopsis - Delete a component from the ksonnet application. This is equivalent to deleting the component file in the components directory and cleaning up all component references throughout the project. ``` -ks component rm <component-name> +ks component rm <component-name> [flags] ``` ### Examples @@ -26,6 +25,7 @@ ks component rm guestbook ``` --component string The component to be removed from components/ + -h, --help help for rm ``` ### Options inherited from parent commands @@ -35,5 +35,6 @@ ks component rm guestbook ``` ### SEE ALSO + * [ks component](ks_component.md) - Manage ksonnet components diff --git a/docs/cli-reference/ks_delete.md b/docs/cli-reference/ks_delete.md index 830f83a1..fcc4a416 100644 --- a/docs/cli-reference/ks_delete.md +++ b/docs/cli-reference/ks_delete.md @@ -5,7 +5,6 @@ Remove component-specified Kubernetes resources from remote clusters ### Synopsis - The `delete` command removes Kubernetes resources (described in local *component* manifests) from a cluster. This cluster is determined by the mandatory `<env-name>`argument. @@ -24,7 +23,7 @@ components. ``` -ks delete [env-name] [-c <component-name>] +ks delete [env-name] [-c <component-name>] [flags] ``` ### Examples @@ -55,6 +54,7 @@ ks delete --kubeconfig=./kubeconfig -c nginx -V, --ext-str stringSlice Values of external variables --ext-str-file stringSlice Read external variable from a file --grace-period int Number of seconds given to resources to terminate gracefully. A negative value is ignored (default -1) + -h, --help help for delete --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure -J, --jpath stringSlice Additional jsonnet library search path --kubeconfig string Path to a kubeconfig file. Alternative to env var $KUBECONFIG. @@ -78,5 +78,6 @@ ks delete --kubeconfig=./kubeconfig -c nginx ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster diff --git a/docs/cli-reference/ks_diff.md b/docs/cli-reference/ks_diff.md index 70491f99..031fbfaf 100644 --- a/docs/cli-reference/ks_diff.md +++ b/docs/cli-reference/ks_diff.md @@ -5,7 +5,6 @@ Compare manifests, based on environment or location (local or remote) ### Synopsis - The `diff` command displays standard file diffs, and can be used to compare manifests based on *environment* or location ('local' ksonnet app manifests or what's running on a 'remote' server). @@ -34,7 +33,7 @@ the manifest for that particular component. ``` -ks diff <location1:env1> [location2:env2] [-c <component-name>] +ks diff <location1:env1> [location2:env2] [-c <component-name>] [flags] ``` ### Examples @@ -71,6 +70,7 @@ ks diff dev -c redis --diff-strategy string Diff strategy, all or subset. (default "all") -V, --ext-str stringSlice Values of external variables --ext-str-file stringSlice Read external variable from a file + -h, --help help for diff -J, --jpath stringSlice Additional jsonnet library search path --resolve-images string Change implementation of resolveImage native function. One of: noop, registry (default "noop") --resolve-images-error string Action when resolveImage fails. One of ignore,warn,error (default "warn") @@ -85,5 +85,6 @@ ks diff dev -c redis ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster diff --git a/docs/cli-reference/ks_env.md b/docs/cli-reference/ks_env.md index d3bc8a41..52074a2d 100644 --- a/docs/cli-reference/ks_env.md +++ b/docs/cli-reference/ks_env.md @@ -5,7 +5,6 @@ Manage ksonnet environments ### Synopsis - An environment is a deployment target for your ksonnet app and its constituent components. You can use ksonnet to deploy a given app to *multiple* environments, such as `dev` and `prod`. @@ -43,7 +42,7 @@ represented as a hierarchy in the `environments/` directory of a ksonnet app, li ``` -ks env +ks env [flags] ``` ### Options @@ -56,6 +55,7 @@ ks env --client-key string Path to a client key file for TLS --cluster string The name of the kubeconfig cluster to use --context string The name of the kubeconfig context to use + -h, --help help for env --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure --kubeconfig string Path to a kubeconfig file. Alternative to env var $KUBECONFIG. -n, --namespace string If present, the namespace scope for this CLI request @@ -74,6 +74,7 @@ ks env ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster * [ks env add](ks_env_add.md) - Add a new environment to a ksonnet application * [ks env list](ks_env_list.md) - List all environments in a ksonnet application diff --git a/docs/cli-reference/ks_env_add.md b/docs/cli-reference/ks_env_add.md index ae25c800..2fc98df0 100644 --- a/docs/cli-reference/ks_env_add.md +++ b/docs/cli-reference/ks_env_add.md @@ -5,7 +5,6 @@ Add a new environment to a ksonnet application ### Synopsis - The `add` command creates a new environment (specifically for the ksonnet app whose directory it's executed in). This environment is cached with the following info: @@ -34,7 +33,7 @@ Note that an environment *DOES NOT* contain user-specific data such as private k ``` -ks env add <env-name> +ks env add <env-name> [flags] ``` ### Examples @@ -67,6 +66,7 @@ ks env add prod --server=https://ksonnet-1.us-west.elb.amazonaws.com ``` --api-spec string Manually specify API version from OpenAPI schema, cluster, or Kubernetes version (default "version:v1.7.0") + -h, --help help for add ``` ### Options inherited from parent commands @@ -92,5 +92,6 @@ ks env add prod --server=https://ksonnet-1.us-west.elb.amazonaws.com ``` ### SEE ALSO + * [ks env](ks_env.md) - Manage ksonnet environments diff --git a/docs/cli-reference/ks_env_list.md b/docs/cli-reference/ks_env_list.md index 061c0d2a..7746c5a8 100644 --- a/docs/cli-reference/ks_env_list.md +++ b/docs/cli-reference/ks_env_list.md @@ -5,7 +5,6 @@ List all environments in a ksonnet application ### Synopsis - The `list` command lists all of the available environments for the current ksonnet app. Specifically, this will display the (1) *name*, (2) *server*, and (3) *namespace* of each environment. @@ -20,7 +19,13 @@ current ksonnet app. Specifically, this will display the (1) *name*, ``` -ks env list +ks env list [flags] +``` + +### Options + +``` + -h, --help help for list ``` ### Options inherited from parent commands @@ -46,5 +51,6 @@ ks env list ``` ### SEE ALSO + * [ks env](ks_env.md) - Manage ksonnet environments diff --git a/docs/cli-reference/ks_env_rm.md b/docs/cli-reference/ks_env_rm.md index 4b8b825c..60dfcd04 100644 --- a/docs/cli-reference/ks_env_rm.md +++ b/docs/cli-reference/ks_env_rm.md @@ -5,7 +5,6 @@ Delete an environment from a ksonnet application ### Synopsis - The `rm` command deletes an environment from a ksonnet application. This is the same as removing the `<env-name>` environment directory and all files contained. All empty parent directories are also subsequently deleted. @@ -24,7 +23,7 @@ need to use the `ks delete` command. ``` -ks env rm <env-name> +ks env rm <env-name> [flags] ``` ### Examples @@ -36,6 +35,12 @@ ks env rm <env-name> ks env rm us-west/staging ``` +### Options + +``` + -h, --help help for rm +``` + ### Options inherited from parent commands ``` @@ -59,5 +64,6 @@ ks env rm us-west/staging ``` ### SEE ALSO + * [ks env](ks_env.md) - Manage ksonnet environments diff --git a/docs/cli-reference/ks_env_set.md b/docs/cli-reference/ks_env_set.md index 3fdece1f..bc7f6ac8 100644 --- a/docs/cli-reference/ks_env_set.md +++ b/docs/cli-reference/ks_env_set.md @@ -5,7 +5,6 @@ Set environment-specific fields (name, namespace, server) ### Synopsis - The `set` command lets you change the fields of an existing environment. You can currently only update your environment's name. @@ -20,7 +19,7 @@ directory structure in `environments/`. ``` -ks env set <env-name> +ks env set <env-name> [flags] ``` ### Examples @@ -34,6 +33,7 @@ ks env set us-west/staging --name=us-east/staging ### Options ``` + -h, --help help for set --name string Name used to uniquely identify the environment. Must not already exist within the ksonnet app ``` @@ -60,5 +60,6 @@ ks env set us-west/staging --name=us-east/staging ``` ### SEE ALSO + * [ks env](ks_env.md) - Manage ksonnet environments diff --git a/docs/cli-reference/ks_generate.md b/docs/cli-reference/ks_generate.md index ac970dc3..4c919d64 100644 --- a/docs/cli-reference/ks_generate.md +++ b/docs/cli-reference/ks_generate.md @@ -5,7 +5,6 @@ Use the specified prototype to generate a component manifest ### Synopsis - The `generate` command (aliased from `prototype use`) generates Kubernetes- compatible, Jsonnet manifests for components in your ksonnet app. Each component corresponds to a single manifest in the `components/` directory. This manifest @@ -43,7 +42,7 @@ different prototypes support their own unique flags. ``` -ks generate <prototype-name> <component-name> [type] [parameter-flags] +ks generate <prototype-name> <component-name> [type] [parameter-flags] [flags] ``` ### Examples @@ -68,6 +67,12 @@ ks prototype use deployment nginx-depl \ --image=nginx ``` +### Options + +``` + -h, --help help for generate +``` + ### Options inherited from parent commands ``` @@ -75,5 +80,6 @@ ks prototype use deployment nginx-depl \ ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster diff --git a/docs/cli-reference/ks_init.md b/docs/cli-reference/ks_init.md index 21bde859..a1d31365 100644 --- a/docs/cli-reference/ks_init.md +++ b/docs/cli-reference/ks_init.md @@ -5,7 +5,6 @@ Initialize a ksonnet application ### Synopsis - The `init` command initializes a ksonnet application in a new directory, `app-name`. This command generates all the project scaffolding required to begin creating and @@ -91,6 +90,7 @@ ks init app-name --dir=custom-location --cluster string The name of the kubeconfig cluster to use --context string The name of the kubeconfig context to use --dir string Ksonnet application directory + -h, --help help for init --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure --kubeconfig string Path to a kubeconfig file. Alternative to env var $KUBECONFIG. -n, --namespace string If present, the namespace scope for this CLI request @@ -109,5 +109,6 @@ ks init app-name --dir=custom-location ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster diff --git a/docs/cli-reference/ks_param.md b/docs/cli-reference/ks_param.md index a7375e22..c9d43934 100644 --- a/docs/cli-reference/ks_param.md +++ b/docs/cli-reference/ks_param.md @@ -5,7 +5,6 @@ Manage ksonnet parameters for components and environments ### Synopsis - Parameters are customizable fields that are used inside ksonnet *component* manifests. Examples might include a deployment's 'name' or 'image'. Parameters can also be defined on a *per-environment* basis. (Environments are ksonnet @@ -36,7 +35,13 @@ Jsonnet files. ``` -ks param +ks param [flags] +``` + +### Options + +``` + -h, --help help for param ``` ### Options inherited from parent commands @@ -46,6 +51,7 @@ ks param ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster * [ks param diff](ks_param_diff.md) - Display differences between the component parameters of two environments * [ks param list](ks_param_list.md) - List known component parameters diff --git a/docs/cli-reference/ks_param_diff.md b/docs/cli-reference/ks_param_diff.md index d1e0355b..c017ed93 100644 --- a/docs/cli-reference/ks_param_diff.md +++ b/docs/cli-reference/ks_param_diff.md @@ -5,7 +5,6 @@ Display differences between the component parameters of two environments ### Synopsis - The `diff` command pretty prints differences between the component parameters of two environments. @@ -21,7 +20,7 @@ is supported via a component flag. ``` -ks param diff <env1> <env2> [--component <component-name>] +ks param diff <env1> <env2> [--component <component-name>] [flags] ``` ### Examples @@ -40,6 +39,7 @@ ks param diff dev prod --component=guestbook ``` --component string Specify the component to diff against + -h, --help help for diff ``` ### Options inherited from parent commands @@ -49,5 +49,6 @@ ks param diff dev prod --component=guestbook ``` ### SEE ALSO + * [ks param](ks_param.md) - Manage ksonnet parameters for components and environments diff --git a/docs/cli-reference/ks_param_list.md b/docs/cli-reference/ks_param_list.md index e72da2b9..38b12d1a 100644 --- a/docs/cli-reference/ks_param_list.md +++ b/docs/cli-reference/ks_param_list.md @@ -5,7 +5,6 @@ List known component parameters ### Synopsis - The `list` command displays all known component parameters or environment parameters. If a component is specified, this command displays all of its specific parameters. @@ -20,7 +19,7 @@ Furthermore, parameters can be listed on a per-environment basis. ``` -ks param list [<component-name>] [--env <env-name>] +ks param list [<component-name>] [--env <env-name>] [flags] ``` ### Examples @@ -44,6 +43,7 @@ ks param list guestbook --env=dev ``` --env string Specify environment to list parameters for + -h, --help help for list ``` ### Options inherited from parent commands @@ -53,5 +53,6 @@ ks param list guestbook --env=dev ``` ### SEE ALSO + * [ks param](ks_param.md) - Manage ksonnet parameters for components and environments diff --git a/docs/cli-reference/ks_param_set.md b/docs/cli-reference/ks_param_set.md index 04a3ba55..d1d8df8c 100644 --- a/docs/cli-reference/ks_param_set.md +++ b/docs/cli-reference/ks_param_set.md @@ -5,7 +5,6 @@ Change component or environment parameters (e.g. replica count, name) ### Synopsis - The `set` command sets component or environment parameters such as replica count or name. Parameters are set individually, one at a time. All of these changes are reflected in the `params.libsonnet` files. @@ -26,7 +25,7 @@ for greater customization of environment parameters, we suggest modifying the ``` -ks param set <component-name> <param-key> <param-value> +ks param set <component-name> <param-key> <param-value> [flags] ``` ### Examples @@ -45,6 +44,7 @@ ks param set guestbook replicas 2 --env=dev ``` --env string Specify environment to set parameters for + -h, --help help for set ``` ### Options inherited from parent commands @@ -54,5 +54,6 @@ ks param set guestbook replicas 2 --env=dev ``` ### SEE ALSO + * [ks param](ks_param.md) - Manage ksonnet parameters for components and environments diff --git a/docs/cli-reference/ks_pkg.md b/docs/cli-reference/ks_pkg.md index f32c0390..0e3378ca 100644 --- a/docs/cli-reference/ks_pkg.md +++ b/docs/cli-reference/ks_pkg.md @@ -5,7 +5,6 @@ Manage packages and dependencies for the current ksonnet application ### Synopsis - A ksonnet package contains: * A set of prototypes (see `ks prototype --help` for more info on prototypes), which @@ -33,7 +32,13 @@ See the annotated file tree below, as an example: ``` -ks pkg +ks pkg [flags] +``` + +### Options + +``` + -h, --help help for pkg ``` ### Options inherited from parent commands @@ -43,6 +48,7 @@ ks pkg ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster * [ks pkg describe](ks_pkg_describe.md) - Describe a ksonnet package and its contents * [ks pkg install](ks_pkg_install.md) - Install a package (e.g. extra prototypes) for the current ksonnet app diff --git a/docs/cli-reference/ks_pkg_describe.md b/docs/cli-reference/ks_pkg_describe.md index 72df9ce1..4564117b 100644 --- a/docs/cli-reference/ks_pkg_describe.md +++ b/docs/cli-reference/ks_pkg_describe.md @@ -5,7 +5,6 @@ Describe a ksonnet package and its contents ### Synopsis - The `describe` command outputs documentation for a package that is available (e.g. downloaded) in the current ksonnet application. (This must belong to an already known `<registry-name>` like *incubator*). The output includes: @@ -24,7 +23,13 @@ known `<registry-name>` like *incubator*). The output includes: ``` -ks pkg describe [<registry-name>/]<package-name> +ks pkg describe [<registry-name>/]<package-name> [flags] +``` + +### Options + +``` + -h, --help help for describe ``` ### Options inherited from parent commands @@ -34,5 +39,6 @@ ks pkg describe [<registry-name>/]<package-name> ``` ### SEE ALSO + * [ks pkg](ks_pkg.md) - Manage packages and dependencies for the current ksonnet application diff --git a/docs/cli-reference/ks_pkg_install.md b/docs/cli-reference/ks_pkg_install.md index e885c454..c332e070 100644 --- a/docs/cli-reference/ks_pkg_install.md +++ b/docs/cli-reference/ks_pkg_install.md @@ -5,7 +5,6 @@ Install a package (e.g. extra prototypes) for the current ksonnet app ### Synopsis - The `install` command caches a ksonnet library locally, and makes it available for use in the current ksonnet application. Enough info and metadata is recorded in `app.yaml` that new users can retrieve the dependency after a fresh clone of this app. @@ -24,7 +23,7 @@ channels for official ksonnet libraries. ``` -ks pkg install <registry>/<library>@<version> +ks pkg install <registry>/<library>@<version> [flags] ``` ### Examples @@ -46,6 +45,7 @@ ks pkg install incubator/nginx@master ### Options ``` + -h, --help help for install --name string Name to give the dependency, to use within the ksonnet app ``` @@ -56,5 +56,6 @@ ks pkg install incubator/nginx@master ``` ### SEE ALSO + * [ks pkg](ks_pkg.md) - Manage packages and dependencies for the current ksonnet application diff --git a/docs/cli-reference/ks_pkg_list.md b/docs/cli-reference/ks_pkg_list.md index 3f490f57..ca5e4c6c 100644 --- a/docs/cli-reference/ks_pkg_list.md +++ b/docs/cli-reference/ks_pkg_list.md @@ -5,7 +5,6 @@ List all packages known (downloaded or not) for the current ksonnet app ### Synopsis - The `list` command outputs a table that describes all *known* packages (not necessarily downloaded, but available from existing registries). This includes the following info: @@ -24,7 +23,13 @@ the following info: ``` -ks pkg list +ks pkg list [flags] +``` + +### Options + +``` + -h, --help help for list ``` ### Options inherited from parent commands @@ -34,5 +39,6 @@ ks pkg list ``` ### SEE ALSO + * [ks pkg](ks_pkg.md) - Manage packages and dependencies for the current ksonnet application diff --git a/docs/cli-reference/ks_prototype.md b/docs/cli-reference/ks_prototype.md index ff42110e..19133d39 100644 --- a/docs/cli-reference/ks_prototype.md +++ b/docs/cli-reference/ks_prototype.md @@ -5,7 +5,6 @@ Instantiate, inspect, and get examples for ksonnet prototypes ### Synopsis - Use the `prototype` subcommands to manage, inspect, instantiate, and get examples for ksonnet prototypes. @@ -23,7 +22,13 @@ for your use case. ``` -ks prototype +ks prototype [flags] +``` + +### Options + +``` + -h, --help help for prototype ``` ### Options inherited from parent commands @@ -33,6 +38,7 @@ ks prototype ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster * [ks prototype describe](ks_prototype_describe.md) - See more info about a prototype's output and usage * [ks prototype list](ks_prototype_list.md) - List all locally available ksonnet prototypes diff --git a/docs/cli-reference/ks_prototype_describe.md b/docs/cli-reference/ks_prototype_describe.md index 3a1e3739..e07bab4c 100644 --- a/docs/cli-reference/ks_prototype_describe.md +++ b/docs/cli-reference/ks_prototype_describe.md @@ -5,7 +5,6 @@ See more info about a prototype's output and usage ### Synopsis - This command outputs documentation, examples, and other information for the specified prototype (identified by name). Specifically, this describes: @@ -23,7 +22,7 @@ the specified prototype (identified by name). Specifically, this describes: ``` -ks prototype describe <prototype-name> +ks prototype describe <prototype-name> [flags] ``` ### Examples @@ -34,6 +33,12 @@ ks prototype describe <prototype-name> ks prototype describe deployment ``` +### Options + +``` + -h, --help help for describe +``` + ### Options inherited from parent commands ``` @@ -41,5 +46,6 @@ ks prototype describe deployment ``` ### SEE ALSO + * [ks prototype](ks_prototype.md) - Instantiate, inspect, and get examples for ksonnet prototypes diff --git a/docs/cli-reference/ks_prototype_list.md b/docs/cli-reference/ks_prototype_list.md index 85b78a20..b596a2ea 100644 --- a/docs/cli-reference/ks_prototype_list.md +++ b/docs/cli-reference/ks_prototype_list.md @@ -5,7 +5,6 @@ List all locally available ksonnet prototypes ### Synopsis - The `list` command displays all prototypes that are available locally, as well as brief descriptions of what they generate. @@ -25,7 +24,13 @@ from the *incubator* registry. ``` -ks prototype list +ks prototype list [flags] +``` + +### Options + +``` + -h, --help help for list ``` ### Options inherited from parent commands @@ -35,5 +40,6 @@ ks prototype list ``` ### SEE ALSO + * [ks prototype](ks_prototype.md) - Instantiate, inspect, and get examples for ksonnet prototypes diff --git a/docs/cli-reference/ks_prototype_preview.md b/docs/cli-reference/ks_prototype_preview.md index 255c0968..08adcee8 100644 --- a/docs/cli-reference/ks_prototype_preview.md +++ b/docs/cli-reference/ks_prototype_preview.md @@ -5,7 +5,6 @@ Preview a prototype's output without creating a component (stdout) ### Synopsis - This `preview` command expands a prototype with CLI flag parameters, and emits the resulting manifest to stdout. This allows you to see the potential output of a `ks generate` command without actually creating a new component file. @@ -21,7 +20,7 @@ a component with `ks generate` and then use `ks show`. ``` -ks prototype preview <prototype-name> [parameter-flags] +ks prototype preview <prototype-name> [parameter-flags] [flags] ``` ### Examples @@ -36,6 +35,12 @@ ks prototype preview single-port-deployment \ --port=80 ``` +### Options + +``` + -h, --help help for preview +``` + ### Options inherited from parent commands ``` @@ -43,5 +48,6 @@ ks prototype preview single-port-deployment \ ``` ### SEE ALSO + * [ks prototype](ks_prototype.md) - Instantiate, inspect, and get examples for ksonnet prototypes diff --git a/docs/cli-reference/ks_prototype_search.md b/docs/cli-reference/ks_prototype_search.md index fff86275..5dce04ba 100644 --- a/docs/cli-reference/ks_prototype_search.md +++ b/docs/cli-reference/ks_prototype_search.md @@ -5,7 +5,6 @@ Search for a prototype ### Synopsis - The `prototype search` command allows you to search for specific prototypes by name. Specifically, it matches any prototypes with names that contain the string <name-substring>. @@ -18,7 +17,7 @@ Specifically, it matches any prototypes with names that contain the string <name ``` -ks prototype search <name-substring> +ks prototype search <name-substring> [flags] ``` ### Examples @@ -29,6 +28,12 @@ ks prototype search <name-substring> ks prototype search service ``` +### Options + +``` + -h, --help help for search +``` + ### Options inherited from parent commands ``` @@ -36,5 +41,6 @@ ks prototype search service ``` ### SEE ALSO + * [ks prototype](ks_prototype.md) - Instantiate, inspect, and get examples for ksonnet prototypes diff --git a/docs/cli-reference/ks_prototype_use.md b/docs/cli-reference/ks_prototype_use.md index 48307bff..9535b877 100644 --- a/docs/cli-reference/ks_prototype_use.md +++ b/docs/cli-reference/ks_prototype_use.md @@ -5,7 +5,6 @@ Use the specified prototype to generate a component manifest ### Synopsis - The `generate` command (aliased from `prototype use`) generates Kubernetes- compatible, Jsonnet manifests for components in your ksonnet app. Each component corresponds to a single manifest in the `components/` directory. This manifest @@ -43,7 +42,7 @@ different prototypes support their own unique flags. ``` -ks prototype use <prototype-name> <componentName> [type] [parameter-flags] +ks prototype use <prototype-name> <componentName> [type] [parameter-flags] [flags] ``` ### Examples @@ -68,6 +67,12 @@ ks prototype use deployment nginx-depl \ --image=nginx ``` +### Options + +``` + -h, --help help for use +``` + ### Options inherited from parent commands ``` @@ -75,5 +80,6 @@ ks prototype use deployment nginx-depl \ ``` ### SEE ALSO + * [ks prototype](ks_prototype.md) - Instantiate, inspect, and get examples for ksonnet prototypes diff --git a/docs/cli-reference/ks_registry.md b/docs/cli-reference/ks_registry.md index b0b86bc3..d4f02ed8 100644 --- a/docs/cli-reference/ks_registry.md +++ b/docs/cli-reference/ks_registry.md @@ -5,7 +5,6 @@ Manage registries for current project ### Synopsis - A ksonnet registry is basically a repository for *packages*. (Registry here is used in the same sense as a container image registry). Registries are identified by a `registry.yaml` in their root that declares which packages they contain. @@ -24,7 +23,13 @@ described above. (See `ks prototype --help` for more information.) ``` -ks registry +ks registry [flags] +``` + +### Options + +``` + -h, --help help for registry ``` ### Options inherited from parent commands @@ -34,6 +39,7 @@ ks registry ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster * [ks registry add](ks_registry_add.md) - Add a registry to the current ksonnet app * [ks registry describe](ks_registry_describe.md) - Describe a ksonnet registry and the packages it contains diff --git a/docs/cli-reference/ks_registry_add.md b/docs/cli-reference/ks_registry_add.md index 24f622e4..969c0597 100644 --- a/docs/cli-reference/ks_registry_add.md +++ b/docs/cli-reference/ks_registry_add.md @@ -5,7 +5,6 @@ Add a registry to the current ksonnet app ### Synopsis - The `add` command allows custom registries to be added to your ksonnet app, provided that their file structures follow the appropriate schema. *You can look at the `incubator` repo (https://github.com/ksonnet/parts/tree/master/incubator) @@ -31,7 +30,7 @@ name*). If a version is not specified, it will default to `latest`. ``` -ks registry add <registry-name> <registry-uri> +ks registry add <registry-name> <registry-uri> [flags] ``` ### Examples @@ -49,6 +48,7 @@ ks registry add databases github.com/example/tree/master/reg --version=0.0.1 ### Options ``` + -h, --help help for add --version string Version of the registry to add ``` @@ -59,5 +59,6 @@ ks registry add databases github.com/example/tree/master/reg --version=0.0.1 ``` ### SEE ALSO + * [ks registry](ks_registry.md) - Manage registries for current project diff --git a/docs/cli-reference/ks_registry_describe.md b/docs/cli-reference/ks_registry_describe.md index bc9c0e97..b01133f7 100644 --- a/docs/cli-reference/ks_registry_describe.md +++ b/docs/cli-reference/ks_registry_describe.md @@ -5,7 +5,6 @@ Describe a ksonnet registry and the packages it contains ### Synopsis - The `describe` command outputs documentation for the ksonnet registry identified by `<registry-name>`. Specifically, it displays the following: @@ -21,7 +20,13 @@ by `<registry-name>`. Specifically, it displays the following: ``` -ks registry describe <registry-name> +ks registry describe <registry-name> [flags] +``` + +### Options + +``` + -h, --help help for describe ``` ### Options inherited from parent commands @@ -31,5 +36,6 @@ ks registry describe <registry-name> ``` ### SEE ALSO + * [ks registry](ks_registry.md) - Manage registries for current project diff --git a/docs/cli-reference/ks_registry_list.md b/docs/cli-reference/ks_registry_list.md index 85bf64df..bac4c8bb 100644 --- a/docs/cli-reference/ks_registry_list.md +++ b/docs/cli-reference/ks_registry_list.md @@ -5,7 +5,6 @@ List all registries known to the current ksonnet app. ### Synopsis - The `list` command displays all known ksonnet registries in a table. This table includes the following info: @@ -21,7 +20,13 @@ table includes the following info: ``` -ks registry list +ks registry list [flags] +``` + +### Options + +``` + -h, --help help for list ``` ### Options inherited from parent commands @@ -31,5 +36,6 @@ ks registry list ``` ### SEE ALSO + * [ks registry](ks_registry.md) - Manage registries for current project diff --git a/docs/cli-reference/ks_show.md b/docs/cli-reference/ks_show.md index 252de9a7..d96c318a 100644 --- a/docs/cli-reference/ks_show.md +++ b/docs/cli-reference/ks_show.md @@ -5,7 +5,6 @@ Show expanded manifests for a specific environment. ### Synopsis - Show expanded manifests (resource definitions) for a specific environment. Jsonnet manifests, each defining a ksonnet component, are expanded into their JSON or YAML equivalents (YAML is the default). Any parameters in these Jsonnet @@ -28,7 +27,7 @@ manifest for that particular component. ``` -ks show <env> [-c <component-filename>] +ks show <env> [-c <component-filename>] [flags] ``` ### Examples @@ -54,6 +53,7 @@ ks show dev -c redis -c nginx-server -V, --ext-str stringSlice Values of external variables --ext-str-file stringSlice Read external variable from a file -o, --format string Output format. Supported values are: json, yaml (default "yaml") + -h, --help help for show -J, --jpath stringSlice Additional jsonnet library search path --resolve-images string Change implementation of resolveImage native function. One of: noop, registry (default "noop") --resolve-images-error string Action when resolveImage fails. One of ignore,warn,error (default "warn") @@ -68,5 +68,6 @@ ks show dev -c redis -c nginx-server ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster diff --git a/docs/cli-reference/ks_validate.md b/docs/cli-reference/ks_validate.md index a931c18d..41965319 100644 --- a/docs/cli-reference/ks_validate.md +++ b/docs/cli-reference/ks_validate.md @@ -5,7 +5,6 @@ Check generated component manifests against the server's API ### Synopsis - The `validate` command checks that an application or file is compliant with the server API's Kubernetes specification. Note that this command actually communicates *with* the server for the specified `<env-name>`, so it only works if your @@ -27,7 +26,7 @@ the manifest for that particular component. ``` -ks validate <env-name> [-c <component-name>] +ks validate <env-name> [-c <component-name>] [flags] ``` ### Examples @@ -59,6 +58,7 @@ ksonnet validate prod -c redis --context string The name of the kubeconfig context to use -V, --ext-str stringSlice Values of external variables --ext-str-file stringSlice Read external variable from a file + -h, --help help for validate --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure -J, --jpath stringSlice Additional jsonnet library search path --kubeconfig string Path to a kubeconfig file. Alternative to env var $KUBECONFIG. @@ -82,5 +82,6 @@ ksonnet validate prod -c redis ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster diff --git a/docs/cli-reference/ks_version.md b/docs/cli-reference/ks_version.md index ced07b4f..e0a361ea 100644 --- a/docs/cli-reference/ks_version.md +++ b/docs/cli-reference/ks_version.md @@ -5,7 +5,6 @@ Print version information for this ksonnet binary ### Synopsis - The `version` command prints out version info about the current ksonnet CLI, as well as for any of its helper libraries (e.g. `client-go`). @@ -13,7 +12,13 @@ as well as for any of its helper libraries (e.g. `client-go`). ``` -ks version +ks version [flags] +``` + +### Options + +``` + -h, --help help for version ``` ### Options inherited from parent commands @@ -23,5 +28,6 @@ ks version ``` ### SEE ALSO + * [ks](ks.md) - Configure your application to deploy to a Kubernetes cluster diff --git a/vendor/github.com/spf13/cobra/.travis.yml b/vendor/github.com/spf13/cobra/.travis.yml index cb2bf0d5..68efa136 100644 --- a/vendor/github.com/spf13/cobra/.travis.yml +++ b/vendor/github.com/spf13/cobra/.travis.yml @@ -2,8 +2,8 @@ language: go matrix: include: - - go: 1.7.5 - - go: 1.8.1 + - go: 1.7.6 + - go: 1.8.3 - go: tip allow_failures: - go: tip diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index b45f401e..851fcc08 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -19,13 +19,34 @@ Many of the most widely used Go projects are built using Cobra including: * [GiantSwarm's swarm](https://github.com/giantswarm/cli) * [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) [](https://travis-ci.org/spf13/cobra) [](https://circleci.com/gh/spf13/cobra) [](https://godoc.org/github.com/spf13/cobra) - +# Table of Contents + +- [Overview](#overview) +- [Concepts](#concepts) + * [Commands](#commands) + * [Flags](#flags) +- [Installing](#installing) +- [Getting Started](#getting-started) + * [Using the Cobra Generator](#using-the-cobra-generator) + * [Using the Cobra Library](#using-the-cobra-library) + * [Working with Flags](#working-with-flags) + * [Positional and Custom Arguments](#positional-and-custom-arguments) + * [Example](#example) + * [Help Command](#help-command) + * [Usage Message](#usage-message) + * [PreRun and PostRun Hooks](#prerun-and-postrun-hooks) + * [Suggestions when "unknown command" happens](#suggestions-when-unknown-command-happens) + * [Generating documentation for your command](#generating-documentation-for-your-command) + * [Generating bash completions](#generating-bash-completions) +- [Contributing](#contributing) +- [License](#license) # Overview @@ -43,7 +64,6 @@ Cobra provides: * Easy generation of applications & commands with `cobra init appname` & `cobra add cmdname` * Intelligent suggestions (`app srver`... did you mean `app server`?) * Automatic help generation for commands and flags -* Automatic detailed help for `app help [command]` * Automatic help flag recognition of `-h`, `--help`, etc. * Automatically generated bash autocomplete for your application * Automatically generated man pages for your application @@ -51,16 +71,6 @@ Cobra provides: * The flexibility to define your own help, usage, etc. * Optional tight integration with [viper](http://github.com/spf13/viper) for 12-factor apps -Cobra has an exceptionally clean interface and simple design without needless -constructors or initialization methods. - -Applications built with Cobra commands are designed to be as user-friendly as -possible. Flags can be placed before or after the command (as long as a -confusing space isn’t provided). Both short and long flags can be used. A -command need not even be fully typed. Help is automatically generated and -available for the application or for a specific command using either the help -command or the `--help` flag. - # Concepts Cobra is built on a structure of commands, arguments & flags. @@ -93,20 +103,11 @@ have children commands and optionally run an action. In the example above, 'server' is the command. -A Command has the following structure: - -```go -type Command struct { - Use string // The one-line usage message. - Short string // The short description shown in the 'help' output. - Long string // The long message shown in the 'help <this-command>' output. - Run func(cmd *Command, args []string) // Run runs the command. -} -``` +[More about cobra.Command](https://godoc.org/github.com/spf13/cobra#Command) ## Flags -A Flag is a way to modify the behavior of a command. Cobra supports +A flag is a way to modify the behavior of a command. Cobra supports fully POSIX-compliant flags as well as the Go [flag package](https://golang.org/pkg/flag/). A Cobra command can define flags that persist through to children commands and flags that are only available to that command. @@ -114,23 +115,15 @@ and flags that are only available to that command. In the example above, 'port' is the flag. Flag functionality is provided by the [pflag -library](https://github.com/ogier/pflag), a fork of the flag standard library +library](https://github.com/spf13/pflag), a fork of the flag standard library which maintains the same interface while adding POSIX compliance. -## Usage - -Cobra works by creating a set of commands and then organizing them into a tree. -The tree defines the structure of the application. - -Once each command is defined with its corresponding flags, then the -tree is assigned to the commander which is finally executed. - # Installing Using Cobra is easy. First, use `go get` to install the latest version -of the library. This command will install the `cobra` generator executible -along with the library: +of the library. This command will install the `cobra` generator executable +along with the library and its dependencies: - go get -v github.com/spf13/cobra/cobra + go get -u github.com/spf13/cobra/cobra Next, include Cobra in your application: @@ -140,8 +133,8 @@ import "github.com/spf13/cobra" # Getting Started -While you are welcome to provide your own organization, typically a Cobra based -application will follow the following organizational structure. +While you are welcome to provide your own organization, typically a Cobra-based +application will follow the following organizational structure: ``` ▾ appName/ @@ -153,23 +146,20 @@ application will follow the following organizational structure. main.go ``` -In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra. +In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra. ```go package main import ( - "fmt" - "os" + "fmt" + "os" - "{pathToYourApp}/cmd" + "{pathToYourApp}/cmd" ) func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + cmd.Execute() } ``` @@ -178,141 +168,89 @@ func main() { Cobra provides its own program that will create your application and add any commands you want. It's the easiest way to incorporate Cobra into your application. -In order to use the cobra command, compile it using the following command: - - go get github.com/spf13/cobra/cobra - -This will create the cobra executable under your `$GOPATH/bin` directory. - -### cobra init - -The `cobra init [yourApp]` command will create your initial application code -for you. It is a very powerful application that will populate your program with -the right structure so you can immediately enjoy all the benefits of Cobra. It -will also automatically apply the license you specify to your application. - -Cobra init is pretty smart. You can provide it a full path, or simply a path -similar to what is expected in the import. - -``` -cobra init github.com/spf13/newAppName -``` - -### cobra add - -Once an application is initialized Cobra can create additional commands for you. -Let's say you created an app and you wanted the following commands for it: - -* app serve -* app config -* app config create - -In your project directory (where your main.go file is) you would run the following: - -``` -cobra add serve -cobra add config -cobra add create -p 'configCmd' -``` - -*Note: Use camelCase (not snake_case/snake-case) for command names. -Otherwise, you will become unexpected errors. -For example, `cobra add add-user` is incorrect, but `cobra add addUser` is valid.* +[Here](https://github.com/spf13/cobra/blob/master/cobra/README.md) you can find more information about it. -Once you have run these three commands you would have an app structure that would look like: +## Using the Cobra Library -``` - ▾ app/ - ▾ cmd/ - serve.go - config.go - create.go - main.go -``` - -at this point you can run `go run main.go` and it would run your app. `go run -main.go serve`, `go run main.go config`, `go run main.go config create` along -with `go run main.go help serve`, etc would all work. - -Obviously you haven't added your own code to these yet, the commands are ready -for you to give them their tasks. Have fun. - -### Configuring the cobra generator - -The cobra generator will be easier to use if you provide a simple configuration -file which will help you eliminate providing a bunch of repeated information in -flags over and over. - -An example ~/.cobra.yaml file: - -```yaml -author: Steve Francia <spf@spf13.com> -license: MIT -``` - -You can specify no license by setting `license` to `none` or you can specify -a custom license: - -```yaml -license: - header: This file is part of {{ .appName }}. - text: | - {{ .copyright }} - - This is my license. There are many like it, but this one is mine. - My license is my best friend. It is my life. I must master it as I must - master my life. -``` - -You can also use built-in licenses. For example, **GPLv2**, **GPLv3**, **LGPL**, -**AGPL**, **MIT**, **2-Clause BSD** or **3-Clause BSD**. - -## Manually implementing Cobra - -To manually implement cobra you need to create a bare main.go file and a RootCmd file. +To manually implement Cobra you need to create a bare main.go file and a rootCmd file. You will optionally provide additional commands as you see fit. -### Create the root command - -The root command represents your binary itself. - - -#### Manually create rootCmd +### Create rootCmd 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{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with +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 love by spf13 and friends in Go. Complete documentation is available at http://hugo.spf13.com`, - Run: func(cmd *cobra.Command, args []string) { - // Do Stuff Here - }, + Run: func(cmd *cobra.Command, args []string) { + // 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. -for example cmd/root.go: +For example cmd/root.go: ```go +import ( + "fmt" + "os" + + homedir "github.com/mitchellh/go-homedir" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + func init() { - cobra.OnInitialize(initConfig) - RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") - 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") + 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")) + viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>") + viper.SetDefault("license", "apache") +} + +func initConfig() { + // Don't forget to read config either from cfgFile or from home directory! + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".cobra" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".cobra") + } + + if err := viper.ReadInConfig(); err != nil { + fmt.Println("Can't read config:", err) + os.Exit(1) + } } ``` @@ -327,21 +265,17 @@ In a Cobra app, typically the main.go file is very bare. It serves, one purpose, package main import ( - "fmt" - "os" + "fmt" + "os" - "{pathToYourApp}/cmd" + "{pathToYourApp}/cmd" ) func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + cmd.Execute() } ``` - ### Create additional commands Additional commands can be defined and typically are each given their own file @@ -354,48 +288,25 @@ populate it with the following: package cmd import ( - "github.com/spf13/cobra" - "fmt" + "fmt" + + "github.com/spf13/cobra" ) func init() { - RootCmd.AddCommand(versionCmd) + rootCmd.AddCommand(versionCmd) } var versionCmd = &cobra.Command{ - Use: "version", - Short: "Print the version number of Hugo", - Long: `All software has versions. This is Hugo's`, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") - }, + Use: "version", + Short: "Print the version number of Hugo", + Long: `All software has versions. This is Hugo's`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") + }, } ``` -### Attach command to its parent - - -If you notice in the above example we attach the command to its parent. In -this case the parent is the rootCmd. In this example we are attaching it to the -root, but commands can be attached at any level. - -```go -RootCmd.AddCommand(versionCmd) -``` - -### Remove a command from its parent - -Removing a command is not a common action in simple programs, but it allows 3rd -parties to customize an existing command tree. - -In this example, we remove the existing `VersionCmd` command of an existing -root command, and we replace it with our own version: - -```go -mainlib.RootCmd.RemoveCommand(mainlib.VersionCmd) -mainlib.RootCmd.AddCommand(versionCmd) -``` - ## Working with Flags Flags provide modifiers to control how the action command operates. @@ -420,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 @@ -428,9 +339,83 @@ 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 +parse local flags on each command before executing the target command. + +```go +command := cobra.Command{ + Use: "print [OPTIONS] [COMMANDS]", + TraverseChildren: true, +} +``` + +### Bind Flags with Config + +You can also bind your flags with [viper](https://github.com/spf13/viper): +```go +var author string + +func init() { + rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution") + viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) +} +``` + +In this example the persistent flag `author` is bound with `viper`. +**Note**, that the variable `author` will not be set to the value from config, +when the `--author` flag is not provided by user. + +More in [viper documentation](https://github.com/spf13/viper#working-with-flags). + +### 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 +of `Command`. + +The following validators are built in: + +- `NoArgs` - the command will report an error if there are any positional args. +- `ArbitraryArgs` - the command will accept any args. +- `OnlyValidArgs` - the command will report an error if there are any positional args that are not in the `ValidArgs` field of `Command`. +- `MinimumNArgs(int)` - the command will report an error if there are not at least N positional args. +- `MaximumNArgs(int)` - the command will report an error if there are more than N positional args. +- `ExactArgs(int)` - the command will report an error if there are not exactly N positional args. +- `RangeArgs(min, max)` - the command will report an error if the number of args is not between the minimum and maximum number of expected args. + +An example of setting the custom validator: + +```go +var cmd = &cobra.Command{ + Short: "hello", + Args: func(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return errors.New("requires at least one arg") + } + if myapp.IsValidColor(args[0]) { + return nil + } + return fmt.Errorf("invalid color specified: %s", args[0]) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Hello, World!") + }, +} +``` ## Example @@ -447,62 +432,62 @@ More documentation about flags is available at https://github.com/spf13/pflag package main import ( - "fmt" - "strings" + "fmt" + "strings" - "github.com/spf13/cobra" + "github.com/spf13/cobra" ) func main() { - - var echoTimes int - - var cmdPrint = &cobra.Command{ - Use: "print [string to print]", - Short: "Print anything to the screen", - Long: `print is for printing anything back to the screen. - For many years people have printed back to the screen. - `, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } - - var cmdEcho = &cobra.Command{ - Use: "echo [string to echo]", - Short: "Echo anything to the screen", - Long: `echo is for echoing anything back. - Echo works a lot like print, except it has a child command. - `, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } - - var cmdTimes = &cobra.Command{ - Use: "times [# times] [string to echo]", - Short: "Echo anything to the screen more times", - Long: `echo things multiple times back to the user by providing - a count and a string.`, - Run: func(cmd *cobra.Command, args []string) { - for i := 0; i < echoTimes; i++ { - fmt.Println("Echo: " + strings.Join(args, " ")) - } - }, - } - - cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") - - var rootCmd = &cobra.Command{Use: "app"} - rootCmd.AddCommand(cmdPrint, cmdEcho) - cmdEcho.AddCommand(cmdTimes) - rootCmd.Execute() + var echoTimes int + + var cmdPrint = &cobra.Command{ + Use: "print [string to print]", + Short: "Print anything to the screen", + Long: `print is for printing anything back to the screen. +For many years people have printed back to the screen.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Print: " + strings.Join(args, " ")) + }, + } + + var cmdEcho = &cobra.Command{ + Use: "echo [string to echo]", + Short: "Echo anything to the screen", + Long: `echo is for echoing anything back. +Echo works a lot like print, except it has a child command.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Print: " + strings.Join(args, " ")) + }, + } + + var cmdTimes = &cobra.Command{ + Use: "times [# times] [string to echo]", + Short: "Echo anything to the screen more times", + Long: `echo things multiple times back to the user by providing +a count and a string.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + for i := 0; i < echoTimes; i++ { + fmt.Println("Echo: " + strings.Join(args, " ")) + } + }, + } + + cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") + + var rootCmd = &cobra.Command{Use: "app"} + rootCmd.AddCommand(cmdPrint, cmdEcho) + cmdEcho.AddCommand(cmdTimes) + rootCmd.Execute() } ``` For a more complete example of a larger application, please checkout [Hugo](http://gohugo.io/). -## The Help Command +## Help Command Cobra automatically adds a help command to your application when you have subcommands. This will be called when a user runs 'app help'. Additionally, help will also @@ -515,60 +500,28 @@ create' is called. Every command will automatically have the '--help' flag adde The following output is automatically generated by Cobra. Nothing beyond the command and flag definitions are needed. - > hugo help - - hugo is the main command, used to build your Hugo site. + $ cobra help - Hugo is a Fast and Flexible Static Site Generator - built with love by spf13 and friends in Go. - - Complete documentation is available at http://gohugo.io/. + Cobra is a CLI library for Go that empowers applications. + This application is a tool to generate the needed files + to quickly create a Cobra application. Usage: - hugo [flags] - hugo [command] + cobra [command] Available Commands: - server Hugo runs its own webserver to render the files - version Print the version number of Hugo - config Print the site configuration - check Check content in the source directory - benchmark Benchmark hugo by building a site a number of times. - convert Convert your content to different formats - new Create new content for your site - list Listing out various types of content - undraft Undraft changes the content's draft status from 'True' to 'False' - genautocomplete Generate shell autocompletion script for Hugo - gendoc Generate Markdown documentation for the Hugo CLI. - genman Generate man page for Hugo - import Import your site from others. + add Add a command to a Cobra Application + help Help about any command + init Initialize a Cobra Application Flags: - -b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/ - -D, --buildDrafts[=false]: include content marked as draft - -F, --buildFuture[=false]: include content with publishdate in the future - --cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/ - --canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL - --config="": config file (default is path/config.yaml|json|toml) - -d, --destination="": filesystem path to write files to - --disableRSS[=false]: Do not build RSS files - --disableSitemap[=false]: Do not build Sitemap file - --editor="": edit new content with this editor, if provided - --ignoreCache[=false]: Ignores the cache directory for reading but still writes to it - --log[=false]: Enable Logging - --logFile="": Log File path (if set, logging enabled automatically) - --noTimes[=false]: Don't sync modification time of files - --pluralizeListTitles[=true]: Pluralize titles in lists using inflect - --preserveTaxonomyNames[=false]: Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu") - -s, --source="": filesystem path to read files relative from - --stepAnalysis[=false]: display memory and timing of different steps of the program - -t, --theme="": theme to use (located in /themes/THEMENAME/) - --uglyURLs[=false]: if true, use /filename.html instead of /filename/ - -v, --verbose[=false]: verbose output - --verboseLog[=false]: verbose logging - -w, --watch[=false]: watch filesystem for changes and recreate as needed - - Use "hugo [command] --help" for more information about a command. + -a, --author string author name for copyright attribution (default "YOUR NAME") + --config string config file (default is $HOME/.cobra.yaml) + -h, --help help for cobra + -l, --license string name of license for the project + --viper use Viper for configuration (default true) + + Use "cobra [command] --help" for more information about a command. Help is just a command like any other. There is no special logic or behavior @@ -576,38 +529,18 @@ around it. In fact, you can provide your own if you want. ### Defining your own help -You can provide your own Help command or your own template for the default command to use. - -The default help command is - -```go -func (c *Command) initHelp() { - if c.helpCommand == nil { - c.helpCommand = &Command{ - Use: "help [command]", - Short: "Help about any command", - Long: `Help provides help for any command in the application. - Simply type ` + c.Name() + ` help [path to command] for full details.`, - Run: c.HelpFunc(), - } - } - c.AddCommand(c.helpCommand) -} -``` - -You can provide your own command, function or template through the following methods: +You can provide your own Help command or your own template for the default command to use +with following functions: ```go -command.SetHelpCommand(cmd *Command) - -command.SetHelpFunc(f func(*Command, []string)) - -command.SetHelpTemplate(s string) +cmd.SetHelpCommand(cmd *Command) +cmd.SetHelpFunc(f func(*Command, []string)) +cmd.SetHelpTemplate(s string) ``` The latter two will also apply to any children commands. -## Usage +## Usage Message When the user provides an invalid flag or invalid command, Cobra responds by showing the user the 'usage'. @@ -616,71 +549,42 @@ showing the user the 'usage'. You may recognize this from the help above. That's because the default help embeds the usage as part of its output. + $ cobra --invalid + Error: unknown flag: --invalid Usage: - hugo [flags] - hugo [command] + cobra [command] Available Commands: - server Hugo runs its own webserver to render the files - version Print the version number of Hugo - config Print the site configuration - check Check content in the source directory - benchmark Benchmark hugo by building a site a number of times. - convert Convert your content to different formats - new Create new content for your site - list Listing out various types of content - undraft Undraft changes the content's draft status from 'True' to 'False' - genautocomplete Generate shell autocompletion script for Hugo - gendoc Generate Markdown documentation for the Hugo CLI. - genman Generate man page for Hugo - import Import your site from others. + add Add a command to a Cobra Application + help Help about any command + init Initialize a Cobra Application Flags: - -b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/ - -D, --buildDrafts[=false]: include content marked as draft - -F, --buildFuture[=false]: include content with publishdate in the future - --cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/ - --canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL - --config="": config file (default is path/config.yaml|json|toml) - -d, --destination="": filesystem path to write files to - --disableRSS[=false]: Do not build RSS files - --disableSitemap[=false]: Do not build Sitemap file - --editor="": edit new content with this editor, if provided - --ignoreCache[=false]: Ignores the cache directory for reading but still writes to it - --log[=false]: Enable Logging - --logFile="": Log File path (if set, logging enabled automatically) - --noTimes[=false]: Don't sync modification time of files - --pluralizeListTitles[=true]: Pluralize titles in lists using inflect - --preserveTaxonomyNames[=false]: Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu") - -s, --source="": filesystem path to read files relative from - --stepAnalysis[=false]: display memory and timing of different steps of the program - -t, --theme="": theme to use (located in /themes/THEMENAME/) - --uglyURLs[=false]: if true, use /filename.html instead of /filename/ - -v, --verbose[=false]: verbose output - --verboseLog[=false]: verbose logging - -w, --watch[=false]: watch filesystem for changes and recreate as needed + -a, --author string author name for copyright attribution (default "YOUR NAME") + --config string config file (default is $HOME/.cobra.yaml) + -h, --help help for cobra + -l, --license string name of license for the project + --viper use Viper for configuration (default true) + + Use "cobra [command] --help" for more information about a command. ### Defining your own usage You can provide your own usage function or template for Cobra to use. - -The default usage function is: +Like help, the function and template are overridable through public methods: ```go -return func(c *Command) error { - err := tmpl(c.Out(), c.UsageTemplate(), c) - return err -} +cmd.SetUsageFunc(f func(*Command) error) +cmd.SetUsageTemplate(s string) ``` -Like help, the function and template are overridable through public methods: +## Version Flag -```go -command.SetUsageFunc(f func(*Command) error) - -command.SetUsageTemplate(s string) -``` +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 or 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: @@ -696,105 +600,73 @@ An example of two commands which use all of these features is below. When the s package main import ( - "fmt" + "fmt" - "github.com/spf13/cobra" + "github.com/spf13/cobra" ) func main() { - var rootCmd = &cobra.Command{ - Use: "root [sub]", - Short: "My root command", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) - }, - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) - }, - } - - var subCmd = &cobra.Command{ - Use: "sub [no options!]", - Short: "My subcommand", - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) - }, - } - - rootCmd.AddCommand(subCmd) - - rootCmd.SetArgs([]string{""}) - _ = rootCmd.Execute() - fmt.Print("\n") - rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) - _ = rootCmd.Execute() + var rootCmd = &cobra.Command{ + Use: "root [sub]", + Short: "My root command", + PersistentPreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) + }, + PreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd Run with args: %v\n", args) + }, + PostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) + }, + PersistentPostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) + }, + } + + var subCmd = &cobra.Command{ + Use: "sub [no options!]", + Short: "My subcommand", + PreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PreRun with args: %v\n", args) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd Run with args: %v\n", args) + }, + PostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PostRun with args: %v\n", args) + }, + PersistentPostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) + }, + } + + rootCmd.AddCommand(subCmd) + + rootCmd.SetArgs([]string{""}) + rootCmd.Execute() + fmt.Println() + rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) + rootCmd.Execute() } ``` +Output: +``` +Inside rootCmd PersistentPreRun with args: [] +Inside rootCmd PreRun with args: [] +Inside rootCmd Run with args: [] +Inside rootCmd PostRun with args: [] +Inside rootCmd PersistentPostRun with args: [] -## Alternative Error Handling - -Cobra also has functions where the return signature is an error. This allows for errors to bubble up to the top, -providing a way to handle the errors in one location. The current list of functions that return an error is: - -* PersistentPreRunE -* PreRunE -* RunE -* PostRunE -* PersistentPostRunE - -If you would like to silence the default `error` and `usage` output in favor of your own, you can set `SilenceUsage` -and `SilenceErrors` to `true` on the command. A child command respects these flags if they are set on the parent -command. - -**Example Usage using RunE:** - -```go -package main - -import ( - "errors" - "log" - - "github.com/spf13/cobra" -) - -func main() { - 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 - love by spf13 and friends in Go. - Complete documentation is available at http://hugo.spf13.com`, - RunE: func(cmd *cobra.Command, args []string) error { - // Do Stuff Here - return errors.New("some random error") - }, - } - - if err := rootCmd.Execute(); err != nil { - log.Fatal(err) - } -} +Inside rootCmd PersistentPreRun with args: [arg1 arg2] +Inside subCmd PreRun with args: [arg1 arg2] +Inside subCmd Run with args: [arg1 arg2] +Inside subCmd PostRun with args: [arg1 arg2] +Inside subCmd PersistentPostRun with args: [arg1 arg2] ``` ## Suggestions when "unknown command" happens @@ -837,51 +709,28 @@ Did you mean this? Run 'kubectl help' for usage. ``` -## Generating Markdown-formatted documentation for your command +## Generating documentation for your command -Cobra can generate a Markdown-formatted document based on the subcommands, flags, etc. A simple example of how to do this for your command can be found in [Markdown Docs](doc/md_docs.md). +Cobra can generate documentation based on subcommands, flags, etc. in the following formats: -## Generating man pages for your command +- [Markdown](doc/md_docs.md) +- [ReStructured Text](doc/rest_docs.md) +- [Man Page](doc/man_docs.md) -Cobra can generate a man page based on the subcommands, flags, etc. A simple example of how to do this for your command can be found in [Man Docs](doc/man_docs.md). - -## Generating bash completions for your command +## Generating bash completions Cobra can generate a bash-completion file. If you add more information to your command, these completions can be amazingly powerful and flexible. Read more about it in [Bash Completions](bash_completions.md). -## Debugging - -Cobra provides a ‘DebugFlags’ method on a command which, when called, will print -out everything Cobra knows about the flags for each command. - -### Example - -```go -command.DebugFlags() -``` - -## Extensions - -Libraries for extending Cobra: - -* [cmdns](https://github.com/gosuri/cmdns): Enables name spacing a command's immediate children. It provides an alternative way to structure subcommands, similar to `heroku apps:create` and `ovrclk clusters:launch`. - -## Contributing +# Contributing 1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request - -## Contributors - -Names in no particular order: - -* [spf13](https://github.com/spf13), -[eparis](https://github.com/eparis), -[bep](https://github.com/bep), and many more! - -## License +2. Download your fork to your PC (`git clone https://github.com/your_username/cobra && cd cobra`) +3. Create your feature branch (`git checkout -b my-new-feature`) +4. Make changes and add them (`git add .`) +5. Commit your changes (`git commit -m 'Add some feature'`) +6. Push to the branch (`git push origin my-new-feature`) +7. Create new pull request + +# License Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt) diff --git a/vendor/github.com/spf13/cobra/args.go b/vendor/github.com/spf13/cobra/args.go new file mode 100644 index 00000000..a5d8a927 --- /dev/null +++ b/vendor/github.com/spf13/cobra/args.go @@ -0,0 +1,89 @@ +package cobra + +import ( + "fmt" +) + +type PositionalArgs func(cmd *Command, args []string) error + +// Legacy arg validation has the following behaviour: +// - root commands with no subcommands can take arbitrary arguments +// - root commands with subcommands will do subcommand validity checking +// - subcommands will always accept arbitrary arguments +func legacyArgs(cmd *Command, args []string) error { + // no subcommand, always take args + if !cmd.HasSubCommands() { + return nil + } + + // root command with subcommands, do subcommand checking. + if !cmd.HasParent() && len(args) > 0 { + return fmt.Errorf("unknown command %q for %q%s", args[0], cmd.CommandPath(), cmd.findSuggestions(args[0])) + } + return nil +} + +// NoArgs returns an error if any args are included. +func NoArgs(cmd *Command, args []string) error { + if len(args) > 0 { + return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath()) + } + return nil +} + +// OnlyValidArgs returns an error if any args are not in the list of ValidArgs. +func OnlyValidArgs(cmd *Command, args []string) error { + if len(cmd.ValidArgs) > 0 { + for _, v := range args { + if !stringInSlice(v, cmd.ValidArgs) { + return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0])) + } + } + } + return nil +} + +// ArbitraryArgs never returns an error. +func ArbitraryArgs(cmd *Command, args []string) error { + return nil +} + +// MinimumNArgs returns an error if there is not at least N args. +func MinimumNArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) < n { + return fmt.Errorf("requires at least %d arg(s), only received %d", n, len(args)) + } + return nil + } +} + +// MaximumNArgs returns an error if there are more than N args. +func MaximumNArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) > n { + return fmt.Errorf("accepts at most %d arg(s), received %d", n, len(args)) + } + return nil + } +} + +// ExactArgs returns an error if there are not exactly n args. +func ExactArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) != n { + return fmt.Errorf("accepts %d arg(s), received %d", n, len(args)) + } + return nil + } +} + +// RangeArgs returns an error if the number of args is not within the expected range. +func RangeArgs(min int, max int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) < min || len(args) > max { + return fmt.Errorf("accepts between %d and %d arg(s), received %d", min, max, len(args)) + } + return nil + } +} diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go index a0d04027..d898630b 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.go +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -1,6 +1,7 @@ package cobra import ( + "bytes" "fmt" "io" "os" @@ -18,13 +19,10 @@ const ( BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir" ) -func preamble(out io.Writer, name string) error { - _, err := fmt.Fprintf(out, "# bash completion for %-36s -*- shell-script -*-\n", name) - if err != nil { - return err - } - preamStr := ` -__debug() +func writePreamble(buf *bytes.Buffer, name string) { + buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name)) + buf.WriteString(fmt.Sprintf(` +__%[1]s_debug() { if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then echo "$*" >> "${BASH_COMP_DEBUG_FILE}" @@ -33,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 @@ -51,7 +49,7 @@ __index_of_word() index=-1 } -__contains_word() +__%[1]s_contains_word() { local w word=$1; shift for w in "$@"; do @@ -60,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 @@ -87,14 +85,14 @@ __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="" cur="${cur#*=}" ${flags_completion[${index}]} if [ -n "${ZSH_VERSION}" ]; then - # zfs completion needs --flag= prefix + # zsh completion needs --flag= prefix eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )" fi fi @@ -105,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 @@ -134,25 +132,34 @@ __handle_reply() declare -F __custom_func >/dev/null && __custom_func fi - __ltrim_colon_completions "$cur" + # available in bash-completion >= 2, not always present on macOS + if declare -F __ltrim_colon_completions >/dev/null; then + __ltrim_colon_completions "$cur" + fi + + # 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" -__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]} @@ -163,27 +170,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 @@ -195,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=() - elif __contains_word "${words[c]}" "${noun_aliases[@]}"; then + elif __%[1]s_contains_word "${words[c]}" "${noun_aliases[@]}"; then must_have_one_noun=() fi @@ -209,62 +219,57 @@ __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 next_command="_${last_command}_${words[c]//:/__}" else if [[ $c -eq 0 ]]; then - next_command="_$(basename "${words[c]//:/__}")" + next_command="_%[1]s_root_command" else next_command="_${words[c]//:/__}" 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 ]]; then + __%[1]s_handle_command else - __handle_noun + __%[1]s_handle_noun fi - __handle_word + __%[1]s_handle_word } -` - _, err = fmt.Fprint(out, preamStr) - return err +`, name)) } -func postscript(w io.Writer, name string) error { +func writePostscript(buf *bytes.Buffer, name string) { name = strings.Replace(name, ":", "__", -1) - _, err := fmt.Fprintf(w, "__start_%s()\n", name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, `{ + buf.WriteString(fmt.Sprintf("__start_%s()\n", name)) + buf.WriteString(fmt.Sprintf(`{ local cur prev words cword declare -A flaghash 2>/dev/null || : if declare -F _init_completion >/dev/null 2>&1; then _init_completion -s || return else - __my_init_completion -n "=" || return + __%[1]s_init_completion -n "=" || return fi local c=0 @@ -273,206 +278,141 @@ func postscript(w io.Writer, name string) error { 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) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, `if [[ $(type -t compopt) = "builtin" ]]; then +`, name)) + buf.WriteString(fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then complete -o default -F __start_%s %s else complete -o default -o nospace -F __start_%s %s fi -`, name, name, name, name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, "# ex: ts=4 sw=4 et filetype=sh\n") - return err +`, name, name, name, name)) + buf.WriteString("# ex: ts=4 sw=4 et filetype=sh\n") } -func writeCommands(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " commands=()\n"); err != nil { - return err - } +func writeCommands(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" commands=()\n") for _, c := range cmd.Commands() { if !c.IsAvailableCommand() || c == cmd.helpCommand { continue } - if _, err := fmt.Fprintf(w, " commands+=(%q)\n", c.Name()); err != nil { - return err - } + buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name())) } - _, err := fmt.Fprintf(w, "\n") - return err + buf.WriteString("\n") } -func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) error { +func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string, cmd *Command) { for key, value := range annotations { switch key { case BashCompFilenameExt: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) - if err != nil { - return err - } + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + var ext string if len(value) > 0 { - ext := "__handle_filename_extension_flag " + strings.Join(value, "|") - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) + ext = fmt.Sprintf("__%s_handle_filename_extension_flag ", cmd.Name()) + strings.Join(value, "|") } else { - ext := "_filedir" - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) - } - if err != nil { - return err + ext = "_filedir" } + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext)) case BashCompCustom: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) - if err != nil { - return err - } + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) if len(value) > 0 { handlers := strings.Join(value, "; ") - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", handlers) + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", handlers)) } else { - _, err = fmt.Fprintf(w, " flags_completion+=(:)\n") - } - if err != nil { - return err + buf.WriteString(" flags_completion+=(:)\n") } case BashCompSubdirsInDir: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + var ext string if len(value) == 1 { - ext := "__handle_subdirs_in_dir_flag " + value[0] - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) + ext = fmt.Sprintf("__%s_handle_subdirs_in_dir_flag ", cmd.Name()) + value[0] } else { - ext := "_filedir -d" - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) - } - if err != nil { - return err + ext = "_filedir -d" } + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext)) } } - return nil } -func writeShortFlag(flag *pflag.Flag, w io.Writer) error { - b := (len(flag.NoOptDefVal) > 0) +func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) { name := flag.Shorthand format := " " - if !b { + if len(flag.NoOptDefVal) == 0 { format += "two_word_" } format += "flags+=(\"-%s\")\n" - if _, err := fmt.Fprintf(w, format, name); err != nil { - return err - } - return writeFlagHandler("-"+name, flag.Annotations, w) + buf.WriteString(fmt.Sprintf(format, name)) + writeFlagHandler(buf, "-"+name, flag.Annotations, cmd) } -func writeFlag(flag *pflag.Flag, w io.Writer) error { - b := (len(flag.NoOptDefVal) > 0) +func writeFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) { name := flag.Name format := " flags+=(\"--%s" - if !b { + if len(flag.NoOptDefVal) == 0 { format += "=" } format += "\")\n" - if _, err := fmt.Fprintf(w, format, name); err != nil { - return err - } - return writeFlagHandler("--"+name, flag.Annotations, w) + buf.WriteString(fmt.Sprintf(format, name)) + writeFlagHandler(buf, "--"+name, flag.Annotations, cmd) } -func writeLocalNonPersistentFlag(flag *pflag.Flag, w io.Writer) error { - b := (len(flag.NoOptDefVal) > 0) +func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) { name := flag.Name format := " local_nonpersistent_flags+=(\"--%s" - if !b { + if len(flag.NoOptDefVal) == 0 { format += "=" } format += "\")\n" - _, err := fmt.Fprintf(w, format, name) - return err + buf.WriteString(fmt.Sprintf(format, name)) } -func writeFlags(cmd *Command, w io.Writer) error { - _, err := fmt.Fprintf(w, ` flags=() +func writeFlags(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(` flags=() two_word_flags=() local_nonpersistent_flags=() flags_with_completion=() flags_completion=() `) - if err != nil { - return err - } localNonPersistentFlags := cmd.LocalNonPersistentFlags() - var visitErr error cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { if nonCompletableFlag(flag) { return } - if err := writeFlag(flag, w); err != nil { - visitErr = err - return - } + writeFlag(buf, flag, cmd) if len(flag.Shorthand) > 0 { - if err := writeShortFlag(flag, w); err != nil { - visitErr = err - return - } + writeShortFlag(buf, flag, cmd) } if localNonPersistentFlags.Lookup(flag.Name) != nil { - if err := writeLocalNonPersistentFlag(flag, w); err != nil { - visitErr = err - return - } + writeLocalNonPersistentFlag(buf, flag) } }) - if visitErr != nil { - return visitErr - } cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { if nonCompletableFlag(flag) { return } - if err := writeFlag(flag, w); err != nil { - visitErr = err - return - } + writeFlag(buf, flag, cmd) if len(flag.Shorthand) > 0 { - if err := writeShortFlag(flag, w); err != nil { - visitErr = err - return - } + writeShortFlag(buf, flag, cmd) } }) - if visitErr != nil { - return visitErr - } - _, err = fmt.Fprintf(w, "\n") - return err + buf.WriteString("\n") } -func writeRequiredFlag(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " must_have_one_flag=()\n"); err != nil { - return err - } +func writeRequiredFlag(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" must_have_one_flag=()\n") flags := cmd.NonInheritedFlags() - var visitErr error flags.VisitAll(func(flag *pflag.Flag) { if nonCompletableFlag(flag) { return @@ -481,107 +421,74 @@ func writeRequiredFlag(cmd *Command, w io.Writer) error { switch key { case BashCompOneRequiredFlag: format := " must_have_one_flag+=(\"--%s" - b := (flag.Value.Type() == "bool") - if !b { + if flag.Value.Type() != "bool" { format += "=" } format += "\")\n" - if _, err := fmt.Fprintf(w, format, flag.Name); err != nil { - visitErr = err - return - } + buf.WriteString(fmt.Sprintf(format, flag.Name)) if len(flag.Shorthand) > 0 { - if _, err := fmt.Fprintf(w, " must_have_one_flag+=(\"-%s\")\n", flag.Shorthand); err != nil { - visitErr = err - return - } + buf.WriteString(fmt.Sprintf(" must_have_one_flag+=(\"-%s\")\n", flag.Shorthand)) } } } }) - return visitErr } -func writeRequiredNouns(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil { - return err - } +func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" must_have_one_noun=()\n") sort.Sort(sort.StringSlice(cmd.ValidArgs)) for _, value := range cmd.ValidArgs { - if _, err := fmt.Fprintf(w, " must_have_one_noun+=(%q)\n", value); err != nil { - return err - } + buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value)) } - return nil } -func writeArgAliases(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " noun_aliases=()\n"); err != nil { - return err - } +func writeArgAliases(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" noun_aliases=()\n") sort.Sort(sort.StringSlice(cmd.ArgAliases)) for _, value := range cmd.ArgAliases { - if _, err := fmt.Fprintf(w, " noun_aliases+=(%q)\n", value); err != nil { - return err - } + buf.WriteString(fmt.Sprintf(" noun_aliases+=(%q)\n", value)) } - return nil } -func gen(cmd *Command, w io.Writer) error { +func gen(buf *bytes.Buffer, cmd *Command) { for _, c := range cmd.Commands() { if !c.IsAvailableCommand() || c == cmd.helpCommand { continue } - if err := gen(c, w); err != nil { - return err - } + gen(buf, c) } commandName := cmd.CommandPath() commandName = strings.Replace(commandName, " ", "_", -1) commandName = strings.Replace(commandName, ":", "__", -1) - if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil { - return err - } - if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil { - return err - } - if err := writeCommands(cmd, w); err != nil { - return err - } - if err := writeFlags(cmd, w); err != nil { - return err - } - if err := writeRequiredFlag(cmd, w); err != nil { - return err - } - if err := writeRequiredNouns(cmd, w); err != nil { - return err - } - if err := writeArgAliases(cmd, w); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "}\n\n"); err != nil { - return err + + if cmd.Root() == cmd { + buf.WriteString(fmt.Sprintf("_%s_root_command()\n{\n", commandName)) + } else { + buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName)) } - return nil + + buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName)) + writeCommands(buf, cmd) + writeFlags(buf, cmd) + writeRequiredFlag(buf, cmd) + writeRequiredNouns(buf, cmd) + writeArgAliases(buf, cmd) + buf.WriteString("}\n\n") } // GenBashCompletion generates bash completion file and writes to the passed writer. -func (cmd *Command) GenBashCompletion(w io.Writer) error { - if err := preamble(w, cmd.Name()); err != nil { - return err - } - if len(cmd.BashCompletionFunction) > 0 { - if _, err := fmt.Fprintf(w, "%s\n", cmd.BashCompletionFunction); err != nil { - return err - } - } - if err := gen(cmd, w); err != nil { - return err +func (c *Command) GenBashCompletion(w io.Writer) error { + buf := new(bytes.Buffer) + writePreamble(buf, c.Name()) + if len(c.BashCompletionFunction) > 0 { + buf.WriteString(c.BashCompletionFunction + "\n") } - return postscript(w, cmd.Name()) + gen(buf, c) + writePostscript(buf, c.Name()) + + _, err := buf.WriteTo(w) + return err } func nonCompletableFlag(flag *pflag.Flag) bool { @@ -589,47 +496,50 @@ func nonCompletableFlag(flag *pflag.Flag) bool { } // GenBashCompletionFile generates bash completion file. -func (cmd *Command) GenBashCompletionFile(filename string) error { +func (c *Command) GenBashCompletionFile(filename string) error { outFile, err := os.Create(filename) if err != nil { return err } defer outFile.Close() - return cmd.GenBashCompletion(outFile) + return c.GenBashCompletion(outFile) } -// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists. -func (cmd *Command) MarkFlagRequired(name string) error { - return MarkFlagRequired(cmd.Flags(), name) +// 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. -func (cmd *Command) MarkPersistentFlagRequired(name string) error { - return MarkFlagRequired(cmd.PersistentFlags(), name) +// 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"}) } // MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists. // Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func (cmd *Command) MarkFlagFilename(name string, extensions ...string) error { - return MarkFlagFilename(cmd.Flags(), name, extensions...) +func (c *Command) MarkFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.Flags(), name, extensions...) } // MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. // Generated bash autocompletion will call the bash function f for the flag. -func (cmd *Command) MarkFlagCustom(name string, f string) error { - return MarkFlagCustom(cmd.Flags(), name, f) +func (c *Command) MarkFlagCustom(name string, f string) error { + return MarkFlagCustom(c.Flags(), name, f) } // MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists. // Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func (cmd *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { - return MarkFlagFilename(cmd.PersistentFlags(), name, extensions...) +func (c *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.PersistentFlags(), name, extensions...) } // MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists. diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md index 52bd39dd..691a04e1 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.md +++ b/vendor/github.com/spf13/cobra/bash_completions.md @@ -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 @@ -204,3 +204,17 @@ __kubectl_get_namespaces() fi } ``` +# Using bash aliases for commands + +You can also configure the `bash aliases` for the commands and they will also support completions. + +```bash +alias aliasname=origcommand +complete -o default -F __start_origcommand aliasname + +# and now when you run `aliasname` completion will make +# suggestions as it did for `origcommand`. + +$) aliasname <tab><tab> +completion firstcommand secondcommand +``` diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index 2726d19e..7010fd15 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -47,6 +47,15 @@ var EnablePrefixMatching = false // To disable sorting, set it to false. var EnableCommandSorting = true +// MousetrapHelpText enables an information splash screen on Windows +// if the CLI is started from explorer.exe. +// To disable the mousetrap, just set this variable to blank string (""). +// Works only on Microsoft Windows. +var MousetrapHelpText string = `This is a command line tool. + +You need to open cmd.exe and run it from there. +` + // AddTemplateFunc adds a template function that's available to Usage and Help // template generation. func AddTemplateFunc(name string, tmplFunc interface{}) { @@ -61,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...) } @@ -179,3 +189,12 @@ func ld(s, t string, ignoreCase bool) int { } return d[len(s)][len(t)] } + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/license_agpl.go b/vendor/github.com/spf13/cobra/cobra/cmd/license_agpl.go index 4ea036ed..bc22e973 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/license_agpl.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/license_agpl.go @@ -4,8 +4,7 @@ func initAgpl() { Licenses["agpl"] = License{ Name: "GNU Affero General Public License", PossibleMatches: []string{"agpl", "affero gpl", "gnu agpl"}, - Header: `{{.copyright}} - + Header: ` This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/license_apache_2.go b/vendor/github.com/spf13/cobra/cobra/cmd/license_apache_2.go index 3f330867..38393d54 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/license_apache_2.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/license_apache_2.go @@ -19,7 +19,8 @@ func initApache2() { Licenses["apache"] = License{ Name: "Apache 2.0", PossibleMatches: []string{"apache", "apache20", "apache 2.0", "apache2.0", "apache-2.0"}, - Header: `Licensed under the Apache License, Version 2.0 (the "License"); + Header: ` +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_2.go b/vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_2.go index f2982dab..4a847e04 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_2.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_2.go @@ -20,8 +20,7 @@ func initBsdClause2() { Name: "Simplified BSD License", PossibleMatches: []string{"freebsd", "simpbsd", "simple bsd", "2-clause bsd", "2 clause bsd", "simplified bsd license"}, - Header: ` -All rights reserved. + Header: `All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_3.go b/vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_3.go index 39c9571f..c7476b31 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_3.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/license_bsd_clause_3.go @@ -19,8 +19,7 @@ func initBsdClause3() { Licenses["bsd"] = License{ Name: "NewBSD", PossibleMatches: []string{"bsd", "newbsd", "3 clause bsd", "3-clause bsd"}, - Header: ` -All rights reserved. + Header: `All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_2.go b/vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_2.go index 054b470f..03e05b3a 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_2.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_2.go @@ -19,20 +19,19 @@ func initGpl2() { Licenses["gpl2"] = License{ Name: "GNU General Public License 2.0", PossibleMatches: []string{"gpl2", "gnu gpl2", "gplv2"}, - Header: `{{.copyright}} - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>.`, + Header: ` +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>.`, Text: ` GNU GENERAL PUBLIC LICENSE Version 2, June 1991 diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_3.go b/vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_3.go index d1ef656a..ce07679c 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_3.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/license_gpl_3.go @@ -19,8 +19,7 @@ func initGpl3() { Licenses["gpl3"] = License{ Name: "GNU General Public License 3.0", PossibleMatches: []string{"gpl3", "gplv3", "gpl", "gnu gpl3", "gnu gpl"}, - Header: `{{.copyright}} - + Header: ` This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/license_lgpl.go b/vendor/github.com/spf13/cobra/cobra/cmd/license_lgpl.go index 75fd043b..0f8b96ca 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/license_lgpl.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/license_lgpl.go @@ -4,8 +4,7 @@ func initLgpl() { Licenses["lgpl"] = License{ Name: "GNU Lesser General Public License", PossibleMatches: []string{"lgpl", "lesser gpl", "gnu lgpl"}, - Header: `{{.copyright}} - + Header: ` This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/license_mit.go b/vendor/github.com/spf13/cobra/cobra/cmd/license_mit.go index 4ff5a4cd..bd2d0c4f 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/license_mit.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/license_mit.go @@ -17,7 +17,7 @@ package cmd func initMit() { Licenses["mit"] = License{ - Name: "Mit", + Name: "MIT License", PossibleMatches: []string{"mit"}, Header: ` Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/licenses.go b/vendor/github.com/spf13/cobra/cobra/cmd/licenses.go index d73e6fb3..a070134d 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/licenses.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/licenses.go @@ -63,7 +63,7 @@ func getLicense() License { // If user wants to have custom license, use that. if viper.IsSet("license.header") || viper.IsSet("license.text") { return License{Header: viper.GetString("license.header"), - Text: "license.text"} + Text: viper.GetString("license.text")} } // If user wants to have built-in license, use that. @@ -77,7 +77,11 @@ func getLicense() License { func copyrightLine() string { author := viper.GetString("author") - year := time.Now().Format("2006") + + year := viper.GetString("year") // For tests. + if year == "" { + year = time.Now().Format("2006") + } return "Copyright © " + year + " " + author } diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index 9e6bdf30..29675b33 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -54,6 +54,9 @@ type Command struct { // ValidArgs is list of all valid non-flag arguments that are accepted in bash completions ValidArgs []string + // Expected arguments + Args PositionalArgs + // ArgAliases is List of aliases for ValidArgs. // These are not suggested to the user in the bash completion, // but accepted if entered manually. @@ -72,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() @@ -115,6 +123,10 @@ type Command struct { // will be printed by generating docs for this command. DisableAutoGenTag bool + // DisableFlagsInUseLine will disable the addition of [flags] to the usage + // line of a command when printing help or generating docs + DisableFlagsInUseLine bool + // DisableSuggestions disables the suggestions based on Levenshtein distance // that go along with 'unknown command' messages. DisableSuggestions bool @@ -122,8 +134,9 @@ type Command struct { // Must be > 0. SuggestionsMinimumDistance int - // name is the command name, usually the executable's name. - name string + // TraverseChildren parses flags on all parents before executing child command. + TraverseChildren bool + // commands is the list of commands supported by this program. commands []*Command // parent is a parent command for this command. @@ -134,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 @@ -169,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 @@ -214,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) { @@ -403,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 { @@ -430,37 +468,28 @@ func stripFlags(args []string, c *Command) []string { c.mergePersistentFlags() commands := []string{} - inQuote := false flags := c.Flags() Loop: for len(args) > 0 { s := args[0] args = args[1:] - if !inQuote { - switch { - case strings.HasPrefix(s, "\"") || strings.Contains(s, "=\""): - inQuote = true - case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): - // If '--flag arg' then - // delete arg from args. - fallthrough // (do the same as below) - case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): - // If '-f arg' then - // delete 'arg' from args or break the loop if len(args) <= 1. - if len(args) <= 1 { - break Loop - } else { - args = args[1:] - continue - } - case s != "" && !strings.HasPrefix(s, "-"): - commands = append(commands, s) + switch { + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + // If '--flag arg' then + // delete arg from args. + fallthrough // (do the same as below) + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // If '-f arg' then + // delete 'arg' from args or break the loop if len(args) <= 1. + if len(args) <= 1 { + break Loop + } else { + args = args[1:] + continue } - } - - if strings.HasSuffix(s, "\"") && !strings.HasSuffix(s, "\\\"") { - inQuote = false + case s != "" && !strings.HasPrefix(s, "-"): + commands = append(commands, s) } } @@ -481,13 +510,14 @@ func argsMinusFirstX(args []string, x string) []string { return args } +func isFlagArg(arg string) bool { + return ((len(arg) >= 3 && arg[1] == '-') || + (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-')) +} + // Find the target command given the args and command tree // Meant to be run on the highest node. Only searches down. func (c *Command) Find(args []string) (*Command, []string, error) { - if c == nil { - return nil, nil, fmt.Errorf("Called find() on a nil Command") - } - var innerfind func(*Command, []string) (*Command, []string) innerfind = func(c *Command, innerArgs []string) (*Command, []string) { @@ -496,57 +526,98 @@ func (c *Command) Find(args []string) (*Command, []string, error) { return c, innerArgs } nextSubCmd := argsWOflags[0] - matches := make([]*Command, 0) - for _, cmd := range c.commands { - if cmd.Name() == nextSubCmd || cmd.HasAlias(nextSubCmd) { // exact name or alias match - return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) - } - if EnablePrefixMatching { - if strings.HasPrefix(cmd.Name(), nextSubCmd) { // prefix match - matches = append(matches, cmd) - } - for _, x := range cmd.Aliases { - if strings.HasPrefix(x, nextSubCmd) { - matches = append(matches, cmd) - } - } - } - } - // only accept a single prefix match - multiple matches would be ambiguous - if len(matches) == 1 { - return innerfind(matches[0], argsMinusFirstX(innerArgs, argsWOflags[0])) + cmd := c.findNext(nextSubCmd) + if cmd != nil { + return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) } - return c, innerArgs } commandFound, a := innerfind(c, args) - argsWOflags := stripFlags(a, commandFound) + if commandFound.Args == nil { + return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound)) + } + return commandFound, a, nil +} - // no subcommand, always take args - if !commandFound.HasSubCommands() { - return commandFound, a, nil +func (c *Command) findSuggestions(arg string) string { + if c.DisableSuggestions { + return "" } + if c.SuggestionsMinimumDistance <= 0 { + c.SuggestionsMinimumDistance = 2 + } + suggestionsString := "" + if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 { + suggestionsString += "\n\nDid you mean this?\n" + for _, s := range suggestions { + suggestionsString += fmt.Sprintf("\t%v\n", s) + } + } + return suggestionsString +} - // root command with subcommands, do subcommand checking - if commandFound == c && len(argsWOflags) > 0 { - suggestionsString := "" - if !c.DisableSuggestions { - if c.SuggestionsMinimumDistance <= 0 { - c.SuggestionsMinimumDistance = 2 - } - if suggestions := c.SuggestionsFor(argsWOflags[0]); len(suggestions) > 0 { - suggestionsString += "\n\nDid you mean this?\n" - for _, s := range suggestions { - suggestionsString += fmt.Sprintf("\t%v\n", s) - } - } +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) { + matches = append(matches, cmd) } - return commandFound, a, fmt.Errorf("unknown command %q for %q%s", argsWOflags[0], commandFound.CommandPath(), suggestionsString) } - return commandFound, a, nil + if len(matches) == 1 { + return matches[0] + } + + return nil +} + +// Traverse the command tree to find the command, and parse args for +// each parent. +func (c *Command) Traverse(args []string) (*Command, []string, error) { + flags := []string{} + inFlag := false + + for i, arg := range args { + switch { + // A long flag with a space separated value + case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="): + // TODO: this isn't quite right, we should really check ahead for 'true' or 'false' + inFlag = !hasNoOptDefVal(arg[2:], c.Flags()) + flags = append(flags, arg) + continue + // A short flag with a space separated value + case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()): + inFlag = true + flags = append(flags, arg) + continue + // The value for a flag + case inFlag: + inFlag = false + flags = append(flags, arg) + continue + // A flag without a value, or with an `=` separated value + case isFlagArg(arg): + flags = append(flags, arg) + continue + } + + cmd := c.findNext(arg) + if cmd == nil { + return c, args, nil + } + + if err := c.ParseFlags(flags); err != nil { + return nil, args, err + } + return cmd.Traverse(args[i+1:]) + } + return c, args, nil } // SuggestionsFor provides suggestions for the typedName. @@ -586,10 +657,8 @@ func (c *Command) Root() *Command { return c } -// ArgsLenAtDash will return the length of f.Args at the moment when a -- was -// found during arg parsing. This allows your program to know which args were -// before the -- and which came after. (Description from -// https://godoc.org/github.com/spf13/pflag#FlagSet.ArgsLenAtDash). +// ArgsLenAtDash will return the length of c.Flags().Args at the moment +// when a -- was found during args parsing. func (c *Command) ArgsLenAtDash() int { return c.Flags().ArgsLenAtDash() } @@ -603,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 { @@ -622,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 } @@ -633,6 +723,10 @@ func (c *Command) execute(a []string) (err error) { argWoFlags = a } + if err := c.ValidateArgs(argWoFlags); err != nil { + return err + } + for p := c; p != nil; p = p.Parent() { if p.PersistentPreRunE != nil { if err := p.PersistentPreRunE(c, argWoFlags); err != nil { @@ -652,6 +746,9 @@ func (c *Command) execute(a []string) (err error) { c.PreRun(c, argWoFlags) } + if err := c.validateRequiredFlags(); err != nil { + return err + } if c.RunE != nil { if err := c.RunE(c, argWoFlags); err != nil { return err @@ -687,7 +784,7 @@ func (c *Command) preRun() { } } -// Execute Call execute to use the args (os.Args[1:] by default) +// Execute uses the args (os.Args[1:] by default) // and run through the command tree finding appropriate matches // for commands and then corresponding flags. func (c *Command) Execute() error { @@ -709,7 +806,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { // initialize help as the last point possible to allow for user // overriding - c.initHelpCmd() + c.InitDefaultHelpCmd() var args []string @@ -720,7 +817,12 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { args = c.args } - cmd, flags, err := c.Find(args) + var flags []string + if c.TraverseChildren { + cmd, flags, err = c.Traverse(args) + } else { + cmd, flags, err = c.Find(args) + } if err != nil { // If found parse to a subcommand and then failed, talk about the subcommand if cmd != nil { @@ -732,6 +834,12 @@ 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 @@ -752,9 +860,34 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { if !cmd.SilenceUsage && !c.SilenceUsage { c.Println(cmd.UsageString()) } - return cmd, err } - return cmd, nil + return cmd, err +} + +func (c *Command) ValidateArgs(args []string) error { + if c.Args == nil { + return nil + } + return c.Args(c, args) +} + +func (c *Command) validateRequiredFlags() error { + flags := c.Flags() + missingFlagNames := []string{} + flags.VisitAll(func(pflag *flag.Flag) { + requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag] + if !found { + return + } + if (requiredAnnotation[0] == "true") && !pflag.Changed { + missingFlagNames = append(missingFlagNames, pflag.Name) + } + }) + + if len(missingFlagNames) > 0 { + return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`)) + } + return nil } // InitDefaultHelpFlag adds default help flag to c. @@ -773,19 +906,41 @@ func (c *Command) InitDefaultHelpFlag() { } } -func (c *Command) initHelpCmd() { - if c.helpCommand == nil { - if !c.HasSubCommands() { - return +// 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. +func (c *Command) InitDefaultHelpCmd() { + if !c.HasSubCommands() { + return + } + + if c.helpCommand == nil { c.helpCommand = &Command{ Use: "help [command]", Short: "Help about any command", Long: `Help provides help for any command in the application. - Simply type ` + c.Name() + ` help [path to command] for full details.`, - PersistentPreRun: func(cmd *Command, args []string) {}, - PersistentPostRun: func(cmd *Command, args []string) {}, +Simply type ` + c.Name() + ` help [path to command] for full details.`, Run: func(c *Command, args []string) { cmd, _, e := c.Root().Find(args) @@ -803,8 +958,9 @@ func (c *Command) initHelpCmd() { c.AddCommand(c.helpCommand) } -// ResetCommands used for testing. +// ResetCommands delete parent, subcommand and help command from c. func (c *Command) ResetCommands() { + c.parent = nil c.commands = nil c.helpCommand = nil c.parentsPflags = nil @@ -921,6 +1077,9 @@ func (c *Command) UseLine() string { } else { useline = c.Use } + if c.DisableFlagsInUseLine { + return useline + } if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") { useline += " [flags]" } @@ -970,15 +1129,12 @@ func (c *Command) DebugFlags() { // Name returns the command's name: the first word in the use line. func (c *Command) Name() string { - if c.name == "" { - name := c.Use - i := strings.Index(name, " ") - if i >= 0 { - name = name[:i] - } - c.name = name + name := c.Use + i := strings.Index(name, " ") + if i >= 0 { + name = name[:i] } - return c.name + return name } // HasAlias determines if a given string is an alias of the command. @@ -991,7 +1147,32 @@ func (c *Command) HasAlias(s string) bool { return false } -// NameAndAliases returns string containing name and all aliases +// 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 + } + } + return false +} + +// NameAndAliases returns a list of the command name and all aliases func (c *Command) NameAndAliases() string { return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ") } @@ -1077,7 +1258,7 @@ func (c *Command) HasAvailableSubCommands() bool { } } - // the command either has no sub comamnds, or no available (non deprecated/help/hidden) + // the command either has no sub commands, or no available (non deprecated/help/hidden) // sub commands return false } @@ -1087,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 } @@ -1131,6 +1312,9 @@ func (c *Command) LocalFlags() *flag.FlagSet { c.lflags.SetOutput(c.flagErrorBuf) } c.lflags.SortFlags = c.Flags().SortFlags + if c.globNormFunc != nil { + c.lflags.SetNormalizeFunc(c.globNormFunc) + } addToLocal := func(f *flag.Flag) { if c.lflags.Lookup(f.Name) == nil && c.parentsPflags.Lookup(f.Name) == nil { @@ -1155,6 +1339,10 @@ func (c *Command) InheritedFlags() *flag.FlagSet { } local := c.LocalFlags() + if c.globNormFunc != nil { + c.iflags.SetNormalizeFunc(c.globNormFunc) + } + c.parentsPflags.VisitAll(func(f *flag.Flag) { if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil { c.iflags.AddFlag(f) @@ -1180,7 +1368,7 @@ func (c *Command) PersistentFlags() *flag.FlagSet { return c.pflags } -// ResetFlags is used in testing. +// ResetFlags deletes all flags from command. func (c *Command) ResetFlags() { c.flagErrorBuf = new(bytes.Buffer) c.flagErrorBuf.Reset() @@ -1188,6 +1376,10 @@ func (c *Command) ResetFlags() { c.flags.SetOutput(c.flagErrorBuf) c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) c.pflags.SetOutput(c.flagErrorBuf) + + c.lflags = nil + c.iflags = nil + c.parentsPflags = nil } // HasFlags checks if the command contains any flags (local plus persistent from the entire structure). @@ -1258,13 +1450,23 @@ func (c *Command) persistentFlag(name string) (flag *flag.Flag) { } // ParseFlags parses persistent flag tree and local flags. -func (c *Command) ParseFlags(args []string) (err error) { +func (c *Command) ParseFlags(args []string) error { if c.DisableFlagParsing { return nil } + + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + beforeErrorBufLen := c.flagErrorBuf.Len() c.mergePersistentFlags() - err = c.Flags().Parse(args) - return + err := c.Flags().Parse(args) + // Print warnings if they occurred (e.g. deprecated flag messages). + if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil { + c.Print(c.flagErrorBuf.String()) + } + + return err } // Parent returns a commands parent command. @@ -1275,8 +1477,8 @@ func (c *Command) Parent() *Command { // mergePersistentFlags merges c.PersistentFlags() to c.Flags() // and adds missing persistent flags of all parents. func (c *Command) mergePersistentFlags() { - c.Flags().AddFlagSet(c.PersistentFlags()) c.updateParentsPflags() + c.Flags().AddFlagSet(c.PersistentFlags()) c.Flags().AddFlagSet(c.parentsPflags) } @@ -1290,6 +1492,10 @@ func (c *Command) updateParentsPflags() { c.parentsPflags.SortFlags = false } + if c.globNormFunc != nil { + c.parentsPflags.SetNormalizeFunc(c.globNormFunc) + } + c.Root().PersistentFlags().AddFlagSet(flag.CommandLine) c.VisitParents(func(parent *Command) { diff --git a/vendor/github.com/spf13/cobra/command_win.go b/vendor/github.com/spf13/cobra/command_win.go index 4b0eaa1b..edec728e 100644 --- a/vendor/github.com/spf13/cobra/command_win.go +++ b/vendor/github.com/spf13/cobra/command_win.go @@ -11,14 +11,8 @@ import ( var preExecHookFn = preExecHook -// enables an information splash screen on Windows if the CLI is started from explorer.exe. -var MousetrapHelpText string = `This is a command line tool - -You need to open cmd.exe and run it from there. -` - func preExecHook(c *Command) { - if mousetrap.StartedByExplorer() { + if MousetrapHelpText != "" && mousetrap.StartedByExplorer() { c.Print(MousetrapHelpText) time.Sleep(5 * time.Second) os.Exit(1) diff --git a/vendor/github.com/spf13/cobra/doc/man_docs.go b/vendor/github.com/spf13/cobra/doc/man_docs.go index 74b284d2..ce92332d 100644 --- a/vendor/github.com/spf13/cobra/doc/man_docs.go +++ b/vendor/github.com/spf13/cobra/doc/man_docs.go @@ -190,6 +190,9 @@ func manPrintOptions(buf *bytes.Buffer, command *cobra.Command) { } func genMan(cmd *cobra.Command, header *GenManHeader) []byte { + cmd.InitDefaultHelpCmd() + cmd.InitDefaultHelpFlag() + // something like `rootcmd-subcmd1-subcmd2` dashCommandName := strings.Replace(cmd.CommandPath(), " ", "-", -1) diff --git a/vendor/github.com/spf13/cobra/doc/md_docs.go b/vendor/github.com/spf13/cobra/doc/md_docs.go index 9bbfa36f..d7a2c2b6 100644 --- a/vendor/github.com/spf13/cobra/doc/md_docs.go +++ b/vendor/github.com/spf13/cobra/doc/md_docs.go @@ -52,6 +52,9 @@ func GenMarkdown(cmd *cobra.Command, w io.Writer) error { // GenMarkdownCustom creates custom markdown output. func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { + cmd.InitDefaultHelpCmd() + cmd.InitDefaultHelpFlag() + buf := new(bytes.Buffer) name := cmd.CommandPath() @@ -64,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())) @@ -79,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() diff --git a/vendor/github.com/spf13/cobra/doc/rest_docs.go b/vendor/github.com/spf13/cobra/doc/rest_docs.go new file mode 100644 index 00000000..4913e3ee --- /dev/null +++ b/vendor/github.com/spf13/cobra/doc/rest_docs.go @@ -0,0 +1,185 @@ +//Copyright 2015 Red Hat Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package doc + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" + "time" + + "github.com/spf13/cobra" +) + +func printOptionsReST(buf *bytes.Buffer, cmd *cobra.Command, name string) error { + flags := cmd.NonInheritedFlags() + flags.SetOutput(buf) + if flags.HasFlags() { + buf.WriteString("Options\n") + buf.WriteString("~~~~~~~\n\n::\n\n") + flags.PrintDefaults() + buf.WriteString("\n") + } + + parentFlags := cmd.InheritedFlags() + parentFlags.SetOutput(buf) + if parentFlags.HasFlags() { + buf.WriteString("Options inherited from parent commands\n") + buf.WriteString("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n") + parentFlags.PrintDefaults() + buf.WriteString("\n") + } + return nil +} + +// linkHandler for default ReST hyperlink markup +func defaultLinkHandler(name, ref string) string { + return fmt.Sprintf("`%s <%s.rst>`_", name, ref) +} + +// GenReST creates reStructured Text output. +func GenReST(cmd *cobra.Command, w io.Writer) error { + return GenReSTCustom(cmd, w, defaultLinkHandler) +} + +// GenReSTCustom creates custom reStructured Text output. +func GenReSTCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string, string) string) error { + cmd.InitDefaultHelpCmd() + cmd.InitDefaultHelpFlag() + + buf := new(bytes.Buffer) + name := cmd.CommandPath() + + short := cmd.Short + long := cmd.Long + if len(long) == 0 { + long = short + } + ref := strings.Replace(name, " ", "_", -1) + + buf.WriteString(".. _" + ref + ":\n\n") + buf.WriteString(name + "\n") + buf.WriteString(strings.Repeat("-", len(name)) + "\n\n") + buf.WriteString(short + "\n\n") + buf.WriteString("Synopsis\n") + buf.WriteString("~~~~~~~~\n\n") + buf.WriteString("\n" + long + "\n\n") + + if cmd.Runnable() { + buf.WriteString(fmt.Sprintf("::\n\n %s\n\n", cmd.UseLine())) + } + + if len(cmd.Example) > 0 { + buf.WriteString("Examples\n") + buf.WriteString("~~~~~~~~\n\n") + buf.WriteString(fmt.Sprintf("::\n\n%s\n\n", indentString(cmd.Example, " "))) + } + + if err := printOptionsReST(buf, cmd, name); err != nil { + return err + } + if hasSeeAlso(cmd) { + buf.WriteString("SEE ALSO\n") + buf.WriteString("~~~~~~~~\n\n") + if cmd.HasParent() { + parent := cmd.Parent() + pname := parent.CommandPath() + ref = strings.Replace(pname, " ", "_", -1) + buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(pname, ref), parent.Short)) + cmd.VisitParents(func(c *cobra.Command) { + if c.DisableAutoGenTag { + cmd.DisableAutoGenTag = c.DisableAutoGenTag + } + }) + } + + children := cmd.Commands() + sort.Sort(byName(children)) + + for _, child := range children { + if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { + continue + } + cname := name + " " + child.Name() + ref = strings.Replace(cname, " ", "_", -1) + buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(cname, ref), child.Short)) + } + buf.WriteString("\n") + } + if !cmd.DisableAutoGenTag { + buf.WriteString("*Auto generated by spf13/cobra on " + time.Now().Format("2-Jan-2006") + "*\n") + } + _, err := buf.WriteTo(w) + return err +} + +// GenReSTTree will generate a ReST page for this command and all +// descendants in the directory given. +// This function may not work correctly if your command names have `-` in them. +// If you have `cmd` with two subcmds, `sub` and `sub-third`, +// and `sub` has a subcommand called `third`, it is undefined which +// help output will be in the file `cmd-sub-third.1`. +func GenReSTTree(cmd *cobra.Command, dir string) error { + emptyStr := func(s string) string { return "" } + return GenReSTTreeCustom(cmd, dir, emptyStr, defaultLinkHandler) +} + +// GenReSTTreeCustom is the the same as GenReSTTree, but +// with custom filePrepender and linkHandler. +func GenReSTTreeCustom(cmd *cobra.Command, dir string, filePrepender func(string) string, linkHandler func(string, string) string) error { + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { + continue + } + if err := GenReSTTreeCustom(c, dir, filePrepender, linkHandler); err != nil { + return err + } + } + + basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".rst" + filename := filepath.Join(dir, basename) + f, err := os.Create(filename) + if err != nil { + return err + } + defer f.Close() + + if _, err := io.WriteString(f, filePrepender(filename)); err != nil { + return err + } + if err := GenReSTCustom(cmd, f, linkHandler); err != nil { + return err + } + return nil +} + +// adapted from: https://github.com/kr/text/blob/main/indent.go +func indentString(s, p string) string { + var res []byte + b := []byte(s) + prefix := []byte(p) + bol := true + for _, c := range b { + if bol && c != '\n' { + res = append(res, prefix...) + } + res = append(res, c) + bol = c == '\n' + } + return string(res) +} diff --git a/vendor/github.com/spf13/cobra/doc/rest_docs.md b/vendor/github.com/spf13/cobra/doc/rest_docs.md new file mode 100644 index 00000000..6098430e --- /dev/null +++ b/vendor/github.com/spf13/cobra/doc/rest_docs.md @@ -0,0 +1,114 @@ +# Generating ReStructured Text Docs For Your Own cobra.Command + +Generating ReST pages from a cobra command is incredibly easy. An example is as follows: + +```go +package main + +import ( + "log" + + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" +) + +func main() { + cmd := &cobra.Command{ + Use: "test", + Short: "my test program", + } + err := doc.GenReSTTree(cmd, "/tmp") + if err != nil { + log.Fatal(err) + } +} +``` + +That will get you a ReST document `/tmp/test.rst` + +## Generate ReST docs for the entire command tree + +This program can actually generate docs for the kubectl command in the kubernetes project + +```go +package main + +import ( + "log" + "io/ioutil" + "os" + + "k8s.io/kubernetes/pkg/kubectl/cmd" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + + "github.com/spf13/cobra/doc" +) + +func main() { + kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + err := doc.GenReSTTree(kubectl, "./") + if err != nil { + log.Fatal(err) + } +} +``` + +This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") + +## Generate ReST docs for a single command + +You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenReST` instead of `GenReSTTree` + +```go + out := new(bytes.Buffer) + err := doc.GenReST(cmd, out) + if err != nil { + log.Fatal(err) + } +``` + +This will write the ReST doc for ONLY "cmd" into the out, buffer. + +## Customize the output + +Both `GenReST` and `GenReSTTree` have alternate versions with callbacks to get some control of the output: + +```go +func GenReSTTreeCustom(cmd *Command, dir string, filePrepender func(string) string, linkHandler func(string, string) string) error { + //... +} +``` + +```go +func GenReSTCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string, string) string) error { + //... +} +``` + +The `filePrepender` will prepend the return value given the full filepath to the rendered ReST file. A common use case is to add front matter to use the generated documentation with [Hugo](http://gohugo.io/): + +```go +const fmTemplate = `--- +date: %s +title: "%s" +slug: %s +url: %s +--- +` +filePrepender := func(filename string) string { + now := time.Now().Format(time.RFC3339) + name := filepath.Base(filename) + base := strings.TrimSuffix(name, path.Ext(name)) + url := "/commands/" + strings.ToLower(base) + "/" + return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) +} +``` + +The `linkHandler` can be used to customize the rendered links to the commands, given a command name and reference. This is useful while converting rst to html or while generating documentation with tools like Sphinx where `:ref:` is used: + +```go +// Sphinx cross-referencing format +linkHandler := func(name, ref string) string { + return fmt.Sprintf(":ref:`%s <%s>`", name, ref) +} +``` diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs.go b/vendor/github.com/spf13/cobra/doc/yaml_docs.go index 54c244d4..ea00af07 100644 --- a/vendor/github.com/spf13/cobra/doc/yaml_docs.go +++ b/vendor/github.com/spf13/cobra/doc/yaml_docs.go @@ -89,6 +89,9 @@ func GenYaml(cmd *cobra.Command, w io.Writer) error { // GenYamlCustom creates custom yaml output. func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { + cmd.InitDefaultHelpCmd() + cmd.InitDefaultHelpFlag() + yamlDoc := cmdDoc{} yamlDoc.Name = cmd.CommandPath() diff --git a/vendor/github.com/spf13/cobra/zsh_completions.go b/vendor/github.com/spf13/cobra/zsh_completions.go new file mode 100644 index 00000000..889c22e2 --- /dev/null +++ b/vendor/github.com/spf13/cobra/zsh_completions.go @@ -0,0 +1,126 @@ +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "strings" +) + +// GenZshCompletionFile generates zsh completion file. +func (c *Command) GenZshCompletionFile(filename string) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.GenZshCompletion(outFile) +} + +// GenZshCompletion generates a zsh completion file and writes to the passed writer. +func (c *Command) GenZshCompletion(w io.Writer) error { + buf := new(bytes.Buffer) + + writeHeader(buf, c) + maxDepth := maxDepth(c) + writeLevelMapping(buf, maxDepth) + writeLevelCases(buf, maxDepth, c) + + _, err := buf.WriteTo(w) + return err +} + +func writeHeader(w io.Writer, cmd *Command) { + fmt.Fprintf(w, "#compdef %s\n\n", cmd.Name()) +} + +func maxDepth(c *Command) int { + if len(c.Commands()) == 0 { + return 0 + } + maxDepthSub := 0 + for _, s := range c.Commands() { + subDepth := maxDepth(s) + if subDepth > maxDepthSub { + maxDepthSub = subDepth + } + } + return 1 + maxDepthSub +} + +func writeLevelMapping(w io.Writer, numLevels int) { + fmt.Fprintln(w, `_arguments \`) + for i := 1; i <= numLevels; i++ { + fmt.Fprintf(w, ` '%d: :->level%d' \`, i, i) + fmt.Fprintln(w) + } + fmt.Fprintf(w, ` '%d: :%s'`, numLevels+1, "_files") + fmt.Fprintln(w) +} + +func writeLevelCases(w io.Writer, maxDepth int, root *Command) { + fmt.Fprintln(w, "case $state in") + defer fmt.Fprintln(w, "esac") + + for i := 1; i <= maxDepth; i++ { + fmt.Fprintf(w, " level%d)\n", i) + writeLevel(w, root, i) + fmt.Fprintln(w, " ;;") + } + fmt.Fprintln(w, " *)") + fmt.Fprintln(w, " _arguments '*: :_files'") + fmt.Fprintln(w, " ;;") +} + +func writeLevel(w io.Writer, root *Command, i int) { + fmt.Fprintf(w, " case $words[%d] in\n", i) + defer fmt.Fprintln(w, " esac") + + commands := filterByLevel(root, i) + byParent := groupByParent(commands) + + for p, c := range byParent { + names := names(c) + fmt.Fprintf(w, " %s)\n", p) + fmt.Fprintf(w, " _arguments '%d: :(%s)'\n", i, strings.Join(names, " ")) + fmt.Fprintln(w, " ;;") + } + fmt.Fprintln(w, " *)") + fmt.Fprintln(w, " _arguments '*: :_files'") + fmt.Fprintln(w, " ;;") + +} + +func filterByLevel(c *Command, l int) []*Command { + cs := make([]*Command, 0) + if l == 0 { + cs = append(cs, c) + return cs + } + for _, s := range c.Commands() { + cs = append(cs, filterByLevel(s, l-1)...) + } + return cs +} + +func groupByParent(commands []*Command) map[string][]*Command { + m := make(map[string][]*Command) + for _, c := range commands { + parent := c.Parent() + if parent == nil { + continue + } + m[parent.Name()] = append(m[parent.Name()], c) + } + return m +} + +func names(commands []*Command) []string { + ns := make([]string, len(commands)) + for i, c := range commands { + ns[i] = c.Name() + } + return ns +} -- GitLab