Skip to content

Commit

Permalink
impl
Browse files Browse the repository at this point in the history
  • Loading branch information
bartekpacia committed Oct 30, 2024
1 parent ba40dae commit 4c63582
Showing 1 changed file with 66 additions and 25 deletions.
91 changes: 66 additions & 25 deletions completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,35 @@ package cli

import (
"context"
"embed"
"fmt"
"sort"
)

const (
completionCommandName = "completion"

// This flag is supposed to only be used by the completion script itself, to generate completions on the fly.
// This flag is supposed to only be used by the completion script itself to generate completions on the fly.
completionFlagName = "generate-shell-completion"
completionFlag = "--" + completionFlagName
)

var (
//go:embed autocomplete
autoCompleteFS embed.FS

shellCompletions = map[string]renderCompletionFunc{
"bash": getCompletion("autocomplete/bash_autocomplete"),
"ps": getCompletion("autocomplete/powershell_autocomplete.ps1"),
"zsh": func(cmd *Command, appName string) (string, error) {
return genZshCompletion(appName), nil
},
"fish": func(c *Command, appName string) (string, error) {
return c.ToFishCompletion()
},
}
)
var shellCompletions = map[string]renderCompletionFunc{
"bash": func(cmd *Command, appName string) (string, error) {
return genBashCompletion(appName), nil
},
"zsh": func(cmd *Command, appName string) (string, error) {
return genZshCompletion(appName), nil
},
"fish": func(c *Command, appName string) (string, error) {
return c.ToFishCompletion()
},
"pwsh": func(cmd *Command, appName string) (string, error) {
return genPwshCompletion(), nil
},
}

type renderCompletionFunc func(cmd *Command, appName string) (string, error)

func getCompletion(s string) renderCompletionFunc {
return func(cmd *Command, appName string) (string, error) {
b, err := autoCompleteFS.ReadFile(s)
return string(b), err
}
}

func buildCompletionCommand(appName string) *Command {
return &Command{
Name: completionCommandName,
Expand Down Expand Up @@ -81,11 +72,49 @@ func printShellCompletion(_ context.Context, cmd *Command, appName string) error
return nil
}

func genBashCompletion(appName string) string {
return fmt.Sprintf(`#!/usr/env/bin bash
# This is a shell completion script auto-generated by https://github.com/urfave/cli for 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-shell-completion"
else
requestComp="${words[*]} --generate-shell-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 %[1]s
`, appName)
}

func genZshCompletion(appName string) string {
return fmt.Sprintf(`#compdef %[1]s
compdef _%[1]s %[1]s
# This is a shell completion script auto-generated by https://github.com/urfave/cli.
# This is a shell completion script auto-generated by https://github.com/urfave/cli for zsh.
_%[1]s() {
local -a opts # Declare a local array
Expand Down Expand Up @@ -113,3 +142,15 @@ if [ "$funcstack[1]" = "_%[1]s" ]; then
fi
`, appName)
}

func genPwshCompletion() string {
return fmt.Sprintf(`$fn = $($MyInvocation.MyCommand.Name)

Check failure on line 147 in completion.go

View workflow job for this annotation

GitHub Actions / staticcheck

unnecessary use of fmt.Sprintf (S1039)

Check failure on line 147 in completion.go

View workflow job for this annotation

GitHub Actions / golangci-lint

S1039: unnecessary use of fmt.Sprintf (gosimple)
$name = $fn -replace "(.*)\.ps1$", '$1'
Register-ArgumentCompleter -Native -CommandName $name -ScriptBlock {
param($commandName, $wordToComplete, $cursorPosition)
$other = "$wordToComplete --generate-shell-completion"
Invoke-Expression $other | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}`)
}

0 comments on commit 4c63582

Please sign in to comment.