lsp: Add sync variant of LSP formatting

Also, factor out a `vim.lsp.util.get_effective_tabstop()` helper and add
tests for it.
This commit is contained in:
David Lukes 2020-05-05 17:23:45 +02:00
parent 4496628c18
commit ebee9ebe2b
4 changed files with 59 additions and 10 deletions

View File

@ -58,6 +58,11 @@ Nvim provides the |vim.lsp.omnifunc| 'omnifunc' handler which allows
" Use LSP omni-completion in Python files.
autocmd Filetype python setlocal omnifunc=v:lua.vim.lsp.omnifunc
If a function has a `*_sync` variant, it's primarily intended for being run
automatically on file save. E.g. code formatting: >
" Auto-format *.rs files prior to saving them
autocmd BufWritePre *.rs lua vim.lsp.buf.formatting_sync(nil, 1000)
================================================================================
FAQ *lsp-faq*
@ -767,6 +772,12 @@ document_symbol() *vim.lsp.buf.document_symbol()*
formatting({options}) *vim.lsp.buf.formatting()*
TODO: Documentation
formatting_sync({options}, {timeout_ms}) *vim.lsp.buf.formatting_sync()*
Same as |vim.lsp.buf.formatting()| but synchronous. Useful
for running on save, to make sure buffer is formatted prior
to being saved. {timeout_ms} is passed on to
|vim.lsp.buf_request_sync()|.
hover() *vim.lsp.buf.hover()*
TODO: Documentation

View File

@ -65,19 +65,18 @@ function M.completion(context)
end
function M.formatting(options)
validate { options = {options, 't', true} }
local sts = vim.bo.softtabstop;
options = vim.tbl_extend('keep', options or {}, {
tabSize = (sts > 0 and sts) or (sts < 0 and vim.bo.shiftwidth) or vim.bo.tabstop;
insertSpaces = vim.bo.expandtab;
})
local params = {
textDocument = { uri = vim.uri_from_bufnr(0) };
options = options;
}
local params = util.make_formatting_params(options)
return request('textDocument/formatting', params)
end
function M.formatting_sync(options, timeout_ms)
local params = util.make_formatting_params(options)
local result = vim.lsp.buf_request_sync(0, "textDocument/formatting", params, timeout_ms)
if not result then return end
result = result[1].result
vim.lsp.util.apply_text_edits(result)
end
function M.range_formatting(options, start_pos, end_pos)
validate {
options = {options, 't', true};

View File

@ -1259,6 +1259,30 @@ function M.make_text_document_params()
return { uri = vim.uri_from_bufnr(0) }
end
--- Get visual width of tabstop.
---
--@see |softtabstop|
--@param bufnr (optional, number): Buffer handle, defaults to current
--@returns (number) tabstop visual width
function M.get_effective_tabstop(bufnr)
validate { bufnr = {bufnr, 'n', true} }
local bo = bufnr and vim.bo[bufnr] or vim.bo
local sts = bo.softtabstop
return (sts > 0 and sts) or (sts < 0 and bo.shiftwidth) or bo.tabstop
end
function M.make_formatting_params(options)
validate { options = {options, 't', true} }
options = vim.tbl_extend('keep', options or {}, {
tabSize = M.get_effective_tabstop();
insertSpaces = vim.bo.expandtab;
})
return {
textDocument = { uri = vim.uri_from_bufnr(0) };
options = options;
}
end
-- @param buf buffer handle or 0 for current.
-- @param row 0-indexed line
-- @param col 0-indexed byte offset in line

View File

@ -1424,4 +1424,19 @@ describe('LSP', function()
eq({15,5}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents,{width = 15, wrap_at = 14})} ]])
end)
end)
describe('lsp.util.get_effective_tabstop', function()
local function test_tabstop(tabsize, softtabstop)
exec_lua(string.format([[
vim.api.nvim_buf_set_option(0, 'softtabstop', %d)
vim.api.nvim_buf_set_option(0, 'tabstop', 2)
vim.api.nvim_buf_set_option(0, 'shiftwidth', 3)
]], softtabstop))
eq(tabsize, exec_lua('return vim.lsp.util.get_effective_tabstop()'))
end
it('with softtabstop = 1', function() test_tabstop(1, 1) end)
it('with softtabstop = 0', function() test_tabstop(2, 0) end)
it('with softtabstop = -1', function() test_tabstop(3, -1) end)
end)
end)