diff options
author | Magnus Groß <21310755+vimpostor@users.noreply.github.com> | 2022-09-07 12:38:01 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-07 19:38:01 +0900 |
commit | 9feba1148c7949523108a38ab45297d5ed0d5b1a (patch) | |
tree | 7183d6bcb8d305615964ff6e63dfecc5c0fa74ee /autoload | |
parent | 4943b7d39f75cb19e5be6c0cab94132655f07f07 (diff) | |
download | ale-9feba1148c7949523108a38ab45297d5ed0d5b1a.zip |
Implement buffer-wide virtual text support (#4289)
* Remove virtual text via types-filter
This is more robust and has the additional sideeffect that it will make
it easier to implement showing virtual text for all warnings
simultaneously.
We definitely do not want to do a call to prop_remove() for every
virtual text as that will cause noticeable lag when many warnings are
present, thus we can use this to remove all virtual text lines with one
call in the future.
Fixes #4294
refs: https://github.com/vim/vim/pull/10945
* Allow virtual text to appear for all warnings of the buffer
This can be enabled with:
let g:ale_virtualtext_cursor = 2
It is implemented both for neovim and vim 9.0.0297.
Note that sometimes it may appear like some warnings are displayed
multiple times. This is not a bug in the virtual text implementation,
but a sideeffect of multiple linters returning similar results.
For example for Rust, the 'cargo' and 'rls' linters appear to be
activated at the same time, but they sometimes return identical errors.
This causes the virtual text to show the same warning twice.
In the future we can mitigate this problem by removing duplicate errors
from our internal location list.
However users can also achieve cleaner warnings simply by activating
only one linter for each language (or multiple unambiguous linters).
For example for Rust, the problem could be solved with:
let g:ale_linters = {'rust': ['analyzer']}
Fixes #2962
Fixes #3666
Diffstat (limited to 'autoload')
-rw-r--r-- | autoload/ale/engine.vim | 6 | ||||
-rw-r--r-- | autoload/ale/events.vim | 2 | ||||
-rw-r--r-- | autoload/ale/toggle.vim | 4 | ||||
-rw-r--r-- | autoload/ale/virtualtext.vim | 95 |
4 files changed, 65 insertions, 42 deletions
diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index 00789a2d..97c46656 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -203,6 +203,10 @@ function! ale#engine#SetResults(buffer, loclist) abort call ale#highlight#SetHighlights(a:buffer, a:loclist) endif + if g:ale_virtualtext_cursor == 2 + call ale#virtualtext#SetTexts(a:buffer, a:loclist) + endif + if l:linting_is_done if g:ale_echo_cursor " Try and echo the warning now. @@ -210,7 +214,7 @@ function! ale#engine#SetResults(buffer, loclist) abort call ale#cursor#EchoCursorWarning() endif - if g:ale_virtualtext_cursor + if g:ale_virtualtext_cursor == 1 " Try and show the warning now. " This will only do something meaningful if we're in normal mode. call ale#virtualtext#ShowCursorWarning() diff --git a/autoload/ale/events.vim b/autoload/ale/events.vim index b8350c79..4efb8a3b 100644 --- a/autoload/ale/events.vim +++ b/autoload/ale/events.vim @@ -139,7 +139,7 @@ function! ale#events#Init() abort autocmd InsertLeave * if exists('*ale#engine#Cleanup') | call ale#cursor#EchoCursorWarning() | endif endif - if g:ale_virtualtext_cursor + if g:ale_virtualtext_cursor == 1 autocmd CursorMoved,CursorHold * if exists('*ale#engine#Cleanup') | call ale#virtualtext#ShowCursorWarningWithDelay() | endif " Look for a warning to echo as soon as we leave Insert mode. " The script's position variable used when moving the cursor will diff --git a/autoload/ale/toggle.vim b/autoload/ale/toggle.vim index 122d6cc4..7f8957d4 100644 --- a/autoload/ale/toggle.vim +++ b/autoload/ale/toggle.vim @@ -14,8 +14,8 @@ function! s:DisablePostamble() abort call ale#highlight#UpdateHighlights() endif - if g:ale_virtualtext_cursor - call ale#virtualtext#Clear() + if g:ale_virtualtext_cursor == 1 + call ale#virtualtext#Clear(bufnr('')) endif endfunction diff --git a/autoload/ale/virtualtext.vim b/autoload/ale/virtualtext.vim index e4bf5d25..5fade39b 100644 --- a/autoload/ale/virtualtext.vim +++ b/autoload/ale/virtualtext.vim @@ -15,52 +15,49 @@ if has('nvim-0.3.2') let s:has_virt_text = 1 elseif has('textprop') && has('popupwin') let s:has_virt_text = 1 - let s:emulate_virt = !has('patch-9.0.0214') + let s:emulate_virt = !has('patch-9.0.0297') + let s:hl_list = [] if s:emulate_virt call prop_type_add('ale', {}) let s:last_virt = -1 - else - let s:last_virt = 1 endif endif -function! ale#virtualtext#Clear() abort +function! ale#virtualtext#Clear(buf) abort if !s:has_virt_text return endif - let l:buffer = bufnr('') - if has('nvim') - call nvim_buf_clear_highlight(l:buffer, s:ns_id, 0, -1) + call nvim_buf_clear_namespace(a:buf, s:ns_id, 0, -1) else if s:emulate_virt && s:last_virt != -1 call prop_remove({'type': 'ale'}) call popup_close(s:last_virt) let s:last_virt = -1 - elseif !s:emulate_virt && s:last_virt != 1 - call prop_remove({'id': s:last_virt}) - let s:last_virt = 1 + elseif !empty(s:hl_list) + call prop_remove({ + \ 'types': s:hl_list, + \ 'all': 1, + \ 'bufnr': a:buf}) endif endif endfunction -function! ale#virtualtext#ShowMessage(message, hl_group) abort - if !s:has_virt_text +function! ale#virtualtext#ShowMessage(message, hl_group, buf, line) abort + if !s:has_virt_text || !bufexists(str2nr(a:buf)) return endif - let l:line = line('.') - let l:buffer = bufnr('') let l:prefix = get(g:, 'ale_virtualtext_prefix', '> ') let l:msg = l:prefix.trim(substitute(a:message, '\n', ' ', 'g')) if has('nvim') - call nvim_buf_set_virtual_text(l:buffer, s:ns_id, l:line-1, [[l:msg, a:hl_group]], {}) + call nvim_buf_set_virtual_text(a:buf, s:ns_id, a:line-1, [[l:msg, a:hl_group]], {}) elseif s:emulate_virt let l:left_pad = col('$') - call prop_add(l:line, l:left_pad, { + call prop_add(a:line, l:left_pad, { \ 'type': 'ale', \}) let s:last_virt = popup_create(l:msg, { @@ -77,12 +74,14 @@ function! ale#virtualtext#ShowMessage(message, hl_group) abort let type = prop_type_get(a:hl_group) if type == {} + call add(s:hl_list, a:hl_group) call prop_type_add(a:hl_group, {'highlight': a:hl_group}) endif - let s:last_virt = prop_add(l:line, 0, { + call prop_add(a:line, 0, { \ 'type': a:hl_group, - \ 'text': ' ' . l:msg + \ 'text': ' ' . l:msg, + \ 'bufnr': a:buf \}) endif endfunction @@ -94,8 +93,26 @@ function! s:StopCursorTimer() abort endif endfunction +function! ale#virtualtext#GetHlGroup(type, style) abort + if a:type is# 'E' + if a:style is# 'style' + return 'ALEVirtualTextStyleError' + else + return 'ALEVirtualTextError' + endif + elseif a:type is# 'W' + if a:style is# 'style' + return 'ALEVirtualTextStyleWarning' + else + return 'ALEVirtualTextWarning' + endif + else + return 'ALEVirtualTextInfo' + endif +endfunction + function! ale#virtualtext#ShowCursorWarning(...) abort - if !g:ale_virtualtext_cursor + if g:ale_virtualtext_cursor != 1 return endif @@ -111,35 +128,21 @@ function! ale#virtualtext#ShowCursorWarning(...) abort let [l:info, l:loc] = ale#util#FindItemAtCursor(l:buffer) - call ale#virtualtext#Clear() + call ale#virtualtext#Clear(l:buffer) if !empty(l:loc) let l:msg = l:loc.text - let l:hl_group = 'ALEVirtualTextInfo' let l:type = get(l:loc, 'type', 'E') - - if l:type is# 'E' - if get(l:loc, 'sub_type', '') is# 'style' - let l:hl_group = 'ALEVirtualTextStyleError' - else - let l:hl_group = 'ALEVirtualTextError' - endif - elseif l:type is# 'W' - if get(l:loc, 'sub_type', '') is# 'style' - let l:hl_group = 'ALEVirtualTextStyleWarning' - else - let l:hl_group = 'ALEVirtualTextWarning' - endif - endif - - call ale#virtualtext#ShowMessage(l:msg, l:hl_group) + let l:style = get(l:loc, 'sub_type', '') + let l:hl_group = ale#virtualtext#GetHlGroup(l:type, l:style) + call ale#virtualtext#ShowMessage(l:msg, l:hl_group, l:buffer, line('.')) endif endfunction function! ale#virtualtext#ShowCursorWarningWithDelay() abort let l:buffer = bufnr('') - if !g:ale_virtualtext_cursor + if g:ale_virtualtext_cursor != 1 return endif @@ -166,3 +169,19 @@ function! ale#virtualtext#ShowCursorWarningWithDelay() abort endif endfunction +function! ale#virtualtext#SetTexts(buf, loclist) abort + if !has('nvim') && s:emulate_virt + return + endif + + call ale#virtualtext#Clear(a:buf) + + for l in a:loclist + if l['bufnr'] != a:buf + continue + endif + + let hl = ale#virtualtext#GetHlGroup(l['type'], get(l, 'sub_type', '')) + call ale#virtualtext#ShowMessage(l['text'], hl, a:buf, l['lnum']) + endfor +endfunction |