Using formatter.nvim and lsp format together
For most filetypes, I prefer to use formatters provided by formatter.nvim. But there are some exceptions, for which I would use lsp format.
To avoid having to manually decide and execute formatter.nvim or lsp format, we can define the decision logic within our formatter.nvim config and assign it to a singluar keybind.
This allows us to simply hit our keybind for formatting, and based on our predefined logic, the file will either be formatted with formatter.nvim or lsp format.
A basic config for formatter.nvim looks like this:
require("formatter").setup({
logging = true,
log_level = vim.log.levels.WARN,
filetype = {
-- Formatter configurations per filetype go here
lua = {
-- format with stylua
require("formatter.filetypes.lua").stylua,
},
-- Define formatter configurations for all filetypes
["*"] = {
-- "formatter.filetypes.any" defines default configurations for any
-- filetype
require("formatter.filetypes.any").remove_trailing_whitespace,
},
},
})
The special "*"
filetype, will be run on every call to :Format
(the command
that runs formatter.nvim).
We can therefore define a function within ["*"]
which checks whether we have
assigned a formatter to a filetype in formatter.nvim, and if we haven’t, to
execute vim.lsp.buf.format()
instead.
-- ...
["*"] = {
function()
local formatters = require("formatter.util").get_available_formatters_for_ft(vim.bo.filetype)
if #formatters > 0 then
print("formatted with formatter.nvim")
return
end
-- check if there are any LSP formatters
local lsp_clients = vim.lsp.buf_get_clients()
for _, client in pairs(lsp_clients) do
if client.server_capabilities.document_formatting then
print("formatted with lsp")
vim.lsp.buf.format()
return
end
end
print("no formatters found from formatter.nvim OR lsp")
end,
},
All together it looks like this:
local bufopts = { noremap = true, silent = true }
vim.keymap.set({ "v", "n" }, "<leader>f", ":Format<cr>", bufopts)
require("formatter").setup({
logging = true,
log_level = vim.log.levels.WARN,
filetype = {
lua = {
require("formatter.filetypes.lua").stylua,
},
["*"] = {
require("formatter.filetypes.any").remove_trailing_whitespace,
function()
local formatters = require("formatter.util").get_available_formatters_for_ft(vim.bo.filetype)
if #formatters > 0 then
print("formatted with formatter.nvim")
return
end
local lsp_clients = vim.lsp.buf_get_clients()
for _, client in pairs(lsp_clients) do
if client.server_capabilities.document_formatting then
print("formatted with lsp")
vim.lsp.buf.format()
return
end
end
print("no formatters found from formatter.nvim OR lsp")
end,
},
},
})
With this setup, if we run :Format
on a lua file, we will format with
formatter.nvim using stylua. If we wanted instead to format our lua files with
lua-language-server
(a lsp for lua), we can simply remove the config for lua
filetypes:
-- ...
filetype = {
-- lua = {
-- require("formatter.filetypes.lua").stylua,
-- },
["*"] = {
require("formatter.filetypes.any").remove_trailing_whitespace,
function()
-- code below unchanged
For more context you can check the solution source here in Github issues.