Vim will move the cursor to the beginning of an object after invoking operator upon it. From an interactive editing perspective this may be considered annoying however it is the consistent choice as operators can be destructive. As such restoring the cursor to its prior position after invoking an operator on an object may not make sense.
There are many ways possible to alter this behaviour to your preference with mappings and/or scripting. But with custom operator mappings this can be particularly ugly.
A common method is to drop a mark or save a view in the mapping. However the
mapping must end with g@
so Vim will wait for the operator, meaning the
mapping itself can't move the cursor movement back to its original location.
As such the movement would have to be placed inside the function that
operatorfunc
has been set to. I consider this quite ugly as functions should
not have to have such a priori knowledge about the mappings that are calling
them. Note that dropping a mark or saving a view inside the operatorfunc
function is not an option as the cursor has already been moved by the time this
is invoked.
A neat solution to this is to save a view whenever operatorfunc
is set
with an autocmd
. Then whenever the cursor is moved check if
operatorfunc
is set, if so restore the view, dispose of the temporary
variable containing said view, and unset operatorfunc
with autocmd
's
disabled as to avoid a loop.
To avoid having an autocmd
always fire when the cursor is moved we can
instantiate it only when operatorfunc
is set. Now that this
instantiation occurs whenever operatorfunc
is set we can make two
further refinements. Firstly we can stop checking if operatorfunc
is
set and secondly the autocmd
that restores the view can be one shot.
function! OpfuncSteady() abort
let w:opfuncview = winsaveview()
autocmd OpfuncSteady CursorMoved,TextYankPost *
\ call winrestview(w:opfuncview)
\ | unlet w:opfuncview
\ | noautocmd set operatorfunc=
\ | autocmd! OpfuncSteady CursorMoved,TextYankPost *
endfunction
augroup OpfuncSteady
autocmd!
autocmd OptionSet operatorfunc call OpfuncSteady()
augroup END
One could even create re-implementations of Vim's built in operators to leverage this technique, though I'll leave that as an exercise for the reader.
That's an interesting, somewhat holistic, approach. Just like having the quickfix window open automatically in a plugin-agnostic way. I like it.
Sometimes, when looking at my vim-qf and things like this, I feel there's room for a "global smoothing" plugin that would remove the need of a number of hacks but there would be an uphill battle against all the snippets and plugins using those hacks.