1

Since there are no VisualEnter and VisualLeave events, I am trying to make a function that will activate on every cursor movement in visual mode, i.e. it will automatically highlight all the matches of the current visual selection.

The mapping from Automatically highlight all occurrences of the selected text in visual mode:

xnoremap <silent> <cr> "*y:silent! let searchTerm = '\V'.substitute(escape(@*, '\/'), "\n", '\\n', "g") <bar> let @/ = searchTerm <bar> echo '/'.@/ <bar> call histadd("search", searchTerm) <bar> set hls<cr>

works perfectly for me but I am failing to implement it into function. This is what I tried:

function! HighlightVisual(mode)
    if mode()=~#"^[vV\<C-v>]"
        call feedkeys('"*y')
        let searchTerm = '\V'.substitute(escape(@*, '\/'), "\n", '\\n', "g")
        let @/ = searchTerm
        echo '/'.@/
        call histadd("search", searchTerm)
        set hls
    endif
endfunction

autocmd CursorMoved * call HighlightVisual(mode())

However, it is not working. What am I doing wrong? Moreover, does anybody think there is a better way to search for matches on every cursor movement in visual mode?

1
  • 3
    Part of the problem you're running into might be that the @/ register is restored at the end of a function call. See :help function-search-undo for more details. As a workaround, you can return searchTerm from your function and use an autocmd CursorMoved * let @/ = HighlightVisual(mode()) instead (though you might need to handle the case where you're not in Visual mode to prevent clobbering that register in that case.)
    – filbranden
    Jul 20, 2022 at 1:14

1 Answer 1

1

I have made it work. Firstly, I found from Vim does not call functions correctly when wrapped in another function that "Vim doesn't like updating Screen too often" so redraw was necessary after set hls. And secondly, y was forcing normal mode and gv was moving cursor triggering the autocmd CursorMoved inside the function thus making an infinite loop. I made a workaround by set eventignore=CursorMoved and resetting it back at the end of function. I am saving selected word to register h (as in highlight) but you can choose any by changing "hy and @h. Moreover, I added highlight toggle when not needed. So, if somebody wants to use the feature of automatically highlighting visual matches, here is the code:

function! HighlightVisual(mode)
    if mode()=~#"^[vV\<C-v>]"
        set eventignore=CursorMoved
        normal "hy
        normal gv
        let searchTerm = '\V'.substitute(escape(@h, '\/'), "\n", '\\n', "g")
        let @/ = searchTerm
        call histadd("search", searchTerm)
        set hls
        redraw
        set eventignore=""
    endif
endfunction

autocmd CursorMoved * :call HighlightVisual(mode())
vnoremap <silent> <ESC> :<C-u>set nohlsearch<CR>

; just copy-paste it in your .vimrc/init.vim. Big thanks to trusktr as I used his answer in Automatically highlight all occurrences of the selected text in visual mode to build my function I wanted for sooo long. Happy coding!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.