From ee9a73cbfaa723e101ffafca37b99eea84114f01 Mon Sep 17 00:00:00 2001 From: D4yvid Date: Wed, 26 Oct 2022 21:13:19 -0300 Subject: [PATCH] Create custom popup for code action and added a option to enable/disable it --- autoload/lsp/codeaction.vim | 70 +++++++++++++++++++++++++++---------- autoload/lsp/options.vim | 4 ++- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/autoload/lsp/codeaction.vim b/autoload/lsp/codeaction.vim index 761afb8..578603f 100644 --- a/autoload/lsp/codeaction.vim +++ b/autoload/lsp/codeaction.vim @@ -4,6 +4,28 @@ vim9script import './util.vim' import './textedit.vim' +import './options.vim' as opt + +export def HandleCodeAction(lspserver: dict, selAction: dict) + # textDocument/codeAction can return either Command[] or CodeAction[]. + # If it is a CodeAction, it can have either an edit, a command or both. + # Edits should be executed first. + if selAction->has_key('edit') || selAction->has_key('command') + if selAction->has_key('edit') + # apply edit first + textedit.ApplyWorkspaceEdit(selAction.edit) + endif + if selAction->has_key('command') + lspserver.executeCommand(selAction) + endif + else + lspserver.executeCommand(selAction) + endif +enddef + +def Print(a: any) + echo string(a) +enddef export def ApplyCodeAction(lspserver: dict, actions: list>): void if actions->empty() @@ -12,13 +34,13 @@ export def ApplyCodeAction(lspserver: dict, actions: list>): void return endif - var prompt: list = ['Code Actions:'] + var text: list = [] var act: dict for i in range(actions->len()) act = actions[i] var t: string = act.title->substitute('\r\n', '\\r\\n', 'g') t = t->substitute('\n', '\\n', 'g') - prompt->add(printf("%d. %s", i + 1, t)) + text->add(printf(" %d. %s ", i + 1, t)) endfor var choice: number @@ -28,28 +50,38 @@ export def ApplyCodeAction(lspserver: dict, actions: list>): void # choice set in LSPTest_CodeActionChoice. choice = g:LSPTest_CodeActionChoice else - choice = inputlist(prompt) + if opt.lspOptions.usePopupInCodeAction + # Use a popup menu to show the code action + popup_create(text, { + pos: 'botleft', + line: 'cursor-1', + col: 'cursor', + zindex: 1000, + cursorline: 1, + mapping: 0, + wrap: 0, + title: 'Code action', + callback: (_, id) => { + # Invalid item selected or closed the popup + if id <= 0 || id > text->len() + return + endif + + # Do the code action + HandleCodeAction(lspserver, actions[id - 1]) + }, + filter: 'popup_filter_menu' + }) + else + choice = inputlist(["Code action:"] + text) + endif endif - if choice < 1 || choice >= prompt->len() + if choice < 1 || choice > text->len() return endif - var selAction = actions[choice - 1] - # textDocument/codeAction can return either Command[] or CodeAction[]. - # If it is a CodeAction, it can have either an edit, a command or both. - # Edits should be executed first. - if selAction->has_key('edit') || selAction->has_key('command') - if selAction->has_key('edit') - # apply edit first - textedit.ApplyWorkspaceEdit(selAction.edit) - endif - if selAction->has_key('command') - lspserver.executeCommand(selAction) - endif - else - lspserver.executeCommand(selAction) - endif + HandleCodeAction(lspserver, actions[choice - 1]) enddef # vim: tabstop=8 shiftwidth=2 softtabstop=2 diff --git a/autoload/lsp/options.vim b/autoload/lsp/options.vim index e824e74..5308e83 100644 --- a/autoload/lsp/options.vim +++ b/autoload/lsp/options.vim @@ -35,7 +35,9 @@ export var lspOptions: dict = { # Make diagnostics show in a popup instead of echoing showDiagInPopup: true, # Don't print message when a configured language server is missing. - ignoreMissingServer: false + ignoreMissingServer: false, + # Use a floating menu to show the code action menu instead of asking for input + usePopupInCodeAction: false } # set LSP options from user provided options -- 2.48.1