@@ -2,12 +2,17 @@ let s:use_vim_popup = has('patch-8.1.1517') && !has('nvim')
2
2
let s: use_nvim_float = exists (' *nvim_open_win' ) && has (' nvim' )
3
3
4
4
let s: last_popup_id = -1
5
+ let s: last_timer_id = v: false
5
6
6
- function ! s: complete_done () abort
7
+ function ! s: complete_changed () abort
7
8
if ! g: lsp_documentation_float | return | endif
8
9
" Use a timer to avoid textlock (see :h textlock).
9
- let l: event = deepcopy (v: event )
10
- call timer_start (0 , {- > s: show_documentation (l: event )})
10
+ let l: event = copy (v: event )
11
+ if s: last_timer_id
12
+ call timer_stop (s: last_timer_id )
13
+ let s: last_timer_id = v: false
14
+ endif
15
+ let s: last_timer_id = timer_start (g: lsp_documentation_debounce , {- > s: show_documentation (l: event )})
11
16
endfunction
12
17
13
18
function ! s: show_documentation (event ) abort
@@ -17,54 +22,118 @@ function! s:show_documentation(event) abort
17
22
return
18
23
endif
19
24
20
- let l: right = wincol () < winwidth (0 ) / 2
21
-
22
- " TODO: Neovim
23
- if l: right
24
- let l: line = a: event [' row' ] + 1
25
- let l: col = a: event [' col' ] + a: event [' width' ] + 1 + (a: event [' scrollbar' ] ? 1 : 0 )
26
- else
27
- let l: line = a: event [' row' ] + 1
28
- let l: col = a: event [' col' ] - 1
29
- endif
30
25
31
26
" TODO: Support markdown
32
27
let l: data = split (a: event [' completed_item' ][' info' ], ' \n' )
33
28
let l: lines = []
34
29
let l: syntax_lines = []
35
30
let l: ft = lsp#ui#vim#output#append (l: data , l: lines , l: syntax_lines )
36
31
37
- let l: current_win_id = win_getid ()
38
32
39
- if s: use_vim_popup
40
- let s: last_popup_id = popup_create (' (no documentation available)' , {' line' : l: line , ' col' : l: col , ' pos' : l: right ? ' topleft' : ' topright' , ' padding' : [0 , 1 , 0 , 1 ]})
41
- elseif s: use_nvim_float
42
- let l: height = float2nr (winheight (0 ) - l: line + 1 )
43
- let l: width = float2nr (l: right ? winwidth (0 ) - l: col + 1 : l: col )
44
- if l: width <= 0
45
- let l: width = 1
33
+ " Neovim
34
+ if s: use_nvim_float
35
+ let l: event = a: event
36
+ let l: event .row = float2nr (l: event .row)
37
+ let l: event .col = float2nr (l: event .col )
38
+
39
+ let l: buffer = nvim_create_buf (v: false , v: true )
40
+ let l: curpos = win_screenpos (nvim_get_current_win ())[0 ] + winline () - 1
41
+ let g: lsp_documentation_float_docked = get (g: , ' lsp_documentation_float_docked' , 0 )
42
+
43
+ if g: lsp_documentation_float_docked
44
+ let g: lsp_documentation_float_docked_maxheight = get (g: , ' :lsp_documentation_float_docked_maxheight' , &previewheight )
45
+ let l: dock_downwards = max ([screenrow (), l: curpos ]) < (&lines / 2 )
46
+ let l: height = min ([len (l: data ), g: lsp_documentation_float_docked_maxheight ])
47
+ let l: width = &columns
48
+ let l: col = 0
49
+ if l: dock_downwards
50
+ let l: anchor = ' SW'
51
+ let l: row = &lines - &cmdheight - 1
52
+ let l: height = min ([l: height , &lines - &cmdheight - l: event .row - l: event .height])
53
+ else " dock upwards
54
+ let l: anchor = ' NW'
55
+ let l: row = 0
56
+ let l: height = min ([l: height , l: event .row - 1 ])
57
+ endif
58
+
59
+ else " not docked
60
+ let l: row = l: event [' row' ]
61
+ let l: height = max ([&lines - &cmdheight - l: row , &previewheight ])
62
+
63
+ let l: right_area = &columns - l: event .col - l: event .width + 1 " 1 for the padding of popup
64
+ let l: left_area = l: event .col - 1
65
+ let l: right = l: right_area > l: left_area
66
+ if l: right
67
+ let l: anchor = ' NW'
68
+ let l: width = l: right_area - 1
69
+ let l: col = l: event .col + l: event .width + (l: event .scrollbar ? 1 : 0 )
70
+ else
71
+ let l: anchor = ' NE'
72
+ let l: width = l: left_area
73
+ let l: col = l: event .col - 1 " 1 due to padding of completion popup
74
+ endif
75
+ endif
76
+
77
+ call setbufvar (l: buffer , ' lsp_syntax_highlights' , l: syntax_lines )
78
+ call setbufvar (l: buffer , ' lsp_do_conceal' , 1 )
79
+
80
+ " add padding on both sides of lines containing text
81
+ for l: index in range (len (l: lines ))
82
+ if len (l: lines [l: index ]) > 0
83
+ let l: lines [l: index ] = ' ' . l: lines [l: index ] . ' '
84
+ endif
85
+ endfor
86
+
87
+ call nvim_buf_set_lines (l: buffer , 0 , -1 , v: false , l: lines )
88
+ call nvim_buf_set_option (l: buffer , ' readonly' , v: true )
89
+ call nvim_buf_set_option (l: buffer , ' modifiable' , v: false )
90
+ call nvim_buf_set_option (l: buffer , ' filetype' , l: ft .' .lsp-hover' )
91
+
92
+ if ! g: lsp_documentation_float_docked
93
+ let l: bufferlines = nvim_buf_line_count (l: buffer )
94
+ let l: maxwidth = max (map (getbufline (l: buffer , 1 , ' $' ), ' strdisplaywidth(v:val)' ))
95
+ if g: lsp_preview_max_width > 0
96
+ let l: maxwidth = min ([g: lsp_preview_max_width , l: maxwidth ])
97
+ endif
98
+ let l: width = min ([float2nr (l: width ), l: maxwidth ])
99
+ let l: height = min ([float2nr (l: height ), l: bufferlines ])
46
100
endif
47
- if l: height <= 0
48
- let l: height = 1
101
+ if g: lsp_preview_max_height > 0
102
+ let l: maxheight = g: lsp_preview_max_height
103
+ let l: height = min ([l: height , l: maxheight ])
49
104
endif
50
- let s: last_popup_id = lsp#ui#vim#output#floatingpreview ([])
51
- call nvim_win_set_config (s: last_popup_id , {' relative' : ' win' , ' anchor' : l: right ? ' NW' : ' NE' , ' row' : l: line - 1 , ' col' : l: col - 1 , ' height' : l: height , ' width' : l: width })
105
+
106
+ " Height and width must be atleast 1, otherwise error
107
+ let l: height = (l: height < 1 ? 1 : l: height )
108
+ let l: width = (l: width < 1 ? 1 : l: width )
109
+
110
+ let s: last_popup_id = nvim_open_win (l: buffer , v: false , {' relative' : ' editor' , ' anchor' : l: anchor , ' row' : l: row , ' col' : l: col , ' height' : l: height , ' width' : l: width , ' style' : ' minimal' })
111
+ return
52
112
endif
53
113
114
+ " Vim
115
+ let l: current_win_id = win_getid ()
116
+
117
+ let l: right = wincol () < winwidth (0 ) / 2
118
+ if l: right
119
+ let l: line = a: event [' row' ] + 1
120
+ let l: col = a: event [' col' ] + a: event [' width' ] + 1 + (a: event [' scrollbar' ] ? 1 : 0 )
121
+ else
122
+ let l: line = a: event [' row' ] + 1
123
+ let l: col = a: event [' col' ] - 1
124
+ endif
125
+ let s: last_popup_id = popup_create (' (no documentation available)' , {' line' : l: line , ' col' : l: col , ' pos' : l: right ? ' topleft' : ' topright' , ' padding' : [0 , 1 , 0 , 1 ]})
54
126
call setbufvar (winbufnr (s: last_popup_id ), ' lsp_syntax_highlights' , l: syntax_lines )
55
127
call setbufvar (winbufnr (s: last_popup_id ), ' lsp_do_conceal' , 1 )
56
128
call lsp#ui#vim#output#setcontent (s: last_popup_id , l: lines , l: ft )
57
- let [l: bufferlines , l: maxwidth ] = lsp#ui#vim#output#get_size_info ()
58
-
59
129
call win_gotoid (l: current_win_id )
60
-
61
- if s: use_nvim_float
62
- call lsp#ui#vim#output#adjust_float_placement (l: bufferlines , l: maxwidth )
63
- call nvim_win_set_config (s: last_popup_id , {' relative' : ' win' , ' row' : l: line - 1 , ' col' : l: col - 1 })
64
- endif
65
130
endfunction
66
131
67
132
function ! s: close_popup () abort
133
+ if s: last_timer_id
134
+ call timer_stop (s: last_timer_id )
135
+ let s: last_timer_id = v: false
136
+ endif
68
137
if s: last_popup_id >= 0
69
138
if s: use_vim_popup | call popup_close (s: last_popup_id ) | endif
70
139
if s: use_nvim_float && nvim_win_is_valid (s: last_popup_id ) | call nvim_win_close (s: last_popup_id , 1 ) | endif
@@ -77,8 +146,10 @@ function! lsp#ui#vim#documentation#setup() abort
77
146
augroup lsp_documentation_popup
78
147
autocmd !
79
148
if exists (' ##CompleteChanged' )
80
- autocmd CompleteChanged * call s: complete_done ()
149
+ autocmd CompleteChanged * call s: complete_changed ()
81
150
endif
82
151
autocmd CompleteDone * call s: close_popup ()
83
152
augroup end
84
153
endfunction
154
+
155
+ " vim: et ts = 4
0 commit comments