在Vim中更改变量名


95

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

最好有一些命令可以帮助我在读取代码的过程中将变量名更改为更有意义的名称,以便可以更快地读取其余部分。

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

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

  1. 同一单个字母名称在不同作用域中可能具有不同的用途

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

任何已知的解决方案?

Answers:


197

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

将光标移至变量用法。按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


40
+1可学习超过5个我以前应该知道的新Vim技巧。谢谢
肯尼·迈耶

6
注意:在macvim中的Javascript模式下,gd无法在定义的直接作用域中找到变量。我首先要在文件的某些函数中使用变量名:((如果您在某个范围内,并且想要选择该范围,则可以使用“ va {”-“在{周围进行可视选择”-我认为
Srikumar 2011年

3
稍有改进的版本:gist.github.com/048616a2e3f5d1b5a9ad提示用户,显示旧名称,替换后恢复光标位置
Andy Ray

7
+1很好的创业(我想我刚刚创造了一个新词)。注意:实际上,我需要按:两次冒号()。第一次按下它,我看到了:'<,'>。如果我只是s/从那里打字,那是行不通的。我必须在s/。之前键入另一个冒号。
开尔文2012年

6
请注意,您不需要<C-R>使用replace命令,只需省略搜索将使vim使用最后一次搜索的模式,在这种情况下,该模式是从gd命令创建的。因此,简单地做:s//<newname>/gc就足够了。
shangxiao

10

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

  1. 限制使用标记的更改范围。
  2. 输入正则表达式时,请用\ <和>括住名称。这将使其与整个单词匹配,从而减少将发生的错误重命名的类型。
  3. 不要执行多行替换以减少错误替换的机会
  4. 仔细检查一下代码差异是否只是小小的变化。

我的零钱看起来像这样

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

我很想因为没有针对VIM的重构工具而错了,但我还没有看到。


在Perl中,您也可以将类型添加到搜索模式中。例如,标量为$,数组为@,哈希为%
Nathan Fellman

@Nathan:不幸的是,在Perl(5.X)中要困难一些,因为数组和哈希的符号随用法而变化:%hash->整个哈希,$ hash {key}->单值,@hash { qw / ab /}哈希切片。
user55400 2009年

9

我知道这是一个老问题,@ mykola-golubyev的方式显然是OP问题中特定情况的最佳答案(我认为这是经过混淆的代码,其中您可能有多个具有相同var名称的块) ; 但是问题的名称是这样的,许多来自Google搜索的人可能都在寻找一种不太特定于情况的方法来重命名VIM中的变量-而且这些方法可能更简洁

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

* :s// 新名字 /gc

*是一样的gn-它会搜索下光标字的旁边发生和它成为最后的搜索模式,所以当你在替换命令省略了搜索模式,VIM假定这是搜索的模式。

对于少量的var副本,更快的副本:

* cw <esc>然后n.NEWNAME重复其他情况

搜索出现cw更改单词的命令,n转到上一个搜索到的单词的下一个出现位置,然后.重复最后一个命令(将更改单词更改为NEWNAME

(对我来说,这一切都归功于Reddit上的@doomedbunnies

另一个很酷的技巧是:(感谢@ nobe4

* cgn <esc>然后.NEWNAME重复其他情况

cgn是“更改(查找下一个出现的结果)的结果”。现在这是最后一个命令,您无需n再转到下一个出现的位置,因此再次减少了笔触,更重要的是,无需交替使用n.。但是,显然,这一缺点是没有办法跳过发生的事情。

这里有一些好处:

  • 没有映射,没有.vimrc(或init.vim),因此您可以在遇到的任何VIM副本中使用它(例如,在某些VPS或您朋友的机器上执行快速任务,以这种方式配置VIM会破坏“快速”的目的) )
  • 使用*gn进行单词选择非常快-只需一次击键(好吧,假设1.5)
  • 使用*gn确保您不会像在其他单词中一样找到任何匹配项:%s/<C-R>//gc。击败:%s/\<OLDNAME\>/NEWNAME/gc手工打字:我个人倾向于忘记使用这些\<东西将匹配项限制为仅整个单词。
  • 不使用范围只会导致n跳过多余匹配的额外笔画-可能甚至比限制范围所需的额外笔画还要少。在正常情况下,无论如何,您的变量很可能会局部定位到某个代码块。

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\2以便重新插入替换模式中。


3

您可以在全局搜索中使用'c'修饰符,然后进行替换,这将要求您确认每次替换。这将花费更长的时间,但对于非繁琐的代码文件可能会起作用:

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

c代表确认。


我代表忽略情况。您要c,确认所有更改。
Michael Kristofik,

糟糕..抱歉。.固定答案
Adnan

答案仍然没有完全解决;)
user55400(2009年

你是说逃脱的美元吗?那是我个人的偏爱。$不能逃脱,也可以在正则表达式世界中使用,因为在正则表达式中,vi在$中具有特殊含义,我想为了清楚起见而对其进行逃避。
阿德南(Adnan)2009年

0

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


0

如果这涉及多个文件,则可以考虑查看sed。使用find来获取文件和xargs plus sed进行替换。假设您要在所有与* .c匹配的文件中将a替换为a_better_name,则可以

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.