在Vim中更改变量名称

时间:2009-02-28 07:29:54

标签: vim variables refactoring

我试图通过Vim读取很多C / Perl代码,其中包含许多单字母变量名。

当我正在阅读代码时,有一些命令可以帮助我将变量的名称更改为更有意义的内容,这样我就可以更快地阅读其余内容。

Vim中是否有一些命令可以让我快速执行此操作?

我不认为正则表达式会起作用,因为:

  1. 相同的单个字母名称在不同的范围块中可能有不同的用途

  2. 相同的字母组合可能是另一个较大的var名称的一部分,或者是字符串或注释......不想修改那些

  3. 任何已知的解决方案?

7 个答案:

答案 0 :(得分:179)

以下是如何重命名在当前范围{}中定义的变量。

将光标移动到变量用法。按gd。这意味着 - 将光标移动到定义。 现在按[{ - 这将带您进入范围开始。 按V - 将打开视线选择。 按% - 将跳转到相反的},因此将选择整个范围。 按:s/ - 替换命令的开头。 <C-R>/ - 将插入与变量名称匹配的模式(在按gd之前您所使用的名称)。 /newname/gc<CR> - 将在每场比赛中启动搜索并替换确认信息。

现在你必须录制一个宏甚至更好 - 映射一个键。

以下是最终的映射:

" 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>

将此信息发送到.vimrc或执行。 在此按下gr后,本地变量将带您进入:s命令,您只需输入new_variable_name并按 Enter

答案 1 :(得分:9)

AFAIK,VIM中没有实际的重构支持。在以重构为目的进行重命名时,我通常采取以下预防措施:

  1. 使用标记限制更改的范围。
  2. 输入正则表达式时,将名称括在\&lt;&lt;和&gt;。这将使它与整个单词匹配,从而减少将发生的错误重命名的类型。
  3. 不要进行多线替换以减少更换错误的可能性
  4. 仔细查看代码差异,如果它只是一个小小的变化,那么。
  5. 我的结束变化看起来像这样

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

    我很想知道没有VIM的重构工具,但我还没有看到它。

答案 2 :(得分:8)

将它放在你的.vimrc

" Function to rename the variable under the cursor
function! Rnvar()
  let word_to_replace = expand("<cword>")
  let replacement = input("new name: ")
  execute '%s/\(\W\)' . word_to_replace . '\(\W\)/\1' . replacement . '\2/gc'
endfunction

使用:call Rnvar()

进行调用

expand("<cword>")获取光标下的单词。搜索字符串使用%作为文件范围,\(\W\)模式在要替换的单词的边界处查找非单词字符,并将它们保存在变量\1和{{ 1}}以便重新插入替换模式。

答案 3 :(得分:7)

我知道这是一个古老的问题,@ mykola-golubyev的方式显然是OP问题中特定情况的最佳答案(我假设是通过混淆的代码你可能有多个具有相同var名称的块的地方);但问题的名称就像从谷歌搜索来到这里的许多人可能会寻找一种更少特定情况的方法来重命名VIM中的变量 - 这些可以更简洁

我很惊讶没有人建议这样:

  

* :s// NEWNAME /gc

*gn相同 - 它搜索光标下的单词的下一个出现并且它成为最后搜索的模式,因此当您在substitute命令中省略搜索模式时, VIM假设这是要搜索的模式。

对于少量var副本,更快一个:

  

* cw NEWNAME <esc> 然后重复 n. 其他事件

搜索事件,cw更改字的命令,n转到下一次出现以进行上次搜索,.重复上一次命令(这是将字词更改为NEWNAME

(据我所知,所有这些都归功于@doomedbunnies on Reddit

另一个很酷的伎俩是:(credits to @nobe4

  

* cgn NEWNAME <esc> 然后重复 . 其他事件

cgn是&#34;更改(查找下一次出现)&#34;的结果。现在这是最后一个命令,您不需要n转到下一个匹配项,因此再次发生更少的笔划,更重要的是,无需替换n和{{ 1}}。但是,显然,这个缺点是没有办法跳过事件。

以下是一些好处:

  • 没有映射,没有.vimrc(或init.vim),因此您可以在遇到的任何VIM副本中使用它(例如,某些VPS或您朋友的机器上的快速任务,您可以按照自己的方式配置VIM打败&#39; quick&#39;)
  • 的目的
  • 使用.*进行单词选择非常快 - 只需一次击键(好吧,让我们说1.5)
  • 使用gn*确保您不会在其他字词中获得任何匹配,就像gn一样。节拍手动输入:%s/<C-R>//gc:我个人倾向于忘记使用:%s/\<OLDNAME\>/NEWNAME/gc内容来限制匹配整个单词。
  • 不使用范围只会导致\<的一些额外笔划以跳过不需要的匹配 - 可能甚至比限制范围所需的额外笔划更少。在正常情况下,无论如何,您的变量很可能在某种程度上对某个代码块进行了本地化。

答案 4 :(得分:2)

您可以在全局搜索中使用'c'修饰符并替换它,要求您确认每个替换。这需要更长的时间,但它可能适用于非大量的代码文件:

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

c代表确认。

答案 5 :(得分:0)

在c中,您可以使用cscope取得一些进展。它试图理解语法,因此有机会知道字母何时是变量。

答案 6 :(得分:0)

如果这是跨多个文件,您可以考虑查看sed。使用find来获取文件,使用xargs和sed进行替换。假设你想在匹配* .c的所有文件中用a_better_name替换a,你可以做

找到。 -name“* .c”| xargs sed -i -e's / a / a_better_name / g'

请记住,这将替换所有出现的a,因此您可能需要更强大的正则表达式。