はじめに
GoでCLIツール作るのにフレームワークとして spf13/cobra が便利なのでよく使ってます。
そんなcobraですが、よく見るとbash/zsh補完スクリプトの自動生成が意外と簡単にできることに気づいたので、やり方を共有しておきます。
環境
手元の環境は以下のとおりです。
- macOS 10.14
- zsh 5.3
- bash 3.2
- Go 1.12
- cobra 0.05
補完スクリプトを生成するコマンドを生やす
completionというサブコマンドを生やして、その下にさらにbashとzshコマンドを生やします。
イメージとしてはこんなかんじ。ここではコマンド名を hoge
とします。
hoge completion bash
hoge completion zsh
コードはこんなかんじ。
package cmd
import (
"os"
"github.com/spf13/cobra"
)
func init() {
RootCmd.AddCommand(newCompletionCmd())
}
func newCompletionCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "completion",
Short: "Generates shell completion scripts",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
cmd.AddCommand(
newCompletionBashCmd(),
newCompletionZshCmd(),
)
return cmd
}
func newCompletionBashCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "bash",
Short: "Generates bash completion scripts",
Run: func(cmd *cobra.Command, args []string) {
RootCmd.GenBashCompletion(os.Stdout)
},
}
return cmd
}
func newCompletionZshCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "zsh",
Short: "Generates zsh completion scripts",
Run: func(cmd *cobra.Command, args []string) {
RootCmd.GenZshCompletion(os.Stdout)
},
}
return cmd
}
補完スクリプトを読み込む
生成されるスクリプト自体は、とりあえず標準出力に垂れ流してあるので、zshならfpathが通ってる適当なところに保存します。
Homebrewでzsh-completionsを使ってる場合、 /usr/local/share/zsh/site-functions/_hoge
に保存しておけば自動で読み込まれます。
$ hoge completion zsh > /usr/local/share/zsh/site-functions/_hoge
普段zsh使ってるのでbashはあんまり良くわかってませんが、Homebrewのbash-completionを使ってる場合は、 /usr/local/etc/bash_completion.d/hoge
に置いておけば良さそうです。
HomebrewのFormulaで自動インストールする
CLIツール自体を既にHomebrewで配布している場合は、バイナリのインストール時に自動で補完スクリプトも仕込んであるとうれしいですね。
あらかじめリポジトリにコミットしてあるファイルを配布するだけなら、 単純に zsh_completion.install
とかでいけるっぽいのです。が、動的に生成したファイルを登録する方法がわからず、ちょっと悩みました。
そういえば kubectl
もcobraだったなと思い出し、 kubectlのformula を参考に、こんなかんじにしておけば良さそうです。
class Hoge < Formula
desc "Hoge"
homepage "https://github.com/minamijoyo/hoge"
url "https://github.com/minamijoyo/hoge/releases/download/v0.0.1/hoge_v0.0.1_darwin_amd64.tar.gz"
version "0.0.1"
sha256 "xxxxxx"
def install
bin.install "hoge"
output = Utils.popen_read("#{bin}/hoge completion bash")
(bash_completion/"hoge").write output
output = Utils.popen_read("#{bin}/hoge completion zsh")
(zsh_completion/"_hoge").write output
end
end
おわりに
cobraのドキュメントを見ると、もうちょっとカスタマイズできるっぽいのですが、まだいろいろ発展途上のようです。
Generating Zsh Completion for your cobra.Command
ただTabでサブコマンドや引数の補完が出るだけでも十分快適です。
わりと簡単に実装できてコスパがよいので、cobraで自作のCLIツール作ってる人は補完できるようにしてみるとよいんではなかろうか。