summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Groß <21310755+vimpostor@users.noreply.github.com>2022-09-07 12:38:01 +0200
committerGitHub <noreply@github.com>2022-09-07 19:38:01 +0900
commit9feba1148c7949523108a38ab45297d5ed0d5b1a (patch)
tree7183d6bcb8d305615964ff6e63dfecc5c0fa74ee
parent4943b7d39f75cb19e5be6c0cab94132655f07f07 (diff)
downloadale-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
-rw-r--r--autoload/ale/engine.vim6
-rw-r--r--autoload/ale/events.vim2
-rw-r--r--autoload/ale/toggle.vim4
-rw-r--r--autoload/ale/virtualtext.vim95
-rw-r--r--doc/ale.txt3
5 files changed, 68 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
diff --git a/doc/ale.txt b/doc/ale.txt
index c9cb8585..049f7159 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -2297,6 +2297,9 @@ g:ale_virtualtext_cursor *g:ale_virtualtext_cursor*
column nearest to the cursor when the cursor is resting on a line which
contains a warning or error. This option can be set to `0` to disable this
behavior.
+ When this option is set to `2`, then all warnings will be shown for the
+ whole buffer, regardless of if the cursor is currently positioned in that
+ line.
Messages are only displayed after a short delay. See |g:ale_virtualtext_delay|.