Skip to content

CursorMoved event fired even when the cursor doesn't move #2053

@lacygoill

Description

@lacygoill

Consider this minimal vimrc (written in /tmp/vimrc):

let g:loaded_matchparen = 1
set updatetime=3000 vbs=8
au CursorHold * exe ''

cmap <expr>  <cr>                 getcmdtype() =~# '[/?]' ? Set_hls() : '<cr>'
nno  <expr>  <plug>(disable_hls)  Disable_hls()

fu! Set_hls()
    set hls
    return "\<cr>\<plug>(disable_hls)"
endfu

fu! Disable_hls()
    augroup disable_hls
        au CursorMoved * set nohls | au! disable_hls
    augroup END
    return ''
endfu

Its goal is to enable 'hlsearch' after a search and to disable it after the cursor is moved.

Here's a gif showing the result, when I start Vim with absolutely no configuration except for the previous minimal vimrc:

$ vim -Nu /tmp/vimrc /tmp/vimrc

'hls' is automatically enabled after the search. Then, after 3 seconds, it's automatically disabled, because Vim executes the fire-once autocmd which listens to CursorMoved, as reported by the message at the bottom of the screen:

Executing CursorMoved Auto commands for "*"

But as you can see, the cursor didn't move, and I didn't press any key after the search. So, I don't understand what causes CursorMoved to be fired.

Inside the vimrc file, if I remove the autocmd:

au CursorHold * exe ''

Or if I add this autocmd:

au CursorMoved * exe ''

Or if I add this setting:

setlocal conceallevel=1

Then, the issue disappears. Vim behaves as expected: it doesn't disable 'hlsearch' as long as the cursor is moved.

In a real use case, with custom configuration, this issue is difficult to notice. For example, if you have the default matchparen plugin enabled, you probably won't see any problem with the previous vimrc. This is because matchparen installs an autocmd which listens to CursorMoved. And as soon as an autocmd listening to CursorMoved is installed (a definitive one, not a fire-once), the issue disappears. At the very least, you have to disable matchparen by executing :NoMatchParen.

This is why I recorded the gif with no configuration at all, except for the vimrc.

Also, this mysterious CursorMoved event is not directly due to the motion caused by the search. The autocmd which disables the highlighting is installed after the search, not before. And you can increase the value of the option 'updatetime' as much as you want, to delay the unexplained CursorMoved.

I know this CursorMoved event is linked to the autocmd which listens to a CursorHold event, because it happens exactly after &updatetime ms. However, I still don't understand it:

  • the autocmd listening to CursorHold doesn't do anything; and you can replace exe '' with any other command
  • there's no nested flag, so the autocmds should not nest (should they?)
  • adding an autocmd listening to CursorMoved solves the issue ; I don't understand why
  • setlocal conceallevel=1 solves the issue, and yet, AFAIK this option has nothing to do with the motion of the cursor (besides it relies on syntax highlighting, but there was no syntax highlighting in the gif)

Here are some information about my environment:

  • vim --version: VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Sep 3 2017 21:05:31)
    Included patches: 1-1052

  • Operating system: Linux, Ubuntu 16.04

  • Terminal name: xfce4-terminal

  • $TERM: xterm-256color

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions