1

Based on the accepted answer to this previous question, I put the code below in my .vimrc, which changes the color of my statusline depending on whether my search (started with / or ?) yields results or not.

Unfortunately, I don't understand vimscript, so I cannot fix a simple problem with this code:

When I press / and then immediately cancel the search with <Esc>, the cursor jumps to the first match of whatever previous search term was used.

For example, assume I do /foo<CR>. I move around for a while and think I want to search again, press / but then remember I need to fix something where I am and press <Esc>. This takes me back to foo instead of leaving me where I was.

The problem with the code is also apparent in the fact that the status line immediately turns red or green when I press /, depending on whether the previous search was successful or not.

How can I change the code to 'forget' about the previous search?

" Define an autocmd to call the HighLightSearch function when we enter the search command line
function! HighlightSearch(timer)
    " When it is the first call to the function we save the current status of
    " the StatusLine HL group so that we can restore it when we are done searching
    if (g:firstCall)
        let g:originalStatusLineHLGroup = execute("hi StatusLine")
        let g:firstCall = 0
    endif

    if (exists("g:searching") && g:searching)
        " The variable g:searching is set to 1, we are in the search command line
        " make the highlighting and call the function again after a delay
        let searchString = escape(getcmdline(), ' \')
        let newBG = search(searchString) != 0 ? "green" : "red"
        execute("hi StatusLine ctermfg=" . newBG)
        let g:highlightTimer = timer_start(300, 'HighlightSearch')
    else
        " The variable g:searching is either not set or set to 0, we stopped searching
        " restore the hightlighting and stop calling the function
        let originalBG = matchstr(g:originalStatusLineHLGroup, 'ctermfg=\zs[^ ]\+')
        execute("hi StatusLine ctermfg=" . originalBG)

        if exists("g:highlightTimer")
            call timer_stop(g:highlightTimer)
        endif
    endif
endfunction
" And a second one to stop the function when we are done searching
augroup betterSeachHighlighting
    autocmd!
    autocmd CmdlineEnter * if (index(['?', '/'], getcmdtype()) >= 0) | let g:searching = 1 | let g:firstCall = 1 | call timer_start(1, 'HighlightSearch') | endif
    autocmd CmdlineLeave * let g:searching = 0
augroup END
0
if searchString != ""
    let newBG = search(searchString) != 0 ? "green" : "red"
    execute("hi StatusLine ctermfg=" . newBG)
endif

Explanation: It seems vim's search function is the culprit (note that the function in question continuously runs vim's search to update the color of the statusline). It automatically uses the previous search term if nothing is entered. This can be tested in a clean vim:

  1. vim --clean
  2. ia<CR>b<CR>a<esc> (enter three lines, each with a single letter, end at third line)
  3. /a<CR> (jumps to first line)
  4. /<CR> (jumps to third line, because it uses the search term a)

WARNING: This introduces another problem: The hlsearch-highlight skips one match now. What is highlighted before pressing Enter is not the closed match (which is what the search actually ends up presenting at pressing Enter).

  • 1
    An explanation to accompany this answer would be nice... – D. Ben Knoble Dec 17 '18 at 20:17
  • @DBenKnoble I have no idea how this answer works. Why would I jump to the previous search result if the searchString is empty? – Bananach Dec 18 '18 at 5:36
  • 1
    @DBenKnoble I came up with an explanation – Bananach Dec 18 '18 at 14:25
  • @DBenKnoble Unfortunately, I just noticed that my fix introduces another problem. The hlsearch-highlight always skip one match now. What is highlighted before I press Enter is not the closed match (and is also not what the search actually ends up with when I hit Enter) – Bananach Dec 18 '18 at 15:30
  • 1
    Thats strange... but also at this point I must mention I don’t see the use of this behavior (i use hlsearch, and vim gives an error if there are no results) – D. Ben Knoble Dec 18 '18 at 16:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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