aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/buf.lua
diff options
context:
space:
mode:
authorKarim Abou Zeid <karim23697@gmail.com>2021-04-30 13:40:20 +0200
committerKarim Abou Zeid <karim23697@gmail.com>2021-05-01 21:12:40 +0200
commit48a59f8f4f3eced84b21a473527b00ef1b9b5bd2 (patch)
treed51718506182dbe8f0098173a48c3ab08cb58083 /runtime/lua/vim/lsp/buf.lua
parent59eae3b38fc98ba8c14e681b6d231e9821a11d52 (diff)
downloadrneovim-48a59f8f4f3eced84b21a473527b00ef1b9b5bd2.tar.gz
rneovim-48a59f8f4f3eced84b21a473527b00ef1b9b5bd2.tar.bz2
rneovim-48a59f8f4f3eced84b21a473527b00ef1b9b5bd2.zip
Add formatting_seq_sync, change formatting and formatting_sync
Diffstat (limited to 'runtime/lua/vim/lsp/buf.lua')
-rw-r--r--runtime/lua/vim/lsp/buf.lua94
1 files changed, 87 insertions, 7 deletions
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 31116985e2..d7f3353ad9 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -111,6 +111,39 @@ function M.completion(context)
return request('textDocument/completion', params)
end
+--@private
+--- If there is more than one client with formatting capability, asks the user
+--- which one to use.
+--
+--@returns The client to use for formatting
+local function get_formatting_client()
+ local clients = vim.tbl_values(vim.lsp.buf_get_clients());
+ clients = vim.tbl_filter(function (client)
+ return client.resolved_capabilities.document_formatting
+ end, clients)
+ -- better UX when choices are always in the same order (between restarts)
+ table.sort(clients, function (a, b) return a.name < b.name end)
+
+ if #clients > 1 then
+ local choices = {}
+ for k,v in ipairs(clients) do
+ table.insert(choices, string.format("%d %s", k, v.name))
+ end
+ local user_choice = vim.fn.confirm(
+ "Select a language server for formatting:",
+ table.concat(choices, "\n"),
+ 0,
+ "Question"
+ )
+ if user_choice == 0 then return nil end
+ return clients[user_choice]
+ elseif #clients < 1 then
+ return nil
+ else
+ return clients[1]
+ end
+end
+
--- Formats the current buffer.
---
--@param options (optional, table) Can be used to specify FormattingOptions.
@@ -119,8 +152,11 @@ end
--
--@see https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting
function M.formatting(options)
+ local client = get_formatting_client()
+ if client == nil then return end
+
local params = util.make_formatting_params(options)
- return request('textDocument/formatting', params)
+ return client.request("textDocument/formatting", params)
end
--- Performs |vim.lsp.buf.formatting()| synchronously.
@@ -134,14 +170,58 @@ end
---
--@param options Table with valid `FormattingOptions` entries
--@param timeout_ms (number) Request timeout
+--@see |vim.lsp.buf.formatting_seq_sync|
function M.formatting_sync(options, timeout_ms)
+ local client = get_formatting_client()
+ if client == nil then return end
+
local params = util.make_formatting_params(options)
- local result = vim.lsp.buf_request_sync(0, "textDocument/formatting", params, timeout_ms)
- if not result or vim.tbl_isempty(result) then return end
- local _, formatting_result = next(result)
- result = formatting_result.result
- if not result then return end
- vim.lsp.util.apply_text_edits(result)
+ local result = client.request_sync("textDocument/formatting", params, timeout_ms)
+ if result and result.result then
+ util.apply_text_edits(result.result)
+ end
+end
+
+--- Formats the current buffer by sequentially requesting formatting from attached clients.
+---
+--- Useful when multiple clients with formatting capability are attached.
+---
+--- Since it's synchronous, can be used for running on save, to make sure buffer is formatted
+--- prior to being saved. {timeout_ms} is passed on to the |vim.lsp.client| `request_sync` method.
+--- Example:
+--- <pre>
+--- vim.api.nvim_command[[autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_seq_sync()]]
+--- </pre>
+---
+--@param options (optional, table) `FormattingOptions` entries
+--@param timeout_ms (optional, number) Request timeout
+--@param order (optional, table) List of client names. Formatting is requested from clients
+---in the following order: first all clients that are not in the `order` list, then
+---the remaining clients in the order as they occur in the `order` list.
+function M.formatting_seq_sync(options, timeout_ms, order)
+ local clients = vim.tbl_values(vim.lsp.buf_get_clients());
+
+ -- sort the clients according to `order`
+ for _, client_name in ipairs(order or {}) do
+ -- if the client exists, move to the end of the list
+ for i, client in ipairs(clients) do
+ if client.name == client_name then
+ table.insert(clients, table.remove(clients, i))
+ break
+ end
+ end
+ end
+
+ -- loop through the clients and make synchronous formatting requests
+ for _, client in ipairs(clients) do
+ if client.resolved_capabilities.document_formatting then
+ local params = util.make_formatting_params(options)
+ local result = client.request_sync("textDocument/formatting", params, timeout_ms)
+ if result and result.result then
+ util.apply_text_edits(result.result)
+ end
+ end
+ end
end
--- Formats a given range.