## 背景
[[none-ls.nvim]]を使っていたが、以下の理由から[[conform.nvim]]に興味を持ったため。
- [[none-ls.nvim]]より設定が簡単そう
- [[none-ls.nvim]]だとなぜかファイル保存時に[[Biome]]のimport最適化がかからない
## 要件
[[none-ls.nvim]]で利用している以下の[[フォーマッター]]を動かせ、ファイル保存時に自動で実行できること。
- [[Biome]]
- [[prettierd]]
- [[StyLua]]
- [[goimports]]
- [[sh|shfmt]]
### none-lsの設定
```lua
{
"nvimtools/none-ls.nvim",
config = function()
local null_ls = require("null-ls")
local augroup = vim.api.nvim_create_augroup("LspNullFormatting", {})
null_ls.setup({
sources = {
null_ls.builtins.formatting.biome.with({
only_local = "node_modules/.bin",
condition = function(utils)
return utils.root_has_file({ "biome.json" })
end,
}),
null_ls.builtins.formatting.prettierd.with({
prefer_local = "node_modules/.bin",
extra_filetypes = { "svelte" },
disabled_filetypes = { "markdown" },
condition = function(utils)
return not utils.root_has_file({ "biome.json", "deno.json", "deno.jsonc" })
end,
}),
null_ls.builtins.formatting.stylua,
null_ls.builtins.formatting.goimports,
null_ls.builtins.formatting.shfmt,
},
on_attach = function(client, bufnr)
if client.supports_method("textDocument/formatting") then
print(string.format("[%s] Enable auto-format on save", client.name))
vim.api.nvim_clear_autocmds({ group = augroup, buffer = bufnr })
vim.api.nvim_create_autocmd("BufWritePre", {
group = augroup,
buffer = bufnr,
callback = function()
vim.lsp.buf.format({
async = false,
filter = function(c)
return c.name == "null-ls"
end,
})
end,
})
end
end,
})
end,
}
```
## インストール
[[lazy.nvim]]でインストール。
<div class="link-card">
<div class="link-card-header">
<img src="https://github.githubassets.com/favicons/favicon.svg" class="link-card-site-icon"/>
<span class="link-card-site-name">GitHub</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<p class="link-card-title">GitHub - stevearc/conform.nvim: Lightweight yet powerful formatter plugin for Neovim</p>
<p class="link-card-description">Lightweight yet powerful formatter plugin for Neovim - stevearc/conform.nvim</p>
</div>
<img src="https://opengraph.githubassets.com/d7b25f4342cc54129a3454b0052af14adbaecaf0bede256ba3b77bfc40d9117c/stevearc/conform.nvim" class="link-card-image" />
</div>
<a href="https://github.com/stevearc/conform.nvim?tab=readme-ov-file#installation"></a>
</div>
```lua
{
"stevearc/conform.nvim",
opts = {},
}
```
[[GitHub]]のアイコン見て気づいたけど、[[oil.nvim]]の開発者なのか。[[oil.nvim]]は愛用させていただいてるしバグにも遭遇しないので期待値が上がった。
## 動作確認
[[StyLua]]で試してみる。
```lua
{
"stevearc/conform.nvim",
config = function()
require("conform").setup({
formatters_by_ft = {
lua = { "stylua" },
},
format_on_save = {
timeout_ms = 500,
lsp_format = "fallback",
},
})
end,
}
```
ファイルを保存したら自動フォーマットされるようになった。
> [!info]
> [[ファイル保存時に自動フォーマット (conform.nvim)]]
## 各フォーマッターの設定を適応
よく使う[[ファイルタイプ (Vim)|ファイルタイプ]]をとりあえず追加。
```lua
return {
"stevearc/conform.nvim",
config = function()
local web_formatter = { "biome", "prettierd", stop_after_first = true }
require("conform").setup({
formatters_by_ft = {
lua = { "stylua" },
go = { "goimports" },
bash = { "shfmt" },
-- Web
typescript = web_formatter,
javascript = web_formatter,
typescriptreact = web_formatter,
javascriptreact = web_formatter,
vue = web_formatter,
svelte = web_formatter,
json = web_formatter,
jsonc = web_formatter,
yaml = web_formatter,
html = web_formatter,
css = web_formatter,
scss = web_formatter,
less = web_formatter,
},
format_on_save = {
timeout_ms = 500,
lsp_format = "fallback",
},
})
end,
}
```
## Biomeのorganize imports
[[conform.nvim]]に移行しようとした大きなモチベの1つがコレなので検証する。
> - [[none-ls.nvim]]だとなぜかファイル保存時に[[Biome]]のimport最適化がかからない
先ほどの設定のままではorganize importsはかからなそう。調べたところ、`biome-check`を使うのがよさそう。
```diff
- local web_formatter = { "biome", "prettierd", stop_after_first = true }
+ local web_formatter = { "biome-check", "prettierd", stop_after_first = true }
```
> [!info]
> [[conform.nvimでファイル保存時にインポート最適化 (Biome)]]
## Biomeで不要importを自動削除
せっかくなので不要import削除もできるようにしたい。`linter.rules.correctness.noUnusedImports`を設定する。
```json
{
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": { "noUnusedImports": "warn" }
}
}
}
```
> [!info]
> [[未使用import文をファイル保存時に自動削除 (Biome)]]
## 遭遇した問題
[[Typo]]というイージーミスでハマってしまったが、ついでに[[conform.nvim]]の確認方法を学べたのでヨシ。
<div class="link-card">
<div class="link-card-header">
<img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" class="link-card-site-icon"/>
<span class="link-card-site-name">minerva.mamansoft.net</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<p class="link-card-title">📝conform.nvimでluaファイルにStyluaを設定してもlua_lsのフォーマットが優先される</p>
</div>
<img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/troubleshooting.webp" class="link-card-image" />
</div>
<a class="internal-link" data-href="Notes/📝conform.nvimでluaファイルにStyluaを設定してもlua_lsのフォーマットが優先される.md"></a>
</div>
%%[[📝conform.nvimでluaファイルにStyluaを設定してもlua_lsのフォーマットが優先される]]%%
READMEどおりにやっていれば遭遇しないけど、[[Qiita]]や[[Zenn]]の記事で見た記憶を辿ったら怒られた。
<div class="link-card">
<div class="link-card-header">
<img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" class="link-card-site-icon"/>
<span class="link-card-site-name">minerva.mamansoft.net</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<p class="link-card-title">📝conform.nvimでThe nested {} syntax のdeprecatedエラー</p>
</div>
<img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/troubleshooting.webp" class="link-card-image" />
</div>
<a class="internal-link" data-href="Notes/📝conform.nvimでThe nested {} syntax のdeprecatedエラー.md"></a>
</div>
%%[[📝conform.nvimでThe nested {} syntax のdeprecatedエラー]]%%