mirror of
https://github.com/prabirshrestha/vim-lsp.git
synced 2025-12-14 20:35:59 +01:00
Show diagnostics in a floating window (#700)
* fix comment
* fix indent
* support diagnostics in a floating window
* doc: add g:lsp_diagnostics_float_{cursor,delay}
* fix vint errors except unused variables
* suppress vint unused variable errors
* lint: use robust operator
This commit is contained in:
@@ -3,7 +3,7 @@ cmdargs:
|
||||
|
||||
policies:
|
||||
ProhibitUnusedVariable:
|
||||
enabled: true
|
||||
enabled: false
|
||||
ProhibitImplicitScopeVariable:
|
||||
enabled: true
|
||||
ProhibitNoAbortFunction:
|
||||
|
||||
@@ -115,7 +115,7 @@ endfunction
|
||||
" "exited", "starting", "failed", "running", "not running"
|
||||
function! lsp#get_server_status(...) abort
|
||||
if a:0 == 0
|
||||
let l:strs = map(keys(s:servers), {k, v -> v . ": " . s:server_status(v)})
|
||||
let l:strs = map(keys(s:servers), {k, v -> v . ': ' . s:server_status(v)})
|
||||
return join(l:strs, "\n")
|
||||
else
|
||||
return s:server_status(a:1)
|
||||
@@ -189,7 +189,7 @@ function! s:register_events() abort
|
||||
if exists('##TextChangedP')
|
||||
autocmd TextChangedP * call s:on_text_document_did_change()
|
||||
endif
|
||||
if g:lsp_diagnostics_echo_cursor || g:lsp_highlight_references_enabled
|
||||
if g:lsp_diagnostics_echo_cursor || g:lsp_diagnostics_float_cursor || g:lsp_highlight_references_enabled
|
||||
autocmd CursorMoved * call s:on_cursor_moved()
|
||||
endif
|
||||
autocmd BufWinEnter,BufWinLeave,InsertEnter * call lsp#ui#vim#references#clean_references()
|
||||
@@ -243,6 +243,8 @@ function! s:on_cursor_moved() abort
|
||||
|
||||
if g:lsp_diagnostics_echo_cursor
|
||||
call lsp#ui#vim#diagnostics#echo#cursor_moved()
|
||||
elseif g:lsp_diagnostics_float_cursor && lsp#ui#vim#output#float_supported()
|
||||
call lsp#ui#vim#diagnostics#float#cursor_moved()
|
||||
endif
|
||||
|
||||
if g:lsp_highlight_references_enabled
|
||||
@@ -517,7 +519,7 @@ function! s:ensure_init(buf, server_name, cb) abort
|
||||
if has_key(l:server_info, 'capabilities')
|
||||
let l:capabilities = l:server_info['capabilities']
|
||||
else
|
||||
let l:capabilities = call(g:lsp_get_supported_capabilities[0], [server_info])
|
||||
let l:capabilities = call(g:lsp_get_supported_capabilities[0], [l:server_info])
|
||||
endif
|
||||
|
||||
let l:request = {
|
||||
@@ -886,8 +888,8 @@ function! s:add_didchange_queue(buf) abort
|
||||
call add(s:didchange_queue, a:buf)
|
||||
call lsp#log('s:send_didchange_queue() will be triggered')
|
||||
call timer_stop(s:didchange_timer)
|
||||
let lazy = &updatetime > 1000 ? &updatetime : 1000
|
||||
let s:didchange_timer = timer_start(lazy, function('s:send_didchange_queue'))
|
||||
let l:lazy = &updatetime > 1000 ? &updatetime : 1000
|
||||
let s:didchange_timer = timer_start(l:lazy, function('s:send_didchange_queue'))
|
||||
endfunction
|
||||
|
||||
function! s:send_didchange_queue(...) abort
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
let s:save_cpo = &cpoptions
|
||||
set cpoptions&vim
|
||||
|
||||
let s:clients = {} " { client_id: ctx }
|
||||
|
||||
@@ -268,10 +268,10 @@ function! s:lsp_get_last_request_id(id) abort
|
||||
endfunction
|
||||
|
||||
function! s:lsp_is_error(obj_or_response) abort
|
||||
let vt = type(a:obj_or_response)
|
||||
if vt == type('')
|
||||
let l:vt = type(a:obj_or_response)
|
||||
if l:vt == type('')
|
||||
return len(a:obj_or_response) > 0
|
||||
elseif vt == type({})
|
||||
elseif l:vt == type({})
|
||||
return has_key(a:obj_or_response, 'error')
|
||||
endif
|
||||
return 0
|
||||
@@ -330,6 +330,6 @@ endfunction
|
||||
|
||||
" }}}
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
let &cpoptions = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
" vim sw=4 ts=4 et
|
||||
|
||||
@@ -249,14 +249,14 @@ function! lsp#ui#vim#document_format() abort
|
||||
endfunction
|
||||
|
||||
function! lsp#ui#vim#stop_server(...) abort
|
||||
let l:name = get(a:000, 0, '')
|
||||
for l:server in lsp#get_whitelisted_servers()
|
||||
if !empty(l:name) && l:server != l:name
|
||||
continue
|
||||
endif
|
||||
echo 'Stopping' l:server 'server ...'
|
||||
call lsp#stop_server(server)
|
||||
endfor
|
||||
let l:name = get(a:000, 0, '')
|
||||
for l:server in lsp#get_whitelisted_servers()
|
||||
if !empty(l:name) && l:server != l:name
|
||||
continue
|
||||
endif
|
||||
echo 'Stopping' l:server 'server ...'
|
||||
call lsp#stop_server(l:server)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:get_selection_pos(type) abort
|
||||
@@ -439,15 +439,15 @@ function! s:handle_location(ctx, server, type, data) abort "ctx = {counter, list
|
||||
if has_key(l:loc,'viewstart') " showing a locationLink
|
||||
let l:view = l:lines[l:loc['viewstart'] : l:loc['viewend']]
|
||||
call lsp#ui#vim#output#preview(a:server, l:view, {
|
||||
\ 'statusline': ' LSP Peek ' . a:type,
|
||||
\ 'filetype': &filetype
|
||||
\ })
|
||||
\ 'statusline': ' LSP Peek ' . a:type,
|
||||
\ 'filetype': &filetype
|
||||
\ })
|
||||
else " showing a location
|
||||
call lsp#ui#vim#output#preview(a:server, l:lines, {
|
||||
\ 'statusline': ' LSP Peek ' . a:type,
|
||||
\ 'cursor': { 'line': l:loc['lnum'], 'col': l:loc['col'], 'align': g:lsp_peek_alignment },
|
||||
\ 'filetype': &filetype
|
||||
\ })
|
||||
\ 'statusline': ' LSP Peek ' . a:type,
|
||||
\ 'cursor': { 'line': l:loc['lnum'], 'col': l:loc['col'], 'align': g:lsp_peek_alignment },
|
||||
\ 'filetype': &filetype
|
||||
\ })
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -582,9 +582,9 @@ function! s:get_treeitem_for_tree_hierarchy(Callback, object) dict abort
|
||||
endfunction
|
||||
|
||||
function! lsp#ui#vim#code_action() abort
|
||||
call lsp#ui#vim#code_action#do({
|
||||
\ 'sync': v:false,
|
||||
\ 'selection': v:false,
|
||||
\ 'query': '',
|
||||
\ })
|
||||
call lsp#ui#vim#code_action#do({
|
||||
\ 'sync': v:false,
|
||||
\ 'selection': v:false,
|
||||
\ 'query': '',
|
||||
\ })
|
||||
endfunction
|
||||
|
||||
@@ -35,7 +35,7 @@ function! lsp#ui#vim#diagnostics#document_diagnostics() abort
|
||||
endif
|
||||
|
||||
let l:result = []
|
||||
for [l:server_name, l:data] in items(l:diagnostics)
|
||||
for l:data in values(l:diagnostics)
|
||||
let l:result += lsp#ui#vim#utils#diagnostics_to_loc_list(l:data)
|
||||
endfor
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function! lsp#ui#vim#diagnostics#echo#cursor_moved() abort
|
||||
if mode() isnot# 'n'
|
||||
" dont' show echo only in normal mode
|
||||
" show echo only in normal mode
|
||||
return
|
||||
endif
|
||||
|
||||
|
||||
32
autoload/lsp/ui/vim/diagnostics/float.vim
Normal file
32
autoload/lsp/ui/vim/diagnostics/float.vim
Normal file
@@ -0,0 +1,32 @@
|
||||
function! lsp#ui#vim#diagnostics#float#cursor_moved() abort
|
||||
call s:stop_cursor_moved_timer()
|
||||
|
||||
let l:current_pos = getcurpos()[0:2]
|
||||
|
||||
" use timer to avoid recalculation
|
||||
if !exists('s:last_pos') || l:current_pos != s:last_pos
|
||||
let s:last_pos = l:current_pos
|
||||
let s:cursor_moved_timer = timer_start(g:lsp_diagnostics_float_delay, function('s:float_diagnostics_under_cursor'))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:float_diagnostics_under_cursor(...) abort
|
||||
let l:diagnostic = lsp#ui#vim#diagnostics#get_diagnostics_under_cursor()
|
||||
if !empty(l:diagnostic) && has_key(l:diagnostic, 'message')
|
||||
let l:lines = split(l:diagnostic['message'], '\n', 1)
|
||||
call lsp#ui#vim#output#preview('', l:lines, {
|
||||
\ 'statusline': ' LSP Diagnostics'
|
||||
\})
|
||||
let s:displaying_message = 1
|
||||
elseif get(s:, 'displaying_message', 0)
|
||||
call lsp#ui#vim#output#closepreview()
|
||||
let s:displaying_message = 0
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:stop_cursor_moved_timer() abort
|
||||
if exists('s:cursor_moved_timer')
|
||||
call timer_stop(s:cursor_moved_timer)
|
||||
unlet s:cursor_moved_timer
|
||||
endif
|
||||
endfunction
|
||||
@@ -11,58 +11,58 @@ function! s:vim_popup_closed(...) abort
|
||||
endfunction
|
||||
|
||||
function! lsp#ui#vim#output#closepreview() abort
|
||||
if win_getid() == s:winid
|
||||
" Don't close if window got focus
|
||||
return
|
||||
endif
|
||||
"closing floats in vim8.1 must use popup_close() (nvim could use nvim_win_close but pclose
|
||||
"works)
|
||||
if s:use_vim_popup && s:winid
|
||||
call popup_close(s:winid)
|
||||
else
|
||||
pclose
|
||||
endif
|
||||
let s:winid = v:false
|
||||
let s:preview_data = v:false
|
||||
augroup lsp_float_preview_close
|
||||
augroup end
|
||||
autocmd! lsp_float_preview_close CursorMoved,CursorMovedI,VimResized *
|
||||
doautocmd User lsp_float_closed
|
||||
if win_getid() ==# s:winid
|
||||
" Don't close if window got focus
|
||||
return
|
||||
endif
|
||||
"closing floats in vim8.1 must use popup_close() (nvim could use nvim_win_close but pclose
|
||||
"works)
|
||||
if s:use_vim_popup && s:winid
|
||||
call popup_close(s:winid)
|
||||
else
|
||||
pclose
|
||||
endif
|
||||
let s:winid = v:false
|
||||
let s:preview_data = v:false
|
||||
augroup lsp_float_preview_close
|
||||
augroup end
|
||||
autocmd! lsp_float_preview_close CursorMoved,CursorMovedI,VimResized *
|
||||
doautocmd User lsp_float_closed
|
||||
endfunction
|
||||
|
||||
function! lsp#ui#vim#output#focuspreview() abort
|
||||
" This does not work for vim8.1 popup but will work for nvim and old preview
|
||||
if s:winid
|
||||
if win_getid() != s:winid
|
||||
let s:prevwin = win_getid()
|
||||
call win_gotoid(s:winid)
|
||||
elseif s:prevwin
|
||||
" Temporarily disable hooks
|
||||
" TODO: remove this when closing logic is able to distinguish different move directions
|
||||
autocmd! lsp_float_preview_close CursorMoved,CursorMovedI,VimResized *
|
||||
call win_gotoid(s:prevwin)
|
||||
call s:add_float_closing_hooks()
|
||||
let s:prevwin = v:false
|
||||
" This does not work for vim8.1 popup but will work for nvim and old preview
|
||||
if s:winid
|
||||
if win_getid() !=# s:winid
|
||||
let s:prevwin = win_getid()
|
||||
call win_gotoid(s:winid)
|
||||
elseif s:prevwin
|
||||
" Temporarily disable hooks
|
||||
" TODO: remove this when closing logic is able to distinguish different move directions
|
||||
autocmd! lsp_float_preview_close CursorMoved,CursorMovedI,VimResized *
|
||||
call win_gotoid(s:prevwin)
|
||||
call s:add_float_closing_hooks()
|
||||
let s:prevwin = v:false
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:bufwidth() abort
|
||||
let width = winwidth(0)
|
||||
let numberwidth = max([&numberwidth, strlen(line('$'))+1])
|
||||
let numwidth = (&number || &relativenumber)? numberwidth : 0
|
||||
let foldwidth = &foldcolumn
|
||||
let l:width = winwidth(0)
|
||||
let l:numberwidth = max([&numberwidth, strlen(line('$'))+1])
|
||||
let l:numwidth = (&number || &relativenumber)? l:numberwidth : 0
|
||||
let l:foldwidth = &foldcolumn
|
||||
|
||||
if &signcolumn ==? 'yes'
|
||||
let signwidth = 2
|
||||
elseif &signcolumn ==? 'auto'
|
||||
let signs = execute(printf('sign place buffer=%d', bufnr('')))
|
||||
let signs = split(signs, "\n")
|
||||
let signwidth = len(signs)>2? 2: 0
|
||||
else
|
||||
let signwidth = 0
|
||||
endif
|
||||
return width - numwidth - foldwidth - signwidth
|
||||
if &signcolumn ==? 'yes'
|
||||
let l:signwidth = 2
|
||||
elseif &signcolumn ==? 'auto'
|
||||
let l:signs = execute(printf('sign place buffer=%d', bufnr('')))
|
||||
let l:signs = split(l:signs, "\n")
|
||||
let l:signwidth = len(l:signs)>2? 2: 0
|
||||
else
|
||||
let l:signwidth = 0
|
||||
endif
|
||||
return l:width - l:numwidth - l:foldwidth - l:signwidth
|
||||
endfunction
|
||||
|
||||
|
||||
@@ -73,118 +73,118 @@ function! s:get_float_positioning(height, width) abort
|
||||
" TODO: add option to configure it 'docked' at the bottom/top/right
|
||||
let l:y = winline()
|
||||
if l:y + l:height >= winheight(0)
|
||||
" Float does not fit
|
||||
if l:y > l:height
|
||||
" Fits above
|
||||
let l:y = winline() - l:height - 1
|
||||
elseif l:y - 2 > winheight(0) - l:y
|
||||
" Take space above cursor
|
||||
let l:y = 1
|
||||
let l:height = winline()-2
|
||||
else
|
||||
" Take space below cursor
|
||||
let l:height = winheight(0) -l:y
|
||||
endif
|
||||
" Float does not fit
|
||||
if l:y > l:height
|
||||
" Fits above
|
||||
let l:y = winline() - l:height - 1
|
||||
elseif l:y - 2 > winheight(0) - l:y
|
||||
" Take space above cursor
|
||||
let l:y = 1
|
||||
let l:height = winline()-2
|
||||
else
|
||||
" Take space below cursor
|
||||
let l:height = winheight(0) -l:y
|
||||
endif
|
||||
endif
|
||||
let l:col = col('.')
|
||||
let l:style = 'minimal'
|
||||
" Positioning is not window but screen relative
|
||||
let l:opts = {
|
||||
\ 'relative': 'win',
|
||||
\ 'row': l:y,
|
||||
\ 'col': l:col,
|
||||
\ 'width': l:width,
|
||||
\ 'height': l:height,
|
||||
\ 'style': l:style,
|
||||
\ }
|
||||
\ 'relative': 'win',
|
||||
\ 'row': l:y,
|
||||
\ 'col': l:col,
|
||||
\ 'width': l:width,
|
||||
\ 'height': l:height,
|
||||
\ 'style': l:style,
|
||||
\ }
|
||||
return l:opts
|
||||
endfunction
|
||||
|
||||
function! lsp#ui#vim#output#floatingpreview(data) abort
|
||||
if s:use_nvim_float
|
||||
let l:buf = nvim_create_buf(v:false, v:true)
|
||||
call setbufvar(l:buf, '&signcolumn', 'no')
|
||||
if s:use_nvim_float
|
||||
let l:buf = nvim_create_buf(v:false, v:true)
|
||||
call setbufvar(l:buf, '&signcolumn', 'no')
|
||||
|
||||
" Try to get as much space around the cursor, but at least 10x10
|
||||
let l:width = max([s:bufwidth(), 10])
|
||||
let l:height = max([&lines - winline() + 1, winline() - 1, 10])
|
||||
" Try to get as much space around the cursor, but at least 10x10
|
||||
let l:width = max([s:bufwidth(), 10])
|
||||
let l:height = max([&lines - winline() + 1, winline() - 1, 10])
|
||||
|
||||
if g:lsp_preview_max_height > 0
|
||||
let l:height = min([g:lsp_preview_max_height, l:height])
|
||||
if g:lsp_preview_max_height > 0
|
||||
let l:height = min([g:lsp_preview_max_height, l:height])
|
||||
endif
|
||||
|
||||
let l:opts = s:get_float_positioning(l:height, l:width)
|
||||
|
||||
let s:winid = nvim_open_win(l:buf, v:true, l:opts)
|
||||
call nvim_win_set_option(s:winid, 'winhl', 'Normal:Pmenu,NormalNC:Pmenu')
|
||||
call nvim_win_set_option(s:winid, 'foldenable', v:false)
|
||||
call nvim_win_set_option(s:winid, 'wrap', v:true)
|
||||
call nvim_win_set_option(s:winid, 'statusline', '')
|
||||
call nvim_win_set_option(s:winid, 'number', v:false)
|
||||
call nvim_win_set_option(s:winid, 'relativenumber', v:false)
|
||||
call nvim_win_set_option(s:winid, 'cursorline', v:false)
|
||||
" Enable closing the preview with esc, but map only in the scratch buffer
|
||||
nmap <buffer><silent> <esc> :pclose<cr>
|
||||
elseif s:use_vim_popup
|
||||
let l:options = {
|
||||
\ 'moved': 'any',
|
||||
\ 'border': [1, 1, 1, 1],
|
||||
\ 'callback': function('s:vim_popup_closed')
|
||||
\ }
|
||||
|
||||
if g:lsp_preview_max_width > 0
|
||||
let l:options['maxwidth'] = g:lsp_preview_max_width
|
||||
endif
|
||||
|
||||
if g:lsp_preview_max_height > 0
|
||||
let l:options['maxheight'] = g:lsp_preview_max_height
|
||||
endif
|
||||
|
||||
let s:winid = popup_atcursor('...', l:options)
|
||||
endif
|
||||
|
||||
let l:opts = s:get_float_positioning(l:height, l:width)
|
||||
|
||||
let s:winid = nvim_open_win(buf, v:true, l:opts)
|
||||
call nvim_win_set_option(s:winid, 'winhl', 'Normal:Pmenu,NormalNC:Pmenu')
|
||||
call nvim_win_set_option(s:winid, 'foldenable', v:false)
|
||||
call nvim_win_set_option(s:winid, 'wrap', v:true)
|
||||
call nvim_win_set_option(s:winid, 'statusline', '')
|
||||
call nvim_win_set_option(s:winid, 'number', v:false)
|
||||
call nvim_win_set_option(s:winid, 'relativenumber', v:false)
|
||||
call nvim_win_set_option(s:winid, 'cursorline', v:false)
|
||||
" Enable closing the preview with esc, but map only in the scratch buffer
|
||||
nmap <buffer><silent> <esc> :pclose<cr>
|
||||
elseif s:use_vim_popup
|
||||
let l:options = {
|
||||
\ 'moved': 'any',
|
||||
\ 'border': [1, 1, 1, 1],
|
||||
\ 'callback': function('s:vim_popup_closed')
|
||||
\ }
|
||||
|
||||
if g:lsp_preview_max_width > 0
|
||||
let l:options['maxwidth'] = g:lsp_preview_max_width
|
||||
endif
|
||||
|
||||
if g:lsp_preview_max_height > 0
|
||||
let l:options['maxheight'] = g:lsp_preview_max_height
|
||||
endif
|
||||
|
||||
let s:winid = popup_atcursor('...', l:options)
|
||||
endif
|
||||
return s:winid
|
||||
return s:winid
|
||||
endfunction
|
||||
|
||||
function! s:setcontent(lines, ft) abort
|
||||
if s:use_vim_popup
|
||||
" vim popup
|
||||
call setbufline(winbufnr(s:winid), 1, a:lines)
|
||||
let l:lightline_toggle = v:false
|
||||
if exists('#lightline') && !has('nvim')
|
||||
" Lightline does not work in popups but does not recognize it yet.
|
||||
" It is ugly to have an check for an other plugin here, better fix lightline...
|
||||
let l:lightline_toggle = v:true
|
||||
call lightline#disable()
|
||||
endif
|
||||
call win_execute(s:winid, 'setlocal filetype=' . a:ft . '.lsp-hover')
|
||||
if l:lightline_toggle
|
||||
call lightline#enable()
|
||||
endif
|
||||
else
|
||||
" nvim floating or preview
|
||||
call setline(1, a:lines)
|
||||
if s:use_vim_popup
|
||||
" vim popup
|
||||
call setbufline(winbufnr(s:winid), 1, a:lines)
|
||||
let l:lightline_toggle = v:false
|
||||
if exists('#lightline') && !has('nvim')
|
||||
" Lightline does not work in popups but does not recognize it yet.
|
||||
" It is ugly to have an check for an other plugin here, better fix lightline...
|
||||
let l:lightline_toggle = v:true
|
||||
call lightline#disable()
|
||||
endif
|
||||
call win_execute(s:winid, 'setlocal filetype=' . a:ft . '.lsp-hover')
|
||||
if l:lightline_toggle
|
||||
call lightline#enable()
|
||||
endif
|
||||
else
|
||||
" nvim floating or preview
|
||||
call setline(1, a:lines)
|
||||
|
||||
setlocal readonly nomodifiable
|
||||
silent! let &l:filetype = a:ft . '.lsp-hover'
|
||||
endif
|
||||
setlocal readonly nomodifiable
|
||||
silent! let &l:filetype = a:ft . '.lsp-hover'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:adjust_float_placement(bufferlines, maxwidth) abort
|
||||
if s:use_nvim_float
|
||||
let l:win_config = {}
|
||||
let l:height = min([winheight(s:winid), a:bufferlines])
|
||||
let l:width = min([winwidth(s:winid), a:maxwidth])
|
||||
let l:win_config = s:get_float_positioning(l:height, l:width)
|
||||
call nvim_win_set_config(s:winid, l:win_config )
|
||||
let l:win_config = {}
|
||||
let l:height = min([winheight(s:winid), a:bufferlines])
|
||||
let l:width = min([winwidth(s:winid), a:maxwidth])
|
||||
let l:win_config = s:get_float_positioning(l:height, l:width)
|
||||
call nvim_win_set_config(s:winid, l:win_config )
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:add_float_closing_hooks() abort
|
||||
if g:lsp_preview_autoclose
|
||||
augroup lsp_float_preview_close
|
||||
autocmd! lsp_float_preview_close CursorMoved,CursorMovedI,VimResized *
|
||||
autocmd CursorMoved,CursorMovedI,VimResized * call lsp#ui#vim#output#closepreview()
|
||||
augroup END
|
||||
augroup lsp_float_preview_close
|
||||
autocmd! lsp_float_preview_close CursorMoved,CursorMovedI,VimResized *
|
||||
autocmd CursorMoved,CursorMovedI,VimResized * call lsp#ui#vim#output#closepreview()
|
||||
augroup END
|
||||
endif
|
||||
endfunction
|
||||
|
||||
@@ -194,10 +194,10 @@ endfunction
|
||||
|
||||
function! s:open_preview(data) abort
|
||||
if s:use_vim_popup || s:use_nvim_float
|
||||
let l:winid = lsp#ui#vim#output#floatingpreview(a:data)
|
||||
let l:winid = lsp#ui#vim#output#floatingpreview(a:data)
|
||||
else
|
||||
execute &previewheight.'new'
|
||||
let l:winid = win_getid()
|
||||
execute &previewheight.'new'
|
||||
let l:winid = win_getid()
|
||||
endif
|
||||
return l:winid
|
||||
endfunction
|
||||
@@ -208,37 +208,37 @@ function! s:set_cursor(current_window_id, options) abort
|
||||
endif
|
||||
|
||||
if s:use_nvim_float
|
||||
" Neovim floats
|
||||
" Go back to the preview window to set the cursor
|
||||
call win_gotoid(s:winid)
|
||||
let l:old_scrolloff = &scrolloff
|
||||
let &scrolloff = 0
|
||||
" Neovim floats
|
||||
" Go back to the preview window to set the cursor
|
||||
call win_gotoid(s:winid)
|
||||
let l:old_scrolloff = &scrolloff
|
||||
let &scrolloff = 0
|
||||
|
||||
call nvim_win_set_cursor(s:winid, [a:options['cursor']['line'], a:options['cursor']['col']])
|
||||
call s:align_preview(a:options)
|
||||
call nvim_win_set_cursor(s:winid, [a:options['cursor']['line'], a:options['cursor']['col']])
|
||||
call s:align_preview(a:options)
|
||||
|
||||
" Finally, go back to the original window
|
||||
call win_gotoid(a:current_window_id)
|
||||
" Finally, go back to the original window
|
||||
call win_gotoid(a:current_window_id)
|
||||
|
||||
let &scrolloff = l:old_scrolloff
|
||||
let &scrolloff = l:old_scrolloff
|
||||
elseif s:use_vim_popup
|
||||
" Vim popups
|
||||
function! AlignVimPopup(timer) closure abort
|
||||
call s:align_preview(a:options)
|
||||
endfunction
|
||||
call timer_start(0, function('AlignVimPopup'))
|
||||
" Vim popups
|
||||
function! AlignVimPopup(timer) closure abort
|
||||
call s:align_preview(a:options)
|
||||
endfunction
|
||||
call timer_start(0, function('AlignVimPopup'))
|
||||
else
|
||||
" Preview
|
||||
" Don't use 'scrolloff', it might mess up the cursor's position
|
||||
let &l:scrolloff = 0
|
||||
call cursor(a:options['cursor']['line'], a:options['cursor']['col'])
|
||||
call s:align_preview(a:options)
|
||||
" Preview
|
||||
" Don't use 'scrolloff', it might mess up the cursor's position
|
||||
let &l:scrolloff = 0
|
||||
call cursor(a:options['cursor']['line'], a:options['cursor']['col'])
|
||||
call s:align_preview(a:options)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:align_preview(options) abort
|
||||
if !has_key(a:options, 'cursor') ||
|
||||
\ !has_key(a:options['cursor'], 'align')
|
||||
\ !has_key(a:options['cursor'], 'align')
|
||||
return
|
||||
endif
|
||||
|
||||
@@ -256,13 +256,13 @@ function! s:align_preview(options) abort
|
||||
let l:width = l:pos['core_width']
|
||||
|
||||
let l:options = {
|
||||
\ 'minwidth': l:width,
|
||||
\ 'maxwidth': l:width,
|
||||
\ 'minheight': l:height,
|
||||
\ 'maxheight': l:height,
|
||||
\ 'pos': l:below ? 'topleft' : 'botleft',
|
||||
\ 'line': l:below ? 'cursor+1' : 'cursor-1'
|
||||
\ }
|
||||
\ 'minwidth': l:width,
|
||||
\ 'maxwidth': l:width,
|
||||
\ 'minheight': l:height,
|
||||
\ 'maxheight': l:height,
|
||||
\ 'pos': l:below ? 'topleft' : 'botleft',
|
||||
\ 'line': l:below ? 'cursor+1' : 'cursor-1'
|
||||
\ }
|
||||
|
||||
if l:align ==? 'top'
|
||||
let l:options['firstline'] = a:options['cursor']['line']
|
||||
@@ -286,13 +286,17 @@ function! s:align_preview(options) abort
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lsp#ui#vim#output#float_supported() abort
|
||||
return s:use_vim_popup || s:use_nvim_float
|
||||
endfunction
|
||||
|
||||
function! lsp#ui#vim#output#preview(server, data, options) abort
|
||||
if s:winid && type(s:preview_data) == type(a:data)
|
||||
\ && s:preview_data == a:data
|
||||
\ && type(g:lsp_preview_doubletap) == 3
|
||||
\ && len(g:lsp_preview_doubletap) >= 1
|
||||
\ && type(g:lsp_preview_doubletap[0]) == 2
|
||||
\ && index(['i', 's'], mode()[0]) == -1
|
||||
if s:winid && type(s:preview_data) ==# type(a:data)
|
||||
\ && s:preview_data ==# a:data
|
||||
\ && type(g:lsp_preview_doubletap) ==# 3
|
||||
\ && len(g:lsp_preview_doubletap) >= 1
|
||||
\ && type(g:lsp_preview_doubletap[0]) ==# 2
|
||||
\ && index(['i', 's'], mode()[0]) ==# -1
|
||||
echo ''
|
||||
return call(g:lsp_preview_doubletap[0], [])
|
||||
endif
|
||||
@@ -310,8 +314,8 @@ function! lsp#ui#vim#output#preview(server, data, options) abort
|
||||
|
||||
" If the server response is empty content, we don't display anything.
|
||||
if empty(l:lines) && empty(l:syntax_lines)
|
||||
echo ''
|
||||
return
|
||||
echo ''
|
||||
return
|
||||
endif
|
||||
|
||||
let s:winid = s:open_preview(a:data)
|
||||
@@ -320,12 +324,10 @@ function! lsp#ui#vim#output#preview(server, data, options) abort
|
||||
let l:ft = a:options['filetype']
|
||||
endif
|
||||
|
||||
let l:server_info = lsp#get_server_info(a:server)
|
||||
try
|
||||
let l:do_conceal = l:server_info['config']['hover_conceal']
|
||||
catch
|
||||
let l:do_conceal = g:lsp_hover_conceal
|
||||
endtry
|
||||
let l:do_conceal = g:lsp_hover_conceal
|
||||
let l:server_info = a:server !=# '' ? lsp#get_server_info(a:server) : {}
|
||||
let l:config = get(l:server_info, 'config', {})
|
||||
let l:do_conceal = get(l:config, 'hover_conceal', l:do_conceal)
|
||||
|
||||
call setbufvar(winbufnr(s:winid), 'lsp_syntax_highlights', l:syntax_lines)
|
||||
call setbufvar(winbufnr(s:winid), 'lsp_do_conceal', l:do_conceal)
|
||||
@@ -334,17 +336,17 @@ function! lsp#ui#vim#output#preview(server, data, options) abort
|
||||
" Get size information while still having the buffer active
|
||||
let l:maxwidth = max(map(getline(1, '$'), 'strdisplaywidth(v:val)'))
|
||||
if g:lsp_preview_max_width > 0
|
||||
let l:bufferlines = 0
|
||||
let l:maxwidth = min([g:lsp_preview_max_width, l:maxwidth])
|
||||
let l:bufferlines = 0
|
||||
let l:maxwidth = min([g:lsp_preview_max_width, l:maxwidth])
|
||||
|
||||
" Determine, for each line, how many "virtual" lines it spans, and add
|
||||
" these together for all lines in the buffer
|
||||
for l:line in getline(1, '$')
|
||||
let l:num_lines = str2nr(string(ceil(strdisplaywidth(l:line) * 1.0 / g:lsp_preview_max_width)))
|
||||
let l:bufferlines += max([l:num_lines, 1])
|
||||
endfor
|
||||
" Determine, for each line, how many "virtual" lines it spans, and add
|
||||
" these together for all lines in the buffer
|
||||
for l:line in getline(1, '$')
|
||||
let l:num_lines = str2nr(string(ceil(strdisplaywidth(l:line) * 1.0 / g:lsp_preview_max_width)))
|
||||
let l:bufferlines += max([l:num_lines, 1])
|
||||
endfor
|
||||
else
|
||||
let l:bufferlines = line('$')
|
||||
let l:bufferlines = line('$')
|
||||
endif
|
||||
|
||||
if s:use_preview
|
||||
@@ -362,22 +364,22 @@ function! lsp#ui#vim#output#preview(server, data, options) abort
|
||||
echo ''
|
||||
|
||||
if s:winid && (s:use_vim_popup || s:use_nvim_float)
|
||||
if s:use_nvim_float
|
||||
" Neovim floats
|
||||
call s:adjust_float_placement(l:bufferlines, l:maxwidth)
|
||||
call s:set_cursor(l:current_window_id, a:options)
|
||||
call s:add_float_closing_hooks()
|
||||
elseif s:use_vim_popup
|
||||
" Vim popups
|
||||
call s:set_cursor(l:current_window_id, a:options)
|
||||
endif
|
||||
if s:use_nvim_float
|
||||
" Neovim floats
|
||||
call s:adjust_float_placement(l:bufferlines, l:maxwidth)
|
||||
call s:set_cursor(l:current_window_id, a:options)
|
||||
call s:add_float_closing_hooks()
|
||||
elseif s:use_vim_popup
|
||||
" Vim popups
|
||||
call s:set_cursor(l:current_window_id, a:options)
|
||||
endif
|
||||
|
||||
doautocmd User lsp_float_opened
|
||||
doautocmd User lsp_float_opened
|
||||
endif
|
||||
|
||||
if !g:lsp_preview_keep_focus
|
||||
" set the focus to the preview window
|
||||
call win_gotoid(s:winid)
|
||||
" set the focus to the preview window
|
||||
call win_gotoid(s:winid)
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
@@ -387,19 +389,19 @@ function! s:escape_string_for_display(str) abort
|
||||
endfunction
|
||||
|
||||
function! s:append(data, lines, syntax_lines) abort
|
||||
if type(a:data) == type([])
|
||||
if type(a:data) ==# type([])
|
||||
for l:entry in a:data
|
||||
call s:append(entry, a:lines, a:syntax_lines)
|
||||
call s:append(l:entry, a:lines, a:syntax_lines)
|
||||
endfor
|
||||
|
||||
return 'markdown'
|
||||
elseif type(a:data) == type('')
|
||||
elseif type(a:data) ==# type('')
|
||||
if !empty(a:data)
|
||||
call extend(a:lines, split(s:escape_string_for_display(a:data), "\n", v:true))
|
||||
endif
|
||||
|
||||
return 'markdown'
|
||||
elseif type(a:data) == type({}) && has_key(a:data, 'language')
|
||||
elseif type(a:data) ==# type({}) && has_key(a:data, 'language')
|
||||
if !empty(a:data.value)
|
||||
let l:new_lines = split(s:escape_string_for_display(a:data.value), '\n')
|
||||
|
||||
@@ -413,9 +415,9 @@ function! s:append(data, lines, syntax_lines) abort
|
||||
endif
|
||||
|
||||
return 'markdown'
|
||||
elseif type(a:data) == type({}) && has_key(a:data, 'kind')
|
||||
elseif type(a:data) ==# type({}) && has_key(a:data, 'kind')
|
||||
if !empty(a:data.value)
|
||||
call extend(a:lines, split(s:escape_string_for_display(a:data.value), '\n', v:true))
|
||||
call extend(a:lines, split(s:escape_string_for_display(a:data.value), '\n', v:true))
|
||||
endif
|
||||
|
||||
return a:data.kind ==? 'plaintext' ? 'text' : a:data.kind
|
||||
|
||||
@@ -19,7 +19,7 @@ function! lsp#ui#vim#signature_help#get_signature_help_under_cursor() abort
|
||||
\ 'method': 'textDocument/signatureHelp',
|
||||
\ 'params': {
|
||||
\ 'textDocument': lsp#get_text_document_identifier(),
|
||||
\ 'position': position,
|
||||
\ 'position': l:position,
|
||||
\ },
|
||||
\ 'on_notification': function('s:handle_signature_help', [l:server]),
|
||||
\ })
|
||||
|
||||
@@ -28,12 +28,12 @@ function! s:encode_uri(path, start_pos_encode, default_prefix) abort
|
||||
|
||||
let l:result = strpart(a:path, 0, a:start_pos_encode)
|
||||
|
||||
for i in range(a:start_pos_encode, len(l:path) - 1)
|
||||
for l:i in range(a:start_pos_encode, len(l:path) - 1)
|
||||
" Don't encode '/' here, `path` is expected to be a valid path.
|
||||
if l:path[i] =~# '^[a-zA-Z0-9_.~/-]$'
|
||||
let l:result .= l:path[i]
|
||||
if l:path[l:i] =~# '^[a-zA-Z0-9_.~/-]$'
|
||||
let l:result .= l:path[l:i]
|
||||
else
|
||||
let l:result .= s:urlencode_char(l:path[i])
|
||||
let l:result .= s:urlencode_char(l:path[l:i])
|
||||
endif
|
||||
endfor
|
||||
|
||||
@@ -116,8 +116,8 @@ endfunction
|
||||
function! lsp#utils#find_nearest_parent_file_directory(path, filename) abort
|
||||
if type(a:filename) == 3
|
||||
let l:matched_paths = {}
|
||||
for current_name in a:filename
|
||||
let l:path = lsp#utils#find_nearest_parent_file_directory(a:path, current_name)
|
||||
for l:current_name in a:filename
|
||||
let l:path = lsp#utils#find_nearest_parent_file_directory(a:path, l:current_name)
|
||||
|
||||
if !empty(l:path)
|
||||
if has_key(l:matched_paths, l:path)
|
||||
|
||||
@@ -56,7 +56,7 @@ function! lsp#utils#buffer#_open_lsp_location(location) abort
|
||||
endif
|
||||
execute l:cmd . ' | call cursor('.l:start_line.','.l:start_col.')'
|
||||
|
||||
normal V
|
||||
normal! V
|
||||
call setpos("'<", [l:bufnr, l:start_line, l:start_col])
|
||||
call setpos("'>", [l:bufnr, l:end_line, l:end_col])
|
||||
endfunction
|
||||
|
||||
@@ -3,7 +3,7 @@ function! lsp#utils#workspace_config#get_value(server_name, item) abort
|
||||
let l:server_info = lsp#get_server_info(a:server_name)
|
||||
let l:config = l:server_info['workspace_config']
|
||||
|
||||
for section in split(a:item['section'], '\.')
|
||||
for l:section in split(a:item['section'], '\.')
|
||||
let l:config = l:config[l:section]
|
||||
endfor
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ CONTENTS *vim-lsp-contents*
|
||||
g:lsp_insert_text_enabled |g:lsp_insert_text_enabled|
|
||||
g:lsp_text_edit_enabled |g:lsp_text_edit_enabled|
|
||||
g:lsp_diagnostics_echo_cursor |g:lsp_diagnostics_echo_cursor|
|
||||
g:lsp_diagnostics_echo_delay |g:lsp_diagnostics_echo_delay|
|
||||
g:lsp_diagnostics_float_cursor |g:lsp_diagnostics_float_cursor|
|
||||
g:lsp_diagnostics_float_delay |g:lsp_diagnostics_float_delay|
|
||||
g:lsp_signs_enabled |g:lsp_signs_enabled|
|
||||
g:lsp_signs_priority |g:lsp_signs_priority|
|
||||
g:lsp_signs_priority_map |g:lsp_signs_priority_map|
|
||||
@@ -344,6 +347,42 @@ g:lsp_diagnostics_echo_cursor *g:lsp_diagnostics_echo_cursor*
|
||||
let g:lsp_diagnostics_echo_cursor = 1
|
||||
let g:lsp_diagnostics_echo_cursor = 0
|
||||
|
||||
g:lsp_diagnostics_echo_delay *g:lsp_diagnostics_echo_delay*
|
||||
Type: |Number|
|
||||
Default: `500`
|
||||
|
||||
Delay milliseconds to echo diagnostic error for the current line to status. Requires
|
||||
Enables echo of diagnostic error for the current line to status. Requires
|
||||
|g:lsp_diagnostics_enabled| and |g:lsp_diagnostics_echo_cursor| set to 1.
|
||||
|
||||
Example: >
|
||||
let g:lsp_diagnostics_echo_delay = 200
|
||||
let g:lsp_diagnostics_echo_delay = 1000
|
||||
|
||||
g:lsp_diagnostics_float_cursor *g:lsp_diagnostics_float_cursor*
|
||||
Type: |Number|
|
||||
Default: `0`
|
||||
|
||||
Enables a floating window of diagnostic error for the current line to status. Requires
|
||||
nvim_win_open() or popup_create is available, and |g:lsp_diagnostics_enabled| set to 1.
|
||||
|
||||
Example: >
|
||||
let g:lsp_diagnostics_float_cursor = 1
|
||||
let g:lsp_diagnostics_float_cursor = 0
|
||||
|
||||
g:lsp_diagnostics_float_delay *g:lsp_diagnostics_float_delay*
|
||||
Type: |Number|
|
||||
Default: `500`
|
||||
|
||||
Delay milliseconds to show diagnostic error for the current line to status
|
||||
in a float window. Requires Enables float of diagnostic error for the
|
||||
current line to status. Requires |g:lsp_diagnostics_enabled| and
|
||||
|g:lsp_diagnostics_echo_cursor| set to 1.
|
||||
|
||||
Example: >
|
||||
let g:lsp_diagnostics_echo_delay = 200
|
||||
let g:lsp_diagnostics_echo_delay = 1000
|
||||
|
||||
g:lsp_signs_enabled *g:lsp_signs_enabled*
|
||||
Type: |Number|
|
||||
Default: `1` for vim/neovim with patch 8.1.0772
|
||||
|
||||
@@ -23,6 +23,8 @@ let g:lsp_signs_priority_map = get(g:, 'lsp_signs_priority_map', {})
|
||||
let g:lsp_diagnostics_enabled = get(g:, 'lsp_diagnostics_enabled', 1)
|
||||
let g:lsp_diagnostics_echo_cursor = get(g:, 'lsp_diagnostics_echo_cursor', 0)
|
||||
let g:lsp_diagnostics_echo_delay = get(g:, 'lsp_diagnostics_echo_delay', 500)
|
||||
let g:lsp_diagnostics_float_cursor = get(g:, 'lsp_diagnostics_float_cursor', 0)
|
||||
let g:lsp_diagnostics_float_delay = get(g:, 'lsp_diagnostics_float_delay', 500)
|
||||
let g:lsp_next_sign_id = get(g:, 'lsp_next_sign_id', 6999)
|
||||
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'))
|
||||
|
||||
Reference in New Issue
Block a user