How do I format the current buffer using the language server protocol in Neovim?
Answer
vim.lsp.buf.format()
Explanation
Neovim's built-in LSP client exposes vim.lsp.buf.format(), which delegates formatting to the language server attached to the current buffer. Once a server is configured (e.g. with nvim-lspconfig), this gives you editor-agnostic, project-configured formatting — the same logic your CI pipeline uses — without any separate formatter plugin.
How it works
vim.lsp.buf.format()sends atextDocument/formattingrequest to the active language server- The server returns a set of text edits and Neovim applies them to the buffer
- Pass
{ async = false }to block until the edits are applied (required inBufWritePreautocmds) - Pass
{ filter = ... }to select a specific server when multiple are attached
Example
Add a normal-mode mapping and a format-on-save autocmd to your config:
-- Map <leader>f to format in normal mode
vim.keymap.set('n', '<leader>f', function()
vim.lsp.buf.format({ async = true })
end, { desc = 'Format buffer (LSP)' })
-- Format synchronously on save
vim.api.nvim_create_autocmd('BufWritePre', {
callback = function()
vim.lsp.buf.format({ async = false })
end,
})
Tips
- If multiple LSP clients are attached, use
filterto pick the right one:vim.lsp.buf.format({ filter = function(c) return c.name == 'gopls' end }) - Run
:lua vim.lsp.buf.format()ad-hoc from the command line to format without a mapping - Use
formatexpr=v:lua.vim.lsp.formatexpr()to integrategqwith the LSP formatter - Combines well with
conform.nvimfor fallback formatters when no LSP is available