Skip to content

Commit 47f9f27

Browse files
committed
preview information shown in hover at the cursor
1 parent 21d51ff commit 47f9f27

File tree

3 files changed

+110
-1
lines changed

3 files changed

+110
-1
lines changed

autoload/lsp/ui/vim/output.vim

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,83 @@
1+
let s:supports_floating = exists('*nvim_open_win')
2+
let s:win = v:false
3+
4+
function! lsp#ui#vim#output#closepreview() abort
5+
if win_getid() == s:win
6+
" Don't close if window got focus
7+
return
8+
endif
9+
pclose
10+
let s:win = v:false
11+
autocmd! lsp_float_preview_close CursorMoved,CursorMovedI,VimResized *
12+
endfunction
13+
14+
function! s:get_float_positioning(height, width)
15+
let l:height = a:height
16+
let l:width = a:width
17+
" For a start show it below/above the cursor
18+
" TODO: add option to configure it 'docked' at the bottom/top/right
19+
let l:y = winline()
20+
if l:y + l:height >= &lines
21+
" Float does not fit
22+
if l:y - 2 > l:height
23+
" Fits above
24+
let l:y = winline() - l:height
25+
elseif l:y - 2 > &lines - l:y
26+
" Take space above cursor
27+
let l:y = 1
28+
let l:height = winline()-2
29+
else
30+
" Take space below cursor
31+
let l:height = &lines -l:y
32+
endif
33+
endif
34+
let l:col = col(".")
35+
" Positioning is not window but screen relative
36+
let l:opts = {
37+
\ 'relative': 'win',
38+
\ 'row': l:y,
39+
\ 'col': l:col,
40+
\ 'width': l:width,
41+
\ 'height': l:height,
42+
\ }
43+
return l:opts
44+
endfunction
45+
46+
function! lsp#ui#vim#output#floatingpreview(data) abort
47+
let l:buf = nvim_create_buf(v:false, v:true)
48+
call setbufvar(l:buf, '&signcolumn', 'no')
49+
50+
" Try to get as much pace right-bolow the cursor, but at least 10x10
51+
let l:width = max([float2nr(&columns - col(".") - 10), 10])
52+
let l:height = max([&lines - winline() + 1, 10])
53+
54+
let l:opts = s:get_float_positioning(l:height, l:width)
55+
56+
let s:win = nvim_open_win(buf, v:true, l:opts)
57+
call nvim_win_set_option(s:win, 'winhl', "Normal:Pmenu,NormalNC:Pmenu")
58+
call nvim_win_set_option(s:win, 'foldenable', v:false)
59+
call nvim_win_set_option(s:win, 'wrap', v:true)
60+
call nvim_win_set_option(s:win, 'statusline', '')
61+
call nvim_win_set_option(s:win, 'number', v:false)
62+
call nvim_win_set_option(s:win, 'relativenumber', v:false)
63+
call nvim_win_set_option(s:win, 'cursorline', v:false)
64+
" Enable closing the preview with esc, but map only in the scratch buffer
65+
nmap <buffer><silent> <esc> :pclose<cr>
66+
return s:win
67+
endfunction
68+
169
function! lsp#ui#vim#output#preview(data) abort
270
" Close any previously opened preview window
371
pclose
472

573
let l:current_window_id = win_getid()
674

7-
execute &previewheight.'new'
75+
if s:supports_floating && g:lsp_preview_float
76+
call lsp#ui#vim#output#floatingpreview(a:data)
77+
else
78+
execute &previewheight.'new'
79+
endif
80+
let s:win = win_getid()
881

982
let l:ft = s:append(a:data)
1083
" Delete first empty line
@@ -13,6 +86,9 @@ function! lsp#ui#vim#output#preview(data) abort
1386
setlocal readonly nomodifiable
1487

1588
let &l:filetype = l:ft . '.lsp-hover'
89+
" Get size information while still having the buffer active
90+
let l:bufferlines = line("$")
91+
let l:maxwidth = max(map(getline(1, '$'), 'strdisplaywidth(v:val)'))
1692

