Formatting Ruby with Doomed LSP
I've found myself writing a lot more Ruby than expected recently, and waiting on Rubocop to tell me my code is bad enough that I can't ship my work. Something had to be done.
Rather than throw out a tool that does occasionally contribute meaningful feedback, I opted to integrated formatting into Emacs via Apheleia and eglot.
This approach saves me from a lot of tedious editing without wait times of several seconds on a codebase with fewer than 9,000 lines of code.
First, we teach Apheleia about eglot with a custom formatter that we’ll refer to
later as (surprise, surprise) eglot
.
(after! apheleia
(cl-defun +apheleia-indent-eglot-managed-buffer
(&key buffer scratch callback &allow-other-keys)
"Copy BUFFER to SCRATCH, then format scratch, then call CALLBACK."
(with-current-buffer scratch
(setq-local eglot--cached-server
(with-current-buffer buffer
(eglot-current-server)))
(let ((buffer-file-name (buffer-local-value 'buffer-file-name buffer)))
(eglot-format-buffer))
(funcall callback)))
(add-to-list 'apheleia-formatters
'(eglot . +apheleia-indent-eglot-managed-buffer)))
Now we only have to configure ruby-mode to both connect to our preferred LSP
server and use our new eglot
formatter. I’m using ruby-lsp
but you can use
any LSP implementation that takes your fancy.
(after! eglot
(add-to-list 'eglot-server-programs
`((ruby-mode ruby-ts-mode)
. ,(eglot-alternatives '(("ruby-lsp")
("solargraph" "socket" "--port" :autoport))))))
And then one additional piece of configuration, this time to eval-after-loading Apheleia.
(after! apheleia
(add-to-list 'apheleia-mode-alist
'(ruby-mode . eglot)))
At this point one should have lightning fast formatting of even the gnarliest of Ruby. And most importantly, you can ship and learn without a red build every time you open a pull request.
Bon voyage!