15

If I have the following:

function foo(bar) {
    return bar + 1;
}

And I use cw to change the first bar to baz, how do I jump to the next matching bar, so that I can use . to make the same change?

I can't use *, because that searches for the current word under the cursor, and I foolishly didn't search for bar the first time, so n won't work.

Is there a simple way to search for the next occurrence of the word as it was before I changed it?

I don't want to do a search and replace, because either there are other occurrences of bar in my file that I don't want to change, or because there were only two instances of bar, and I forgot about :%s/bar/baz/ before I started and that's too much effort to change the only remaining instance.

3
  • 2
    That doesn't totally follow the workflow you described but vim-oblique improves the * search. Especially it makes * visually select the current word without moving your cursor. Once it is installed you could do *ciw to put the old word in the search register and change the word. Then you can use n and ..
    – statox
    Commented May 12, 2016 at 9:32
  • 1
    Pressing n will move you to the next occurrence of last searched pattern. Why didn't you try that?
    – SibiCoder
    Commented May 12, 2016 at 10:28
  • ...because I didn't search to get to the first occurrence, so n won't work. Commented May 12, 2016 at 11:53

3 Answers 3

15

The text you just changed with cw was cut into the unnamed register so you can reuse it with:

/<C-r>"<CR>

to jump to the next occurrence of the text covered by your last change.

6

To extend off of romainl as a complete workflow...

If you are more into performing an edit of this sort and then realize you need to apply the same edits over a paragraph/function you can use the " and . registers.

In your example you can perform the initial edit of the argument. If you enter visual mode (I'd use Visual Line just to make sure you select everything correctly) and then apply a find and replace.

V]] - Visual Line, to end of paragraph/function.

  • : - Since you're in visual mode this becomes :'<,'>
  • s/ - Find
  • CTRL+" - last yank/delete item (bar in the example)
  • / - and Replace
  • CTRL+. - last insert (baz in the example)

This pattern takes a little while to get use to since you have to use. Most of the time you'd want to just apply the find and replace to the entire function including the argument, but its a nice way to not perform the anti-pattern "Do work, realize you should have done it better, undo and redo correctly."

2

If you do not mind pressing a different combination than cw, then I believe you can get what you want easily, by defining a shortcut. What you can do is to place the following

nmap <leader>a "1yiw:let @/=@1^Mciw

in your .vimrc file. Note that ^M is a capture of return key, and not the characters ^ and M. You get it by pressing Ctrl+V in insert mode followed by Enter. Now, with this defined, pressing <leader>a will do the same as cw, but now the word (prior to the change) will be in your "last search register" (that is, the / register), so pressing n after you have made the change and returned to normal mode will get you to next occurrence. Likewise, pressing N will get you to the previous occurrence.

The shortcut You can of course choose a different shortcut than <leader>a, but I just find that this is a very accessible shortcut. Personally I have set <leader> to , so that I just need to press , followed by a, but this is because I do not use an American keyboard, so that my \ is hidden away somewhat (I believe \ is the default <leader>).

Explanation The idea is really simple. Yank the word under the cursor to the search register / and then do cw. Thus nmap <leader>a "/yciw was what I was aiming for, but unfortunately I do not think that you can yank to the search register, so the workaround is to yank the word under the cursor to the 1 register, then set the / register equal to that, and then do cw. So "1yiw is the part that yanks the inner word under the cursor to the register 1. If you do not know about inner words, you can check out :help iw. Afterwards, :let @/=@1 follows by a capture of Enter puts the contents of the 1 register into the /. At this point n and N works as next and previous occurrence of the word under the cursor, and then a ciw is done so that the word under the curser is deleted and Vim is put into insert mode.

word versus inner word I just realised that I assumed that you wanted the entire word under the curser, and not just from the point of the curser and on. This is why I used iw instead of w everywhere. If this is not the case, then you should use

nmap <leader>a "1yw:let @/=@1^Mcw

instead. If the cursor is on the first letter of the word, there is no difference.

disclaimer This solution will probably not work well if you try to use it on something that contains stuff different from letters, for example by having the cursor stand on a \ or by replacing iw by iW, ib, is or ip or something (though I do not know why you would want this feature with whole sentences)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.