diff --git a/autoload/lsp/ui/vim/float.vim b/autoload/lsp/ui/vim/float.vim new file mode 100644 index 000000000..b92bb78c5 --- /dev/null +++ b/autoload/lsp/ui/vim/float.vim @@ -0,0 +1,133 @@ +"""""""""""""""""""""""""""""""""""""""""" +" LICENSE: +" Author: +" Version: +" CreateTime: 2019-03-16 16:36:16 +" LastUpdate: 2019-03-16 16:36:16 +" Desc: float win +"""""""""""""""""""""""""""""""""""""""""" + +if exists("s:is_load") + finish +endif +let s:is_load = 1 + +let s:float_win = 0 +let s:curbuf = 0 +let s:data_buf = [] + +let s:float_width = 0 " float window height +let s:float_height = 0 + +function! s:reset() + let s:data_buf = [] + call nvim_buf_set_option(s:curbuf, 'modifiable', v:true) +endfunction + +function! s:set_buf_option() + call nvim_buf_set_option(s:curbuf, 'modifiable', v:false) +endfunction + +function! s:set_win_option() + call nvim_win_set_option(s:float_win, 'number', v:false) + call nvim_win_set_option(s:float_win, 'relativenumber', v:false) +endfunction + +function! s:float_win_position() abort + let l:win_height = winheight('.') + let l:win_width = winwidth('.') + let l:max_text_width = l:win_width + if l:max_text_width > 12 + let l:max_text_width = l:max_text_width - 3 + endif + + let l:max_width = 0 + let l:line_count = 0 + + for l:line in s:data_buf + let l:line_count = l:line_count + 1 + let l:len = strwidth(line) + if l:len < l:max_text_width + if l:len > l:max_width + let l:max_width = l:len + endif + else + let l:max_width = l:max_text_width + let l:calc_count = l:len / l:max_width + let l:line_count = l:line_count + l:calc_count + endif + endfor + + let l:cline = winline() + let l:ccol = wincol() + + if l:ccol + l:max_width + 1 <= l:win_width + let l:ccol = l:ccol - 1 + else + let l:ccol = l:win_width - l:max_width + endif + + if l:cline + l:line_count > l:win_height + if l:cline > l:win_height / 2 + let l:line_count = min([l:line_count, l:cline - 1]) + let l:cline = l:cline - l:line_count - 1 + else + let l:line_count = l:win_height - l:cline + endif + endif + + return {'col': l:ccol, 'row': l:cline, 'height': l:line_count, 'width': l:max_width} + +endfunction + +function! s:remove_spec_char(data) abort + return split(a:data, '\%x00') +endfunction + +function! lsp#ui#vim#float#float_open(data) + if s:curbuf ==# 0 + let s:curbuf = nvim_create_buf(v:false, v:true) + endif + call s:reset() + call s:convert_to_data_buf(a:data) + call nvim_buf_set_lines(s:curbuf, 0, -1, v:true, s:data_buf) + call s:set_buf_option() + call s:open_float_win() +endfunction + +function! s:convert_to_data_buf(data) + if type(a:data) == type([]) + for l:entry in a:data + call s:convert_to_data_buf(entry) + endfor + + return + elseif type(a:data) == type('') + call extend(s:data_buf, s:remove_spec_char(a:data)) + + return + elseif type(a:data) == type({}) && has_key(a:data, 'language') + call add(s:data_buf, '```'.a:data.language) + call extend(s:data_buf, s:remove_spec_char(a:data.value)) + call add(s:data_buf, '```') + + return + elseif type(a:data) == type({}) && has_key(a:data, 'kind') + call extend(s:data_buf, s:remove_spec_char(a:data.value)) + + return + endif +endfunction + +function! s:open_float_win() + let l:opts = s:float_win_position() + call extend(l:opts, {'relative': 'win', 'anchor': 'NW'}) + let s:float_win = nvim_open_win(s:curbuf, v:true, l:opts) + map :call float_close() + call s:set_win_option() +endfunction + +function! s:float_close() + call nvim_win_close(s:float_win, 1) + unmap +endfunction diff --git a/autoload/lsp/ui/vim/hover.vim b/autoload/lsp/ui/vim/hover.vim index 4166d7783..4dae562bd 100644 --- a/autoload/lsp/ui/vim/hover.vim +++ b/autoload/lsp/ui/vim/hover.vim @@ -35,8 +35,18 @@ function! s:handle_hover(server, data) abort endif if !empty(a:data['response']['result']) && !empty(a:data['response']['result']['contents']) - call lsp#ui#vim#output#preview(a:data['response']['result']['contents']) - return + for ui in g:lsp_hover_ui + if ui == "float" + if exists("*nvim_open_win") + call lsp#ui#vim#float#float_open(a:data['response']['result']['contents']) + return + endif + elseif ui == "preview" + call lsp#ui#vim#output#preview(a:data['response']['result']['contents']) + return + endif + endfor + call lsp#utils#error('Hover ui is not found') else call lsp#utils#error('No hover information found') endif diff --git a/doc/vim-lsp.txt b/doc/vim-lsp.txt index ff6127e8d..fb7c8cbe2 100644 --- a/doc/vim-lsp.txt +++ b/doc/vim-lsp.txt @@ -17,6 +17,7 @@ CONTENTS *vim-lsp-contents* g:lsp_text_edit_enabled |g:lsp_text_edit_enabled| g:lsp_signs_enabled |g:lsp_signs_enabled| g:lsp_use_event_queue |g:lsp_use_event_queue| + g:lsp_hover_ui |g:lsp_hover_ui| Functions |vim-lsp-functions| enable |vim-lsp-enable| disable |vim-lsp-disable| @@ -122,6 +123,12 @@ g:lsp_auto_enable *g:lsp_auto_enable* let g:lsp_auto_enable = 1 let g:lsp_auto_enable = 0 +g:lsp_hover_ui *g:lsp_hover_ui* + Type: List + Default: ["float", "preview"] + + Indicates hover info show ui + g:lsp_preview_keep_focus *g:lsp_preview_keep_focus* Type: |Number| Default: `1` diff --git a/plugin/lsp.vim b/plugin/lsp.vim index c39753c26..f3bed236e 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -23,6 +23,7 @@ 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) let g:lsp_text_edit_enabled = get(g:, 'lsp_text_edit_enabled', has('patch-8.0.1493')) +let g:lsp_hover_ui = get(g:, 'lsp_hover_ui', ['float', 'preview']) if g:lsp_auto_enable augroup lsp_auto_enable