See Automatically choose one language server to formatting when using multiple language servers · Issue #14952 · neovim/neovim · GitHub for past discussion. Anyone have an idea for how to do this?
Right your own formatting function that calls
local client = function_that_gets_the_client_I_want_filtering_by_name
client.request("textDocument/formatting", {} , nil, vim.api.nvim_get_current_buf())
and put that in on_attach
bound to a key.
You can iterate over clients attached to the buffer with
for client in vim.lsp.get_active_clients() do
print(client.name)
end
Using this:
nvim_lsp.pyls.setup {
on_attach = function(client, bufnr)
if <condition> then
-- print(client.name) -- I see "pyls" printed here
client.request("textDocument/formatting", {} , nil, vim.api.nvim_get_current_buf())
-- client.resolved_capabilities.document_formatting = false
end
on_attach(client, bufnr)
end,
settings = {
pyls = {
plugins = {
-- This requires: pip install yapf
yapf = { enabled = true },
autopep8 = { enabled = false },
pylint = { enabled = true },
pycodestyle = { enabled = false },
}
}
}
}
Results in:
RPC[Error] code_name = InvalidParams, message = "TypeError: 'NoneType' object is not subscriptable" data = {
traceback = { " File \"/usr/local/google/home/kovas/.local/lib/python3.9/site-packages/pyls_jsonrpc/endpoint.py\"
, line 113, in consume\n self._handle_request(message['id'], message['method'], message.get('params'))\n", ' Fil
e "/usr/local/google/home/kovas/.local/lib/python3.9/site-packages/pyls_jsonrpc/endpoint.py", line 182, in _handle_r
equest\n handler_result = handler(params)\n', ' File "/usr/local/google/home/kovas/.local/lib/python3.9/site-pac
kages/pyls_jsonrpc/dispatchers.py", line 23, in handler\n return method(**(params or {}))\n', " File \"/usr/loca
l/google/home/kovas/.local/lib/python3.9/site-packages/pyls/python_ls.py\", line 338, in m_text_document__formatting
\n return self.format_document(textDocument['uri'])\n" }
AND I still get the option to choose between language servers when trying to format .
Perhaps I misunderstood?
Any ideas what I might be doing wrong here?
Here is my formatting function. I rewrite the select_client
function and make it choose the language server I want. The code of formatting_sync
is from the builitin lsp.
local function select_client(method)
local clients = vim.tbl_values(vim.lsp.buf_get_clients())
clients =
vim.tbl_filter(
function(client)
return client.supports_method(method)
end,
clients
)
for i = 1, #clients do
if clients[i].name == "efm" then
return clients[i]
end
end
return nil
end
function formatting_sync(options, timeout_ms)
local client = select_client("textDocument/formatting")
if client == nil then
return
end
local params = util.make_formatting_params(options)
local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, vim.api.nvim_get_current_buf())
if result and result.result then
util.apply_text_edits(result.result)
elseif err then
vim.notify("vim.lsp.buf.formatting_sync: " .. err, vim.log.levels.WARN)
end
end
Hmmm, I added that code to my init.lua with no change in behavior. Do you then reference that formatting_sync function later? I feel like my understanding of how this system works isn’t quite complete yet…
Yes, you can call it later in somewhere. Just replace the vim.lsp.buf.formatting_sync
function.
For example:
vim.cmd([[
augroup formatOnSave
autocmd!
autocmd BufWritePost * lua formatting_sync()
augroup end
]])
Ok great I got it working! It looks like the functions you are redefining are at neovim/buf.lua at master · neovim/neovim · GitHub (for future reference). My code ended up looking like this:
function formatting(options)
local client = select_client("textDocument/formatting")
if client == nil then return end
local params = util.make_formatting_params(options)
return client.request("textDocument/formatting", params, vim.api.nvim_get_current_buf())
end
vim.lsp.buf.formatting = formatting
function range_formatting(options, start_pos, end_pos)
local client = select_client("textDocument/rangeFormatting")
if client == nil then return end
local params = util.make_given_range_params(start_pos, end_pos)
params.options = util.make_formatting_params(options).options
return client.request("textDocument/rangeFormatting", params)
end
vim.lsp.buf.range_formatting = range_formatting
as I wasn’t using the sync
versions. I also redefined the vim.lsp.buf.formatting
functions as I am binding keys using the on_attach
function suggested at GitHub - neovim/nvim-lspconfig: Quickstart configurations for the Nvim LSP client, and this was the easiest way to make that work.