Formatting of visual selection with LSP

Things look solidly grim at this point. On the edge of reporting a bug against vim.lsp.buf.format().


I’d like to format current visual selection via LSP.

documentFormattingProvider is present in client.server_capabilities and formatting the whole file works just fine.

What I have tried so far:

  • Using vim.lsp.buf.format() as per documented. It fails to act on visual selection when called without parameters.
  • Force range and bufnr. Same result, formats the whole buffer.
  • Calling it via user command. Still formats the whole buffer.

Tested with ruff, shfmt and autopep8 acting as formatters.

Any ideas how to make it work? As an absolutely last resort, I am considering extracting text via Lua function, passing it to an external formatter via stdin and then replacing selection with its stdout, but… This is too much, there has to be a better way.

As an update, here are some snippets I have tried:

vim.keymap.set('v', '\\q', vim.lsp.buf.format, { buffer = true })
vim.keymap.set('v', '\\q', function() vim.lsp.buf.format() end, { buffer = true })
local c_buf = vim.api.nvim_get_current_buf()
local s_start = vim.api.nvim_buf_get_mark(0, "<")
local s_end = vim.api.nvim_buf_get_mark(0, ">")

vim.keymap.set('v', '\\q', function() vim.lsp.buf.format({ bufnr = c_buf, range = {["start"] = s_start, ["end"] = s_end} }) end, { buffer = true })

…all fail to format a selection.

I use conform.nvim to handle formatting, i think it has an option for this
https://github.com/stevearc/conform.nvim

1 Like