某sym**nyに負けじと、ethnaでも _ethna() を書いてみるテスト。
さいきん2ちゃんでシェルスクリプト総合スレみたいなのを読んでいて、もう一歩ステップアップな気分になり、補完関数書いてみようと思い立ったわけですが、正直かなりむずい。というより必要な知識の方向がだいぶ違った。
まずは
- http://www.ayu.ics.keio.ac.jp/members/mukai/translate/write_zsh_functions.html
- http://catbot.net/blog/2006/02/symfonyzsh.html
を眺めるわけですが、 %s/sym**ny/ethna/g だけじゃあダサいし、かといってちゃんと理解して書くにはすごい時間かかりそうだし。
man zshallと、すでにある関数を眺めつつ適当にコピペでなんとかならないかなー、といろいろ。
補完関数のサンプル
/usr/share/zsh/4.?.?/functions/Completion 以下にあった、なんかしら特徴のありそうなものは以下のとおり。
- _sudo: すごいシンプル
- _apt-get, _aptitude: command, subcommand式のサンプルになりそう
- _ant, _make: ファイルの内容で補完内容が変化する
- _subversion: ディレクトリ・ファイルを眺めて補完内容が変化する
- _ssh: remfilesとか、かなり複雑だけど、ssh, slogin, scpなどをまとめて書いている例
つーか読めません。man zshparam, man zshexpnを全部理解しないとこんなの理解できませんよ。
仕様を考える
ethnaコマンドは "ethna add-hoge fuga" みたいなコマンドラインをとり、コマンド "add-hoge" の部分は $ETHNA_HOME/class/Handle/Ethna_Handler_AddHoge.php というハンドラ(のファイル名)によって決まります。なので、とりあえずは勝手にこのディレクトリを眺めて、適当な "add-hoge" を表示してくれればいいや、と思いました。
Ethna_HandleManger::_getIdFromFile()によると、正規表現でがんばってファイル名からコマンド名に置換すればよいらしいのですが、zsh組み込みでは正規表現は使えるんだか良く分かりません。sedを使っている例があったので、それでいいことにする。
あと、バージョンはとりあえず出したいですよね。
とりあえず動いた
つーことでとりあえず書いてみたのが、次のようなもの。typesetとかは必要なのか良くわかんない。それいがいはsym**nyとほとんど同じ。
#compdef ethna _ethna() { local curcontext="$curcontext" state line expl ret=1 typeset -a handles handles=( ${(L)$( \ echo ${ETHNA_HOME}/class/Handle/Ethna_Handle_*.php(N:t) \ | sed -e "s/Ethna_Handle_Manager\.php//; \ s/Ethna_Handle_\([A-Za-z]\+\)\.php/\1/g; \ s/\([A-Z]\)/-\1/g; \ s/\(^\| \)-/\1/g;" \ )} ) _arguments -C \ '(-v --version)'{-v,--version}'[show version]' \ '*::ethna command:->ethna-commands' \ && ret=0 if [[ -n "$state" ]]; then if (( CURRENT == 1 )); then _wanted commands expl 'ethna command' compadd -a handles && ret=0 fi fi return ret }
sedダサくないですか?