feat(lsp): add formatexpr (#16186)

Co-authored-by: Meck <yesmeck@gmail.com>
Co-authored-by: TJ DeVries <devries.timothyj@gmail.com>
This commit is contained in:
Michael Lingelbach 2021-10-31 05:40:26 -07:00 committed by GitHub
parent 4da0351651
commit 52fa1d26db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 0 deletions

View File

@ -61,6 +61,10 @@ Example config (in init.vim): >
-- See `:help omnifunc` and `:help ins-completion` for more information.
vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Use LSP as the handler for formatexpr.
-- See `:help formatexpr` for more information.
vim.api.nvim_buf_set_option(0, 'formatexpr', 'v:lua.vim.lsp.formatexpr')
-- For plugins with an `on_attach` callback, call them here. For example:
-- require('completion').on_attach()
end

View File

@ -1529,6 +1529,54 @@ function lsp.omnifunc(findstart, base)
return -2
end
--- Provides an interface between the built-in client and a `formatexpr` function.
---
--- Currently only supports a single client. This can be set via
--- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach`
--- via `vim.api.nvim_buf_set_option(bufnr, 'formatexpr', 'v:lua.vim.lsp.formatexpr()')`.
---
--- Can additionally be wrapped with a function that passes an optional table for customization.
---
---@param opts table options for customizing the formatting expression which takes the
--- following keys:
--- * timeout_ms (default 500ms). The timeout period for the formatting request.
function lsp.formatexpr(opts)
opts = opts or {}
local timeout_ms = opts.timeout_ms or 500
if vim.tbl_contains({'i', 'R', 'ic', 'ix'}, vim.fn.mode()) then
-- `formatexpr` is also called when exceeding `textwidth` in insert mode
-- fall back to internal formatting
return 1
end
local start_line = vim.v.lnum
local end_line = start_line + vim.v.count - 1
if start_line > 0 and end_line > 0 then
local params = {
textDocument = util.make_text_document_params();
range = {
start = { line = start_line - 1; character = 0; };
["end"] = { line = end_line - 1; character = 0; };
};
};
params.options = util.make_formatting_params().options
local client_results = vim.lsp.buf_request_sync(0, "textDocument/rangeFormatting", params, timeout_ms)
-- Apply the text edits from one and only one of the clients.
for _, response in pairs(client_results) do
if response.result then
vim.lsp.util.apply_text_edits(response.result, 0)
return 0
end
end
end
-- do not run builtin formatter.
return 0
end
---Checks whether a client is stopped.
---
---@param client_id (Number)