From f411c042e7bb431868326f756e13fcc8fdad757a Mon Sep 17 00:00:00 2001 From: kilyanni Date: Tue, 3 Mar 2026 04:10:33 +0100 Subject: [PATCH] Add completions for fish shell --- README.md | 21 +++++++++++++++++---- app.go | 10 ++++++++++ model.go | 1 + templates.go | 12 ++++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5495ca1..fcdac5f 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ - [Default Values](#default-values) - [Place-holders in Help](#place-holders-in-help) - [Consuming all remaining arguments](#consuming-all-remaining-arguments) - - [Bash/ZSH Shell Completion](#bashzsh-shell-completion) + - [Bash/ZSH/Fish Shell Completion](#bashzshfish-shell-completion) - [Supporting -h for help](#supporting--h-for-help) - [Custom help](#custom-help) @@ -531,7 +531,7 @@ And use it like so: ips := IPList(kingpin.Arg("ips", "IP addresses to ping.")) ``` -### Bash/ZSH Shell Completion +### Bash/ZSH/Fish Shell Completion By default, all flags and commands/subcommands generate completions internally. @@ -548,8 +548,9 @@ for your target platform/shell). An alternative is to instruct your end user to source a script from their `bash_profile` (or equivalent). Fortunately Kingpin makes it easy to generate or source a script for use -with end users shells. `./yourtool --completion-script-bash` and -`./yourtool --completion-script-zsh` will generate these scripts for you. +with end users shells. `./yourtool --completion-script-bash`, +`./yourtool --completion-script-zsh`, and `./yourtool --completion-script-fish` +will generate these scripts for you. **Installation by Package** @@ -574,6 +575,18 @@ Or for ZSH eval "$(your-cli-tool --completion-script-zsh)" ``` +Or for fish + +``` +your-cli-tool --completion-script-fish | source +``` + +Or, to install the fish completions permanently: + +``` +your-cli-tool --completion-script-fish > ~/.config/fish/completions/your-cli-tool.fish +``` + #### Additional API To provide more flexibility, a completion option API has been exposed for flags to allow user defined completion options, to extend diff --git a/app.go b/app.go index 4f1f31b..d16b74b 100644 --- a/app.go +++ b/app.go @@ -68,6 +68,7 @@ func New(name, help string) *Application { a.Flag("completion-bash", "Output possible completions for the given args.").Hidden().BoolVar(&a.completion) a.Flag("completion-script-bash", "Generate completion script for bash.").Hidden().PreAction(a.generateBashCompletionScript).Bool() a.Flag("completion-script-zsh", "Generate completion script for ZSH.").Hidden().PreAction(a.generateZSHCompletionScript).Bool() + a.Flag("completion-script-fish", "Generate completion script for fish.").Hidden().PreAction(a.generateFishCompletionScript).Bool() return a } @@ -108,6 +109,15 @@ func (a *Application) generateZSHCompletionScript(c *ParseContext) error { return nil } +func (a *Application) generateFishCompletionScript(c *ParseContext) error { + a.Writer(os.Stdout) + if err := a.UsageForContextWithTemplate(c, 2, FishCompletionTemplate); err != nil { + return err + } + a.terminate(0) + return nil +} + // DefaultEnvars configures all flags (that do not already have an associated // envar) to use a default environment variable in the form "_". // diff --git a/model.go b/model.go index 382616c..6e98687 100644 --- a/model.go +++ b/model.go @@ -16,6 +16,7 @@ var ( "completion-bash": true, "completion-script-bash": true, "completion-script-zsh": true, + "completion-script-fish": true, } ) diff --git a/templates.go b/templates.go index 703c2cd..f021b37 100644 --- a/templates.go +++ b/templates.go @@ -260,3 +260,15 @@ if [[ "$(basename -- ${(%):-%x})" != "_{{.App.Name}}" ]]; then compdef _{{.App.Name}} {{.App.Name}} fi ` + +var FishCompletionTemplate = `complete -c {{.App.Name}} -f -a '( + set -l c (commandline -opc) + set -e c[1] + set -l r ({{.App.Name}} --completion-bash $c) + if test -n "$r" + echo $r + else + __fish_complete_path (commandline -ct) + end +)' +`