繁体   English   中英

如何在 Vim 中快速更改变量名?

[英]How to quickly change variable names in Vim?

我正在使用 Vim 来阅读大量包含许多单字母变量名的 C 和 Perl 代码。

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

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

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

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

  2. 相同的字母组合可以是另一个更长的变量名称、字符串文字或注释的一部分。

是否有任何已知的解决方案?

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

将光标移动到变量用法。 gd 这意味着 - 将光标移动到定义。 现在按[{ - 这将带您进入范围开始。 V - 将打开可视线选择。 % - 将跳转到相反的}从而选择整个范围。 :s/ - 替代命令的开始。 <CR>/ - 将插入匹配变量名称(按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 即可

我知道这是一个老问题,@mykola-golubyev 的方式显然是 OP 问题中特定情况的最佳答案(我认为这是经过混淆的代码,其中您可能有多个具有相同 var 名称的块) ; 但是很多人从谷歌搜索到这里的问题名称可能会寻找一种不太针对特定情况的方法来重命名 VIM 中的变量——这些方法可以更简洁

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

* :s//名字/gc

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

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

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

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

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

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

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

cgn是“改变(查找下一个事件)的结果”。 现在这是最后一个命令,您不需要n转到下一次出现,因此再次减少笔画,更重要的是,无需交替n. . 但是,很明显,这个方法有一个缺点,就是无法跳过某个事件。

以下是一些好处:

  • 没有映射,没有 .vimrc(或 init.vim),所以你可以在你遇到的任何 VIM 副本中使用它(例如在某些 VPS 或你朋友的机器上的快速任务,其中以你的方式配置 VIM 会破坏“快速”的目的)
  • 使用*gn进行单词选择非常快——只需一次击键(好吧,假设为 1.5)
  • 使用*gn确保您不会在其他单词中获得任何匹配项,就像:%s/<CR>//gc一样。 :%s/\\<OLDNAME\\>/NEWNAME/gc输入:%s/\\<OLDNAME\\>/NEWNAME/gc :我个人倾向于忘记使用\\<来限制匹配到整个单词。
  • 不使用范围只会导致n的一些额外笔画跳过不需要的匹配——甚至可能比限制范围所需的额外笔画更少。 在正常情况下,无论如何,您的变量很可能在某种程度上本地化到某个代码块。

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

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

我的最终变化看起来像这样

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

我很想错,因为没有用于 VIM 的重构工具,但我还没有看到它。

把它放在你的 .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以便重新插入替换模式。

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

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

c 代表确认。

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM