LunarVimが凄すぎた件について

最近LunarVimというものにハマっていまして、こいつが想像以上にすごかったので、ぜひこの喜びを共有できたらなと思いまして、この記事を書いてみようと思いました。

もともとastronvim -> NvChad -> lazy.nvimベースでの自前構成(今も現役) -> LunarVim。という形で移行していきました。その中でも一番長かったのはlazy.nvimベースの構成でしょうか。

現在はlazy.nvimベースで組んだ[nvim-lazy_load-custom](https://github.com/garchomp-game/nvim-lazy_load-custom)となるべく同じ形を目指した[LunarVim-custom](https://github.com/garchomp-game/LunarVim-custom)があるので、LunarVimの主要な機能と拡張方法を説明した後に、どのように設定を進めていったかについて紹介していけたらと思っています。


## そもそもLunarVimとは？

LunarVimとはそもそもどのようなものでしょう？[公式ドキュメント](https://www.LunarVim.org/)には、以下のように書いてあります。

> An IDE layer for Neovim with sane defaults. Completely free and community driven.

素直に訳すと、「合理的なデフォルト設定を備えたNeovimのためのIDEレイヤー、完全無料でコミュニティ主導型」ということらしいです（英語苦手なので翻訳機はさみました💧）

実際にLunarVimは、IDEライクに使うための構成がデフォルトで同梱されており、しかも最初から有効な状態で使うことができるので、いきなりlspやパーサーが効いた状態で開発することができます。なんと素晴らしいことなんでしょう。

また、すべての設定は、後に紹介する`lvim.builtin`をとおして無効化することもでき、また設定の拡張をするのも容易であることから、非常にカスタマイズ性の高いIDEとも言えます。

なお、Lunarvimのベースには、[lazy.nvim](https://github.com/folke/lazy.nvim)や[mason](https://github.com/williamboman/mason.nvim)、[treesitter](https://github.com/nvim-treesitter/nvim-treesitter)などが採用されているため、もともとこれらを触ったことある方はカスタマイズの理解も早いのではないかなと思います。

## LunarVim標準搭載のプラグイン

LunarVimに標準搭載されているプラグインは以下の通りです。

<!-- markdownlint-disable MD013 -->
| 機能                     | プラグイン                                                          |
| ----------------------   | ------------------------------------------------------------------- |
| プラグインマネージャー   | [lazy.nvim](https://github.com/folke/lazy.nvim)                     |
| コードの補完             | [nvim-cmp](https://github.com/hrsh7th/nvim-cmp)                      |
| 統合ターミナル           | [toggleterm](https://github.com/akinsho/toggleterm.nvim)            |
| ファイルエクスプローラー | [nvim-tree](https://github.com/nvim-tree/nvim-tree.lua)             |
| ファジーファインダー     | [telescope](https://github.com/nvim-telescope/telescope.nvim)       |
| LSP                      | [mason-lspconfig](https://github.com/williamboman/mason-lspconfig)  |
| linter                   | [null-ls](https://github.com/jose-elias-alvarez/null-ls.nvim)       |
| デバッグ                 | [nvim-dap](https://github.com/mfussenegger/nvim-dap)                |
| デバッグUI               | [nvim-dap-ui](https://github.com/rcarriga/nvim-dap-ui)              |
| スペースから呼び出すやつ | [nvim-which-key](https://github.com/folke/which-key.nvim)           |
| バッファライン           | [nvim-bufferline](https://github.com/akinsho/nvim-bufferline.lua)   |
<!-- markdownlint-enable MD013 -->

他にもいくつかのプラグインが最初から同梱されており、カスタマイズなしでも非常に便利に使うことが出来ます。それぞれのプラグインの詳細はREADMEもしくは他の記事に譲ります。

## LunarVimならでは特徴について

LunarVimは、最初からプラグインが入っているだけでなく、結構便利にカスタマイズされているので、いくつかある機能のうち、特にいいなと思ったものを紹介します

### LSP及びパーサーの自動インストール

LunarVimは、何らかの言語ファイルを開いたときに、まだそのファイルのLSPやパーサーがインストールされていない場合、ファイル開いたときに自動でインストールしてくれます。

ただし、基本的にmason-lspconfigを使って設定できるものが中心になるので、一部のLinterなどは手動で入れる必要がありますが、こちらは後に紹介する[mason-tool-installerを使った方法](#pluginについて)で簡単に自動インストールの設定ができます。

### 設定済みのwhich-key

自分は使っていないのですが、最初からスペース押すとwhich-keyが使えるようになっているのはなかなか嬉しい機能なんじゃないかなと思っています。

まだvimやneovimにあれこれプラグイン入れて使ったりとかしたことない初心者でも便利に使えるので、なかなかありがたいのではないかなと思います。

### 最初から補完がかなり強力

補完系の設定、ちゃんとやろうとしたら結構難しいんですけれども、この辺も割と完璧な状態に最初からなっているの非常にありがたいなぁと思っています。

例えば、

- コマンドラインの補完もちゃんと/で終わる
- どこでも/ってうったらディレクトリの補完が出てくる(.txtとかでも)
- もちろんluaのrequireの中でも文字列なのに補完が効く
- その他もともと良くありがちな補完もちゃんとできる

個人的にはこれ本当にすごいなーって思ったんですよね。ある程度自前のneovim設定でも補完系にはある程度こだわっていたのですが、そこまでできるのかって気づきにもなりました。

補完系の設定するの面倒な方にも結構勧めやすいんじゃないかなって思ってます。

## LunarVimのカスタマイズ方法の基本について

ここからは、LunarVimのカスタマイズの基本についてかんたんに触れておきます。

実は、LunarVimは最初からIDEのように使える構成になってありながらも、非常に簡単に既存の構成の無効化、変更、拡張などができるようになっています。これを実現しているのが、グローバル変数の「lvim」です

### lvim

LunarVimに関わるすべての作業は、基本的にこのlvimを通して行います。例えば、以下のような形で設定できます。

なお、こちらはLunarvimで設定するときのテンプレートとしても配布しています。興味がある方はぜひ[lunarvim-template](https://github.com/garchomp-game/lunarvim-template)を使ってみてください。

```lua
-- optionとか

-- keymap
lvim.leader = "\\"

lvim.keys.normal_mode["<C-n>"] = ":NvimTreeToggle<CR>"
-- Tips: lunarvimのデフォルトは<gvらしい
lvim.keys.visual_mode["<"] = false
-- >も同様に
lvim.keys.visual_mode[">"] = false

-- telescopeの場合少し特殊で、telescole.builtinをrequireして使う
local builtin = require("telescope.builtin")
lvim.keys.normal_mode["<leader>ff"] = builtin.find_files
lvim.keys.normal_mode["<leader>fg"] = builtin.live_grep
lvim.keys.normal_mode["<leader>fb"] = builtin.buffers
lvim.keys.normal_mode["<leader>fh"] = builtin.help_tags

-- override
-- builtinで既存のプラグインの有効/無効、及びconfig内の調整ができる
-- activeで有効/向こうの切り替え、on_config_doneで追加の設定もしくは変更
lvim.builtin.bufferline.active = false
lvim.builtin.which_key.active = false
-- 実はLunarvimのデフォルトのテーマと全く同じなんだけど、設定例として記載しておく。
lvim.colorscheme = "lunar"

-- フォーマット時自動でセーブするか
lvim.format_on_save.enabled = true

-- lsp
-- mason-lspconfigに登録されているもののみ選択可能
lvim.lsp.installer.setup.ensure_installed = {
  "marksman"
}

-- plugins
-- 導入方法はlazy.nvimの標準的な方法と全く同じ
lvim.plugins = {
  {
    -- linterやformatterだけインストール自動化したい場合はこれがないと自動化するのが難しい
    "WhoIsSethDaniel/mason-tool-installer.nvim",
    dependencies = {
      "williamboman/mason.nvim",
      "williamboman/mason-lspconfig.nvim",
    },
    config = function()
      require("mason-tool-installer").setup({
        ensure_installed = {
          "stylua",
        },
      })
    end,
  },
}
```

一つずつ紹介していきます。

#### builtin

`lvim.builtin`は、既存のプラグインのコアの設定の変更、及び有効化/無効化の設定などができる変数です。

builtinで設定できる項目はいくつかあるのですが、最低限押さえておくべき項目は、`active`と`setup`の２つでしょう。

- active

activeは、プラグインの有効化/無効化を設定するためのものです。基本的な使い方は

```lua
lvim.builtin.設定したい項目.active = true -- or false
```

という形で設定します。例えば、nvimtreeを無効化したい場合は以下のようになります。

```lua
lvim.builtin.nvimtree.active = false
```

- setup

setupは、lazy.nvimでいう`opts`に対応しています。いわゆるセットアップ時に設定したいものをここで指定します。

基本的な使い方は以下のとおりです。

```lua
lvim.builtin.設定したい項目.setup = {
  -- ここに設定したい項目を書いていく
}
```

例として、nvimtreeの追加設定をしたい場合は、以下のようになります。

```lua
lvim.builtin.nvimtree.setup = {
  view = {
    width = 40,
  },
}
```

- おまけ：on_config_done

on_config_doneは、lazy.nvimでいう`config`に対応しています。プラグインの設定が終わった後に、追加で行いたい処理を実装していきます。

基本的な書き方は以下のとおりです。

```lua
lvim.builtin.設定したい項目.on_config_done = function()

end
```

実際の設定のサンプルは思いつかなかったので省略しますが、例えば、coreプラグインの設定後に処理を追加したい時とかに便利です。

#### keysやleaderなど

keysやleaderは設定の仕方が類似している為まとめて紹介します。と入っても基本的に難しいことはなく、とても簡単です。

以下に一部抜粋していきます

```lua
lvim.leader = "\\"
lvim.keys.insert_mode['<C-h>'] = '<Left>'
lvim.keys.visual_mode['<'] = false
-- 以下のbuiltinは、lvim.builtinとは別物です！！！
local builtin = require("telescope.builtin")
lvim.keys.normal_mode["<leader>ff"] = builtin.find_files
lvim.keys.term_mode["<esc>"] = [[<C-\><C-n>]]
```

全部は追いきれていないですが、他にも、replaceモードや矩形選択に対応したモードもあると思います。

#### lsp

lvim.lspでは、lsp関連の様々な設定をすることが出来ます。簡単に紹介していきましょう。

- installer

基本的にLspInstallでインストールできる言語サーバーなどは、こちらにセットすることで、起動時に自動でインストールしておきたいものを指定することが出来ます。

```lua
lvim.lsp.installer.setup.ensure_installed = {
  "marksman"
}
```

ただ、先程も言ったとおり、こちらでセットできるのは、LspInstallできるもの。つまり、[mason-lspconfig](https://github.com/williamboman/mason-lspconfig)のリストにあるもの限定です。

じゃぁnull-lsなどで使うlinterやformatterはどうやって入れるの？ていう話になるのですが、これは後にpluginの項目でしれっとmason-tool-installerを例に出していますので、そちらをご確認いただければと思います。

- null_ls

null_lsの設定は少々特殊なのと、まだちゃんと調査しきれてないこともあり、lvim.lsp.null_lsの活用がわかってないのが現状です。

代替え案として、現在自分は以下のように設定しています。

```lua
local formatters = require("lvim.lsp.null-ls.formatters")
formatters.setup({ { command = "stylua", filetypes = { "lua" } } })
```

requireする形だとうまく行くので、現在自分はこのような形で解決しています。

補足: 上記のようなfiletypeごとの設定は~/.config/lvim/ftplugin/lua.luaのように、ftpluginフォルダーに書いています。[lunarvim-template](https://github.com/garchomp-game/lunarvim-template)にも同じように設定しているので、こちらも合わせて参考にしてみてください。

### pluginについて

最後にプラグインの導入の仕方についてです。とは言っても実は非常に簡単で、単にlvim.pluginsにいつものlazy.nvimでプラグインを追加する方法と全く同じやり方で追加すればいいだけです。

そのため、もともとlazy.nvimを使っていた人であれば、既存の資産をそのまま使うことが出来ます。

```lua
-- plugins
lvim.plugins = {
  {
    "WhoIsSethDaniel/mason-tool-installer.nvim",
    dependencies = {
      "williamboman/mason.nvim",
      "williamboman/mason-lspconfig.nvim",
    },
    config = function()
      require("mason-tool-installer").setup({
        ensure_installed = {
          "stylua",
        },
      })
    end,
  },
}
```

なお、lspのセクションから飛んできた人のために追加で説明すると、基本的にformatterやlinterなどは、現状このmason-tool-installerを使って入れるのがベターなのかなと思っています。

いつかlvim変数経由で簡単にインストールできるようになるといいですね。

## まとめ

色々と話したいことを詰め込んだら、なかなかのボリュームになってしまいましたが、LunarVimの概要を少しでも掴むことは出来たでしょうか？

一応簡単にまとめておきます

- LunarVimは最初からIDEのように使うことができる
- lvim変数を通して色々カスタマイズすることができる
- 最初から色々設定済みなので、便利に活用することができる。

neovimを使い始めたばかりの初心者はもちろん、実はある程度設定をしている方にも、特にlazy.nvimベースでもともと構築していた方にとっては、かなりカスタマイズしやすくなっていると思います。

lazy.nvimベースで普通に設定してもいいけれども、肥大化してきて、面倒な部分はLunarVimに任せる。といったこともできると思うので、これを気に是非LunarVimへの乗り換えを検討してみてはいかがでしょうか？