Maybe it's not the answer you are looking for but I could not resist writing a VIM script for this. I put it in my .vimrc and it works for me:
map ; :call Semicolon()<CR>
function Semicolon()
let s:pos1 = getpos(".")
normal! ;
let s:pos2 = getpos(".")
if s:pos1 == s:pos2
normal! 2;
endif
endfunction
The basic idea is that ;
will not move to the next match, but 2;
will (if there is a match). The script supports ;
after any of tTfF
. The easiest way to implement the ,
command is to write a similar function for that.
EDIT
Changed the script after Luc's excellent suggestion
EDIT2
OK, these things are always more difficult than I originally think. The current mapping has the following problems:
- Suppose you did a search like
tr
above. Now what should d;
or c;
do? As far as I'm concerned they should delete or change up until the first r
not the second. This can be solved by only doing the mapping for normal and visual mode, not operator pending mode.
- The current mapping does not work in visual mode. i.e., if you type
v;;;;
after the first ;
the editor is no longer in visual mode (because of the :call
). This can be solved by calling the function using @=
instead of :call
.
So now I end up with the following in my .vimrc (I also made one function for ,
and ;
):
" Remap ; and , commands so they also work after t and T
" Only do the remapping for normal and visual mode, not operator pending
" Use @= instead of :call to prevent leaving visual mode
nmap ; @=FixCommaAndSemicolon(";")<CR>
nmap , @=FixCommaAndSemicolon(",")<CR>
vmap ; @=FixCommaAndSemicolon(";")<CR>
vmap , @=FixCommaAndSemicolon(",")<CR>
function FixCommaAndSemicolon(command)
let s:pos1 = getpos(".")
execute "normal! " . a:command
let s:pos2 = getpos(".")
if s:pos1 == s:pos2
execute "normal! 2" . a:command
endif
return ""
endfunction