Description
最近触る言語は大抵 オフィシャルかデファクトの高速な formatter を備えている。慣れるとやはり楽……
Ruby は 歴史の積み重ねから公式のフォーマットというのはまだ無いのかな? (tDiary とかハードタブ且つ3だったし)
それはそれで良いと思うんだけど、自分で書いてても微妙なインデントミスとか一々直すの嫌なので、リポジトリ単位で決める手段ぐらいは欲しい
rubyfmt というのが合って確かに結構早いんだけど、パターンマッチへ未対応だったりダブルクォート強制だったりで自分は避けてる
(デフォルトにいきなり強い主張を放り込んでくるのでプチプチoffにする事も多いけれど)機能面が充実していてカスタマイズの手段も用意されているということから 結局 rubocop をフォーマッタとして使っている
基本的に早くは無いんだけど、CIで回す分にはそんな困ってなかった。厄介なのは vscode との integration 方法で、 vscode-ruby はメンテナンスを止めてて rubyide/vscode-ruby@dc81c80 、 rubocop 連携エラーへの修正 rubyide/vscode-ruby#647 がずっとリリースされていない ref: rubyide/vscode-ruby#227, rubyide/vscode-ruby#825
あまりこの辺頑張る気力もなく、フォークしてどうこうみたいなのは考えてなかった。そもそも単にフォーマッタとして走らせたいだけなので https://github.com/pucelle/vscode-run-on-save みたいなアプローチも検討したけど、 config に色々増えるし時間はかかるとうーむだった。また色んなフォーマッタを一つにまとめる https://github.com/numtide/treefmt みたいなプロジェクトもあるんだけど、 dprint 以外の物まで増やしたくはない。なんとか dprint にやらせるとしたら、 Wasm で ruby と rubocop を固めるとかなのかな・・・? と dprint の org を漁ってたら https://github.com/dprint/dprint-plugin-exec というのが合った。
これがまさに他のフォーマッタとの連携を dprint にさせる手段の一つで、標準入出力でフォーマット掛けられる物なら何でも巻き取れそう
rubocop に一杯あるオプションを改めて漁ると、この形式にも対応してくれてた
$ rubocop --autocorrect --stdin file_path --stderr
Autocorrection:
-a, --autocorrect Autocorrect offenses (only when it's safe).
--auto-correct (same, deprecated)
--safe-auto-correct (same, deprecated)
-A, --autocorrect-all Autocorrect offenses (safe and unsafe).
--auto-correct-all (same, deprecated)
--disable-uncorrectable Used with --autocorrect to annotate any
offenses that do not support autocorrect
with `rubocop:todo` comments.
似たようなオプションが一杯合って引っかかりそうになるけど、とりあえず safe 以外で auto format する気にならないのでこんな感じにしている
dprint-plugin-exec 側はこんな感じに dprint.json へ設定する
{
"exec": {
"associations": ["**/*.{rb,gemspec,rake}", "Rakefile", "Gemfile", "Steepfile"],
"rubocop": "bundle exec rubocop --autocorrect --stdin {{file_path}} --stderr",
"rubocop.associations": "**/**"
},
"includes": ["**/*.{json,md,yml,html,css,rb,gemspec,rake}", "{Rakefile,Gemfile,Steepfile}"]
}
associations 側では他の箇所みたいに複数 glob に対応していない https://github.com/dprint/dprint-plugin-exec/blob/94ed0fe3fac6a631c5e3e00538f29c30770a0738/src/configuration.rs#L165-L173 ということなので、更に他の外部プラグインとは連携させづらい強引な config なんだけど、今のところは足りている。 nix の formatter とかも巻取りたくなってきたけど、まぁそのうち誰かが直してくれるのでは・・・
しかし dprint.json を単純に拡張すると、高速なはずの dprint が常に rubocop へ引っ張られて重々になる。なので dprint 用の config を分割する必要があるんだけど、https://github.com/dprint/dprint-vscode は config path 変更に対応しておらず、サクッと対応させるのも難しそうだったので https://github.com/dprint/check 側へ変更コードを入れてもらった dprint/check@23e4f05
最終的にはこうなる
https://github.com/kachick/ruby-gem-template/blob/40c1ee9605359e548b959b3151c402c815167806/dprint-ci.json#L1-L22
https://github.com/kachick/ruby-gem-template/blob/40c1ee9605359e548b959b3151c402c815167806/dprint.json#L1-L22
rubocop の servermode を有効にしておくと走るまでの間が大分改善するんだけど、vscode でワークスペース開いた時に有効化出来ても、閉じる時に上げた時のサーバーを落とさせるみたいなのが難しそう microsoft/vscode#65986 で手動でやってる。
$ bundle exec rubocop --start-server
$ bundle exec rubocop --stop-server