【Golang】spf13/cobraが提供する入力補完(shell completion)をファイル形式でインストールする方法【bash, zsh, fish】
前書き:spf13/cobraのシェル補完は便利
本記事は、spf13/cobraが提供する「シェル補完(文字列)」をファイルとしてシステムにインストールする例を紹介します。今回の例を実践すると、cobraを用いたCLIコマンドでシェル補完が有効になります。ここでのシェル補完とは、ターミナルでコマンド入力中に[TAB]キーを押すと、自動で単語を補完する機能です。
対象シェルは、bash、zsh、fishです。PowerShellは、私が詳しくないので除外します。
cobraは、Golang用のCLIコマンド作成補助ライブラリです。代表的な機能は、CLIコマンド実行時にオプション/サブコマンドが指定されたかどうかを判定する機能です。cobraを使用した場合、自動的にcompletionサブコマンドが追加され(例:以下に示すposixerコマンドのhelp参照)、このサブコマンドはシェル補完用の文字列を出力します。
自動追加されるcompletionサブコマンドのイケてない部分は、出力された文字列をどのように扱えば良いのかがサッパリ分からないことです。恐らく、「ユーザーがシェル補完(文字列)をファイル化して、システムにインストールしてください」が期待値だと考えています。
しかし、ユーザーにコマンドを使ってもらう観点からは、ユーザーに手作業を強いるよりも、「CLIコマンドが自動でシェル補完ファイルをシステムにインストール」した方が利便性が高いです。
そこで、本記事では「シェル補完ファイルのインストール先」を示し、シェル補完ファイルインストールの実装例を示します。
検証環境
Ubuntu21.10、golang version 1.18、spf13/cobra v1.4.0で検証しました。
シェル補完ファイルの出力先
シェル補完ファイルは、シェル毎に格納先が異なります。格納先は大別して、「OS内の全ユーザーが参照できる場所(例:/etc以下 や /usr/local/share以下)」と「特定のユーザーのみが参照できる場所(例:$HOME以下)」の2種類があります。
今回の例では、一般ユーザーがCLIコマンドを実行した場合を想定しているため、シェル補完ファイルをユーザーホームディレクトリ以下にインストールします。全ユーザー向けにインストールしたい場合は、以下に示す参考情報(リンク)を調べてください。以下、特定ユーザー向けのインストール先です。
- bashの場合:$HOME/.bash_completion
- 複数のコマンドの入力補完情報が格納されるファイルのため、編集時に注意が必要
- 参考情報
- fishの場合 :$HOME/.config/fish/completions/${cmd_name}.fish
- zshの場合 :$HOME/.zsh/completion/_${cmd_name}
デフォルトのzshでは、シェル補完ファイル格納先がユーザーホームディレクトリ以下に存在しません。そこで、zshがシェル補完ファイルの格納先を$fpathで管理している事を利用します。具体的には、.zshrcを編集して、$fpathに”$HOME/.zsh/completion”を追加します。
シェル補完ファイル作成の流れ
シェル補完ファイルの作成は、CLIコマンドの起動直後(cmd/root.go Execute()内)で実行します。詳細な処理は後述しますが、大まかな流れは以下のとおりです。
- completionサブコマンドをdisable(使用不可)に変更
- ユーザーが明示的にcompletionサブコマンドを使用しなくなるため
- シェル補完ファイルを必要であれば生成する関数を実行(詳細を後述)
- シェル補完ファイルが既に存在するか
- 「cobraが生成するシェル補完の内容」と「システムに存在するシェル補完ファイル内容」が一致するか
- 上記2点を満たさない場合は、シェル補完ファイルを生成
- cobraのrootコマンドを実行
シェル補完ファイル作成の実例
シェル補完ファイルの作成は、最も面倒なzsh用シェル補完ファイル作成の例だけ示します。bash、fish用の作成例を知りたい方は、GitHub上に実例をアップしているのでそちらをご確認ください。
まずは、シェル補完ファイル作成の実処理を説明する前に、ヘルパー関数(下請け的な関数)を示します。ここでの重要な処理は、”isSameZshCompletionContent()”内で「cobraが生成するシェル補完」と「システムに存在するシェル補完ファイルの内容」を比較する部分です。ここでの比較が一致しなければ、シェル補完ファイルの作成が必要と判断します。
次に、シェル補完ファイルの作成関数を示します。処理を以下の順で実施します。
- シェル補完ファイルが既に最新の場合は、シェル補完ファイルの作成処理をスキップ(①)
- シェル補完ファイルを作成する前に、格納先ディレクトリを作成(②)
- cobraが提供する関数を用いて、シェル補完ファイルを作成(③)
- 必要であれば、.zshrcにシェル補完ファイルの格納先情報を追記(④)
最後に
cobraがシェル補完ファイル作成関数を提供している事から、cobra開発者は「completionサブコマンドを開発者が作り込む事」を期待している気がします。個人的な意見としては、作り込む必要のあるサブコマンドをデフォルトで有効にしない方が好ましいのでは、と思ってしまいます。
今回の例では、ユーザーの負担を減らすために自動でシェル補完ファイル作成や.zshrc追記を実施しています。しかし、ユーザーによっては「勝手にファイルを追加・編集しないで欲しい」という方も居る筈です。そのため、本記事の例は参考実装程度に留めてください。
ロシア人と国際結婚した地方エンジニア。
小学〜大学院、就職の全てが新潟。
大学の専攻は福祉工学だったのに、エンジニアとして就職。新卒入社した会社ではOS開発や半導体露光装置ソフトを開発。現在はサーバーサイドエンジニアとして修行中。HR/HM(メタル)とロシア妻が好き。サイトに関するお問い合わせやTwitterフォローは、お気軽にどうぞ。
1件の返信
[…] […]