diff options
author | Michael Lingelbach <m.j.lbach@gmail.com> | 2021-10-31 05:40:26 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-31 05:40:26 -0700 |
commit | 52fa1d26db43664e8aeb856a59a693e9cb6ad44f (patch) | |
tree | 1aa7e4803d7fc5b2d4cb16f16b46ae8307bae448 | |
parent | 4da0351651848e6c6c52903518fcd9ed15e087be (diff) | |
download | rneovim-52fa1d26db43664e8aeb856a59a693e9cb6ad44f.tar.gz rneovim-52fa1d26db43664e8aeb856a59a693e9cb6ad44f.tar.bz2 rneovim-52fa1d26db43664e8aeb856a59a693e9cb6ad44f.zip |
feat(lsp): add formatexpr (#16186)
Co-authored-by: Meck <yesmeck@gmail.com>
Co-authored-by: TJ DeVries <devries.timothyj@gmail.com>
-rw-r--r-- | runtime/doc/lsp.txt | 4 | ||||
-rw-r--r-- | runtime/lua/vim/lsp.lua | 48 |
2 files changed, 52 insertions, 0 deletions
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 30e8ff658b..c844f8747b 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -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 diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index df700bebbd..3e73ae7b78 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -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) |