From e83950a7149f364b653395cdd4d9446875a7f469 Mon Sep 17 00:00:00 2001 From: Michiel van den Heuvel Date: Fri, 16 Jun 2023 18:23:58 +0200 Subject: Add textDocument/formatting implementation This is tested with the Rust language server and the Lua one. Moving the cursor to the correct position afterwards works with Rust, but not with Lua. Being smarter about the ranges is probably necessary for Lua and might make other ones more robust. --- README.md | 2 ++ init.lua | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/README.md b/README.md index 2b98a91..b9d6cae 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ vis-lspc currently supports: * `textDocument/implementation` * `textDocument/hover` * `textDocument/rename` +* `textDocument/formatting` * `[Diagnostics]` ## Whats not working @@ -109,6 +110,7 @@ vis-lspc is in a early state, but if you are brave there are some default key bi # workspace edits lspc-rename - rename the identifier under the cursor to + lspc-format - format the file in the current window # development support lspc-hover - hover over the current line diff --git a/init.lua b/init.lua index 9f3e7d4..48f7b97 100644 --- a/init.lua +++ b/init.lua @@ -365,6 +365,27 @@ local function vis_apply_textEdit(win, file, textEdit) win:draw() end +-- apply a list of textEdits received from the language server +local function vis_apply_textEdits(win, file, textEdits) + assert(win.file == file) + + local edits = {} + for _, textEdit in ipairs(textEdits) do + local range = lsp_range_to_vis_range(win, textEdit.range) + table.insert(edits, { + mark = file:mark_set(range.start), + len = range.finish - range.start, + newText = textEdit.newText, + }) + end + for _, edit in ipairs(edits) do + local pos = file:mark_get(edit.mark) + file:delete(pos, edit.len) + file:insert(pos, edit.newText) + end + win:draw() +end + -- concatenate all numeric values in choices and pass it on stdin to lspc.menu_cmd local function lspc_select(choices) local menu_input = '' @@ -782,6 +803,10 @@ local function lspc_handle_rename_method_response(win, result) vis_apply_workspaceEdit(win, win.file, result) end +local function lspc_handle_formatting_method_response(win, result) + vis_apply_textEdits(win, win.file, result) +end + local function lspc_handle_initialize_response(ls, result) ls.initialized = true ls.capabilities = result.capabilities @@ -841,6 +866,9 @@ local function ls_handle_method_response(ls, method_response, req) elseif method == 'textDocument/rename' then lspc_handle_rename_method_response(win, result) + elseif method == 'textDocument/formatting' then + lspc_handle_formatting_method_response(win, result) + elseif method == 'shutdown' then ls_send_notification(ls, 'exit') ls.fd:close() @@ -1298,6 +1326,31 @@ vis:command_register('lspc-rename', function(argv, _, win) ls_call_text_document_method(ls, 'rename', params, win) end) +vis:command_register('lspc-format', function(_, _, win) + local ls, err = lspc_get_usable_ls(win.syntax) + if err then + lspc_err(err) + return + end + + -- check if the language server has a provider for this method + if not ls.capabilities['documentFormattingProvider'] then + lspc_err('language server ' .. ls.name .. ' does not provide formatting') + return + end + + if not ls.open_files[win.file.path] then + lspc_open(ls, win, win.file) + end + + local params = { + textDocument = {uri = path_to_uri(win.file.path)}, + options = {tabSize = 2, insertSpaces = true}, + } + + ls_call_text_document_method(ls, 'formatting', params, win) +end) + vis:command_register('lspc-completion', function(_, _, win) local ls, err = lspc_get_usable_ls(win.syntax) if err then -- cgit v1.2.3