在 Vim (Ruby) 中用 do/end 替换匹配的 { 大括号 }

8

有没有插件或宏可以在Vim中将匹配的 { 替换为 doend?最好是将单行语句转换成这样:

foo.each { |f| f.whatever }

into:

foo.each do |f|
  f.whatever
end

我可以为这个特定情况自己编写一个宏,但我想要的是能够处理现有的多行、可能很复杂的块转换的东西,例如:

foo.each { |f|
  f.bars.each { |b| b.whatever }
  hash = { a: 123, b: 456 }
}

into:

foo.each do |f|
  f.bars.each { |b| b.whatever }
  hash = { a: 123, b: 456 }
end

我已经查看了vim-surroundrails.vim,但是都没有找到合适的方法。


我不太了解 Ruby。但是为什么你的多行示例(输出)只替换了外部的 {},而内部的 f.bars.each{... 没有被替换呢? - Kent
支持两者都是不错的,但通常我只想一次展开一个级别。我的情况是,我更喜欢单语句的内联块,但经常发现自己想要添加另一个或两个语句,并且我希望扩展该块以实现此目的。是的,我知道我应该将其全部重构为一个方法。 - Jim Stewart
2个回答

10

有一个名为 Vim Blockle 的 Vim 插件可以执行此功能。

安装插件后,将光标放在 {}doend 上,然后按下 <Leader>b 以切换块样式。


谢谢!有点古怪,但这基本上就是我要找的东西。 - Jim Stewart
3
我来翻译一下:所以我想安装Blockle,但偶然发现Blockle的作者建议安装splitjoin代替:https://github.com/jgdavey/vim-blockle/issues/5 - Eric Hu

0

我假设在你的多行示例中,输出将是:

foo.each do |f|
  f.bars.each do |b| b.whatever end
  hash = { a: 123, b: 456 }
end

也就是说,f.bars.each{...} 也应该被替换。

如果这是目标,请尝试以下方法:

gg/each\s*{<enter>qqf{%send<esc><c-o>sdo<esc>nq200@q

简短解释:

gg               " move cursor to top
/each\s*{<enter> " search pattern we want
qq               " start recording macro to register q
f{               " move to {
%send<esc>       " move to closing {, and change it to "end", back to normal
<c-o>sdo         " back to beginning { and change it into "do"
<esc>nq          " back to normal, and go to next match, stop recording

然后你可以执行例如200@q并检查结果。


这不完全是我想要的。请看一下我在问题上的评论。我只想在当前行的范围内执行它。我会检查一下并看看是否可以使用它。 - Jim Stewart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接