aboutsummaryrefslogtreecommitdiff
path: root/init.lua
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2021-07-13 11:22:52 +0200
committerFlorian Fischer <florian.fischer@muhq.space>2021-07-13 11:22:52 +0200
commit18f22bf4e26933e320634ace56896039897aaa56 (patch)
tree2aa47ca5ce51da43e604543ee43e80ca4078f2f4 /init.lua
parent3bea907ca006fcd87f9dcc777d7fd1714af2c168 (diff)
downloadvis-lspc-18f22bf4e26933e320634ace56896039897aaa56.tar.gz
vis-lspc-18f22bf4e26933e320634ace56896039897aaa56.zip
implement textDocument/rename
Currently only changes in the current window are applied. TODO: * apply changes in opened files by iteration all vis windows * apply changes in all files using sed or something
Diffstat (limited to 'init.lua')
-rw-r--r--init.lua120
1 files changed, 120 insertions, 0 deletions
diff --git a/init.lua b/init.lua
index f133816..947133e 100644
--- a/init.lua
+++ b/init.lua
@@ -112,6 +112,8 @@ lspc = {
-- program used to let the user make choices
-- The available choices are pass to <menu_cmd> on stdin separated by '\n'
menu_cmd = 'vis-menu',
+ -- program used to ask the user for confirmation
+ confirm_cmd = 'vis-menu',
-- should diagnostics be highlighted if available
highlight_diagnostics = false,
@@ -394,6 +396,80 @@ local function lspc_select_location(locations)
return choices[choice]
end
+-- get a user confirmation
+-- return true if user selected yes, false otherwise
+local function lspc_confirm(prompt)
+ local choices = 'no\nyes'
+
+ local cmd = 'printf "' .. choices .. '" | ' .. lspc.confirm_cmd
+
+ if prompt then
+ cmd = cmd .. ' -p \'' .. prompt .. '\''
+ end
+
+ lspc.log('get confirmation using: ' .. cmd)
+ -- local menu = io.popen(cmd)
+ -- local output = menu:read('*a')
+ -- local _, _, status = menu:close()
+
+ local choice = nil
+ local status, output = vis:pipe(vis.win.file, {start = 0, finish = 0}, cmd)
+ if status == 0 then
+ -- trim newline from selection
+ if output:sub(-1) == '\n' then
+ choice = output:sub(1, -2)
+ else
+ choice = output
+ end
+ end
+
+ vis:redraw()
+ return choice == 'yes'
+end
+
+-- apply a WorkspaceEdit received from the language server
+local function vis_apply_workspaceEdit(win, file, workspaceEdit)
+ assert(win.file == file)
+
+ local file_edits = workspaceEdit.changes
+ assert(file_edits)
+
+ -- generate change summary
+ local summary = '--- workspace edit summary ---\n'
+ for uri, edits in pairs(file_edits) do
+ local path = uri_to_path(uri)
+ summary = summary .. path .. ':\n'
+ for i, edit in ipairs(edits) do
+ summary = summary .. '\t' .. i .. '.: ' .. json.encode(edit) .. '\n'
+ end
+ end
+
+ vis:message(summary)
+ vis:redraw()
+
+ -- get user confirmation
+ local confirmation = lspc_confirm('apply changes:')
+
+ -- close summary window
+ vis:command('q')
+
+ if not confirmation then
+ return
+ end
+
+ -- apply changes
+ for uri, edits in pairs(file_edits) do
+ local path = uri_to_path(uri)
+ if path == file.path then
+ for _, edit in ipairs(edits) do
+ vis_apply_textEdit(win, file, edit)
+ end
+ end
+
+ -- TODO: apply changes in different files
+ end
+end
+
local function lspc_highlight_diagnostics(win, diagnostics)
for _, diagnostic in ipairs(diagnostics) do
local range = diagnostic.vis_range
@@ -615,7 +691,12 @@ local function lspc_handle_hover_method_response(win, result, old_pos)
sel.col .. ' ---'
local hover_msg = result.contents.value or result.contents
vis:message(hover_header .. '\n' .. hover_msg)
+end
+local function lspc_handle_rename_method_response(win, result)
+ -- result must always be valid because otherwise we would caught the error
+ -- in ls_handle_method_response
+ vis_apply_workspaceEdit(win, win.file, result)
end
-- method response dispatcher
@@ -623,7 +704,14 @@ local function ls_handle_method_response(ls, method_response, req)
local win = req.win
local method = req.method
+
+ local err = method_response.error
+ if err then
+ lspc_err(err .. ' occurred during ' .. method ' call')
+ end
+
local result = method_response.result
+
-- LuaFormatter off
if method == 'textDocument/definition' or
method == 'textDocument/declaration' or
@@ -644,6 +732,9 @@ local function ls_handle_method_response(ls, method_response, req)
elseif method == 'textDocument/hover' then
lspc_handle_hover_method_response(win, result, req.ctx)
+ elseif method == 'textDocument/rename' then
+ lspc_handle_rename_method_response(win, result, req.ctx)
+
elseif method == 'shutdown' then
ls_send_notification(ls, 'exit')
ls.fd:close()
@@ -1050,6 +1141,35 @@ vis:command_register('lspc-hover', function(_, _, win)
end
end)
+vis:command_register('lspc-rename', function(argv, _, win)
+ local new_name = argv[1]
+ if not new_name then
+ lspc_err('lspc-rename usage: <new name>')
+ return
+ end
+
+ 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['renameProvider'] then
+ lspc_err('language server ' .. ls.name .. ' does not provide rename')
+ return
+ end
+
+ if not ls.open_files[win.file.path] then
+ lspc_open(ls, win, win.file)
+ end
+
+ local params = vis_doc_pos_to_lsp(vis_get_doc_pos(win))
+ params.newName = new_name
+
+ ls_call_text_document_method(ls, 'rename', params, win)
+end)
+
vis:command_register('lspc-completion', function(_, _, win)
local ls, err = lspc_get_usable_ls(win.syntax)
if err then