Skip to content
This repository has been archived by the owner on Jan 27, 2022. It is now read-only.

Commit

Permalink
Add padding and bunch of improvements (#249)
Browse files Browse the repository at this point in the history
* Add padding and bunch of improvements

* Add basic html entities and escape chars(maybe)

* Improve escape char handling

* Add CompeDocumentation highlight group

* Documentation improvements

* Change var name

* Fix documentation bug

* Update vital modules

* Update vital modules

* Improve suggest_offset

* - Avoid GC for perf
- Refactor callback handling

* Avoid restoring flicker

* Improce helper

* Improve convert_lsp
  • Loading branch information
hrsh7th committed Mar 13, 2021
1 parent 2517075 commit 72c4500
Show file tree
Hide file tree
Showing 20 changed files with 450 additions and 334 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Auto completion plugin for nvim.
- [Vim script Config](#vim-script-config)
- [Lua Config](#lua-config)
- [Mappings](#mappings)
- [Highlight](#highlight)
- [Built-in sources](#built-in-sources)
- [Common](#common)
- [Neovim-specific](#neovim-specific)
Expand Down Expand Up @@ -178,6 +179,15 @@ inoremap <silent><expr> <C-f> compe#scroll({ 'delta': +4 })
inoremap <silent><expr> <C-d> compe#scroll({ 'delta': -4 })
```

### Highlight

You can change documentation window's highlight group via following.

```viml
highlight link CompeDocumentation NormalFloat
```


## Built-in sources

### Common
Expand Down
4 changes: 2 additions & 2 deletions autoload/compe.vim
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ function! compe#register_source(name, source) abort
if matchstr(a:name, '^\w\+$') ==# ''
throw "compe: the source's name must be \w\+"
endif
return compe#source#vim_bridge#register(a:name, a:source)
return compe#vim_bridge#register(a:name, a:source)
endfunction

"
" compe#register_source
"
function! compe#unregister_source(id) abort
call compe#source#vim_bridge#unregister(a:id)
call compe#vim_bridge#unregister(a:id)
endfunction

"
Expand Down
88 changes: 42 additions & 46 deletions autoload/compe/documentation.vim
Original file line number Diff line number Diff line change
Expand Up @@ -7,83 +7,79 @@ let s:FloatingWindow = vital#compe#import('VS.Vim.Window.FloatingWindow')
let s:window = s:FloatingWindow.new()
call s:window.set_var('&wrap', 1)
call s:window.set_var('&conceallevel', 2)
call s:window.set_var('&breakindent', 1)
call s:window.set_var('&winhighlight', 'NormalFloat:CompeDocumentation')
call s:window.set_var('compe_documentation', 1)
call s:window.set_bufnr(s:Buffer.create())
call setbufvar(s:window.get_bufnr(), '&buftype', 'nofile')
call setbufvar(s:window.get_bufnr(), '&bufhidden', 'hide')
call setbufvar(s:window.get_bufnr(), '&buflisted', 0)
call setbufvar(s:window.get_bufnr(), '&swapfile', 0)

let s:state = {
\ 'pumpos': {},
\ 'document': '',
\ }

let s:cache = {}
let s:document_cache = {}
let s:state = {}
let s:timer = 0

"
" compe#documentation#show
"
function! compe#documentation#open(document) abort
function! compe#documentation#open(text) abort
if getcmdwintype() !=# ''
return s:window.close()
return compe#documentation#close()
endif

let l:ctx = {}
function! l:ctx.callback(document) abort
let l:state = {}
let l:state.pumpos = pum_getpos()
let l:state.document = type(a:document) == type([]) ? join(a:document, "\n") : a:document

" Check if condition has changed.
let l:same_pumpos = s:state.pumpos == l:state.pumpos
let l:same_document = s:state.document ==# l:state.document
if l:same_pumpos && l:same_document
function! l:ctx.callback(text) abort
if !pumvisible()
return
endif
let s:state = l:state

" Ensure normalized document
if !has_key(s:cache, l:state.document)
let s:cache[l:state.document] = split(s:MarkupContent.normalize(l:state.document), "\n")
endif
let l:document = s:cache[l:state.document]

if !l:same_document
let l:text = type(a:text) == type([]) ? join(a:text, "\n") : a:text
if !has_key(s:document_cache, l:text)
let l:document = map(split(s:MarkupContent.normalize(l:text), "\n"), '" " . v:val . " "')
silent call deletebufline(s:window.get_bufnr(), 1, '$')
silent call setbufline(s:window.get_bufnr(), 1, l:document)
let s:document_cache[l:text] = {}
let s:document_cache[l:text].document = l:document
let s:document_cache[l:text].size = s:window.get_size({ 'maxwidth': float2nr(&columns * 0.4), 'maxheight': float2nr(&lines * 0.3), })
else
silent call deletebufline(s:window.get_bufnr(), 1, '$')
silent call setbufline(s:window.get_bufnr(), 1, s:document_cache[l:text].document)
endif

let l:size = s:window.get_size({
\ 'maxwidth': float2nr(&columns * 0.4),
\ 'maxheight': float2nr(&lines * 0.3),
\ })

let l:pos = s:get_screenpos(l:state.pumpos, l:size)
let l:document = s:document_cache[l:text].document
let l:size = s:document_cache[l:text].size
let l:pos = s:get_screenpos(pum_getpos(), l:size)
if empty(l:pos)
return s:window.close()
return compe#documentation#close()
endif

if pumvisible()
silent call s:window.open({
\ 'row': l:pos[0] + 1,
\ 'col': l:pos[1] + 1,
\ 'width': l:size.width,
\ 'height': l:size.height,
\ })
silent call s:Window.do(s:window.get_winid(), { -> s:Markdown.apply() })
let l:state = { 'pos': l:pos, 'size': l:size, 'document': l:document }
if s:state == l:state
return
endif
let s:state = l:state

silent call s:window.open({
\ 'row': l:state.pos[0] + 1,
\ 'col': l:state.pos[1] + 1,
\ 'width': l:state.size.width,
\ 'height': l:state.size.height,
\ })
silent call s:Window.do(s:window.get_winid(), { -> s:Markdown.apply() })
endfunction
call timer_start(0, { -> l:ctx.callback(a:document) })
call timer_stop(s:timer)
let s:timer = timer_start(0, { -> l:ctx.callback(a:text) })
endfunction

"
" compe#documentation#close
"
function! compe#documentation#close() abort
let s:state = { 'pumpos': {}, 'document': '' }
let s:cache = {}
call timer_start(0, { -> s:window.close() })
let s:document_cache = {}
let s:state = {}
call timer_stop(s:timer)
let s:timer = timer_start(0, { -> s:window.close() })
endfunction

"
Expand All @@ -94,8 +90,8 @@ function! s:get_screenpos(event, size) abort
return []
endif

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
let l:col_if_right = a:event.col + a:event.width + (a:event.scrollbar ? 1 : 0)
let l:col_if_left = a:event.col - a:size.width - 1

if a:event.col > float2nr(&columns * 0.6)
let l:col = l:col_if_left
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ let s:base_bridge_id = 0
let s:sources = {}

"
" compe#source#vim_bridge#register
" compe#vim_bridge#register
"
function! compe#source#vim_bridge#register(name, source) abort
function! compe#vim_bridge#register(name, source) abort
let s:base_bridge_id += 1

let l:bridge_id = a:name . '_' . s:base_bridge_id
Expand All @@ -18,9 +18,9 @@ function! compe#source#vim_bridge#register(name, source) abort
endfunction

"
" compe#source#vim_bridge#unregister
" compe#vim_bridge#unregister
"
function! compe#source#vim_bridge#unregister(id) abort
function! compe#vim_bridge#unregister(id) abort
for [l:bridge_id, l:source] in items(s:sources)
if l:source.id == a:id
unlet s:sources[l:bridge_id]
Expand All @@ -31,73 +31,70 @@ function! compe#source#vim_bridge#unregister(id) abort
endfunction

"
" compe#source#vim_bridge#get_metadata
" compe#vim_bridge#get_metadata
"
function! compe#source#vim_bridge#get_metadata(bridge_id) abort
function! compe#vim_bridge#get_metadata(bridge_id) abort
if has_key(s:sources, a:bridge_id) && has_key(s:sources[a:bridge_id], 'get_metadata')
return s:sources[a:bridge_id].get_metadata()
endif
return {}
endfunction

"
" compe#source#vim_bridge#determine
" compe#vim_bridge#determine
"
function! compe#source#vim_bridge#determine(bridge_id, context) abort
function! compe#vim_bridge#determine(bridge_id, context) abort
if has_key(s:sources, a:bridge_id) && has_key(s:sources[a:bridge_id], 'determine')
return s:sources[a:bridge_id].determine(a:context)
endif
return {}
endfunction

"
" compe#source#vim_bridge#documentation
" compe#vim_bridge#documentation
"
function! compe#source#vim_bridge#documentation(bridge_id, args) abort
function! compe#vim_bridge#documentation(bridge_id, args) abort
if has_key(s:sources, a:bridge_id) && has_key(s:sources[a:bridge_id], 'documentation')
let a:args.callback = { document ->
\ luaeval('require"compe.vim_bridge".documentation_on_callback(_A[1], _A[2])', [a:bridge_id, document])
\ }
let a:args.abort = { ->
\ luaeval('require"compe.vim_bridge".documentation_on_abort(_A[1])', [a:bridge_id])
\ }
let a:args.callback = s:callback(a:args.callback)
let a:args.abort = s:callback(a:args.abort)
call s:sources[a:bridge_id].documentation(a:args)
endif
endfunction

"
" compe#source#vim_bridge#complete
" compe#vim_bridge#complete
"
function! compe#source#vim_bridge#complete(bridge_id, args) abort
function! compe#vim_bridge#complete(bridge_id, args) abort
if has_key(s:sources, a:bridge_id) && has_key(s:sources[a:bridge_id], 'complete')
let a:args.callback = { result ->
\ luaeval('require"compe.vim_bridge".complete_on_callback(_A[1], _A[2])', [a:bridge_id, result])
\ }
let a:args.abort = { ->
\ luaeval('require"compe.vim_bridge".complete_on_abort(_A[1])', [a:bridge_id])
\ }
let a:args.callback = s:callback(a:args.callback)
let a:args.abort = s:callback(a:args.abort)
call s:sources[a:bridge_id].complete(a:args)
endif
endfunction

"
" compe#source#vim_bridge#resolve
" compe#vim_bridge#resolve
"
function! compe#source#vim_bridge#resolve(bridge_id, args) abort
function! compe#vim_bridge#resolve(bridge_id, args) abort
if has_key(s:sources, a:bridge_id) && has_key(s:sources[a:bridge_id], 'resolve')
let a:args.callback = { completed_item ->
\ luaeval('require"compe.vim_bridge".resolve_on_callback(_A[1], _A[2])', [a:bridge_id, completed_item])
\ }
let a:args.callback = s:callback(a:args.callback)
call s:sources[a:bridge_id].resolve(a:args)
endif
endfunction

"
" compe#source#vim_bridge#confirm
" compe#vim_bridge#confirm
"
function! compe#source#vim_bridge#confirm(bridge_id, args) abort
function! compe#vim_bridge#confirm(bridge_id, args) abort
if has_key(s:sources, a:bridge_id) && has_key(s:sources[a:bridge_id], 'confirm')
call s:sources[a:bridge_id].confirm(a:args)
endif
endfunction

"
" callback
"
function! s:callback(callback_id) abort
return { ... -> luaeval('require"compe"._on_callback(_A[1], unpack(_A[2]))', [a:callback_id, a:000]) }
endfunction

63 changes: 49 additions & 14 deletions autoload/vital/_compe/VS/Vim/Syntax/Markdown.vim
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,32 @@ delfunction s:_SID
" ___vital___
function! s:apply(...) abort
if !exists('b:___VS_Vim_Syntax_Markdown')
runtime! syntax/markdown.vim
call s:_execute('runtime! syntax/markdown.vim')

" Modify markdownCode
syntax clear markdownCode
syntax region markdownCode matchgroup=Conceal start=/\%(``\)\@!`/ matchgroup=Conceal end=/\%(``\)\@!`/ containedin=TOP keepend concealends

" Modify markdownEscape
syntax clear markdownEscape
let l:name = 0
for l:char in split('!"#$%&()*+,-.g:;<=>?@[]^_`{|}~' . "'", '\zs')
let l:name += 1
execute printf('syntax match vital_vs_vim_syntax_markdown_escape_%s /[^\\]\?\zs\\\V%s/ conceal cchar=%s containedin=ALL',
\ l:name,
\ l:char,
\ l:char,
\ )
endfor
syntax match vital_vs_vim_syntax_markdown_escape_escape /[^\\]\?\zs\\\\/ conceal cchar=\ containedin=ALL

" Add syntax for basic html entities.
syntax match vital_vs_vim_syntax_markdown_entities_lt /&lt;/ containedin=ALL conceal cchar=<
syntax match vital_vs_vim_syntax_markdown_entities_gt /&gt;/ containedin=ALL conceal cchar=>
syntax match vital_vs_vim_syntax_markdown_entities_amp /&amp;/ containedin=ALL conceal cchar=&
syntax match vital_vs_vim_syntax_markdown_entities_quot /&quot;/ containedin=ALL conceal cchar="
syntax match vital_vs_vim_syntax_markdown_entities_nbsp /&nbsp;/ containedin=ALL conceal cchar=

let b:___VS_Vim_Syntax_Markdown = {}
endif

Expand All @@ -23,25 +48,35 @@ function! s:apply(...) abort
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',
call s:_execute('syntax include @%s syntax/%s.vim', l:group, l:filetype)
call s:_execute('syntax region %s matchgroup=Conceal start=/%s/rs=e matchgroup=Conceal end=/%s/re=s contains=@%s containedin=TOP keepend concealends',
\ l:group,
\ printf('^\s*```\s*%s\s*', l:mark),
\ '\s*```\s*$',
\ printf('```%s\s*', l:mark),
\ '```\s*\%(\s\|' . "\n" . '\|$\)',
\ 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)
unsilent 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 })
unsilent echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
endtry
endfunction

"
" _execute
"
function! s:_execute(command, ...) abort
let b:current_syntax = ''
unlet b:current_syntax

let g:main_syntax = ''
unlet g:main_syntax

execute call('printf', [a:command] + a:000)
endfunction

"
" _get_filetype_map
"
Expand All @@ -63,12 +98,12 @@ function! s:_find_marks(bufnr) abort
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)
let l:match = matchstrpos(l:text, '```\s*\zs\w\+', l:pos, 1)
if empty(l:match[0])
break
endif
let l:marks[l:match[1]] = v:true
let l:pos = matchend(l:text, '```\s*\(\w\+\)', l:pos, 1)
let l:marks[l:match[0]] = v:true
let l:pos = l:match[2]
endwhile

return keys(l:marks)
Expand Down

0 comments on commit 72c4500

Please sign in to comment.