From 10a716e0a39a5a1c9e5e39e8e22b2f90b77ce448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Bia=C5=82o=C5=84?= Date: Mon, 8 Jan 2024 18:18:30 +0100 Subject: [PATCH] Install shell completions (#209) --- .gitignore | 2 + .goreleaser.yml | 12 +++++ internal/cmd/completion/bash_autocomplete | 32 +++++++++++++ internal/cmd/completion/completion.go | 56 +++++++++++++++++++++++ internal/cmd/completion/zsh_autocomplete | 20 ++++++++ main.go | 11 +++-- scripts/completions.sh | 10 ++++ 7 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 internal/cmd/completion/bash_autocomplete create mode 100644 internal/cmd/completion/completion.go create mode 100644 internal/cmd/completion/zsh_autocomplete create mode 100755 scripts/completions.sh diff --git a/.gitignore b/.gitignore index e46f4cd..5073828 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ build dist key.* *.asc + +completions diff --git a/.goreleaser.yml b/.goreleaser.yml index dbdb83f..bba81e1 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,3 +1,7 @@ +before: + hooks: + - ./scripts/completions.sh + builds: - env: - CGO_ENABLED=0 @@ -13,6 +17,10 @@ archives: # https://github.com/spacelift-io/setup-spacectl - format: zip name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + files: + - LICENSE + - README.md + - completions/* dockers: - use: buildx @@ -99,6 +107,10 @@ brews: homepage: https://github.com/spacelift-io/spacectl description: "Spacelift client and CLI" license: "MIT" + extra_install: | + bash_completion.install "completions/{{ .ProjectName }}.bash" => "{{ .ProjectName }}" + zsh_completion.install "completions/{{ .ProjectName }}.zsh" => "_{{ .ProjectName }}" + fish_completion.install "completions/{{ .ProjectName }}.fish" winget: - name: "{{ .ProjectName }}" diff --git a/internal/cmd/completion/bash_autocomplete b/internal/cmd/completion/bash_autocomplete new file mode 100644 index 0000000..f87fbb7 --- /dev/null +++ b/internal/cmd/completion/bash_autocomplete @@ -0,0 +1,32 @@ +#! /bin/bash + +# Macs have bash3 for which the bash-completion package doesn't include +# _init_completion. This is a minimal version of that function. +_cli_init_completion() { + COMPREPLY=() + _get_comp_words_by_ref "$@" cur prev words cword +} + +_cli_bash_autocomplete() { + if [[ "${COMP_WORDS[0]}" != "source" ]]; then + local cur opts base words + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + if declare -F _init_completion >/dev/null 2>&1; then + _init_completion -n "=:" || return + else + _cli_init_completion -n "=:" || return + fi + words=("${words[@]:0:$cword}") + if [[ "$cur" == "-"* ]]; then + requestComp="${words[*]} ${cur} --generate-bash-completion" + else + requestComp="${words[*]} --generate-bash-completion" + fi + opts=$(eval "${requestComp}" 2>/dev/null) + COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + return 0 + fi +} + +complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete spacectl diff --git a/internal/cmd/completion/completion.go b/internal/cmd/completion/completion.go new file mode 100644 index 0000000..b68b3fc --- /dev/null +++ b/internal/cmd/completion/completion.go @@ -0,0 +1,56 @@ +package completion + +import ( + "bytes" + _ "embed" + "io" + "os" + "strings" + + "github.com/urfave/cli/v2" +) + +var ( + //go:embed bash_autocomplete + bashAutocomplete []byte + + //go:embed zsh_autocomplete + zshAutocomplete []byte +) + +func Command() *cli.Command { + return &cli.Command{ + Name: "completion", + Usage: "Print out shell completion script", + Subcommands: []*cli.Command{ + { + Name: "bash", + Usage: "Print out bash shell completion script", + Action: func(cliCtx *cli.Context) error { + _, err := io.Copy(os.Stdout, bytes.NewReader(bashAutocomplete)) + return err + }, + }, + { + Name: "zsh", + Usage: "Print out zsh shell completion script", + Action: func(cliCtx *cli.Context) error { + _, err := io.Copy(os.Stdout, bytes.NewReader(zshAutocomplete)) + return err + }, + }, + { + Name: "fish", + Usage: "Print out fish shell completion script", + Action: func(cliCtx *cli.Context) error { + s, err := cliCtx.App.ToFishCompletion() + if err != nil { + return err + } + _, err = io.Copy(os.Stdout, strings.NewReader(s)) + return err + }, + }, + }, + } +} diff --git a/internal/cmd/completion/zsh_autocomplete b/internal/cmd/completion/zsh_autocomplete new file mode 100644 index 0000000..8d9f3a9 --- /dev/null +++ b/internal/cmd/completion/zsh_autocomplete @@ -0,0 +1,20 @@ +#compdef spacectl + +_cli_zsh_autocomplete() { + local -a opts + local cur + cur=${words[-1]} + if [[ "$cur" == "-"* ]]; then + opts=("${(@f)$(${words[@]:0:#words[@]-1} ${cur} --generate-bash-completion)}") + else + opts=("${(@f)$(${words[@]:0:#words[@]-1} --generate-bash-completion)}") + fi + + if [[ "${opts[1]}" != "" ]]; then + _describe 'values' opts + else + _files + fi +} + +compdef _cli_zsh_autocomplete spacectl diff --git a/main.go b/main.go index 34ec509..d1911fb 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "github.com/urfave/cli/v2" + "github.com/spacelift-io/spacectl/internal/cmd/completion" "github.com/spacelift-io/spacectl/internal/cmd/module" "github.com/spacelift-io/spacectl/internal/cmd/profile" "github.com/spacelift-io/spacectl/internal/cmd/provider" @@ -26,10 +27,11 @@ func main() { log.Fatalf("Could not parse compilation date: %v", err) } app := &cli.App{ - Name: "spacectl", - Version: version, - Compiled: compileTime, - Usage: "Programmatic access to Spacelift GraphQL API.", + Name: "spacectl", + Version: version, + Compiled: compileTime, + Usage: "Programmatic access to Spacelift GraphQL API.", + EnableBashCompletion: true, Commands: []*cli.Command{ module.Command(), profile.Command(), @@ -39,6 +41,7 @@ func main() { whoami.Command(), versioncmd.Command(version), workerpools.Command(), + completion.Command(), }, } diff --git a/scripts/completions.sh b/scripts/completions.sh new file mode 100755 index 0000000..96f0fdf --- /dev/null +++ b/scripts/completions.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +set -e + +rm -rf completions +mkdir completions + +for sh in bash zsh fish; do + go run main.go completion "$sh" >"completions/spacectl.$sh" +done