Neovimの開発環境でRuby-LSPを動かすためにやってみたこと

# はじめに

こんにちは、Gakken LEAPのフロントエンドエンジニアの Okuma です。

私は普段の業務からプライベートまでVim（Neovim）をIDEとして利用しています。いつもフロントエンド側のタスクだとNodeの環境で作業することが多いため、自分のNeovimの設定だとフロントエンド系のLSPやツールが動けば問題なかったのですが、今回Ruby on Railsの中でもテンプレートエンジンである`.erb`ファイルを触る機会があったため、それに合わせてRuby（Rails）の環境をセットアップしようとしましたが、かなり試行錯誤をしたのでその工程をご紹介できればと思います。

# Neovimとは

[Neovim](https://neovim.io/)は、Vimをベースに開発された次世代のテキストエディタです。Vimの軽快さやキーボード中心の操作性を受け継ぎつつ、よりモダンで柔軟なカスタマイズが可能になっているのが大きな特徴です。特に、プログラミング用途での使い勝手が大幅に向上しており、言語サーバープロトコル（LSP）対応や、Luaを使った高速なプラグイン開発、非同期処理など、現代の開発環境にマッチした機能が揃っています。

私がNeovimを使い始めたのは3〜4年前で、当時はスクラッチからLSPやキーマップの設定ファイルを作成していたのですが、2年ほど前からLazyvimという設定群のプリセットを使い始めました。Lazyvimの導入によってよりIDEっぽい開発環境がセットアップでき、開発体験が向上しました！

# Ruby環境を設定した際のつまずき

LazyvimにはExtrasという、追加の機能や設定を簡単に有効化できる拡張セットがあります。特定の開発スタイルや言語・フレームワークなどに合わせて対応するための事前構成済みの設定モジュールだと思ってもらえると良いかと思います。

今回はRuby、Ruby on RailsのIDE環境をセットアップしたいと思い、公式ドキュメントを確認したところ、RubyのExtrasを見つけました！

[Extras > lang > Ruby](https://www.lazyvim.org/extras/lang/ruby)

ドキュメントの記載通りRubyのExtrasを有効にしてみましたが、結局のところ`.rb`ファイルを編集してもruby-lspやrubocopを正しく動かすことができませんでした...。

## ruby-lspを有効にするために試してみたこと

※ ここから先は私が調査と検証を行い、試行錯誤した内容です。正解だとも思っていませんので、参考にされる場合はご注意ください！

`.rb`ファイルを開き、以下のruby-lspに関するwarningが表示されていたので、まずは`:LspInfo`でLspの起動を確認してみました。

```txt
notify.warn Client ruby_lsp quit with exit code 1 and signal 0. Check log for errors: /Users/***/.local/state/nvim/lsp.log
```

```txt
vim.lsp: Active Clients ~
- stimulus_ls (id=2, root_dir=~/***, attached_to=[12])
- copilot (id=4, root_dir=~/***, attached_to=[24,12])
```

Active Clientsを確認するとRubyファイルを編集しているのにも関わらず、ruby-lspが起動していないことがわかります。
私は[Mason](https://github.com/mason-org/mason.nvim)をNeovimのパッケージマネージャーとして、[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)をLSPの設定として使用していたため、その線で調べることにしました。

結構色々と探しました。まずはエラー文などで検索しつつ、ruby-lspをインストールしているのはmasonなので、masonによるエラーと思ってその線でも調べると、関連しそうなissueを見つけることができました！

https://github.com/mason-org/mason.nvim/issues/1777

Rubyのバージョンによってruby-lspが動かないといったissueでしたが、この中のコメントに助けとなるヒントがありました！

```lua
{
    "neovim/nvim-lspconfig",
    opts = {
      servers = {
        ...
        ruby_lsp = {
          cmd = { os.getenv("HOME") .. "/.rbenv/shims/ruby-lsp" },
        },
        ...
      }
    }
  }
```

ruby-lspのコマンドを直接指定しており、さらにそれが`/.rbenv/shims/ruby-lsp`を指定していました。
ということはmason経由のものではないということで私も設定ファイルで以下のように設定してみました！

```lua:lsp.lua
{
    "neovim/nvim-lspconfig",
    opts = {
        servers = {
            ...
            ruby_lsp = {
                mason = false,
                cmd = { "/Users/***/.rbenv/shims/ruby-lsp" },
                filetypes = { "ruby", "eruby" },
                root_dir = function()
                    return vim.loop.cwd()
                end,
            },

        ...
      }
    }
}
```

`mason`経由ではなく、自前のruby-lspを直接指定する方法です。
設定後に改めて`.rb`ファイルを開き、`:LspInfo`をチェックすると...

```txt
vim.lsp: Active Clients ~
- ruby_lsp (id=1, root_dir=~/Developer/glav-backoffice, attached_to=[13])
- stimulus_ls (id=3, root_dir=~/Developer/glav-backoffice, attached_to=[13])
- copilot (id=4, root_dir=~/Developer/glav-backoffice, attached_to=[13])
```

ruby-lspがActiveになりました！

## rubocopを有効にするために試してみたこと

今回はruby-lspの有効化をメインに書いていたため、rubocopについては参考にさせていただいた記事のみ貼り付けておきます！

以下の方法でDockerのコンテナ上にあるRubocop LS{を参照する方法で私は有効になりました！

https://zenn.dev/socialplus/articles/fa0eac39bfa174

ぜひ参考にしてみてください！

# おわりに

実際私も業務でもプライベートでもNeovimも使いつつ、探りさぐりで設定を修正してみたり、プラグインを追加してみたりして楽しんでいます。
dotfilesで管理することでNeovimだけでなく、ターミナル周辺の設定も一括で管理して他のPCでも同じように使用できるのはかなり魅力的です！ これからも自分の使いやすいエディタを作っていきたいと思います！
最後に、改めて今回は私が調査と検証を行い、試行錯誤した内容です。正解だとも思っていませんので、参考にされる場合はご自身でも一度調べてみてください！ありがとうございました

# エンジニア募集中

Gakken LEAP では教育をアップデートしていきたいエンジニアを絶賛大募集しています！！
ぜひお気軽にカジュアル面談へお越しください！！

https://gakken-leap.co.jp/recruit/

# 参考

- [Ruby LSP does not work when using different versions of Ruby](https://github.com/mason-org/mason.nvim/issues/1777)
- [Docker コンテナ上の RuboCop LSP を使って Ruby コードをフォーマットする](https://zenn.dev/socialplus/articles/fa0eac39bfa174)