diff options
author | Andrey Popp <8mayday@gmail.com> | 2019-05-01 21:35:15 +0300 |
---|---|---|
committer | w0rp <w0rp@users.noreply.github.com> | 2019-05-01 19:35:15 +0100 |
commit | 114198e0825d4fa33ad1fe62a41a69fd9b4d52c1 (patch) | |
tree | a2615dc0aeeb643bb5ef1e5bdc896343be65952f /autoload | |
parent | 2f3bce5a1d6e4e1f01ae392d141ab1ab9477ddae (diff) | |
download | ale-114198e0825d4fa33ad1fe62a41a69fd9b4d52c1.zip |
Optionally use neovim's api-highlights (#2169)
Diffstat (limited to 'autoload')
-rw-r--r-- | autoload/ale/highlight.vim | 140 |
1 files changed, 125 insertions, 15 deletions
diff --git a/autoload/ale/highlight.vim b/autoload/ale/highlight.vim index ae1f3e7d..3e09f26d 100644 --- a/autoload/ale/highlight.vim +++ b/autoload/ale/highlight.vim @@ -26,6 +26,41 @@ endif let s:MAX_POS_VALUES = 8 let s:MAX_COL_SIZE = 1073741824 " pow(2, 30) +" Check if we have neovim's buffer highlight API +" +" Below we define some functions' implementation conditionally if this API +" exists or not. +" +" The API itself is more ergonomic and neovim performs highlights positions +" rebases during edits so we see less stalled highlights. +let s:nvim_api = exists('*nvim_buf_add_highlight') && exists('*nvim_buf_clear_namespace') + +function! ale#highlight#HasNeovimApi() abort + return s:nvim_api +endfunction + +function! ale#highlight#nvim_buf_clear_namespace(...) abort + return call('nvim_buf_clear_namespace', a:000) +endfunction + +function! ale#highlight#nvim_buf_add_highlight(...) abort + return call('nvim_buf_add_highlight', a:000) +endfunction + +function! s:ale_nvim_highlight_id(bufnr) abort + let l:id = getbufvar(a:bufnr, 'ale_nvim_highlight_id', -1) + + if l:id is -1 + " NOTE: This will highlight nothing but will allocate new id + let l:id = ale#highlight#nvim_buf_add_highlight( + \ a:bufnr, 0, '', 0, 0, -1 + \) + call setbufvar(a:bufnr, 'ale_nvim_highlight_id', l:id) + endif + + return l:id +endfunction + function! ale#highlight#CreatePositions(line, col, end_line, end_col) abort if a:line >= a:end_line " For single lines, just return the one position. @@ -49,12 +84,90 @@ endfunction " Given a loclist for current items to highlight, remove all highlights " except these which have matching loclist item entries. + function! ale#highlight#RemoveHighlights() abort - for l:match in getmatches() - if l:match.group =~# '^ALE' - call matchdelete(l:match.id) + if ale#highlight#HasNeovimApi() + if get(b:, 'ale_nvim_highlight_id', 0) + let l:bufnr = bufnr('%') + " NOTE: 0, -1 means from 0 line till the end of buffer + call ale#highlight#nvim_buf_clear_namespace( + \ l:bufnr, + \ b:ale_nvim_highlight_id, + \ 0, -1 + \) endif - endfor + else + for l:match in getmatches() + if l:match.group =~# '^ALE' + call matchdelete(l:match.id) + endif + endfor + endif +endfunction + +function! s:highlight_line(bufnr, lnum, group) abort + if ale#highlight#HasNeovimApi() + let l:highlight_id = s:ale_nvim_highlight_id(a:bufnr) + call ale#highlight#nvim_buf_add_highlight( + \ a:bufnr, l:highlight_id, a:group, + \ a:lnum, 0, -1 + \) + else + call matchaddpos(a:group, [a:lnum]) + endif +endfunction + +function! s:highlight_range(bufnr, range, group) abort + if ale#highlight#HasNeovimApi() + let l:highlight_id = s:ale_nvim_highlight_id(a:bufnr) + " NOTE: lines and columns indicies are 0-based in nvim_buf_* API. + let l:lnum = a:range.lnum - 1 + let l:end_lnum = a:range.end_lnum - 1 + let l:col = a:range.col - 1 + let l:end_col = a:range.end_col + + if l:lnum >= l:end_lnum + " For single lines, just return the one position. + call ale#highlight#nvim_buf_add_highlight( + \ a:bufnr, l:highlight_id, a:group, + \ l:lnum, l:col, l:end_col + \) + else + " highlight first line from start till the line end + call ale#highlight#nvim_buf_add_highlight( + \ a:bufnr, l:highlight_id, a:group, + \ l:lnum, l:col, -1 + \) + + " highlight all lines between the first and last entirely + let l:cur = l:lnum + 1 + + while l:cur < l:end_lnum + call ale#highlight#nvim_buf_add_highlight( + \ a:bufnr, l:highlight_id, a:group, + \ l:cur, 0, -1 + \ ) + let l:cur += 1 + endwhile + + call ale#highlight#nvim_buf_add_highlight( + \ a:bufnr, l:highlight_id, a:group, + \ l:end_lnum, 0, l:end_col + \) + endif + else + " Set all of the positions, which are chunked into Lists which + " are as large as will be accepted by matchaddpos. + call map( + \ ale#highlight#CreatePositions( + \ a:range.lnum, + \ a:range.col, + \ a:range.end_lnum, + \ a:range.end_col + \ ), + \ 'matchaddpos(a:group, v:val)' + \) + endif endfunction function! ale#highlight#UpdateHighlights() abort @@ -79,17 +192,14 @@ function! ale#highlight#UpdateHighlights() abort let l:group = 'ALEError' endif - let l:line = l:item.lnum - let l:col = l:item.col - let l:end_line = get(l:item, 'end_lnum', l:line) - let l:end_col = get(l:item, 'end_col', l:col) + let l:range = { + \ 'lnum': l:item.lnum, + \ 'col': l:item.col, + \ 'end_lnum': get(l:item, 'end_lnum', l:item.lnum), + \ 'end_col': get(l:item, 'end_col', l:item.col) + \} - " Set all of the positions, which are chunked into Lists which - " are as large as will be accepted by matchaddpos. - call map( - \ ale#highlight#CreatePositions(l:line, l:col, l:end_line, l:end_col), - \ 'matchaddpos(l:group, v:val)' - \) + call s:highlight_range(l:item.bufnr, l:range, l:group) endfor " If highlights are enabled and signs are not enabled, we should still @@ -111,7 +221,7 @@ function! ale#highlight#UpdateHighlights() abort endif if l:available_groups[l:group] - call matchaddpos(l:group, [l:item.lnum]) + call s:highlight_line(l:item.bufnr, l:item.lnum, l:group) endif endfor endif |