diff --git a/autoload/lsp/ui/vim.vim b/autoload/lsp/ui/vim.vim index 1717ecae0..044bcb478 100644 --- a/autoload/lsp/ui/vim.vim +++ b/autoload/lsp/ui/vim.vim @@ -593,28 +593,34 @@ function! s:handle_code_action(server, last_req_id, type, data) abort return endif - let l:codeActions = a:data['response']['result'] + let l:code_actions = a:data['response']['result'] - let l:index = 0 - let l:choices = [] - - call lsp#log('s:handle_code_action', l:codeActions) + call lsp#log('s:handle_code_action', l:code_actions) - if len(l:codeActions) == 0 + if len(l:code_actions) == 0 echo 'No code actions found' return endif - while l:index < len(l:codeActions) - call add(l:choices, string(l:index + 1) . ' - ' . l:codeActions[index]['title']) + call g:lsp_code_action_selector[0]( + \ l:code_actions, + \ function('execute_command_or_code_action', [a:server]) + \ ) +endfunction + +function! lsp#ui#vim#select_code_action(code_actions, callback) abort + let l:index = 0 + let l:choices = [] + + while l:index < len(a:code_actions) + call add(l:choices, string(l:index + 1) . ' - ' . a:code_actions[index]['title']) let l:index += 1 endwhile let l:choice = inputlist(l:choices) - if l:choice > 0 && l:choice <= l:index - call s:execute_command_or_code_action(a:server, l:codeActions[l:choice - 1]) + call callback(l:code_actions[l:choice - 1]) endif endfunction diff --git a/doc/vim-lsp.txt b/doc/vim-lsp.txt index 05a574433..9e4474129 100644 --- a/doc/vim-lsp.txt +++ b/doc/vim-lsp.txt @@ -36,6 +36,7 @@ CONTENTS *vim-lsp-contents* g:lsp_fold_enabled |g:lsp_fold_enabled| g:lsp_hover_conceal |g:lsp_hover_conceal| g:lsp_ignorecase |g:lsp_ignorecase| + g:lsp_code_action_selector |g:lsp_code_action_selector| g:lsp_log_file |g:lsp_log_file| Functions |vim-lsp-functions| enable |vim-lsp-enable| @@ -528,6 +529,40 @@ g:lsp_ignorecase *g:lsp_ignorecase* items. See |vim-lsp-completion-filter|. By default, the value of |'ignorecase'| is used. +g:lsp_code_action_selector *g:lsp_code_action_selector* + Type: |List| + Default: `[function(lsp#ui#vim#select_code_action)]` + + A |List| containing one element of type |Funcref|. This element is a + reference to the function that vim-lsp uses to show choices of code + actions that provided by server and get user selection. + Changing this variable allows customizing how choices are displayed + in the completion menu, and selector method. + + Example for use `fzf.vim` as selector interface: +> + function! s:select_code_action(code_actions, callback) abort + let l:choices = [] + let l:index = 0 + while l:index < len(a:code_actions) + let l:line = string(l:index) . ' ' . a:code_actions[l:index]['title'] + call add(l:choices, l:line) + + let l:index += 1 + endwhile + + call fzf#run({ + \ 'source': l:choices, + \ 'sink': function('kick_code_action', [a:code_actions, a:callback]), + \ }) + endfunction + let g:lsp_code_action_selector = [function('select_code_action')] + + function! s:kick_code_action(code_actions, callback, line) + let [l:choice; _] = split(a:line) + call a:callback(a:code_actions[l:choice]) + endfunction + g:lsp_log_file *g:lsp_log_file* Type: |String| Default: `''` diff --git a/plugin/lsp.vim b/plugin/lsp.vim index a69ceea00..3a9259ffd 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -39,6 +39,7 @@ let g:lsp_signature_help_enabled = get(g:, 'lsp_signature_help_enabled', 1) let g:lsp_fold_enabled = get(g:, 'lsp_fold_enabled', 1) let g:lsp_hover_conceal = get(g:, 'lsp_hover_conceal', 1) let g:lsp_ignorecase = get(g:, 'lsp_ignorecase', &ignorecase) +let g:lsp_code_action_selector = get(g:, 'lsp_code_action_selector', [function('lsp#ui#vim#select_code_action')]) let g:lsp_get_vim_completion_item = get(g:, 'lsp_get_vim_completion_item', [function('lsp#omni#default_get_vim_completion_item')]) let g:lsp_get_supported_capabilities = get(g:, 'lsp_get_supported_capabilities', [function('lsp#default_get_supported_capabilities')])