在Vim中更改变量名称

Changing variable names in Vim

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

如果有一些命令可以帮助我在读取代码的过程中将变量名更改为更有意义的名称,这样我就可以更快地读取其余的变量。

维姆有什么命令能让我很快做到吗?

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

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

  • 相同的字母组合可以是另一个较大的var名称的一部分,也可以是一个字符串或注释…不想修改那些

  • 有什么已知的解决方案吗?


    下面是如何重命名当前作用域{}中定义的变量。

    将光标移动到变量用法。按gd。这意味着-将光标移动到定义。现在按[{–这将使您进入范围开始。按V-将打开可视线路选择。按%—跳到对面的},选择整个范围。按:s/—启动替代命令。/将插入与变量名匹配的模式(在按gd之前您使用的名称)。/newname/gc将启动搜索,并在每次匹配时用确认替换。

    现在你必须记录一个宏或者更好的-映射一个键。

    以下是最终映射:

    1
    2
    3
    4
    5
    " 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即可。


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

  • 限制使用标记的更改范围。
  • 当输入regex时,用<和>括起名称。这将使它匹配整个单词,从而减少将发生的不正确重命名的类型。
  • 不要进行多行替换以减少错误替换的机会
  • 仔细检查代码差异,如果它不是一个小的变化。
  • 我的找头看起来像这样

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

    我很想对Vim没有重构工具这一点说错,但我还没有看到。


    把这个放在你的.vimrc里

    1
    2
    3
    4
    5
    6
    " 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("")获取光标下的单词。搜索字符串使用%作为文件范围,\(\W\)模式在要替换的单词边界处查找非单词字符,并将它们保存在变量\1\2中,以便重新插入替换模式。


    我知道这是一个古老的问题,@mykola golubyev's way显然是对op问题中特定情况的最佳答案(我假设这是通过模糊的代码,其中您可能有多个具有相同var名称的块);但是,像这样的问题名称,许多人从谷歌搜索来这里可能会寻找一个在vim中重命名变量的特定于情况的方法——这些方法可以更简洁。

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

    * :s// NEWNAME /gc

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

    对于少量的VaR拷贝,甚至更快:

    * cw NEWNAME then repeat n. for other occurrences

    搜索出现,cw是更改字的命令,n转到下一个出现处进行最后一次搜索,.重复最后一个命令(将字更改为newname)

    (我知道这一切归功于在Reddit上的@domedbunnies)

    另一个很酷的技巧是:(归功于@nobe4)

    * cgn NEWNAME then repeat . for other occurrences

    cgn是"改变(寻找下一个事件)的结果"。现在这是最后一个命令,您不需要n进入下一个事件,因此再次减少笔画,更重要的是,不需要交替n.。但是,很明显,这个方法有一个缺点,即没有跳过某个事件的方法。

    以下是一些好处:

    • 没有映射,没有vimrc(或in it.vim),因此您可以在遇到的任何vim副本中使用它(例如,在某些vps或朋友的机器上执行快速任务,在这种情况下,以您的方式配置vim会破坏"快速"的目的)。
    • 使用*gn进行单词选择非常迅速——只需一次按键(好吧,假设是1.5)。
    • 使用*gn,确保您不会得到任何匹配,换句话说,正如:%s///gc所做的那样。比手工输入:%s/\/NEWNAME/gc要好:我个人倾向于忘记使用\<的东西来限制匹配只限于整个单词。
    • 不使用scope只会导致一些额外的n笔画来跳过不需要的匹配——可能比限制范围所需的额外笔画还要少。在正常情况下,您的变量很可能被某种程度上局限于某个代码块。

    您可以在全局搜索和替换中使用"c"修饰符,这将要求您确认每个替换。这将花费更长的时间,但对于一个非冗长的代码文件来说可能是有效的:

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

    C代表确认。


    如果跨越多个文件,您可以考虑查看SED。使用"查找"来获取文件和xargs plus-sed以进行替换。假设您想在所有匹配*.c的文件中用一个更好的名称替换a,您可以这样做

    查找。-名称"*.c"xargs-sed-i-e's/a/a ou better ou name/g'

    请记住,这将替换所有出现的,因此您可能需要更健壮的regex。


    在C中,您可以使用CScope取得一些进展。它试图理解语法,所以有机会知道字母是什么时候的变量。