From 92cc304bbbc05759a8a796754a80804ce0a42959 Mon Sep 17 00:00:00 2001 From: Julian Prein Date: Fri, 1 Nov 2024 00:46:00 +0100 Subject: [PATCH] vim:au: Improve performance of cword/selection highlight - Combine one `exists` call with an implicit `get` into a `get` with an empty default - Do not stop any timer in the `Highlight*` functions as this done already by `ClearHighlights` - Get rid of the check for existence of `w:*_timer_id` since I believe that there is no way of it being unset in the current state. The `_Highlight*` functions are only called via the timer so there should always be the variable. I could also not reproduce the description in the comment - this might have been true in a previous revision. - Make sure that the visual selection itself is not matched. This actually increased the performance a lot while also looking like normally (there were some subtle differences between the highlight by visual mode and `CursorColumn`) --- .config/vim/vimrc.d/80-autocommands.vim | 27 ++++++++----------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/.config/vim/vimrc.d/80-autocommands.vim b/.config/vim/vimrc.d/80-autocommands.vim index c3194ae..e9d89cd 100644 --- a/.config/vim/vimrc.d/80-autocommands.vim +++ b/.config/vim/vimrc.d/80-autocommands.vim @@ -69,30 +69,22 @@ function! HighlightCurrentWord() return endif - if exists('w:old_cword') && w:old_cword == expand('') + if get(w:, 'old_cword', '') == expand('') " Nothing to do if we're still on the same word return endif + " Clear previous highlight and kill the possibly already running timer call ClearHighlights(s:CLEAR_HIGHS_CWORD) " Delay the highlight by 100ms so that not every word is highlighted " while moving the cursor fast. (This kind of simulates a CursorHold " event with a custom time) - if exists('w:cword_timer_id') - " Abort the already running timer and its callback - call timer_stop(w:cword_timer_id) - endif let w:cword_timer_id = timer_start(100, "_HighlightCurrentWord") endfunction function! _HighlightCurrentWord(timer_id) - " TODO: there is probably some kind of race condition here - " NOTE: w:cword_timer_id can be unset when switching from a window that is - " currently in visual mode as then the ModeChanged event is triggered. - if exists('w:cword_timer_id') - unlet w:cword_timer_id - endif + unlet w:cword_timer_id let l:cword = expand('') if (l:cword != '') @@ -110,22 +102,17 @@ function! HighlightVisualSel() return endif + " Clear previous highlight and kill the possibly already running timer call ClearHighlights(s:CLEAR_HIGHS_VISUAL) " Delay the highlight by 100ms so that not every selection is highlighted " while moving the cursor fast. (This kind of simulates a CursorHold " event with a custom time) - if exists('w:selection_timer_id') - " Abort the already running timer and its callback - call timer_stop(w:selection_timer_id) - endif let w:selection_timer_id = timer_start(100, "_HighlightVisualSel") endfunction function! _HighlightVisualSel(timer) - if exists('w:selection_timer_id') - unlet w:selection_timer_id - endif + unlet w:selection_timer_id let l:old_reg = getreg('"') let l:old_regtype = getregtype('"') @@ -144,11 +131,13 @@ function! _HighlightVisualSel(timer) let w:visual_match_ids = [] " Add match to all windows containing the current buffer + " NOTE: \%V\@! prevents the pattern from matching the current selection. As + " it is highlighted already this would be superfluous and inefficient. for l:win in win_findbuf(bufnr()) let w:visual_match_ids += [[ \ matchadd( \ 'CursorColumn', - \ '\V' . substitute(escape(@", '\'), '\n', '\\n', 'g'), + \ '\V\%V\@!' . substitute(escape(@", '\'), '\n', '\\n', 'g'), \ -1, \ -1, \ {'window': l:win}),