MAGAZINE
ルーターマガジン
自作タブ補完入門~sshコマンドのタブ補完で複数のconfigファイルのホストを表示する~
こんにちは、エンジニアのitogaです。
非常事態宣言の中みなさんの開発の進捗も滞っていることと思います。利用するCLIツールが増えるにつれて、こんなタブ補完があったら良いなぁと思いを馳せる頃でしょうか。今回は自作タブ補完の入門として、sshコマンドのタブ補完で複数のconfigファイルのホストを表示することを目標に進めていきます。
せっかちな人向けの、複数configファイルに対応したsshコマンドのタブ補完
以下のgrep対象のディレクトリパスを環境に合わせて変えたものをログインシェルに追記してあげてください。
_ssh()
{
local opts
opts=$(grep '^Host ' ~/.ssh/config ~/.ssh/conf.d/* 2>/dev/null | grep -v '[?*]' | cut -d ' ' -f 2-)
COMPREPLY=( $(compgen -W "${opts}" -- "${COMP_WORDS[${COMP_CWORD}]}") )
}
complete -F _ssh ssh
まずは、complete関数でタブ補完を触ってみる
早速sshコマンドのタブ補完をいじってみましょう。まず、変数COMPREPLYに配列を定義する関数を定義します。
$ _dummy_ssh() { COMPREPLY=(apple orange apricot); }
次に、この関数をcomplete関数の-Fオプションに渡し、タブ補完するコマンド名sshを末尾に記載し実行します。
$ complete -F _dummy_ssh ssh
そして、sshコマンドのタブ補完を試してみると無事変更できたことが確認できます。
$ ssh
apple apricot orange
補完対象を絞り込み
現状だと、途中まで入力した状態でタブを押しても絞り込みや入力まではされません。それを実現するためにはCOMP_CWORD、COMP_WORDSという変数とcompgenという関数を使います。
COMP_CWORDとCOMP_WORDS
$ _dummy_ssh()
{
echo
echo COMP_CWORD: ${COMP_CWORD}
echo COMP_WORDS: ${COMP_WORDS[@]}
echo PREV_WORDS: ${COMP_WORDS[${COMP_CWORD}-1]}
}
COMP_CWORDは入力中の語句のインデックス番号、COMP_WORDSは入力中のコマンド全体の語句の配列になっています。
$ ssh first sec
COMP_CWORD: 2
COMP_WORDS: ssh first sec
PREV_WORDS: first
compgen
compgen関数は、与えられた文字列のリストに対して前方一致する文字列のみを返す関数です。
$ compgen -W "apple orange apricot" --
apple
orange
apricot
$ compgen -W "apple orange apricot" -- a
apple
apricot
$ compgen -W "apple orange apricot" -- app
apple
タブ補完で補完対象を絞り込み
compgenとCOMP_CWORD、COMP_WORDSを組み合わせて以下のような関数をcomplete関数に渡します。
$ _dummy_ssh()
{
local opts
opts="apple orange apricot"
COMPREPLY=( $(compgen -W "${opts}" -- "${COMP_WORDS[${COMP_CWORD}]}") )
}
すると、親の顔より見慣れたタブ補完を実装できます。
$ ssh a
# タブを押す
$ ssh ap
# タブを2回押す
$ ssh ap
apple apricot
$ ssh app
# タブを押す
$ ssh apple
sshコマンドのタブ補完で複数のconfigファイルのホストを表示する
あとは、grep,cutを駆使して補完対象リストの文字列を生成してあげるだけで実装完了!!complete関数の実行も忘れずに。
$ _ssh()
{
local opts
opts=$(grep '^Host ' ~/.ssh/config ~/.ssh/conf.d/* 2>/dev/null | grep -v '[?*]' | cut -d ' ' -f 2-)
COMPREPLY=( $(compgen -W "${opts}" -- "${COMP_WORDS[${COMP_CWORD}]}") )
}
$ complete -F _ssh ssh
おわりに
いかがでしたでしょうか。この関数の定義とcomplete関数の実行を、bash_profileなどのログインシェルに記載すればいつでもコマンド補完ができます。このCLIツール、機能としては便利だけどオプションや引数のタイプが面倒なんだよなぁ、という惜しい局面で役立ていただければ幸いです。
CONTACT
お問い合わせ・ご依頼はこちらから