vimtricks.wiki Concise Vim tricks, one at a time.

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 a textDocument/formatting request 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 in BufWritePre autocmds)
  • 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 filter to 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 integrate gq with the LSP formatter
  • Combines well with conform.nvim for fallback formatters when no LSP is available

Next

How do I jump to a tag in Vim and automatically choose if there is only one match?