Vim Tips Wiki
(previous version caused glitches because the cursor indiscriminately moved right then left)
(fix a typo)
Line 14: Line 14:
 
__TOC__
 
__TOC__
 
==Faking a timer==
 
==Faking a timer==
Since there is no timer function in Vim, a trick is needed: use two autocommands that invoke each another. In the following, the <tt>CursorIdle</tt> and <tt>CursorMoved</tt> events are used; each cancels the action performed by the other. The period can be set via the <tt>updatetime</tt> option (abbreviated to <tt>ut</tt>).
+
Since there is no timer function in Vim, a trick is needed: use two autocommands that invoke each another. In the following, the <tt>CursorHold</tt> and <tt>CursorMoved</tt> events are used; each cancels the action performed by the other. The period can be set via the <tt>updatetime</tt> option (abbreviated to <tt>ut</tt>).
 
<pre>
 
<pre>
 
let moveflag = 0
 
let moveflag = 0

Revision as of 01:49, 30 October 2009

Tip 1612 Printable Monobook Previous Next

created January 4, 2009 · complexity basic · version 7.0


It may be helpful to run a commmand periodically in the background. This can be used, for example, to write an auto-updating clock in Vim, or to check for user input via an input loop, such as in a game. In one application, Vim was used as a front end for a media player, where the song information had to be updated and other actions taken when a song finished.

Faking a timer

Since there is no timer function in Vim, a trick is needed: use two autocommands that invoke each another. In the following, the CursorHold and CursorMoved events are used; each cancels the action performed by the other. The period can be set via the updatetime option (abbreviated to ut).

let moveflag = 0
au CursorHold * let moveflag=1 | let previnmiddle=0 | let prevjustabovemid=0 | let middleline=(line("w0")+line("w$"))/2 | if line(".")==middleline | let previnmiddle=1 | endif | if line(".")+1==middleline | let prevjustabovemid=1 | endif | if line(".")<middleline | exe "normal j" | else | exe "normal k" | endif
au CursorMoved * if moveflag==1 | let middleline=(line("w0")+line("w$"))/2 | if previnmiddle==1 | exe "normal j" | else | if prevjustabovemid==1 | exe "normal k" | else | if line(".")<middleline | exe "normal k" | else | exe "normal j" | endif | endif | endif | let moveflag=0 | endif
set noswapfile
set ut=3000

Here, the autocommand CursorMoved event distinguishes user movements from autocommand movements via the moveflag variable. This loop increments and displays k every 3 seconds while the cursor is idle.

The noswapfile option is set so that Vim isn't writing to a swap file every 3 seconds, if the action happens to update the file.

All the code is there simply to make sure the action caused to trigger off the auto commands returns things to exactly the same place where they were before. It's nasty but it works. It's done by moving the cursor up then down, or vice versa, or vice versa again if the cursor is near the middle of the screen.

Comments