From 92b70c79c103fee33cd4151ec83c9e9c9abf9207 Mon Sep 17 00:00:00 2001 From: Roberto Hidalgo Date: Mon, 25 Nov 2019 17:38:28 -0500 Subject: [PATCH] fix shell completion after update to urfave/cli@2.0.0 Depends on urfave/cli#946 --- Makefile | 7 ++++++ bin/autocomplete/completion.bash | 2 +- bin/autocomplete/completion.zsh | 28 ++++++++++++--------- cmd/autocomplete/autocomplete.go | 36 +++++++++++++++++++++++---- cmd/autocomplete/autocomplete_test.go | 2 +- 5 files changed, 56 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 6e5287c..2f2a763 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,13 @@ BUILD_HOST := $(shell uname -s | tr '[[:upper:]]' '[[:lower:]]') BINARY := dist/$(BUILD_HOST)/go-config-yourself export GO111MODULE=on +complete: build-local + mv dist/local/gcy dist/local/asdf + rm /usr/local/share/zsh/site-functions/_asdf || true + cp bin/autocomplete/completion.zsh /usr/local/share/zsh/site-functions/_asdf + rm ~/.zcompdump* + #now run rehash && compinit + # -------------- # Dev setup # -------------- diff --git a/bin/autocomplete/completion.bash b/bin/autocomplete/completion.bash index b37ea0f..4340310 100644 --- a/bin/autocomplete/completion.bash +++ b/bin/autocomplete/completion.bash @@ -4,7 +4,7 @@ _cli_bash_autocomplete() { local cur opts; COMPREPLY=(); cur="${COMP_WORDS[COMP_CWORD]}"; - opts=$( CUR=$cur ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-completion ); + opts=$( CUR=$cur ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion ); COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ); return 0; }; diff --git a/bin/autocomplete/completion.zsh b/bin/autocomplete/completion.zsh index bbbb45a..b84a26f 100644 --- a/bin/autocomplete/completion.zsh +++ b/bin/autocomplete/completion.zsh @@ -1,17 +1,21 @@ #compdef gcy +#autoload # shellcheck shell=bash -autoload -U compinit && compinit; -autoload -U bashcompinit && bashcompinit; -_cli_bash_autocomplete() { - local cur opts; - COMPREPLY=(); - cur="${COMP_WORDS[COMP_CWORD]}"; - opts=$( CUR="$cur" "${COMP_WORDS[@]:0:$COMP_CWORD}" --generate-completion ); - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ); - return 0; -}; +_gcy_zsh_autocomplete () { -_gcy () { - complete -o nospace -o default -F _cli_bash_autocomplete gcy + local -a opts + opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} --generate-bash-completion)}") + + exit_code="$?" + if [[ $exit_code -gt 0 ]]; then + _path_files + [[ $exit_code == 1 ]]; return + fi + + _describe 'gcy' opts + + return } + +compdef _gcy_zsh_autocomplete gcy diff --git a/cmd/autocomplete/autocomplete.go b/cmd/autocomplete/autocomplete.go index f841a1d..f3ec757 100644 --- a/cmd/autocomplete/autocomplete.go +++ b/cmd/autocomplete/autocomplete.go @@ -21,10 +21,15 @@ func CommandAutocomplete(ctx *cli.Context) { } for _, cmd := range ctx.App.VisibleCommands() { - if strings.HasPrefix(cmd.Name, firstArg) { - fmt.Println(cmd.Name) + if firstArg == "" || strings.HasPrefix(cmd.Name, firstArg) { + if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" { + fmt.Printf("%s:%s\n", cmd.Name, cmd.Usage) + } else { + fmt.Println(cmd.Name) + } } } + os.Exit(0) } //ListKeys lists keys at a given keypath @@ -91,22 +96,43 @@ func ListProviderFlags(ctx *cli.Context) (keepGoing bool) { // ListAllFlags all possible flags func ListAllFlags(ctx *cli.Context) { var flags []cli.Flag - if ctx.Command != nil { + if ctx.Command != nil && ctx.Command.Name != "" { flags = ctx.Command.VisibleFlags() } else { flags = ctx.App.VisibleFlags() } + isZSH := os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") for _, f := range flags { name := f.Names()[0] if name == "init-completion" { continue } + description := "" + if isZSH == "1" { + switch typedFlag := f.(type) { + case *cli.StringFlag: + description = typedFlag.Usage + case *cli.BoolFlag: + description = typedFlag.Usage + case *cli.GenericFlag: + description = typedFlag.Usage + case *cli.StringSliceFlag: + description = typedFlag.Usage + default: + log.Warningf("%s: %T", name, typedFlag) + } + } + _, isRepeatable := f.(*cli.StringSliceFlag) if isRepeatable || !ctx.IsSet(name) { - fmt.Println(fmt.Sprintf("--%s", name)) + if isZSH == "1" { + fmt.Println(fmt.Sprintf("--%s:%s", name, description)) + } else { + fmt.Println(fmt.Sprintf("--%s", name)) + } } } } @@ -139,7 +165,7 @@ func LastFlagIs(flagName string) (query string, ok bool) { func validArgs() (validArgs []string) { for _, arg := range os.Args { - if arg == "--" || arg == "--generate-completion" { + if arg == "--" || arg == "--generate-bash-completion" { break } diff --git a/cmd/autocomplete/autocomplete_test.go b/cmd/autocomplete/autocomplete_test.go index 4d3bbc1..366be10 100644 --- a/cmd/autocomplete/autocomplete_test.go +++ b/cmd/autocomplete/autocomplete_test.go @@ -27,7 +27,7 @@ func TestCommandAutoComplete(t *testing.T) { comp.CommandAutocomplete(fx.MockCliCtx(nil)) output := mockedStdOut() options := strings.Split(output, "\n") - expected := []string{"command", ""} + expected := []string{"--verbose", "--version", "command", ""} if !diff.Equal(options, expected) { t.Fatalf("Invalid output, got: %v, expected %v", options, expected)