やっぱtabで補完だよね

某sym**nyに負けじと、ethnaでも _ethna() を書いてみるテスト。

さいきん2ちゃんでシェルスクリプト総合スレみたいなのを読んでいて、もう一歩ステップアップな気分になり、補完関数書いてみようと思い立ったわけですが、正直かなりむずい。というより必要な知識の方向がだいぶ違った。

まずは

を眺めるわけですが、 %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ダサくないですか?

今後の発展は?

ほんとは、各コマンドごとにそのあとの引数は種類が変わるわけですよね(add-view -tとか)。存在するアクションの一覧を取得するとか、そこまでやりたくはないし、sym**nyみたいにガリガリ書き並べちゃっても良かったような気がしてきた。

ethnaコマンドのusageの出力を食べる(svn方式)ほうがいいかなぁ。svnlook的な、シンプルな出力を簡単に呼び出せればいいんだけれど。