Skip to content

Commit

Permalink
Updates completion system to current version suggested by cobra.
Browse files Browse the repository at this point in the history
This adds completions for fish and powershell and shows the descriptions for commands and flags.
  • Loading branch information
chr-fritz committed Mar 14, 2021
1 parent 8ace9a8 commit 8056325
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 367 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,4 @@ buildDeps:
completions:
rm -rf completions
mkdir completions
for sh in bash zsh; do go run main.go completion "$$sh" >"completions/minikube-support.$$sh"; done
for sh in bash zsh fish ps1; do go run main.go completion "$$sh" >"completions/$(NAME).$$sh"; done
244 changes: 47 additions & 197 deletions cmd/completion.go
Original file line number Diff line number Diff line change
@@ -1,227 +1,77 @@
package cmd

import (
"bytes"
"io"
"os"

"github.com/pkg/errors"
"github.com/spf13/cobra"
)

var (
completionShells = map[string]func(out io.Writer, cmd *cobra.Command) error{
"bash": runCompletionBash,
"zsh": runCompletionZsh,
}
)

// NewCmdCompletion creates the `completion` command
func NewCompletionCmd() *cobra.Command {
shells := []string{}
for s := range completionShells {
shells = append(shells, s)
}

cmd := &cobra.Command{
Use: "completion SHELL",
DisableFlagsInUseLine: true,
Short: "Output shell completion code for the specified shell (bash or zsh)",

RunE: func(cmd *cobra.Command, args []string) error {
return RunCompletion(os.Stdout, cmd, args)
},
ValidArgs: shells,
}

return cmd
}

