ページャを呼び出したいというニーズのかなり大多数がこれじゃないかって気がする。
CUI プログラムの宿命として、機能が豊富になってくるとどうしても –help の出力がデカくなってくる。特に Python の argparse の使いやすさはぱねぇので、ついつい「よろこんで」ヘルプを充実させてしまう。そしてすぐにコンソールが「溢れる」。
無論エンドユーザが自分でページャにパイプすればいいことだけれど、時折面倒くさい。特にそのスクリプトの「使い方間違い」をした際にスクリーンが溢れ、「仕方なくもう一度起動、ただし今度はページャにパイプ」というのが典型的な流れなのね。特に自分で開発途中のスクリプトなんかインターフェイスが最初は全然枯れなくて、bash のヒストリから呼び戻したものがもう最新のインターフェイスに適合してない、なんてのはヒヅネチャメシゴト。
argparse の場合は多分二つのアプローチがあるんじゃないかなと思う。一つは ArgumentParser の print_help などをリプレイスする方法、もう一つは ArgumentParser に渡す formatter=argparse.HelpFormatter をリプレイスする方法。後者も出来そうではあるけれど責務から考えれば「不適切」と思うので試みない。というかおそらくバカげたコーディングが必要だろう。
「リプレイス」は素直に ArgumentParser のサブクラスを作るんでもいいんだけれど、Run-time method patching のアプローチがコピペしやすくていいんじゃないかと思う。なわけで、明示的にユーザが –help を叩いた場合も「使い方間違い」時もいつでもページャを起動したいとするなら:
1 import argparse
2 import types
3 parser = argparse.ArgumentParser()
4 parser.print_help = types.MethodType(
5 lambda self, _=None: ???(self.format_help()), parser)
6 parser.print_usage = types.MethodType(
7 lambda self, _=None: ???(self.format_usage()), parser)
8 parser.error = types.MethodType(
9 lambda self, text: (
10 ???(text + "\n" * 2 + self.format_help()), exit(1)
11 ), parser)
みたいな感じにしたい。「???」部分がページャ起動機能だとして、たとえば文字列を受け取れると仮定しておく。あるいはやり方によっては「stream」的なものをリプレイスする必要があるのかも?
ページャそのものはどうすればいいかいね、と思ったが、調べる前に pydoc に心当たらなかったのはちょいとチョンボ。わかってたはずじゃん…。(undocumented で will not be available in the future 言うておるけれど、公開メソッドである以上はそう簡単には破棄されないハズよ。結構枯れてるし、pydoc。)
というわけで:
1 import argparse
2 import pydoc, types
3 parser = argparse.ArgumentParser()
4 parser.print_help = types.MethodType(
5 lambda self, _=None: pydoc.pager(self.format_help()), parser)
6 parser.print_usage = types.MethodType(
7 lambda self, _=None: pydoc.pager(self.format_usage()), parser)
8 parser.error = types.MethodType(
9 lambda self, text: (
10 pydoc.pager(text + "\n" * 2 + self.format_help()), exit(1)
11 ), parser)
結果的には大変シンプルで理想的。これで「スクリーンが溢れ、「仕方なくもう一度起動、ただし今度はページャにパイプ」」の手間が減る、「自分が作るものなら」。
なお Windows で MSYS あるいは cygwin ユーザなら、環境変数 PAGER に less をセットしておくとハッピーよ。