1793
if g:lsp_preview_keep_focus
1894
" restore focus to the previous window
@@ -21,6 +97,17 @@ function! lsp#ui#vim#output#preview(data) abort
2197

2298
echo ''
2399

100+
if s:supports_floating && s:win && g:lsp_preview_float
101+
let l:win_config = {}
102+
let l:height = min([winheight(s:win), l:bufferlines])
103+
let l:width = min([winwidth(s:win), l:maxwidth])
104+
let l:win_config = s:get_float_positioning(l:height, l:width)
105+
call nvim_win_set_config(s:win, l:win_config )
106+
augroup lsp_float_preview_close
107+
autocmd! lsp_float_preview_close CursorMoved,CursorMovedI,VimResized *
108+
autocmd CursorMoved,CursorMovedI,VimResized * call lsp#ui#vim#output#closepreview()
109+
augroup END
110+
endif
24111
return ''
25112
endfunction
26113

doc/vim-lsp.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ CONTENTS *vim-lsp-contents*
1313
g:lsp_diagnostics_enabled |g:lsp_diagnostics_enabled|
1414
g:lsp_auto_enable |g:lsp_auto_enable|
1515
g:lsp_preview_keep_focus |g:lsp_preview_keep_focus|
16+
g:lsp_preview_float |g:lsp_preview_float|
1617
g:lsp_insert_text_enabled |g:lsp_insert_text_enabled|
1718
g:lsp_text_edit_enabled |g:lsp_text_edit_enabled|
1819
g:lsp_diagnostics_echo_cursor |g:lsp_diagnostics_echo_cursor|
@@ -149,6 +150,23 @@ g:lsp_preview_keep_focus *g:lsp_preview_keep_focus*
149150

150151
* |preview-window| can be closed using the default vim mapping - `<c-w><c-z>`.
151152

153+
g:lsp_preview_float *g:lsp_preview_float*
154+
Type: |Number|
155+
Default: `1`
156+
157+
If set and nvim_win_open() is available, hover information are shown in a
158+
floating window as |preview-window| at the cursor position.
159+
The |preview-window| is closed automatically on cursor moves, unless it is
160+
focused. While focused it may be closed with <esc>.
161+
This feature requires neovim 0.4.0 (current master).
162+
163+
Example:
164+
" Opens preview windows as floating
165+
let g:lsp_preview_float = 1
166+
167+
" Opens preview windows as normal windows
168+
let g:lsp_preview_float = 0
169+
152170
g:lsp_insert_text_enabled *g:lsp_insert_text_enabled*
153171
Type: |Number|
154172
Default: `1`
@@ -535,6 +553,9 @@ Gets the hover information and displays it in the |preview-window|.
535553
* |preview-window| can be closed using the default vim mapping - `<c-w><c-z>`.
536554
* To control the default focus of |preview-window| for |LspHover|
537555
configure |g:lsp_preview_keep_focus|.
556+
* If using neovim with nvim_win_open() available, |g:lsp_preview_float| can be
557+
set to enable a floating preview at the cursor which is closed automatically
558+
on cursormove if not focused and can be closed with <esc> if focused.
538559

539560

540561
LspNextError *LspNextError*

plugin/lsp.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ let g:lsp_use_event_queue = get(g:, 'lsp_use_event_queue', has('nvim') || has('p
2525
let g:lsp_insert_text_enabled= get(g:, 'lsp_insert_text_enabled', 1)
2626
let g:lsp_text_edit_enabled = get(g:, 'lsp_text_edit_enabled', has('patch-8.0.1493'))
2727
let g:lsp_highlight_references_enabled = get(g:, 'lsp_highlight_references_enabled', 1)
28+
let g:lsp_preview_float = get(g:, 'lsp_preview_float', 1)
2829

2930
if g:lsp_auto_enable
3031
augroup lsp_auto_enable

0 commit comments

Comments
 (0)