会社でコードを書いていると、いろんなプロジェクトのディレクトリ間を頻繁に移動します。毎回cdするのはだるいので、それを解消する便利なzsh用の関数と補完関数を書いたので紹介します。はてなのエンジニアのひとと、zsh補完関数を書いてみたい人にはそこそこ役立つといった趣のエントリです。
会社のプロジェクトのリポジトリは、~/work/hatena というところに全部まとめています。だいたい以下のような感じです。
>ls ~/work/hatenaHatena-Antenna/ Hatena-Diary/ Hatena-Ugomemo/ git-hooks/Hatena-Bookmark/ Hatena-Group/ Ridge/ iphone/Hatena-Coco/ Hatena-Star/ android/ sketch/
各プロジェクトのリポジトリには頻繁に移動するので、簡単なzsh関数を作って使っています。
function h {cd ~/work/hatena/$1}
h Hatena-Bookmarkのようにすれば、各プロジェクトにcdできて便利です。しかし、毎回、Hatena-Bookmarkとか打つのは面倒な感じです。なので、zshの補完関数を作ってみました。
h [TAB]と入力すると、以下のように表示されます。

はてなの多くのプロジェクトのリポジトリの名前はHatena-から始まるので、その後の部分だけで補完できるようになっています。たとえばh b[TAB]と入力するとh Hatena-Bookmarkに補完できます。
以下のgistを.zshrcのcompinit以降にべたっとはって、パスを調整すれば使えるようになりますので、はてなのエンジニアのみなさまははどうぞご利用ください。
Hatena-Project zsh completion · GitHub
上記の関数を完成させるまでに試行錯誤をしたので、途中でうまれた補完関数を紹介します。
補完関数を書くための支援関数である_filesを使って ~/work/hatena 以下を全部補完します
function _h { _files -W ~/work/hatena/ &&return0;return1;}
普通はだいたいこれで間に合う気がするのですが、プロジェクトのディレクトリに移動するにはHatena-がじゃまで、何度もTABを入力する必要があってめんどくさい感じです。
補完候補を登録する関数であるcompaddを直接使います。_filesなどの支援関数は内部でcompaddを呼んでいます。この関数は高機能で引数のprefixやsuffixを指定できたりします。
function_h {# プロジェクトっぽいディレクトリを配列に格納local-a projectsprojects=($(find ~/work/hatena/* -type d -maxdepth0 -exec basename'{}'';'|grep'^Hatena-'|sed -e's/^Hatena-//') )# 'Hatena-' prefix付きで補完候補に登録 compadd-P'Hatena-'$projectsreturn1;}
-P 'Hatena-'のように指定しておくと、補完した結果にprefixをつけてくれます。b[TAB]と入力してBookmarkを補完すると、結果としてHatena-Bookmarkが得られます。
しかし、このままだと、Hatena-ではじまらないディレクトリが補完できません。二回にわけてcompaddしても良いのですが、二種類の補完候補が混ざってしまいます。
最終形です。_describeをつかえば、タグで補完候補をまとめつつ、説明をつけて補完候補を登録できます。内部で呼ばれているcompadd関数に引数を直接わたすこともできます。
function_h {local allfileslocal-a _projects _othersallfiles=`find ~/work/hatena/* -type d -maxdepth0 -exec basename'{}'';'`# projects というタグで補完候補をまとめつつ# "Projects" という descriptionをつけて# _projects 内の値を補完候補に登録する# compadd に渡るときに "-P Hatena-" オプションをつける_projects=($(echo$allfiles|grep'^Hatena-'|sed -e's/^Hatena-//') ) _describe-t projects"Projects" _projects-P Hatena- #Projects と同様だが compadd にオプションはつけない_others=($(echo$allfiles|grep -v'^Hatena-') ) _describe-t others"Others" _othersreturn1;}
という感じで求める補完関数にたどりつきました。
弊社内では便利な関数と補完関数について紹介しました。
説明した関数以外にも、条件に応じて補完を制御できる_arguments関数や、コマンドの実行結果をキャッシュできる_store_cacheなど便利(だけど使い方が難しい)関数がそろっています。PerlとかRubyで適当に値のリストをつくって登録するだけでもそこそこ便利なので、気軽に作って見ると良いと思います。
man zshcompsys: 補完についての全体について説明されています。_describe や_filesの解説はこのマニュアルに記載されています。man zshcompwid: よりローレベルな補完の仕組みについて説明されています。compaddの解説はここに記載されています。$fpath: zshの補完関数の実態が置かれています。manページはリファレンスには使えますが、どういうときにどの関数を使うかはあんまりわかんないので、実例を読むのが良いと思います。引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。