diff --git a/app.go b/app.go index 290d3bb..6087d9e 100644 --- a/app.go +++ b/app.go @@ -138,6 +138,7 @@ func (a *App) Setup() { if a.EnableBashCompletion { a.appendFlag(BashCompletionFlag) + a.appendFlag(InitCompletionFlag) } if !a.HideVersion { @@ -176,6 +177,11 @@ func (a *App) Run(arguments []string) (err error) { return nil } + var done bool + if done, err = checkInitCompletion(context); done { + return nil + } + if err != nil { if a.OnUsageError != nil { err := a.OnUsageError(context, err, false) diff --git a/flag.go b/flag.go index 807c95f..ee7629e 100644 --- a/flag.go +++ b/flag.go @@ -27,6 +27,12 @@ var BashCompletionFlag = &BoolFlag{ Hidden: true, } +// InitCompletionFlag generates completion code +var InitCompletionFlag = &StringFlag{ + Name: "init-completion", + Usage: "generate completion code. Value must be 'bash' or 'zsh'", +} + // VersionFlag prints the version for the application var VersionFlag = &BoolFlag{ Name: "version", diff --git a/help.go b/help.go index 1dca46f..9a4c334 100644 --- a/help.go +++ b/help.go @@ -286,3 +286,41 @@ func checkCommandCompletions(c *Context, name string) bool { return false } + +func checkInitCompletion(c *Context) (bool, error) { + if c.IsSet(InitCompletionFlag.Name) { + shell := c.String(InitCompletionFlag.Name) + progName := os.Args[0] + switch shell { + case "bash": + fmt.Print(bashCompletionCode(progName)) + return true, nil + case "zsh": + fmt.Print(zshCompletionCode(progName)) + return true, nil + default: + return false, fmt.Errorf("--init-completion value cannot be '%s'", shell) + } + } + return false, nil +} + +func bashCompletionCode(progName string) string { + var template = `_cli_bash_autocomplete() { + local cur opts base; + COMPREPLY=(); + cur="${COMP_WORDS[COMP_CWORD]}"; + opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion ); + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ); + return 0; +}; +complete -F _cli_bash_autocomplete %s` + return fmt.Sprintf(template, progName) +} + +func zshCompletionCode(progName string) string { + var template = `autoload -U compinit && compinit; +autoload -U bashcompinit && bashcompinit;` + + return template + "\n" + bashCompletionCode(progName) +}