// RunCompletion checks given arguments and executes command
func RunCompletion(out io.Writer, cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("Shell not specified.")
}
if len(args) > 1 {
return errors.New("Too many arguments. Expected only the shell type.")
}
run, found := completionShells[args[0]]
if !found {
return errors.Errorf("Unsupported shell type %q.", args[0])
}
Use: "completion [bash|zsh|fish|powershell]",
Short: "Generate completion script",
Long: `To load completions:
return run(out, cmd.Parent())
}
Bash:
func runCompletionBash(out io.Writer, cmd *cobra.Command) error {
return cmd.GenBashCompletion(out)
}
$ source <(minikube-support completion bash)
func runCompletionZsh(out io.Writer, cmd *cobra.Command) error {
zshHead := "#compdef minikube-support\n"
# To load completions for each session, execute once:
# Linux:
$ minikube-support completion bash > /etc/bash_completion.d/minikube-support
# macOS:
$ minikube-support completion bash > /usr/local/etc/bash_completion.d/minikube-support
_, e := out.Write([]byte(zshHead))
if e != nil {
return e
}
Zsh:
zshInitialization := `
__minikube-support_bash_source() {
alias shopt=':'
alias _expand=_bash_expand
alias _complete=_bash_comp
emulate -L sh
setopt kshglob noshglob braceexpand
# If shell completion is not already enabled in your environment,
# you will need to enable it. You can execute the following once:
source "$@"
}
$ echo "autoload -U compinit; compinit" >> ~/.zshrc
__minikube-support_type() {
# -t is not supported by zsh
if [ "$1" == "-t" ]; then
shift
# fake Bash 4 to disable "complete -o nospace". Instead
# "compopt +-o nospace" is used in the code to toggle trailing
# spaces. We don't support that, but leave trailing spaces on
# all the time
if [ "$1" = "__minikube-support_compopt" ]; then
echo builtin
return 0
fi
fi
type "$@"
}
# To load completions for each session, execute once:
$ minikube-support completion zsh > "${fpath[1]}/_minikube-support"
__minikube-support_compgen() {
local completions w
completions=( $(compgen "$@") ) || return $?
# filter by given word as prefix
while [[ "$1" = -* && "$1" != -- ]]; do
shift
shift
done
if [[ "$1" == -- ]]; then
shift
fi
for w in "${completions[@]}"; do
if [[ "${w}" = "$1"* ]]; then
echo "${w}"
fi
done
}
# You will need to start a new shell for this setup to take effect.
__minikube-support_compopt() {
true # don't do anything. Not supported by bashcompinit in zsh
}
fish:
__minikube-support_ltrim_colon_completions()
{
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
# Remove colon-word prefix from COMPREPLY items
local colon_word=${1%${1##*:}}
local i=${#COMPREPLY[*]}
while [[ $((--i)) -ge 0 ]]; do
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
done
fi
}
$ minikube-support completion fish | source
__minikube-support_get_comp_words_by_ref() {
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[${COMP_CWORD}-1]}"
words=("${COMP_WORDS[@]}")
cword=("${COMP_CWORD[@]}")
}
# To load completions for each session, execute once:
$ minikube-support completion fish > ~/.config/fish/completions/minikube-support.fish
__minikube-support_filedir() {
local RET OLD_IFS w qw
__minikube-support_debug "_filedir $@ cur=$cur"
if [[ "$1" = \~* ]]; then
# somehow does not work. Maybe, zsh does not call this at all
eval echo "$1"
return 0
fi
OLD_IFS="$IFS"
IFS=$'\n'
if [ "$1" = "-d" ]; then
shift
RET=( $(compgen -d) )
else
RET=( $(compgen -f) )
fi
IFS="$OLD_IFS"
IFS="," __minikube-support_debug "RET=${RET[@]} len=${#RET[@]}"
for w in ${RET[@]}; do
if [[ ! "${w}" = "${cur}"* ]]; then
continue
fi
if eval "[[ \"\${w}\" = *.$1 || -d \"\${w}\" ]]"; then
qw="$(__minikube-support_quote "${w}")"
if [ -d "${w}" ]; then
COMPREPLY+=("${qw}/")
else
COMPREPLY+=("${qw}")
fi
fi
done
}
PowerShell:
__minikube-support_quote() {
if [[ $1 == \'* || $1 == \"* ]]; then
# Leave out first character
printf %q "${1:1}"
else
printf %q "$1"
fi
}
PS> minikube-support completion powershell | Out-String | Invoke-Expression
autoload -U +X bashcompinit && bashcompinit
# use word boundary patterns for BSD or GNU sed
LWORD='[[:<:]]'
RWORD='[[:>:]]'
if sed --help 2>&1 | grep -q GNU; then
LWORD='\<'
RWORD='\>'
fi
__minikube-support_convert_bash_to_zsh() {
sed \
-e 's/declare -F/whence -w/' \
-e 's/_get_comp_words_by_ref "\$@"/_get_comp_words_by_ref "\$*"/' \
-e 's/local \([a-zA-Z0-9_]*\)=/local \1; \1=/' \
-e 's/flags+=("\(--.*\)=")/flags+=("\1"); two_word_flags+=("\1")/' \
-e 's/must_have_one_flag+=("\(--.*\)=")/must_have_one_flag+=("\1")/' \
-e "s/${LWORD}_filedir${RWORD}/__minikube-support_filedir/g" \
-e "s/${LWORD}_get_comp_words_by_ref${RWORD}/__minikube-support_get_comp_words_by_ref/g" \
-e "s/${LWORD}__ltrim_colon_completions${RWORD}/__minikube-support_ltrim_colon_completions/g" \
-e "s/${LWORD}compgen${RWORD}/__minikube-support_compgen/g" \
-e "s/${LWORD}compopt${RWORD}/__minikube-support_compopt/g" \
-e "s/${LWORD}declare${RWORD}/builtin declare/g" \
-e "s/\\\$(type${RWORD}/\$(__minikube-support_type/g" \
<<'BASH_COMPLETION_EOF'
`
_, _ = out.Write([]byte(zshInitialization))
buf := new(bytes.Buffer)
e = cmd.GenBashCompletion(buf)
if e != nil {
return e
# To load completions for every new session, run:
PS> minikube-support completion powershell > minikube-support.ps1
# and source this file from your PowerShell profile.
`,
DisableFlagsInUseLine: true,
ValidArgs: []string{"bash", "zsh", "fish", "powershell", "ps1"},
Args: cobra.ExactValidArgs(1),
Run: func(cmd *cobra.Command, args []string) {
switch args[0] {
case "bash":
_ = cmd.Root().GenBashCompletion(os.Stdout)
case "zsh":
_ = cmd.Root().GenZshCompletion(os.Stdout)
case "fish":
_ = cmd.Root().GenFishCompletion(os.Stdout, true)
case "powershell":
fallthrough
case "ps1":
_ = cmd.Root().GenPowerShellCompletion(os.Stdout)
}
},
}
_, _ = out.Write(buf.Bytes())

zshTail := `
BASH_COMPLETION_EOF
return cmd
}

__minikube-support_bash_source <(__minikube-support_convert_bash_to_zsh)
_complete minikube-support 2>/dev/null
`
_, _ = out.Write([]byte(zshTail))
return nil
func init() {
rootCmd.AddCommand(NewCompletionCmd())
}
86 changes: 0 additions & 86 deletions cmd/completion_test.go

This file was deleted.

8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ require (
github.com/spf13/cobra v1.1.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.6.1
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect
golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 // indirect
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect
golang.org/x/text v0.3.5 // indirect
google.golang.org/genproto v0.0.0-20210106152847-07624b53cd92 // indirect
google.golang.org/grpc v1.34.0
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506 // indirect
google.golang.org/grpc v1.35.0
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/api v0.20.2
Expand Down
Loading

0 comments on commit 8056325

Please sign in to comment.