diff --git a/cli/cli.go b/cli/cli.go
new file mode 100644
index 0000000..bfc9fcc
--- /dev/null
+++ b/cli/cli.go
@@ -0,0 +1,25 @@
+package cli
+
+import (
+ cli "gopkg.in/urfave/cli.v2"
+)
+
+// New creates a new cli app.
+func New() *cli.App {
+ cli.VersionFlag = &cli.BoolFlag{
+ Name: "version", Aliases: []string{},
+ Usage: "print the version",
+ }
+
+ return &cli.App{
+ Name: "lntop",
+ EnableShellCompletion: true,
+ Flags: []cli.Flag{
+ &cli.BoolFlag{
+ Name: "v",
+ Usage: "verbose",
+ },
+ },
+ Commands: []*cli.Command{},
+ }
+}
diff --git a/cmd/lntop/main.go b/cmd/lntop/main.go
new file mode 100644
index 0000000..40d3665
--- /dev/null
+++ b/cmd/lntop/main.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "log"
+ "os"
+
+ "github.com/edouardparis/lntop/cli"
+)
+
+func main() {
+ err := cli.New().Run(os.Args)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/go.mod b/go.mod
index 90bb394..3022947 100644
--- a/go.mod
+++ b/go.mod
@@ -1 +1,3 @@
module github.com/edouardparis/lntop
+
+require gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..95468d5
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,2 @@
+gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8 h1:Ggy3mWN4l3PUFPfSG0YB3n5fVYggzysUmiUQ89SnX6Y=
+gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8/go.mod h1:cKXr3E0k4aosgycml1b5z33BVV6hai1Kh7uDgFOkbcs=
diff --git a/vendor/gopkg.in/urfave/cli.v2/.flake8 b/vendor/gopkg.in/urfave/cli.v2/.flake8
new file mode 100644
index 0000000..6deafc2
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+max-line-length = 120
diff --git a/vendor/gopkg.in/urfave/cli.v2/.gitignore b/vendor/gopkg.in/urfave/cli.v2/.gitignore
new file mode 100644
index 0000000..faf70c4
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/.gitignore
@@ -0,0 +1,2 @@
+*.coverprofile
+node_modules/
diff --git a/vendor/gopkg.in/urfave/cli.v2/.travis.yml b/vendor/gopkg.in/urfave/cli.v2/.travis.yml
new file mode 100644
index 0000000..dea1790
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/.travis.yml
@@ -0,0 +1,28 @@
+language: go
+sudo: false
+dist: trusty
+osx_image: xcode8.3
+go: 1.8.x
+
+os:
+- linux
+- osx
+
+cache:
+ directories:
+ - node_modules
+
+before_script:
+- if [[ $(uname) == Darwin ]]; then
+ sudo pip2 install flake8;
+ else
+ pip install --user flake8;
+ fi
+- mkdir -p ${GOPATH%%:*}/src/gopkg.in/urfave
+- rm -rvf ${GOPATH%%:*}/src/gopkg.in/urfave/cli.v2
+- rm -rvf ${GOPATH%%:*}/pkg/*/gopkg.in/urfave/cli.v2.a
+- ln -sv ${TRAVIS_BUILD_DIR} ${GOPATH%%:*}/src/gopkg.in/urfave/cli.v2
+
+script:
+- flake8 runtests cli-v1-to-v2 generate-flag-types
+- make all
diff --git a/vendor/gopkg.in/urfave/cli.v2/CHANGELOG.md b/vendor/gopkg.in/urfave/cli.v2/CHANGELOG.md
new file mode 100644
index 0000000..5fa0ca0
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/CHANGELOG.md
@@ -0,0 +1,431 @@
+# Change Log
+
+**ATTN**: This project uses [semantic versioning](http://semver.org/).
+
+## 2.0.0 - (unreleased 2.x series)
+### Added
+- `NewStringSlice` and `NewIntSlice` for creating their related types
+- `Float64SliceFlag` for unmarshaling a list of floats from the user
+- `Context.Lineage` to get all contexts from current up to global
+- `Context.LocalFlagNames` to get the flag names from *only* the current context
+- `BoolFlag.Value` to handle both default-false and default-true
+
+### Changed
+- `Context.FlagNames` now returns all flags in the context lineage
+- `Context.IsSet` now considers the full context lineage
+
+### Removed
+- the ability to specify `&StringSlice{...string}` or `&IntSlice{...int}`.
+ To migrate to the new API, you may choose to run [the migrator
+ (python) script](./cli-v1-to-v2).
+- The optimistic reordering of arguments and flags introduced by
+ https://github.com/codegangsta/cli/pull/36. This behavior only worked when
+ all arguments appeared before all flags, but caused [weird issues with boolean
+ flags](https://github.com/codegangsta/cli/issues/103) and [reordering of the
+ arguments](https://github.com/codegangsta/cli/issues/355) when the user
+ attempted to mix flags and arguments. Given the trade-offs we removed support
+ for this reordering.
+- adapter code for deprecated `Action` func signature
+- deprecated `App.Author`, `App.Email`, and `Command.ShortName` fields
+- All `Context.Global*` methods, as the non-global versions now traverse up
+ the context lineage automatically.
+- `Context.Parent` method, as this is now available via `Context.Lineage`
+- `BoolTFlag` and related code, as this is now available via `BoolFlag.Value`
+
+## [Unreleased] - (1.x series)
+### Added
+
+### Changed
+
+### Removed
+
+### Fixed
+
+### Deprecated
+
+### Security
+
+## [1.19.1] - 2016-11-21
+### Fixed
+- Fixes regression introduced in 1.19.0 where using an `ActionFunc` as
+ the `Action` for a command would cause it to error rather than calling the
+ function. Should not have a affected declarative cases using `func(c
+ *cli.Context) err)`.
+- Shell completion now handles the case where the user specifies
+ `--generate-bash-completion` immediately after a flag that takes an argument.
+ Previously it call the application with `--generate-bash-completion` as the
+ flag value.
+
+## [1.19.0] - 2016-11-19
+### Added
+- `FlagsByName` was added to make it easy to sort flags (e.g. `sort.Sort(cli.FlagsByName(app.Flags))`)
+- A `Description` field was added to `App` for a more detailed description of
+ the application (similar to the existing `Description` field on `Command`)
+- Flag type code generation via `go generate`
+- Write to stderr and exit 1 if action returns non-nil error
+- Added support for TOML to the `altsrc` loader
+- `SkipArgReorder` was added to allow users to skip the argument reordering.
+ This is useful if you want to consider all "flags" after an argument as
+ arguments rather than flags (the default behavior of the stdlib `flag`
+ library). This is backported functionality from the [removal of the flag
+ reordering](https://github.com/urfave/cli/pull/398) in the unreleased version
+ 2
+- For formatted errors (those implementing `ErrorFormatter`), the errors will
+ be formatted during output. Compatible with `pkg/errors`.
+
+### Changed
+- Raise minimum tested/supported Go version to 1.2+
+
+### Fixed
+- Consider empty environment variables as set (previously environment variables
+ with the equivalent of `""` would be skipped rather than their value used).
+- Return an error if the value in a given environment variable cannot be parsed
+ as the flag type. Previously these errors were silently swallowed.
+- Print full error when an invalid flag is specified (which includes the invalid flag)
+- `App.Writer` defaults to `stdout` when `nil`
+- If no action is specified on a command or app, the help is now printed instead of `panic`ing
+- `App.Metadata` is initialized automatically now (previously was `nil` unless initialized)
+- Correctly show help message if `-h` is provided to a subcommand
+- `context.(Global)IsSet` now respects environment variables. Previously it
+ would return `false` if a flag was specified in the environment rather than
+ as an argument
+- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
+- `altsrc`s import paths were updated to use `gopkg.in/urfave/cli.v1`. This
+ fixes issues that occurred when `gopkg.in/urfave/cli.v1` was imported as well
+ as `altsrc` where Go would complain that the types didn't match
+
+## [1.18.1] - 2016-08-28
+### Fixed
+- Removed deprecation warnings to STDERR to avoid them leaking to the end-user (backported)
+
+## [1.18.0] - 2016-06-27
+### Added
+- `./runtests` test runner with coverage tracking by default
+- testing on OS X
+- testing on Windows
+- `UintFlag`, `Uint64Flag`, and `Int64Flag` types and supporting code
+
+### Changed
+- Use spaces for alignment in help/usage output instead of tabs, making the
+ output alignment consistent regardless of tab width
+
+### Fixed
+- Printing of command aliases in help text
+- Printing of visible flags for both struct and struct pointer flags
+- Display the `help` subcommand when using `CommandCategories`
+- No longer swallows `panic`s that occur within the `Action`s themselves when
+ detecting the signature of the `Action` field
+
+## [1.17.1] - 2016-08-28
+### Fixed
+- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
+
+## [1.17.0] - 2016-05-09
+### Added
+- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc`
+- `context.GlobalBoolT` was added as an analogue to `context.GlobalBool`
+- Support for hiding commands by setting `Hidden: true` -- this will hide the
+ commands in help output
+
+### Changed
+- `Float64Flag`, `IntFlag`, and `DurationFlag` default values are no longer
+ quoted in help text output.
+- All flag types now include `(default: {value})` strings following usage when a
+ default value can be (reasonably) detected.
+- `IntSliceFlag` and `StringSliceFlag` usage strings are now more consistent
+ with non-slice flag types
+- Apps now exit with a code of 3 if an unknown subcommand is specified
+ (previously they printed "No help topic for...", but still exited 0. This
+ makes it easier to script around apps built using `cli` since they can trust
+ that a 0 exit code indicated a successful execution.
+- cleanups based on [Go Report Card
+ feedback](https://goreportcard.com/report/github.com/urfave/cli)
+
+## [1.16.1] - 2016-08-28
+### Fixed
+- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
+
+## [1.16.0] - 2016-05-02
+### Added
+- `Hidden` field on all flag struct types to omit from generated help text
+
+### Changed
+- `BashCompletionFlag` (`--enable-bash-completion`) is now omitted from
+generated help text via the `Hidden` field
+
+### Fixed
+- handling of error values in `HandleAction` and `HandleExitCoder`
+
+## [1.15.0] - 2016-04-30
+### Added
+- This file!
+- Support for placeholders in flag usage strings
+- `App.Metadata` map for arbitrary data/state management
+- `Set` and `GlobalSet` methods on `*cli.Context` for altering values after
+parsing.
+- Support for nested lookup of dot-delimited keys in structures loaded from
+YAML.
+
+### Changed
+- The `App.Action` and `Command.Action` now prefer a return signature of
+`func(*cli.Context) error`, as defined by `cli.ActionFunc`. If a non-nil
+`error` is returned, there may be two outcomes:
+ - If the error fulfills `cli.ExitCoder`, then `os.Exit` will be called
+ automatically
+ - Else the error is bubbled up and returned from `App.Run`
+- Specifying an `Action` with the legacy return signature of
+`func(*cli.Context)` will produce a deprecation message to stderr
+- Specifying an `Action` that is not a `func` type will produce a non-zero exit
+from `App.Run`
+- Specifying an `Action` func that has an invalid (input) signature will
+produce a non-zero exit from `App.Run`
+
+### Deprecated
+-
+`cli.App.RunAndExitOnError`, which should now be done by returning an error
+that fulfills `cli.ExitCoder` to `cli.App.Run`.
+- the legacy signature for
+`cli.App.Action` of `func(*cli.Context)`, which should now have a return
+signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
+
+### Fixed
+- Added missing `*cli.Context.GlobalFloat64` method
+
+## [1.14.0] - 2016-04-03 (backfilled 2016-04-25)
+### Added
+- Codebeat badge
+- Support for categorization via `CategorizedHelp` and `Categories` on app.
+
+### Changed
+- Use `filepath.Base` instead of `path.Base` in `Name` and `HelpName`.
+
+### Fixed
+- Ensure version is not shown in help text when `HideVersion` set.
+
+## [1.13.0] - 2016-03-06 (backfilled 2016-04-25)
+### Added
+- YAML file input support.
+- `NArg` method on context.
+
+## [1.12.0] - 2016-02-17 (backfilled 2016-04-25)
+### Added
+- Custom usage error handling.
+- Custom text support in `USAGE` section of help output.
+- Improved help messages for empty strings.
+- AppVeyor CI configuration.
+
+### Changed
+- Removed `panic` from default help printer func.
+- De-duping and optimizations.
+
+### Fixed
+- Correctly handle `Before`/`After` at command level when no subcommands.
+- Case of literal `-` argument causing flag reordering.
+- Environment variable hints on Windows.
+- Docs updates.
+
+## [1.11.1] - 2015-12-21 (backfilled 2016-04-25)
+### Changed
+- Use `path.Base` in `Name` and `HelpName`
+- Export `GetName` on flag types.
+
+### Fixed
+- Flag parsing when skipping is enabled.
+- Test output cleanup.
+- Move completion check to account for empty input case.
+
+## [1.11.0] - 2015-11-15 (backfilled 2016-04-25)
+### Added
+- Destination scan support for flags.
+- Testing against `tip` in Travis CI config.
+
+### Changed
+- Go version in Travis CI config.
+
+### Fixed
+- Removed redundant tests.
+- Use correct example naming in tests.
+
+## [1.10.2] - 2015-10-29 (backfilled 2016-04-25)
+### Fixed
+- Remove unused var in bash completion.
+
+## [1.10.1] - 2015-10-21 (backfilled 2016-04-25)
+### Added
+- Coverage and reference logos in README.
+
+### Fixed
+- Use specified values in help and version parsing.
+- Only display app version and help message once.
+
+## [1.10.0] - 2015-10-06 (backfilled 2016-04-25)
+### Added
+- More tests for existing functionality.
+- `ArgsUsage` at app and command level for help text flexibility.
+
+### Fixed
+- Honor `HideHelp` and `HideVersion` in `App.Run`.
+- Remove juvenile word from README.
+
+## [1.9.0] - 2015-09-08 (backfilled 2016-04-25)
+### Added
+- `FullName` on command with accompanying help output update.
+- Set default `$PROG` in bash completion.
+
+### Changed
+- Docs formatting.
+
+### Fixed
+- Removed self-referential imports in tests.
+
+## [1.8.0] - 2015-06-30 (backfilled 2016-04-25)
+### Added
+- Support for `Copyright` at app level.
+- `Parent` func at context level to walk up context lineage.
+
+### Fixed
+- Global flag processing at top level.
+
+## [1.7.1] - 2015-06-11 (backfilled 2016-04-25)
+### Added
+- Aggregate errors from `Before`/`After` funcs.
+- Doc comments on flag structs.
+- Include non-global flags when checking version and help.
+- Travis CI config updates.
+
+### Fixed
+- Ensure slice type flags have non-nil values.
+- Collect global flags from the full command hierarchy.
+- Docs prose.
+
+## [1.7.0] - 2015-05-03 (backfilled 2016-04-25)
+### Changed
+- `HelpPrinter` signature includes output writer.
+
+### Fixed
+- Specify go 1.1+ in docs.
+- Set `Writer` when running command as app.
+
+## [1.6.0] - 2015-03-23 (backfilled 2016-04-25)
+### Added
+- Multiple author support.
+- `NumFlags` at context level.
+- `Aliases` at command level.
+
+### Deprecated
+- `ShortName` at command level.
+
+### Fixed
+- Subcommand help output.
+- Backward compatible support for deprecated `Author` and `Email` fields.
+- Docs regarding `Names`/`Aliases`.
+
+## [1.5.0] - 2015-02-20 (backfilled 2016-04-25)
+### Added
+- `After` hook func support at app and command level.
+
+### Fixed
+- Use parsed context when running command as subcommand.
+- Docs prose.
+
+## [1.4.1] - 2015-01-09 (backfilled 2016-04-25)
+### Added
+- Support for hiding `-h / --help` flags, but not `help` subcommand.
+- Stop flag parsing after `--`.
+
+### Fixed
+- Help text for generic flags to specify single value.
+- Use double quotes in output for defaults.
+- Use `ParseInt` instead of `ParseUint` for int environment var values.
+- Use `0` as base when parsing int environment var values.
+
+## [1.4.0] - 2014-12-12 (backfilled 2016-04-25)
+### Added
+- Support for environment variable lookup "cascade".
+- Support for `Stdout` on app for output redirection.
+
+### Fixed
+- Print command help instead of app help in `ShowCommandHelp`.
+
+## [1.3.1] - 2014-11-13 (backfilled 2016-04-25)
+### Added
+- Docs and example code updates.
+
+### Changed
+- Default `-v / --version` flag made optional.
+
+## [1.3.0] - 2014-08-10 (backfilled 2016-04-25)
+### Added
+- `FlagNames` at context level.
+- Exposed `VersionPrinter` var for more control over version output.
+- Zsh completion hook.
+- `AUTHOR` section in default app help template.
+- Contribution guidelines.
+- `DurationFlag` type.
+
+## [1.2.0] - 2014-08-02
+### Added
+- Support for environment variable defaults on flags plus tests.
+
+## [1.1.0] - 2014-07-15
+### Added
+- Bash completion.
+- Optional hiding of built-in help command.
+- Optional skipping of flag parsing at command level.
+- `Author`, `Email`, and `Compiled` metadata on app.
+- `Before` hook func support at app and command level.
+- `CommandNotFound` func support at app level.
+- Command reference available on context.
+- `GenericFlag` type.
+- `Float64Flag` type.
+- `BoolTFlag` type.
+- `IsSet` flag helper on context.
+- More flag lookup funcs at context level.
+- More tests & docs.
+
+### Changed
+- Help template updates to account for presence/absence of flags.
+- Separated subcommand help template.
+- Exposed `HelpPrinter` var for more control over help output.
+
+## [1.0.0] - 2013-11-01
+### Added
+- `help` flag in default app flag set and each command flag set.
+- Custom handling of argument parsing errors.
+- Command lookup by name at app level.
+- `StringSliceFlag` type and supporting `StringSlice` type.
+- `IntSliceFlag` type and supporting `IntSlice` type.
+- Slice type flag lookups by name at context level.
+- Export of app and command help functions.
+- More tests & docs.
+
+## 0.1.0 - 2013-07-22
+### Added
+- Initial implementation.
+
+[Unreleased]: https://github.com/urfave/cli/compare/v1.18.0...HEAD
+[1.18.0]: https://github.com/urfave/cli/compare/v1.17.0...v1.18.0
+[1.17.0]: https://github.com/urfave/cli/compare/v1.16.0...v1.17.0
+[1.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0
+[1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0
+[1.14.0]: https://github.com/urfave/cli/compare/v1.13.0...v1.14.0
+[1.13.0]: https://github.com/urfave/cli/compare/v1.12.0...v1.13.0
+[1.12.0]: https://github.com/urfave/cli/compare/v1.11.1...v1.12.0
+[1.11.1]: https://github.com/urfave/cli/compare/v1.11.0...v1.11.1
+[1.11.0]: https://github.com/urfave/cli/compare/v1.10.2...v1.11.0
+[1.10.2]: https://github.com/urfave/cli/compare/v1.10.1...v1.10.2
+[1.10.1]: https://github.com/urfave/cli/compare/v1.10.0...v1.10.1
+[1.10.0]: https://github.com/urfave/cli/compare/v1.9.0...v1.10.0
+[1.9.0]: https://github.com/urfave/cli/compare/v1.8.0...v1.9.0
+[1.8.0]: https://github.com/urfave/cli/compare/v1.7.1...v1.8.0
+[1.7.1]: https://github.com/urfave/cli/compare/v1.7.0...v1.7.1
+[1.7.0]: https://github.com/urfave/cli/compare/v1.6.0...v1.7.0
+[1.6.0]: https://github.com/urfave/cli/compare/v1.5.0...v1.6.0
+[1.5.0]: https://github.com/urfave/cli/compare/v1.4.1...v1.5.0
+[1.4.1]: https://github.com/urfave/cli/compare/v1.4.0...v1.4.1
+[1.4.0]: https://github.com/urfave/cli/compare/v1.3.1...v1.4.0
+[1.3.1]: https://github.com/urfave/cli/compare/v1.3.0...v1.3.1
+[1.3.0]: https://github.com/urfave/cli/compare/v1.2.0...v1.3.0
+[1.2.0]: https://github.com/urfave/cli/compare/v1.1.0...v1.2.0
+[1.1.0]: https://github.com/urfave/cli/compare/v1.0.0...v1.1.0
+[1.0.0]: https://github.com/urfave/cli/compare/v0.1.0...v1.0.0
diff --git a/vendor/gopkg.in/urfave/cli.v2/GNUmakefile b/vendor/gopkg.in/urfave/cli.v2/GNUmakefile
new file mode 100644
index 0000000..4543b19
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/GNUmakefile
@@ -0,0 +1,37 @@
+default: test
+
+deps:
+ go get golang.org/x/tools/cmd/goimports || true
+ go get github.com/urfave/gfmrun/... || true
+ go list ./... \
+ | xargs go list -f '{{ join .Deps "\n" }}{{ printf "\n" }}{{ join .TestImports "\n" }}' \
+ | grep -v github.com/urfave/cli \
+ | xargs go get
+ @if [ ! -f node_modules/.bin/markdown-toc ]; then \
+ npm install markdown-toc ; \
+ fi
+
+gen: deps
+ ./runtests gen
+
+vet:
+ ./runtests vet
+
+gfmrun:
+ ./runtests gfmrun
+
+v1-to-v2:
+ ./cli-v1-to-v2 --selftest
+
+migrations:
+ ./runtests migrations
+
+toc:
+ ./runtests toc
+
+test: deps
+ ./runtests test
+
+all: gen vet test gfmrun v1-to-v2 migrations toc
+
+.PHONY: default gen vet test gfmrun migrations toc v1-to-v2 deps all
diff --git a/vendor/gopkg.in/urfave/cli.v2/LICENSE b/vendor/gopkg.in/urfave/cli.v2/LICENSE
new file mode 100644
index 0000000..42a597e
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 Jeremy Saenz & Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/gopkg.in/urfave/cli.v2/README.md b/vendor/gopkg.in/urfave/cli.v2/README.md
new file mode 100644
index 0000000..dbe1bf3
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/README.md
@@ -0,0 +1,1433 @@
+cli
+===
+
+[![Build Status](https://travis-ci.org/urfave/cli.svg?branch=master)](https://travis-ci.org/urfave/cli)
+[![Windows Build Status](https://ci.appveyor.com/api/projects/status/rtgk5xufi932pb2v?svg=true)](https://ci.appveyor.com/project/urfave/cli)
+[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://godoc.org/github.com/urfave/cli)
+[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli)
+[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli)
+[![top level coverage](https://gocover.io/_badge/github.com/urfave/cli?0 "top level coverage")](http://gocover.io/github.com/urfave/cli) /
+[![altsrc coverage](https://gocover.io/_badge/github.com/urfave/cli/altsrc?0 "altsrc coverage")](http://gocover.io/github.com/urfave/cli/altsrc)
+
+**Notice:** This is the library formerly known as
+`github.com/codegangsta/cli` -- Github will automatically redirect requests
+to this repository, but we recommend updating your references for clarity.
+
+cli is a simple, fast, and fun package for building command line apps in Go. The
+goal is to enable developers to write fast and distributable command line
+applications in an expressive way.
+
+
+
+- [Overview](#overview)
+- [Installation](#installation)
+ * [Supported platforms](#supported-platforms)
+ * [Using the `v2` branch](#using-the-v2-branch)
+ * [Pinning to the `v1` releases](#pinning-to-the-v1-releases)
+- [Getting Started](#getting-started)
+- [Examples](#examples)
+ * [Arguments](#arguments)
+ * [Flags](#flags)
+ + [Placeholder Values](#placeholder-values)
+ + [Alternate Names](#alternate-names)
+ + [Ordering](#ordering)
+ + [Values from the Environment](#values-from-the-environment)
+ + [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others)
+ + [Default Values for help output](#default-values-for-help-output)
+ * [Subcommands](#subcommands)
+ * [Subcommands categories](#subcommands-categories)
+ * [Exit code](#exit-code)
+ * [Shell Completion](#shell-completion)
+ + [Enabling](#enabling)
+ + [Distribution](#distribution)
+ + [Customization](#customization)
+ * [Generated Help Text](#generated-help-text)
+ + [Customization](#customization-1)
+ * [Version Flag](#version-flag)
+ + [Customization](#customization-2)
+ * [Full API Example](#full-api-example)
+- [Contribution Guidelines](#contribution-guidelines)
+
+
+
+## Overview
+
+Command line apps are usually so tiny that there is absolutely no reason why
+your code should *not* be self-documenting. Things like generating help text and
+parsing command flags/options should not hinder productivity when writing a
+command line app.
+
+**This is where cli comes into play.** cli makes command line programming fun,
+organized, and expressive!
+
+## Installation
+
+Make sure you have a working Go environment. Go version 1.2+ is supported. [See
+the install instructions for Go](http://golang.org/doc/install.html).
+
+To install cli, simply run:
+```
+$ go get github.com/urfave/cli
+```
+
+Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can
+be easily used:
+```
+export PATH=$PATH:$GOPATH/bin
+```
+
+### Supported platforms
+
+cli is tested against multiple versions of Go on Linux, and against the latest
+released version of Go on OS X and Windows. For full details, see
+[`./.travis.yml`](./.travis.yml) and [`./appveyor.yml`](./appveyor.yml).
+
+### Using the `v2` branch
+
+**Warning**: The `v2` branch is currently unreleased and considered unstable.
+
+There is currently a long-lived branch named `v2` that is intended to land as
+the new `master` branch once development there has settled down. The current
+`master` branch (mirrored as `v1`) is being manually merged into `v2` on
+an irregular human-based schedule, but generally if one wants to "upgrade" to
+`v2` *now* and accept the volatility (read: "awesomeness") that comes along with
+that, please use whatever version pinning of your preference, such as via
+`gopkg.in`:
+
+```
+$ go get gopkg.in/urfave/cli.v2
+```
+
+``` go
+...
+import (
+ "gopkg.in/urfave/cli.v2" // imports as package "cli"
+)
+...
+```
+
+**NOTE**: There is a [migrator (python) script](./cli-v1-to-v2) available to aid
+with the transition from the v1 to v2 API.
+
+### Pinning to the `v1` releases
+
+Similarly to the section above describing use of the `v2` branch, if one wants
+to avoid any unexpected compatibility pains once `v2` becomes `master`, then
+pinning to `v1` is an acceptable option, e.g.:
+
+```
+$ go get gopkg.in/urfave/cli.v1
+```
+
+``` go
+...
+import (
+ "gopkg.in/urfave/cli.v1" // imports as package "cli"
+)
+...
+```
+
+This will pull the latest tagged `v1` release (e.g. `v1.18.1` at the time of writing).
+
+## Getting Started
+
+One of the philosophies behind cli is that an API should be playful and full of
+discovery. So a cli app can be as little as one line of code in `main()`.
+
+
+``` go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ (&cli.App{}).Run(os.Args)
+}
+```
+
+This app will run and show help text, but is not very useful. Let's give an
+action to execute and some help documentation:
+
+
+``` go
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Name: "boom",
+ Usage: "make an explosive entrance",
+ Action: func(c *cli.Context) error {
+ fmt.Println("boom! I say!")
+ return nil
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+Running this already gives you a ton of functionality, plus support for things
+like subcommands and flags, which are covered below.
+
+## Examples
+
+Being a programmer can be a lonely job. Thankfully by the power of automation
+that is not the case! Let's create a greeter app to fend off our demons of
+loneliness!
+
+Start by creating a directory named `greet`, and within it, add a file,
+`greet.go` with the following code in it:
+
+
+``` go
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Name: "greet",
+ Usage: "fight the loneliness!",
+ Action: func(c *cli.Context) error {
+ fmt.Println("Hello friend!")
+ return nil
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+Install our command to the `$GOPATH/bin` directory:
+
+```
+$ go install
+```
+
+Finally run our new command:
+
+```
+$ greet
+Hello friend!
+```
+
+cli also generates neat help text:
+
+```
+$ greet help
+NAME:
+ greet - fight the loneliness!
+
+USAGE:
+ greet [global options] command [command options] [arguments...]
+
+VERSION:
+ 0.0.0
+
+COMMANDS:
+ help, h Shows a list of commands or help for one command
+
+GLOBAL OPTIONS
+ --version Shows version information
+```
+
+### Arguments
+
+You can lookup arguments by calling the `Args` function on `cli.Context`, e.g.:
+
+
+``` go
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Action: func(c *cli.Context) error {
+ fmt.Printf("Hello %q", c.Args().Get(0))
+ return nil
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+### Flags
+
+Setting and querying flags is simple.
+
+
+``` go
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Flags: []cli.Flag {
+ &cli.StringFlag{
+ Name: "lang",
+ Value: "english",
+ Usage: "language for the greeting",
+ },
+ },
+ Action: func(c *cli.Context) error {
+ name := "Nefertiti"
+ if c.NArg() > 0 {
+ name = c.Args().Get(0)
+ }
+ if c.String("lang") == "spanish" {
+ fmt.Println("Hola", name)
+ } else {
+ fmt.Println("Hello", name)
+ }
+ return nil
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+You can also set a destination variable for a flag, to which the content will be
+scanned.
+
+
+``` go
+package main
+
+import (
+ "os"
+ "fmt"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ var language string
+
+ app := &cli.App{
+ Flags: []cli.Flag {
+ &cli.StringFlag{
+ Name: "lang",
+ Value: "english",
+ Usage: "language for the greeting",
+ Destination: &language,
+ },
+ },
+ Action: func(c *cli.Context) error {
+ name := "someone"
+ if c.NArg() > 0 {
+ name = c.Args().Get(0)
+ }
+ if language == "spanish" {
+ fmt.Println("Hola", name)
+ } else {
+ fmt.Println("Hello", name)
+ }
+ return nil
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+See full list of flags at http://godoc.org/github.com/urfave/cli
+
+#### Placeholder Values
+
+Sometimes it's useful to specify a flag's value within the usage string itself.
+Such placeholders are indicated with back quotes.
+
+For example this:
+
+
+```go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Flags: []cli.Flag{
+ &cli.StringFlag{
+ Name: "config",
+ Aliases: []string{"c"},
+ Usage: "Load configuration from `FILE`",
+ },
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+Will result in help output like:
+
+```
+--config FILE, -c FILE Load configuration from FILE
+```
+
+Note that only the first placeholder is used. Subsequent back-quoted words will
+be left as-is.
+
+#### Alternate Names
+
+You can set alternate (or short) names for flags by providing a comma-delimited
+list for the `Name`. e.g.
+
+
+``` go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Flags: []cli.Flag {
+ &cli.StringFlag{
+ Name: "lang",
+ Aliases: []string{"l"},
+ Value: "english",
+ Usage: "language for the greeting",
+ },
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+That flag can then be set with `--lang spanish` or `-l spanish`. Note that
+giving two different forms of the same flag in the same command invocation is an
+error.
+
+#### Ordering
+
+Flags for the application and commands are shown in the order they are defined.
+However, it's possible to sort them from outside this library by using `FlagsByName`
+or `CommandsByName` with `sort`.
+
+For example this:
+
+
+``` go
+package main
+
+import (
+ "os"
+ "sort"
+
+ "github.com/urfave/cli"
+)
+
+func main() {
+ app := &cli.App{
+ Flags: []cli.Flag{
+ &cli.StringFlag{
+ Name: "lang, l",
+ Value: "english",
+ Usage: "Language for the greeting",
+ },
+ &cli.StringFlag{
+ Name: "config, c",
+ Usage: "Load configuration from `FILE`",
+ },
+ },
+ Commands: []*cli.Command{
+ {
+ Name: "complete",
+ Aliases: []string{"c"},
+ Usage: "complete a task on the list",
+ Action: func(c *cli.Context) error {
+ return nil
+ },
+ },
+ {
+ Name: "add",
+ Aliases: []string{"a"},
+ Usage: "add a task to the list",
+ Action: func(c *cli.Context) error {
+ return nil
+ },
+ },
+ },
+ }
+
+ sort.Sort(cli.FlagsByName(app.Flags))
+ sort.Sort(cli.CommandsByName(app.Commands))
+
+ app.Run(os.Args)
+}
+```
+
+Will result in help output like:
+
+```
+--config FILE, -c FILE Load configuration from FILE
+--lang value, -l value Language for the greeting (default: "english")
+```
+
+#### Values from the Environment
+
+You can also have the default value set from the environment via `EnvVars`. e.g.
+
+
+``` go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Flags: []cli.Flag {
+ &cli.StringFlag{
+ Name: "lang",
+ Aliases: []string{"l"},
+ Value: "english",
+ Usage: "language for the greeting",
+ EnvVars: []string{"APP_LANG"},
+ },
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+If `EnvVars` contains more than one string, the first environment variable that
+resolves is used as the default.
+
+
+``` go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Flags: []cli.Flag{
+ &cli.StringFlag{
+ Name: "lang",
+ Aliases: []string{"l"},
+ Value: "english",
+ Usage: "language for the greeting",
+ EnvVars: []string{"LEGACY_COMPAT_LANG", "APP_LANG", "LANG"},
+ },
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+#### Values from alternate input sources (YAML, TOML, and others)
+
+There is a separate package altsrc that adds support for getting flag values
+from other file input sources.
+
+Currently supported input source formats:
+* YAML
+* TOML
+
+In order to get values for a flag from an alternate input source the following
+code would be added to wrap an existing cli.Flag like below:
+
+``` go
+ altsrc.NewIntFlag(&cli.IntFlag{Name: "test"})
+```
+
+Initialization must also occur for these flags. Below is an example initializing
+getting data from a yaml file below.
+
+``` go
+ command.Before = altsrc.InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
+```
+
+The code above will use the "load" string as a flag name to get the file name of
+a yaml file from the cli.Context. It will then use that file name to initialize
+the yaml input source for any flags that are defined on that command. As a note
+the "load" flag used would also have to be defined on the command flags in order
+for this code snipped to work.
+
+Currently only the aboved specified formats are supported but developers can
+add support for other input sources by implementing the
+altsrc.InputSourceContext for their given sources.
+
+Here is a more complete sample of a command using YAML support:
+
+
+``` go
+package notmain
+
+import (
+ "fmt"
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+ "gopkg.in/urfave/cli.v2/altsrc"
+)
+
+func main() {
+ flags := []cli.Flag{
+ altsrc.NewIntFlag(&cli.IntFlag{Name: "test"}),
+ &cli.StringFlag{Name: "load"},
+ }
+
+ app := &cli.App{
+ Action: func(c *cli.Context) error {
+ fmt.Println("yaml ist rad")
+ return nil
+ },
+ Before: altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load")),
+ Flags: flags,
+ }
+
+ app.Run(os.Args)
+}
+```
+
+#### Default Values for help output
+
+Sometimes it's useful to specify a flag's default help-text value within the flag declaration. This can be useful if the default value for a flag is a computed value. The default value can be set via the `DefaultText` struct field.
+
+For example this:
+
+
+```go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Flags: []cli.Flag{
+ &cli.IntFlag{
+ Name: "port",
+ Usage: "Use a randomized port",
+ Value: 0,
+ DefaultText: "random",
+ },
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+Will result in help output like:
+
+```
+--port value Use a randomized port (default: random)
+```
+
+
+### Subcommands
+
+Subcommands can be defined for a more git-like command line app.
+
+
+```go
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Commands: []*cli.Command{
+ {
+ Name: "add",
+ Aliases: []string{"a"},
+ Usage: "add a task to the list",
+ Action: func(c *cli.Context) error {
+ fmt.Println("added task: ", c.Args().First())
+ return nil
+ },
+ },
+ {
+ Name: "complete",
+ Aliases: []string{"c"},
+ Usage: "complete a task on the list",
+ Action: func(c *cli.Context) error {
+ fmt.Println("completed task: ", c.Args().First())
+ return nil
+ },
+ },
+ {
+ Name: "template",
+ Aliases: []string{"t"},
+ Usage: "options for task templates",
+ Subcommands: []*cli.Command{
+ {
+ Name: "add",
+ Usage: "add a new template",
+ Action: func(c *cli.Context) error {
+ fmt.Println("new task template: ", c.Args().First())
+ return nil
+ },
+ },
+ {
+ Name: "remove",
+ Usage: "remove an existing template",
+ Action: func(c *cli.Context) error {
+ fmt.Println("removed task template: ", c.Args().First())
+ return nil
+ },
+ },
+ },
+ },
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+### Subcommands categories
+
+For additional organization in apps that have many subcommands, you can
+associate a category for each command to group them together in the help
+output.
+
+E.g.
+
+```go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Commands: []*cli.Command{
+ {
+ Name: "noop",
+ },
+ {
+ Name: "add",
+ Category: "template",
+ },
+ {
+ Name: "remove",
+ Category: "template",
+ },
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+Will include:
+
+```
+COMMANDS:
+ noop
+
+ Template actions:
+ add
+ remove
+```
+
+### Exit code
+
+Calling `App.Run` will not automatically call `os.Exit`, which means that by
+default the exit code will "fall through" to being `0`. An explicit exit code
+may be set by returning a non-nil error that fulfills `cli.ExitCoder`, *or* a
+`cli.MultiError` that includes an error that fulfills `cli.ExitCoder`, e.g.:
+
+``` go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ app := &cli.App{
+ Flags: []cli.Flag{
+ &cli.BoolFlag{
+ Name: "ginger-crouton",
+ Value: true,
+ Usage: "is it in the soup?",
+ },
+ },
+ Action: func(ctx *cli.Context) error {
+ if !ctx.Bool("ginger-crouton") {
+ return cli.Exit("it is not in the soup", 86)
+ }
+ return nil
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+### Shell Completion
+
+You can enable completion commands by setting the `EnableShellCompletion`
+flag on the `App` object. By default, this setting will only auto-complete to
+show an app's subcommands, but you can write your own completion methods for
+the App or its subcommands.
+
+
+``` go
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"}
+
+ app := &cli.App{
+ EnableShellCompletion: true,
+ Commands: []*cli.Command{
+ {
+ Name: "complete",
+ Aliases: []string{"c"},
+ Usage: "complete a task on the list",
+ Action: func(c *cli.Context) error {
+ fmt.Println("completed task: ", c.Args().First())
+ return nil
+ },
+ ShellComplete: func(c *cli.Context) {
+ // This will complete if no args are passed
+ if c.NArg() > 0 {
+ return
+ }
+ for _, t := range tasks {
+ fmt.Println(t)
+ }
+ },
+ },
+ },
+ }
+
+ app.Run(os.Args)
+}
+```
+
+#### Enabling
+
+You can generate bash or zsh completion code by using the flag `--init-completion bash` or `--init-completion zsh`.
+
+To setup for bash:
+
+```
+eval "`myprogram --init-completion bash`"
+```
+
+Alternatively, you can put the completion code in your `.bashrc` file:
+```
+myprogram --init-completion bash >> ~/.bashrc
+```
+
+#### Distribution
+
+Copy `autocomplete/bash_autocomplete` into `/etc/bash_completion.d/` and rename
+it to the name of the program you wish to add autocomplete support for (or
+automatically install it there if you are distributing a package). Don't forget
+to source the file to make it active in the current shell.
+
+```
+sudo cp src/bash_autocomplete /etc/bash_completion.d/
+source /etc/bash_completion.d/
+```
+
+Alternatively, you can just document that users should source the generic
+`autocomplete/bash_autocomplete` in their bash configuration with `$PROG` set
+to the name of their program (as above).
+
+#### Customization
+
+The default shell completion flag (`--generate-completion`) is defined as
+`cli.GenerateCompletionFlag`, and may be redefined if desired, e.g.:
+
+
+``` go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ cli.GenerateCompletionFlag = &cli.BoolFlag{
+ Name: "compgen",
+ Hidden: true,
+ }
+
+ app := &cli.App{
+ EnableShellCompletion: true,
+ Commands: []*cli.Command{
+ {
+ Name: "wat",
+ },
+ },
+ }
+ app.Run(os.Args)
+}
+```
+
+### Generated Help Text
+
+The default help flag (`-h/--help`) is defined as `cli.HelpFlag` and is checked
+by the cli internals in order to print generated help text for the app, command,
+or subcommand, and break execution.
+
+#### Customization
+
+All of the help text generation may be customized, and at multiple levels. The
+templates are exposed as variables `AppHelpTemplate`, `CommandHelpTemplate`, and
+`SubcommandHelpTemplate` which may be reassigned or augmented, and full override
+is possible by assigning a compatible func to the `cli.HelpPrinter` variable,
+e.g.:
+
+
+``` go
+package main
+
+import (
+ "fmt"
+ "io"
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ // EXAMPLE: Append to an existing template
+ cli.AppHelpTemplate = fmt.Sprintf(`%s
+
+WEBSITE: http://awesometown.example.com
+
+SUPPORT: support@awesometown.example.com
+
+`, cli.AppHelpTemplate)
+
+ // EXAMPLE: Override a template
+ cli.AppHelpTemplate = `NAME:
+ {{.Name}} - {{.Usage}}
+USAGE:
+ {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
+ {{if len .Authors}}
+AUTHOR:
+ {{range .Authors}}{{ . }}{{end}}
+ {{end}}{{if .Commands}}
+COMMANDS:
+{{range .Commands}}{{if not .HideHelp}} {{join .Names ", "}}{{ "\t"}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
+GLOBAL OPTIONS:
+ {{range .VisibleFlags}}{{.}}
+ {{end}}{{end}}{{if .Copyright }}
+COPYRIGHT:
+ {{.Copyright}}
+ {{end}}{{if .Version}}
+VERSION:
+ {{.Version}}
+ {{end}}
+`
+
+ // EXAMPLE: Replace the `HelpPrinter` func
+ cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
+ fmt.Println("Ha HA. I pwnd the help!!1")
+ }
+
+ (&cli.App{}).Run(os.Args)
+}
+```
+
+The default flag may be customized to something other than `-h/--help` by
+setting `cli.HelpFlag`, e.g.:
+
+
+``` go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ cli.HelpFlag = &cli.BoolFlag{
+ Name: "haaaaalp", Aliases: []string{"halp"},
+ Usage: "HALP",
+ EnvVars: []string{"SHOW_HALP", "HALPPLZ"},
+ }
+
+ (&cli.App{}).Run(os.Args)
+}
+```
+
+### Version Flag
+
+The default version flag (`-v/--version`) is defined as `cli.VersionFlag`, which
+is checked by the cli internals in order to print the `App.Version` via
+`cli.VersionPrinter` and break execution.
+
+#### Customization
+
+The default flag may be customized to something other than `-v/--version` by
+setting `cli.VersionFlag`, e.g.:
+
+
+``` go
+package main
+
+import (
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func main() {
+ cli.VersionFlag = &cli.BoolFlag{
+ Name: "print-version", Aliases: []string{"V"},
+ Usage: "print only the version",
+ }
+
+ app := &cli.App{
+ Name: "partay",
+ Version: "v19.99.0",
+ }
+ app.Run(os.Args)
+}
+```
+
+Alternatively, the version printer at `cli.VersionPrinter` may be overridden, e.g.:
+
+
+``` go
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+var (
+ Revision = "fafafaf"
+)
+
+func main() {
+ cli.VersionPrinter = func(c *cli.Context) {
+ fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision)
+ }
+
+ app := &cli.App{
+ Name: "partay",
+ Version: "v19.99.0",
+ }
+ app.Run(os.Args)
+}
+```
+
+### Full API Example
+
+**Notice**: This is a contrived (functioning) example meant strictly for API
+demonstration purposes. Use of one's imagination is encouraged.
+
+
+``` go
+package main
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "time"
+
+ "gopkg.in/urfave/cli.v2"
+)
+
+func init() {
+ cli.AppHelpTemplate += "\nCUSTOMIZED: you bet ur muffins\n"
+ cli.CommandHelpTemplate += "\nYMMV\n"
+ cli.SubcommandHelpTemplate += "\nor something\n"
+
+ cli.HelpFlag = &cli.BoolFlag{Name: "halp"}
+ cli.GenerateCompletionFlag = &cli.BoolFlag{Name: "compgen", Hidden: true}
+ cli.VersionFlag = &cli.BoolFlag{Name: "print-version", Aliases: []string{"V"}}
+
+ cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
+ fmt.Fprintf(w, "best of luck to you\n")
+ }
+ cli.VersionPrinter = func(c *cli.Context) {
+ fmt.Fprintf(c.App.Writer, "version=%s\n", c.App.Version)
+ }
+ cli.OsExiter = func(c int) {
+ fmt.Fprintf(cli.ErrWriter, "refusing to exit %d\n", c)
+ }
+ cli.ErrWriter = ioutil.Discard
+ cli.FlagStringer = func(fl cli.Flag) string {
+ return fmt.Sprintf("\t\t%s", fl.Names()[0])
+ }
+}
+
+type hexWriter struct{}
+
+func (w *hexWriter) Write(p []byte) (int, error) {
+ for _, b := range p {
+ fmt.Printf("%x", b)
+ }
+ fmt.Printf("\n")
+
+ return len(p), nil
+}
+
+type genericType struct {
+ s string
+}
+
+func (g *genericType) Set(value string) error {
+ g.s = value
+ return nil
+}
+
+func (g *genericType) String() string {
+ return g.s
+}
+
+func main() {
+ app := cli.App{
+ Name: "kənˈtrīv",
+ Version: "v19.99.0",
+ Compiled: time.Now(),
+ Authors: []*cli.Author{
+ &cli.Author{
+ Name: "Example Human",
+ Email: "human@example.com",
+ },
+ },
+ Copyright: "(c) 1999 Serious Enterprise",
+ HelpName: "contrive",
+ Usage: "demonstrate available API",
+ UsageText: "contrive - demonstrating the available API",
+ ArgsUsage: "[args and such]",
+ Commands: []*cli.Command{
+ &cli.Command{
+ Name: "doo",
+ Aliases: []string{"do"},
+ Category: "motion",
+ Usage: "do the doo",
+ UsageText: "doo - does the dooing",
+ Description: "no really, there is a lot of dooing to be done",
+ ArgsUsage: "[arrgh]",
+ Flags: []cli.Flag{
+ &cli.BoolFlag{Name: "forever", Aliases: []string{"forevvarr"}},
+ },
+ Subcommands: []*cli.Command{
+ &cli.Command{
+ Name: "wop",
+ Action: wopAction,
+ },
+ },
+ SkipFlagParsing: false,
+ HideHelp: false,
+ Hidden: false,
+ HelpName: "doo!",
+ ShellComplete: func(c *cli.Context) {
+ fmt.Fprintf(c.App.Writer, "--better\n")
+ },
+ Before: func(c *cli.Context) error {
+ fmt.Fprintf(c.App.Writer, "brace for impact\n")
+ return nil
+ },
+ After: func(c *cli.Context) error {
+ fmt.Fprintf(c.App.Writer, "did we lose anyone?\n")
+ return nil
+ },
+ Action: func(c *cli.Context) error {
+ c.Command.FullName()
+ c.Command.HasName("wop")
+ c.Command.Names()
+ c.Command.VisibleFlags()
+ fmt.Fprintf(c.App.Writer, "dodododododoodododddooooododododooo\n")
+ if c.Bool("forever") {
+ c.Command.Run(c)
+ }
+ return nil
+ },
+ OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error {
+ fmt.Fprintf(c.App.Writer, "for shame\n")
+ return err
+ },
+ },
+ },
+ Flags: []cli.Flag{
+ &cli.BoolFlag{Name: "fancy"},
+ &cli.BoolFlag{Value: true, Name: "fancier"},
+ &cli.DurationFlag{Name: "howlong", Aliases: []string{"H"}, Value: time.Second * 3},
+ &cli.Float64Flag{Name: "howmuch"},
+ &cli.GenericFlag{Name: "wat", Value: &genericType{}},
+ &cli.Int64Flag{Name: "longdistance"},
+ &cli.Int64SliceFlag{Name: "intervals"},
+ &cli.IntFlag{Name: "distance"},
+ &cli.IntSliceFlag{Name: "times"},
+ &cli.StringFlag{Name: "dance-move", Aliases: []string{"d"}},
+ &cli.StringSliceFlag{Name: "names", Aliases: []string{"N"}},
+ &cli.UintFlag{Name: "age"},
+ &cli.Uint64Flag{Name: "bigage"},
+ },
+ EnableShellCompletion: true,
+ HideHelp: false,
+ HideVersion: false,
+ ShellComplete: func(c *cli.Context) {
+ fmt.Fprintf(c.App.Writer, "lipstick\nkiss\nme\nlipstick\nringo\n")
+ },
+ Before: func(c *cli.Context) error {
+ fmt.Fprintf(c.App.Writer, "HEEEERE GOES\n")
+ return nil
+ },
+ After: func(c *cli.Context) error {
+ fmt.Fprintf(c.App.Writer, "Phew!\n")
+ return nil
+ },
+ CommandNotFound: func(c *cli.Context, command string) {
+ fmt.Fprintf(c.App.Writer, "Thar be no %q here.\n", command)
+ },
+ OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error {
+ if isSubcommand {
+ return err
+ }
+
+ fmt.Fprintf(c.App.Writer, "WRONG: %#v\n", err)
+ return nil
+ },
+ Action: func(c *cli.Context) error {
+ cli.DefaultAppComplete(c)
+ cli.HandleExitCoder(errors.New("not an exit coder, though"))
+ cli.ShowAppHelp(c)
+ cli.ShowCommandCompletions(c, "nope")
+ cli.ShowCommandHelp(c, "also-nope")
+ cli.ShowCompletions(c)
+ cli.ShowSubcommandHelp(c)
+ cli.ShowVersion(c)
+
+ categories := c.App.Categories
+ categories.AddCommand("sounds", &cli.Command{
+ Name: "bloop",
+ })
+
+ for _, category := range c.App.Categories.Categories() {
+ fmt.Fprintf(c.App.Writer, "%s\n", category.Name)
+ fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands())
+ fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands())
+ }
+
+ fmt.Printf("%#v\n", c.App.Command("doo"))
+ if c.Bool("infinite") {
+ c.App.Run([]string{"app", "doo", "wop"})
+ }
+
+ if c.Bool("forevar") {
+ c.App.RunAsSubcommand(c)
+ }
+ c.App.Setup()
+ fmt.Printf("%#v\n", c.App.VisibleCategories())
+ fmt.Printf("%#v\n", c.App.VisibleCommands())
+ fmt.Printf("%#v\n", c.App.VisibleFlags())
+
+ fmt.Printf("%#v\n", c.Args().First())
+ if c.Args().Len() > 0 {
+ fmt.Printf("%#v\n", c.Args().Get(1))
+ }
+ fmt.Printf("%#v\n", c.Args().Present())
+ fmt.Printf("%#v\n", c.Args().Tail())
+
+ set := flag.NewFlagSet("contrive", 0)
+ nc := cli.NewContext(c.App, set, c)
+
+ fmt.Printf("%#v\n", nc.Args())
+ fmt.Printf("%#v\n", nc.Bool("nope"))
+ fmt.Printf("%#v\n", !nc.Bool("nerp"))
+ fmt.Printf("%#v\n", nc.Duration("howlong"))
+ fmt.Printf("%#v\n", nc.Float64("hay"))
+ fmt.Printf("%#v\n", nc.Generic("bloop"))
+ fmt.Printf("%#v\n", nc.Int64("bonk"))
+ fmt.Printf("%#v\n", nc.Int64Slice("burnks"))
+ fmt.Printf("%#v\n", nc.Int("bips"))
+ fmt.Printf("%#v\n", nc.IntSlice("blups"))
+ fmt.Printf("%#v\n", nc.String("snurt"))
+ fmt.Printf("%#v\n", nc.StringSlice("snurkles"))
+ fmt.Printf("%#v\n", nc.Uint("flub"))
+ fmt.Printf("%#v\n", nc.Uint64("florb"))
+
+ fmt.Printf("%#v\n", nc.FlagNames())
+ fmt.Printf("%#v\n", nc.IsSet("wat"))
+ fmt.Printf("%#v\n", nc.Set("wat", "nope"))
+ fmt.Printf("%#v\n", nc.NArg())
+ fmt.Printf("%#v\n", nc.NumFlags())
+ fmt.Printf("%#v\n", nc.Lineage()[1])
+
+ nc.Set("wat", "also-nope")
+
+ ec := cli.Exit("ohwell", 86)
+ fmt.Fprintf(c.App.Writer, "%d", ec.ExitCode())
+ fmt.Printf("made it!\n")
+ return ec
+ },
+ Metadata: map[string]interface{}{
+ "layers": "many",
+ "explicable": false,
+ "whatever-values": 19.99,
+ },
+ }
+
+ if os.Getenv("HEXY") != "" {
+ app.Writer = &hexWriter{}
+ app.ErrWriter = &hexWriter{}
+ }
+
+ app.Run(os.Args)
+}
+
+func wopAction(c *cli.Context) error {
+ fmt.Fprintf(c.App.Writer, ":wave: over here, eh\n")
+ return nil
+}
+```
+
+## Contribution Guidelines
+
+Feel free to put up a pull request to fix a bug or maybe add a feature. I will
+give it a code review and make sure that it does not break backwards
+compatibility. If I or any other collaborators agree that it is in line with
+the vision of the project, we will work with you to get the code into
+a mergeable state and merge it into the master branch.
+
+If you have contributed something significant to the project, we will most
+likely add you as a collaborator. As a collaborator you are given the ability
+to merge others pull requests. It is very important that new code does not
+break existing code, so be careful about what code you do choose to merge.
+
+If you feel like you have contributed to the project but have not yet been
+added as a collaborator, we probably forgot to add you, please open an issue.
diff --git a/vendor/gopkg.in/urfave/cli.v2/app.go b/vendor/gopkg.in/urfave/cli.v2/app.go
new file mode 100644
index 0000000..4c073c5
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/app.go
@@ -0,0 +1,490 @@
+package cli
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
+ "sort"
+ "time"
+)
+
+// App is the main structure of a cli application.
+type App struct {
+ // The name of the program. Defaults to path.Base(os.Args[0])
+ Name string
+ // Full name of command for help, defaults to Name
+ HelpName string
+ // Description of the program.
+ Usage string
+ // Text to override the USAGE section of help
+ UsageText string
+ // Description of the program argument format.
+ ArgsUsage string
+ // Version of the program
+ Version string
+ // Description of the program
+ Description string
+ // List of commands to execute
+ Commands []*Command
+ // List of flags to parse
+ Flags []Flag
+ // Boolean to enable shell completion commands
+ EnableShellCompletion bool
+ // Boolean to hide built-in help command
+ HideHelp bool
+ // Boolean to hide built-in version flag and the VERSION section of help
+ HideVersion bool
+ // Categories contains the categorized commands and is populated on app startup
+ Categories CommandCategories
+ // An action to execute when the shell completion flag is set
+ ShellComplete ShellCompleteFunc
+ // An action to execute before any subcommands are run, but after the context is ready
+ // If a non-nil error is returned, no subcommands are run
+ Before BeforeFunc
+ // An action to execute after any subcommands are run, but after the subcommand has finished
+ // It is run even if Action() panics
+ After AfterFunc
+ // The action to execute when no subcommands are specified
+ Action ActionFunc
+ // Execute this function if the proper command cannot be found
+ CommandNotFound CommandNotFoundFunc
+ // Execute this function if an usage error occurs
+ OnUsageError OnUsageErrorFunc
+ // Compilation date
+ Compiled time.Time
+ // List of all authors who contributed
+ Authors []*Author
+ // Copyright of the binary if any
+ Copyright string
+ // Writer writer to write output to
+ Writer io.Writer
+ // ErrWriter writes error output
+ ErrWriter io.Writer
+ // Other custom info
+ Metadata map[string]interface{}
+ // Carries a function which returns app specific info.
+ ExtraInfo func() map[string]string
+ // CustomAppHelpTemplate the text template for app help topic.
+ // cli.go uses text/template to render templates. You can
+ // render custom help text by setting this variable.
+ CustomAppHelpTemplate string
+
+ didSetup bool
+}
+
+// Tries to find out when this binary was compiled.
+// Returns the current time if it fails to find it.
+func compileTime() time.Time {
+ info, err := os.Stat(os.Args[0])
+ if err != nil {
+ return time.Now()
+ }
+ return info.ModTime()
+}
+
+// Setup runs initialization code to ensure all data structures are ready for
+// `Run` or inspection prior to `Run`. It is internally called by `Run`, but
+// will return early if setup has already happened.
+func (a *App) Setup() {
+ if a.didSetup {
+ return
+ }
+
+ a.didSetup = true
+
+ if a.Name == "" {
+ a.Name = filepath.Base(os.Args[0])
+ }
+
+ if a.HelpName == "" {
+ a.HelpName = filepath.Base(os.Args[0])
+ }
+
+ if a.Usage == "" {
+ a.Usage = "A new cli application"
+ }
+
+ if a.Version == "" {
+ a.Version = "0.0.0"
+ }
+
+ if a.ShellComplete == nil {
+ a.ShellComplete = DefaultAppComplete
+ }
+
+ if a.Action == nil {
+ a.Action = helpCommand.Action
+ }
+
+ if a.Compiled == (time.Time{}) {
+ a.Compiled = compileTime()
+ }
+
+ if a.Writer == nil {
+ a.Writer = os.Stdout
+ }
+
+ newCmds := []*Command{}
+ for _, c := range a.Commands {
+ if c.HelpName == "" {
+ c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
+ }
+ newCmds = append(newCmds, c)
+ }
+ a.Commands = newCmds
+
+ if a.Command(helpCommand.Name) == nil && !a.HideHelp {
+ a.appendCommand(helpCommand)
+
+ if HelpFlag != nil {
+ a.appendFlag(HelpFlag)
+ }
+ }
+
+ if a.EnableShellCompletion {
+ a.appendFlag(GenerateCompletionFlag)
+ a.appendFlag(InitCompletionFlag)
+ }
+
+ if !a.HideVersion {
+ a.appendFlag(VersionFlag)
+ }
+
+ a.Categories = newCommandCategories()
+ for _, command := range a.Commands {
+ a.Categories.AddCommand(command.Category, command)
+ }
+ sort.Sort(a.Categories.(*commandCategories))
+
+ if a.Metadata == nil {
+ a.Metadata = make(map[string]interface{})
+ }
+
+ if a.Writer == nil {
+ a.Writer = os.Stdout
+ }
+}
+
+// Run is the entry point to the cli app. Parses the arguments slice and routes
+// to the proper flag/args combination
+func (a *App) Run(arguments []string) (err error) {
+ a.Setup()
+
+ // handle the completion flag separately from the flagset since
+ // completion could be attempted after a flag, but before its value was put
+ // on the command line. this causes the flagset to interpret the completion
+ // flag name as the value of the flag before it which is undesirable
+ // note that we can only do this because the shell autocomplete function
+ // always appends the completion flag at the end of the command
+ shellComplete, arguments := checkShellCompleteFlag(a, arguments)
+
+ // parse flags
+ set, err := flagSet(a.Name, a.Flags)
+ if err != nil {
+ return err
+ }
+
+ set.SetOutput(ioutil.Discard)
+ err = set.Parse(arguments[1:])
+ nerr := normalizeFlags(a.Flags, set)
+ context := NewContext(a, set, nil)
+ if nerr != nil {
+ fmt.Fprintln(a.Writer, nerr)
+ ShowAppHelp(context)
+ return nerr
+ }
+ context.shellComplete = shellComplete
+
+ if checkCompletions(context) {
+ return nil
+ }
+
+ if done, cerr := checkInitCompletion(context); done {
+ if cerr != nil {
+ err = cerr
+ } else {
+ return nil
+ }
+ }
+
+ if err != nil {
+ if a.OnUsageError != nil {
+ err = a.OnUsageError(context, err, false)
+ HandleExitCoder(err)
+ return err
+ }
+ fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
+ ShowAppHelp(context)
+ return err
+ }
+
+ if !a.HideHelp && checkHelp(context) {
+ ShowAppHelp(context)
+ return nil
+ }
+
+ if !a.HideVersion && checkVersion(context) {
+ ShowVersion(context)
+ return nil
+ }
+
+ if a.After != nil {
+ defer func() {
+ if afterErr := a.After(context); afterErr != nil {
+ if err != nil {
+ err = newMultiError(err, afterErr)
+ } else {
+ err = afterErr
+ }
+ }
+ }()
+ }
+
+ if a.Before != nil {
+ beforeErr := a.Before(context)
+ if beforeErr != nil {
+ ShowAppHelp(context)
+ HandleExitCoder(beforeErr)
+ err = beforeErr
+ return err
+ }
+ }
+
+ args := context.Args()
+ if args.Present() {
+ name := args.First()
+ c := a.Command(name)
+ if c != nil {
+ return c.Run(context)
+ }
+ }
+
+ if a.Action == nil {
+ a.Action = helpCommand.Action
+ }
+
+ // Run default Action
+ err = a.Action(context)
+
+ HandleExitCoder(err)
+ return err
+}
+
+// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to
+// generate command-specific flags
+func (a *App) RunAsSubcommand(ctx *Context) (err error) {
+ a.Setup()
+
+ // append help to commands
+ if len(a.Commands) > 0 {
+ if a.Command(helpCommand.Name) == nil && !a.HideHelp {
+ a.appendCommand(helpCommand)
+
+ if HelpFlag != nil {
+ a.appendFlag(HelpFlag)
+ }
+ }
+ }
+
+ newCmds := []*Command{}
+ for _, c := range a.Commands {
+ if c.HelpName == "" {
+ c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
+ }
+ newCmds = append(newCmds, c)
+ }
+ a.Commands = newCmds
+
+ // append flags
+ if a.EnableShellCompletion {
+ a.appendFlag(GenerateCompletionFlag)
+ }
+
+ // parse flags
+ set, err := flagSet(a.Name, a.Flags)
+ if err != nil {
+ return err
+ }
+
+ set.SetOutput(ioutil.Discard)
+ err = set.Parse(ctx.Args().Tail())
+ nerr := normalizeFlags(a.Flags, set)
+ context := NewContext(a, set, ctx)
+
+ if nerr != nil {
+ fmt.Fprintln(a.Writer, nerr)
+ fmt.Fprintln(a.Writer)
+ if len(a.Commands) > 0 {
+ ShowSubcommandHelp(context)
+ } else {
+ ShowCommandHelp(ctx, context.Args().First())
+ }
+ return nerr
+ }
+
+ if checkCompletions(context) {
+ return nil
+ }
+
+ if err != nil {
+ if a.OnUsageError != nil {
+ err = a.OnUsageError(context, err, true)
+ HandleExitCoder(err)
+ return err
+ }
+ fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
+ ShowSubcommandHelp(context)
+ return err
+ }
+
+ if len(a.Commands) > 0 {
+ if checkSubcommandHelp(context) {
+ return nil
+ }
+ } else {
+ if checkCommandHelp(ctx, context.Args().First()) {
+ return nil
+ }
+ }
+
+ if a.After != nil {
+ defer func() {
+ afterErr := a.After(context)
+ if afterErr != nil {
+ HandleExitCoder(err)
+ if err != nil {
+ err = newMultiError(err, afterErr)
+ } else {
+ err = afterErr
+ }
+ }
+ }()
+ }
+
+ if a.Before != nil {
+ beforeErr := a.Before(context)
+ if beforeErr != nil {
+ HandleExitCoder(beforeErr)
+ err = beforeErr
+ return err
+ }
+ }
+
+ args := context.Args()
+ if args.Present() {
+ name := args.First()
+ c := a.Command(name)
+ if c != nil {
+ return c.Run(context)
+ }
+ }
+
+ // Run default Action
+ err = a.Action(context)
+
+ HandleExitCoder(err)
+ return err
+}
+
+// Command returns the named command on App. Returns nil if the command does not exist
+func (a *App) Command(name string) *Command {
+ for _, c := range a.Commands {
+ if c.HasName(name) {
+ return c
+ }
+ }
+
+ return nil
+}
+
+// VisibleCategories returns a slice of categories and commands that are
+// Hidden=false
+func (a *App) VisibleCategories() []CommandCategory {
+ ret := []CommandCategory{}
+ for _, category := range a.Categories.Categories() {
+ if visible := func() CommandCategory {
+ if len(category.VisibleCommands()) > 0 {
+ return category
+ }
+ return nil
+ }(); visible != nil {
+ ret = append(ret, visible)
+ }
+ }
+ return ret
+}
+
+// VisibleCommands returns a slice of the Commands with Hidden=false
+func (a *App) VisibleCommands() []*Command {
+ ret := []*Command{}
+ for _, command := range a.Commands {
+ if !command.Hidden {
+ ret = append(ret, command)
+ }
+ }
+ return ret
+}
+
+// VisibleFlags returns a slice of the Flags with Hidden=false
+func (a *App) VisibleFlags() []Flag {
+ return visibleFlags(a.Flags)
+}
+
+func (a *App) hasFlag(flag Flag) bool {
+ for _, f := range a.Flags {
+ if reflect.DeepEqual(flag, f) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func (a *App) errWriter() io.Writer {
+
+ // When the app ErrWriter is nil use the package level one.
+ if a.ErrWriter == nil {
+ return ErrWriter
+ }
+
+ return a.ErrWriter
+}
+
+func (a *App) appendFlag(fl Flag) {
+ if !hasFlag(a.Flags, fl) {
+ a.Flags = append(a.Flags, fl)
+ }
+}
+
+func (a *App) appendCommand(c *Command) {
+ if !hasCommand(a.Commands, c) {
+ a.Commands = append(a.Commands, c)
+ }
+}
+
+// Author represents someone who has contributed to a cli project.
+type Author struct {
+ Name string // The Authors name
+ Email string // The Authors email
+}
+
+// String makes Author comply to the Stringer interface, to allow an easy print in the templating process
+func (a *Author) String() string {
+ e := ""
+ if a.Email != "" {
+ e = " <" + a.Email + ">"
+ }
+
+ return fmt.Sprintf("%v%v", a.Name, e)
+}
+
+// DefaultAppComplete returns an ActionFunc to run a default command if non were passed.
+// Usage: `app.Action = cli.DefaultCommand("command")`
+func DefaultCommand(name string) ActionFunc {
+ return func(ctx *Context) error {
+ return ctx.App.Command(name).Run(ctx)
+ }
+}
diff --git a/vendor/gopkg.in/urfave/cli.v2/appveyor.yml b/vendor/gopkg.in/urfave/cli.v2/appveyor.yml
new file mode 100644
index 0000000..886f0e9
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/appveyor.yml
@@ -0,0 +1,36 @@
+version: "{build}"
+
+os: Windows Server 2016
+
+image: Visual Studio 2017
+
+clone_folder: c:\gopath\src\github.com\urfave\cli
+
+cache:
+- node_modules
+
+environment:
+ GOPATH: C:\gopath
+ GOVERSION: 1.8.x
+ PYTHON: C:\Python36-x64
+ PYTHON_VERSION: 3.6.x
+ PYTHON_ARCH: 64
+
+install:
+- set PATH=%GOPATH%\bin;C:\go\bin;%PATH%
+- go version
+- go env
+- go get github.com/urfave/gfmrun/...
+- rmdir c:\gopath\src\gopkg.in\urfave\cli.v2 /s /q
+- rmdir c:\gopath\pkg /s /q
+- git clone . c:\gopath\src\gopkg.in\urfave\cli.v2
+- go get -v -t ./...
+- if not exist node_modules\.bin\markdown-toc npm install markdown-toc
+
+build_script:
+- python runtests vet
+- python runtests test
+- python runtests gfmrun
+- python cli-v1-to-v2 --selftest
+- python runtests migrations
+- python runtests toc
diff --git a/vendor/gopkg.in/urfave/cli.v2/args.go b/vendor/gopkg.in/urfave/cli.v2/args.go
new file mode 100644
index 0000000..5618a47
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/args.go
@@ -0,0 +1,60 @@
+package cli
+
+import "errors"
+
+var (
+ argsRangeErr = errors.New("index out of range")
+)
+
+type Args interface {
+ // Get returns the nth argument, or else a blank string
+ Get(n int) string
+ // First returns the first argument, or else a blank string
+ First() string
+ // Tail returns the rest of the arguments (not the first one)
+ // or else an empty string slice
+ Tail() []string
+ // Len returns the length of the wrapped slice
+ Len() int
+ // Present checks if there are any arguments present
+ Present() bool
+ // Slice returns a copy of the internal slice
+ Slice() []string
+}
+
+type args []string
+
+func (a *args) Get(n int) string {
+ if len(*a) > n {
+ return (*a)[n]
+ }
+ return ""
+}
+
+func (a *args) First() string {
+ return a.Get(0)
+}
+
+func (a *args) Tail() []string {
+ if a.Len() >= 2 {
+ tail := []string((*a)[1:])
+ ret := make([]string, len(tail))
+ copy(ret, tail)
+ return ret
+ }
+ return []string{}
+}
+
+func (a *args) Len() int {
+ return len(*a)
+}
+
+func (a *args) Present() bool {
+ return a.Len() != 0
+}
+
+func (a *args) Slice() []string {
+ ret := make([]string, len(*a))
+ copy(ret, []string(*a))
+ return ret
+}
diff --git a/vendor/gopkg.in/urfave/cli.v2/category.go b/vendor/gopkg.in/urfave/cli.v2/category.go
new file mode 100644
index 0000000..3b405c0
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/category.go
@@ -0,0 +1,85 @@
+package cli
+
+type CommandCategories interface {
+ // AddCommand adds a command to a category, creating a new category if necessary.
+ AddCommand(category string, command *Command)
+ // Categories returns a copy of the category slice
+ Categories() []CommandCategory
+}
+
+type commandCategories []*commandCategory
+
+func newCommandCategories() CommandCategories {
+ ret := commandCategories([]*commandCategory{})
+ return &ret
+}
+
+func (c *commandCategories) Less(i, j int) bool {
+ return (*c)[i].Name() < (*c)[j].Name()
+}
+
+func (c *commandCategories) Len() int {
+ return len(*c)
+}
+
+func (c *commandCategories) Swap(i, j int) {
+ (*c)[i], (*c)[j] = (*c)[j], (*c)[i]
+}
+
+func (c *commandCategories) AddCommand(category string, command *Command) {
+ for _, commandCategory := range []*commandCategory(*c) {
+ if commandCategory.name == category {
+ commandCategory.commands = append(commandCategory.commands, command)
+ return
+ }
+ }
+ newVal := commandCategories(append(*c,
+ &commandCategory{name: category, commands: []*Command{command}}))
+ (*c) = newVal
+}
+
+func (c *commandCategories) Categories() []CommandCategory {
+ ret := make([]CommandCategory, len(*c))
+ for i, cat := range *c {
+ ret[i] = cat
+ }
+ return ret
+}
+
+// CommandCategory is a category containing commands.
+type CommandCategory interface {
+ // Name returns the category name string
+ Name() string
+ // VisibleCommands returns a slice of the Commands with Hidden=false
+ VisibleCommands() []*Command
+}
+
+type commandCategory struct {
+ name string
+ commands []*Command
+}
+
+func newCommandCategory(name string) *commandCategory {
+ return &commandCategory{
+ name: name,
+ commands: []*Command{},
+ }
+}
+
+func (c *commandCategory) Name() string {
+ return c.name
+}
+
+func (c *commandCategory) VisibleCommands() []*Command {
+ if c.commands == nil {
+ c.commands = []*Command{}
+ }
+
+ ret := []*Command{}
+ for _, command := range c.commands {
+ if !command.Hidden {
+ ret = append(ret, command)
+ }
+ }
+ return ret
+}
diff --git a/vendor/gopkg.in/urfave/cli.v2/cli-v1-to-v2 b/vendor/gopkg.in/urfave/cli.v2/cli-v1-to-v2
new file mode 100644
index 0000000..b815295
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/cli-v1-to-v2
@@ -0,0 +1,479 @@
+#!/usr/bin/env python
+from __future__ import print_function, unicode_literals
+
+import argparse
+import io
+import logging
+import os
+import re
+import sys
+
+
+_DESCRIPTION = """\
+Migrate arbitrary `.go` sources (mostly) from the v1 to v2 API.
+"""
+_MIGRATORS = []
+
+
+def main(sysargs=sys.argv[:]):
+ parser = argparse.ArgumentParser(
+ description=_DESCRIPTION,
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+ parser.add_argument('path', nargs='*',
+ type=os.path.abspath, default=os.getcwd())
+ parser.add_argument('-w', '--write', help='write changes back to file',
+ action='store_true', default=False)
+ parser.add_argument('-q', '--quiet', help='quiet down the logging',
+ action='store_true', default=False)
+ parser.add_argument('-D', '--debug', help='debug up the logging',
+ action='store_true',
+ default=(os.environ.get('DEBUG') != ''))
+ parser.add_argument('--selftest', help='run internal tests',
+ action='store_true', default=False)
+
+ args = parser.parse_args(sysargs[1:])
+
+ if args.selftest:
+ logging.basicConfig(
+ level=logging.WARN,
+ format='selftest: %(message)s'
+ )
+ test_migrators()
+ return 0
+
+ level = logging.FATAL if args.quiet else logging.INFO
+ level = logging.DEBUG if args.debug else level
+
+ logging.basicConfig(level=level, format='%(message)s')
+
+ paths = args.path
+ if len(paths) == 0:
+ paths = ['.']
+
+ for filepath in _find_candidate_files(paths):
+ updated_source = _update_filepath(filepath)
+ if args.write:
+ logging.info('Updating %s', filepath)
+
+ with io.open(filepath, 'w', encoding='utf-8') as outfile:
+ outfile.write(updated_source)
+ else:
+ logging.info('// Updated %s:', filepath)
+ print(updated_source)
+
+ return 0
+
+
+def _find_candidate_files(paths):
+ for path in paths:
+ if not os.path.isdir(path):
+ yield path
+ continue
+
+ for curdir, dirs, files in os.walk(path):
+ for i, dirname in enumerate(dirs[:]):
+ if dirname.startswith('.'):
+ dirs.pop(i)
+
+ for filename in files:
+ if not filename.decode('utf-8').endswith('.go'):
+ continue
+
+ filepath = os.path.join(curdir, filename)
+ if not os.access(filepath, os.R_OK | os.W_OK):
+ continue
+
+ yield filepath
+
+
+def _update_filepath(filepath):
+ with io.open(filepath, encoding='utf-8') as infile:
+ return _update_source(infile.read())
+
+
+def _update_source(source):
+ for migrator, func in _MIGRATORS:
+ logging.debug('Running %s migrator', migrator)
+ source = func(source)
+ return source
+
+
+def _subfmt(pattern, replfmt, source, flags=re.UNICODE):
+ def repl(match):
+ return replfmt.format(**match.groupdict())
+ return re.sub(pattern, repl, source, flags=flags)
+
+
+def _migrator(func):
+ _MIGRATORS.append((func.__name__.strip('_'), func))
+ return func
+
+
+@_migrator
+def _slice_pointer_types(source):
+ return _subfmt(
+ '(?P\\[\\])cli\\.(?PCommand|Author){',
+ '{prefix}*cli.{type}{{', source
+ )
+
+
+@_migrator
+def _pointer_type_literal(source):
+ return _subfmt(
+ '(?P\\s+)cli\\.(?PCommand|Author){',
+ '{prefix}&cli.{type}{{', source
+ )
+
+
+@_migrator
+def _slice_types(source):
+ return _subfmt(
+ '&cli\\.(?PIntSlice|StringSlice){(?P[^}]*)}',
+ 'cli.New{type}({args})', source, flags=re.DOTALL | re.UNICODE
+ )
+
+
+@_migrator
+def _flag_literals(source):
+ return _subfmt(
+ '(?P\\s+)cli\\.(?P\\w+)Flag{',
+ '{prefix}&cli.{type}Flag{{', source
+ )
+
+
+@_migrator
+def _v1_imports(source):
+ return re.sub(
+ '"(?:github\\.com|gopkg\\.in)/(?:codegangsta|urfave)/cli(?:\\.v1|)"',
+ '"gopkg.in/urfave/cli.v2"', source, flags=re.UNICODE
+ )
+
+
+@_migrator
+def _new_exit_error(source):
+ return re.sub('cli\\.NewExitError', 'cli.Exit', source, flags=re.UNICODE)
+
+
+@_migrator
+def _bool_t_flag(source):
+ return _subfmt(
+ 'cli\\.BoolTFlag{(?P[^}]*)}',
+ 'cli.BoolFlag{{Value: true,{args}}}',
+ source, flags=re.DOTALL | re.UNICODE
+ )
+
+
+@_migrator
+def _context_args_len(source):
+ return _subfmt(
+ 'len\\((?P\\S+)\\.Args\\(\\)\\)',
+ '{prefix}.Args().Len()', source
+ )
+
+
+@_migrator
+def _context_args_index(source):
+ return _subfmt(
+ '\\.Args\\(\\)\\[(?P\\d+)\\]',
+ '.Args().Get({index})', source
+ )
+
+
+@_migrator
+def _envvar_string(source):
+ return re.sub(
+ 'EnvVar:(?P\\s+)"(?P[^"]+)"',
+ _envvar_string_repl, source, flags=re.UNICODE
+ )
+
+
+def _envvar_string_repl(match):
+ return 'EnvVars:{ws}[]string{{{value}}}'.format(
+ value=', '.join([
+ '"{}"'.format(s) for s in
+ re.split(
+ '\\s*,\\s*', match.groupdict()['string'],
+ flags=re.UNICODE
+ )
+ ]),
+ **match.groupdict()
+ )
+
+
+@_migrator
+def _flag_name_stringly(source):
+ return re.sub(
+ '(?P\\s+)Name:(?P\\s+)"(?P[^"]+)"',
+ _flag_name_stringly_repl, source, flags=re.UNICODE
+ )
+
+
+def _flag_name_stringly_repl(match):
+ revars = dict(match.groupdict())
+
+ string = revars['string']
+ parts = list(
+ reversed(
+ sorted(
+ filter(lambda s: len(s.strip()) > 0, [
+ part.strip() for part in string.split(',')
+ ]), key=len
+ )
+ )
+ )
+
+ if len(parts) == 1:
+ return '{prefix}Name:{ws}"{string}"'.format(**revars)
+
+ return (
+ '{prefix}Name:{ws}"{name}", Aliases: []string{{{aliases}}}'
+ ).format(
+ name=parts[0],
+ aliases=', '.join(['"{}"'.format(s) for s in parts[1:]]),
+ **revars
+ )
+
+
+@_migrator
+def _commands_opaque_type(source):
+ return _subfmt(
+ 'cli\\.Commands(?P[^B])',
+ '[]*cli.Command{suffix}',
+ source
+ )
+
+
+@_migrator
+def _flag_names(source):
+ return re.sub('\\.GetName\\(\\)', '.Names()[0]', source, flags=re.UNICODE)
+
+
+@_migrator
+def _app_categories(source):
+ source = _subfmt(
+ '(?Prange\\s+\\S+)\\.App\\.Categories\\(\\)',
+ '{prefix}.App.Categories.Categories()', source
+ )
+
+ return re.sub(
+ '\\.App\\.Categories\\(\\)', '.App.Categories',
+ source, flags=re.UNICODE
+ )
+
+
+@_migrator
+def _command_category_commands(source):
+ # XXX: brittle
+ return _subfmt(
+ '(?P\\s+category\\.)Commands(?P[^(])',
+ '{prefix}VisibleCommands(){suffix}', source
+ )
+
+
+@_migrator
+def _context_bool_t(source):
+ # XXX: probably brittle
+ return _subfmt(
+ '(?P\\S+)(?:Global|)BoolT\\(',
+ '!{prefix}Bool(', source
+ )
+
+
+@_migrator
+def _context_global_methods(source):
+ return _subfmt(
+ '\\.Global(?P'
+ 'Bool|Duration|Float64|Generic|Int|IntSlice|String|StringSlice|'
+ 'FlagNames|IsSet|Set'
+ ')\\(',
+ '.{method}(', source
+ )
+
+
+@_migrator
+def _context_parent(source):
+ # XXX: brittle
+ return re.sub('\\.Parent\\(\\)', '.Lineage()[1]', source, flags=re.UNICODE)
+
+
+@_migrator
+def _app_init(source):
+ return re.sub(
+ 'cli\\.NewApp\\(\\)', '(&cli.App{})', source, flags=re.UNICODE
+ )
+
+
+@_migrator
+def _bash_complete(source):
+ return re.sub(
+ 'BashComplete:', 'ShellComplete:',
+ re.sub('\\.BashComplete', '.ShellComplete', source, flags=re.UNICODE))
+
+
+@_migrator
+def _enable_bash_completion(source):
+ return re.sub(
+ '\\.EnableBashCompletion', '.EnableShellCompletion', source, flags=re.UNICODE
+ )
+
+
+@_migrator
+def _bash_completion_flag(source):
+ return re.sub(
+ 'cli\\.BashCompletionFlag', 'cli.GenerateCompletionFlag', source, flags=re.UNICODE
+ )
+
+
+def test_migrators():
+ import difflib
+
+ for i, (source, expected) in enumerate(_MIGRATOR_TESTS):
+ actual = _update_source(source)
+ if expected != actual:
+ udiff = difflib.unified_diff(
+ expected.splitlines(), actual.splitlines(),
+ fromfile='a/source.go', tofile='b/source.go', lineterm=''
+ )
+ for line in udiff:
+ print(line)
+ raise AssertionError('migrated source does not match expected')
+ logging.warn('Test case %d/%d OK', i+1, len(_MIGRATOR_TESTS))
+
+
+_MIGRATOR_TESTS = (
+ ("""
+\t\t\t&cli.StringSlice{"a", "b", "c"},
+""", """
+\t\t\tcli.NewStringSlice("a", "b", "c"),
+"""),
+ ("""
+\t\tcli.IntFlag{
+\t\t\tName: "yep",
+\t\t\tValue: 3,
+\t\t}
+""", """
+\t\t&cli.IntFlag{
+\t\t\tName: "yep",
+\t\t\tValue: 3,
+\t\t}
+"""),
+ ("""
+\t\tapp.Commands = []cli.Command{
+\t\t\t{
+\t\t\t\tName: "whatebbs",
+\t\t\t},
+\t\t}
+""", """
+\t\tapp.Commands = []*cli.Command{
+\t\t\t{
+\t\t\t\tName: "whatebbs",
+\t\t\t},
+\t\t}
+"""),
+ ("""
+\t\tapp.Commands = []cli.Command{
+\t\t\tcli.Command{
+\t\t\t\tName: "whatebbs",
+\t\t\t},
+\t\t}
+""", """
+\t\tapp.Commands = []*cli.Command{
+\t\t\t&cli.Command{
+\t\t\t\tName: "whatebbs",
+\t\t\t},
+\t\t}
+"""),
+ ("""
+\t"github.com/codegangsta/cli"
+\t"github.com/urfave/cli"
+\t"gopkg.in/codegangsta/cli"
+\t"gopkg.in/codegangsta/cli.v1"
+\t"gopkg.in/urfave/cli"
+\t"gopkg.in/urfave/cli.v1"
+""", """
+\t"gopkg.in/urfave/cli.v2"
+\t"gopkg.in/urfave/cli.v2"
+\t"gopkg.in/urfave/cli.v2"
+\t"gopkg.in/urfave/cli.v2"
+\t"gopkg.in/urfave/cli.v2"
+\t"gopkg.in/urfave/cli.v2"
+"""),
+ ("""
+\t\t\t\treturn cli.NewExitError("foo whatebber", 9)
+""", """
+\t\t\t\treturn cli.Exit("foo whatebber", 9)
+"""),
+ ("""
+\t\t\tapp.Flags = []cli.Flag{
+\t\t\t\tcli.StringFlag{
+\t\t\t\t\tName: "aha",
+\t\t\t\t},
+\t\t\t\tcli.BoolTFlag{
+\t\t\t\t\tName: "blurp",
+\t\t\t\t},
+\t\t\t}
+""", """
+\t\t\tapp.Flags = []cli.Flag{
+\t\t\t\t&cli.StringFlag{
+\t\t\t\t\tName: "aha",
+\t\t\t\t},
+\t\t\t\t&cli.BoolFlag{Value: true,
+\t\t\t\t\tName: "blurp",
+\t\t\t\t},
+\t\t\t}
+"""),
+ ("""
+\t\t\tAction = func(c *cli.Context) error {
+\t\t\t\tif c.Args()[4] == "meep" {
+\t\t\t\t\treturn nil
+\t\t\t\t}
+\t\t\t\treturn errors.New("mope")
+\t\t\t}
+""", """
+\t\t\tAction = func(c *cli.Context) error {
+\t\t\t\tif c.Args().Get(4) == "meep" {
+\t\t\t\t\treturn nil
+\t\t\t\t}
+\t\t\t\treturn errors.New("mope")
+\t\t\t}
+"""),
+ ("""
+\t\tapp.Flags = []cli.Flag{
+\t\t\tcli.StringFlag{
+\t\t\t\tName: "toots",
+\t\t\t\tEnvVar: "TOOTS,TOOTERS",
+\t\t\t},
+\t\t}
+""", """
+\t\tapp.Flags = []cli.Flag{
+\t\t\t&cli.StringFlag{
+\t\t\t\tName: "toots",
+\t\t\t\tEnvVars: []string{"TOOTS", "TOOTERS"},
+\t\t\t},
+\t\t}
+"""),
+ ("""
+\t\tapp.Flags = []cli.Flag{
+\t\t\tcli.StringFlag{
+\t\t\t\tName: "t, tootles, toots",
+\t\t\t},
+\t\t}
+""", """
+\t\tapp.Flags = []cli.Flag{
+\t\t\t&cli.StringFlag{
+\t\t\t\tName: "tootles", Aliases: []string{"toots", "t"},
+\t\t\t},
+\t\t}
+"""),
+ ("""
+\t\tapp := cli.NewApp()
+\t\tapp.HideHelp = true
+""", """
+\t\tapp := (&cli.App{})
+\t\tapp.HideHelp = true
+""")
+)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/vendor/gopkg.in/urfave/cli.v2/cli.go b/vendor/gopkg.in/urfave/cli.v2/cli.go
new file mode 100644
index 0000000..81fc7ab
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/cli.go
@@ -0,0 +1,23 @@
+// Package cli provides a minimal framework for creating and organizing command line
+// Go applications. cli is designed to be easy to understand and write, the most simple
+// cli application can be written as follows:
+// func main() {
+// (&cli.App{}).Run(os.Args)
+// }
+//
+// Of course this application does not do much, so let's make this an actual application:
+// func main() {
+// app := &cli.App{
+// Name: "greet",
+// Usage: "say a greeting",
+// Action: func(c *cli.Context) error {
+// fmt.Println("Greetings")
+// return nil
+// },
+// }
+//
+// app.Run(os.Args)
+// }
+package cli
+
+//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go
diff --git a/vendor/gopkg.in/urfave/cli.v2/command.go b/vendor/gopkg.in/urfave/cli.v2/command.go
new file mode 100644
index 0000000..05093b8
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/command.go
@@ -0,0 +1,270 @@
+package cli
+
+import (
+ "fmt"
+ "io/ioutil"
+ "sort"
+ "strings"
+)
+
+// Command is a subcommand for a cli.App.
+type Command struct {
+ // The name of the command
+ Name string
+ // A list of aliases for the command
+ Aliases []string
+ // A short description of the usage of this command
+ Usage string
+ // Custom text to show on USAGE section of help
+ UsageText string
+ // A longer explanation of how the command works
+ Description string
+ // A short description of the arguments of this command
+ ArgsUsage string
+ // The category the command is part of
+ Category string
+ // The function to call when checking for shell command completions
+ ShellComplete ShellCompleteFunc
+ // An action to execute before any sub-subcommands are run, but after the context is ready
+ // If a non-nil error is returned, no sub-subcommands are run
+ Before BeforeFunc
+ // An action to execute after any subcommands are run, but after the subcommand has finished
+ // It is run even if Action() panics
+ After AfterFunc
+ // The function to call when this command is invoked
+ Action ActionFunc
+ // Execute this function if a usage error occurs.
+ OnUsageError OnUsageErrorFunc
+ // List of child commands
+ Subcommands []*Command
+ // List of flags to parse
+ Flags []Flag
+ // Treat all flags as normal arguments if true
+ SkipFlagParsing bool
+ // Boolean to hide built-in help command
+ HideHelp bool
+ // Boolean to hide this command from help or completion
+ Hidden bool
+
+ // Full name of command for help, defaults to full command name, including parent commands.
+ HelpName string
+ commandNamePath []string
+
+ // CustomHelpTemplate the text template for the command help topic.
+ // cli.go uses text/template to render templates. You can
+ // render custom help text by setting this variable.
+ CustomHelpTemplate string
+}
+
+type CommandsByName []*Command
+
+func (c CommandsByName) Len() int {
+ return len(c)
+}
+
+func (c CommandsByName) Less(i, j int) bool {
+ return c[i].Name < c[j].Name
+}
+
+func (c CommandsByName) Swap(i, j int) {
+ c[i], c[j] = c[j], c[i]
+}
+
+// FullName returns the full name of the command.
+// For subcommands this ensures that parent commands are part of the command path
+func (c *Command) FullName() string {
+ if c.commandNamePath == nil {
+ return c.Name
+ }
+ return strings.Join(c.commandNamePath, " ")
+}
+
+// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags
+func (c *Command) Run(ctx *Context) (err error) {
+ if len(c.Subcommands) > 0 {
+ return c.startApp(ctx)
+ }
+
+ if !c.HideHelp && HelpFlag != nil {
+ // append help to flags
+ c.appendFlag(HelpFlag)
+ }
+
+ if ctx.App.EnableShellCompletion {
+ c.appendFlag(GenerateCompletionFlag)
+ }
+
+ set, err := flagSet(c.Name, c.Flags)
+ if err != nil {
+ return err
+ }
+ set.SetOutput(ioutil.Discard)
+
+ if c.SkipFlagParsing {
+ err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
+ } else {
+ err = set.Parse(ctx.Args().Tail())
+ }
+
+ nerr := normalizeFlags(c.Flags, set)
+ if nerr != nil {
+ fmt.Fprintln(ctx.App.Writer, nerr)
+ fmt.Fprintln(ctx.App.Writer)
+ ShowCommandHelp(ctx, c.Name)
+ return nerr
+ }
+
+ context := NewContext(ctx.App, set, ctx)
+ context.Command = c
+ if checkCommandCompletions(context, c.Name) {
+ return nil
+ }
+
+ if err != nil {
+ if c.OnUsageError != nil {
+ err = c.OnUsageError(context, err, false)
+ HandleExitCoder(err)
+ return err
+ }
+ fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error())
+ fmt.Fprintln(context.App.Writer)
+ ShowCommandHelp(context, c.Name)
+ return err
+ }
+
+ if checkCommandHelp(context, c.Name) {
+ return nil
+ }
+
+ if c.After != nil {
+ defer func() {
+ afterErr := c.After(context)
+ if afterErr != nil {
+ HandleExitCoder(err)
+ if err != nil {
+ err = newMultiError(err, afterErr)
+ } else {
+ err = afterErr
+ }
+ }
+ }()
+ }
+
+ if c.Before != nil {
+ err = c.Before(context)
+ if err != nil {
+ ShowCommandHelp(context, c.Name)
+ HandleExitCoder(err)
+ return err
+ }
+ }
+
+ if c.Action == nil {
+ c.Action = helpSubcommand.Action
+ }
+
+ context.Command = c
+ err = c.Action(context)
+
+ if err != nil {
+ HandleExitCoder(err)
+ }
+ return err
+}
+
+// Names returns the names including short names and aliases.
+func (c *Command) Names() []string {
+ return append([]string{c.Name}, c.Aliases...)
+}
+
+// HasName returns true if Command.Name matches given name
+func (c *Command) HasName(name string) bool {
+ for _, n := range c.Names() {
+ if n == name {
+ return true
+ }
+ }
+ return false
+}
+
+func (c *Command) startApp(ctx *Context) error {
+ app := &App{
+ Metadata: ctx.App.Metadata,
+ Name: fmt.Sprintf("%s %s", ctx.App.Name, c.Name),
+ }
+
+ if c.HelpName == "" {
+ app.HelpName = c.HelpName
+ } else {
+ app.HelpName = app.Name
+ }
+
+ app.Usage = c.Usage
+ app.Description = c.Description
+ app.ArgsUsage = c.ArgsUsage
+
+ // set CommandNotFound
+ app.CommandNotFound = ctx.App.CommandNotFound
+ app.CustomAppHelpTemplate = c.CustomHelpTemplate
+
+ // set the flags and commands
+ app.Commands = c.Subcommands
+ app.Flags = c.Flags
+ app.HideHelp = c.HideHelp
+
+ app.Version = ctx.App.Version
+ app.HideVersion = ctx.App.HideVersion
+ app.Compiled = ctx.App.Compiled
+ app.Writer = ctx.App.Writer
+ app.ErrWriter = ctx.App.ErrWriter
+
+ app.Categories = newCommandCategories()
+ for _, command := range c.Subcommands {
+ app.Categories.AddCommand(command.Category, command)
+ }
+
+ sort.Sort(app.Categories.(*commandCategories))
+
+ // bash completion
+ app.EnableShellCompletion = ctx.App.EnableShellCompletion
+ if c.ShellComplete != nil {
+ app.ShellComplete = c.ShellComplete
+ }
+
+ // set the actions
+ app.Before = c.Before
+ app.After = c.After
+ if c.Action != nil {
+ app.Action = c.Action
+ } else {
+ app.Action = helpSubcommand.Action
+ }
+ app.OnUsageError = c.OnUsageError
+
+ for index, cc := range app.Commands {
+ app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
+ }
+
+ return app.RunAsSubcommand(ctx)
+}
+
+// VisibleFlags returns a slice of the Flags with Hidden=false
+func (c *Command) VisibleFlags() []Flag {
+ return visibleFlags(c.Flags)
+}
+
+func (c *Command) appendFlag(fl Flag) {
+ if !hasFlag(c.Flags, fl) {
+ c.Flags = append(c.Flags, fl)
+ }
+}
+
+func hasCommand(commands []*Command, command *Command) bool {
+ for _, existing := range commands {
+ if command == existing {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/vendor/gopkg.in/urfave/cli.v2/context.go b/vendor/gopkg.in/urfave/cli.v2/context.go
new file mode 100644
index 0000000..9802594
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/context.go
@@ -0,0 +1,236 @@
+package cli
+
+import (
+ "errors"
+ "flag"
+ "os"
+ "reflect"
+ "strings"
+)
+
+// Context is a type that is passed through to
+// each Handler action in a cli application. Context
+// can be used to retrieve context-specific args and
+// parsed command-line options.
+type Context struct {
+ App *App
+ Command *Command
+ shellComplete bool
+
+ flagSet *flag.FlagSet
+ parentContext *Context
+}
+
+// NewContext creates a new context. For use in when invoking an App or Command action.
+func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
+ c := &Context{App: app, flagSet: set, parentContext: parentCtx}
+
+ if parentCtx != nil {
+ c.shellComplete = parentCtx.shellComplete
+ }
+
+ return c
+}
+
+// NumFlags returns the number of flags set
+func (c *Context) NumFlags() int {
+ return c.flagSet.NFlag()
+}
+
+// Set sets a context flag to a value.
+func (c *Context) Set(name, value string) error {
+ return c.flagSet.Set(name, value)
+}
+
+// IsSet determines if the flag was actually set
+func (c *Context) IsSet(name string) bool {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ isSet := false
+ fs.Visit(func(f *flag.Flag) {
+ if f.Name == name {
+ isSet = true
+ }
+ })
+ if isSet {
+ return true
+ }
+ }
+
+ // XXX hack to support IsSet for flags with EnvVar
+ //
+ // There isn't an easy way to do this with the current implementation since
+ // whether a flag was set via an environment variable is very difficult to
+ // determine here. Instead, we intend to introduce a backwards incompatible
+ // change in version 2 to add `IsSet` to the Flag interface to push the
+ // responsibility closer to where the information required to determine
+ // whether a flag is set by non-standard means such as environment
+ // variables is avaliable.
+ //
+ // See https://github.com/urfave/cli/issues/294 for additional discussion
+ f := lookupFlag(name, c)
+ if f == nil {
+ return false
+ }
+
+ val := reflect.ValueOf(f)
+ if val.Kind() == reflect.Ptr {
+ val = val.Elem()
+ }
+
+ envVarValues := val.FieldByName("EnvVars")
+ if !envVarValues.IsValid() {
+ return false
+ }
+
+ for _, envVar := range envVarValues.Interface().([]string) {
+ envVar = strings.TrimSpace(envVar)
+ if envVal := os.Getenv(envVar); envVal != "" {
+ return true
+ }
+ }
+
+ return false
+}
+
+// LocalFlagNames returns a slice of flag names used in this context.
+func (c *Context) LocalFlagNames() []string {
+ names := []string{}
+ c.flagSet.Visit(makeFlagNameVisitor(&names))
+ return names
+}
+
+// FlagNames returns a slice of flag names used by the this context and all of
+// its parent contexts.
+func (c *Context) FlagNames() []string {
+ names := []string{}
+ for _, ctx := range c.Lineage() {
+ ctx.flagSet.Visit(makeFlagNameVisitor(&names))
+ }
+ return names
+}
+
+// Lineage returns *this* context and all of its ancestor contexts in order from
+// child to parent
+func (c *Context) Lineage() []*Context {
+ lineage := []*Context{}
+
+ for cur := c; cur != nil; cur = cur.parentContext {
+ lineage = append(lineage, cur)
+ }
+
+ return lineage
+}
+
+// value returns the value of the flag corresponding to `name`
+func (c *Context) value(name string) interface{} {
+ return c.flagSet.Lookup(name).Value.(flag.Getter).Get()
+}
+
+// Args returns the command line arguments associated with the context.
+func (c *Context) Args() Args {
+ ret := args(c.flagSet.Args())
+ return &ret
+}
+
+// NArg returns the number of the command line arguments.
+func (c *Context) NArg() int {
+ return c.Args().Len()
+}
+
+func lookupFlag(name string, ctx *Context) Flag {
+ for _, c := range ctx.Lineage() {
+ if c.Command == nil {
+ continue
+ }
+
+ for _, f := range c.Command.Flags {
+ for _, n := range f.Names() {
+ if n == name {
+ return f
+ }
+ }
+ }
+ }
+
+ if ctx.App != nil {
+ for _, f := range ctx.App.Flags {
+ for _, n := range f.Names() {
+ if n == name {
+ return f
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+func lookupFlagSet(name string, ctx *Context) *flag.FlagSet {
+ for _, c := range ctx.Lineage() {
+ if f := c.flagSet.Lookup(name); f != nil {
+ return c.flagSet
+ }
+ }
+
+ return nil
+}
+
+func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
+ switch ff.Value.(type) {
+ case Serializeder:
+ set.Set(name, ff.Value.(Serializeder).Serialized())
+ default:
+ set.Set(name, ff.Value.String())
+ }
+}
+
+func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
+ visited := make(map[string]bool)
+ set.Visit(func(f *flag.Flag) {
+ visited[f.Name] = true
+ })
+ for _, f := range flags {
+ parts := f.Names()
+ if len(parts) == 1 {
+ continue
+ }
+ var ff *flag.Flag
+ for _, name := range parts {
+ name = strings.Trim(name, " ")
+ if visited[name] {
+ if ff != nil {
+ return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
+ }
+ ff = set.Lookup(name)
+ }
+ }
+ if ff == nil {
+ continue
+ }
+ for _, name := range parts {
+ name = strings.Trim(name, " ")
+ if !visited[name] {
+ copyFlag(name, ff, set)
+ }
+ }
+ }
+ return nil
+}
+
+func makeFlagNameVisitor(names *[]string) func(*flag.Flag) {
+ return func(f *flag.Flag) {
+ nameParts := strings.Split(f.Name, ",")
+ name := strings.TrimSpace(nameParts[0])
+
+ for _, part := range nameParts {
+ part = strings.TrimSpace(part)
+ if len(part) > len(name) {
+ name = part
+ }
+ }
+
+ if name != "" {
+ (*names) = append(*names, name)
+ }
+ }
+}
diff --git a/vendor/gopkg.in/urfave/cli.v2/errors.go b/vendor/gopkg.in/urfave/cli.v2/errors.go
new file mode 100644
index 0000000..6259699
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/errors.go
@@ -0,0 +1,125 @@
+package cli
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "strings"
+)
+
+// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
+var OsExiter = os.Exit
+
+// ErrWriter is used to write errors to the user. This can be anything
+// implementing the io.Writer interface and defaults to os.Stderr.
+var ErrWriter io.Writer = os.Stderr
+
+// MultiError is an error that wraps multiple errors.
+type MultiError interface {
+ error
+ // Errors returns a copy of the errors slice
+ Errors() []error
+}
+
+// NewMultiError creates a new MultiError. Pass in one or more errors.
+func newMultiError(err ...error) MultiError {
+ ret := multiError(err)
+ return &ret
+}
+
+type multiError []error
+
+// Error implements the error interface.
+func (m *multiError) Error() string {
+ errs := make([]string, len(*m))
+ for i, err := range *m {
+ errs[i] = err.Error()
+ }
+
+ return strings.Join(errs, "\n")
+}
+
+// Errors returns a copy of the errors slice
+func (m *multiError) Errors() []error {
+ errs := make([]error, len(*m))
+ for _, err := range *m {
+ errs = append(errs, err)
+ }
+ return errs
+}
+
+type ErrorFormatter interface {
+ Format(s fmt.State, verb rune)
+}
+
+// ExitCoder is the interface checked by `App` and `Command` for a custom exit
+// code
+type ExitCoder interface {
+ error
+ ExitCode() int
+}
+
+type exitError struct {
+ exitCode int
+ message interface{}
+}
+
+// Exit wraps a message and exit code into an ExitCoder suitable for handling by
+// HandleExitCoder
+func Exit(message interface{}, exitCode int) ExitCoder {
+ return &exitError{
+ exitCode: exitCode,
+ message: message,
+ }
+}
+
+func (ee *exitError) Error() string {
+ return fmt.Sprintf("%v", ee.message)
+}
+
+func (ee *exitError) ExitCode() int {
+ return ee.exitCode
+}
+
+// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
+// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
+// given exit code. If the given error is a MultiError, then this func is
+// called on all members of the Errors slice and calls OsExiter with the last exit code.
+func HandleExitCoder(err error) {
+ if err == nil {
+ return
+ }
+
+ if exitErr, ok := err.(ExitCoder); ok {
+ if err.Error() != "" {
+ if _, ok := exitErr.(ErrorFormatter); ok {
+ fmt.Fprintf(ErrWriter, "%+v\n", err)
+ } else {
+ fmt.Fprintln(ErrWriter, err)
+ }
+ }
+ OsExiter(exitErr.ExitCode())
+ return
+ }
+
+ if multiErr, ok := err.(MultiError); ok {
+ code := handleMultiError(multiErr)
+ OsExiter(code)
+ return
+ }
+}
+
+func handleMultiError(multiErr MultiError) int {
+ code := 1
+ for _, merr := range multiErr.Errors() {
+ if multiErr2, ok := merr.(MultiError); ok {
+ code = handleMultiError(multiErr2)
+ } else if merr != nil {
+ fmt.Fprintln(ErrWriter, merr)
+ if exitErr, ok := merr.(ExitCoder); ok {
+ code = exitErr.ExitCode()
+ }
+ }
+ }
+ return code
+}
diff --git a/vendor/gopkg.in/urfave/cli.v2/flag-types.json b/vendor/gopkg.in/urfave/cli.v2/flag-types.json
new file mode 100644
index 0000000..bd5ec3f
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/flag-types.json
@@ -0,0 +1,98 @@
+[
+ {
+ "name": "Bool",
+ "type": "bool",
+ "context_default": "false",
+ "parser": "strconv.ParseBool(f.Value.String())"
+ },
+ {
+ "name": "Duration",
+ "type": "time.Duration",
+ "doctail": " (see https://golang.org/pkg/time/#ParseDuration)",
+ "context_default": "0",
+ "parser": "time.ParseDuration(f.Value.String())"
+ },
+ {
+ "name": "Float64",
+ "type": "float64",
+ "context_default": "0",
+ "parser": "strconv.ParseFloat(f.Value.String(), 64)"
+ },
+ {
+ "name": "Generic",
+ "type": "Generic",
+ "dest": false,
+ "context_default": "nil",
+ "context_type": "interface{}"
+ },
+ {
+ "name": "Int64",
+ "type": "int64",
+ "context_default": "0",
+ "parser": "strconv.ParseInt(f.Value.String(), 0, 64)"
+ },
+ {
+ "name": "Int",
+ "type": "int",
+ "context_default": "0",
+ "parser": "strconv.ParseInt(f.Value.String(), 0, 64)",
+ "parser_cast": "int(parsed)"
+ },
+ {
+ "name": "IntSlice",
+ "type": "*IntSlice",
+ "dest": false,
+ "context_default": "nil",
+ "context_type": "[]int",
+ "parser": "(f.Value.(*IntSlice)).Value(), error(nil)"
+ },
+ {
+ "name": "Int64Slice",
+ "type": "*Int64Slice",
+ "dest": false,
+ "context_default": "nil",
+ "context_type": "[]int64",
+ "parser": "(f.Value.(*Int64Slice)).Value(), error(nil)"
+ },
+ {
+ "name": "Float64Slice",
+ "type": "*Float64Slice",
+ "dest": false,
+ "context_default": "nil",
+ "context_type": "[]float64",
+ "parser": "(f.Value.(*Float64Slice)).Value(), error(nil)"
+ },
+ {
+ "name": "String",
+ "type": "string",
+ "context_default": "\"\"",
+ "parser": "f.Value.String(), error(nil)"
+ },
+ {
+ "name": "Path",
+ "type": "string",
+ "context_default": "\"\"",
+ "parser": "f.Value.String(), error(nil)"
+ },
+ {
+ "name": "StringSlice",
+ "type": "*StringSlice",
+ "dest": false,
+ "context_default": "nil",
+ "context_type": "[]string",
+ "parser": "(f.Value.(*StringSlice)).Value(), error(nil)"
+ },
+ {
+ "name": "Uint64",
+ "type": "uint64",
+ "context_default": "0",
+ "parser": "strconv.ParseUint(f.Value.String(), 0, 64)"
+ },
+ {
+ "name": "Uint",
+ "type": "uint",
+ "context_default": "0",
+ "parser": "strconv.ParseUint(f.Value.String(), 0, 64)",
+ "parser_cast": "uint(parsed)"
+ }
+]
diff --git a/vendor/gopkg.in/urfave/cli.v2/flag.go b/vendor/gopkg.in/urfave/cli.v2/flag.go
new file mode 100644
index 0000000..364362c
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/flag.go
@@ -0,0 +1,1034 @@
+package cli
+
+import (
+ "encoding/json"
+ "flag"
+ "fmt"
+ "reflect"
+ "regexp"
+ "runtime"
+ "strconv"
+ "strings"
+ "syscall"
+ "time"
+)
+
+const defaultPlaceholder = "value"
+
+var (
+ slPfx = fmt.Sprintf("sl:::%d:::", time.Now().UTC().UnixNano())
+
+ commaWhitespace = regexp.MustCompile("[, ]+.*")
+)
+
+// GenerateCompletionFlag enables completion for all commands and subcommands
+var GenerateCompletionFlag Flag = &BoolFlag{
+ Name: "generate-completion",
+ Hidden: true,
+}
+
+func genCompName() string {
+ names := GenerateCompletionFlag.Names()
+ if len(names) == 0 {
+ return "generate-completion"
+ }
+ return names[0]
+}
+
+// InitCompletionFlag generates completion code
+var InitCompletionFlag = &StringFlag{
+ Name: "init-completion",
+ Usage: "generate completion code. Value must be 'bash' or 'zsh'",
+}
+
+// VersionFlag prints the version for the application
+var VersionFlag Flag = &BoolFlag{
+ Name: "version",
+ Aliases: []string{"v"},
+ Usage: "print the version",
+}
+
+// HelpFlag prints the help for all commands and subcommands.
+// Set to nil to disable the flag. The subcommand
+// will still be added unless HideHelp is set to true.
+var HelpFlag Flag = &BoolFlag{
+ Name: "help",
+ Aliases: []string{"h"},
+ Usage: "show help",
+}
+
+// FlagStringer converts a flag definition to a string. This is used by help
+// to display a flag.
+var FlagStringer FlagStringFunc = stringifyFlag
+
+// Serializeder is used to circumvent the limitations of flag.FlagSet.Set
+type Serializeder interface {
+ Serialized() string
+}
+
+// FlagsByName is a slice of Flag.
+type FlagsByName []Flag
+
+func (f FlagsByName) Len() int {
+ return len(f)
+}
+
+func (f FlagsByName) Less(i, j int) bool {
+ if len(f[j].Names()) == 0 {
+ return false
+ } else if len(f[i].Names()) == 0 {
+ return true
+ }
+ return f[i].Names()[0] < f[j].Names()[0]
+}
+
+func (f FlagsByName) Swap(i, j int) {
+ f[i], f[j] = f[j], f[i]
+}
+
+// Flag is a common interface related to parsing flags in cli.
+// For more advanced flag parsing techniques, it is recommended that
+// this interface be implemented.
+type Flag interface {
+ fmt.Stringer
+ // Apply Flag settings to the given flag set
+ Apply(*flag.FlagSet)
+ Names() []string
+}
+
+// errorableFlag is an interface that allows us to return errors during apply
+// it allows flags defined in this library to return errors in a fashion backwards compatible
+// TODO remove in v2 and modify the existing Flag interface to return errors
+type errorableFlag interface {
+ Flag
+
+ ApplyWithError(*flag.FlagSet) error
+}
+
+func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
+ set := flag.NewFlagSet(name, flag.ContinueOnError)
+
+ for _, f := range flags {
+ //TODO remove in v2 when errorableFlag is removed
+ if ef, ok := f.(errorableFlag); ok {
+ if err := ef.ApplyWithError(set); err != nil {
+ return nil, err
+ }
+ } else {
+ f.Apply(set)
+ }
+ }
+ return set, nil
+}
+
+// Generic is a generic parseable type identified by a specific flag
+type Generic interface {
+ Set(value string) error
+ String() string
+}
+
+// Apply takes the flagset and calls Set on the generic flag with the value
+// provided by the user for parsing by the flag
+// Ignores parsing errors
+func (f *GenericFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError takes the flagset and calls Set on the generic flag with the
+// value provided by the user for parsing by the flag
+func (f *GenericFlag) ApplyWithError(set *flag.FlagSet) error {
+ val := f.Value
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ val.Set(envVal)
+ break
+ }
+ }
+ }
+
+ for _, name := range f.Names() {
+ set.Var(val, name, f.Usage)
+ }
+ return nil
+}
+
+// StringSlice wraps a []string to satisfy flag.Value
+type StringSlice struct {
+ slice []string
+ hasBeenSet bool
+}
+
+// NewStringSlice creates a *StringSlice with default values
+func NewStringSlice(defaults ...string) *StringSlice {
+ return &StringSlice{slice: append([]string{}, defaults...)}
+}
+
+// Set appends the string value to the list of values
+func (f *StringSlice) Set(value string) error {
+ if !f.hasBeenSet {
+ f.slice = []string{}
+ f.hasBeenSet = true
+ }
+
+ if strings.HasPrefix(value, slPfx) {
+ // Deserializing assumes overwrite
+ _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &f.slice)
+ f.hasBeenSet = true
+ return nil
+ }
+
+ f.slice = append(f.slice, value)
+ return nil
+}
+
+// String returns a readable representation of this value (for usage defaults)
+func (f *StringSlice) String() string {
+ return fmt.Sprintf("%s", f.slice)
+}
+
+// Serialized allows StringSlice to fulfill Serializeder
+func (f *StringSlice) Serialized() string {
+ jsonBytes, _ := json.Marshal(f.slice)
+ return fmt.Sprintf("%s%s", slPfx, string(jsonBytes))
+}
+
+// Value returns the slice of strings set by this flag
+func (f *StringSlice) Value() []string {
+ return f.slice
+}
+
+// Get returns the slice of strings set by this flag
+func (f *StringSlice) Get() interface{} {
+ return *f
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *StringSliceFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *StringSliceFlag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ newVal := NewStringSlice()
+ for _, s := range strings.Split(envVal, ",") {
+ s = strings.TrimSpace(s)
+ if err := newVal.Set(s); err != nil {
+ return fmt.Errorf("could not parse %q as string value for flag %s: %s", envVal, f.Name, err)
+ }
+ }
+ f.Value = newVal
+ break
+ }
+ }
+ }
+
+ if f.Value == nil {
+ f.Value = NewStringSlice()
+ }
+
+ for _, name := range f.Names() {
+ set.Var(f.Value, name, f.Usage)
+ }
+ return nil
+}
+
+// IntSlice wraps an []int to satisfy flag.Value
+type IntSlice struct {
+ slice []int
+ hasBeenSet bool
+}
+
+// NewIntSlice makes an *IntSlice with default values
+func NewIntSlice(defaults ...int) *IntSlice {
+ return &IntSlice{slice: append([]int{}, defaults...)}
+}
+
+// NewInt64Slice makes an *Int64Slice with default values
+func NewInt64Slice(defaults ...int64) *Int64Slice {
+ return &Int64Slice{slice: append([]int64{}, defaults...)}
+}
+
+// SetInt directly adds an integer to the list of values
+func (i *IntSlice) SetInt(value int) {
+ if !i.hasBeenSet {
+ i.slice = []int{}
+ i.hasBeenSet = true
+ }
+
+ i.slice = append(i.slice, value)
+}
+
+// Set parses the value into an integer and appends it to the list of values
+func (i *IntSlice) Set(value string) error {
+ if !i.hasBeenSet {
+ i.slice = []int{}
+ i.hasBeenSet = true
+ }
+
+ if strings.HasPrefix(value, slPfx) {
+ // Deserializing assumes overwrite
+ _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice)
+ i.hasBeenSet = true
+ return nil
+ }
+
+ tmp, err := strconv.ParseInt(value, 0, 64)
+ if err != nil {
+ return err
+ }
+
+ i.slice = append(i.slice, int(tmp))
+ return nil
+}
+
+// String returns a readable representation of this value (for usage defaults)
+func (f *IntSlice) String() string {
+ return fmt.Sprintf("%#v", f.slice)
+}
+
+// Serialized allows IntSlice to fulfill Serializeder
+func (i *IntSlice) Serialized() string {
+ jsonBytes, _ := json.Marshal(i.slice)
+ return fmt.Sprintf("%s%s", slPfx, string(jsonBytes))
+}
+
+// Value returns the slice of ints set by this flag
+func (i *IntSlice) Value() []int {
+ return i.slice
+}
+
+// Get returns the slice of ints set by this flag
+func (f *IntSlice) Get() interface{} {
+ return *f
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *IntSliceFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *IntSliceFlag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ newVal := NewIntSlice()
+ for _, s := range strings.Split(envVal, ",") {
+ s = strings.TrimSpace(s)
+ if err := newVal.Set(s); err != nil {
+ return fmt.Errorf("could not parse %q as int slice value for flag %s: %s", envVal, f.Name, err)
+ }
+ }
+ f.Value = newVal
+ break
+ }
+ }
+ }
+
+ if f.Value == nil {
+ f.Value = NewIntSlice()
+ }
+
+ for _, name := range f.Names() {
+ set.Var(f.Value, name, f.Usage)
+ }
+ return nil
+}
+
+// Int64Slice is an opaque type for []int to satisfy flag.Value
+type Int64Slice struct {
+ slice []int64
+ hasBeenSet bool
+}
+
+// Set parses the value into an integer and appends it to the list of values
+func (f *Int64Slice) Set(value string) error {
+ if !f.hasBeenSet {
+ f.slice = []int64{}
+ f.hasBeenSet = true
+ }
+
+ if strings.HasPrefix(value, slPfx) {
+ // Deserializing assumes overwrite
+ _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &f.slice)
+ f.hasBeenSet = true
+ return nil
+ }
+
+ tmp, err := strconv.ParseInt(value, 0, 64)
+ if err != nil {
+ return err
+ }
+
+ f.slice = append(f.slice, tmp)
+ return nil
+}
+
+// String returns a readable representation of this value (for usage defaults)
+func (f *Int64Slice) String() string {
+ return fmt.Sprintf("%#v", f.slice)
+}
+
+// Serialized allows Int64Slice to fulfill Serializeder
+func (f *Int64Slice) Serialized() string {
+ jsonBytes, _ := json.Marshal(f.slice)
+ return fmt.Sprintf("%s%s", slPfx, string(jsonBytes))
+}
+
+// Value returns the slice of ints set by this flag
+func (f *Int64Slice) Value() []int64 {
+ return f.slice
+}
+
+// Get returns the slice of ints set by this flag
+func (f *Int64Slice) Get() interface{} {
+ return *f
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *Int64SliceFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ newVal := NewInt64Slice()
+ for _, s := range strings.Split(envVal, ",") {
+ s = strings.TrimSpace(s)
+ if err := newVal.Set(s); err != nil {
+ return fmt.Errorf("could not parse %q as int64 slice value for flag %s: %s", envVal, f.Name, err)
+ }
+ }
+ f.Value = newVal
+ break
+ }
+ }
+ }
+
+ if f.Value == nil {
+ f.Value = NewInt64Slice()
+ }
+
+ for _, name := range f.Names() {
+ set.Var(f.Value, name, f.Usage)
+ }
+ return nil
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *BoolFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *BoolFlag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ if envVal == "" {
+ f.Value = false
+ break
+ }
+
+ envValBool, err := strconv.ParseBool(envVal)
+ if err != nil {
+ return fmt.Errorf("could not parse %q as bool value for flag %s: %s", envVal, f.Name, err)
+ }
+ f.Value = envValBool
+ break
+ }
+ }
+ }
+
+ for _, name := range f.Names() {
+ if f.Destination != nil {
+ set.BoolVar(f.Destination, name, f.Value, f.Usage)
+ continue
+ }
+ set.Bool(name, f.Value, f.Usage)
+ }
+ return nil
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *StringFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *StringFlag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ f.Value = envVal
+ break
+ }
+ }
+ }
+
+ for _, name := range f.Names() {
+ if f.Destination != nil {
+ set.StringVar(f.Destination, name, f.Value, f.Usage)
+ continue
+ }
+ set.String(name, f.Value, f.Usage)
+ }
+ return nil
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *PathFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *PathFlag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ f.Value = envVal
+ break
+ }
+ }
+ }
+
+ for _, name := range f.Names() {
+ if f.Destination != nil {
+ set.StringVar(f.Destination, name, f.Value, f.Usage)
+ continue
+ }
+ set.String(name, f.Value, f.Usage)
+ }
+ return nil
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *IntFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *IntFlag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ envValInt, err := strconv.ParseInt(envVal, 0, 64)
+ if err != nil {
+ return fmt.Errorf("could not parse %q as int value for flag %s: %s", envVal, f.Name, err)
+ }
+ f.Value = int(envValInt)
+ break
+ }
+ }
+ }
+
+ for _, name := range f.Names() {
+ if f.Destination != nil {
+ set.IntVar(f.Destination, name, f.Value, f.Usage)
+ continue
+ }
+ set.Int(name, f.Value, f.Usage)
+ }
+ return nil
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *Int64Flag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *Int64Flag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ envValInt, err := strconv.ParseInt(envVal, 0, 64)
+ if err != nil {
+ return fmt.Errorf("could not parse %q as int value for flag %s: %s", envVal, f.Name, err)
+ }
+
+ f.Value = envValInt
+ break
+ }
+ }
+ }
+
+ for _, name := range f.Names() {
+ if f.Destination != nil {
+ set.Int64Var(f.Destination, name, f.Value, f.Usage)
+ return nil
+ }
+ set.Int64(name, f.Value, f.Usage)
+ }
+ return nil
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *UintFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *UintFlag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ envValInt, err := strconv.ParseUint(envVal, 0, 64)
+ if err != nil {
+ return fmt.Errorf("could not parse %q as uint value for flag %s: %s", envVal, f.Name, err)
+ }
+
+ f.Value = uint(envValInt)
+ break
+ }
+ }
+ }
+
+ for _, name := range f.Names() {
+ if f.Destination != nil {
+ set.UintVar(f.Destination, name, f.Value, f.Usage)
+ return nil
+ }
+ set.Uint(name, f.Value, f.Usage)
+ }
+ return nil
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *Uint64Flag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *Uint64Flag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ envValInt, err := strconv.ParseUint(envVal, 0, 64)
+ if err != nil {
+ return fmt.Errorf("could not parse %q as uint64 value for flag %s: %s", envVal, f.Name, err)
+ }
+
+ f.Value = uint64(envValInt)
+ break
+ }
+ }
+ }
+
+ for _, name := range f.Names() {
+ if f.Destination != nil {
+ set.Uint64Var(f.Destination, name, f.Value, f.Usage)
+ return nil
+ }
+ set.Uint64(name, f.Value, f.Usage)
+ }
+ return nil
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *DurationFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *DurationFlag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ envValDuration, err := time.ParseDuration(envVal)
+ if err != nil {
+ return fmt.Errorf("could not parse %q as duration for flag %s: %s", envVal, f.Name, err)
+ }
+
+ f.Value = envValDuration
+ break
+ }
+ }
+ }
+
+ for _, name := range f.Names() {
+ if f.Destination != nil {
+ set.DurationVar(f.Destination, name, f.Value, f.Usage)
+ continue
+ }
+ set.Duration(name, f.Value, f.Usage)
+ }
+ return nil
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *Float64Flag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *Float64Flag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ envValFloat, err := strconv.ParseFloat(envVal, 10)
+ if err != nil {
+ return fmt.Errorf("could not parse %q as float64 value for flag %s: %s", envVal, f.Name, err)
+ }
+
+ f.Value = float64(envValFloat)
+ break
+ }
+ }
+ }
+
+ for _, name := range f.Names() {
+ if f.Destination != nil {
+ set.Float64Var(f.Destination, name, f.Value, f.Usage)
+ continue
+ }
+ set.Float64(name, f.Value, f.Usage)
+ }
+ return nil
+}
+
+// NewFloat64Slice makes a *Float64Slice with default values
+func NewFloat64Slice(defaults ...float64) *Float64Slice {
+ return &Float64Slice{slice: append([]float64{}, defaults...)}
+}
+
+// Float64Slice is an opaque type for []float64 to satisfy flag.Value
+type Float64Slice struct {
+ slice []float64
+ hasBeenSet bool
+}
+
+// Set parses the value into a float64 and appends it to the list of values
+func (f *Float64Slice) Set(value string) error {
+ if !f.hasBeenSet {
+ f.slice = []float64{}
+ f.hasBeenSet = true
+ }
+
+ if strings.HasPrefix(value, slPfx) {
+ // Deserializing assumes overwrite
+ _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &f.slice)
+ f.hasBeenSet = true
+ return nil
+ }
+
+ tmp, err := strconv.ParseFloat(value, 64)
+ if err != nil {
+ return err
+ }
+
+ f.slice = append(f.slice, tmp)
+ return nil
+}
+
+// String returns a readable representation of this value (for usage defaults)
+func (f *Float64Slice) String() string {
+ return fmt.Sprintf("%#v", f.slice)
+}
+
+// Serialized allows Float64Slice to fulfill Serializeder
+func (f *Float64Slice) Serialized() string {
+ jsonBytes, _ := json.Marshal(f.slice)
+ return fmt.Sprintf("%s%s", slPfx, string(jsonBytes))
+}
+
+// Value returns the slice of float64s set by this flag
+func (f *Float64Slice) Value() []float64 {
+ return f.slice
+}
+
+// Apply populates the flag given the flag set and environment
+// Ignores errors
+func (f *Float64SliceFlag) Apply(set *flag.FlagSet) {
+ f.ApplyWithError(set)
+}
+
+// ApplyWithError populates the flag given the flag set and environment
+func (f *Float64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
+ if f.EnvVars != nil {
+ for _, envVar := range f.EnvVars {
+ if envVal, ok := syscall.Getenv(envVar); ok {
+ newVal := NewFloat64Slice()
+ for _, s := range strings.Split(envVal, ",") {
+ s = strings.TrimSpace(s)
+ err := newVal.Set(s)
+ if err != nil {
+ fmt.Fprintf(ErrWriter, err.Error())
+ }
+ }
+ f.Value = newVal
+ break
+ }
+ }
+ }
+
+ if f.Value == nil {
+ f.Value = NewFloat64Slice()
+ }
+
+ for _, name := range f.Names() {
+ set.Var(f.Value, name, f.Usage)
+ }
+ return nil
+}
+
+func visibleFlags(fl []Flag) []Flag {
+ visible := []Flag{}
+ for _, flag := range fl {
+ field := flagValue(flag).FieldByName("Hidden")
+ if !field.IsValid() || !field.Bool() {
+ visible = append(visible, flag)
+ }
+ }
+ return visible
+}
+
+func prefixFor(name string) (prefix string) {
+ if len(name) == 1 {
+ prefix = "-"
+ } else {
+ prefix = "--"
+ }
+
+ return
+}
+
+// Returns the placeholder, if any, and the unquoted usage string.
+func unquoteUsage(usage string) (string, string) {
+ for i := 0; i < len(usage); i++ {
+ if usage[i] == '`' {
+ for j := i + 1; j < len(usage); j++ {
+ if usage[j] == '`' {
+ name := usage[i+1 : j]
+ usage = usage[:i] + name + usage[j+1:]
+ return name, usage
+ }
+ }
+ break
+ }
+ }
+ return "", usage
+}
+
+func prefixedNames(names []string, placeholder string) string {
+ var prefixed string
+ for i, name := range names {
+ if name == "" {
+ continue
+ }
+
+ prefixed += prefixFor(name) + name
+ if placeholder != "" {
+ prefixed += " " + placeholder
+ }
+ if i < len(names)-1 {
+ prefixed += ", "
+ }
+ }
+ return prefixed
+}
+
+func withEnvHint(envVars []string, str string) string {
+ envText := ""
+ if envVars != nil && len(envVars) > 0 {
+ prefix := "$"
+ suffix := ""
+ sep := ", $"
+ if runtime.GOOS == "windows" {
+ prefix = "%"
+ suffix = "%"
+ sep = "%, %"
+ }
+ envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(envVars, sep), suffix)
+ }
+ return str + envText
+}
+
+func flagNames(f Flag) []string {
+ ret := []string{}
+
+ name := flagStringField(f, "Name")
+ aliases := flagStringSliceField(f, "Aliases")
+
+ for _, part := range append([]string{name}, aliases...) {
+ // v1 -> v2 migration warning zone:
+ // Strip off anything after the first found comma or space, which
+ // *hopefully* makes it a tiny bit more obvious that unexpected behavior is
+ // caused by using the v1 form of stringly typed "Name".
+ ret = append(ret, commaWhitespace.ReplaceAllString(part, ""))
+ }
+
+ return ret
+}
+
+func flagStringSliceField(f Flag, name string) []string {
+ fv := flagValue(f)
+ field := fv.FieldByName(name)
+
+ if field.IsValid() {
+ return field.Interface().([]string)
+ }
+
+ return []string{}
+}
+
+func flagStringField(f Flag, name string) string {
+ fv := flagValue(f)
+ field := fv.FieldByName(name)
+
+ if field.IsValid() {
+ return field.String()
+ }
+
+ return ""
+}
+
+func flagValue(f Flag) reflect.Value {
+ fv := reflect.ValueOf(f)
+ for fv.Kind() == reflect.Ptr {
+ fv = reflect.Indirect(fv)
+ }
+ return fv
+}
+
+func stringifyFlag(f Flag) string {
+ fv := flagValue(f)
+
+ switch f.(type) {
+ case *IntSliceFlag:
+ return withEnvHint(flagStringSliceField(f, "EnvVars"),
+ stringifyIntSliceFlag(f.(*IntSliceFlag)))
+ case *Int64SliceFlag:
+ return withEnvHint(flagStringSliceField(f, "EnvVars"),
+ stringifyInt64SliceFlag(f.(*Int64SliceFlag)))
+ case *Float64SliceFlag:
+ return withEnvHint(flagStringSliceField(f, "EnvVars"),
+ stringifyFloat64SliceFlag(f.(*Float64SliceFlag)))
+ case *StringSliceFlag:
+ return withEnvHint(flagStringSliceField(f, "EnvVars"),
+ stringifyStringSliceFlag(f.(*StringSliceFlag)))
+ }
+
+ placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())
+
+ needsPlaceholder := false
+ defaultValueString := ""
+ val := fv.FieldByName("Value")
+ if val.IsValid() {
+ needsPlaceholder = val.Kind() != reflect.Bool
+ defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
+
+ if val.Kind() == reflect.String && val.String() != "" {
+ defaultValueString = fmt.Sprintf(" (default: %q)", val.String())
+ }
+ }
+
+ helpText := fv.FieldByName("DefaultText")
+ if helpText.IsValid() && helpText.String() != "" {
+ needsPlaceholder = val.Kind() != reflect.Bool
+ defaultValueString = fmt.Sprintf(" (default: %s)", helpText.String())
+ }
+
+ if defaultValueString == " (default: )" {
+ defaultValueString = ""
+ }
+
+ if needsPlaceholder && placeholder == "" {
+ placeholder = defaultPlaceholder
+ }
+
+ usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString))
+
+ return withEnvHint(flagStringSliceField(f, "EnvVars"),
+ fmt.Sprintf("%s\t%s", prefixedNames(f.Names(), placeholder), usageWithDefault))
+}
+
+func stringifyIntSliceFlag(f *IntSliceFlag) string {
+ defaultVals := []string{}
+ if f.Value != nil && len(f.Value.Value()) > 0 {
+ for _, i := range f.Value.Value() {
+ defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
+ }
+ }
+
+ return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
+}
+
+func stringifyInt64SliceFlag(f *Int64SliceFlag) string {
+ defaultVals := []string{}
+ if f.Value != nil && len(f.Value.Value()) > 0 {
+ for _, i := range f.Value.Value() {
+ defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
+ }
+ }
+
+ return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
+}
+
+func stringifyFloat64SliceFlag(f *Float64SliceFlag) string {
+ defaultVals := []string{}
+ if f.Value != nil && len(f.Value.Value()) > 0 {
+ for _, i := range f.Value.Value() {
+ defaultVals = append(defaultVals, strings.TrimRight(strings.TrimRight(fmt.Sprintf("%f", i), "0"), "."))
+ }
+ }
+
+ return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
+}
+
+func stringifyStringSliceFlag(f *StringSliceFlag) string {
+ defaultVals := []string{}
+ if f.Value != nil && len(f.Value.Value()) > 0 {
+ for _, s := range f.Value.Value() {
+ if len(s) > 0 {
+ defaultVals = append(defaultVals, fmt.Sprintf("%q", s))
+ }
+ }
+ }
+
+ return stringifySliceFlag(f.Usage, f.Names(), defaultVals)
+}
+
+func stringifySliceFlag(usage string, names, defaultVals []string) string {
+ placeholder, usage := unquoteUsage(usage)
+ if placeholder == "" {
+ placeholder = defaultPlaceholder
+ }
+
+ defaultVal := ""
+ if len(defaultVals) > 0 {
+ defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", "))
+ }
+
+ usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal))
+ return fmt.Sprintf("%s\t%s", prefixedNames(names, placeholder), usageWithDefault)
+}
+
+func hasFlag(flags []Flag, fl Flag) bool {
+ for _, existing := range flags {
+ if fl == existing {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/vendor/gopkg.in/urfave/cli.v2/flag_generated.go b/vendor/gopkg.in/urfave/cli.v2/flag_generated.go
new file mode 100644
index 0000000..a958150
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/flag_generated.go
@@ -0,0 +1,629 @@
+package cli
+
+import (
+ "flag"
+ "strconv"
+ "time"
+)
+
+// WARNING: This file is generated!
+
+// BoolFlag is a flag with type bool
+type BoolFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value bool
+ DefaultText string
+
+ Destination *bool
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *BoolFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *BoolFlag) Names() []string {
+ return flagNames(f)
+}
+
+// Bool looks up the value of a local BoolFlag, returns
+// false if not found
+func (c *Context) Bool(name string) bool {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupBool(name, fs)
+ }
+ return false
+}
+
+func lookupBool(name string, set *flag.FlagSet) bool {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := strconv.ParseBool(f.Value.String())
+ if err != nil {
+ return false
+ }
+ return parsed
+ }
+ return false
+}
+
+// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration)
+type DurationFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value time.Duration
+ DefaultText string
+
+ Destination *time.Duration
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *DurationFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *DurationFlag) Names() []string {
+ return flagNames(f)
+}
+
+// Duration looks up the value of a local DurationFlag, returns
+// 0 if not found
+func (c *Context) Duration(name string) time.Duration {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupDuration(name, fs)
+ }
+ return 0
+}
+
+func lookupDuration(name string, set *flag.FlagSet) time.Duration {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := time.ParseDuration(f.Value.String())
+ if err != nil {
+ return 0
+ }
+ return parsed
+ }
+ return 0
+}
+
+// Float64Flag is a flag with type float64
+type Float64Flag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value float64
+ DefaultText string
+
+ Destination *float64
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *Float64Flag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *Float64Flag) Names() []string {
+ return flagNames(f)
+}
+
+// Float64 looks up the value of a local Float64Flag, returns
+// 0 if not found
+func (c *Context) Float64(name string) float64 {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupFloat64(name, fs)
+ }
+ return 0
+}
+
+func lookupFloat64(name string, set *flag.FlagSet) float64 {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := strconv.ParseFloat(f.Value.String(), 64)
+ if err != nil {
+ return 0
+ }
+ return parsed
+ }
+ return 0
+}
+
+// GenericFlag is a flag with type Generic
+type GenericFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value Generic
+ DefaultText string
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *GenericFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *GenericFlag) Names() []string {
+ return flagNames(f)
+}
+
+// Generic looks up the value of a local GenericFlag, returns
+// nil if not found
+func (c *Context) Generic(name string) interface{} {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupGeneric(name, fs)
+ }
+ return nil
+}
+
+func lookupGeneric(name string, set *flag.FlagSet) interface{} {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := f.Value, error(nil)
+ if err != nil {
+ return nil
+ }
+ return parsed
+ }
+ return nil
+}
+
+// Int64Flag is a flag with type int64
+type Int64Flag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value int64
+ DefaultText string
+
+ Destination *int64
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *Int64Flag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *Int64Flag) Names() []string {
+ return flagNames(f)
+}
+
+// Int64 looks up the value of a local Int64Flag, returns
+// 0 if not found
+func (c *Context) Int64(name string) int64 {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupInt64(name, fs)
+ }
+ return 0
+}
+
+func lookupInt64(name string, set *flag.FlagSet) int64 {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
+ if err != nil {
+ return 0
+ }
+ return parsed
+ }
+ return 0
+}
+
+// IntFlag is a flag with type int
+type IntFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value int
+ DefaultText string
+
+ Destination *int
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *IntFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *IntFlag) Names() []string {
+ return flagNames(f)
+}
+
+// Int looks up the value of a local IntFlag, returns
+// 0 if not found
+func (c *Context) Int(name string) int {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupInt(name, fs)
+ }
+ return 0
+}
+
+func lookupInt(name string, set *flag.FlagSet) int {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
+ if err != nil {
+ return 0
+ }
+ return int(parsed)
+ }
+ return 0
+}
+
+// IntSliceFlag is a flag with type *IntSlice
+type IntSliceFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value *IntSlice
+ DefaultText string
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *IntSliceFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *IntSliceFlag) Names() []string {
+ return flagNames(f)
+}
+
+// IntSlice looks up the value of a local IntSliceFlag, returns
+// nil if not found
+func (c *Context) IntSlice(name string) []int {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupIntSlice(name, fs)
+ }
+ return nil
+}
+
+func lookupIntSlice(name string, set *flag.FlagSet) []int {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := (f.Value.(*IntSlice)).Value(), error(nil)
+ if err != nil {
+ return nil
+ }
+ return parsed
+ }
+ return nil
+}
+
+// Int64SliceFlag is a flag with type *Int64Slice
+type Int64SliceFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value *Int64Slice
+ DefaultText string
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *Int64SliceFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *Int64SliceFlag) Names() []string {
+ return flagNames(f)
+}
+
+// Int64Slice looks up the value of a local Int64SliceFlag, returns
+// nil if not found
+func (c *Context) Int64Slice(name string) []int64 {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupInt64Slice(name, fs)
+ }
+ return nil
+}
+
+func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil)
+ if err != nil {
+ return nil
+ }
+ return parsed
+ }
+ return nil
+}
+
+// Float64SliceFlag is a flag with type *Float64Slice
+type Float64SliceFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value *Float64Slice
+ DefaultText string
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *Float64SliceFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *Float64SliceFlag) Names() []string {
+ return flagNames(f)
+}
+
+// Float64Slice looks up the value of a local Float64SliceFlag, returns
+// nil if not found
+func (c *Context) Float64Slice(name string) []float64 {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupFloat64Slice(name, fs)
+ }
+ return nil
+}
+
+func lookupFloat64Slice(name string, set *flag.FlagSet) []float64 {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := (f.Value.(*Float64Slice)).Value(), error(nil)
+ if err != nil {
+ return nil
+ }
+ return parsed
+ }
+ return nil
+}
+
+// StringFlag is a flag with type string
+type StringFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value string
+ DefaultText string
+
+ Destination *string
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *StringFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *StringFlag) Names() []string {
+ return flagNames(f)
+}
+
+// String looks up the value of a local StringFlag, returns
+// "" if not found
+func (c *Context) String(name string) string {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupString(name, fs)
+ }
+ return ""
+}
+
+func lookupString(name string, set *flag.FlagSet) string {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := f.Value.String(), error(nil)
+ if err != nil {
+ return ""
+ }
+ return parsed
+ }
+ return ""
+}
+
+// PathFlag is a flag with type string
+type PathFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value string
+ DefaultText string
+
+ Destination *string
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *PathFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *PathFlag) Names() []string {
+ return flagNames(f)
+}
+
+// Path looks up the value of a local PathFlag, returns
+// "" if not found
+func (c *Context) Path(name string) string {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupPath(name, fs)
+ }
+ return ""
+}
+
+func lookupPath(name string, set *flag.FlagSet) string {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := f.Value.String(), error(nil)
+ if err != nil {
+ return ""
+ }
+ return parsed
+ }
+ return ""
+}
+
+// StringSliceFlag is a flag with type *StringSlice
+type StringSliceFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value *StringSlice
+ DefaultText string
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *StringSliceFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *StringSliceFlag) Names() []string {
+ return flagNames(f)
+}
+
+// StringSlice looks up the value of a local StringSliceFlag, returns
+// nil if not found
+func (c *Context) StringSlice(name string) []string {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupStringSlice(name, fs)
+ }
+ return nil
+}
+
+func lookupStringSlice(name string, set *flag.FlagSet) []string {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := (f.Value.(*StringSlice)).Value(), error(nil)
+ if err != nil {
+ return nil
+ }
+ return parsed
+ }
+ return nil
+}
+
+// Uint64Flag is a flag with type uint64
+type Uint64Flag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value uint64
+ DefaultText string
+
+ Destination *uint64
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *Uint64Flag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *Uint64Flag) Names() []string {
+ return flagNames(f)
+}
+
+// Uint64 looks up the value of a local Uint64Flag, returns
+// 0 if not found
+func (c *Context) Uint64(name string) uint64 {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupUint64(name, fs)
+ }
+ return 0
+}
+
+func lookupUint64(name string, set *flag.FlagSet) uint64 {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
+ if err != nil {
+ return 0
+ }
+ return parsed
+ }
+ return 0
+}
+
+// UintFlag is a flag with type uint
+type UintFlag struct {
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value uint
+ DefaultText string
+
+ Destination *uint
+}
+
+// String returns a readable representation of this value
+// (for usage defaults)
+func (f *UintFlag) String() string {
+ return FlagStringer(f)
+}
+
+// Names returns the names of the flag
+func (f *UintFlag) Names() []string {
+ return flagNames(f)
+}
+
+// Uint looks up the value of a local UintFlag, returns
+// 0 if not found
+func (c *Context) Uint(name string) uint {
+ if fs := lookupFlagSet(name, c); fs != nil {
+ return lookupUint(name, fs)
+ }
+ return 0
+}
+
+func lookupUint(name string, set *flag.FlagSet) uint {
+ f := set.Lookup(name)
+ if f != nil {
+ parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
+ if err != nil {
+ return 0
+ }
+ return uint(parsed)
+ }
+ return 0
+}
diff --git a/vendor/gopkg.in/urfave/cli.v2/funcs.go b/vendor/gopkg.in/urfave/cli.v2/funcs.go
new file mode 100644
index 0000000..fa7d502
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/funcs.go
@@ -0,0 +1,28 @@
+package cli
+
+// ShellCompleteFunc is an action to execute when the shell completion flag is set
+type ShellCompleteFunc func(*Context)
+
+// BeforeFunc is an action to execute before any subcommands are run, but after
+// the context is ready if a non-nil error is returned, no subcommands are run
+type BeforeFunc func(*Context) error
+
+// AfterFunc is an action to execute after any subcommands are run, but after the
+// subcommand has finished it is run even if Action() panics
+type AfterFunc func(*Context) error
+
+// ActionFunc is the action to execute when no subcommands are specified
+type ActionFunc func(*Context) error
+
+// CommandNotFoundFunc is executed if the proper command cannot be found
+type CommandNotFoundFunc func(*Context, string)
+
+// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying
+// customized usage error messages. This function is able to replace the
+// original error messages. If this function is not set, the "Incorrect usage"
+// is displayed and the execution is interrupted.
+type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error
+
+// FlagStringFunc is used by the help generation to display a flag, which is
+// expected to be a single line.
+type FlagStringFunc func(Flag) string
diff --git a/vendor/gopkg.in/urfave/cli.v2/generate-flag-types b/vendor/gopkg.in/urfave/cli.v2/generate-flag-types
new file mode 100644
index 0000000..d77d470
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/generate-flag-types
@@ -0,0 +1,255 @@
+#!/usr/bin/env python
+"""
+The flag types that ship with the cli library have many things in common, and
+so we can take advantage of the `go generate` command to create much of the
+source code from a list of definitions. These definitions attempt to cover
+the parts that vary between flag types, and should evolve as needed.
+
+An example of the minimum definition needed is:
+
+ {
+ "name": "SomeType",
+ "type": "sometype",
+ "context_default": "nil"
+ }
+
+In this example, the code generated for the `cli` package will include a type
+named `SomeTypeFlag` that is expected to wrap a value of type `sometype`.
+Fetching values by name via `*cli.Context` will default to a value of `nil`.
+
+A more complete, albeit somewhat redundant, example showing all available
+definition keys is:
+
+ {
+ "name": "VeryMuchType",
+ "type": "*VeryMuchType",
+ "value": true,
+ "dest": false,
+ "doctail": " which really only wraps a []float64, oh well!",
+ "context_type": "[]float64",
+ "context_default": "nil",
+ "parser": "parseVeryMuchType(f.Value.String())",
+ "parser_cast": "[]float64(parsed)"
+ }
+
+The meaning of each field is as follows:
+
+ name (string) - The type "name", which will be suffixed with
+ `Flag` when generating the type definition
+ for `cli` and the wrapper type for `altsrc`
+ type (string) - The type that the generated `Flag` type for
+ `cli` is expected to "contain" as its `.Value`
+ member
+ value (bool) - Should the generated `cli` type have a `Value`
+ member?
+ dest (bool) - Should the generated `cli` type support a
+ destination pointer?
+ doctail (string) - Additional docs for the `cli` flag type comment
+ context_type (string) - The literal type used in the `*cli.Context`
+ reader func signature
+ context_default (string) - The literal value used as the default by the
+ `*cli.Context` reader funcs when no value is
+ present
+ parser (string) - Literal code used to parse the flag `f`,
+ expected to have a return signature of
+ (value, error)
+ parser_cast (string) - Literal code used to cast the `parsed` value
+ returned from the `parser` code
+"""
+
+from __future__ import print_function, unicode_literals
+
+import argparse
+import json
+import os
+import subprocess
+import sys
+import tempfile
+import textwrap
+
+
+_PY3 = sys.version_info.major == 3
+
+
+class _FancyFormatter(argparse.ArgumentDefaultsHelpFormatter,
+ argparse.RawDescriptionHelpFormatter):
+ pass
+
+
+def main(sysargs=sys.argv[:]):
+ parser = argparse.ArgumentParser(
+ description='Generate flag type code!',
+ formatter_class=_FancyFormatter)
+ parser.add_argument(
+ 'package',
+ type=str, default='cli', choices=_WRITEFUNCS.keys(),
+ help='Package for which flag types will be generated'
+ )
+ parser.add_argument(
+ '-i', '--in-json',
+ type=argparse.FileType('r'),
+ default=sys.stdin,
+ help='Input JSON file which defines each type to be generated'
+ )
+ parser.add_argument(
+ '-o', '--out-go',
+ type=argparse.FileType('w'),
+ default=sys.stdout,
+ help='Output file/stream to which generated source will be written'
+ )
+ parser.epilog = __doc__
+
+ args = parser.parse_args(sysargs[1:])
+ _generate_flag_types(_WRITEFUNCS[args.package], args.out_go, args.in_json)
+ return 0
+
+
+def _generate_flag_types(writefunc, output_go, input_json):
+ types = json.load(input_json)
+
+ tmp = _get_named_tmp_go()
+ writefunc(tmp, types)
+ tmp.close()
+
+ new_content = subprocess.check_output(
+ ['goimports', tmp.name]
+ ).decode('utf-8')
+
+ print(new_content, file=output_go, end='')
+ output_go.flush()
+ os.remove(tmp.name)
+
+
+def _get_named_tmp_go():
+ tmp_args = dict(suffix='.go', mode='w', delete=False)
+ if _PY3:
+ tmp_args['encoding'] = 'utf-8'
+ return tempfile.NamedTemporaryFile(**tmp_args)
+
+
+def _set_typedef_defaults(typedef):
+ typedef.setdefault('doctail', '')
+ typedef.setdefault('context_type', typedef['type'])
+ typedef.setdefault('dest', True)
+ typedef.setdefault('parser', 'f.Value, error(nil)')
+ typedef.setdefault('parser_cast', 'parsed')
+
+
+def _write_cli_flag_types(outfile, types):
+ _fwrite(outfile, """\
+ package cli
+
+ // WARNING: This file is generated!
+
+ """)
+
+ for typedef in types:
+ _set_typedef_defaults(typedef)
+
+ _fwrite(outfile, """\
+ // {name}Flag is a flag with type {type}{doctail}
+ type {name}Flag struct {{
+ Name string
+ Aliases []string
+ Usage string
+ EnvVars []string
+ Hidden bool
+ Value {type}
+ DefaultText string
+ """.format(**typedef))
+
+ if typedef['dest']:
+ _fwrite(outfile, """\
+ Destination *{type}
+ """.format(**typedef))
+
+ _fwrite(outfile, "\n}\n\n")
+
+ _fwrite(outfile, """\
+ // String returns a readable representation of this value
+ // (for usage defaults)
+ func (f *{name}Flag) String() string {{
+ return FlagStringer(f)
+ }}
+
+ // Names returns the names of the flag
+ func (f *{name}Flag) Names() []string {{
+ return flagNames(f)
+ }}
+
+ // {name} looks up the value of a local {name}Flag, returns
+ // {context_default} if not found
+ func (c *Context) {name}(name string) {context_type} {{
+ if fs := lookupFlagSet(name, c); fs != nil {{
+ return lookup{name}(name, fs)
+ }}
+ return {context_default}
+ }}
+
+ func lookup{name}(name string, set *flag.FlagSet) {context_type} {{
+ f := set.Lookup(name)
+ if f != nil {{
+ parsed, err := {parser}
+ if err != nil {{
+ return {context_default}
+ }}
+ return {parser_cast}
+ }}
+ return {context_default}
+ }}
+ """.format(**typedef))
+
+
+def _write_altsrc_flag_types(outfile, types):
+ _fwrite(outfile, """\
+ package altsrc
+
+ import "gopkg.in/urfave/cli.v2"
+
+ // WARNING: This file is generated!
+
+ """)
+
+ for typedef in types:
+ _set_typedef_defaults(typedef)
+
+ _fwrite(outfile, """\
+ // {name}Flag is the flag type that wraps cli.{name}Flag to allow
+ // for other values to be specified
+ type {name}Flag struct {{
+ *cli.{name}Flag
+ set *flag.FlagSet
+ }}
+
+ // New{name}Flag creates a new {name}Flag
+ func New{name}Flag(fl *cli.{name}Flag) *{name}Flag {{
+ return &{name}Flag{{{name}Flag: fl, set: nil}}
+ }}
+
+ // Apply saves the flagSet for later usage calls, then calls the
+ // wrapped {name}Flag.Apply
+ func (f *{name}Flag) Apply(set *flag.FlagSet) {{
+ f.set = set
+ f.{name}Flag.Apply(set)
+ }}
+
+ // ApplyWithError saves the flagSet for later usage calls, then calls the
+ // wrapped {name}Flag.ApplyWithError
+ func (f *{name}Flag) ApplyWithError(set *flag.FlagSet) error {{
+ f.set = set
+ return f.{name}Flag.ApplyWithError(set)
+ }}
+ """.format(**typedef))
+
+
+def _fwrite(outfile, text):
+ print(textwrap.dedent(text), end=None, file=outfile)
+
+
+_WRITEFUNCS = {
+ 'cli': _write_cli_flag_types,
+ 'altsrc': _write_altsrc_flag_types
+}
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/vendor/gopkg.in/urfave/cli.v2/help.go b/vendor/gopkg.in/urfave/cli.v2/help.go
new file mode 100644
index 0000000..02fcf33
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/help.go
@@ -0,0 +1,382 @@
+package cli
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "strings"
+ "text/tabwriter"
+ "text/template"
+)
+
+// AppHelpTemplate is the text template for the Default help topic.
+// cli.go uses text/template to render templates. You can
+// render custom help text by setting this variable.
+var AppHelpTemplate = `NAME:
+ {{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
+
+USAGE:
+ {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
+
+VERSION:
+ {{.Version}}{{end}}{{end}}{{if .Description}}
+
+DESCRIPTION:
+ {{.Description}}{{end}}{{if len .Authors}}
+
+AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
+ {{range $index, $author := .Authors}}{{if $index}}
+ {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
+
+COMMANDS:{{range .VisibleCategories}}{{if .Name}}
+ {{.Name}}:{{end}}{{range .VisibleCommands}}
+ {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
+
+GLOBAL OPTIONS:
+ {{range $index, $option := .VisibleFlags}}{{if $index}}
+ {{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
+
+COPYRIGHT:
+ {{.Copyright}}{{end}}
+`
+
+// CommandHelpTemplate is the text template for the command help topic.
+// cli.go uses text/template to render templates. You can
+// render custom help text by setting this variable.
+var CommandHelpTemplate = `NAME:
+ {{.HelpName}} - {{.Usage}}
+
+USAGE:
+ {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}}
+
+CATEGORY:
+ {{.Category}}{{end}}{{if .Description}}
+
+DESCRIPTION:
+ {{.Description}}{{end}}{{if .VisibleFlags}}
+
+OPTIONS:
+ {{range .VisibleFlags}}{{.}}
+ {{end}}{{end}}
+`
+
+// SubcommandHelpTemplate is the text template for the subcommand help topic.
+// cli.go uses text/template to render templates. You can
+// render custom help text by setting this variable.
+var SubcommandHelpTemplate = `NAME:
+ {{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}}
+
+USAGE:
+ {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}
+
+COMMANDS:{{range .VisibleCategories}}{{if .Name}}
+ {{.Name}}:{{end}}{{range .VisibleCommands}}
+ {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}
+{{end}}{{if .VisibleFlags}}
+OPTIONS:
+ {{range .VisibleFlags}}{{.}}
+ {{end}}{{end}}
+`
+
+var helpCommand = &Command{
+ Name: "help",
+ Aliases: []string{"h"},
+ Usage: "Shows a list of commands or help for one command",
+ ArgsUsage: "[command]",
+ Action: func(c *Context) error {
+ args := c.Args()
+ if args.Present() {
+ return ShowCommandHelp(c, args.First())
+ }
+
+ ShowAppHelp(c)
+ return nil
+ },
+}
+
+var helpSubcommand = &Command{
+ Name: "help",
+ Aliases: []string{"h"},
+ Usage: "Shows a list of commands or help for one command",
+ ArgsUsage: "[command]",
+ Action: func(c *Context) error {
+ args := c.Args()
+ if args.Present() {
+ return ShowCommandHelp(c, args.First())
+ }
+
+ return ShowSubcommandHelp(c)
+ },
+}
+
+// Prints help for the App or Command
+type helpPrinter func(w io.Writer, templ string, data interface{})
+
+// Prints help for the App or Command with custom template function.
+type helpPrinterCustom func(w io.Writer, templ string, data interface{}, customFunc map[string]interface{})
+
+// HelpPrinter is a function that writes the help output. If not set a default
+// is used. The function signature is:
+// func(w io.Writer, templ string, data interface{})
+var HelpPrinter helpPrinter = printHelp
+
+// HelpPrinterCustom is same as HelpPrinter but
+// takes a custom function for template function map.
+var HelpPrinterCustom helpPrinterCustom = printHelpCustom
+
+// VersionPrinter prints the version for the App
+var VersionPrinter = printVersion
+
+// ShowAppHelpAndExit - Prints the list of subcommands for the app and exits with exit code.
+func ShowAppHelpAndExit(c *Context, exitCode int) {
+ ShowAppHelp(c)
+ os.Exit(exitCode)
+}
+
+// ShowAppHelp is an action that displays the help.
+func ShowAppHelp(c *Context) (err error) {
+ if c.App.CustomAppHelpTemplate == "" {
+ HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
+ return
+ }
+ customAppData := func() map[string]interface{} {
+ if c.App.ExtraInfo == nil {
+ return nil
+ }
+ return map[string]interface{}{
+ "ExtraInfo": c.App.ExtraInfo,
+ }
+ }
+ HelpPrinterCustom(c.App.Writer, c.App.CustomAppHelpTemplate, c.App, customAppData())
+ return nil
+}
+
+// DefaultAppComplete prints the list of subcommands as the default app completion method
+func DefaultAppComplete(c *Context) {
+ for _, command := range c.App.Commands {
+ if command.Hidden {
+ continue
+ }
+ for _, name := range command.Names() {
+ fmt.Fprintln(c.App.Writer, name)
+ }
+ }
+}
+
+// ShowCommandHelpAndExit - exits with code after showing help
+func ShowCommandHelpAndExit(c *Context, command string, code int) {
+ ShowCommandHelp(c, command)
+ os.Exit(code)
+}
+
+// ShowCommandHelp prints help for the given command
+func ShowCommandHelp(ctx *Context, command string) error {
+ // show the subcommand help for a command with subcommands
+ if command == "" {
+ HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
+ return nil
+ }
+
+ for _, c := range ctx.App.Commands {
+ if c.HasName(command) {
+ if c.CustomHelpTemplate != "" {
+ HelpPrinterCustom(ctx.App.Writer, c.CustomHelpTemplate, c, nil)
+ } else {
+ HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
+ }
+ return nil
+ }
+ }
+
+ if ctx.App.CommandNotFound == nil {
+ return Exit(fmt.Sprintf("No help topic for '%v'", command), 3)
+ }
+
+ ctx.App.CommandNotFound(ctx, command)
+ return nil
+}
+
+// ShowSubcommandHelp prints help for the given subcommand
+func ShowSubcommandHelp(c *Context) error {
+ if c == nil {
+ return nil
+ }
+
+ if c.Command != nil {
+ return ShowCommandHelp(c, c.Command.Name)
+ }
+
+ return ShowCommandHelp(c, "")
+}
+
+// ShowVersion prints the version number of the App
+func ShowVersion(c *Context) {
+ VersionPrinter(c)
+}
+
+func printVersion(c *Context) {
+ fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version)
+}
+
+// ShowCompletions prints the lists of commands within a given context
+func ShowCompletions(c *Context) {
+ a := c.App
+ if a != nil && a.ShellComplete != nil {
+ a.ShellComplete(c)
+ }
+}
+
+// ShowCommandCompletions prints the custom completions for a given command
+func ShowCommandCompletions(ctx *Context, command string) {
+ c := ctx.App.Command(command)
+ if c != nil && c.ShellComplete != nil {
+ c.ShellComplete(ctx)
+ }
+}
+
+func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) {
+ funcMap := template.FuncMap{
+ "join": strings.Join,
+ }
+ if customFunc != nil {
+ for key, value := range customFunc {
+ funcMap[key] = value
+ }
+ }
+
+ w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0)
+ t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
+
+ errDebug := os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != ""
+
+ err := t.Execute(w, data)
+ if err != nil {
+ if errDebug {
+ fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err)
+ }
+ return
+ }
+
+ w.Flush()
+}
+
+func printHelp(out io.Writer, templ string, data interface{}) {
+ printHelpCustom(out, templ, data, nil)
+}
+
+func checkVersion(c *Context) bool {
+ found := false
+ for _, name := range VersionFlag.Names() {
+ if c.Bool(name) {
+ found = true
+ }
+ }
+ return found
+}
+
+func checkHelp(c *Context) bool {
+ found := false
+ for _, name := range HelpFlag.Names() {
+ if c.Bool(name) {
+ found = true
+ }
+ }
+ return found
+}
+
+func checkCommandHelp(c *Context, name string) bool {
+ if c.Bool("h") || c.Bool("help") {
+ ShowCommandHelp(c, name)
+ return true
+ }
+
+ return false
+}
+
+func checkSubcommandHelp(c *Context) bool {
+ if c.Bool("h") || c.Bool("help") {
+ ShowSubcommandHelp(c)
+ return true
+ }
+
+ return false
+}
+
+func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) {
+ if !a.EnableShellCompletion {
+ return false, arguments
+ }
+
+ pos := len(arguments) - 1
+ lastArg := arguments[pos]
+
+ if lastArg != "--"+genCompName() {
+ return false, arguments
+ }
+
+ return true, arguments[:pos]
+}
+
+func checkCompletions(c *Context) bool {
+ if !c.shellComplete {
+ return false
+ }
+
+ if args := c.Args(); args.Present() {
+ name := args.First()
+ if cmd := c.App.Command(name); cmd != nil {
+ // let the command handle the completion
+ return false
+ }
+ }
+
+ ShowCompletions(c)
+ return true
+}
+
+func checkCommandCompletions(c *Context, name string) bool {
+ if !c.shellComplete {
+ return false
+ }
+
+ ShowCommandCompletions(c, name)
+ return true
+}
+
+func checkInitCompletion(c *Context) (bool, error) {
+ if c.IsSet(InitCompletionFlag.Name) {
+ shell := c.String(InitCompletionFlag.Name)
+ progName := os.Args[0]
+ switch shell {
+ case "bash":
+ fmt.Print(bashCompletionCode(progName))
+ return true, nil
+ case "zsh":
+ fmt.Print(zshCompletionCode(progName))
+ return true, nil
+ default:
+ return false, fmt.Errorf("--init-completion value cannot be '%s'", shell)
+ }
+ }
+ return false, nil
+}
+
+func bashCompletionCode(progName string) string {
+ var template = `_cli_bash_autocomplete() {
+ local cur opts base;
+ COMPREPLY=();
+ cur="${COMP_WORDS[COMP_CWORD]}";
+ opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --%s );
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) );
+ return 0;
+};
+complete -F _cli_bash_autocomplete %s`
+ return fmt.Sprintf(template, genCompName(), progName)
+}
+
+func zshCompletionCode(progName string) string {
+ var template = `autoload -U compinit && compinit;
+autoload -U bashcompinit && bashcompinit;`
+
+ return template + "\n" + bashCompletionCode(progName)
+}
diff --git a/vendor/gopkg.in/urfave/cli.v2/runtests b/vendor/gopkg.in/urfave/cli.v2/runtests
new file mode 100644
index 0000000..d2c5ea6
--- /dev/null
+++ b/vendor/gopkg.in/urfave/cli.v2/runtests
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+from __future__ import print_function, unicode_literals
+
+import argparse
+import codecs
+import glob
+import os
+import platform
+import shutil
+import sys
+import tempfile
+
+from subprocess import check_call, check_output
+
+
+_PY3 = sys.version_info.major == 3
+_WINDOWS = platform.system().lower() == 'windows'
+_PACKAGE_NAME = os.environ.get(
+ 'CLI_PACKAGE_NAME', 'github.com/urfave/cli'
+)
+_TARGETS = {}
+
+
+def main(sysargs=sys.argv[:]):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'target', nargs='?', choices=tuple(_TARGETS.keys()), default='test'
+ )
+ args = parser.parse_args(sysargs[1:])
+
+ _TARGETS[args.target]()
+ return 0
+
+
+def _target(func):
+ _TARGETS[func.__name__.strip('_')] = func
+ return func
+
+
+@_target
+def _test():
+ if _go_version() < 'go1.2':
+ _run('go test -v .')
+ return
+
+ coverprofiles = []
+ for subpackage in ['', 'altsrc']:
+ coverprofile = 'cli.coverprofile'
+ if subpackage != '':
+ coverprofile = '{}.coverprofile'.format(subpackage)
+
+ coverprofiles.append(coverprofile)
+
+ _run('go test -v'.split() + [
+ '-coverprofile={}'.format(coverprofile),
+ ('{}/{}'.format(_PACKAGE_NAME, subpackage)).rstrip('/')
+ ])
+
+ combined_name = _combine_coverprofiles(coverprofiles)
+ _run('go tool cover -func={}'.format(combined_name))
+ os.remove(combined_name)
+
+
+@_target
+def _gfmrun():
+ go_version = _go_version()
+ if go_version < 'go1.3':
+ print('runtests: skip on {}'.format(go_version), file=sys.stderr)
+ return
+ _run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md'])
+
+
+@_target
+def _vet():
+ _run('go vet ./...')
+
+
+@_target
+def _migrations():
+ go_version = _go_version()
+ if go_version < 'go1.3':
+ print('runtests: skip on {}'.format(go_version), file=sys.stderr)
+ return
+
+ migration_script = os.path.abspath(
+ os.environ.get('V1TOV2', './cli-v1-to-v2')
+ )
+ v1_readme_url = os.environ.get(
+ 'V1README',
+ 'https://raw.githubusercontent.com/urfave/cli/v1/README.md'
+ )
+
+ tmpdir = tempfile.mkdtemp()
+ try:
+ os.chdir(tmpdir)
+ _run('curl -sSL -o README.md {}'.format(v1_readme_url).split())
+ _run('gfmrun extract -o .'.split())
+
+ for gofile in glob.glob('*.go'):
+ for i in (0, 1):
+ _run(['python', migration_script, '-w', gofile])
+ _run('go build -o tmp.out {}'.format(gofile).split())
+ finally:
+ if os.environ.get('NOCLEAN', '') == '':
+ shutil.rmtree(tmpdir, ignore_errors=True)
+
+
+@_target
+def _toc():
+ exe = ['bash'] if _WINDOWS else []
+ _run(exe + [
+ os.path.join('node_modules', '.bin', 'markdown-toc'),
+ '-i', 'README.md'
+ ])
+ _run('git diff --exit-code')
+
+
+@_target
+def _gen():
+ go_version = _go_version()
+ if go_version < 'go1.5':
+ print('runtests: skip on {}'.format(go_version), file=sys.stderr)
+ return
+
+ _run('go generate ./...')
+ _run('git diff --exit-code')
+
+
+def _run(command):
+ if hasattr(command, 'split'):
+ command = command.split()
+ print('runtests: {}'.format(' '.join(command)), file=sys.stderr)
+ sys.stderr.flush()
+ check_call(command)
+
+
+def _gfmrun_count():
+ with codecs.open('README.md', 'r', 'utf-8') as infile:
+ lines = infile.read().splitlines()
+ return len(list(filter(_is_go_runnable, lines)))
+
+
+def _is_go_runnable(line):
+ return line.startswith('package main')
+
+
+def _go_version():
+ return check_output('go version'.split()).decode('utf-8').split()[2]
+
+
+def _combine_coverprofiles(coverprofiles):
+ tmp_args = dict(suffix='.coverprofile', mode='w', delete=False)
+ if _PY3:
+ tmp_args['encoding'] = 'utf-8'
+
+ combined = tempfile.NamedTemporaryFile(**tmp_args)
+ combined.write('mode: set\n')
+
+ for coverprofile in coverprofiles:
+ with codecs.open(coverprofile, 'r', 'utf-8') as infile:
+ for line in infile.readlines():
+ if not line.startswith('mode: '):
+ combined.write(line)
+
+ combined.flush()
+ name = combined.name
+ combined.close()
+ return name
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/vendor/modules.txt b/vendor/modules.txt
new file mode 100644
index 0000000..061aa51
--- /dev/null
+++ b/vendor/modules.txt
@@ -0,0 +1,2 @@
+# gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
+gopkg.in/urfave/cli.v2