Update https://github.com/urfave/cli to version 1.2.0 (#6838)
From un-tagged pervious version : https://github.com/urfave/cli/compare/d86a009f5e13...master
This commit is contained in:
parent
dbb0c9658c
commit
2933ae4e88
2
go.mod
2
go.mod
|
@ -109,7 +109,7 @@ require (
|
||||||
github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 // indirect
|
github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 // indirect
|
||||||
github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200 // indirect
|
github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200 // indirect
|
||||||
github.com/tstranex/u2f v1.0.0
|
github.com/tstranex/u2f v1.0.0
|
||||||
github.com/urfave/cli v0.0.0-20161102131801-d86a009f5e13
|
github.com/urfave/cli v1.20.0
|
||||||
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 // indirect
|
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 // indirect
|
||||||
github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53
|
github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53
|
||||||
go.etcd.io/bbolt v1.3.2 // indirect
|
go.etcd.io/bbolt v1.3.2 // indirect
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -221,8 +221,6 @@ github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK86
|
||||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mcuadros/go-version v0.0.0-20171003094716-88e56e02bea1 h1:4yXas1DDHpauOfuyfmAMm+EB+SiqPKEoTdc88XEJHsc=
|
|
||||||
github.com/mcuadros/go-version v0.0.0-20171003094716-88e56e02bea1/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
|
|
||||||
github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 h1:Pijfgr7ZuvX7QIQiEwLdRVr3RoMG+i0SbBO1Qu+7yVk=
|
github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 h1:Pijfgr7ZuvX7QIQiEwLdRVr3RoMG+i0SbBO1Qu+7yVk=
|
||||||
github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
|
github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
|
||||||
github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a h1:d18LCO3ctH2kugUqt0pEyKKP8L+IYrocaPqGFilhTKk=
|
github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a h1:d18LCO3ctH2kugUqt0pEyKKP8L+IYrocaPqGFilhTKk=
|
||||||
|
@ -299,8 +297,8 @@ github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200 h1:ZVvr38DYEyOPyelySq
|
||||||
github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||||
github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ=
|
github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ=
|
||||||
github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo=
|
github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo=
|
||||||
github.com/urfave/cli v0.0.0-20161102131801-d86a009f5e13 h1:niRuEF0NOlFnqraxzjuvvOdCM6gxmHiaBABjvg3/kDo=
|
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||||
github.com/urfave/cli v0.0.0-20161102131801-d86a009f5e13/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 h1:E8u341JM/N8LCnPXBV6ZFD1RKo/j+qHl1XOqSV+GstA=
|
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 h1:E8u341JM/N8LCnPXBV6ZFD1RKo/j+qHl1XOqSV+GstA=
|
||||||
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||||
github.com/xanzy/ssh-agent v0.2.0 h1:Adglfbi5p9Z0BmK2oKU9nTG+zKfniSfnaMYB+ULd+Ro=
|
github.com/xanzy/ssh-agent v0.2.0 h1:Adglfbi5p9Z0BmK2oKU9nTG+zKfniSfnaMYB+ULd+Ro=
|
||||||
|
@ -359,8 +357,6 @@ gopkg.in/src-d/go-billy.v4 v4.3.0 h1:KtlZ4c1OWbIs4jCv5ZXrTqG8EQocr0g/d4DjNg70aek
|
||||||
gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
|
gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
|
||||||
gopkg.in/src-d/go-git-fixtures.v3 v3.1.1 h1:XWW/s5W18RaJpmo1l0IYGqXKuJITWRFuA45iOf1dKJs=
|
gopkg.in/src-d/go-git-fixtures.v3 v3.1.1 h1:XWW/s5W18RaJpmo1l0IYGqXKuJITWRFuA45iOf1dKJs=
|
||||||
gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||||
gopkg.in/src-d/go-git.v4 v4.8.0 h1:dDEbgvfNG9vUDM54uhCYPExiGa8uYgXpQ/MR8YvxcAM=
|
|
||||||
gopkg.in/src-d/go-git.v4 v4.8.0/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk=
|
|
||||||
gopkg.in/src-d/go-git.v4 v4.10.0 h1:NWjTJTQnk8UpIGlssuefyDZ6JruEjo5s88vm88uASbw=
|
gopkg.in/src-d/go-git.v4 v4.10.0 h1:NWjTJTQnk8UpIGlssuefyDZ6JruEjo5s88vm88uASbw=
|
||||||
gopkg.in/src-d/go-git.v4 v4.10.0/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk=
|
gopkg.in/src-d/go-git.v4 v4.10.0/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk=
|
||||||
gopkg.in/stretchr/testify.v1 v1.2.2 h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz3M=
|
gopkg.in/stretchr/testify.v1 v1.2.2 h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz3M=
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[flake8]
|
||||||
|
max-line-length = 120
|
|
@ -1,32 +1,20 @@
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
sudo: false
|
sudo: false
|
||||||
|
dist: trusty
|
||||||
|
osx_image: xcode8.3
|
||||||
|
go: 1.8.x
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- node_modules
|
- node_modules
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.2.x
|
|
||||||
- 1.3.x
|
|
||||||
- 1.4.2
|
|
||||||
- 1.5.x
|
|
||||||
- 1.6.x
|
|
||||||
- 1.7.x
|
|
||||||
- master
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- go: master
|
|
||||||
include:
|
|
||||||
- go: 1.6.x
|
|
||||||
os: osx
|
|
||||||
- go: 1.7.x
|
|
||||||
os: osx
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- go get github.com/urfave/gfmrun/... || true
|
- go get github.com/urfave/gfmrun/... || true
|
||||||
- go get golang.org/x/tools/... || true
|
- go get golang.org/x/tools/cmd/goimports
|
||||||
- if [ ! -f node_modules/.bin/markdown-toc ] ; then
|
- if [ ! -f node_modules/.bin/markdown-toc ] ; then
|
||||||
npm install markdown-toc ;
|
npm install markdown-toc ;
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -3,14 +3,105 @@
|
||||||
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## 1.20.0 - 2017-08-10
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* `HandleExitCoder` is now correctly iterates over all errors in
|
||||||
|
a `MultiError`. The exit code is the exit code of the last error or `1` if
|
||||||
|
there are no `ExitCoder`s in the `MultiError`.
|
||||||
|
* Fixed YAML file loading on Windows (previously would fail validate the file path)
|
||||||
|
* Subcommand `Usage`, `Description`, `ArgsUsage`, `OnUsageError` correctly
|
||||||
|
propogated
|
||||||
|
* `ErrWriter` is now passed downwards through command structure to avoid the
|
||||||
|
need to redefine it
|
||||||
|
* Pass `Command` context into `OnUsageError` rather than parent context so that
|
||||||
|
all fields are avaiable
|
||||||
|
* Errors occuring in `Before` funcs are no longer double printed
|
||||||
|
* Use `UsageText` in the help templates for commands and subcommands if
|
||||||
|
defined; otherwise build the usage as before (was previously ignoring this
|
||||||
|
field)
|
||||||
|
* `IsSet` and `GlobalIsSet` now correctly return whether a flag is set if
|
||||||
|
a program calls `Set` or `GlobalSet` directly after flag parsing (would
|
||||||
|
previously only return `true` if the flag was set during parsing)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* No longer exit the program on command/subcommand error if the error raised is
|
||||||
|
not an `OsExiter`. This exiting behavior was introduced in 1.19.0, but was
|
||||||
|
determined to be a regression in functionality. See [the
|
||||||
|
PR](https://github.com/urfave/cli/pull/595) for discussion.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
* `CommandsByName` type was added to make it easy to sort `Command`s by name,
|
||||||
|
alphabetically
|
||||||
|
* `altsrc` now handles loading of string and int arrays from TOML
|
||||||
|
* Support for definition of custom help templates for `App` via
|
||||||
|
`CustomAppHelpTemplate`
|
||||||
|
* Support for arbitrary key/value fields on `App` to be used with
|
||||||
|
`CustomAppHelpTemplate` via `ExtraInfo`
|
||||||
|
* `HelpFlag`, `VersionFlag`, and `BashCompletionFlag` changed to explictly be
|
||||||
|
`cli.Flag`s allowing for the use of custom flags satisfying the `cli.Flag`
|
||||||
|
interface to be used.
|
||||||
|
|
||||||
|
|
||||||
|
## [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`
|
- Flag type code generation via `go generate`
|
||||||
- Write to stderr and exit 1 if action returns non-nil error
|
- Write to stderr and exit 1 if action returns non-nil error
|
||||||
- Added support for TOML to the `altsrc` loader
|
- 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
|
### Changed
|
||||||
- Raise minimum tested/supported Go version to 1.2+
|
- 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
|
## [1.18.0] - 2016-06-27
|
||||||
### Added
|
### Added
|
||||||
- `./runtests` test runner with coverage tracking by default
|
- `./runtests` test runner with coverage tracking by default
|
||||||
|
@ -29,6 +120,10 @@
|
||||||
- No longer swallows `panic`s that occur within the `Action`s themselves when
|
- No longer swallows `panic`s that occur within the `Action`s themselves when
|
||||||
detecting the signature of the `Action` field
|
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
|
## [1.17.0] - 2016-05-09
|
||||||
### Added
|
### Added
|
||||||
- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc`
|
- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc`
|
||||||
|
@ -50,6 +145,10 @@
|
||||||
- cleanups based on [Go Report Card
|
- cleanups based on [Go Report Card
|
||||||
feedback](https://goreportcard.com/report/github.com/urfave/cli)
|
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
|
## [1.16.0] - 2016-05-02
|
||||||
### Added
|
### Added
|
||||||
- `Hidden` field on all flag struct types to omit from generated help text
|
- `Hidden` field on all flag struct types to omit from generated help text
|
||||||
|
|
|
@ -455,13 +455,13 @@ error.
|
||||||
|
|
||||||
Flags for the application and commands are shown in the order they are defined.
|
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`
|
However, it's possible to sort them from outside this library by using `FlagsByName`
|
||||||
with `sort`.
|
or `CommandsByName` with `sort`.
|
||||||
|
|
||||||
For example this:
|
For example this:
|
||||||
|
|
||||||
<!-- {
|
<!-- {
|
||||||
"args": ["--help"],
|
"args": ["--help"],
|
||||||
"output": "Load configuration from FILE\n.*Language for the greeting.*"
|
"output": "add a task to the list\n.*complete a task on the list\n.*\n\n.*\n.*Load configuration from FILE\n.*Language for the greeting.*"
|
||||||
} -->
|
} -->
|
||||||
``` go
|
``` go
|
||||||
package main
|
package main
|
||||||
|
@ -488,7 +488,27 @@ func main() {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.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.FlagsByName(app.Flags))
|
||||||
|
sort.Sort(cli.CommandsByName(app.Commands))
|
||||||
|
|
||||||
app.Run(os.Args)
|
app.Run(os.Args)
|
||||||
}
|
}
|
||||||
|
@ -940,16 +960,13 @@ SUPPORT: support@awesometown.example.com
|
||||||
cli.AppHelpTemplate = `NAME:
|
cli.AppHelpTemplate = `NAME:
|
||||||
{{.Name}} - {{.Usage}}
|
{{.Name}} - {{.Usage}}
|
||||||
USAGE:
|
USAGE:
|
||||||
{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command
|
{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
|
||||||
[command options]{{end}} {{if
|
|
||||||
.ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
|
|
||||||
{{if len .Authors}}
|
{{if len .Authors}}
|
||||||
AUTHOR(S):
|
AUTHOR:
|
||||||
{{range .Authors}}{{ . }}{{end}}
|
{{range .Authors}}{{ . }}{{end}}
|
||||||
{{end}}{{if .Commands}}
|
{{end}}{{if .Commands}}
|
||||||
COMMANDS:
|
COMMANDS:
|
||||||
{{range .Commands}}{{if not .HideHelp}} {{join .Names ", "}}{{ "\t"
|
{{range .Commands}}{{if not .HideHelp}} {{join .Names ", "}}{{ "\t"}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
||||||
}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
|
||||||
GLOBAL OPTIONS:
|
GLOBAL OPTIONS:
|
||||||
{{range .VisibleFlags}}{{.}}
|
{{range .VisibleFlags}}{{.}}
|
||||||
{{end}}{{end}}{{if .Copyright }}
|
{{end}}{{end}}{{if .Copyright }}
|
||||||
|
|
|
@ -85,6 +85,12 @@ type App struct {
|
||||||
ErrWriter io.Writer
|
ErrWriter io.Writer
|
||||||
// Other custom info
|
// Other custom info
|
||||||
Metadata map[string]interface{}
|
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
|
didSetup bool
|
||||||
}
|
}
|
||||||
|
@ -145,10 +151,6 @@ func (a *App) Setup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.EnableBashCompletion {
|
|
||||||
a.appendFlag(BashCompletionFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !a.HideVersion {
|
if !a.HideVersion {
|
||||||
a.appendFlag(VersionFlag)
|
a.appendFlag(VersionFlag)
|
||||||
}
|
}
|
||||||
|
@ -173,8 +175,20 @@ func (a *App) Setup() {
|
||||||
func (a *App) Run(arguments []string) (err error) {
|
func (a *App) Run(arguments []string) (err error) {
|
||||||
a.Setup()
|
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
|
// parse flags
|
||||||
set := flagSet(a.Name, a.Flags)
|
set, err := flagSet(a.Name, a.Flags)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
set.SetOutput(ioutil.Discard)
|
set.SetOutput(ioutil.Discard)
|
||||||
err = set.Parse(arguments[1:])
|
err = set.Parse(arguments[1:])
|
||||||
nerr := normalizeFlags(a.Flags, set)
|
nerr := normalizeFlags(a.Flags, set)
|
||||||
|
@ -184,6 +198,7 @@ func (a *App) Run(arguments []string) (err error) {
|
||||||
ShowAppHelp(context)
|
ShowAppHelp(context)
|
||||||
return nerr
|
return nerr
|
||||||
}
|
}
|
||||||
|
context.shellComplete = shellComplete
|
||||||
|
|
||||||
if checkCompletions(context) {
|
if checkCompletions(context) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -225,7 +240,6 @@ func (a *App) Run(arguments []string) (err error) {
|
||||||
if a.Before != nil {
|
if a.Before != nil {
|
||||||
beforeErr := a.Before(context)
|
beforeErr := a.Before(context)
|
||||||
if beforeErr != nil {
|
if beforeErr != nil {
|
||||||
fmt.Fprintf(a.Writer, "%v\n\n", beforeErr)
|
|
||||||
ShowAppHelp(context)
|
ShowAppHelp(context)
|
||||||
HandleExitCoder(beforeErr)
|
HandleExitCoder(beforeErr)
|
||||||
err = beforeErr
|
err = beforeErr
|
||||||
|
@ -242,6 +256,10 @@ func (a *App) Run(arguments []string) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if a.Action == nil {
|
||||||
|
a.Action = helpCommand.Action
|
||||||
|
}
|
||||||
|
|
||||||
// Run default Action
|
// Run default Action
|
||||||
err = HandleAction(a.Action, context)
|
err = HandleAction(a.Action, context)
|
||||||
|
|
||||||
|
@ -283,13 +301,12 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||||
}
|
}
|
||||||
a.Commands = newCmds
|
a.Commands = newCmds
|
||||||
|
|
||||||
// append flags
|
// parse flags
|
||||||
if a.EnableBashCompletion {
|
set, err := flagSet(a.Name, a.Flags)
|
||||||
a.appendFlag(BashCompletionFlag)
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse flags
|
|
||||||
set := flagSet(a.Name, a.Flags)
|
|
||||||
set.SetOutput(ioutil.Discard)
|
set.SetOutput(ioutil.Discard)
|
||||||
err = set.Parse(ctx.Args().Tail())
|
err = set.Parse(ctx.Args().Tail())
|
||||||
nerr := normalizeFlags(a.Flags, set)
|
nerr := normalizeFlags(a.Flags, set)
|
||||||
|
@ -467,7 +484,9 @@ func (a Author) String() string {
|
||||||
// it's an ActionFunc or a func with the legacy signature for Action, the func
|
// it's an ActionFunc or a func with the legacy signature for Action, the func
|
||||||
// is run!
|
// is run!
|
||||||
func HandleAction(action interface{}, context *Context) (err error) {
|
func HandleAction(action interface{}, context *Context) (err error) {
|
||||||
if a, ok := action.(func(*Context) error); ok {
|
if a, ok := action.(ActionFunc); ok {
|
||||||
|
return a(context)
|
||||||
|
} else if a, ok := action.(func(*Context) error); ok {
|
||||||
return a(context)
|
return a(context)
|
||||||
} else if a, ok := action.(func(*Context)); ok { // deprecated function signature
|
} else if a, ok := action.(func(*Context)); ok { // deprecated function signature
|
||||||
a(context)
|
a(context)
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
version: "{build}"
|
version: "{build}"
|
||||||
|
|
||||||
os: Windows Server 2012 R2
|
os: Windows Server 2016
|
||||||
|
|
||||||
|
image: Visual Studio 2017
|
||||||
|
|
||||||
clone_folder: c:\gopath\src\github.com\urfave\cli
|
clone_folder: c:\gopath\src\github.com\urfave\cli
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
GOPATH: C:\gopath
|
GOPATH: C:\gopath
|
||||||
GOVERSION: 1.6
|
GOVERSION: 1.8.x
|
||||||
PYTHON: C:\Python27-x64
|
PYTHON: C:\Python36-x64
|
||||||
PYTHON_VERSION: 2.7.x
|
PYTHON_VERSION: 3.6.x
|
||||||
PYTHON_ARCH: 64
|
PYTHON_ARCH: 64
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// app.Usage = "say a greeting"
|
// app.Usage = "say a greeting"
|
||||||
// app.Action = func(c *cli.Context) error {
|
// app.Action = func(c *cli.Context) error {
|
||||||
// println("Greetings")
|
// println("Greetings")
|
||||||
|
// return nil
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// app.Run(os.Args)
|
// app.Run(os.Args)
|
||||||
|
|
|
@ -59,6 +59,25 @@ type Command struct {
|
||||||
// Full name of command for help, defaults to full command name, including parent commands.
|
// Full name of command for help, defaults to full command name, including parent commands.
|
||||||
HelpName string
|
HelpName string
|
||||||
commandNamePath []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.
|
// FullName returns the full name of the command.
|
||||||
|
@ -87,11 +106,10 @@ func (c Command) Run(ctx *Context) (err error) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.App.EnableBashCompletion {
|
set, err := flagSet(c.Name, c.Flags)
|
||||||
c.Flags = append(c.Flags, BashCompletionFlag)
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
set := flagSet(c.Name, c.Flags)
|
|
||||||
set.SetOutput(ioutil.Discard)
|
set.SetOutput(ioutil.Discard)
|
||||||
|
|
||||||
if c.SkipFlagParsing {
|
if c.SkipFlagParsing {
|
||||||
|
@ -132,18 +150,6 @@ func (c Command) Run(ctx *Context) (err error) {
|
||||||
err = set.Parse(ctx.Args().Tail())
|
err = set.Parse(ctx.Args().Tail())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if c.OnUsageError != nil {
|
|
||||||
err := c.OnUsageError(ctx, err, false)
|
|
||||||
HandleExitCoder(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage:", err.Error())
|
|
||||||
fmt.Fprintln(ctx.App.Writer)
|
|
||||||
ShowCommandHelp(ctx, c.Name)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
nerr := normalizeFlags(c.Flags, set)
|
nerr := normalizeFlags(c.Flags, set)
|
||||||
if nerr != nil {
|
if nerr != nil {
|
||||||
fmt.Fprintln(ctx.App.Writer, nerr)
|
fmt.Fprintln(ctx.App.Writer, nerr)
|
||||||
|
@ -153,11 +159,23 @@ func (c Command) Run(ctx *Context) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
context := NewContext(ctx.App, set, ctx)
|
context := NewContext(ctx.App, set, ctx)
|
||||||
|
context.Command = c
|
||||||
if checkCommandCompletions(context, c.Name) {
|
if checkCommandCompletions(context, c.Name) {
|
||||||
return nil
|
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) {
|
if checkCommandHelp(context, c.Name) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -179,15 +197,16 @@ func (c Command) Run(ctx *Context) (err error) {
|
||||||
if c.Before != nil {
|
if c.Before != nil {
|
||||||
err = c.Before(context)
|
err = c.Before(context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(ctx.App.Writer, err)
|
ShowCommandHelp(context, c.Name)
|
||||||
fmt.Fprintln(ctx.App.Writer)
|
|
||||||
ShowCommandHelp(ctx, c.Name)
|
|
||||||
HandleExitCoder(err)
|
HandleExitCoder(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.Command = c
|
if c.Action == nil {
|
||||||
|
c.Action = helpSubcommand.Action
|
||||||
|
}
|
||||||
|
|
||||||
err = HandleAction(c.Action, context)
|
err = HandleAction(c.Action, context)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -228,14 +247,13 @@ func (c Command) startApp(ctx *Context) error {
|
||||||
app.HelpName = app.Name
|
app.HelpName = app.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Description != "" {
|
app.Usage = c.Usage
|
||||||
app.Usage = c.Description
|
app.Description = c.Description
|
||||||
} else {
|
app.ArgsUsage = c.ArgsUsage
|
||||||
app.Usage = c.Usage
|
|
||||||
}
|
|
||||||
|
|
||||||
// set CommandNotFound
|
// set CommandNotFound
|
||||||
app.CommandNotFound = ctx.App.CommandNotFound
|
app.CommandNotFound = ctx.App.CommandNotFound
|
||||||
|
app.CustomAppHelpTemplate = c.CustomHelpTemplate
|
||||||
|
|
||||||
// set the flags and commands
|
// set the flags and commands
|
||||||
app.Commands = c.Subcommands
|
app.Commands = c.Subcommands
|
||||||
|
@ -248,6 +266,7 @@ func (c Command) startApp(ctx *Context) error {
|
||||||
app.Author = ctx.App.Author
|
app.Author = ctx.App.Author
|
||||||
app.Email = ctx.App.Email
|
app.Email = ctx.App.Email
|
||||||
app.Writer = ctx.App.Writer
|
app.Writer = ctx.App.Writer
|
||||||
|
app.ErrWriter = ctx.App.ErrWriter
|
||||||
|
|
||||||
app.categories = CommandCategories{}
|
app.categories = CommandCategories{}
|
||||||
for _, command := range c.Subcommands {
|
for _, command := range c.Subcommands {
|
||||||
|
@ -270,6 +289,7 @@ func (c Command) startApp(ctx *Context) error {
|
||||||
} else {
|
} else {
|
||||||
app.Action = helpSubcommand.Action
|
app.Action = helpSubcommand.Action
|
||||||
}
|
}
|
||||||
|
app.OnUsageError = c.OnUsageError
|
||||||
|
|
||||||
for index, cc := range app.Commands {
|
for index, cc := range app.Commands {
|
||||||
app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
|
app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
|
||||||
|
|
|
@ -3,9 +3,9 @@ package cli
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Context is a type that is passed through to
|
// Context is a type that is passed through to
|
||||||
|
@ -15,6 +15,7 @@ import (
|
||||||
type Context struct {
|
type Context struct {
|
||||||
App *App
|
App *App
|
||||||
Command Command
|
Command Command
|
||||||
|
shellComplete bool
|
||||||
flagSet *flag.FlagSet
|
flagSet *flag.FlagSet
|
||||||
setFlags map[string]bool
|
setFlags map[string]bool
|
||||||
parentContext *Context
|
parentContext *Context
|
||||||
|
@ -22,7 +23,13 @@ type Context struct {
|
||||||
|
|
||||||
// NewContext creates a new context. For use in when invoking an App or Command action.
|
// 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 {
|
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
|
||||||
return &Context{App: app, flagSet: set, parentContext: parentCtx}
|
c := &Context{App: app, flagSet: set, parentContext: parentCtx}
|
||||||
|
|
||||||
|
if parentCtx != nil {
|
||||||
|
c.shellComplete = parentCtx.shellComplete
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumFlags returns the number of flags set
|
// NumFlags returns the number of flags set
|
||||||
|
@ -32,11 +39,13 @@ func (c *Context) NumFlags() int {
|
||||||
|
|
||||||
// Set sets a context flag to a value.
|
// Set sets a context flag to a value.
|
||||||
func (c *Context) Set(name, value string) error {
|
func (c *Context) Set(name, value string) error {
|
||||||
|
c.setFlags = nil
|
||||||
return c.flagSet.Set(name, value)
|
return c.flagSet.Set(name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GlobalSet sets a context flag to a value on the global flagset
|
// GlobalSet sets a context flag to a value on the global flagset
|
||||||
func (c *Context) GlobalSet(name, value string) error {
|
func (c *Context) GlobalSet(name, value string) error {
|
||||||
|
globalContext(c).setFlags = nil
|
||||||
return globalContext(c).flagSet.Set(name, value)
|
return globalContext(c).flagSet.Set(name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +100,7 @@ func (c *Context) IsSet(name string) bool {
|
||||||
|
|
||||||
eachName(envVarValue.String(), func(envVar string) {
|
eachName(envVarValue.String(), func(envVar string) {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if _, ok := syscall.Getenv(envVar); ok {
|
||||||
c.setFlags[name] = true
|
c.setFlags[name] = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -147,6 +156,11 @@ func (c *Context) Parent() *Context {
|
||||||
return c.parentContext
|
return c.parentContext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// value returns the value of the flag coressponding to `name`
|
||||||
|
func (c *Context) value(name string) interface{} {
|
||||||
|
return c.flagSet.Lookup(name).Value.(flag.Getter).Get()
|
||||||
|
}
|
||||||
|
|
||||||
// Args contains apps console arguments
|
// Args contains apps console arguments
|
||||||
type Args []string
|
type Args []string
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@ func (m MultiError) Error() string {
|
||||||
return strings.Join(errs, "\n")
|
return strings.Join(errs, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ErrorFormatter interface {
|
||||||
|
Format(s fmt.State, verb rune)
|
||||||
|
}
|
||||||
|
|
||||||
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
|
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
|
||||||
// code
|
// code
|
||||||
type ExitCoder interface {
|
type ExitCoder interface {
|
||||||
|
@ -44,11 +48,11 @@ type ExitCoder interface {
|
||||||
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
|
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
|
||||||
type ExitError struct {
|
type ExitError struct {
|
||||||
exitCode int
|
exitCode int
|
||||||
message string
|
message interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewExitError makes a new *ExitError
|
// NewExitError makes a new *ExitError
|
||||||
func NewExitError(message string, exitCode int) *ExitError {
|
func NewExitError(message interface{}, exitCode int) *ExitError {
|
||||||
return &ExitError{
|
return &ExitError{
|
||||||
exitCode: exitCode,
|
exitCode: exitCode,
|
||||||
message: message,
|
message: message,
|
||||||
|
@ -58,7 +62,7 @@ func NewExitError(message string, exitCode int) *ExitError {
|
||||||
// Error returns the string message, fulfilling the interface required by
|
// Error returns the string message, fulfilling the interface required by
|
||||||
// `error`
|
// `error`
|
||||||
func (ee *ExitError) Error() string {
|
func (ee *ExitError) Error() string {
|
||||||
return ee.message
|
return fmt.Sprintf("%v", ee.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExitCode returns the exit code, fulfilling the interface required by
|
// ExitCode returns the exit code, fulfilling the interface required by
|
||||||
|
@ -70,7 +74,7 @@ func (ee *ExitError) ExitCode() int {
|
||||||
// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
|
// 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
|
// 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
|
// given exit code. If the given error is a MultiError, then this func is
|
||||||
// called on all members of the Errors slice.
|
// called on all members of the Errors slice and calls OsExiter with the last exit code.
|
||||||
func HandleExitCoder(err error) {
|
func HandleExitCoder(err error) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
|
@ -78,21 +82,34 @@ func HandleExitCoder(err error) {
|
||||||
|
|
||||||
if exitErr, ok := err.(ExitCoder); ok {
|
if exitErr, ok := err.(ExitCoder); ok {
|
||||||
if err.Error() != "" {
|
if err.Error() != "" {
|
||||||
fmt.Fprintln(ErrWriter, err)
|
if _, ok := exitErr.(ErrorFormatter); ok {
|
||||||
|
fmt.Fprintf(ErrWriter, "%+v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintln(ErrWriter, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
OsExiter(exitErr.ExitCode())
|
OsExiter(exitErr.ExitCode())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if multiErr, ok := err.(MultiError); ok {
|
if multiErr, ok := err.(MultiError); ok {
|
||||||
for _, merr := range multiErr.Errors {
|
code := handleMultiError(multiErr)
|
||||||
HandleExitCoder(merr)
|
OsExiter(code)
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if err.Error() != "" {
|
|
||||||
fmt.Fprintln(ErrWriter, err)
|
func handleMultiError(multiErr MultiError) int {
|
||||||
}
|
code := 1
|
||||||
OsExiter(1)
|
for _, merr := range multiErr.Errors {
|
||||||
|
if multiErr2, ok := merr.(MultiError); ok {
|
||||||
|
code = handleMultiError(multiErr2)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintln(ErrWriter, merr)
|
||||||
|
if exitErr, ok := merr.(ExitCoder); ok {
|
||||||
|
code = exitErr.ExitCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return code
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,24 +3,24 @@ package cli
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultPlaceholder = "value"
|
const defaultPlaceholder = "value"
|
||||||
|
|
||||||
// BashCompletionFlag enables bash-completion for all commands and subcommands
|
// BashCompletionFlag enables bash-completion for all commands and subcommands
|
||||||
var BashCompletionFlag = BoolFlag{
|
var BashCompletionFlag Flag = BoolFlag{
|
||||||
Name: "generate-bash-completion",
|
Name: "generate-bash-completion",
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// VersionFlag prints the version for the application
|
// VersionFlag prints the version for the application
|
||||||
var VersionFlag = BoolFlag{
|
var VersionFlag Flag = BoolFlag{
|
||||||
Name: "version, v",
|
Name: "version, v",
|
||||||
Usage: "print the version",
|
Usage: "print the version",
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ var VersionFlag = BoolFlag{
|
||||||
// HelpFlag prints the help for all commands and subcommands
|
// HelpFlag prints the help for all commands and subcommands
|
||||||
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
|
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
|
||||||
// unless HideHelp is set to true)
|
// unless HideHelp is set to true)
|
||||||
var HelpFlag = BoolFlag{
|
var HelpFlag Flag = BoolFlag{
|
||||||
Name: "help, h",
|
Name: "help, h",
|
||||||
Usage: "show help",
|
Usage: "show help",
|
||||||
}
|
}
|
||||||
|
@ -62,13 +62,29 @@ type Flag interface {
|
||||||
GetName() string
|
GetName() string
|
||||||
}
|
}
|
||||||
|
|
||||||
func flagSet(name string, flags []Flag) *flag.FlagSet {
|
// 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)
|
set := flag.NewFlagSet(name, flag.ContinueOnError)
|
||||||
|
|
||||||
for _, f := range flags {
|
for _, f := range flags {
|
||||||
f.Apply(set)
|
//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
|
return set, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func eachName(longName string, fn func(string)) {
|
func eachName(longName string, fn func(string)) {
|
||||||
|
@ -87,13 +103,22 @@ type Generic interface {
|
||||||
|
|
||||||
// Apply takes the flagset and calls Set on the generic flag with the value
|
// Apply takes the flagset and calls Set on the generic flag with the value
|
||||||
// provided by the user for parsing by the flag
|
// provided by the user for parsing by the flag
|
||||||
|
// Ignores parsing errors
|
||||||
func (f GenericFlag) Apply(set *flag.FlagSet) {
|
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
|
val := f.Value
|
||||||
if f.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
val.Set(envVal)
|
if err := val.Set(envVal); err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,9 +127,11 @@ func (f GenericFlag) Apply(set *flag.FlagSet) {
|
||||||
eachName(f.Name, func(name string) {
|
eachName(f.Name, func(name string) {
|
||||||
set.Var(f.Value, name, f.Usage)
|
set.Var(f.Value, name, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringSlice is an opaque type for []string to satisfy flag.Value
|
// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter
|
||||||
type StringSlice []string
|
type StringSlice []string
|
||||||
|
|
||||||
// Set appends the string value to the list of values
|
// Set appends the string value to the list of values
|
||||||
|
@ -123,16 +150,29 @@ func (f *StringSlice) Value() []string {
|
||||||
return *f
|
return *f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
|
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.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
newVal := &StringSlice{}
|
newVal := &StringSlice{}
|
||||||
for _, s := range strings.Split(envVal, ",") {
|
for _, s := range strings.Split(envVal, ",") {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
newVal.Set(s)
|
if err := newVal.Set(s); err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
f.Value = newVal
|
f.Value = newVal
|
||||||
break
|
break
|
||||||
|
@ -146,9 +186,11 @@ func (f StringSliceFlag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Var(f.Value, name, f.Usage)
|
set.Var(f.Value, name, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntSlice is an opaque type for []int to satisfy flag.Value
|
// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter
|
||||||
type IntSlice []int
|
type IntSlice []int
|
||||||
|
|
||||||
// Set parses the value into an integer and appends it to the list of values
|
// Set parses the value into an integer and appends it to the list of values
|
||||||
|
@ -171,18 +213,28 @@ func (f *IntSlice) Value() []int {
|
||||||
return *f
|
return *f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
|
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.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
newVal := &IntSlice{}
|
newVal := &IntSlice{}
|
||||||
for _, s := range strings.Split(envVal, ",") {
|
for _, s := range strings.Split(envVal, ",") {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
err := newVal.Set(s)
|
if err := newVal.Set(s); err != nil {
|
||||||
if err != nil {
|
return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err)
|
||||||
fmt.Fprintf(ErrWriter, err.Error())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.Value = newVal
|
f.Value = newVal
|
||||||
|
@ -197,9 +249,11 @@ func (f IntSliceFlag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Var(f.Value, name, f.Usage)
|
set.Var(f.Value, name, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int64Slice is an opaque type for []int to satisfy flag.Value
|
// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter
|
||||||
type Int64Slice []int64
|
type Int64Slice []int64
|
||||||
|
|
||||||
// Set parses the value into an integer and appends it to the list of values
|
// Set parses the value into an integer and appends it to the list of values
|
||||||
|
@ -222,18 +276,28 @@ func (f *Int64Slice) Value() []int64 {
|
||||||
return *f
|
return *f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
|
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.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
newVal := &Int64Slice{}
|
newVal := &Int64Slice{}
|
||||||
for _, s := range strings.Split(envVal, ",") {
|
for _, s := range strings.Split(envVal, ",") {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
err := newVal.Set(s)
|
if err := newVal.Set(s); err != nil {
|
||||||
if err != nil {
|
return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err)
|
||||||
fmt.Fprintf(ErrWriter, err.Error())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.Value = newVal
|
f.Value = newVal
|
||||||
|
@ -248,19 +312,33 @@ func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Var(f.Value, name, f.Usage)
|
set.Var(f.Value, name, f.Usage)
|
||||||
})
|
})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f BoolFlag) Apply(set *flag.FlagSet) {
|
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 {
|
||||||
val := false
|
val := false
|
||||||
if f.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
envValBool, err := strconv.ParseBool(envVal)
|
if envVal == "" {
|
||||||
if err == nil {
|
val = false
|
||||||
val = envValBool
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
envValBool, err := strconv.ParseBool(envVal)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
val = envValBool
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,20 +351,35 @@ func (f BoolFlag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Bool(name, val, f.Usage)
|
set.Bool(name, val, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f BoolTFlag) Apply(set *flag.FlagSet) {
|
func (f BoolTFlag) Apply(set *flag.FlagSet) {
|
||||||
|
f.ApplyWithError(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyWithError populates the flag given the flag set and environment
|
||||||
|
func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error {
|
||||||
val := true
|
val := true
|
||||||
if f.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
envValBool, err := strconv.ParseBool(envVal)
|
if envVal == "" {
|
||||||
if err == nil {
|
val = false
|
||||||
val = envValBool
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
envValBool, err := strconv.ParseBool(envVal)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
val = envValBool
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,14 +391,22 @@ func (f BoolTFlag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Bool(name, val, f.Usage)
|
set.Bool(name, val, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f StringFlag) Apply(set *flag.FlagSet) {
|
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.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
f.Value = envVal
|
f.Value = envVal
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -319,19 +420,28 @@ func (f StringFlag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.String(name, f.Value, f.Usage)
|
set.String(name, f.Value, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f IntFlag) Apply(set *flag.FlagSet) {
|
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.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
f.Value = int(envValInt)
|
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
f.Value = int(envValInt)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,19 +453,29 @@ func (f IntFlag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Int(name, f.Value, f.Usage)
|
set.Int(name, f.Value, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f Int64Flag) Apply(set *flag.FlagSet) {
|
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.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
f.Value = envValInt
|
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.Value = envValInt
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,19 +487,29 @@ func (f Int64Flag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Int64(name, f.Value, f.Usage)
|
set.Int64(name, f.Value, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f UintFlag) Apply(set *flag.FlagSet) {
|
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.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
f.Value = uint(envValInt)
|
return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.Value = uint(envValInt)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -391,19 +521,29 @@ func (f UintFlag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Uint(name, f.Value, f.Usage)
|
set.Uint(name, f.Value, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f Uint64Flag) Apply(set *flag.FlagSet) {
|
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.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
f.Value = uint64(envValInt)
|
return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.Value = uint64(envValInt)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,19 +555,29 @@ func (f Uint64Flag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Uint64(name, f.Value, f.Usage)
|
set.Uint64(name, f.Value, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f DurationFlag) Apply(set *flag.FlagSet) {
|
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.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
envValDuration, err := time.ParseDuration(envVal)
|
envValDuration, err := time.ParseDuration(envVal)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
f.Value = envValDuration
|
return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.Value = envValDuration
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,18 +589,29 @@ func (f DurationFlag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Duration(name, f.Value, f.Usage)
|
set.Duration(name, f.Value, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
// Apply populates the flag given the flag set and environment
|
||||||
|
// Ignores errors
|
||||||
func (f Float64Flag) Apply(set *flag.FlagSet) {
|
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.EnvVar != "" {
|
if f.EnvVar != "" {
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||||
envVar = strings.TrimSpace(envVar)
|
envVar = strings.TrimSpace(envVar)
|
||||||
if envVal := os.Getenv(envVar); envVal != "" {
|
if envVal, ok := syscall.Getenv(envVar); ok {
|
||||||
envValFloat, err := strconv.ParseFloat(envVal, 10)
|
envValFloat, err := strconv.ParseFloat(envVal, 10)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
f.Value = float64(envValFloat)
|
return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.Value = float64(envValFloat)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,12 +623,15 @@ func (f Float64Flag) Apply(set *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
set.Float64(name, f.Value, f.Usage)
|
set.Float64(name, f.Value, f.Usage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func visibleFlags(fl []Flag) []Flag {
|
func visibleFlags(fl []Flag) []Flag {
|
||||||
visible := []Flag{}
|
visible := []Flag{}
|
||||||
for _, flag := range fl {
|
for _, flag := range fl {
|
||||||
if !flagValue(flag).FieldByName("Hidden").Bool() {
|
field := flagValue(flag).FieldByName("Hidden")
|
||||||
|
if !field.IsValid() || !field.Bool() {
|
||||||
visible = append(visible, flag)
|
visible = append(visible, flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -560,9 +724,8 @@ func stringifyFlag(f Flag) string {
|
||||||
|
|
||||||
needsPlaceholder := false
|
needsPlaceholder := false
|
||||||
defaultValueString := ""
|
defaultValueString := ""
|
||||||
val := fv.FieldByName("Value")
|
|
||||||
|
|
||||||
if val.IsValid() {
|
if val := fv.FieldByName("Value"); val.IsValid() {
|
||||||
needsPlaceholder = true
|
needsPlaceholder = true
|
||||||
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
|
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
|
||||||
|
|
||||||
|
|
|
@ -232,6 +232,13 @@ def _write_altsrc_flag_types(outfile, types):
|
||||||
f.set = set
|
f.set = set
|
||||||
f.{name}Flag.Apply(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))
|
""".format(**typedef))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
// cli.go uses text/template to render templates. You can
|
// cli.go uses text/template to render templates. You can
|
||||||
// render custom help text by setting this variable.
|
// render custom help text by setting this variable.
|
||||||
var AppHelpTemplate = `NAME:
|
var AppHelpTemplate = `NAME:
|
||||||
{{.Name}} - {{.Usage}}
|
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
|
||||||
|
|
||||||
USAGE:
|
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}}
|
{{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}}
|
||||||
|
@ -47,7 +47,7 @@ var CommandHelpTemplate = `NAME:
|
||||||
{{.HelpName}} - {{.Usage}}
|
{{.HelpName}} - {{.Usage}}
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}}
|
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}}
|
||||||
|
|
||||||
CATEGORY:
|
CATEGORY:
|
||||||
{{.Category}}{{end}}{{if .Description}}
|
{{.Category}}{{end}}{{if .Description}}
|
||||||
|
@ -64,10 +64,10 @@ OPTIONS:
|
||||||
// cli.go uses text/template to render templates. You can
|
// cli.go uses text/template to render templates. You can
|
||||||
// render custom help text by setting this variable.
|
// render custom help text by setting this variable.
|
||||||
var SubcommandHelpTemplate = `NAME:
|
var SubcommandHelpTemplate = `NAME:
|
||||||
{{.HelpName}} - {{.Usage}}
|
{{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}}
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
|
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}
|
||||||
|
|
||||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||||
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
||||||
|
@ -112,17 +112,42 @@ var helpSubcommand = Command{
|
||||||
// Prints help for the App or Command
|
// Prints help for the App or Command
|
||||||
type helpPrinter func(w io.Writer, templ string, data interface{})
|
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
|
// HelpPrinter is a function that writes the help output. If not set a default
|
||||||
// is used. The function signature is:
|
// is used. The function signature is:
|
||||||
// func(w io.Writer, templ string, data interface{})
|
// func(w io.Writer, templ string, data interface{})
|
||||||
var HelpPrinter helpPrinter = printHelp
|
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
|
// VersionPrinter prints the version for the App
|
||||||
var VersionPrinter = printVersion
|
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.
|
// ShowAppHelp is an action that displays the help.
|
||||||
func ShowAppHelp(c *Context) error {
|
func ShowAppHelp(c *Context) (err error) {
|
||||||
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +163,12 @@ func DefaultAppComplete(c *Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
// ShowCommandHelp prints help for the given command
|
||||||
func ShowCommandHelp(ctx *Context, command string) error {
|
func ShowCommandHelp(ctx *Context, command string) error {
|
||||||
// show the subcommand help for a command with subcommands
|
// show the subcommand help for a command with subcommands
|
||||||
|
@ -148,7 +179,11 @@ func ShowCommandHelp(ctx *Context, command string) error {
|
||||||
|
|
||||||
for _, c := range ctx.App.Commands {
|
for _, c := range ctx.App.Commands {
|
||||||
if c.HasName(command) {
|
if c.HasName(command) {
|
||||||
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
|
if c.CustomHelpTemplate != "" {
|
||||||
|
HelpPrinterCustom(ctx.App.Writer, c.CustomHelpTemplate, c, nil)
|
||||||
|
} else {
|
||||||
|
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,10 +226,15 @@ func ShowCommandCompletions(ctx *Context, command string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printHelp(out io.Writer, templ string, data interface{}) {
|
func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) {
|
||||||
funcMap := template.FuncMap{
|
funcMap := template.FuncMap{
|
||||||
"join": strings.Join,
|
"join": strings.Join,
|
||||||
}
|
}
|
||||||
|
if customFunc != nil {
|
||||||
|
for key, value := range customFunc {
|
||||||
|
funcMap[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0)
|
w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0)
|
||||||
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
|
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
|
||||||
|
@ -210,10 +250,14 @@ func printHelp(out io.Writer, templ string, data interface{}) {
|
||||||
w.Flush()
|
w.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printHelp(out io.Writer, templ string, data interface{}) {
|
||||||
|
printHelpCustom(out, templ, data, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func checkVersion(c *Context) bool {
|
func checkVersion(c *Context) bool {
|
||||||
found := false
|
found := false
|
||||||
if VersionFlag.Name != "" {
|
if VersionFlag.GetName() != "" {
|
||||||
eachName(VersionFlag.Name, func(name string) {
|
eachName(VersionFlag.GetName(), func(name string) {
|
||||||
if c.GlobalBool(name) || c.Bool(name) {
|
if c.GlobalBool(name) || c.Bool(name) {
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
|
@ -224,8 +268,8 @@ func checkVersion(c *Context) bool {
|
||||||
|
|
||||||
func checkHelp(c *Context) bool {
|
func checkHelp(c *Context) bool {
|
||||||
found := false
|
found := false
|
||||||
if HelpFlag.Name != "" {
|
if HelpFlag.GetName() != "" {
|
||||||
eachName(HelpFlag.Name, func(name string) {
|
eachName(HelpFlag.GetName(), func(name string) {
|
||||||
if c.GlobalBool(name) || c.Bool(name) {
|
if c.GlobalBool(name) || c.Bool(name) {
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
|
@ -252,20 +296,43 @@ func checkSubcommandHelp(c *Context) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkCompletions(c *Context) bool {
|
func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) {
|
||||||
if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion {
|
if !a.EnableBashCompletion {
|
||||||
ShowCompletions(c)
|
return false, arguments
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
pos := len(arguments) - 1
|
||||||
|
lastArg := arguments[pos]
|
||||||
|
|
||||||
|
if lastArg != "--"+BashCompletionFlag.GetName() {
|
||||||
|
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 {
|
func checkCommandCompletions(c *Context, name string) bool {
|
||||||
if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
|
if !c.shellComplete {
|
||||||
ShowCommandCompletions(c, name)
|
return false
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
ShowCommandCompletions(c, name)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,7 +321,7 @@ github.com/syndtr/goleveldb/leveldb/util
|
||||||
github.com/tinylib/msgp/msgp
|
github.com/tinylib/msgp/msgp
|
||||||
# github.com/tstranex/u2f v1.0.0
|
# github.com/tstranex/u2f v1.0.0
|
||||||
github.com/tstranex/u2f
|
github.com/tstranex/u2f
|
||||||
# github.com/urfave/cli v0.0.0-20161102131801-d86a009f5e13
|
# github.com/urfave/cli v1.20.0
|
||||||
github.com/urfave/cli
|
github.com/urfave/cli
|
||||||
# github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621
|
# github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621
|
||||||
github.com/willf/bitset
|
github.com/willf/bitset
|
||||||
|
|
Loading…
Reference in New Issue