Vimで.erbファイルを書きたい
Rails7のHotwireを試したくて、(nvimで)何年かぶりにeRubyを書いてみてるのだけど、eRuby向けのLanguage Serverが見当たらなくて泣きそうになった。
せめて文法エラーのチェックくらいはできたら・・・1
そこで、どんなコマンドでもLanguage Serverにしてしまえる efm-langserver
を使ってみることにした。
efm-langserverのREADMEには、
lint-command: 'erb -x -T - | ruby -c'
と書いてあるが、これだと以下のようなブロックを含むeRubyのコードを扱えない。
<%= simple_form_for(quote, html: { class: "quote form" }) do |f| %>
<%= f.input :name, input_html: { autofocus: true } %>
<%= f.submit class: "btn btn--secondary" %>
<% end %>
ブロックがあると常に SyntaxError になってしまう。
$ (erb -x -T - | ruby -c) <<'EOF'
> <%= simple_form_for(quote, html: { class: "quote form" }) do |f| %>
<%= f.input :name, input_html: { autofocus: true } %>
<%= f.submit class: "btn btn--secondary" %>
<% end %>
> EOF
-:2: syntax error, unexpected ')'
...class: "quote form" }) do |f| ).to_s); _erbout.<< "\n".freeze
-:5: syntax error, unexpected `end', expecting ')'
; end ; _erbout.<< "\n".freeze
-:6: syntax error, unexpected end-of-input, expecting ')'
; _erbout
これはRubyの標準ライブラリのERBがブロックを含むeRubyをハンドリングしないのが原因。
Railsで使われているeRubyライブラリのerubiも同様だった。
かわりに使えるものを探してみると、baby_erubis
というのを見つけた。
もう長らくメンテされていないが、
(Experimental) Block argument expression supported
と書いてある。
こんな感じで試してみると、ブロックの含まれるeRubyタグのハンドリングが期待通りにできた。
gem install baby_erubis
cat ./app/views/quotes/index.html.erb | ruby -r baby_erubis -e 'puts BabyErubis::Html.new.from_str(STDIN.read).src'
そこで、erb -x -T - | ruby -c
のかわりにためしに使ってみることにした。
セットアップ
coc.nvim は導入済みの前提。
efm-langserver と baby_erubis をいれる。
brew install efm-langserver
gem install baby_erubis
ファイルタイプがeruby
のときにefm-langserver
を呼び出すようにする。
(ちなみに、FileTypeがeruby
のときにはcoc-html
も使われるようになっている)
{
"html.filetypes": ["html", "eruby"],
"html.format.templating": true,
"languageserver": {
"efm": {
"command": "efm-langserver",
"args": [],
"filetypes": ["eruby"]
}
}
}
以下のRubyスクリプトをパスの通った場所に置いて実行権限をつける。
これが erb -x -T - | ruby -c
のかわりになる。
#!/usr/bin/env ruby
# https://github.com/kwatch/baby_erubis
require "baby_erubis"
begin
BabyErubis::Html.new.from_str(STDIN.read, '-').src
puts "Syntax OK"
rescue SyntaxError => se
STDERR.puts se.message
exit 1
end
.config/efm-langserver/config.yaml
を作成して、以下の内容にする。
(efm-langserver のREADMEに書いてあるものとほぼ一緒)
version: 2
tools:
eruby-erb: &eruby-erb
lint-debounce: 2s
lint-command: 'erbcheck'
lint-stdin: true
lint-offset: 0
format-stdin: true
format-command: htmlbeautifier
languages:
eruby:
- <<: *eruby-erb
あとはvimでてきとうな.erb
ファイルを開くと、文法チェックをおこなってくれるようになる。
これにて一件落着。
今後の課題
文法チェックはできるようになったけど、欲を言えばeRubyのRuby部分の自動補完とかもやってほしいので、solargraphと組み合わせてどうにかできないか試してみたい。
-
Ruby自体のLanguage Serverはsolargraphというのがあり、だましだましだがRailsもサポートされている ↩