From: Andreas Louv Date: Sat, 11 Mar 2023 09:32:57 +0000 (+0100) Subject: Make it possible to specify a name, pattern or number directly to "LspCodeAction" X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=7b0c6e93be88d36150981bb54ab5401930af7822;p=vim-lsp.git Make it possible to specify a name, pattern or number directly to "LspCodeAction" --- diff --git a/autoload/lsp/codeaction.vim b/autoload/lsp/codeaction.vim index 5a34d90..2295230 100644 --- a/autoload/lsp/codeaction.vim +++ b/autoload/lsp/codeaction.vim @@ -43,7 +43,7 @@ export def HandleCodeAction(lspserver: dict, selAction: dict) endif enddef -export def ApplyCodeAction(lspserver: dict, actions: list>): void +export def ApplyCodeAction(lspserver: dict, actions: list>, query: string): void if actions->empty() # no action can be performed util.WarnMsg('No code action is available') @@ -61,46 +61,46 @@ export def ApplyCodeAction(lspserver: dict, actions: list>): void var choice: number - if exists('g:LSPTest') && g:LSPTest && exists('g:LSPTest_CodeActionChoice') - # Running the LSP unit-tests. Instead of prompting the user, use the - # choice set in LSPTest_CodeActionChoice. - choice = g:LSPTest_CodeActionChoice - else - 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: (_, result) => { - # Invalid item selected or closed the popup - if result <= 0 || result > text->len() - return - endif + if query =~ '^\d\+' # digit + choice = str2nr(query) + elseif query =~ '^/' # regex + choice = 1 + util.Indexof(actions, (i, a) => a.title =~ query[1 : ]) + elseif query != '' # literal string + choice = 1 + util.Indexof(actions, (i, a) => a.title[0 : query->len() - 1] == query) + elseif 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: (_, result) => { + # Invalid item selected or closed the popup + if result <= 0 || result > text->len() + return + endif - # Do the code action - HandleCodeAction(lspserver, actions[result - 1]) - }, - filter: (winid, key) => { - if key == 'h' || key == 'l' - winid->popup_close(-1) - elseif key->str2nr() > 0 - # assume less than 10 entries are present - winid->popup_close(key->str2nr()) - else - return popup_filter_menu(winid, key) - endif - return 1 - }, - }) - else - choice = inputlist(["Code action:"] + text) - endif + # Do the code action + HandleCodeAction(lspserver, actions[result - 1]) + }, + filter: (winid, key) => { + if key == 'h' || key == 'l' + winid->popup_close(-1) + elseif key->str2nr() > 0 + # assume less than 10 entries are present + winid->popup_close(key->str2nr()) + else + return popup_filter_menu(winid, key) + endif + return 1 + }, + }) + else + choice = inputlist(["Code action:"] + text) endif if choice < 1 || choice > text->len() diff --git a/autoload/lsp/lsp.vim b/autoload/lsp/lsp.vim index e42b12a..24f41bb 100644 --- a/autoload/lsp/lsp.vim +++ b/autoload/lsp/lsp.vim @@ -707,14 +707,14 @@ enddef # Perform a code action # Uses LSP "textDocument/codeAction" request -export def CodeAction(line1: number, line2: number) +export def CodeAction(line1: number, line2: number, query: string) var lspserver: dict = buf.CurbufGetServerChecked() if lspserver->empty() return endif var fname: string = @% - lspserver.codeAction(fname, line1, line2) + lspserver.codeAction(fname, line1, line2, query) enddef # Perform a workspace wide symbol lookup diff --git a/autoload/lsp/lspserver.vim b/autoload/lsp/lspserver.vim index 16d9838..0f6385b 100644 --- a/autoload/lsp/lspserver.vim +++ b/autoload/lsp/lspserver.vim @@ -1335,7 +1335,7 @@ enddef # Request: "textDocument/codeAction" # Param: CodeActionParams def CodeAction(lspserver: dict, fname_arg: string, line1: number, - line2: number) + line2: number, query: string) # Check whether LSP server supports code action operation if !lspserver.isCodeActionProvider util.ErrMsg("Error: LSP server does not support code action operation") @@ -1368,7 +1368,7 @@ def CodeAction(lspserver: dict, fname_arg: string, line1: number, return endif - codeaction.ApplyCodeAction(lspserver, reply.result) + codeaction.ApplyCodeAction(lspserver, reply.result, query) enddef # List project-wide symbols matching query string diff --git a/autoload/lsp/util.vim b/autoload/lsp/util.vim index 11b1606..091c8d2 100644 --- a/autoload/lsp/util.vim +++ b/autoload/lsp/util.vim @@ -206,4 +206,16 @@ export def JumpToLspLocation(location: dict, cmdmods: string) location.targetSelectionRange.start.character + 1) enddef +# 'indexof' is to new to use it, use this instead. +export def Indexof(list: list, CallbackFn: func(number, any): bool): number + var ix = 0 + for val in list + if CallbackFn(ix, val) + return ix + endif + ix += 1 + endfor + return -1 +enddef + # vim: tabstop=8 shiftwidth=2 softtabstop=2 diff --git a/doc/lsp.txt b/doc/lsp.txt index f25181d..0cecbe7 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -330,13 +330,19 @@ A description of the various commands provided by this plugin is below. You can map these commands to keys and make it easier to invoke them. *:LspCodeAction* -:LspCodeAction Apply the code action supplied by the language server +:LspCodeAction [query] Apply the code action supplied by the language server to the diagnostic in the current line. This works only if there is a diagnostic message for the current line. You can use the |:LspDiagCurrent| command to display - the diagnostic for the current line. You will be - prompted to select one of the actions supplied by the - language server. + the diagnostic for the current line. + + When [query] is given the code action starting with + [query] will be applied. [query] can be a regexp + pattern, or a digit corresponding to the index of the + code actions in the created prompt. + + When [query] is not given you will be prompted to select + one of the actions supplied by the language server. *:LspDiagCurrent* :LspDiagCurrent Displays the diagnostic message (if any) for the diff --git a/plugin/lsp.vim b/plugin/lsp.vim index c983f56..8bf146b 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -80,7 +80,7 @@ augroup END # autocmd VimLeavePre * call lsp.StopAllServers() # LSP commands -command! -nargs=0 -bar -range LspCodeAction lsp.CodeAction(, ) +command! -nargs=? -bar -range LspCodeAction lsp.CodeAction(, , ) command! -nargs=0 -bar LspDiagCurrent lsp.LspShowCurrentDiag() command! -nargs=0 -bar LspDiagFirst lsp.JumpToDiag('first') command! -nargs=0 -bar LspDiagHighlightDisable lsp.DiagHighlightDisable() diff --git a/test/unit_tests.vim b/test/unit_tests.vim index dd16bfd..777649a 100644 --- a/test/unit_tests.vim +++ b/test/unit_tests.vim @@ -343,28 +343,59 @@ def Test_LspCodeAction() sleep 1 cursor(4, 1) redraw! - g:LSPTest_CodeActionChoice = 1 - :LspCodeAction + :LspCodeAction 1 assert_equal("\tcount = 20;", getline(4)) setline(4, "\tcount = 20:") cursor(4, 1) sleep 500m - g:LSPTest_CodeActionChoice = 0 - :LspCodeAction + :LspCodeAction 0 assert_equal("\tcount = 20:", getline(4)) - g:LSPTest_CodeActionChoice = 2 cursor(4, 1) - :LspCodeAction + :LspCodeAction 2 assert_equal("\tcount = 20:", getline(4)) - g:LSPTest_CodeActionChoice = 1 cursor(4, 1) - :LspCodeAction + :LspCodeAction 1 assert_equal("\tcount = 20;", getline(4)) bw! + # pattern and string prefix + silent! edit Xtest.c + sleep 200m + var lines2: list =<< trim END + void testFunc() + { + int count; + if (count = 1) { + } + } + END + setline(1, lines2) + sleep 1 + cursor(4, 1) + redraw! + :LspCodeAction use + assert_equal("\tif (count == 1) {", getline(4)) + + setline(4, "\tif (count = 1) {") + cursor(4, 1) + sleep 500m + :LspCodeAction /paren + assert_equal("\tif ((count = 1)) {", getline(4)) + + setline(4, "\tif (count = 1) {") + cursor(4, 1) + sleep 500m + :LspCodeAction NON_EXISTING_PREFIX + assert_equal("\tif (count = 1) {", getline(4)) + + cursor(4, 1) + :LspCodeAction /NON_EXISTING_REGEX + assert_equal("\tif (count = 1) {", getline(4)) + bw! + # empty file assert_equal('', execute('LspCodeAction'))