grinが便利なのでPythonのオプションパーサオブジェクトからZshCompletionFunctionを自動で生成するモジュールを作ってみた

reddit経由で grin というソース検索コマンドがあるのを知りました。 Perlでは ack 、Rubyでは rak というのがあります。

ack,rak,grinを使うと見やすい表示や色付き表示でgrepのような単語検索を行うことができます。 私は自称Pythonistaですので、Python実装であるところのgrinを応援することにします。

で、grinはコマンドオプションが結構あるのですが、Pythonで実装しているので うまくオプションパーサオブジェクトからZsh補完関数を自動で生成できないかな、と。 いろいろなページを参考に genzshcomp モジュールを作って見ました。

Zsh補完関数を生成する擬似コードは以下のような感じです。

from genzshcomp import ZshCompletionGenerator
generator = ZshCompletionGenerator(command_name,
                                   python_option_parser_object)
print generator.get()

コマンドの名前を第1引数に、 オプション設定した(していなくてもよいですが)パーサオブジェクトを第2引数に指定して ジェネレータを生成し、get()メソッドでZsh補完関数の文字列を返却します。

grinで実際に生成するコードは以下になります。

from grin import get_grin_arg_parser
from genzshcomp import ZshCompletionGenerator

if __name__ == '__main__':
    generator = ZshCompletionGenerator("grin",
                                       get_grin_arg_parser())
    print generator.get()

で、実際のZsh補完関数は以下です。

#compdef grin

typeset -A opt_args
local context state line

_arguments -s -S \
  "-h[show this help message and exit]::_files -/" \
  "--help[show this help message and exit]::_files -/" \
  "-v[show program's version number and exit]::_files -/" \
  "--version[show program's version number and exit]::_files -/" \
  "-i[ignore case in the regex]::_files -/" \
  "--ignore-case[ignore case in the regex]::_files -/" \
                                 :
  "-0[filenames specified in --files-from-file are separated by NULs]::_files -/" \
  "--null-separated[filenames specified in --files-from-file are separated by NULs]::_files -/" \
  ":files:->files" \
  && return 0
case $state in
(files)
  _files -/ && return 0
  ;;
esac

まだまだ改善点がありますが、Python使いなZsh使いな人はぜひ使ってみてください。

(自家製Mercurialリポジトリだとsshなpushとかで不便なので、bitbucket使うことにしました。)