mirror of
https://github.com/prabirshrestha/vim-lsp.git
synced 2025-12-14 20:35:59 +01:00
completion/resolve support for documentation and use the new floating window (#1052)
* doc * floating window with completion/resolve * add comments * use _split_by_eol * copy event * fix dupe * Fix size/markdown/detail * - Improve for exceptional case - Fix code style - Support detail only case * Add lsp_float_opened/lsp_float_closed * remove old documentation code * update documenation and change flags to use g:lsp_completion_documentation Co-authored-by: hrsh7th <hrsh7th@gmail.com>
This commit is contained in:
@@ -63,6 +63,7 @@ function! lsp#enable() abort
|
||||
call lsp#internal#diagnostics#_enable()
|
||||
call lsp#internal#show_message_request#_enable()
|
||||
call lsp#internal#work_done_progress#_enable()
|
||||
call lsp#internal#completion#documentation#_enable()
|
||||
call s:register_events()
|
||||
endfunction
|
||||
|
||||
@@ -76,6 +77,7 @@ function! lsp#disable() abort
|
||||
call lsp#internal#diagnostics#_disable()
|
||||
call lsp#internal#show_message_request#_disable()
|
||||
call lsp#internal#work_done_progress#_disable()
|
||||
call lsp#internal#completion#documentation#_disable()
|
||||
call s:unregister_events()
|
||||
let s:enabled = 0
|
||||
endfunction
|
||||
@@ -473,7 +475,7 @@ function! lsp#default_get_supported_capabilities(server_info) abort
|
||||
\ 'completion': {
|
||||
\ 'dynamicRegistration': v:false,
|
||||
\ 'completionItem': {
|
||||
\ 'documentationFormat': ['plaintext'],
|
||||
\ 'documentationFormat': ['markdown', 'plaintext'],
|
||||
\ 'snippetSupport': v:false,
|
||||
\ 'resolveSupport': {
|
||||
\ 'properties': ['additionalTextEdits']
|
||||
@@ -857,8 +859,6 @@ function! s:handle_initialize(server_name, data) abort
|
||||
call l:Init_callback(a:data)
|
||||
endfor
|
||||
|
||||
call lsp#ui#vim#documentation#setup()
|
||||
|
||||
doautocmd <nomodeline> User lsp_server_init
|
||||
endfunction
|
||||
|
||||
|
||||
@@ -191,3 +191,6 @@ function! lsp#capabilities#get_code_action_kinds(server_name) abort
|
||||
return []
|
||||
endfunction
|
||||
|
||||
function! lsp#capabilities#has_completion_resolve_provider(server_name) abort
|
||||
return s:has_provider(a:server_name, 'completionProvider', 'resolveProvider')
|
||||
endfunction
|
||||
|
||||
189
autoload/lsp/internal/completion/documentation.vim
Normal file
189
autoload/lsp/internal/completion/documentation.vim
Normal file
@@ -0,0 +1,189 @@
|
||||
" https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
|
||||
let s:enabled = 0
|
||||
|
||||
let s:Markdown = vital#lsp#import('VS.Vim.Syntax.Markdown')
|
||||
let s:MarkupContent = vital#lsp#import('VS.LSP.MarkupContent')
|
||||
let s:FloatingWindow = vital#lsp#import('VS.Vim.Window.FloatingWindow')
|
||||
let s:Window = vital#lsp#import('VS.Vim.Window')
|
||||
let s:Buffer = vital#lsp#import('VS.Vim.Buffer')
|
||||
|
||||
function! lsp#internal#completion#documentation#_enable() abort
|
||||
" don't even bother registering if the feature is disabled
|
||||
if !g:lsp_completion_documentation_enabled | return | endif
|
||||
|
||||
if !s:FloatingWindow.is_available() | return | endif
|
||||
if !exists('##CompleteChanged') | return | endif
|
||||
|
||||
if s:enabled | return | endif
|
||||
let s:enabled = 1
|
||||
|
||||
let s:Dispose = lsp#callbag#pipe(
|
||||
\ lsp#callbag#merge(
|
||||
\ lsp#callbag#pipe(
|
||||
\ lsp#callbag#fromEvent('CompleteChanged'),
|
||||
\ lsp#callbag#filter({_->g:lsp_completion_documentation_enabled}),
|
||||
\ lsp#callbag#map({->copy(v:event)}),
|
||||
\ lsp#callbag#debounceTime(g:lsp_completion_documentation_delay),
|
||||
\ lsp#callbag#switchMap({event->
|
||||
\ lsp#callbag#pipe(
|
||||
\ s:resolve_completion(event),
|
||||
\ lsp#callbag#tap({managed_user_data->s:show_floating_window(event, managed_user_data)}),
|
||||
\ lsp#callbag#takeUntil(lsp#callbag#fromEvent('CompleteDone'))
|
||||
\ )
|
||||
\ })
|
||||
\ ),
|
||||
\ lsp#callbag#pipe(
|
||||
\ lsp#callbag#fromEvent('CompleteDone'),
|
||||
\ lsp#callbag#tap({_->s:close_floating_window(v:false)}),
|
||||
\ )
|
||||
\ ),
|
||||
\ lsp#callbag#subscribe(),
|
||||
\ )
|
||||
endfunction
|
||||
|
||||
function! s:resolve_completion(event) abort
|
||||
let l:managed_user_data = lsp#omni#get_managed_user_data_from_completed_item(a:event['completed_item'])
|
||||
if empty(l:managed_user_data)
|
||||
return lsp#callbag#of({})
|
||||
endif
|
||||
|
||||
let l:completion_item = l:managed_user_data['completion_item']
|
||||
|
||||
if has_key(l:completion_item, 'documentation')
|
||||
return lsp#callbag#of(l:managed_user_data)
|
||||
elseif lsp#capabilities#has_completion_resolve_provider(l:managed_user_data['server_name'])
|
||||
return lsp#callbag#pipe(
|
||||
\ lsp#request(l:managed_user_data['server_name'], {
|
||||
\ 'method': 'completionItem/resolve',
|
||||
\ 'params': l:completion_item,
|
||||
\ }),
|
||||
\ lsp#callbag#map({x->{
|
||||
\ 'server_name': l:managed_user_data['server_name'],
|
||||
\ 'completion_item': x['response']['result'],
|
||||
\ 'complete_position': l:managed_user_data['complete_position'],
|
||||
\ }})
|
||||
\ )
|
||||
else
|
||||
return lsp#callbag#of({})
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:show_floating_window(event, managed_user_data) abort
|
||||
if empty(a:managed_user_data) || !pumvisible()
|
||||
call s:close_floating_window(v:true)
|
||||
return
|
||||
endif
|
||||
let l:completion_item = a:managed_user_data['completion_item']
|
||||
|
||||
let l:contents = []
|
||||
|
||||
" Add detail field if provided.
|
||||
if type(get(l:completion_item, 'detail', v:null)) == type('')
|
||||
if !empty(l:completion_item.detail)
|
||||
let l:detail = s:MarkupContent.normalize({
|
||||
\ 'language': &filetype,
|
||||
\ 'value': l:completion_item['detail'],
|
||||
\ })
|
||||
let l:contents += [l:detail]
|
||||
endif
|
||||
endif
|
||||
|
||||
" Add documentation filed if provided.
|
||||
let l:documentation = s:MarkupContent.normalize(get(l:completion_item, 'documentation', ''))
|
||||
if !empty(l:documentation)
|
||||
let l:contents += [l:documentation]
|
||||
endif
|
||||
|
||||
" Ignore if contents is empty.
|
||||
if empty(l:contents)
|
||||
return s:close_floating_window(v:true)
|
||||
endif
|
||||
|
||||
" Update contents.
|
||||
let l:doc_win = s:get_doc_win()
|
||||
call deletebufline(l:doc_win.get_bufnr(), 1, '$')
|
||||
call setbufline(l:doc_win.get_bufnr(), 1, lsp#utils#_split_by_eol(join(l:contents, "\n\n")))
|
||||
|
||||
" Calculate layout.
|
||||
let l:size = l:doc_win.get_size({
|
||||
\ 'maxwidth': float2nr(&columns * 0.4),
|
||||
\ 'maxheight': float2nr(&lines * 0.4),
|
||||
\ })
|
||||
let l:pos = s:compute_position(a:event, l:size)
|
||||
if empty(l:pos)
|
||||
call s:close_floating_window(v:true)
|
||||
return
|
||||
endif
|
||||
|
||||
" Show popupmenu and apply markdown syntax.
|
||||
call l:doc_win.open({
|
||||
\ 'row': l:pos[0] + 1,
|
||||
\ 'col': l:pos[1] + 1,
|
||||
\ 'width': l:size.width,
|
||||
\ 'height': l:size.height,
|
||||
\ 'topline': 1,
|
||||
\ })
|
||||
call s:Window.do(l:doc_win.get_winid(), { -> s:Markdown.apply() })
|
||||
endfunction
|
||||
|
||||
function! s:close_floating_window(force) abort
|
||||
" Ignore `CompleteDone` if it occurred by `complete()` because in this case, the popup menu will re-appear immediately.
|
||||
let l:ctx = {}
|
||||
function! l:ctx.callback(force) abort
|
||||
if !pumvisible() || a:force
|
||||
call s:get_doc_win().close()
|
||||
endif
|
||||
endfunction
|
||||
call timer_start(1, { -> l:ctx.callback(a:force) })
|
||||
endfunction
|
||||
|
||||
function! s:compute_position(event, size) abort
|
||||
let l:col_if_right = a:event.col + a:event.width + 1 + (a:event.scrollbar ? 1 : 0)
|
||||
let l:col_if_left = a:event.col - a:size.width - 2
|
||||
|
||||
if a:size.width >= (&columns - l:col_if_right)
|
||||
let l:col = l:col_if_left
|
||||
else
|
||||
let l:col = l:col_if_right
|
||||
endif
|
||||
|
||||
if l:col <= 0
|
||||
return []
|
||||
endif
|
||||
if &columns <= l:col + a:size.width
|
||||
return []
|
||||
endif
|
||||
|
||||
return [a:event.row, l:col]
|
||||
endfunction
|
||||
|
||||
function! s:get_doc_win() abort
|
||||
if exists('s:doc_win')
|
||||
return s:doc_win
|
||||
endif
|
||||
|
||||
let s:doc_win = s:FloatingWindow.new({
|
||||
\ 'on_opened': { -> execute('doautocmd <nomodeline> User lsp_float_opened') },
|
||||
\ 'on_closed': { -> execute('doautocmd <nomodeline> User lsp_float_closed') }
|
||||
\ })
|
||||
call s:doc_win.set_var('&wrap', 1)
|
||||
call s:doc_win.set_var('&conceallevel', 2)
|
||||
call s:doc_win.set_bufnr(s:Buffer.create())
|
||||
call setbufvar(s:doc_win.get_bufnr(), '&buftype', 'nofile')
|
||||
call setbufvar(s:doc_win.get_bufnr(), '&bufhidden', 'hide')
|
||||
call setbufvar(s:doc_win.get_bufnr(), '&buflisted', 0)
|
||||
return s:doc_win
|
||||
endfunction
|
||||
|
||||
function! lsp#internal#completion#documentation#_disable() abort
|
||||
if !s:enabled | return | endif
|
||||
if exists('s:Dispose')
|
||||
call s:Dispose()
|
||||
unlet s:Dispose
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:log(x) abort
|
||||
echom json_encode(a:x)
|
||||
endfunction
|
||||
|
||||
@@ -346,6 +346,9 @@ function! lsp#omni#get_managed_user_data_from_completed_item(completed_item) abo
|
||||
endif
|
||||
|
||||
let l:user_data_string = get(a:completed_item, 'user_data', '')
|
||||
if type(l:user_data_string) != type('')
|
||||
return {}
|
||||
endif
|
||||
|
||||
" Check managed user_data.
|
||||
if has_key(s:managed_user_data_map, l:user_data_string)
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
let s:use_vim_popup = has('patch-8.1.1517') && !has('nvim')
|
||||
let s:use_nvim_float = exists('*nvim_open_win') && has('nvim')
|
||||
|
||||
let s:last_popup_id = -1
|
||||
let s:last_timer_id = v:false
|
||||
|
||||
function! s:complete_changed() abort
|
||||
if !g:lsp_documentation_float | return | endif
|
||||
" Use a timer to avoid textlock (see :h textlock).
|
||||
let l:event = copy(v:event)
|
||||
if s:last_timer_id
|
||||
call timer_stop(s:last_timer_id)
|
||||
let s:last_timer_id = v:false
|
||||
endif
|
||||
let s:last_timer_id = timer_start(g:lsp_documentation_debounce, {-> s:show_documentation(l:event)})
|
||||
endfunction
|
||||
|
||||
function! s:show_documentation(event) abort
|
||||
call s:close_popup()
|
||||
|
||||
let l:managed_data = lsp#omni#get_managed_user_data_from_completed_item(a:event['completed_item'])
|
||||
if empty(l:managed_data)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:completion_item = l:managed_data['completion_item']
|
||||
if !has_key(l:completion_item, 'documentation')
|
||||
return
|
||||
endif
|
||||
|
||||
if type(l:completion_item['documentation']) == type('')
|
||||
let l:documentation = l:completion_item['documentation']
|
||||
elseif type(l:completion_item['documentation']) == type({}) && has_key(l:completion_item['documentation'], 'value')
|
||||
" field is MarkupContent (hopefully plaintext)
|
||||
let l:documentation = substitute(l:completion_item['documentation']['value'], '\r', '', 'g')
|
||||
endif
|
||||
|
||||
" TODO: Support markdown
|
||||
let l:data = split(l:documentation, '\n')
|
||||
let l:lines = []
|
||||
let l:syntax_lines = []
|
||||
let l:ft = lsp#ui#vim#output#append(l:data, l:lines, l:syntax_lines)
|
||||
|
||||
" Neovim
|
||||
if s:use_nvim_float
|
||||
let l:event = a:event
|
||||
let l:event.row = float2nr(l:event.row)
|
||||
let l:event.col = float2nr(l:event.col)
|
||||
|
||||
let l:buffer = nvim_create_buf(v:false, v:true)
|
||||
let l:curpos = screenrow()
|
||||
let g:lsp_documentation_float_docked = get(g:, 'lsp_documentation_float_docked', 0)
|
||||
|
||||
call setbufvar(l:buffer, 'lsp_syntax_highlights', l:syntax_lines)
|
||||
call setbufvar(l:buffer, 'lsp_do_conceal', 1)
|
||||
call nvim_buf_set_lines(l:buffer, 0, -1, v:false, l:lines)
|
||||
call nvim_buf_set_option(l:buffer, 'readonly', v:true)
|
||||
call nvim_buf_set_option(l:buffer, 'modifiable', v:false)
|
||||
call nvim_buf_set_option(l:buffer, 'filetype', l:ft.'.lsp-hover')
|
||||
|
||||
|
||||
if g:lsp_documentation_float_docked
|
||||
let g:lsp_documentation_float_docked_maxheight = get(g:, 'lsp_documentation_float_docked_maxheight', &previewheight)
|
||||
let l:dock_downwards = (l:curpos + l:event.height) < (&lines / 2)
|
||||
let l:height = min([len(l:data), g:lsp_documentation_float_docked_maxheight])
|
||||
let l:width = &columns
|
||||
let l:col = 0
|
||||
if l:dock_downwards
|
||||
let l:anchor = 'SW'
|
||||
let l:row = &lines - &cmdheight - 1
|
||||
let l:height = min([l:height, &lines - &cmdheight - l:event.row - l:event.height - 1]) - 1
|
||||
" Extra -1 of height to distinguish between completion popup
|
||||
" and documentation popup
|
||||
else " dock upwards
|
||||
let l:anchor = 'NW'
|
||||
let l:row = 0
|
||||
let l:height = min([l:height, l:event.row - 1])
|
||||
endif
|
||||
|
||||
else " not docked
|
||||
let l:bufferlines = nvim_buf_line_count(l:buffer)
|
||||
let l:maxwidth = max(map(getbufline(l:buffer, 1, '$'), 'strdisplaywidth(v:val)'))
|
||||
|
||||
let l:row = l:event['row']
|
||||
let l:height = max([&lines - &cmdheight - l:row, &previewheight])
|
||||
|
||||
let l:right_area = &columns - l:event.col - l:event.width + 1 " 1 for the padding of popup
|
||||
let l:left_area = l:event.col - 1
|
||||
let l:right = l:right_area > l:left_area
|
||||
if l:right
|
||||
let l:anchor = 'NW'
|
||||
let l:width = l:right_area - 1
|
||||
let l:col = l:event.col + l:event.width + (l:event.scrollbar ? 1 : 0)
|
||||
else
|
||||
let l:anchor = 'NE'
|
||||
let l:width = l:left_area
|
||||
let l:col = l:event.col - 1 " 1 due to padding of completion popup
|
||||
endif
|
||||
if l:width < 0.75 * l:maxwidth
|
||||
let l:col = &columns
|
||||
let l:width = l:maxwidth
|
||||
let l:above = l:event.row > &lines - &cmdheight - l:event.row - l:event.height
|
||||
if l:above
|
||||
let l:anchor = 'SE'
|
||||
let l:row = l:event.row
|
||||
let l:height = l:row
|
||||
else
|
||||
let l:anchor = 'NE'
|
||||
let l:row = l:event.row + l:event.height
|
||||
let l:height = &lines - &cmdheight - l:row
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
" add padding on both sides of lines containing text
|
||||
for l:index in range(len(l:lines))
|
||||
if len(l:lines[l:index]) > 0
|
||||
let l:lines[l:index] = ' ' . l:lines[l:index] . ' '
|
||||
endif
|
||||
endfor
|
||||
|
||||
if !g:lsp_documentation_float_docked
|
||||
let l:width = min([float2nr(l:width), l:maxwidth])
|
||||
let l:height = min([float2nr(l:height), l:bufferlines])
|
||||
endif
|
||||
if g:lsp_preview_max_height > 0
|
||||
let l:maxheight = g:lsp_preview_max_height
|
||||
let l:height = min([l:height, l:maxheight])
|
||||
endif
|
||||
if g:lsp_preview_max_width > 0
|
||||
let l:maxwidth = min([g:lsp_preview_max_width, l:width])
|
||||
endif
|
||||
|
||||
" Height and width must be atleast 1, otherwise error
|
||||
let l:height = (l:height < 1 ? 1 : l:height)
|
||||
let l:width = (l:width < 1 ? 1 : l:width)
|
||||
|
||||
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'})
|
||||
call nvim_win_set_option(s:last_popup_id, 'wrap', v:true)
|
||||
doautocmd <nomodeline> User lsp_float_opened
|
||||
return
|
||||
endif
|
||||
|
||||
" Vim
|
||||
let l:current_win_id = win_getid()
|
||||
|
||||
let l:right = wincol() < winwidth(0) / 2
|
||||
if l:right
|
||||
let l:line = a:event['row'] + 1
|
||||
let l:col = a:event['col'] + a:event['width'] + 1 + (a:event['scrollbar'] ? 1 : 0)
|
||||
if l:col > &columns - 2
|
||||
let l:col -= winwidth(0) / 2
|
||||
endif
|
||||
else
|
||||
let l:line = a:event['row'] + 1
|
||||
let l:col = a:event['col'] - 1
|
||||
endif
|
||||
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], 'border': [1, 1, 1, 1]})
|
||||
doautocmd <nomodeline> User lsp_float_opened
|
||||
call setbufvar(winbufnr(s:last_popup_id), 'lsp_syntax_highlights', l:syntax_lines)
|
||||
call setbufvar(winbufnr(s:last_popup_id), 'lsp_do_conceal', 1)
|
||||
call lsp#ui#vim#output#setcontent(s:last_popup_id, l:lines, l:ft)
|
||||
call win_gotoid(l:current_win_id)
|
||||
endfunction
|
||||
|
||||
function! s:close_popup() abort
|
||||
if s:last_timer_id
|
||||
call timer_stop(s:last_timer_id)
|
||||
let s:last_timer_id = v:false
|
||||
endif
|
||||
if s:last_popup_id >= 0
|
||||
if s:use_vim_popup | call popup_close(s:last_popup_id) | endif
|
||||
if s:use_nvim_float && nvim_win_is_valid(s:last_popup_id) | call nvim_win_close(s:last_popup_id, 1) | endif
|
||||
|
||||
let s:last_popup_id = -1
|
||||
doautocmd <nomodeline> User lsp_float_closed
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lsp#ui#vim#documentation#setup() abort
|
||||
augroup lsp_documentation_popup
|
||||
autocmd!
|
||||
if exists('##CompleteChanged')
|
||||
autocmd CompleteChanged * call s:complete_changed()
|
||||
endif
|
||||
autocmd CompleteDone * call s:close_popup()
|
||||
augroup end
|
||||
endfunction
|
||||
|
||||
" vim: et ts=4
|
||||
63
autoload/vital/_lsp/VS/LSP/MarkupContent.vim
Normal file
63
autoload/vital/_lsp/VS/LSP/MarkupContent.vim
Normal file
@@ -0,0 +1,63 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not modify the code nor insert new lines before '" ___vital___'
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_lsp#VS#LSP#MarkupContent#import() abort', printf("return map({'_vital_depends': '', 'normalize': '', '_vital_loaded': ''}, \"vital#_lsp#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
"
|
||||
" _vital_loaded
|
||||
"
|
||||
function! s:_vital_loaded(V) abort
|
||||
let s:Text = a:V.import('VS.LSP.Text')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _vital_depends
|
||||
"
|
||||
function! s:_vital_depends() abort
|
||||
return ['VS.LSP.Text']
|
||||
endfunction
|
||||
|
||||
"
|
||||
" normalize
|
||||
"
|
||||
function! s:normalize(markup_content) abort
|
||||
if type(a:markup_content) == type('')
|
||||
return s:_compact(a:markup_content)
|
||||
elseif type(a:markup_content) == type([])
|
||||
return s:_compact(join(a:markup_content, "\n"))
|
||||
elseif type(a:markup_content) == type({})
|
||||
let l:string = a:markup_content.value
|
||||
if has_key(a:markup_content, 'language')
|
||||
let l:string = '```' . a:markup_content.language . ' ' . l:string . '```'
|
||||
endif
|
||||
return s:_compact(l:string)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let s:_compact_fenced_start = '\%(^\|' . "\n" . '\)\s*'
|
||||
let s:_compact_fenced_end = '\s*\%($\|' . "\n" . '\)'
|
||||
let s:_compact_fenced_empty = '\s*\%(\s\|' . "\n" . '\)\s*'
|
||||
|
||||
"
|
||||
" _compact
|
||||
"
|
||||
function! s:_compact(string) abort
|
||||
" normalize eol.
|
||||
let l:string = s:Text.normalize_eol(a:string)
|
||||
|
||||
" compact fenced code block start.
|
||||
let l:string = substitute(l:string, s:_compact_fenced_start . '```\s*\w\+\s*\zs' . s:_compact_fenced_empty, ' ', 'g')
|
||||
|
||||
" compact fenced code block end.
|
||||
let l:string = substitute(l:string, s:_compact_fenced_empty . '\ze```' . s:_compact_fenced_end, ' ', 'g')
|
||||
|
||||
" trim first/last whitespace.
|
||||
let l:string = substitute(l:string, '^' . s:_compact_fenced_empty . '\|' . s:_compact_fenced_empty . '$', '', 'g')
|
||||
|
||||
return l:string
|
||||
endfunction
|
||||
|
||||
23
autoload/vital/_lsp/VS/LSP/Text.vim
Normal file
23
autoload/vital/_lsp/VS/LSP/Text.vim
Normal file
@@ -0,0 +1,23 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not modify the code nor insert new lines before '" ___vital___'
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_lsp#VS#LSP#Text#import() abort', printf("return map({'normalize_eol': '', 'split_by_eol': ''}, \"vital#_lsp#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
"
|
||||
" normalize_eol
|
||||
"
|
||||
function! s:normalize_eol(text) abort
|
||||
return substitute(a:text, "\r\n\\|\r", "\n", 'g')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" split_by_eol
|
||||
"
|
||||
function! s:split_by_eol(text) abort
|
||||
return split(a:text, "\r\n\\|\r\\|\n", v:true)
|
||||
endfunction
|
||||
|
||||
@@ -49,11 +49,23 @@ endfunction
|
||||
"
|
||||
if exists('*bufload')
|
||||
function! s:load(bufnr_or_path) abort
|
||||
call bufload(bufnr(a:bufnr_or_path, v:true))
|
||||
let l:bufnr = bufnr(a:bufnr_or_path, v:true)
|
||||
silent call bufload(l:bufnr)
|
||||
return l:bufnr
|
||||
endfunction
|
||||
else
|
||||
function! s:load(bufnr_or_path) abort
|
||||
call s:do(bufnr(a:bufnr_or_path, v:true), { -> {} })
|
||||
let l:curr_bufnr = bufnr('%')
|
||||
|
||||
try
|
||||
let l:bufnr = bufnr(a:bufnr_or_path, v:true)
|
||||
execute printf('keepalt keepjumps silent %sbuffer', l:bufnr)
|
||||
catch /.*/
|
||||
echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
|
||||
finally
|
||||
execute printf('noautocmd keepalt keepjumps silent %sbuffer', l:curr_bufnr)
|
||||
endtry
|
||||
return l:bufnr
|
||||
endfunction
|
||||
endif
|
||||
|
||||
@@ -68,12 +80,12 @@ function! s:do(bufnr, func) abort
|
||||
endif
|
||||
|
||||
try
|
||||
execute printf('noautocmd keepalt keepjumps %sbuffer', a:bufnr)
|
||||
execute printf('noautocmd keepalt keepjumps silent %sbuffer', a:bufnr)
|
||||
call a:func()
|
||||
catch /.*/
|
||||
echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
|
||||
finally
|
||||
execute printf('noautocmd keepalt keepjumps %sbuffer', l:curr_bufnr)
|
||||
execute printf('noautocmd keepalt keepjumps silent %sbuffer', l:curr_bufnr)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
|
||||
95
autoload/vital/_lsp/VS/Vim/Syntax/Markdown.vim
Normal file
95
autoload/vital/_lsp/VS/Vim/Syntax/Markdown.vim
Normal file
@@ -0,0 +1,95 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not modify the code nor insert new lines before '" ___vital___'
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_lsp#VS#Vim#Syntax#Markdown#import() abort', printf("return map({'apply': ''}, \"vital#_lsp#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
function! s:apply(...) abort
|
||||
if !exists('b:___VS_Vim_Syntax_Markdown')
|
||||
runtime! syntax/markdown.vim
|
||||
let b:___VS_Vim_Syntax_Markdown = {}
|
||||
endif
|
||||
|
||||
let l:bufnr = bufnr('%')
|
||||
try
|
||||
for [l:mark, l:filetype] in items(s:_get_filetype_map(l:bufnr, get(a:000, 0, {})))
|
||||
let l:group = substitute(toupper(l:mark), '\.', '_', 'g')
|
||||
if has_key(b:___VS_Vim_Syntax_Markdown, l:group)
|
||||
continue
|
||||
endif
|
||||
let b:___VS_Vim_Syntax_Markdown[l:group] = v:true
|
||||
|
||||
try
|
||||
if exists('b:current_syntax')
|
||||
unlet b:current_syntax
|
||||
endif
|
||||
execute printf('syntax include @%s syntax/%s.vim', l:group, l:filetype)
|
||||
execute printf('syntax region %s matchgroup=Conceal start=/%s/rs=e matchgroup=Conceal end=/%s/re=s contains=@%s containedin=ALL keepend concealends',
|
||||
\ l:group,
|
||||
\ printf('^\s*```\s*%s\s*', l:mark),
|
||||
\ '\s*```\s*$',
|
||||
\ l:group
|
||||
\ )
|
||||
catch /.*/
|
||||
echomsg printf('[VS.Vim.Syntax.Markdown] The `%s` is not valid filetype! You can add `"let g:markdown_fenced_languages = ["FILETYPE=%s"]`.', l:mark, l:mark)
|
||||
endtry
|
||||
endfor
|
||||
catch /.*/
|
||||
echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _get_filetype_map
|
||||
"
|
||||
function! s:_get_filetype_map(bufnr, filetype_map) abort
|
||||
let l:filetype_map = {}
|
||||
for l:mark in s:_find_marks(a:bufnr)
|
||||
let l:filetype_map[l:mark] = s:_get_filetype_from_mark(l:mark, a:filetype_map)
|
||||
endfor
|
||||
return l:filetype_map
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _find_marks
|
||||
"
|
||||
function! s:_find_marks(bufnr) abort
|
||||
let l:marks = {}
|
||||
|
||||
" find from buffer contents.
|
||||
let l:text = join(getbufline(a:bufnr, '^', '$'), "\n")
|
||||
let l:pos = 0
|
||||
while 1
|
||||
let l:match = matchlist(l:text, '```\s*\(\w\+\)', l:pos, 1)
|
||||
if empty(l:match)
|
||||
break
|
||||
endif
|
||||
let l:marks[l:match[1]] = v:true
|
||||
let l:pos = matchend(l:text, '```\s*\(\w\+\)', l:pos, 1)
|
||||
endwhile
|
||||
|
||||
return keys(l:marks)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _get_filetype_from_mark
|
||||
"
|
||||
function! s:_get_filetype_from_mark(mark, filetype_map) abort
|
||||
for l:config in get(g:, 'markdown_fenced_languages', [])
|
||||
if l:config !~# '='
|
||||
if l:config ==# a:mark
|
||||
return a:mark
|
||||
endif
|
||||
else
|
||||
let l:config = split(l:config, '=')
|
||||
if l:config[1] ==# a:mark
|
||||
return l:config[0]
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
return get(a:filetype_map, a:mark, a:mark)
|
||||
endfunction
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_lsp#VS#Vim#Window#import() abort', printf("return map({'info': '', 'do': '', 'find': '', 'scroll': '', 'screenpos': ''}, \"vital#_lsp#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
execute join(['function! vital#_lsp#VS#Vim#Window#import() abort', printf("return map({'info': '', 'do': '', 'is_floating': '', 'find': '', 'scroll': '', 'screenpos': ''}, \"vital#_lsp#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
let s:Do = { -> {} }
|
||||
@@ -43,8 +43,8 @@ endfunction
|
||||
" info
|
||||
"
|
||||
if has('nvim')
|
||||
function! s:info(win) abort
|
||||
let l:info = getwininfo(a:win)[0]
|
||||
function! s:info(winid) abort
|
||||
let l:info = getwininfo(a:winid)[0]
|
||||
return {
|
||||
\ 'width': l:info.width,
|
||||
\ 'height': l:info.height,
|
||||
@@ -52,9 +52,9 @@ if has('nvim')
|
||||
\ }
|
||||
endfunction
|
||||
else
|
||||
function! s:info(win) abort
|
||||
if index(s:_get_visible_popup_winids(), a:win) >= 0
|
||||
let l:info = popup_getpos(a:win)
|
||||
function! s:info(winid) abort
|
||||
if s:is_floating(a:winid)
|
||||
let l:info = popup_getpos(a:winid)
|
||||
return {
|
||||
\ 'width': l:info.width,
|
||||
\ 'height': l:info.height,
|
||||
@@ -69,7 +69,7 @@ else
|
||||
let self.info.height = winheight(0)
|
||||
let self.info.topline = line('w0')
|
||||
endfunction
|
||||
call s:do(a:win, { -> l:ctx.callback() })
|
||||
call s:do(a:winid, { -> l:ctx.callback() })
|
||||
return l:ctx.info
|
||||
endfunction
|
||||
endif
|
||||
@@ -84,6 +84,20 @@ function! s:find(callback) abort
|
||||
return filter(l:winids, 'a:callback(v:val)')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" is_floating
|
||||
"
|
||||
if has('nvim')
|
||||
function! s:is_floating(winid) abort
|
||||
let l:config = nvim_win_get_config(a:winid)
|
||||
return empty(l:config) || !empty(get(l:config, 'relative', ''))
|
||||
endfunction
|
||||
else
|
||||
function! s:is_floating(winid) abort
|
||||
return winheight(a:winid) != -1 && win_id2win(a:winid) == 0
|
||||
endfunction
|
||||
endif
|
||||
|
||||
"
|
||||
" scroll
|
||||
"
|
||||
@@ -99,7 +113,7 @@ function! s:scroll(winid, topline) abort
|
||||
return
|
||||
endif
|
||||
|
||||
if index(s:_get_visible_popup_winids(), a:winid) >= 0
|
||||
if !has('nvim') && s:is_floating(a:winid)
|
||||
call popup_setoptions(a:winid, {
|
||||
\ 'firstline': l:topline,
|
||||
\ })
|
||||
@@ -118,13 +132,17 @@ endfunction
|
||||
" @param {[number, number]} pos - position on the current buffer.
|
||||
"
|
||||
function! s:screenpos(pos) abort
|
||||
let l:ui_x = wincol() - col('.')
|
||||
let l:y = a:pos[0]
|
||||
let l:x = a:pos[1] + get(a:pos, 2, 0)
|
||||
|
||||
let l:view = winsaveview()
|
||||
let l:scroll_x = l:view.leftcol
|
||||
let l:scroll_y = l:view.topline - 1
|
||||
let l:scroll_y = l:view.topline
|
||||
|
||||
let l:winpos = win_screenpos(win_getid())
|
||||
let l:origin1 = [l:winpos[0] + (a:pos[0] - l:scroll_y) - 1, l:winpos[1] + (a:pos[1] + a:pos[2] + l:ui_x - l:scroll_x) - 1]
|
||||
return [l:origin1[0] - 1, l:origin1[1] - 1]
|
||||
let l:y = l:winpos[0] + l:y - l:scroll_y
|
||||
let l:x = l:winpos[1] + l:x - l:scroll_x
|
||||
return [l:y, l:x + (wincol() - virtcol('.')) - 1]
|
||||
endfunction
|
||||
|
||||
"
|
||||
|
||||
@@ -33,7 +33,7 @@ function! s:is_available() abort
|
||||
if has('nvim')
|
||||
return v:true
|
||||
endif
|
||||
return exists('*popup_create') && exists('*popup_hide') && exists('*popup_move') && exists('*popup_getpos')
|
||||
return exists('*popup_create') && exists('*popup_close') && exists('*popup_move') && exists('*popup_getpos')
|
||||
endfunction
|
||||
|
||||
"
|
||||
@@ -93,6 +93,7 @@ endfunction
|
||||
" @param {number?} args.maxwidth
|
||||
" @param {number?} args.minheight
|
||||
" @param {number?} args.maxheight
|
||||
" @param {boolean?} args.wrap
|
||||
"
|
||||
function! s:FloatingWindow.get_size(args) abort
|
||||
if self._bufnr is# v:null
|
||||
@@ -115,10 +116,14 @@ function! s:FloatingWindow.get_size(args) abort
|
||||
let l:width = l:maxwidth == -1 ? l:width : min([l:maxwidth, l:width])
|
||||
|
||||
" height
|
||||
let l:height = 0
|
||||
for l:line in l:lines
|
||||
let l:height += max([1, float2nr(ceil(strdisplaywidth(l:line) / str2float('' . l:width)))])
|
||||
endfor
|
||||
if get(a:args, 'wrap', get(self._vars, '&wrap', 0))
|
||||
let l:height = 0
|
||||
for l:line in l:lines
|
||||
let l:height += max([1, float2nr(ceil(strdisplaywidth(l:line) / str2float('' . l:width)))])
|
||||
endfor
|
||||
else
|
||||
let l:height = len(l:lines)
|
||||
endif
|
||||
let l:height = l:minheight == -1 ? l:height : max([l:minheight, l:height])
|
||||
let l:height = l:maxheight == -1 ? l:height : min([l:maxheight, l:height])
|
||||
|
||||
@@ -154,6 +159,16 @@ function! s:FloatingWindow.get_winid() abort
|
||||
return v:null
|
||||
endfunction
|
||||
|
||||
"
|
||||
" info
|
||||
"
|
||||
function! s:FloatingWindow.info() abort
|
||||
if self.is_visible()
|
||||
return s:_info(self._winid)
|
||||
endif
|
||||
return v:null
|
||||
endfunction
|
||||
|
||||
"
|
||||
" set_var
|
||||
"
|
||||
@@ -183,6 +198,8 @@ endfunction
|
||||
" @param {number} args.col 0-based indexing
|
||||
" @param {number} args.width
|
||||
" @param {number} args.height
|
||||
" @param {number?} args.topline
|
||||
" @param {string?} args.origin - topleft/topright/botleft/botright
|
||||
"
|
||||
function! s:FloatingWindow.open(args) abort
|
||||
let l:style = {
|
||||
@@ -190,15 +207,20 @@ function! s:FloatingWindow.open(args) abort
|
||||
\ 'col': a:args.col,
|
||||
\ 'width': a:args.width,
|
||||
\ 'height': a:args.height,
|
||||
\ 'topline': get(a:args, 'topline', 1),
|
||||
\ 'origin': get(a:args, 'origin', 'topleft'),
|
||||
\ }
|
||||
|
||||
if self.is_visible()
|
||||
call s:_move(self._winid, l:style)
|
||||
let l:will_move = self.is_visible()
|
||||
if l:will_move
|
||||
let self._winid = s:_move(self, self._winid, self._bufnr, l:style)
|
||||
else
|
||||
let self._winid = s:_open(self._bufnr, l:style, { -> self._on_closed() })
|
||||
for [l:key, l:value] in items(self._vars)
|
||||
call setwinvar(self._winid, l:key, l:value)
|
||||
endfor
|
||||
endif
|
||||
for [l:key, l:value] in items(self._vars)
|
||||
call setwinvar(self._winid, l:key, l:value)
|
||||
endfor
|
||||
if !l:will_move
|
||||
call s:_notify_opened(self._winid, self)
|
||||
endif
|
||||
endfunction
|
||||
@@ -231,12 +253,14 @@ endfunction
|
||||
" open
|
||||
"
|
||||
if has('nvim')
|
||||
function! s:_open(buf, style, callback) abort
|
||||
return nvim_open_win(a:buf, v:false, s:_style(a:style))
|
||||
function! s:_open(bufnr, style, callback) abort
|
||||
let l:winid = nvim_open_win(a:bufnr, v:false, s:_style(a:style))
|
||||
call s:Window.scroll(l:winid, a:style.topline)
|
||||
return l:winid
|
||||
endfunction
|
||||
else
|
||||
function! s:_open(buf, style, callback) abort
|
||||
return popup_create(a:buf, extend(s:_style(a:style), {
|
||||
function! s:_open(bufnr, style, callback) abort
|
||||
return popup_create(a:bufnr, extend(s:_style(a:style), {
|
||||
\ 'callback': a:callback,
|
||||
\ }, 'force'))
|
||||
endfunction
|
||||
@@ -246,13 +270,13 @@ endif
|
||||
" close
|
||||
"
|
||||
if has('nvim')
|
||||
function! s:_close(win) abort
|
||||
call nvim_win_close(a:win, v:true)
|
||||
function! s:_close(winid) abort
|
||||
call nvim_win_close(a:winid, v:true)
|
||||
call s:_notify_closed()
|
||||
endfunction
|
||||
else
|
||||
function! s:_close(win) abort
|
||||
call popup_close(a:win)
|
||||
function! s:_close(winid) abort
|
||||
call popup_close(a:winid)
|
||||
endfunction
|
||||
endif
|
||||
|
||||
@@ -260,12 +284,26 @@ endif
|
||||
" move
|
||||
"
|
||||
if has('nvim')
|
||||
function! s:_move(win, style) abort
|
||||
call nvim_win_set_config(a:win, s:_style(a:style))
|
||||
function! s:_move(self, winid, bufnr, style) abort
|
||||
call nvim_win_set_config(a:winid, s:_style(a:style))
|
||||
if a:bufnr != nvim_win_get_buf(a:winid)
|
||||
call nvim_win_set_buf(a:winid, a:bufnr)
|
||||
endif
|
||||
call s:Window.scroll(a:winid, a:style.topline)
|
||||
return a:winid
|
||||
endfunction
|
||||
else
|
||||
function! s:_move(win, style) abort
|
||||
call popup_move(a:win, s:_style(a:style))
|
||||
function! s:_move(self, winid, bufnr, style) abort
|
||||
" vim's popup window can't change bufnr so open new popup in here.
|
||||
if a:bufnr != winbufnr(a:winid)
|
||||
let l:On_closed = a:self._on_closed
|
||||
let a:self._on_closed = { -> {} }
|
||||
call s:_close(a:winid)
|
||||
let a:self._on_closed = l:On_closed
|
||||
return s:_open(a:bufnr, a:style, { -> a:self._on_closed() })
|
||||
endif
|
||||
call popup_move(a:winid, s:_style(a:style))
|
||||
return a:winid
|
||||
endfunction
|
||||
endif
|
||||
|
||||
@@ -273,11 +311,11 @@ endif
|
||||
" enter
|
||||
"
|
||||
if has('nvim')
|
||||
function! s:_enter(win) abort
|
||||
call win_gotoid(a:win)
|
||||
function! s:_enter(winid) abort
|
||||
call win_gotoid(a:winid)
|
||||
endfunction
|
||||
else
|
||||
function! s:_enter(win) abort
|
||||
function! s:_enter(winid) abort
|
||||
" not supported.
|
||||
endfunction
|
||||
endif
|
||||
@@ -286,12 +324,36 @@ endif
|
||||
" exists
|
||||
"
|
||||
if has('nvim')
|
||||
function! s:_exists(win) abort
|
||||
return type(a:win) == type(0) && nvim_win_is_valid(a:win) && nvim_win_get_number(a:win) != -1
|
||||
function! s:_exists(winid) abort
|
||||
return type(a:winid) == type(0) && nvim_win_is_valid(a:winid) && nvim_win_get_number(a:winid) != -1
|
||||
endfunction
|
||||
else
|
||||
function! s:_exists(win) abort
|
||||
return type(a:win) == type(0) && winheight(a:win) != -1
|
||||
function! s:_exists(winid) abort
|
||||
return type(a:winid) == type(0) && winheight(a:winid) != -1
|
||||
endfunction
|
||||
endif
|
||||
|
||||
if has('nvim')
|
||||
function! s:_info(winid) abort
|
||||
let l:info = getwininfo(a:winid)[0]
|
||||
return {
|
||||
\ 'row': l:info.winrow,
|
||||
\ 'col': l:info.wincol,
|
||||
\ 'width': l:info.width,
|
||||
\ 'height': l:info.height,
|
||||
\ 'topline': l:info.topline,
|
||||
\ }
|
||||
endfunction
|
||||
else
|
||||
function! s:_info(winid) abort
|
||||
let l:pos = popup_getpos(a:winid)
|
||||
return {
|
||||
\ 'row': l:pos.core_line,
|
||||
\ 'col': l:pos.core_col,
|
||||
\ 'width': l:pos.core_width,
|
||||
\ 'height': l:pos.core_height,
|
||||
\ 'topline': l:pos.firstline,
|
||||
\ }
|
||||
endfunction
|
||||
endif
|
||||
|
||||
@@ -300,33 +362,69 @@ endif
|
||||
"
|
||||
if has('nvim')
|
||||
function! s:_style(style) abort
|
||||
let l:style = s:_resolve_style(a:style)
|
||||
return {
|
||||
\ 'relative': 'editor',
|
||||
\ 'width': a:style.width,
|
||||
\ 'height': a:style.height,
|
||||
\ 'row': a:style.row,
|
||||
\ 'col': a:style.col,
|
||||
\ 'row': l:style.row - 1,
|
||||
\ 'col': l:style.col - 1,
|
||||
\ 'width': l:style.width,
|
||||
\ 'height': l:style.height,
|
||||
\ 'focusable': v:true,
|
||||
\ 'style': 'minimal',
|
||||
\ }
|
||||
endfunction
|
||||
else
|
||||
function! s:_style(style) abort
|
||||
let l:style = s:_resolve_style(a:style)
|
||||
return {
|
||||
\ 'line': a:style.row + 1,
|
||||
\ 'col': a:style.col + 1,
|
||||
\ 'line': l:style.row,
|
||||
\ 'col': l:style.col,
|
||||
\ 'pos': 'topleft',
|
||||
\ 'wrap': v:false,
|
||||
\ 'moved': [0, 0, 0],
|
||||
\ 'scrollbar': 0,
|
||||
\ 'maxwidth': a:style.width,
|
||||
\ 'maxheight': a:style.height,
|
||||
\ 'minwidth': a:style.width,
|
||||
\ 'minheight': a:style.height,
|
||||
\ 'maxwidth': l:style.width,
|
||||
\ 'maxheight': l:style.height,
|
||||
\ 'minwidth': l:style.width,
|
||||
\ 'minheight': l:style.height,
|
||||
\ 'tabpage': 0,
|
||||
\ 'firstline': l:style.topline,
|
||||
\ 'padding': [0, 0, 0, 0],
|
||||
\ 'fixed': v:true,
|
||||
\ }
|
||||
endfunction
|
||||
endif
|
||||
|
||||
"
|
||||
" resolve_style
|
||||
"
|
||||
function! s:_resolve_style(style) abort
|
||||
if index(['topleft', 'topright', 'bottomleft', 'bottomright', 'topcenter', 'bottomcenter'], a:style.origin) == -1
|
||||
let a:style.origin = 'topleft'
|
||||
endif
|
||||
|
||||
if a:style.origin ==# 'topleft'
|
||||
let a:style.col = a:style.col
|
||||
let a:style.row = a:style.row
|
||||
elseif a:style.origin ==# 'topright'
|
||||
let a:style.col = a:style.col - (a:style.width - 1)
|
||||
let a:style.row = a:style.row
|
||||
elseif a:style.origin ==# 'bottomleft'
|
||||
let a:style.col = a:style.col
|
||||
let a:style.row = a:style.row - (a:style.height - 1)
|
||||
elseif a:style.origin ==# 'bottomright'
|
||||
let a:style.col = a:style.col - (a:style.width - 1)
|
||||
let a:style.row = a:style.row - (a:style.height - 1)
|
||||
elseif a:style.origin ==# 'topcenter'
|
||||
let a:style.col = a:style.col - float2nr(a:style.width / 2)
|
||||
let a:style.row = a:style.row
|
||||
elseif a:style.origin ==# 'bottomcenter'
|
||||
let a:style.col = a:style.col - float2nr(a:style.width / 2)
|
||||
let a:style.row = a:style.row - (a:style.height - 1)
|
||||
endif
|
||||
return a:style
|
||||
endfunction
|
||||
|
||||
"
|
||||
" init
|
||||
"
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
lsp
|
||||
274654a8153a620b94c7e6869e838d43b8d9e701
|
||||
621cda4f832d2f43f3b15cdbfb70ca36b219efc2
|
||||
|
||||
VS.LSP.MarkupContent
|
||||
VS.Vim.Window.FloatingWindow
|
||||
VS.Vim.Syntax.Markdown
|
||||
VS.Vim.Buffer
|
||||
VS.Vim.Window
|
||||
|
||||
@@ -19,11 +19,10 @@ CONTENTS *vim-lsp-contents*
|
||||
g:lsp_preview_doubletap |g:lsp_preview_doubletap|
|
||||
g:lsp_insert_text_enabled |g:lsp_insert_text_enabled|
|
||||
g:lsp_text_edit_enabled |g:lsp_text_edit_enabled|
|
||||
g:lsp_documentation_debounce |g:lsp_documentation_debounce|
|
||||
g:lsp_documentation_float |g:lsp_documentation_float|
|
||||
g:lsp_documentation_float_docked |g:lsp_documentation_float_docked|
|
||||
g:lsp_documentation_float_docked_maxheight
|
||||
|g:lsp_documentation_float_docked_maxheight|
|
||||
g:lsp_completion_documentation_enabled
|
||||
|g:lsp_completion_documentation_enabled|
|
||||
g:lsp_completion_documentation_delay
|
||||
|g:lsp_completion_documentation_delay|
|
||||
g:lsp_diagnostics_enabled |g:lsp_diagnostics_enabled|
|
||||
g:lsp_diagnostics_echo_cursor |g:lsp_diagnostics_echo_cursor|
|
||||
g:lsp_diagnostics_echo_delay |g:lsp_diagnostics_echo_delay|
|
||||
@@ -398,7 +397,17 @@ g:lsp_text_edit_enabled *g:lsp_text_edit_enabled*
|
||||
let g:lsp_text_edit_enabled = 1
|
||||
let g:lsp_text_edit_enabled = 0
|
||||
|
||||
g:lsp_documentation_debounce *g:lsp_documentation_debounce*
|
||||
g:lsp_completion_documentation_enabled *g:lsp_completion_documentation_enabled*
|
||||
Type: |Number|
|
||||
Default: `1`
|
||||
|
||||
Enables floating window documentation for complete items.
|
||||
|
||||
Example: >
|
||||
let g:lsp_completion_documentation_enabled = 1
|
||||
let g:lsp_completion_documentation_enabled = 0
|
||||
|
||||
g:lsp_completion_documentation_delay *g:lsp_completion_documentation_delay*
|
||||
Type: |Number|
|
||||
Default: `80`
|
||||
|
||||
@@ -406,39 +415,8 @@ g:lsp_documentation_debounce *g:lsp_documentation_debounce*
|
||||
help with performance. Set this to `0` to disable debouncing.
|
||||
|
||||
Example: >
|
||||
let g:lsp_documentation_debounce = 120
|
||||
let g:lsp_documentation_debounce = 0
|
||||
|
||||
g:lsp_documentation_float *g:lsp_documentation_float*
|
||||
Type: |Number|
|
||||
Default: `1`
|
||||
|
||||
Enables floating window documentation for complete items.
|
||||
|
||||
Example: >
|
||||
let g:lsp_documentation_float = 1
|
||||
let g:lsp_documentation_float = 0
|
||||
|
||||
g:lsp_documentation_float_docked *g:lsp_documentation_float_docked*
|
||||
Type: |Number|
|
||||
Default: `0`
|
||||
|
||||
Dock the floating documentation window for complete items if enabled.
|
||||
|
||||
Example: >
|
||||
let g:lsp_documentation_float_docked = 1
|
||||
let g:lsp_documentation_float_docked = 0
|
||||
|
||||
g:lsp_documentation_float_docked_maxheight
|
||||
*g:lsp_documentation_float_docked_maxheight*
|
||||
Type: |Number|
|
||||
Default: `&previewheight`
|
||||
|
||||
The maximum height of the docked documentation window if enabled.
|
||||
|
||||
Example: >
|
||||
let g:lsp_documentation_float_docked_maxheight = 1
|
||||
let g:lsp_documentation_float_docked_maxheight = 0
|
||||
let g:lsp_completion_documentation_delay = 120
|
||||
let g:lsp_completion_documentation_delay = 0
|
||||
|
||||
g:lsp_diagnostics_enabled *g:lsp_diagnostics_enabled*
|
||||
Type: |Number|
|
||||
|
||||
@@ -10,10 +10,9 @@ let g:lsp_log_file = get(g:, 'lsp_log_file', '')
|
||||
let g:lsp_log_verbose = get(g:, 'lsp_log_verbose', 1)
|
||||
let g:lsp_debug_servers = get(g:, 'lsp_debug_servers', [])
|
||||
let g:lsp_format_sync_timeout = get(g:, 'lsp_format_sync_timeout', -1)
|
||||
let g:lsp_documentation_debounce = get(g:, 'lsp_documentation_debounce', 80)
|
||||
let g:lsp_documentation_float = get(g:, 'lsp_documentation_float', 1)
|
||||
let g:lsp_documentation_float_docked = get(g:, 'lsp_documentation_float_docked', 0)
|
||||
let g:lsp_documentation_float_docked_maxheight = get(g:, ':lsp_documentation_float_docked_maxheight', &previewheight)
|
||||
|
||||
let g:lsp_completion_documentation_enabled = get(g:, 'lsp_completion_documentation_enabled', 1)
|
||||
let g:lsp_completion_documentation_delay = get(g:, 'lsp_completion_documention_delay', 80)
|
||||
|
||||
let g:lsp_diagnostics_enabled = get(g:, 'lsp_diagnostics_enabled', 1)
|
||||
let g:lsp_diagnostics_echo_cursor = get(g:, 'lsp_diagnostics_echo_cursor', 0)
|
||||
|
||||
Reference in New Issue
Block a user