mirror of
https://github.com/prabirshrestha/vim-lsp.git
synced 2025-12-14 20:35:59 +01:00
[WIP] add codeaction sign support (#1085)
* add codeaction sign support * add hl LspCodeActionText * add docs * add support for multiple servers * only set signs if buffer exists
This commit is contained in:
@@ -61,6 +61,7 @@ function! lsp#enable() abort
|
||||
call lsp#ui#vim#completion#_setup()
|
||||
call lsp#internal#document_highlight#_enable()
|
||||
call lsp#internal#diagnostics#_enable()
|
||||
call lsp#internal#document_code_action#signs#_enable()
|
||||
call lsp#internal#show_message_request#_enable()
|
||||
call lsp#internal#work_done_progress#_enable()
|
||||
call lsp#internal#completion#documentation#_enable()
|
||||
@@ -75,6 +76,7 @@ function! lsp#disable() abort
|
||||
call lsp#ui#vim#completion#_disable()
|
||||
call lsp#internal#document_highlight#_disable()
|
||||
call lsp#internal#diagnostics#_disable()
|
||||
call lsp#internal#document_code_action#signs#_disable()
|
||||
call lsp#internal#show_message_request#_disable()
|
||||
call lsp#internal#work_done_progress#_disable()
|
||||
call lsp#internal#completion#documentation#_disable()
|
||||
|
||||
131
autoload/lsp/internal/document_code_action/signs.vim
Normal file
131
autoload/lsp/internal/document_code_action/signs.vim
Normal file
@@ -0,0 +1,131 @@
|
||||
" https://microsoft.github.io/language-server-protocol/specification#textDocument_codeAction
|
||||
|
||||
" internal state for whether it is enabled or not to avoid multiple subscriptions
|
||||
let s:enabled = 0
|
||||
|
||||
let s:sign_group = 'vim_lsp_document_code_action_signs'
|
||||
|
||||
if !hlexists('LspCodeActionText')
|
||||
highlight link LspCodeActionText Normal
|
||||
endif
|
||||
|
||||
function! lsp#internal#document_code_action#signs#_enable() abort
|
||||
if !lsp#utils#_has_signs() | return | endif
|
||||
" don't even bother registering if the feature is disabled
|
||||
if !g:lsp_document_code_action_signs_enabled | return | endif
|
||||
|
||||
if s:enabled | return | endif
|
||||
let s:enabled = 1
|
||||
|
||||
call s:define_sign('LspCodeAction', 'A>', g:lsp_document_code_action_signs_hint)
|
||||
|
||||
" Note:
|
||||
" - update CodeAction signs when CusorMoved or CursorHold
|
||||
" - clear signs when InsertEnter or BufLeave
|
||||
" - debounce code action requests
|
||||
" - automatically switch to latest code action request via switchMap()
|
||||
" - cancel code action request via takeUntil() when BufLeave
|
||||
let s:Dispose = lsp#callbag#pipe(
|
||||
\ lsp#callbag#merge(
|
||||
\ lsp#callbag#fromEvent(['CursorMoved', 'CursorHold']),
|
||||
\ lsp#callbag#pipe(
|
||||
\ lsp#callbag#fromEvent(['InsertEnter', 'BufLeave']),
|
||||
\ lsp#callbag#tap({_ -> s:clear_signs() }),
|
||||
\ )
|
||||
\ ),
|
||||
\ lsp#callbag#filter({_ -> g:lsp_document_code_action_signs_enabled }),
|
||||
\ lsp#callbag#debounceTime(g:lsp_document_code_action_signs_delay),
|
||||
\ lsp#callbag#map({_->{'bufnr': bufnr('%'), 'curpos': getcurpos()[0:2], 'changedtick': b:changedtick }}),
|
||||
\ lsp#callbag#distinctUntilChanged({a,b -> a['bufnr'] == b['bufnr'] && a['curpos'] == b['curpos'] && a['changedtick'] == b['changedtick']}),
|
||||
\ lsp#callbag#filter({_->mode() is# 'n' && getbufvar(bufnr('%'), '&buftype') !=# 'terminal' }),
|
||||
\ lsp#callbag#switchMap({_->
|
||||
\ lsp#callbag#pipe(
|
||||
\ s:send_request(),
|
||||
\ lsp#callbag#materialize(),
|
||||
\ lsp#callbag#filter({x->lsp#callbag#isNextNotification(x)}),
|
||||
\ lsp#callbag#map({x->x['value']}),
|
||||
\ lsp#callbag#takeUntil(
|
||||
\ lsp#callbag#fromEvent('BufLeave')
|
||||
\ )
|
||||
\ )
|
||||
\ }),
|
||||
\ lsp#callbag#subscribe({x->s:set_signs(x)}),
|
||||
\)
|
||||
endfunction
|
||||
|
||||
function! lsp#internal#document_code_action#signs#_disable() abort
|
||||
if !s:enabled | return | endif
|
||||
if exists('s:Dispose')
|
||||
call s:Dispose()
|
||||
unlet s:Dispose
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:send_request() abort
|
||||
let l:servers = filter(lsp#get_allowed_servers(), 'lsp#capabilities#has_code_action_provider(v:val)')
|
||||
|
||||
if empty(l:servers)
|
||||
return lsp#callbag#empty()
|
||||
endif
|
||||
|
||||
let l:range = lsp#utils#range#_get_current_line_range()
|
||||
return lsp#callbag#pipe(
|
||||
\ lsp#callbag#fromList(l:servers),
|
||||
\ lsp#callbag#flatMap({server->
|
||||
\ lsp#request(server, {
|
||||
\ 'method': 'textDocument/codeAction',
|
||||
\ 'params': {
|
||||
\ 'textDocument': lsp#get_text_document_identifier(),
|
||||
\ 'range': l:range,
|
||||
\ 'context': {
|
||||
\ 'diagnostics': [],
|
||||
\ 'only': ['', 'quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source', 'source.organizeImports'],
|
||||
\ }
|
||||
\ }
|
||||
\ })
|
||||
\ }),
|
||||
\ lsp#callbag#filter({x->!empty(x['response']['result'])}),
|
||||
\ lsp#callbag#take(1),
|
||||
\ )
|
||||
endfunction
|
||||
|
||||
function! s:clear_signs() abort
|
||||
call sign_unplace(s:sign_group)
|
||||
endfunction
|
||||
|
||||
function! s:set_signs(data) abort
|
||||
call s:clear_signs()
|
||||
|
||||
if lsp#client#is_error(a:data['response']) | return | endif
|
||||
|
||||
if empty(a:data['response']['result'])
|
||||
return
|
||||
endif
|
||||
|
||||
let l:bufnr = bufnr(lsp#utils#uri_to_path(a:data['request']['params']['textDocument']['uri']))
|
||||
call s:place_signs(a:data, l:bufnr)
|
||||
endfunction
|
||||
|
||||
" Set default sign text to handle case when user provides empty dict
|
||||
function! s:define_sign(sign_name, sign_default_text, sign_options) abort
|
||||
let l:options = {
|
||||
\ 'text': get(a:sign_options, 'text', a:sign_default_text),
|
||||
\ 'texthl': a:sign_name . 'Text',
|
||||
\ 'linehl': a:sign_name . 'Line',
|
||||
\ }
|
||||
let l:sign_icon = get(a:sign_options, 'icon', '')
|
||||
if !empty(l:sign_icon)
|
||||
let l:options['icon'] = l:sign_icon
|
||||
endif
|
||||
call sign_define(a:sign_name, l:options)
|
||||
endfunction
|
||||
|
||||
function! s:place_signs(data, bufnr) abort
|
||||
if !bufexists(a:bufnr) || !bufloaded(a:bufnr)
|
||||
return
|
||||
endif
|
||||
let l:sign_priority = g:lsp_document_code_action_signs_priority
|
||||
let l:line = lsp#utils#position#lsp_line_to_vim(a:bufnr, a:data['request']['params']['range']['start'])
|
||||
let l:sign_id = sign_place(0, s:sign_group, 'LspCodeAction', a:bufnr,
|
||||
\ { 'lnum': l:line, 'priority': l:sign_priority })
|
||||
endfunction
|
||||
@@ -12,7 +12,7 @@ function! lsp#internal#document_highlight#_enable() abort
|
||||
|
||||
" Note:
|
||||
" - update highlight references when CusorMoved or CursorHold
|
||||
" - clear highlights when InsertEnter of BufLeave
|
||||
" - clear highlights when InsertEnter or BufLeave
|
||||
" - debounce highlight requests
|
||||
" - automatically switch to latest highlight request via switchMap()
|
||||
" - cancel highlight request via takeUntil() when BufLeave
|
||||
|
||||
@@ -49,6 +49,10 @@ CONTENTS *vim-lsp-contents*
|
||||
|g:lsp_diagnostics_virtual_text_delay|
|
||||
g:lsp_diagnostics_virtual_text_prefix
|
||||
|g:lsp_diagnostics_virtual_text_prefix|
|
||||
g:lsp_document_code_action_signs_enabled
|
||||
|g:lsp_document_code_actions_signs_enabled|
|
||||
g:lsp_document_code_action_signs_delay
|
||||
|g:lsp_document_code_actions_signs_delay|
|
||||
g:lsp_format_sync_timeout |g:lsp_format_sync_timeout|
|
||||
g:lsp_use_event_queue |g:lsp_use_event_queue|
|
||||
g:lsp_document_highlight_enabled |g:lsp_document_highlight_enabled|
|
||||
@@ -662,6 +666,29 @@ g:lsp_diagnostics_virtual_text_prefix *g:lsp_diagnostics_virtual_text_prefix*
|
||||
let g:lsp_diagnostics_virtual_text_prefix = "> "
|
||||
let g:lsp_diagnostics_virtual_text_prefix = " ‣ "
|
||||
|
||||
g:lsp_document_code_action_signs_enabled
|
||||
*g:lsp_document_code_action_signs_enabled*
|
||||
Type: |Number|
|
||||
Default: `1`
|
||||
|
||||
Enable support for document code action hints for |signs|.
|
||||
|
||||
Example: >
|
||||
let g:lsp_document_code_action_signs_enabled = 1
|
||||
let g:lsp_document_code_action_signs_enabled = 0
|
||||
<
|
||||
g:lsp_document_code_action_signs_delay
|
||||
*g:lsp_document_code_action_signs_delay*
|
||||
Type: |Number|
|
||||
Default: `500`
|
||||
|
||||
Delay milliseconds to update code action signs. Requires
|
||||
|g:lsp_document_code_action_signs_enabled|.
|
||||
|
||||
Example: >
|
||||
let g:lsp_document_code_action_signs_delay = 200
|
||||
let g:lsp_document_code_action_signs_delay = 1000
|
||||
>
|
||||
g:lsp_use_event_queue *g:lsp_use_event_queue*
|
||||
Type: |Number|
|
||||
Default: `1` for neovim or vim with patch-8.1.0889
|
||||
|
||||
@@ -36,6 +36,11 @@ let g:lsp_diagnostics_virtual_text_insert_mode_enabled = get(g:, 'lsp_diagnostic
|
||||
let g:lsp_diagnostics_virtual_text_delay = get(g:, 'lsp_diagnostics_virtual_text_delay', 500)
|
||||
let g:lsp_diagnostics_virtual_text_prefix = get(g:, 'lsp_diagnostics_virtual_text_prefix', '')
|
||||
|
||||
let g:lsp_document_code_action_signs_enabled = get(g:, 'lsp_document_code_action_signs_enabled', 1)
|
||||
let g:lsp_document_code_action_signs_delay = get(g:, 'lsp_document_code_action_signs_delay', 500)
|
||||
let g:lsp_document_code_action_signs_hint = get(g:, 'lsp_document_code_action_signs_hint', {})
|
||||
let g:lsp_document_code_action_signs_priority = get(g:, 'lsp_document_code_action_signs_priority', 10)
|
||||
|
||||
let g:lsp_preview_keep_focus = get(g:, 'lsp_preview_keep_focus', 1)
|
||||
let g:lsp_use_event_queue = get(g:, 'lsp_use_event_queue', has('nvim') || has('patch-8.1.0889'))
|
||||
let g:lsp_insert_text_enabled= get(g:, 'lsp_insert_text_enabled', 1)
|
||||
|
||||
Reference in New Issue
Block a user