It is possible in vanilla vim to:
- visual select some number of characters, e.g. a variable name in code
- type c to begin replacing selection in insert mode
- type a replacement (variable name)
- exit insert mode
- navigate to another location (typically
n
to go to the next instance of original variable name) - type . to repeat the rename.
Thus the last two steps can be repeated as much as necessary in this common refactoring activity, that of renaming a variable. The brevity of this unit of iteration is critical. I employ further machinery to bring it from 2 steps down to one step and which also accepts counts so I can fire these off expediently. It's all super composable, hence my fixation as you'll see on getting the repeat to work for this.
What I would like to do, which despite experimentation over a decade with a large number of plugins I have not been able to achieve, is the following small tweak to the above workflow: I would like to be able to start it off with a yank as step 0, and exchange step number 2 for a p (or any other suitable verb, I don't care).
Well it does not work. the . fails to replace.
When I employ some solution to prevent p from clobbering the default register like seen here: https://stackoverflow.com/a/290723/340947, what it achieves is the ability to yank the text that I want to use as replacement, go around places and select visually and hit p more than once, and this actually works. Although this is a step in the right direction, . remains broken so I have made very little progress as it does not help save time removing all of those visual operations. It would appear that only the erasure of the selection length got stored in .
, not the whole action of replacement with the paste.
The fact that this works with c
is tantalizing, but I am beginning to worry that this is some kind of a fundamental limitation.
I wonder if repeat.vim could be extended/hacked to do this.
I also wonder if https://github.com/vim-scripts/visualrepeat is exactly what I'm looking for or not. The description does not make it clear to me whether it is relevant. (Update: tested it and it does not help)
Further experimentation:
- I can issue "0p from visual selection instead of p, unsurprisingly this commands vim to do precisely the same thing and does not make . behave any differently
I really want this so I'm willing to go out of the box. If . cannot be coerced then I'll just have to do without it; I could have a different bind to employ in these specific situations. To do this, all I would need is compute the number of characters that the original visual selection was, and delete that number of characters followed by performing a paste. I believe this is all possible (even if I have to actually :normal! gv
to count it)... but it doesn't seem possible to combine this abomination and . into one single bind that knows the right thing to do all of the time.