diff options
author | Magnus Groß <21310755+vimpostor@users.noreply.github.com> | 2023-09-05 15:36:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-05 14:36:17 +0100 |
commit | 59e455b4d8cf70521fd0f551e91d584294a9af46 (patch) | |
tree | 55c990f23f233d2ceb715d1ed9f3d3da94867af2 | |
parent | ea27441834de203c9a8b080d7fbdaa8719f78a52 (diff) | |
download | ale-59e455b4d8cf70521fd0f551e91d584294a9af46.zip |
Improve ALEFix performance for neovim (#3974)
* Avoid performance problems with setbufline() and Treesitter
Call nvim_buf_set_lines() instead.
Since this is a performance problem only in Neovim (Treesitter is only
available there), it doesn't matter that this API is unavailable in Vim.
Note: nvim_buf_set_lines() returns E5555, when set nomodifiable is on.
Fixes #3669
* Avoid sign flickering
The signs flickered because nvim_buf_set_lines() removes all signs from
lines that it touches, which will immediately be readded by Ale (causing
the brief flicker). This is intended behaviour in neovim [0].
Neovim itself faced this problem in their own LSP formatting sync,
although they had the problem with marks instead of signs [1].
Similar to how neovim fixed it by storing and restoring the marks [2],
we can do the same thing with signs.
In fact it is easier with signs, because sign_placelist() will just
ignore and skip invalid line numbers, so we don't need to filter signs
that are not valid anymore.
[0] https://github.com/neovim/neovim/issues/10880#issuecomment-526466042
[1] https://github.com/neovim/neovim/issues/14307
[2] https://github.com/neovim/neovim/pull/14630
-rw-r--r-- | autoload/ale/fix.vim | 2 | ||||
-rw-r--r-- | autoload/ale/util.vim | 13 |
2 files changed, 13 insertions, 2 deletions
diff --git a/autoload/ale/fix.vim b/autoload/ale/fix.vim index d9820847..786978d1 100644 --- a/autoload/ale/fix.vim +++ b/autoload/ale/fix.vim @@ -32,7 +32,7 @@ function! ale#fix#ApplyQueuedFixes(buffer) abort endif endif endif - catch /E21/ + catch /E21\|E5555/ " If we cannot modify the buffer now, try again later. let g:ale_fix_buffer_data[a:buffer] = l:data diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim index 2dc71ce5..98af1635 100644 --- a/autoload/ale/util.vim +++ b/autoload/ale/util.vim @@ -522,7 +522,18 @@ function! ale#util#SetBufferContents(buffer, lines) abort " Use a Vim API for setting lines in other buffers, if available. if l:has_bufline_api - call setbufline(a:buffer, 1, l:new_lines) + if has('nvim') + " save and restore signs to avoid flickering + let signs = sign_getplaced(a:buffer, {'group': 'ale'})[0].signs + + call nvim_buf_set_lines(a:buffer, 0, l:first_line_to_remove, 0, l:new_lines) + + " restore signs (invalid line numbers will be skipped) + call sign_placelist(map(signs, {_, v -> extend(v, {'buffer': a:buffer})})) + else + call setbufline(a:buffer, 1, l:new_lines) + endif + call deletebufline(a:buffer, l:first_line_to_remove, '$') " Fall back on setting lines the old way, for the current buffer. else |