views:

660

answers:

5

I am trying to read a lot of c/perl code through vim which contain many single letter variable names.

It would be nice to have some command which could help me change the name of a variable to something more meaningful while I'm in the process of reading the code so that I could read the rest of it faster.
Is there some command in vim which could let me quickly do this.

I dont think regexes would work cos
1) the same single letter name might have different purposes in different scoping blocks
2) the same combination of letters could part of another larger var name, or in a string or comment .. would not want to modify those

Any known solutions??

A: 

You could use the i modifier in the global search replace that would ask you for confirmation for each replace. would take longer but might work for a non-humongous code file:

%s/\$var/\$foo/gc

The c stands for confirm.

Adnan
The i stands for ignore-case. You want c, confirm every change.
Kristo
Not sure that you need to escape the $ of foo...
Luc M
oops.. sorry about that.. Fixed the answer
Adnan
Answer still not fixed completely ;)
did you mean the escaped $? That's something that's kind of a personal preference of mine. $ works without escape and also with and since in the regex world and in vi $ has special meaning, I like to escape it just for clarity.
Adnan
+6  A: 

AFAIK, there is no actual refactoring support in VIM. When doing a rename with the intent of a refactor i usually take the following percautions.

  1. Limit the scope of the change my using marks.
  2. When entering the regex, bracket the name with \< and >. This will make it match an entire word which reduces the types of incorrect renames that will occur.
  3. Don't do a multiline replace to reduce chances of a bad replace
  4. Look through the code diff carefully if it's anything other than a small change.

My end change looks something like this

:'a,'bs/\<foo\>/bar

I would love to be wrong about there not being a refactoring tool for VIM but I haven't seen it.

JaredPar
In Perl you can also add the type to the search pattern. i.e. $ for scalars, @ for arrays, % for hashes
Nathan Fellman
@Nathan: unfortunately, it's a bit more difficult in Perl (5.X), as the sigil of arrays and hashes changes with the usage: %hash -> whole hash, $hash{key} -> single value, @hash{qw/a b/} hash slice.
+8  A: 

The following is how to rename 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 jumpt to the oposite } 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 is the final sequence

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

For global replace nnoremap gR gD:%s/<C-R>///gc<left><lef><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.

Mykola Golubyev
A: 

In c, you may be able to make some progress using cscope. It makes an attempt at understanding syntax, so would have a chance of knowing when the letter was a variable.

Kim Reece
A: 

If this is across multiple files, you may consider taking a look at sed. Use find to grab your files and xargs plus sed for a replace. Say you want to replace a with a_better_name in all files matching *.c, you could do

find . -name "*.c" | xargs sed -i -e 's/a/a_better_name/g'

Bear in mind that this will replace ALL occurrences of a, so you may want a more robust regex.

Drew Olson