How to quickly change variable names in Vim?

Solution 1:

The following is how to rename a variable which is defined in the current scope {}.

Move your cursor to the variable usage. Press gd. Which means - move cursor to the definition. Now Press [{ - this will bring you to the scope begin. Press V - will turn on Visual Line selection. Press % - will jump to the opposite } thus will select the whole scope. Press :s/ - start of the substitute command. <C-R>/ - will insert pattern that match variable name (that name you were on before pressing gd). /newname/gc<CR> - will initiate search and replace with confirmation on every match.

Now you have to record a macros or even better - map a key.

Here are the final mappings:

" For local replace
nnoremap gr gd[{V%::s/<C-R>///gc<left><left><left>

" For global replace
nnoremap gR gD:%s/<C-R>///gc<left><left><left>

Put this to your .vimrc or just execute. After this pressing gr on the local variable will bring you to :s command where you simply should enter new_variable_name and press Enter.

Solution 2:

I know it's an old question, and @mykola-golubyev's way obviously IS the best answer for the particular case in the OP question (which, I assume is going through obfuscated code where you're likely to have multiple blocks with same var names); but with the question name like that many people coming here from google searches probably look for a less situation-specific ways to rename variables in VIM -- and those can be more concise

I'm surprized no one suggested this way:

* :s// NEWNAME /gc

The * is the same as gn - it searches for the next occurence of the word under cursor AND it becomes the last searched pattern, so when you omit the search pattern in the substitute command, VIM assumes this is the pattern to search for.

For small amounts of var copies, an even quicker one:

* cw NEWNAME <esc> then repeat n. for other occurrences

Search for occurrence, cw is the command for change word, n goes to next occurrence of the last searched term and . repeats the last command (which is change word to NEWNAME)

(Credits for me knowing all this go to @doomedbunnies on Reddit)

Another cool trick is this: (credits to @nobe4)

* cgn NEWNAME <esc> then repeat . for other occurrences

cgn is "change whatever is the result of (find next occurrence)". Now that this is the last command, you don't need the n to go to the next occurrence, so fewer strokes again, and, more importantly, no need to alternate n and .. But, obviously, this one has the drawback of not having a way to skip an occurrence.

Here are some benefits:

  • no mapping, no .vimrc(or init.vim), so you can use it in any VIM copy you come across (e.g. a quick task on some VPS or your friend's machine where configuring VIM your way would defeat the purpose of 'quick')
  • using * or gn for word selection is very quick -- just one keystroke (well, let's say 1.5)
  • using * or gn makes sure you don't get any matches inside other words, just as :%s/<C-R>//gc does. Beats typing the :%s/\<OLDNAME\>/NEWNAME/gc by hand: I personally tend to forget to use the \< things to limit matches to whole words only.
  • Not using scope will only result in a few extra strokes of n to skip unwanted matches -- probably even fewer than the extra strokes needed to limit the scope. Under normal curcumstances, your variables are most likely somewhat localized to a certain code block anyway.