Merge branch 'master' into flag-type-generation-golang
This commit is contained in:
commit
24de27b05e
4
.github/CODEOWNERS
vendored
Normal file
4
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# See https://help.github.com/articles/about-codeowners/
|
||||||
|
# for more info about CODEOWNERS file
|
||||||
|
|
||||||
|
* @urfave/cli
|
29
CHANGELOG.md
29
CHANGELOG.md
@ -4,7 +4,28 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
## 1.20.0 - 2017-08-10
|
## [1.21.0] - 2019-08-02
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fix using "slice" flag types with `EnvVar` in [urfave/cli/pull/687](https://github.com/urfave/cli/pull/687) via [@joshuarubin](https://github.com/joshuarubin)
|
||||||
|
* Fix regression of `SkipFlagParsing` behavior in [urfave/cli/pull/697](https://github.com/urfave/cli/pull/697) via [@jszwedko](https://github.com/jszwedko)
|
||||||
|
* Fix handling `ShortOptions` and `SkipArgReorder` in [urfave/cli/pull/686](https://github.com/urfave/cli/pull/686) via [@baude](https://github.com/baude)
|
||||||
|
* Fix args reordering when bool flags are present in [urfave/cli/pull/712](https://github.com/urfave/cli/pull/712) via [@windler](https://github.com/windler)
|
||||||
|
* Fix parsing of short options in [urfave/cli/pull/758](https://github.com/urfave/cli/pull/758) via [@vrothberg](https://github.com/vrothberg)
|
||||||
|
|
||||||
|
### Added / Changed
|
||||||
|
|
||||||
|
* Added _"required flags"_ support in [urfave/cli/pull/819](https://github.com/urfave/cli/pull/819) via [@lynncyrin](https://github.com/lynncyrin/)
|
||||||
|
* Cleaned up help output in [urfave/cli/pull/664](https://github.com/urfave/cli/pull/664) via [@maguro](https://github.com/maguro)
|
||||||
|
* Case is now considered when sorting strings in [urfave/cli/pull/676](https://github.com/urfave/cli/pull/676) via [@rliebz](https://github.com/rliebz)
|
||||||
|
* Backport JSON `InputSource` to v1 in [urfave/cli/pull/598](https://github.com/urfave/cli/pull/598) via [@jszwedko](https://github.com/jszwedko)
|
||||||
|
* Allow more customization of flag help strings in [urfave/cli/pull/661](https://github.com/urfave/cli/pull/661) via [@rliebz](https://github.com/rliebz)
|
||||||
|
* Allow custom `ExitError` handler function in [urfave/cli/pull/628](https://github.com/urfave/cli/pull/628) via [@phinnaeus](https://github.com/phinnaeus)
|
||||||
|
* Allow loading a variable from a file in [urfave/cli/pull/675](https://github.com/urfave/cli/pull/675) via [@jmccann](https://github.com/jmccann)
|
||||||
|
* Allow combining short bool names in [urfave/cli/pull/684](https://github.com/urfave/cli/pull/684) via [@baude](https://github.com/baude)
|
||||||
|
|
||||||
|
## [1.20.0] - 2017-08-10
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
@ -407,7 +428,11 @@ signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
|
|||||||
### Added
|
### Added
|
||||||
- Initial implementation.
|
- Initial implementation.
|
||||||
|
|
||||||
[Unreleased]: https://github.com/urfave/cli/compare/v1.18.0...HEAD
|
[Unreleased]: https://github.com/urfave/cli/compare/v1.21.0...HEAD
|
||||||
|
[1.21.0]: https://github.com/urfave/cli/compare/v1.20.0...v1.21.0
|
||||||
|
[1.20.0]: https://github.com/urfave/cli/compare/v1.19.1...v1.20.0
|
||||||
|
[1.19.1]: https://github.com/urfave/cli/compare/v1.19.0...v1.19.1
|
||||||
|
[1.19.0]: https://github.com/urfave/cli/compare/v1.18.0...v1.19.0
|
||||||
[1.18.0]: https://github.com/urfave/cli/compare/v1.17.0...v1.18.0
|
[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.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.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
**NOTE**: the primary maintainer(s) may be found in
|
Use @urfave/cli to ping the maintainers.
|
||||||
[./MAINTAINERS.md](./MAINTAINERS.md).
|
|
||||||
|
|
||||||
Feel free to put up a pull request to fix a bug or maybe add a feature. I will
|
Feel free to put up a pull request to fix a bug or maybe add a feature. We will
|
||||||
give it a code review and make sure that it does not break backwards
|
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
|
compatibility. If collaborators agree that it is in line with
|
||||||
the vision of the project, we will work with you to get the code into
|
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.
|
a mergeable state and merge it into the master branch.
|
||||||
|
|
||||||
@ -15,5 +14,5 @@ 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.
|
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
|
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 :sweat_smile:. Please open an
|
as a collaborator, we probably forgot to add you :sweat_smile:. Please open an
|
||||||
issue!
|
issue!
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
- @meatballhat
|
|
||||||
- @lynncyrin
|
|
||||||
- @AudriusButkevicius
|
|
||||||
- @asahasrabuddhe
|
|
@ -679,6 +679,7 @@ from other file input sources.
|
|||||||
|
|
||||||
Currently supported input source formats:
|
Currently supported input source formats:
|
||||||
* YAML
|
* YAML
|
||||||
|
* JSON
|
||||||
* TOML
|
* TOML
|
||||||
|
|
||||||
In order to get values for a flag from an alternate input source the following
|
In order to get values for a flag from an alternate input source the following
|
||||||
@ -701,7 +702,7 @@ 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
|
the "load" flag used would also have to be defined on the command flags in order
|
||||||
for this code snipped to work.
|
for this code snipped to work.
|
||||||
|
|
||||||
Currently only YAML and JSON files are supported but developers can add support
|
Currently only YAML, JSON, and TOML files are supported but developers can add support
|
||||||
for other input sources by implementing the altsrc.InputSourceContext for their
|
for other input sources by implementing the altsrc.InputSourceContext for their
|
||||||
given sources.
|
given sources.
|
||||||
|
|
||||||
@ -901,14 +902,14 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
cli.BoolTFlag{
|
cli.BoolFlag{
|
||||||
Name: "ginger-crouton",
|
Name: "ginger-crouton",
|
||||||
Usage: "is it in the soup?",
|
Usage: "Add ginger croutons to the soup",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
app.Action = func(ctx *cli.Context) error {
|
app.Action = func(ctx *cli.Context) error {
|
||||||
if !ctx.Bool("ginger-crouton") {
|
if !ctx.Bool("ginger-crouton") {
|
||||||
return cli.NewExitError("it is not in the soup", 86)
|
return cli.NewExitError("Ginger croutons are not in the soup", 86)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
83
app_test.go
83
app_test.go
@ -221,6 +221,89 @@ func ExampleApp_Run_subcommandNoAction() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleApp_Run_bashComplete_withShortFlag() {
|
||||||
|
os.Args = []string{"greet", "-", "--generate-bash-completion"}
|
||||||
|
|
||||||
|
app := NewApp()
|
||||||
|
app.Name = "greet"
|
||||||
|
app.EnableBashCompletion = true
|
||||||
|
app.Flags = []Flag{
|
||||||
|
IntFlag{
|
||||||
|
Name: "other,o",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "xyz,x",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Run(os.Args)
|
||||||
|
// Output:
|
||||||
|
// --other
|
||||||
|
// -o
|
||||||
|
// --xyz
|
||||||
|
// -x
|
||||||
|
// --help
|
||||||
|
// -h
|
||||||
|
// --version
|
||||||
|
// -v
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleApp_Run_bashComplete_withLongFlag() {
|
||||||
|
os.Args = []string{"greet", "--s", "--generate-bash-completion"}
|
||||||
|
|
||||||
|
app := NewApp()
|
||||||
|
app.Name = "greet"
|
||||||
|
app.EnableBashCompletion = true
|
||||||
|
app.Flags = []Flag{
|
||||||
|
IntFlag{
|
||||||
|
Name: "other,o",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "xyz,x",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "some-flag,s",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "similar-flag",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Run(os.Args)
|
||||||
|
// Output:
|
||||||
|
// --some-flag
|
||||||
|
// --similar-flag
|
||||||
|
}
|
||||||
|
func ExampleApp_Run_bashComplete_withMultipleLongFlag() {
|
||||||
|
os.Args = []string{"greet", "--st", "--generate-bash-completion"}
|
||||||
|
|
||||||
|
app := NewApp()
|
||||||
|
app.Name = "greet"
|
||||||
|
app.EnableBashCompletion = true
|
||||||
|
app.Flags = []Flag{
|
||||||
|
IntFlag{
|
||||||
|
Name: "int-flag,i",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "string,s",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "string-flag-2",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "similar-flag",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "some-flag",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Run(os.Args)
|
||||||
|
// Output:
|
||||||
|
// --string
|
||||||
|
// --string-flag-2
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleApp_Run_bashComplete() {
|
func ExampleApp_Run_bashComplete() {
|
||||||
// set args for examples sake
|
// set args for examples sake
|
||||||
os.Args = []string{"greet", "--generate-bash-completion"}
|
os.Args = []string{"greet", "--generate-bash-completion"}
|
||||||
|
@ -3,14 +3,19 @@
|
|||||||
: ${PROG:=$(basename ${BASH_SOURCE})}
|
: ${PROG:=$(basename ${BASH_SOURCE})}
|
||||||
|
|
||||||
_cli_bash_autocomplete() {
|
_cli_bash_autocomplete() {
|
||||||
|
if [[ "${COMP_WORDS[0]}" != "source" ]]; then
|
||||||
local cur opts base
|
local cur opts base
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
|
if [[ "$cur" == "-"* ]]; then
|
||||||
|
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-bash-completion )
|
||||||
|
else
|
||||||
|
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
|
||||||
|
fi
|
||||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||||
return 0
|
return 0
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
complete -F _cli_bash_autocomplete $PROG
|
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete $PROG
|
||||||
|
|
||||||
unset PROG
|
unset PROG
|
||||||
|
85
help.go
85
help.go
@ -7,6 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AppHelpTemplate is the text template for the Default help topic.
|
// AppHelpTemplate is the text template for the Default help topic.
|
||||||
@ -157,22 +158,91 @@ func ShowAppHelp(c *Context) (err error) {
|
|||||||
|
|
||||||
// DefaultAppComplete prints the list of subcommands as the default app completion method
|
// DefaultAppComplete prints the list of subcommands as the default app completion method
|
||||||
func DefaultAppComplete(c *Context) {
|
func DefaultAppComplete(c *Context) {
|
||||||
for _, command := range c.App.Commands {
|
DefaultCompleteWithFlags(nil)(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printCommandSuggestions(commands []Command, writer io.Writer) {
|
||||||
|
for _, command := range commands {
|
||||||
if command.Hidden {
|
if command.Hidden {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" {
|
if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" {
|
||||||
for _, name := range command.Names() {
|
for _, name := range command.Names() {
|
||||||
fmt.Fprintf(c.App.Writer, "%s:%s\n", name, command.Usage)
|
fmt.Fprintf(writer, "%s:%s\n", name, command.Usage)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, name := range command.Names() {
|
for _, name := range command.Names() {
|
||||||
fmt.Fprintf(c.App.Writer, "%s\n", name)
|
fmt.Fprintf(writer, "%s\n", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cliArgContains(flagName string) bool {
|
||||||
|
for _, name := range strings.Split(flagName, ",") {
|
||||||
|
name = strings.TrimSpace(name)
|
||||||
|
count := utf8.RuneCountInString(name)
|
||||||
|
if count > 2 {
|
||||||
|
count = 2
|
||||||
|
}
|
||||||
|
flag := fmt.Sprintf("%s%s", strings.Repeat("-", count), name)
|
||||||
|
for _, a := range os.Args {
|
||||||
|
if a == flag {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) {
|
||||||
|
cur := strings.TrimPrefix(lastArg, "-")
|
||||||
|
cur = strings.TrimPrefix(cur, "-")
|
||||||
|
for _, flag := range flags {
|
||||||
|
if bflag, ok := flag.(BoolFlag); ok && bflag.Hidden {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, name := range strings.Split(flag.GetName(), ",") {
|
||||||
|
name = strings.TrimSpace(name)
|
||||||
|
// this will get total count utf8 letters in flag name
|
||||||
|
count := utf8.RuneCountInString(name)
|
||||||
|
if count > 2 {
|
||||||
|
count = 2 // resuse this count to generate single - or -- in flag completion
|
||||||
|
}
|
||||||
|
// if flag name has more than one utf8 letter and last argument in cli has -- prefix then
|
||||||
|
// skip flag completion for short flags example -v or -x
|
||||||
|
if strings.HasPrefix(lastArg, "--") && count == 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// match if last argument matches this flag and it is not repeated
|
||||||
|
if strings.HasPrefix(name, cur) && cur != name && !cliArgContains(flag.GetName()) {
|
||||||
|
flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name)
|
||||||
|
fmt.Fprintln(writer, flagCompletion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultCompleteWithFlags(cmd *Command) func(c *Context) {
|
||||||
|
return func(c *Context) {
|
||||||
|
if len(os.Args) > 2 {
|
||||||
|
lastArg := os.Args[len(os.Args)-2]
|
||||||
|
if strings.HasPrefix(lastArg, "-") {
|
||||||
|
printFlagSuggestions(lastArg, c.App.Flags, c.App.Writer)
|
||||||
|
if cmd != nil {
|
||||||
|
printFlagSuggestions(lastArg, cmd.Flags, c.App.Writer)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cmd != nil {
|
||||||
|
printCommandSuggestions(cmd.Subcommands, c.App.Writer)
|
||||||
|
} else {
|
||||||
|
printCommandSuggestions(c.App.Commands, c.App.Writer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ShowCommandHelpAndExit - exits with code after showing help
|
// ShowCommandHelpAndExit - exits with code after showing help
|
||||||
func ShowCommandHelpAndExit(c *Context, command string, code int) {
|
func ShowCommandHelpAndExit(c *Context, command string, code int) {
|
||||||
ShowCommandHelp(c, command)
|
ShowCommandHelp(c, command)
|
||||||
@ -231,9 +301,14 @@ func ShowCompletions(c *Context) {
|
|||||||
// ShowCommandCompletions prints the custom completions for a given command
|
// ShowCommandCompletions prints the custom completions for a given command
|
||||||
func ShowCommandCompletions(ctx *Context, command string) {
|
func ShowCommandCompletions(ctx *Context, command string) {
|
||||||
c := ctx.App.Command(command)
|
c := ctx.App.Command(command)
|
||||||
if c != nil && c.BashComplete != nil {
|
if c != nil {
|
||||||
c.BashComplete(ctx)
|
if c.BashComplete != nil {
|
||||||
|
c.BashComplete(ctx)
|
||||||
|
} else {
|
||||||
|
DefaultCompleteWithFlags(c)(ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) {
|
func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) {
|
||||||
|
Loading…
Reference in New Issue
Block a user