Major mode for Closure Templates (.soy).

Closure Tools は本当に便利なツール群です。

開発の効率化やクライアントへの丸投げ(笑)にとても貢献してくれます。

ただ、新しめの宿命なのか。こうしたツールを支援するツールというある意味再帰的なツールの少なさが玉に瑕です。私の場合、Emacs でどれだけ弄れるか?が焦点となります。


取りあえず、Library は js2-mode で。Compiler はコマンドラインで何とか凌げるのですが、Templates はさすがにちょっと...

適当に記述しては Emacs が indent-region。typo も flymake で発見などなど。とにかく Emacs 任せの生活に慣れ切ってしまうと、最低限のモードも無い状況はとてもツラいです。


Google 先生に伺っても、Emacs 向けのモードは存在しない様子。ならば!と一念発起して初のメジャーモードを書いてみることにしました。

toomore-such's soy-mode at master - GitHub こちらで公開中!

まずは目標や仕様なんぞ...

  • あまり多くを望まないこと。
    1. 仕様的には font-lock と indent-line-to の二つのみ機能すれば良い。
  • 短時間で決着すること。
    1. 朝活などの手隙の時間帯で記述すること。
    2. 開発期間は 1週間以内。

取りあえず、似ている django-mode をベースにしつつ、チュートリアルに沿って開発を始めてみました。

一応期間内で完成したものの...

Mode Tutorial ページでの Indentation 以外の項目は、django-mode のスタイルを採用しました。

sgml-mode の派生とし、正規表現は raw ではなく、rx を使用しました。rx.el については異論反論があるようですが、個人的には

  • elisp 特有のバックスラッシュを削減できる。
  • 表現自体もリストで記述できるので、ソースが読みやすくなる。

など、メリットが多いと思います。さて、後はインデントの計算ですね。


Mode Tutorial ページでは WPDL という言語サンプルを元に抽出した 5つのルールを記述する形で解説しています。基本的には、現在行とそれ以前の行との比較によってインデント値を得ています。

最初は、Templates の Commands からこうしたルールを抽出しながらコードに落していったのですが、これがどうにもこうにも。

features.soy - closure-templates - Project Hosting on Google Code

公開ファイルでテストにはおあつらえむきなので、この features.soy の完全再現を目標にしていましたが、例外的なパターンが頻出してしまって、動くことは動いたのですが、ソース的にはかなり汚なく手続きチックで美しくなく...


「手間を掛けない」が所期の目標ではありましたが、形になってくると欲が出るものです。着地点は変更せず、時間のみ 1週間プラスして elisp らしい表現はどうしたら良いか再考してみることにしました。

やっぱり Lisp ってムズかしい...

少ない知識で再記述してみたのが現在の形です。

基本的にはリスト構造を処理するのが鉄板だろう、ということで、インデントしたい行から先頭行までのリストをベースに、各行のインデント相対値のリストに変換。そして、最後にそれらの総和を取ることで当該行のインデント値を得る形としてみました。

みましたが... syntax を判断するところで場合分けが頻出してしまって、やはり美しくないですね。mapcar に与えるクロージャ関数に工夫の余地ありかも知れません。


また、この形態では indent-region での処理時間の問題もあります。真正直なリスト処理では行数が増えた分だけ不利になっていきます。確認してはいませんが、古い PC では相当な待ち時間が発生することでしょう。

幸い indent-region-function という関数が用意されているようですので、回避策(キャッシュなどを備えた新たな関数)を講じれば、万事OK かも知れません。


いずれ sgml の派生としながらも、HTML のタグは {print} などワンラインの Commands と同じ扱いとしてしまっていますので、この辺りが今後のバージョンアップへの TODO となるところなのでしょう。


何はともあれ、取りあえず使えそうな最低限のレベルには到達したようですので、公開させていただきました。