Update cobra and pflag
Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
parent
1d5cd86207
commit
c6fd18ddc3
@ -49,8 +49,8 @@ github.com/PuerkitoBio/purell v1.0.0
|
|||||||
github.com/PuerkitoBio/urlesc 5bd2802263f21d8788851d5305584c82a5c75d7e
|
github.com/PuerkitoBio/urlesc 5bd2802263f21d8788851d5305584c82a5c75d7e
|
||||||
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
|
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
|
||||||
github.com/sirupsen/logrus v1.0.0
|
github.com/sirupsen/logrus v1.0.0
|
||||||
github.com/spf13/cobra f62e98d28ab7ad31d707ba837a966378465c7b57
|
github.com/spf13/cobra v0.0.1
|
||||||
github.com/spf13/pflag 9ff6c6923cfffbcd502984b8e0c80539a94968b7
|
github.com/spf13/pflag v1.0.0
|
||||||
github.com/stretchr/testify v1.1.4
|
github.com/stretchr/testify v1.1.4
|
||||||
github.com/syndtr/gocapability e7cb7fa329f456b3855136a2642b197bad7366ba
|
github.com/syndtr/gocapability e7cb7fa329f456b3855136a2642b197bad7366ba
|
||||||
github.com/tchap/go-patricia 5ad6cdb7538b0097d5598c7e57f0a24072adf7dc
|
github.com/tchap/go-patricia 5ad6cdb7538b0097d5598c7e57f0a24072adf7dc
|
||||||
|
60
vendor/github.com/docker/docker/hack/README.md
generated
vendored
Normal file
60
vendor/github.com/docker/docker/hack/README.md
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
## About
|
||||||
|
|
||||||
|
This directory contains a collection of scripts used to build and manage this
|
||||||
|
repository. If there are any issues regarding the intention of a particular
|
||||||
|
script (or even part of a certain script), please reach out to us.
|
||||||
|
It may help us either refine our current scripts, or add on new ones
|
||||||
|
that are appropriate for a given use case.
|
||||||
|
|
||||||
|
## DinD (dind.sh)
|
||||||
|
|
||||||
|
DinD is a wrapper script which allows Docker to be run inside a Docker
|
||||||
|
container. DinD requires the container to
|
||||||
|
be run with privileged mode enabled.
|
||||||
|
|
||||||
|
## Generate Authors (generate-authors.sh)
|
||||||
|
|
||||||
|
Generates AUTHORS; a file with all the names and corresponding emails of
|
||||||
|
individual contributors. AUTHORS can be found in the home directory of
|
||||||
|
this repository.
|
||||||
|
|
||||||
|
## Make
|
||||||
|
|
||||||
|
There are two make files, each with different extensions. Neither are supposed
|
||||||
|
to be called directly; only invoke `make`. Both scripts run inside a Docker
|
||||||
|
container.
|
||||||
|
|
||||||
|
### make.ps1
|
||||||
|
|
||||||
|
- The Windows native build script that uses PowerShell semantics; it is limited
|
||||||
|
unlike `hack\make.sh` since it does not provide support for the full set of
|
||||||
|
operations provided by the Linux counterpart, `make.sh`. However, `make.ps1`
|
||||||
|
does provide support for local Windows development and Windows to Windows CI.
|
||||||
|
More information is found within `make.ps1` by the author, @jhowardmsft
|
||||||
|
|
||||||
|
### make.sh
|
||||||
|
|
||||||
|
- Referenced via `make test` when running tests on a local machine,
|
||||||
|
or directly referenced when running tests inside a Docker development container.
|
||||||
|
- When running on a local machine, `make test` to run all tests found in
|
||||||
|
`test`, `test-unit`, `test-integration`, and `test-docker-py` on
|
||||||
|
your local machine. The default timeout is set in `make.sh` to 60 minutes
|
||||||
|
(`${TIMEOUT:=60m}`), since it currently takes up to an hour to run
|
||||||
|
all of the tests.
|
||||||
|
- When running inside a Docker development container, `hack/make.sh` does
|
||||||
|
not have a single target that runs all the tests. You need to provide a
|
||||||
|
single command line with multiple targets that performs the same thing.
|
||||||
|
An example referenced from [Run targets inside a development container](https://docs.docker.com/opensource/project/test-and-docs/#run-targets-inside-a-development-container): `root@5f8630b873fe:/go/src/github.com/moby/moby# hack/make.sh dynbinary binary cross test-unit test-integration test-docker-py`
|
||||||
|
- For more information related to testing outside the scope of this README,
|
||||||
|
refer to
|
||||||
|
[Run tests and test documentation](https://docs.docker.com/opensource/project/test-and-docs/)
|
||||||
|
|
||||||
|
## Release (release.sh)
|
||||||
|
|
||||||
|
Releases any bundles built by `make` on a public AWS S3 bucket.
|
||||||
|
For information regarding configuration, please view `release.sh`.
|
||||||
|
|
||||||
|
## Vendor (vendor.sh)
|
||||||
|
|
||||||
|
A shell script that is a wrapper around Vndr. For information on how to use
|
||||||
|
this, please refer to [vndr's README](https://github.com/LK4D4/vndr/blob/master/README.md)
|
69
vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md
generated
vendored
Normal file
69
vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Integration Testing on Swarm
|
||||||
|
|
||||||
|
IT on Swarm allows you to execute integration test in parallel across a Docker Swarm cluster
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Master service
|
||||||
|
|
||||||
|
- Works as a funker caller
|
||||||
|
- Calls a worker funker (`-worker-service`) with a chunk of `-check.f` filter strings (passed as a file via `-input` flag, typically `/mnt/input`)
|
||||||
|
|
||||||
|
### Worker service
|
||||||
|
|
||||||
|
- Works as a funker callee
|
||||||
|
- Executes an equivalent of `TESTFLAGS=-check.f TestFoo|TestBar|TestBaz ... make test-integration-cli` using the bind-mounted API socket (`docker.sock`)
|
||||||
|
|
||||||
|
### Client
|
||||||
|
|
||||||
|
- Controls master and workers via `docker stack`
|
||||||
|
- No need to have a local daemon
|
||||||
|
|
||||||
|
Typically, the master and workers are supposed to be running on a cloud environment,
|
||||||
|
while the client is supposed to be running on a laptop, e.g. Docker for Mac/Windows.
|
||||||
|
|
||||||
|
## Requirement
|
||||||
|
|
||||||
|
- Docker daemon 1.13 or later
|
||||||
|
- Private registry for distributed execution with multiple nodes
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Step 1: Prepare images
|
||||||
|
|
||||||
|
$ make build-integration-cli-on-swarm
|
||||||
|
|
||||||
|
Following environment variables are known to work in this step:
|
||||||
|
|
||||||
|
- `BUILDFLAGS`
|
||||||
|
- `DOCKER_INCREMENTAL_BINARY`
|
||||||
|
|
||||||
|
Note: during the transition into Moby Project, you might need to create a symbolic link `$GOPATH/src/github.com/docker/docker` to `$GOPATH/src/github.com/moby/moby`.
|
||||||
|
|
||||||
|
### Step 2: Execute tests
|
||||||
|
|
||||||
|
$ ./hack/integration-cli-on-swarm/integration-cli-on-swarm -replicas 40 -push-worker-image YOUR_REGISTRY.EXAMPLE.COM/integration-cli-worker:latest
|
||||||
|
|
||||||
|
Following environment variables are known to work in this step:
|
||||||
|
|
||||||
|
- `DOCKER_GRAPHDRIVER`
|
||||||
|
- `DOCKER_EXPERIMENTAL`
|
||||||
|
|
||||||
|
#### Flags
|
||||||
|
|
||||||
|
Basic flags:
|
||||||
|
|
||||||
|
- `-replicas N`: the number of worker service replicas. i.e. degree of parallelism.
|
||||||
|
- `-chunks N`: the number of chunks. By default, `chunks` == `replicas`.
|
||||||
|
- `-push-worker-image REGISTRY/IMAGE:TAG`: push the worker image to the registry. Note that if you have only single node and hence you do not need a private registry, you do not need to specify `-push-worker-image`.
|
||||||
|
|
||||||
|
Experimental flags for mitigating makespan nonuniformity:
|
||||||
|
|
||||||
|
- `-shuffle`: Shuffle the test filter strings
|
||||||
|
|
||||||
|
Flags for debugging IT on Swarm itself:
|
||||||
|
|
||||||
|
- `-rand-seed N`: the random seed. This flag is useful for deterministic replaying. By default(0), the timestamp is used.
|
||||||
|
- `-filters-file FILE`: the file contains `-check.f` strings. By default, the file is automatically generated.
|
||||||
|
- `-dry-run`: skip the actual workload
|
||||||
|
- `keep-executor`: do not auto-remove executor containers, which is used for running privileged programs on Swarm
|
2
vendor/github.com/docker/docker/hack/integration-cli-on-swarm/agent/vendor.conf
generated
vendored
Normal file
2
vendor/github.com/docker/docker/hack/integration-cli-on-swarm/agent/vendor.conf
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# dependencies specific to worker (i.e. github.com/docker/docker/...) are not vendored here
|
||||||
|
github.com/bfirsh/funker-go eaa0a2e06f30e72c9a0b7f858951e581e26ef773
|
639
vendor/github.com/spf13/cobra/README.md
generated
vendored
639
vendor/github.com/spf13/cobra/README.md
generated
vendored
@ -8,6 +8,7 @@ Many of the most widely used Go projects are built using Cobra including:
|
|||||||
* [Hugo](http://gohugo.io)
|
* [Hugo](http://gohugo.io)
|
||||||
* [rkt](https://github.com/coreos/rkt)
|
* [rkt](https://github.com/coreos/rkt)
|
||||||
* [etcd](https://github.com/coreos/etcd)
|
* [etcd](https://github.com/coreos/etcd)
|
||||||
|
* [Moby (former Docker)](https://github.com/moby/moby)
|
||||||
* [Docker (distribution)](https://github.com/docker/distribution)
|
* [Docker (distribution)](https://github.com/docker/distribution)
|
||||||
* [OpenShift](https://www.openshift.com/)
|
* [OpenShift](https://www.openshift.com/)
|
||||||
* [Delve](https://github.com/derekparker/delve)
|
* [Delve](https://github.com/derekparker/delve)
|
||||||
@ -15,16 +16,36 @@ Many of the most widely used Go projects are built using Cobra including:
|
|||||||
* [CockroachDB](http://www.cockroachlabs.com/)
|
* [CockroachDB](http://www.cockroachlabs.com/)
|
||||||
* [Bleve](http://www.blevesearch.com/)
|
* [Bleve](http://www.blevesearch.com/)
|
||||||
* [ProjectAtomic (enterprise)](http://www.projectatomic.io/)
|
* [ProjectAtomic (enterprise)](http://www.projectatomic.io/)
|
||||||
* [Parse (CLI)](https://parse.com/)
|
|
||||||
* [GiantSwarm's swarm](https://github.com/giantswarm/cli)
|
* [GiantSwarm's swarm](https://github.com/giantswarm/cli)
|
||||||
* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
|
* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
|
||||||
|
* [rclone](http://rclone.org/)
|
||||||
|
* [nehm](https://github.com/bogem/nehm)
|
||||||
|
|
||||||
[](https://travis-ci.org/spf13/cobra)
|
[](https://travis-ci.org/spf13/cobra)
|
||||||
[](https://circleci.com/gh/spf13/cobra)
|
[](https://circleci.com/gh/spf13/cobra)
|
||||||
[](https://godoc.org/github.com/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
|
# Overview
|
||||||
|
|
||||||
@ -39,27 +60,16 @@ Cobra provides:
|
|||||||
* Fully POSIX-compliant flags (including short & long versions)
|
* Fully POSIX-compliant flags (including short & long versions)
|
||||||
* Nested subcommands
|
* Nested subcommands
|
||||||
* Global, local and cascading flags
|
* Global, local and cascading flags
|
||||||
* Easy generation of applications & commands with `cobra create appname` & `cobra add cmdname`
|
* Easy generation of applications & commands with `cobra init appname` & `cobra add cmdname`
|
||||||
* Intelligent suggestions (`app srver`... did you mean `app server`?)
|
* Intelligent suggestions (`app srver`... did you mean `app server`?)
|
||||||
* Automatic help generation for commands and flags
|
* Automatic help generation for commands and flags
|
||||||
* Automatic detailed help for `app help [command]`
|
|
||||||
* Automatic help flag recognition of `-h`, `--help`, etc.
|
* Automatic help flag recognition of `-h`, `--help`, etc.
|
||||||
* Automatically generated bash autocomplete for your application
|
* Automatically generated bash autocomplete for your application
|
||||||
* Automatically generated man pages for your application
|
* Automatically generated man pages for your application
|
||||||
* Command aliases so you can change things without breaking them
|
* Command aliases so you can change things without breaking them
|
||||||
* The flexibilty to define your own help, usage, etc.
|
* The flexibility to define your own help, usage, etc.
|
||||||
* Optional tight integration with [viper](http://github.com/spf13/viper) for 12-factor apps
|
* 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
|
# Concepts
|
||||||
|
|
||||||
Cobra is built on a structure of commands, arguments & flags.
|
Cobra is built on a structure of commands, arguments & flags.
|
||||||
@ -78,11 +88,11 @@ A few good real world examples may better illustrate this point.
|
|||||||
|
|
||||||
In the following example, 'server' is a command, and 'port' is a flag:
|
In the following example, 'server' is a command, and 'port' is a flag:
|
||||||
|
|
||||||
> hugo server --port=1313
|
hugo server --port=1313
|
||||||
|
|
||||||
In this command we are telling Git to clone the url bare.
|
In this command we are telling Git to clone the url bare.
|
||||||
|
|
||||||
> git clone URL --bare
|
git clone URL --bare
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
@ -92,20 +102,11 @@ have children commands and optionally run an action.
|
|||||||
|
|
||||||
In the example above, 'server' is the command.
|
In the example above, 'server' is the command.
|
||||||
|
|
||||||
A Command has the following structure:
|
[More about cobra.Command](https://godoc.org/github.com/spf13/cobra#Command)
|
||||||
|
|
||||||
```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.
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Flags
|
## 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/).
|
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
|
A Cobra command can define flags that persist through to children commands
|
||||||
and flags that are only available to that command.
|
and flags that are only available to that command.
|
||||||
@ -113,23 +114,15 @@ and flags that are only available to that command.
|
|||||||
In the example above, 'port' is the flag.
|
In the example above, 'port' is the flag.
|
||||||
|
|
||||||
Flag functionality is provided by the [pflag
|
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.
|
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
|
# Installing
|
||||||
Using Cobra is easy. First, use `go get` to install the latest version
|
Using Cobra is easy. First, use `go get` to install the latest version
|
||||||
of the library. This command will install the `cobra` generator executible
|
of the library. This command will install the `cobra` generator executable
|
||||||
along with the library:
|
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:
|
Next, include Cobra in your application:
|
||||||
|
|
||||||
@ -139,8 +132,8 @@ import "github.com/spf13/cobra"
|
|||||||
|
|
||||||
# Getting Started
|
# Getting Started
|
||||||
|
|
||||||
While you are welcome to provide your own organization, typically a Cobra based
|
While you are welcome to provide your own organization, typically a Cobra-based
|
||||||
application will follow the following organizational structure.
|
application will follow the following organizational structure:
|
||||||
|
|
||||||
```
|
```
|
||||||
▾ appName/
|
▾ appName/
|
||||||
@ -152,17 +145,22 @@ application will follow the following organizational structure.
|
|||||||
main.go
|
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
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "{pathToYourApp}/cmd"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"{pathToYourApp}/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if err := cmd.RootCmd.Execute(); err != nil {
|
if err := cmd.RootCmd.Execute(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(-1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -172,99 +170,14 @@ func main() {
|
|||||||
Cobra provides its own program that will create your application and add any
|
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.
|
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:
|
[Here](https://github.com/spf13/cobra/blob/master/cobra/README.md) you can find more information about it.
|
||||||
|
|
||||||
> go install github.com/spf13/cobra/cobra
|
## Using the Cobra Library
|
||||||
|
|
||||||
This will create the cobra executable under your go path bin directory!
|
To manually implement Cobra you need to create a bare main.go file and a RootCmd file.
|
||||||
|
|
||||||
### 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'
|
|
||||||
```
|
|
||||||
|
|
||||||
Once you have run these three commands you would have an app structure that would look like:
|
|
||||||
|
|
||||||
```
|
|
||||||
▾ 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.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Manually implementing Cobra
|
|
||||||
|
|
||||||
To manually implement cobra you need to create a bare main.go file and a RootCmd file.
|
|
||||||
You will optionally provide additional commands as you see fit.
|
You will optionally provide additional commands as you see fit.
|
||||||
|
|
||||||
### Create the root command
|
### Create rootCmd
|
||||||
|
|
||||||
The root command represents your binary itself.
|
|
||||||
|
|
||||||
|
|
||||||
#### Manually create rootCmd
|
|
||||||
|
|
||||||
Cobra doesn't require any special constructors. Simply create your commands.
|
Cobra doesn't require any special constructors. Simply create your commands.
|
||||||
|
|
||||||
@ -285,9 +198,18 @@ var RootCmd = &cobra.Command{
|
|||||||
|
|
||||||
You will additionally define flags and handle configuration in your init() function.
|
You will additionally define flags and handle configuration in your init() function.
|
||||||
|
|
||||||
for example cmd/root.go:
|
For example cmd/root.go:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cobra.OnInitialize(initConfig)
|
cobra.OnInitialize(initConfig)
|
||||||
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
|
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
|
||||||
@ -301,6 +223,34 @@ func init() {
|
|||||||
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
||||||
viper.SetDefault("license", "apache")
|
viper.SetDefault("license", "apache")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Execute() {
|
||||||
|
RootCmd.Execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
func initConfig() {
|
||||||
|
// Don't forget to read config either from cfgFile or from home directory!
|
||||||
|
if cfgFile != "" {
|
||||||
|
// Use config file from the flag.
|
||||||
|
viper.SetConfigFile(cfgFile)
|
||||||
|
} else {
|
||||||
|
// Find home directory.
|
||||||
|
home, err := homedir.Dir()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search config in home directory with name ".cobra" (without extension).
|
||||||
|
viper.AddConfigPath(home)
|
||||||
|
viper.SetConfigName(".cobra")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := viper.ReadInConfig(); err != nil {
|
||||||
|
fmt.Println("Can't read config:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create your main.go
|
### Create your main.go
|
||||||
@ -313,17 +263,21 @@ In a Cobra app, typically the main.go file is very bare. It serves, one purpose,
|
|||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "{pathToYourApp}/cmd"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"{pathToYourApp}/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if err := cmd.RootCmd.Execute(); err != nil {
|
if err := cmd.RootCmd.Execute(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(-1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Create additional commands
|
### Create additional commands
|
||||||
|
|
||||||
Additional commands can be defined and typically are each given their own file
|
Additional commands can be defined and typically are each given their own file
|
||||||
@ -337,6 +291,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -353,30 +308,6 @@ var versionCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 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
|
## Working with Flags
|
||||||
|
|
||||||
Flags provide modifiers to control how the action command operates.
|
Flags provide modifiers to control how the action command operates.
|
||||||
@ -412,6 +343,71 @@ A flag can also be assigned locally which will only apply to that specific comma
|
|||||||
RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
|
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).
|
||||||
|
|
||||||
|
## 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
|
## Example
|
||||||
|
|
||||||
@ -435,15 +431,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
var echoTimes int
|
var echoTimes int
|
||||||
|
|
||||||
var cmdPrint = &cobra.Command{
|
var cmdPrint = &cobra.Command{
|
||||||
Use: "print [string to print]",
|
Use: "print [string to print]",
|
||||||
Short: "Print anything to the screen",
|
Short: "Print anything to the screen",
|
||||||
Long: `print is for printing anything back to the screen.
|
Long: `print is for printing anything back to the screen.
|
||||||
For many years people have printed 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) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Println("Print: " + strings.Join(args, " "))
|
fmt.Println("Print: " + strings.Join(args, " "))
|
||||||
},
|
},
|
||||||
@ -453,8 +448,8 @@ func main() {
|
|||||||
Use: "echo [string to echo]",
|
Use: "echo [string to echo]",
|
||||||
Short: "Echo anything to the screen",
|
Short: "Echo anything to the screen",
|
||||||
Long: `echo is for echoing anything back.
|
Long: `echo is for echoing anything back.
|
||||||
Echo works a lot like print, except it has a child command.
|
Echo works a lot like print, except it has a child command.`,
|
||||||
`,
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Println("Print: " + strings.Join(args, " "))
|
fmt.Println("Print: " + strings.Join(args, " "))
|
||||||
},
|
},
|
||||||
@ -465,6 +460,7 @@ func main() {
|
|||||||
Short: "Echo anything to the screen more times",
|
Short: "Echo anything to the screen more times",
|
||||||
Long: `echo things multiple times back to the user by providing
|
Long: `echo things multiple times back to the user by providing
|
||||||
a count and a string.`,
|
a count and a string.`,
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
for i := 0; i < echoTimes; i++ {
|
for i := 0; i < echoTimes; i++ {
|
||||||
fmt.Println("Echo: " + strings.Join(args, " "))
|
fmt.Println("Echo: " + strings.Join(args, " "))
|
||||||
@ -483,7 +479,7 @@ func main() {
|
|||||||
|
|
||||||
For a more complete example of a larger application, please checkout [Hugo](http://gohugo.io/).
|
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.
|
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
|
This will be called when a user runs 'app help'. Additionally, help will also
|
||||||
@ -496,60 +492,28 @@ create' is called. Every command will automatically have the '--help' flag adde
|
|||||||
The following output is automatically generated by Cobra. Nothing beyond the
|
The following output is automatically generated by Cobra. Nothing beyond the
|
||||||
command and flag definitions are needed.
|
command and flag definitions are needed.
|
||||||
|
|
||||||
> hugo help
|
$ cobra help
|
||||||
|
|
||||||
hugo is the main command, used to build your Hugo site.
|
Cobra is a CLI library for Go that empowers applications.
|
||||||
|
This application is a tool to generate the needed files
|
||||||
Hugo is a Fast and Flexible Static Site Generator
|
to quickly create a Cobra application.
|
||||||
built with love by spf13 and friends in Go.
|
|
||||||
|
|
||||||
Complete documentation is available at http://gohugo.io/.
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
hugo [flags]
|
cobra [command]
|
||||||
hugo [command]
|
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
server Hugo runs its own webserver to render the files
|
add Add a command to a Cobra Application
|
||||||
version Print the version number of Hugo
|
help Help about any command
|
||||||
config Print the site configuration
|
init Initialize a Cobra Application
|
||||||
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.
|
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/
|
-a, --author string author name for copyright attribution (default "YOUR NAME")
|
||||||
-D, --buildDrafts[=false]: include content marked as draft
|
--config string config file (default is $HOME/.cobra.yaml)
|
||||||
-F, --buildFuture[=false]: include content with publishdate in the future
|
-h, --help help for cobra
|
||||||
--cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/
|
-l, --license string name of license for the project
|
||||||
--canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL
|
--viper use Viper for configuration (default true)
|
||||||
--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.
|
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
|
Help is just a command like any other. There is no special logic or behavior
|
||||||
@ -557,38 +521,18 @@ around it. In fact, you can provide your own if you want.
|
|||||||
|
|
||||||
### Defining your own help
|
### Defining your own help
|
||||||
|
|
||||||
You can provide your own Help command or your own template for the default command to use.
|
You can provide your own Help command or your own template for the default command to use
|
||||||
|
with followind functions:
|
||||||
The default help command is
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (c *Command) initHelp() {
|
cmd.SetHelpCommand(cmd *Command)
|
||||||
if c.helpCommand == nil {
|
cmd.SetHelpFunc(f func(*Command, []string))
|
||||||
c.helpCommand = &Command{
|
cmd.SetHelpTemplate(s string)
|
||||||
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:
|
|
||||||
|
|
||||||
```go
|
|
||||||
command.SetHelpCommand(cmd *Command)
|
|
||||||
|
|
||||||
command.SetHelpFunc(f func(*Command, []string))
|
|
||||||
|
|
||||||
command.SetHelpTemplate(s string)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The latter two will also apply to any children commands.
|
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
|
When the user provides an invalid flag or invalid command, Cobra responds by
|
||||||
showing the user the 'usage'.
|
showing the user the 'usage'.
|
||||||
@ -597,73 +541,37 @@ showing the user the 'usage'.
|
|||||||
You may recognize this from the help above. That's because the default help
|
You may recognize this from the help above. That's because the default help
|
||||||
embeds the usage as part of its output.
|
embeds the usage as part of its output.
|
||||||
|
|
||||||
|
$ cobra --invalid
|
||||||
|
Error: unknown flag: --invalid
|
||||||
Usage:
|
Usage:
|
||||||
hugo [flags]
|
cobra [command]
|
||||||
hugo [command]
|
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
server Hugo runs its own webserver to render the files
|
add Add a command to a Cobra Application
|
||||||
version Print the version number of Hugo
|
help Help about any command
|
||||||
config Print the site configuration
|
init Initialize a Cobra Application
|
||||||
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.
|
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/
|
-a, --author string author name for copyright attribution (default "YOUR NAME")
|
||||||
-D, --buildDrafts[=false]: include content marked as draft
|
--config string config file (default is $HOME/.cobra.yaml)
|
||||||
-F, --buildFuture[=false]: include content with publishdate in the future
|
-h, --help help for cobra
|
||||||
--cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/
|
-l, --license string name of license for the project
|
||||||
--canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL
|
--viper use Viper for configuration (default true)
|
||||||
--config="": config file (default is path/config.yaml|json|toml)
|
|
||||||
-d, --destination="": filesystem path to write files to
|
Use "cobra [command] --help" for more information about a command.
|
||||||
--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
|
|
||||||
|
|
||||||
### Defining your own usage
|
### Defining your own usage
|
||||||
You can provide your own usage function or template for Cobra to use.
|
You can provide your own usage function or template for Cobra to use.
|
||||||
|
|
||||||
The default usage function is:
|
|
||||||
|
|
||||||
```go
|
|
||||||
return func(c *Command) error {
|
|
||||||
err := tmpl(c.Out(), c.UsageTemplate(), c)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Like help, the function and template are overridable through public methods:
|
Like help, the function and template are overridable through public methods:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
command.SetUsageFunc(f func(*Command) error)
|
cmd.SetUsageFunc(f func(*Command) error)
|
||||||
|
cmd.SetUsageTemplate(s string)
|
||||||
command.SetUsageTemplate(s string)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 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 inherrited by children if they do not declare their own. These function are run in the following order:
|
It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order:
|
||||||
|
|
||||||
- `PersistentPreRun`
|
- `PersistentPreRun`
|
||||||
- `PreRun`
|
- `PreRun`
|
||||||
@ -724,58 +632,26 @@ func main() {
|
|||||||
rootCmd.AddCommand(subCmd)
|
rootCmd.AddCommand(subCmd)
|
||||||
|
|
||||||
rootCmd.SetArgs([]string{""})
|
rootCmd.SetArgs([]string{""})
|
||||||
_ = rootCmd.Execute()
|
rootCmd.Execute()
|
||||||
fmt.Print("\n")
|
fmt.Println()
|
||||||
rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
|
rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
|
||||||
_ = rootCmd.Execute()
|
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
|
Inside rootCmd PersistentPreRun with args: [arg1 arg2]
|
||||||
|
Inside subCmd PreRun with args: [arg1 arg2]
|
||||||
Cobra also has functions where the return signature is an error. This allows for errors to bubble up to the top,
|
Inside subCmd Run with args: [arg1 arg2]
|
||||||
providing a way to handle the errors in one location. The current list of functions that return an error is:
|
Inside subCmd PostRun with args: [arg1 arg2]
|
||||||
|
Inside subCmd PersistentPostRun with args: [arg1 arg2]
|
||||||
* 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 `false` 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Suggestions when "unknown command" happens
|
## Suggestions when "unknown command" happens
|
||||||
@ -818,81 +694,28 @@ Did you mean this?
|
|||||||
Run 'kubectl help' for usage.
|
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
|
||||||
|
|
||||||
## Generating bash completions for your command
|
|
||||||
|
|
||||||
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).
|
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
|
# Contributing
|
||||||
|
|
||||||
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()
|
|
||||||
```
|
|
||||||
|
|
||||||
## Release Notes
|
|
||||||
* **0.9.0** June 17, 2014
|
|
||||||
* flags can appears anywhere in the args (provided they are unambiguous)
|
|
||||||
* --help prints usage screen for app or command
|
|
||||||
* Prefix matching for commands
|
|
||||||
* Cleaner looking help and usage output
|
|
||||||
* Extensive test suite
|
|
||||||
* **0.8.0** Nov 5, 2013
|
|
||||||
* Reworked interface to remove commander completely
|
|
||||||
* Command now primary structure
|
|
||||||
* No initialization needed
|
|
||||||
* Usage & Help templates & functions definable at any level
|
|
||||||
* Updated Readme
|
|
||||||
* **0.7.0** Sept 24, 2013
|
|
||||||
* Needs more eyes
|
|
||||||
* Test suite
|
|
||||||
* Support for automatic error messages
|
|
||||||
* Support for help command
|
|
||||||
* Support for printing to any io.Writer instead of os.Stderr
|
|
||||||
* Support for persistent flags which cascade down tree
|
|
||||||
* Ready for integration into Hugo
|
|
||||||
* **0.1.0** Sept 3, 2013
|
|
||||||
* Implement first draft
|
|
||||||
|
|
||||||
## 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`.
|
|
||||||
|
|
||||||
## ToDo
|
|
||||||
* Launch proper documentation site
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
1. Fork it
|
1. Fork it
|
||||||
2. Create your feature branch (`git checkout -b my-new-feature`)
|
2. Download your fork to your PC (`git clone https://github.com/your_username/cobra && cd cobra`)
|
||||||
3. Commit your changes (`git commit -am 'Add some feature'`)
|
3. Create your feature branch (`git checkout -b my-new-feature`)
|
||||||
4. Push to the branch (`git push origin my-new-feature`)
|
4. Make changes and add them (`git add .`)
|
||||||
5. Create new Pull Request
|
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
|
||||||
|
|
||||||
## Contributors
|
# License
|
||||||
|
|
||||||
Names in no particular order:
|
|
||||||
|
|
||||||
* [spf13](https://github.com/spf13),
|
|
||||||
[eparis](https://github.com/eparis),
|
|
||||||
[bep](https://github.com/bep), and many more!
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt)
|
Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt)
|
||||||
|
|
||||||
|
|
||||||
[](https://bitdeli.com/free "Bitdeli Badge")
|
|
||||||
|
98
vendor/github.com/spf13/cobra/args.go
generated
vendored
Normal file
98
vendor/github.com/spf13/cobra/args.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringInSlice(a string, list []string) bool {
|
||||||
|
for _, b := range list {
|
||||||
|
if b == a {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
315
vendor/github.com/spf13/cobra/bash_completions.go
generated
vendored
315
vendor/github.com/spf13/cobra/bash_completions.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package cobra
|
package cobra
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -10,19 +11,17 @@ import (
|
|||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Annotations for Bash completion.
|
||||||
const (
|
const (
|
||||||
BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extentions"
|
BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions"
|
||||||
BashCompCustom = "cobra_annotation_bash_completion_custom"
|
BashCompCustom = "cobra_annotation_bash_completion_custom"
|
||||||
BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag"
|
BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag"
|
||||||
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
|
BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir"
|
||||||
)
|
)
|
||||||
|
|
||||||
func preamble(out io.Writer, name string) error {
|
func writePreamble(buf *bytes.Buffer, name string) {
|
||||||
_, err := fmt.Fprintf(out, "# bash completion for %-36s -*- shell-script -*-\n", name)
|
buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name))
|
||||||
if err != nil {
|
buf.WriteString(`
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = fmt.Fprint(out, `
|
|
||||||
__debug()
|
__debug()
|
||||||
{
|
{
|
||||||
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
|
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
|
||||||
@ -87,13 +86,13 @@ __handle_reply()
|
|||||||
local index flag
|
local index flag
|
||||||
flag="${cur%%=*}"
|
flag="${cur%%=*}"
|
||||||
__index_of_word "${flag}" "${flags_with_completion[@]}"
|
__index_of_word "${flag}" "${flags_with_completion[@]}"
|
||||||
if [[ ${index} -ge 0 ]]; then
|
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
|
if [[ ${index} -ge 0 ]]; then
|
||||||
PREFIX=""
|
PREFIX=""
|
||||||
cur="${cur#*=}"
|
cur="${cur#*=}"
|
||||||
${flags_completion[${index}]}
|
${flags_completion[${index}]}
|
||||||
if [ -n "${ZSH_VERSION}" ]; then
|
if [ -n "${ZSH_VERSION}" ]; then
|
||||||
# zfs completion needs --flag= prefix
|
# zsh completion needs --flag= prefix
|
||||||
eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )"
|
eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -133,7 +132,10 @@ __handle_reply()
|
|||||||
declare -F __custom_func >/dev/null && __custom_func
|
declare -F __custom_func >/dev/null && __custom_func
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# available in bash-completion >= 2, not always present on macOS
|
||||||
|
if declare -F __ltrim_colon_completions >/dev/null; then
|
||||||
__ltrim_colon_completions "$cur"
|
__ltrim_colon_completions "$cur"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# The arguments should be in the form "ext1|ext2|extn"
|
# The arguments should be in the form "ext1|ext2|extn"
|
||||||
@ -224,7 +226,7 @@ __handle_command()
|
|||||||
fi
|
fi
|
||||||
c=$((c+1))
|
c=$((c+1))
|
||||||
__debug "${FUNCNAME[0]}: looking for ${next_command}"
|
__debug "${FUNCNAME[0]}: looking for ${next_command}"
|
||||||
declare -F $next_command >/dev/null && $next_command
|
declare -F "$next_command" >/dev/null && $next_command
|
||||||
}
|
}
|
||||||
|
|
||||||
__handle_word()
|
__handle_word()
|
||||||
@ -247,16 +249,12 @@ __handle_word()
|
|||||||
}
|
}
|
||||||
|
|
||||||
`)
|
`)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func postscript(w io.Writer, name string) error {
|
func writePostscript(buf *bytes.Buffer, name string) {
|
||||||
name = strings.Replace(name, ":", "__", -1)
|
name = strings.Replace(name, ":", "__", -1)
|
||||||
_, err := fmt.Fprintf(w, "__start_%s()\n", name)
|
buf.WriteString(fmt.Sprintf("__start_%s()\n", name))
|
||||||
if err != nil {
|
buf.WriteString(fmt.Sprintf(`{
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = fmt.Fprintf(w, `{
|
|
||||||
local cur prev words cword
|
local cur prev words cword
|
||||||
declare -A flaghash 2>/dev/null || :
|
declare -A flaghash 2>/dev/null || :
|
||||||
if declare -F _init_completion >/dev/null 2>&1; then
|
if declare -F _init_completion >/dev/null 2>&1; then
|
||||||
@ -280,318 +278,227 @@ func postscript(w io.Writer, name string) error {
|
|||||||
__handle_word
|
__handle_word
|
||||||
}
|
}
|
||||||
|
|
||||||
`, name)
|
`, name))
|
||||||
if err != nil {
|
buf.WriteString(fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = fmt.Fprintf(w, `if [[ $(type -t compopt) = "builtin" ]]; then
|
|
||||||
complete -o default -F __start_%s %s
|
complete -o default -F __start_%s %s
|
||||||
else
|
else
|
||||||
complete -o default -o nospace -F __start_%s %s
|
complete -o default -o nospace -F __start_%s %s
|
||||||
fi
|
fi
|
||||||
|
|
||||||
`, name, name, name, name)
|
`, name, name, name, name))
|
||||||
if err != nil {
|
buf.WriteString("# ex: ts=4 sw=4 et filetype=sh\n")
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = fmt.Fprintf(w, "# ex: ts=4 sw=4 et filetype=sh\n")
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeCommands(cmd *Command, w io.Writer) error {
|
func writeCommands(buf *bytes.Buffer, cmd *Command) {
|
||||||
if _, err := fmt.Fprintf(w, " commands=()\n"); err != nil {
|
buf.WriteString(" commands=()\n")
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, c := range cmd.Commands() {
|
for _, c := range cmd.Commands() {
|
||||||
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, err := fmt.Fprintf(w, " commands+=(%q)\n", c.Name()); err != nil {
|
buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name()))
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
buf.WriteString("\n")
|
||||||
_, err := fmt.Fprintf(w, "\n")
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) error {
|
func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string) {
|
||||||
for key, value := range annotations {
|
for key, value := range annotations {
|
||||||
switch key {
|
switch key {
|
||||||
case BashCompFilenameExt:
|
case BashCompFilenameExt:
|
||||||
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
|
buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var ext string
|
||||||
if len(value) > 0 {
|
if len(value) > 0 {
|
||||||
ext := "__handle_filename_extension_flag " + strings.Join(value, "|")
|
ext = "__handle_filename_extension_flag " + strings.Join(value, "|")
|
||||||
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
|
||||||
} else {
|
} else {
|
||||||
ext := "_filedir"
|
ext = "_filedir"
|
||||||
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext))
|
||||||
case BashCompCustom:
|
case BashCompCustom:
|
||||||
_, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name)
|
buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name))
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(value) > 0 {
|
if len(value) > 0 {
|
||||||
handlers := strings.Join(value, "; ")
|
handlers := strings.Join(value, "; ")
|
||||||
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", handlers)
|
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", handlers))
|
||||||
} else {
|
} else {
|
||||||
_, err = fmt.Fprintf(w, " flags_completion+=(:)\n")
|
buf.WriteString(" flags_completion+=(:)\n")
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
case BashCompSubdirsInDir:
|
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 {
|
if len(value) == 1 {
|
||||||
ext := "__handle_subdirs_in_dir_flag " + value[0]
|
ext = "__handle_subdirs_in_dir_flag " + value[0]
|
||||||
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
|
||||||
} else {
|
} else {
|
||||||
ext := "_filedir -d"
|
ext = "_filedir -d"
|
||||||
_, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext)
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext))
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeShortFlag(flag *pflag.Flag, w io.Writer) error {
|
func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
||||||
b := (len(flag.NoOptDefVal) > 0)
|
|
||||||
name := flag.Shorthand
|
name := flag.Shorthand
|
||||||
format := " "
|
format := " "
|
||||||
if !b {
|
if len(flag.NoOptDefVal) == 0 {
|
||||||
format += "two_word_"
|
format += "two_word_"
|
||||||
}
|
}
|
||||||
format += "flags+=(\"-%s\")\n"
|
format += "flags+=(\"-%s\")\n"
|
||||||
if _, err := fmt.Fprintf(w, format, name); err != nil {
|
buf.WriteString(fmt.Sprintf(format, name))
|
||||||
return err
|
writeFlagHandler(buf, "-"+name, flag.Annotations)
|
||||||
}
|
|
||||||
return writeFlagHandler("-"+name, flag.Annotations, w)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlag(flag *pflag.Flag, w io.Writer) error {
|
func writeFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
||||||
b := (len(flag.NoOptDefVal) > 0)
|
|
||||||
name := flag.Name
|
name := flag.Name
|
||||||
format := " flags+=(\"--%s"
|
format := " flags+=(\"--%s"
|
||||||
if !b {
|
if len(flag.NoOptDefVal) == 0 {
|
||||||
format += "="
|
format += "="
|
||||||
}
|
}
|
||||||
format += "\")\n"
|
format += "\")\n"
|
||||||
if _, err := fmt.Fprintf(w, format, name); err != nil {
|
buf.WriteString(fmt.Sprintf(format, name))
|
||||||
return err
|
writeFlagHandler(buf, "--"+name, flag.Annotations)
|
||||||
}
|
|
||||||
return writeFlagHandler("--"+name, flag.Annotations, w)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeLocalNonPersistentFlag(flag *pflag.Flag, w io.Writer) error {
|
func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
||||||
b := (len(flag.NoOptDefVal) > 0)
|
|
||||||
name := flag.Name
|
name := flag.Name
|
||||||
format := " local_nonpersistent_flags+=(\"--%s"
|
format := " local_nonpersistent_flags+=(\"--%s"
|
||||||
if !b {
|
if len(flag.NoOptDefVal) == 0 {
|
||||||
format += "="
|
format += "="
|
||||||
}
|
}
|
||||||
format += "\")\n"
|
format += "\")\n"
|
||||||
if _, err := fmt.Fprintf(w, format, name); err != nil {
|
buf.WriteString(fmt.Sprintf(format, name))
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlags(cmd *Command, w io.Writer) error {
|
func writeFlags(buf *bytes.Buffer, cmd *Command) {
|
||||||
_, err := fmt.Fprintf(w, ` flags=()
|
buf.WriteString(` flags=()
|
||||||
two_word_flags=()
|
two_word_flags=()
|
||||||
local_nonpersistent_flags=()
|
local_nonpersistent_flags=()
|
||||||
flags_with_completion=()
|
flags_with_completion=()
|
||||||
flags_completion=()
|
flags_completion=()
|
||||||
|
|
||||||
`)
|
`)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
localNonPersistentFlags := cmd.LocalNonPersistentFlags()
|
localNonPersistentFlags := cmd.LocalNonPersistentFlags()
|
||||||
var visitErr error
|
|
||||||
cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
||||||
if err := writeFlag(flag, w); err != nil {
|
if nonCompletableFlag(flag) {
|
||||||
visitErr = err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
writeFlag(buf, flag)
|
||||||
if len(flag.Shorthand) > 0 {
|
if len(flag.Shorthand) > 0 {
|
||||||
if err := writeShortFlag(flag, w); err != nil {
|
writeShortFlag(buf, flag)
|
||||||
visitErr = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if localNonPersistentFlags.Lookup(flag.Name) != nil {
|
if localNonPersistentFlags.Lookup(flag.Name) != nil {
|
||||||
if err := writeLocalNonPersistentFlag(flag, w); err != nil {
|
writeLocalNonPersistentFlag(buf, flag)
|
||||||
visitErr = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if visitErr != nil {
|
|
||||||
return visitErr
|
|
||||||
}
|
|
||||||
cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
||||||
if err := writeFlag(flag, w); err != nil {
|
if nonCompletableFlag(flag) {
|
||||||
visitErr = err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
writeFlag(buf, flag)
|
||||||
if len(flag.Shorthand) > 0 {
|
if len(flag.Shorthand) > 0 {
|
||||||
if err := writeShortFlag(flag, w); err != nil {
|
writeShortFlag(buf, flag)
|
||||||
visitErr = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if visitErr != nil {
|
|
||||||
return visitErr
|
buf.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = fmt.Fprintf(w, "\n")
|
func writeRequiredFlag(buf *bytes.Buffer, cmd *Command) {
|
||||||
return err
|
buf.WriteString(" must_have_one_flag=()\n")
|
||||||
}
|
|
||||||
|
|
||||||
func writeRequiredFlag(cmd *Command, w io.Writer) error {
|
|
||||||
if _, err := fmt.Fprintf(w, " must_have_one_flag=()\n"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
flags := cmd.NonInheritedFlags()
|
flags := cmd.NonInheritedFlags()
|
||||||
var visitErr error
|
|
||||||
flags.VisitAll(func(flag *pflag.Flag) {
|
flags.VisitAll(func(flag *pflag.Flag) {
|
||||||
|
if nonCompletableFlag(flag) {
|
||||||
|
return
|
||||||
|
}
|
||||||
for key := range flag.Annotations {
|
for key := range flag.Annotations {
|
||||||
switch key {
|
switch key {
|
||||||
case BashCompOneRequiredFlag:
|
case BashCompOneRequiredFlag:
|
||||||
format := " must_have_one_flag+=(\"--%s"
|
format := " must_have_one_flag+=(\"--%s"
|
||||||
b := (flag.Value.Type() == "bool")
|
if flag.Value.Type() != "bool" {
|
||||||
if !b {
|
|
||||||
format += "="
|
format += "="
|
||||||
}
|
}
|
||||||
format += "\")\n"
|
format += "\")\n"
|
||||||
if _, err := fmt.Fprintf(w, format, flag.Name); err != nil {
|
buf.WriteString(fmt.Sprintf(format, flag.Name))
|
||||||
visitErr = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(flag.Shorthand) > 0 {
|
if len(flag.Shorthand) > 0 {
|
||||||
if _, err := fmt.Fprintf(w, " must_have_one_flag+=(\"-%s\")\n", flag.Shorthand); err != nil {
|
buf.WriteString(fmt.Sprintf(" must_have_one_flag+=(\"-%s\")\n", flag.Shorthand))
|
||||||
visitErr = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return visitErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeRequiredNouns(cmd *Command, w io.Writer) error {
|
func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) {
|
||||||
if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil {
|
buf.WriteString(" must_have_one_noun=()\n")
|
||||||
return err
|
|
||||||
}
|
|
||||||
sort.Sort(sort.StringSlice(cmd.ValidArgs))
|
sort.Sort(sort.StringSlice(cmd.ValidArgs))
|
||||||
for _, value := range cmd.ValidArgs {
|
for _, value := range cmd.ValidArgs {
|
||||||
if _, err := fmt.Fprintf(w, " must_have_one_noun+=(%q)\n", value); err != nil {
|
buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value))
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeArgAliases(cmd *Command, w io.Writer) error {
|
func writeArgAliases(buf *bytes.Buffer, cmd *Command) {
|
||||||
if _, err := fmt.Fprintf(w, " noun_aliases=()\n"); err != nil {
|
buf.WriteString(" noun_aliases=()\n")
|
||||||
return err
|
|
||||||
}
|
|
||||||
sort.Sort(sort.StringSlice(cmd.ArgAliases))
|
sort.Sort(sort.StringSlice(cmd.ArgAliases))
|
||||||
for _, value := range cmd.ArgAliases {
|
for _, value := range cmd.ArgAliases {
|
||||||
if _, err := fmt.Fprintf(w, " noun_aliases+=(%q)\n", value); err != nil {
|
buf.WriteString(fmt.Sprintf(" noun_aliases+=(%q)\n", value))
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func gen(cmd *Command, w io.Writer) error {
|
func gen(buf *bytes.Buffer, cmd *Command) {
|
||||||
for _, c := range cmd.Commands() {
|
for _, c := range cmd.Commands() {
|
||||||
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
if !c.IsAvailableCommand() || c == cmd.helpCommand {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := gen(c, w); err != nil {
|
gen(buf, c)
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
commandName := cmd.CommandPath()
|
commandName := cmd.CommandPath()
|
||||||
commandName = strings.Replace(commandName, " ", "_", -1)
|
commandName = strings.Replace(commandName, " ", "_", -1)
|
||||||
commandName = strings.Replace(commandName, ":", "__", -1)
|
commandName = strings.Replace(commandName, ":", "__", -1)
|
||||||
if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil {
|
buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName))
|
||||||
return err
|
buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName))
|
||||||
}
|
writeCommands(buf, cmd)
|
||||||
if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil {
|
writeFlags(buf, cmd)
|
||||||
return err
|
writeRequiredFlag(buf, cmd)
|
||||||
}
|
writeRequiredNouns(buf, cmd)
|
||||||
if err := writeCommands(cmd, w); err != nil {
|
writeArgAliases(buf, cmd)
|
||||||
return err
|
buf.WriteString("}\n\n")
|
||||||
}
|
|
||||||
if err := writeFlags(cmd, w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := writeRequiredFlag(cmd, w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := writeRequiredNouns(cmd, w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := writeArgAliases(cmd, w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := fmt.Fprintf(w, "}\n\n"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Command) GenBashCompletion(w io.Writer) error {
|
// GenBashCompletion generates bash completion file and writes to the passed writer.
|
||||||
if err := preamble(w, cmd.Name()); err != nil {
|
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")
|
||||||
|
}
|
||||||
|
gen(buf, c)
|
||||||
|
writePostscript(buf, c.Name())
|
||||||
|
|
||||||
|
_, err := buf.WriteTo(w)
|
||||||
return err
|
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
|
|
||||||
}
|
|
||||||
return postscript(w, cmd.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cmd *Command) GenBashCompletionFile(filename string) error {
|
func nonCompletableFlag(flag *pflag.Flag) bool {
|
||||||
|
return flag.Hidden || len(flag.Deprecated) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenBashCompletionFile generates bash completion file.
|
||||||
|
func (c *Command) GenBashCompletionFile(filename string) error {
|
||||||
outFile, err := os.Create(filename)
|
outFile, err := os.Create(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer outFile.Close()
|
defer outFile.Close()
|
||||||
|
|
||||||
return cmd.GenBashCompletion(outFile)
|
return c.GenBashCompletion(outFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists.
|
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists.
|
||||||
func (cmd *Command) MarkFlagRequired(name string) error {
|
func (c *Command) MarkFlagRequired(name string) error {
|
||||||
return MarkFlagRequired(cmd.Flags(), name)
|
return MarkFlagRequired(c.Flags(), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag, if it exists.
|
// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag, if it exists.
|
||||||
func (cmd *Command) MarkPersistentFlagRequired(name string) error {
|
func (c *Command) MarkPersistentFlagRequired(name string) error {
|
||||||
return MarkFlagRequired(cmd.PersistentFlags(), name)
|
return MarkFlagRequired(c.PersistentFlags(), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists.
|
// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists.
|
||||||
@ -601,20 +508,20 @@ func MarkFlagRequired(flags *pflag.FlagSet, name string) error {
|
|||||||
|
|
||||||
// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists.
|
// 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.
|
// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.
|
||||||
func (cmd *Command) MarkFlagFilename(name string, extensions ...string) error {
|
func (c *Command) MarkFlagFilename(name string, extensions ...string) error {
|
||||||
return MarkFlagFilename(cmd.Flags(), name, extensions...)
|
return MarkFlagFilename(c.Flags(), name, extensions...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists.
|
// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists.
|
||||||
// Generated bash autocompletion will call the bash function f for the flag.
|
// Generated bash autocompletion will call the bash function f for the flag.
|
||||||
func (cmd *Command) MarkFlagCustom(name string, f string) error {
|
func (c *Command) MarkFlagCustom(name string, f string) error {
|
||||||
return MarkFlagCustom(cmd.Flags(), name, f)
|
return MarkFlagCustom(c.Flags(), name, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists.
|
// 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.
|
// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.
|
||||||
func (cmd *Command) MarkPersistentFlagFilename(name string, extensions ...string) error {
|
func (c *Command) MarkPersistentFlagFilename(name string, extensions ...string) error {
|
||||||
return MarkFlagFilename(cmd.PersistentFlags(), name, extensions...)
|
return MarkFlagFilename(c.PersistentFlags(), name, extensions...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists.
|
// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists.
|
||||||
|
33
vendor/github.com/spf13/cobra/cobra.go
generated
vendored
33
vendor/github.com/spf13/cobra/cobra.go
generated
vendored
@ -29,6 +29,7 @@ import (
|
|||||||
var templateFuncs = template.FuncMap{
|
var templateFuncs = template.FuncMap{
|
||||||
"trim": strings.TrimSpace,
|
"trim": strings.TrimSpace,
|
||||||
"trimRightSpace": trimRightSpace,
|
"trimRightSpace": trimRightSpace,
|
||||||
|
"trimTrailingWhitespaces": trimRightSpace,
|
||||||
"appendIfNotPresent": appendIfNotPresent,
|
"appendIfNotPresent": appendIfNotPresent,
|
||||||
"rpad": rpad,
|
"rpad": rpad,
|
||||||
"gt": Gt,
|
"gt": Gt,
|
||||||
@ -37,21 +38,31 @@ var templateFuncs = template.FuncMap{
|
|||||||
|
|
||||||
var initializers []func()
|
var initializers []func()
|
||||||
|
|
||||||
// automatic prefix matching can be a dangerous thing to automatically enable in CLI tools.
|
// EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing
|
||||||
// Set this to true to enable it
|
// to automatically enable in CLI tools.
|
||||||
|
// Set this to true to enable it.
|
||||||
var EnablePrefixMatching = false
|
var EnablePrefixMatching = false
|
||||||
|
|
||||||
// EnableCommandSorting controls sorting of the slice of commands, which is turned on by default.
|
// EnableCommandSorting controls sorting of the slice of commands, which is turned on by default.
|
||||||
// To disable sorting, set it to false.
|
// To disable sorting, set it to false.
|
||||||
var EnableCommandSorting = true
|
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
|
// AddTemplateFunc adds a template function that's available to Usage and Help
|
||||||
// template generation.
|
// template generation.
|
||||||
func AddTemplateFunc(name string, tmplFunc interface{}) {
|
func AddTemplateFunc(name string, tmplFunc interface{}) {
|
||||||
templateFuncs[name] = tmplFunc
|
templateFuncs[name] = tmplFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
//AddTemplateFuncs adds multiple template functions availalble to Usage and
|
// AddTemplateFuncs adds multiple template functions that are available to Usage and
|
||||||
// Help template generation.
|
// Help template generation.
|
||||||
func AddTemplateFuncs(tmplFuncs template.FuncMap) {
|
func AddTemplateFuncs(tmplFuncs template.FuncMap) {
|
||||||
for k, v := range tmplFuncs {
|
for k, v := range tmplFuncs {
|
||||||
@ -61,11 +72,11 @@ func AddTemplateFuncs(tmplFuncs template.FuncMap) {
|
|||||||
|
|
||||||
// OnInitialize takes a series of func() arguments and appends them to a slice of func().
|
// OnInitialize takes a series of func() arguments and appends them to a slice of func().
|
||||||
func OnInitialize(y ...func()) {
|
func OnInitialize(y ...func()) {
|
||||||
for _, x := range y {
|
initializers = append(initializers, y...)
|
||||||
initializers = append(initializers, x)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME Gt is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra.
|
||||||
|
|
||||||
// Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans,
|
// Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans,
|
||||||
// Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as
|
// Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as
|
||||||
// ints and then compared.
|
// ints and then compared.
|
||||||
@ -96,6 +107,8 @@ func Gt(a interface{}, b interface{}) bool {
|
|||||||
return left > right
|
return left > right
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME Eq is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra.
|
||||||
|
|
||||||
// Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic.
|
// Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic.
|
||||||
func Eq(a interface{}, b interface{}) bool {
|
func Eq(a interface{}, b interface{}) bool {
|
||||||
av := reflect.ValueOf(a)
|
av := reflect.ValueOf(a)
|
||||||
@ -116,7 +129,9 @@ func trimRightSpace(s string) string {
|
|||||||
return strings.TrimRightFunc(s, unicode.IsSpace)
|
return strings.TrimRightFunc(s, unicode.IsSpace)
|
||||||
}
|
}
|
||||||
|
|
||||||
// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s
|
// FIXME appendIfNotPresent is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra.
|
||||||
|
|
||||||
|
// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s.
|
||||||
func appendIfNotPresent(s, stringToAppend string) string {
|
func appendIfNotPresent(s, stringToAppend string) string {
|
||||||
if strings.Contains(s, stringToAppend) {
|
if strings.Contains(s, stringToAppend) {
|
||||||
return s
|
return s
|
||||||
@ -124,7 +139,7 @@ func appendIfNotPresent(s, stringToAppend string) string {
|
|||||||
return s + " " + stringToAppend
|
return s + " " + stringToAppend
|
||||||
}
|
}
|
||||||
|
|
||||||
//rpad adds padding to the right of a string
|
// rpad adds padding to the right of a string.
|
||||||
func rpad(s string, padding int) string {
|
func rpad(s string, padding int) string {
|
||||||
template := fmt.Sprintf("%%-%ds", padding)
|
template := fmt.Sprintf("%%-%ds", padding)
|
||||||
return fmt.Sprintf(template, s)
|
return fmt.Sprintf(template, s)
|
||||||
@ -138,7 +153,7 @@ func tmpl(w io.Writer, text string, data interface{}) error {
|
|||||||
return t.Execute(w, data)
|
return t.Execute(w, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ld compares two strings and returns the levenshtein distance between them
|
// ld compares two strings and returns the levenshtein distance between them.
|
||||||
func ld(s, t string, ignoreCase bool) int {
|
func ld(s, t string, ignoreCase bool) int {
|
||||||
if ignoreCase {
|
if ignoreCase {
|
||||||
s = strings.ToLower(s)
|
s = strings.ToLower(s)
|
||||||
|
865
vendor/github.com/spf13/cobra/command.go
generated
vendored
865
vendor/github.com/spf13/cobra/command.go
generated
vendored
File diff suppressed because it is too large
Load Diff
8
vendor/github.com/spf13/cobra/command_win.go
generated
vendored
8
vendor/github.com/spf13/cobra/command_win.go
generated
vendored
@ -11,14 +11,8 @@ import (
|
|||||||
|
|
||||||
var preExecHookFn = preExecHook
|
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) {
|
func preExecHook(c *Command) {
|
||||||
if mousetrap.StartedByExplorer() {
|
if MousetrapHelpText != "" && mousetrap.StartedByExplorer() {
|
||||||
c.Print(MousetrapHelpText)
|
c.Print(MousetrapHelpText)
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
126
vendor/github.com/spf13/cobra/zsh_completions.go
generated
vendored
Normal file
126
vendor/github.com/spf13/cobra/zsh_completions.go
generated
vendored
Normal file
@ -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
|
||||||
|
}
|
25
vendor/github.com/spf13/pflag/README.md
generated
vendored
25
vendor/github.com/spf13/pflag/README.md
generated
vendored
@ -246,6 +246,25 @@ It is possible to mark a flag as hidden, meaning it will still function as norma
|
|||||||
flags.MarkHidden("secretFlag")
|
flags.MarkHidden("secretFlag")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Disable sorting of flags
|
||||||
|
`pflag` allows you to disable sorting of flags for help and usage message.
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
```go
|
||||||
|
flags.BoolP("verbose", "v", false, "verbose output")
|
||||||
|
flags.String("coolflag", "yeaah", "it's really cool flag")
|
||||||
|
flags.Int("usefulflag", 777, "sometimes it's very useful")
|
||||||
|
flags.SortFlags = false
|
||||||
|
flags.PrintDefaults()
|
||||||
|
```
|
||||||
|
**Output**:
|
||||||
|
```
|
||||||
|
-v, --verbose verbose output
|
||||||
|
--coolflag string it's really cool flag (default "yeaah")
|
||||||
|
--usefulflag int sometimes it's very useful (default 777)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Supporting Go flags when using pflag
|
## Supporting Go flags when using pflag
|
||||||
In order to support flags defined using Go's `flag` package, they must be added to the `pflag` flagset. This is usually necessary
|
In order to support flags defined using Go's `flag` package, they must be added to the `pflag` flagset. This is usually necessary
|
||||||
to support flags defined by third-party dependencies (e.g. `golang/glog`).
|
to support flags defined by third-party dependencies (e.g. `golang/glog`).
|
||||||
@ -270,8 +289,8 @@ func main() {
|
|||||||
You can see the full reference documentation of the pflag package
|
You can see the full reference documentation of the pflag package
|
||||||
[at godoc.org][3], or through go's standard documentation system by
|
[at godoc.org][3], or through go's standard documentation system by
|
||||||
running `godoc -http=:6060` and browsing to
|
running `godoc -http=:6060` and browsing to
|
||||||
[http://localhost:6060/pkg/github.com/ogier/pflag][2] after
|
[http://localhost:6060/pkg/github.com/spf13/pflag][2] after
|
||||||
installation.
|
installation.
|
||||||
|
|
||||||
[2]: http://localhost:6060/pkg/github.com/ogier/pflag
|
[2]: http://localhost:6060/pkg/github.com/spf13/pflag
|
||||||
[3]: http://godoc.org/github.com/ogier/pflag
|
[3]: http://godoc.org/github.com/spf13/pflag
|
||||||
|
4
vendor/github.com/spf13/pflag/count.go
generated
vendored
4
vendor/github.com/spf13/pflag/count.go
generated
vendored
@ -83,7 +83,9 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count like Count only the flag is placed on the CommandLine isntead of a given flag set
|
// Count defines a count flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of an int variable that stores the value of the flag.
|
||||||
|
// A count flag will add 1 to its value evey time it is found on the command line
|
||||||
func Count(name string, usage string) *int {
|
func Count(name string, usage string) *int {
|
||||||
return CommandLine.CountP(name, "", usage)
|
return CommandLine.CountP(name, "", usage)
|
||||||
}
|
}
|
||||||
|
239
vendor/github.com/spf13/pflag/flag.go
generated
vendored
239
vendor/github.com/spf13/pflag/flag.go
generated
vendored
@ -16,7 +16,7 @@ pflag is a drop-in replacement of Go's native flag package. If you import
|
|||||||
pflag under the name "flag" then all code should continue to function
|
pflag under the name "flag" then all code should continue to function
|
||||||
with no changes.
|
with no changes.
|
||||||
|
|
||||||
import flag "github.com/ogier/pflag"
|
import flag "github.com/spf13/pflag"
|
||||||
|
|
||||||
There is one exception to this: if you directly instantiate the Flag struct
|
There is one exception to this: if you directly instantiate the Flag struct
|
||||||
there is one more field "Shorthand" that you will need to set.
|
there is one more field "Shorthand" that you will need to set.
|
||||||
@ -134,14 +134,21 @@ type FlagSet struct {
|
|||||||
// a custom error handler.
|
// a custom error handler.
|
||||||
Usage func()
|
Usage func()
|
||||||
|
|
||||||
|
// SortFlags is used to indicate, if user wants to have sorted flags in
|
||||||
|
// help/usage messages.
|
||||||
|
SortFlags bool
|
||||||
|
|
||||||
name string
|
name string
|
||||||
parsed bool
|
parsed bool
|
||||||
actual map[NormalizedName]*Flag
|
actual map[NormalizedName]*Flag
|
||||||
|
orderedActual []*Flag
|
||||||
|
sortedActual []*Flag
|
||||||
formal map[NormalizedName]*Flag
|
formal map[NormalizedName]*Flag
|
||||||
|
orderedFormal []*Flag
|
||||||
|
sortedFormal []*Flag
|
||||||
shorthands map[byte]*Flag
|
shorthands map[byte]*Flag
|
||||||
args []string // arguments after flags
|
args []string // arguments after flags
|
||||||
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
|
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
|
||||||
exitOnError bool // does the program exit if there's an error?
|
|
||||||
errorHandling ErrorHandling
|
errorHandling ErrorHandling
|
||||||
output io.Writer // nil means stderr; use out() accessor
|
output io.Writer // nil means stderr; use out() accessor
|
||||||
interspersed bool // allow interspersed option/non-option args
|
interspersed bool // allow interspersed option/non-option args
|
||||||
@ -194,11 +201,13 @@ func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
|
|||||||
// "--getUrl" which may also be translated to "geturl" and everything will work.
|
// "--getUrl" which may also be translated to "geturl" and everything will work.
|
||||||
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
|
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
|
||||||
f.normalizeNameFunc = n
|
f.normalizeNameFunc = n
|
||||||
for k, v := range f.formal {
|
f.sortedFormal = f.sortedFormal[:0]
|
||||||
delete(f.formal, k)
|
for k, v := range f.orderedFormal {
|
||||||
nname := f.normalizeFlagName(string(k))
|
delete(f.formal, NormalizedName(v.Name))
|
||||||
f.formal[nname] = v
|
nname := f.normalizeFlagName(v.Name)
|
||||||
v.Name = string(nname)
|
v.Name = string(nname)
|
||||||
|
f.formal[nname] = v
|
||||||
|
f.orderedFormal[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,10 +238,25 @@ func (f *FlagSet) SetOutput(output io.Writer) {
|
|||||||
f.output = output
|
f.output = output
|
||||||
}
|
}
|
||||||
|
|
||||||
// VisitAll visits the flags in lexicographical order, calling fn for each.
|
// VisitAll visits the flags in lexicographical order or
|
||||||
|
// in primordial order if f.SortFlags is false, calling fn for each.
|
||||||
// It visits all flags, even those not set.
|
// It visits all flags, even those not set.
|
||||||
func (f *FlagSet) VisitAll(fn func(*Flag)) {
|
func (f *FlagSet) VisitAll(fn func(*Flag)) {
|
||||||
for _, flag := range sortFlags(f.formal) {
|
if len(f.formal) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var flags []*Flag
|
||||||
|
if f.SortFlags {
|
||||||
|
if len(f.formal) != len(f.sortedFormal) {
|
||||||
|
f.sortedFormal = sortFlags(f.formal)
|
||||||
|
}
|
||||||
|
flags = f.sortedFormal
|
||||||
|
} else {
|
||||||
|
flags = f.orderedFormal
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, flag := range flags {
|
||||||
fn(flag)
|
fn(flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,22 +277,39 @@ func (f *FlagSet) HasAvailableFlags() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// VisitAll visits the command-line flags in lexicographical order, calling
|
// VisitAll visits the command-line flags in lexicographical order or
|
||||||
// fn for each. It visits all flags, even those not set.
|
// in primordial order if f.SortFlags is false, calling fn for each.
|
||||||
|
// It visits all flags, even those not set.
|
||||||
func VisitAll(fn func(*Flag)) {
|
func VisitAll(fn func(*Flag)) {
|
||||||
CommandLine.VisitAll(fn)
|
CommandLine.VisitAll(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visit visits the flags in lexicographical order, calling fn for each.
|
// Visit visits the flags in lexicographical order or
|
||||||
|
// in primordial order if f.SortFlags is false, calling fn for each.
|
||||||
// It visits only those flags that have been set.
|
// It visits only those flags that have been set.
|
||||||
func (f *FlagSet) Visit(fn func(*Flag)) {
|
func (f *FlagSet) Visit(fn func(*Flag)) {
|
||||||
for _, flag := range sortFlags(f.actual) {
|
if len(f.actual) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var flags []*Flag
|
||||||
|
if f.SortFlags {
|
||||||
|
if len(f.actual) != len(f.sortedActual) {
|
||||||
|
f.sortedActual = sortFlags(f.actual)
|
||||||
|
}
|
||||||
|
flags = f.sortedActual
|
||||||
|
} else {
|
||||||
|
flags = f.orderedActual
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, flag := range flags {
|
||||||
fn(flag)
|
fn(flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visit visits the command-line flags in lexicographical order, calling fn
|
// Visit visits the command-line flags in lexicographical order or
|
||||||
// for each. It visits only those flags that have been set.
|
// in primordial order if f.SortFlags is false, calling fn for each.
|
||||||
|
// It visits only those flags that have been set.
|
||||||
func Visit(fn func(*Flag)) {
|
func Visit(fn func(*Flag)) {
|
||||||
CommandLine.Visit(fn)
|
CommandLine.Visit(fn)
|
||||||
}
|
}
|
||||||
@ -278,6 +319,22 @@ func (f *FlagSet) Lookup(name string) *Flag {
|
|||||||
return f.lookup(f.normalizeFlagName(name))
|
return f.lookup(f.normalizeFlagName(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShorthandLookup returns the Flag structure of the short handed flag,
|
||||||
|
// returning nil if none exists.
|
||||||
|
// It panics, if len(name) > 1.
|
||||||
|
func (f *FlagSet) ShorthandLookup(name string) *Flag {
|
||||||
|
if name == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(name) > 1 {
|
||||||
|
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
|
||||||
|
fmt.Fprintf(f.out(), msg)
|
||||||
|
panic(msg)
|
||||||
|
}
|
||||||
|
c := name[0]
|
||||||
|
return f.shorthands[c]
|
||||||
|
}
|
||||||
|
|
||||||
// lookup returns the Flag structure of the named flag, returning nil if none exists.
|
// lookup returns the Flag structure of the named flag, returning nil if none exists.
|
||||||
func (f *FlagSet) lookup(name NormalizedName) *Flag {
|
func (f *FlagSet) lookup(name NormalizedName) *Flag {
|
||||||
return f.formal[name]
|
return f.formal[name]
|
||||||
@ -319,7 +376,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
|
|||||||
if flag == nil {
|
if flag == nil {
|
||||||
return fmt.Errorf("flag %q does not exist", name)
|
return fmt.Errorf("flag %q does not exist", name)
|
||||||
}
|
}
|
||||||
if len(usageMessage) == 0 {
|
if usageMessage == "" {
|
||||||
return fmt.Errorf("deprecated message for flag %q must be set", name)
|
return fmt.Errorf("deprecated message for flag %q must be set", name)
|
||||||
}
|
}
|
||||||
flag.Deprecated = usageMessage
|
flag.Deprecated = usageMessage
|
||||||
@ -334,7 +391,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro
|
|||||||
if flag == nil {
|
if flag == nil {
|
||||||
return fmt.Errorf("flag %q does not exist", name)
|
return fmt.Errorf("flag %q does not exist", name)
|
||||||
}
|
}
|
||||||
if len(usageMessage) == 0 {
|
if usageMessage == "" {
|
||||||
return fmt.Errorf("deprecated message for flag %q must be set", name)
|
return fmt.Errorf("deprecated message for flag %q must be set", name)
|
||||||
}
|
}
|
||||||
flag.ShorthandDeprecated = usageMessage
|
flag.ShorthandDeprecated = usageMessage
|
||||||
@ -358,6 +415,12 @@ func Lookup(name string) *Flag {
|
|||||||
return CommandLine.Lookup(name)
|
return CommandLine.Lookup(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShorthandLookup returns the Flag structure of the short handed flag,
|
||||||
|
// returning nil if none exists.
|
||||||
|
func ShorthandLookup(name string) *Flag {
|
||||||
|
return CommandLine.ShorthandLookup(name)
|
||||||
|
}
|
||||||
|
|
||||||
// Set sets the value of the named flag.
|
// Set sets the value of the named flag.
|
||||||
func (f *FlagSet) Set(name, value string) error {
|
func (f *FlagSet) Set(name, value string) error {
|
||||||
normalName := f.normalizeFlagName(name)
|
normalName := f.normalizeFlagName(name)
|
||||||
@ -365,17 +428,28 @@ func (f *FlagSet) Set(name, value string) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("no such flag -%v", name)
|
return fmt.Errorf("no such flag -%v", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := flag.Value.Set(value)
|
err := flag.Value.Set(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
var flagName string
|
||||||
|
if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
|
||||||
|
flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
|
||||||
|
} else {
|
||||||
|
flagName = fmt.Sprintf("--%s", flag.Name)
|
||||||
}
|
}
|
||||||
|
return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
|
||||||
|
}
|
||||||
|
|
||||||
if f.actual == nil {
|
if f.actual == nil {
|
||||||
f.actual = make(map[NormalizedName]*Flag)
|
f.actual = make(map[NormalizedName]*Flag)
|
||||||
}
|
}
|
||||||
f.actual[normalName] = flag
|
f.actual[normalName] = flag
|
||||||
|
f.orderedActual = append(f.orderedActual, flag)
|
||||||
|
|
||||||
flag.Changed = true
|
flag.Changed = true
|
||||||
if len(flag.Deprecated) > 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
if flag.Deprecated != "" {
|
||||||
|
fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -557,28 +631,28 @@ func wrap(i, w int, s string) string {
|
|||||||
// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no
|
// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no
|
||||||
// wrapping)
|
// wrapping)
|
||||||
func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
||||||
x := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
lines := make([]string, 0, len(f.formal))
|
lines := make([]string, 0, len(f.formal))
|
||||||
|
|
||||||
maxlen := 0
|
maxlen := 0
|
||||||
f.VisitAll(func(flag *Flag) {
|
f.VisitAll(func(flag *Flag) {
|
||||||
if len(flag.Deprecated) > 0 || flag.Hidden {
|
if flag.Deprecated != "" || flag.Hidden {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
line := ""
|
line := ""
|
||||||
if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 {
|
if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
|
||||||
line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name)
|
line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name)
|
||||||
} else {
|
} else {
|
||||||
line = fmt.Sprintf(" --%s", flag.Name)
|
line = fmt.Sprintf(" --%s", flag.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
varname, usage := UnquoteUsage(flag)
|
varname, usage := UnquoteUsage(flag)
|
||||||
if len(varname) > 0 {
|
if varname != "" {
|
||||||
line += " " + varname
|
line += " " + varname
|
||||||
}
|
}
|
||||||
if len(flag.NoOptDefVal) > 0 {
|
if flag.NoOptDefVal != "" {
|
||||||
switch flag.Value.Type() {
|
switch flag.Value.Type() {
|
||||||
case "string":
|
case "string":
|
||||||
line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
|
line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
|
||||||
@ -601,7 +675,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
|||||||
line += usage
|
line += usage
|
||||||
if !flag.defaultIsZeroValue() {
|
if !flag.defaultIsZeroValue() {
|
||||||
if flag.Value.Type() == "string" {
|
if flag.Value.Type() == "string" {
|
||||||
line += fmt.Sprintf(" (default \"%s\")", flag.DefValue)
|
line += fmt.Sprintf(" (default %q)", flag.DefValue)
|
||||||
} else {
|
} else {
|
||||||
line += fmt.Sprintf(" (default %s)", flag.DefValue)
|
line += fmt.Sprintf(" (default %s)", flag.DefValue)
|
||||||
}
|
}
|
||||||
@ -614,10 +688,10 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
|||||||
sidx := strings.Index(line, "\x00")
|
sidx := strings.Index(line, "\x00")
|
||||||
spacing := strings.Repeat(" ", maxlen-sidx)
|
spacing := strings.Repeat(" ", maxlen-sidx)
|
||||||
// maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx
|
// maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx
|
||||||
fmt.Fprintln(x, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
|
fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
return x.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlagUsages returns a string containing the usage information for all flags in
|
// FlagUsages returns a string containing the usage information for all flags in
|
||||||
@ -714,11 +788,10 @@ func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {
|
|||||||
|
|
||||||
// AddFlag will add the flag to the FlagSet
|
// AddFlag will add the flag to the FlagSet
|
||||||
func (f *FlagSet) AddFlag(flag *Flag) {
|
func (f *FlagSet) AddFlag(flag *Flag) {
|
||||||
// Call normalizeFlagName function only once
|
|
||||||
normalizedFlagName := f.normalizeFlagName(flag.Name)
|
normalizedFlagName := f.normalizeFlagName(flag.Name)
|
||||||
|
|
||||||
_, alreadythere := f.formal[normalizedFlagName]
|
_, alreadyThere := f.formal[normalizedFlagName]
|
||||||
if alreadythere {
|
if alreadyThere {
|
||||||
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
|
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
|
||||||
fmt.Fprintln(f.out(), msg)
|
fmt.Fprintln(f.out(), msg)
|
||||||
panic(msg) // Happens only if flags are declared with identical names
|
panic(msg) // Happens only if flags are declared with identical names
|
||||||
@ -729,28 +802,31 @@ func (f *FlagSet) AddFlag(flag *Flag) {
|
|||||||
|
|
||||||
flag.Name = string(normalizedFlagName)
|
flag.Name = string(normalizedFlagName)
|
||||||
f.formal[normalizedFlagName] = flag
|
f.formal[normalizedFlagName] = flag
|
||||||
|
f.orderedFormal = append(f.orderedFormal, flag)
|
||||||
|
|
||||||
if len(flag.Shorthand) == 0 {
|
if flag.Shorthand == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(flag.Shorthand) > 1 {
|
if len(flag.Shorthand) > 1 {
|
||||||
fmt.Fprintf(f.out(), "%s shorthand more than ASCII character: %s\n", f.name, flag.Shorthand)
|
msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
|
||||||
panic("shorthand is more than one character")
|
fmt.Fprintf(f.out(), msg)
|
||||||
|
panic(msg)
|
||||||
}
|
}
|
||||||
if f.shorthands == nil {
|
if f.shorthands == nil {
|
||||||
f.shorthands = make(map[byte]*Flag)
|
f.shorthands = make(map[byte]*Flag)
|
||||||
}
|
}
|
||||||
c := flag.Shorthand[0]
|
c := flag.Shorthand[0]
|
||||||
old, alreadythere := f.shorthands[c]
|
used, alreadyThere := f.shorthands[c]
|
||||||
if alreadythere {
|
if alreadyThere {
|
||||||
fmt.Fprintf(f.out(), "%s shorthand reused: %q for %s already used for %s\n", f.name, c, flag.Name, old.Name)
|
msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
|
||||||
panic("shorthand redefinition")
|
fmt.Fprintf(f.out(), msg)
|
||||||
|
panic(msg)
|
||||||
}
|
}
|
||||||
f.shorthands[c] = flag
|
f.shorthands[c] = flag
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFlagSet adds one FlagSet to another. If a flag is already present in f
|
// AddFlagSet adds one FlagSet to another. If a flag is already present in f
|
||||||
// the flag from newSet will be ignored
|
// the flag from newSet will be ignored.
|
||||||
func (f *FlagSet) AddFlagSet(newSet *FlagSet) {
|
func (f *FlagSet) AddFlagSet(newSet *FlagSet) {
|
||||||
if newSet == nil {
|
if newSet == nil {
|
||||||
return
|
return
|
||||||
@ -798,34 +874,6 @@ func (f *FlagSet) usage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) setFlag(flag *Flag, value string, origArg string) error {
|
|
||||||
if err := flag.Value.Set(value); err != nil {
|
|
||||||
return f.failf("invalid argument %q for %s: %v", value, origArg, err)
|
|
||||||
}
|
|
||||||
// mark as visited for Visit()
|
|
||||||
if f.actual == nil {
|
|
||||||
f.actual = make(map[NormalizedName]*Flag)
|
|
||||||
}
|
|
||||||
f.actual[f.normalizeFlagName(flag.Name)] = flag
|
|
||||||
flag.Changed = true
|
|
||||||
if len(flag.Deprecated) > 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
|
||||||
}
|
|
||||||
if len(flag.ShorthandDeprecated) > 0 && containsShorthand(origArg, flag.Shorthand) {
|
|
||||||
fmt.Fprintf(os.Stderr, "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func containsShorthand(arg, shorthand string) bool {
|
|
||||||
// filter out flags --<flag_name>
|
|
||||||
if strings.HasPrefix(arg, "-") {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
arg = strings.SplitN(arg, "=", 2)[0]
|
|
||||||
return strings.Contains(arg, shorthand)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||||
a = args
|
a = args
|
||||||
name := s[2:]
|
name := s[2:]
|
||||||
@ -833,10 +881,11 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
|||||||
err = f.failf("bad flag syntax: %s", s)
|
err = f.failf("bad flag syntax: %s", s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
split := strings.SplitN(name, "=", 2)
|
split := strings.SplitN(name, "=", 2)
|
||||||
name = split[0]
|
name = split[0]
|
||||||
flag, alreadythere := f.formal[f.normalizeFlagName(name)]
|
flag, exists := f.formal[f.normalizeFlagName(name)]
|
||||||
if !alreadythere {
|
if !exists {
|
||||||
if name == "help" { // special case for nice help message.
|
if name == "help" { // special case for nice help message.
|
||||||
f.usage()
|
f.usage()
|
||||||
return a, ErrHelp
|
return a, ErrHelp
|
||||||
@ -844,11 +893,12 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
|||||||
err = f.failf("unknown flag: --%s", name)
|
err = f.failf("unknown flag: --%s", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var value string
|
var value string
|
||||||
if len(split) == 2 {
|
if len(split) == 2 {
|
||||||
// '--flag=arg'
|
// '--flag=arg'
|
||||||
value = split[1]
|
value = split[1]
|
||||||
} else if len(flag.NoOptDefVal) > 0 {
|
} else if flag.NoOptDefVal != "" {
|
||||||
// '--flag' (arg was optional)
|
// '--flag' (arg was optional)
|
||||||
value = flag.NoOptDefVal
|
value = flag.NoOptDefVal
|
||||||
} else if len(a) > 0 {
|
} else if len(a) > 0 {
|
||||||
@ -860,7 +910,8 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
|||||||
err = f.failf("flag needs an argument: %s", s)
|
err = f.failf("flag needs an argument: %s", s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = fn(flag, value, s)
|
|
||||||
|
err = fn(flag, value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -868,38 +919,49 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
|
|||||||
if strings.HasPrefix(shorthands, "test.") {
|
if strings.HasPrefix(shorthands, "test.") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
outArgs = args
|
outArgs = args
|
||||||
outShorts = shorthands[1:]
|
outShorts = shorthands[1:]
|
||||||
c := shorthands[0]
|
c := shorthands[0]
|
||||||
|
|
||||||
flag, alreadythere := f.shorthands[c]
|
flag, exists := f.shorthands[c]
|
||||||
if !alreadythere {
|
if !exists {
|
||||||
if c == 'h' { // special case for nice help message.
|
if c == 'h' { // special case for nice help message.
|
||||||
f.usage()
|
f.usage()
|
||||||
err = ErrHelp
|
err = ErrHelp
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//TODO continue on error
|
|
||||||
err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
|
err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var value string
|
var value string
|
||||||
if len(shorthands) > 2 && shorthands[1] == '=' {
|
if len(shorthands) > 2 && shorthands[1] == '=' {
|
||||||
|
// '-f=arg'
|
||||||
value = shorthands[2:]
|
value = shorthands[2:]
|
||||||
outShorts = ""
|
outShorts = ""
|
||||||
} else if len(flag.NoOptDefVal) > 0 {
|
} else if flag.NoOptDefVal != "" {
|
||||||
|
// '-f' (arg was optional)
|
||||||
value = flag.NoOptDefVal
|
value = flag.NoOptDefVal
|
||||||
} else if len(shorthands) > 1 {
|
} else if len(shorthands) > 1 {
|
||||||
|
// '-farg'
|
||||||
value = shorthands[1:]
|
value = shorthands[1:]
|
||||||
outShorts = ""
|
outShorts = ""
|
||||||
} else if len(args) > 0 {
|
} else if len(args) > 0 {
|
||||||
|
// '-f arg'
|
||||||
value = args[0]
|
value = args[0]
|
||||||
outArgs = args[1:]
|
outArgs = args[1:]
|
||||||
} else {
|
} else {
|
||||||
|
// '-f' (arg was required)
|
||||||
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
|
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = fn(flag, value, shorthands)
|
|
||||||
|
if flag.ShorthandDeprecated != "" {
|
||||||
|
fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = fn(flag, value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,6 +969,7 @@ func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []stri
|
|||||||
a = args
|
a = args
|
||||||
shorthands := s[1:]
|
shorthands := s[1:]
|
||||||
|
|
||||||
|
// "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv").
|
||||||
for len(shorthands) > 0 {
|
for len(shorthands) > 0 {
|
||||||
shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
|
shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -954,13 +1017,18 @@ func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
|
|||||||
// The return value will be ErrHelp if -help was set but not defined.
|
// The return value will be ErrHelp if -help was set but not defined.
|
||||||
func (f *FlagSet) Parse(arguments []string) error {
|
func (f *FlagSet) Parse(arguments []string) error {
|
||||||
f.parsed = true
|
f.parsed = true
|
||||||
f.args = make([]string, 0, len(arguments))
|
|
||||||
|
|
||||||
assign := func(flag *Flag, value, origArg string) error {
|
if len(arguments) < 0 {
|
||||||
return f.setFlag(flag, value, origArg)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err := f.parseArgs(arguments, assign)
|
f.args = make([]string, 0, len(arguments))
|
||||||
|
|
||||||
|
set := func(flag *Flag, value string) error {
|
||||||
|
return f.Set(flag.Name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := f.parseArgs(arguments, set)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch f.errorHandling {
|
switch f.errorHandling {
|
||||||
case ContinueOnError:
|
case ContinueOnError:
|
||||||
@ -974,7 +1042,7 @@ func (f *FlagSet) Parse(arguments []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type parseFunc func(flag *Flag, value, origArg string) error
|
type parseFunc func(flag *Flag, value string) error
|
||||||
|
|
||||||
// ParseAll parses flag definitions from the argument list, which should not
|
// ParseAll parses flag definitions from the argument list, which should not
|
||||||
// include the command name. The arguments for fn are flag and value. Must be
|
// include the command name. The arguments for fn are flag and value. Must be
|
||||||
@ -985,11 +1053,7 @@ func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string)
|
|||||||
f.parsed = true
|
f.parsed = true
|
||||||
f.args = make([]string, 0, len(arguments))
|
f.args = make([]string, 0, len(arguments))
|
||||||
|
|
||||||
assign := func(flag *Flag, value, origArg string) error {
|
err := f.parseArgs(arguments, fn)
|
||||||
return fn(flag, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := f.parseArgs(arguments, assign)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch f.errorHandling {
|
switch f.errorHandling {
|
||||||
case ContinueOnError:
|
case ContinueOnError:
|
||||||
@ -1036,14 +1100,15 @@ func Parsed() bool {
|
|||||||
// CommandLine is the default set of command-line flags, parsed from os.Args.
|
// CommandLine is the default set of command-line flags, parsed from os.Args.
|
||||||
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
|
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
|
||||||
|
|
||||||
// NewFlagSet returns a new, empty flag set with the specified name and
|
// NewFlagSet returns a new, empty flag set with the specified name,
|
||||||
// error handling property.
|
// error handling property and SortFlags set to true.
|
||||||
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
|
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
|
||||||
f := &FlagSet{
|
f := &FlagSet{
|
||||||
name: name,
|
name: name,
|
||||||
errorHandling: errorHandling,
|
errorHandling: errorHandling,
|
||||||
argsLenAtDash: -1,
|
argsLenAtDash: -1,
|
||||||
interspersed: true,
|
interspersed: true,
|
||||||
|
SortFlags: true,
|
||||||
}
|
}
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user