Vim用のHaskellインデントプラグインvim-haskell-indentを作りました

Haskellはインデントが意味を持つ言語です。コーディングするときには、エディターがいかに心地よく空気を読んでインデントを入れてくれるかが重要になってきます。HaskellVim用インデントプラグインはこれまでいくつかありましたが、それらはどれも機能が少なすぎて、普段からHaskellを書く私にとっては苛々するものばかりでした。とても心地よいインデントをサポートしてくれるインデントプラグインはありませんでした。

とにかくHaskellの最強のインデントプラグインが欲しいということで、作りました。

VimHaskellを書いているよという方は、ぜひインストールしてお使いください。

今のところ以下のような構文に対応しています。

  • データ型のインデント
  • derivingの後はインデントをやめる

https://raw.githubusercontent.com/wiki/itchyny/vim-haskell-indent/image/1.gif

  • guardのインデント
  • otherwiseの後はインデントをやめる
  • whereのインデント

https://raw.githubusercontent.com/wiki/itchyny/vim-haskell-indent/image/2.gif

  • module exportのインデント
  • レコード型のインデント
  • class、instanceのインデント

https://raw.githubusercontent.com/wiki/itchyny/vim-haskell-indent/image/3.gif

その他、case文やif文にも対応しています。

このプラグインのすごいところは、インデントが壊れたHaskellソースコードに対して gg=G でおおよそインデントを修復できることです。もちろん、instanceの中なのか外なのかといった、構文上決定不可能なインデントはあります (関数の型まで解析し始めると、それはインデントプラグインの責務ではない気がしてきます)。Haskellの壊れたインデントをオートインデントで直してくれというのはとても難しい要求です。それでもなお、このプラグインを使った結果where節やguardがめちゃくちゃになるということはないはずです。いや、ないはずというのは言いすぎですが、あまりないと思います。

f:id:itchyny:20151029235114g:plain

上のコードは、まず普通にコードを打ち込んでいき、一旦インデントを全て破壊してから gg=G で整形してみました。インデントとしてのスペースキーを一切打たずに上のコードを打ち込むことができますし、何らかの要因でインデントが破壊されてもこの程度の複雑さのコードならば gg=G でインデントを修復することができます。ここまでサポートしているHaskellインデントプラグインは他にないと思います。

Haskellのインデントルールは複雑です。このプラグインは、インデントプラグインにしてはいろいろやり過ぎていて、既にコードがカオスになりかけています。ただ、テストはわりときちんと書いていますし、今あるテストに対してはリグレッションしないようにメンテナンスを続けていきます。すでにある程度心地よいインデントをできるのではないかなと思いますので、VimHaskellを書いている方には試していただきたいと思います。もしこのプラグインを使っていてインデントでイラッとしたら、気軽にGitHubにissueをたてていただくと、随時修正していきますので、よろしくお願いします。