如何在vim中删除Ruby代码块(do/end)

7
如何使用vim删除ruby中被do/end包围的区块?
例如:
(10..20).map do |i| <CURSOR HERE>
  (1..10).map do |j|
    p j
  end
end

我希望能做类似于“dsb”(删除周围区块)的操作并获取结果。
  (1..10).map do |j|
    p j
  end

1
有一个插件叫做 vim-textobj-rubyblock,但它定义了 irar(内部 Ruby 块/周围 Ruby 块),虽然接近但不完全符合您的要求。不过这更符合惯用法,我不知道有什么方法可以对“周围对象”执行操作。 - DJMcMayhem
vim-surround 支持 HTML 的标签环绕,dst 可以删除环绕的标签,ds' 可以删除环绕的单引号,一定有办法将 do ... end 定义为一个块。 - geckos
1
看一下vim-sandwich吧;它是vim-surround的更可配置的变体,应该允许您定义相应的映射。 - Ingo Karkat
1个回答

2

也许你可以制作一个nnormap。

每个end/do对位于相同的缩进位置,因此首先应该找到配对的缩进 - 在这种情况下,是在相同缩进的下一行(因为您的光标在do行中)。

所以你可以制作一个vimscript函数来查找下一个缩进行并删除它。

以下是该函数的示例。您可以根据需要进行自定义,例如设置休息行的缩进。

function! DeleteWithSameIndent(inc)
    " Get the cursor current position
    let currentPos = getpos('.')
    let currentLine = currentPos[1]
    let firstLine = currentPos[1]
    let matchIndent = 0
    d

    " Look for a line with the same indent level whithout going out of the buffer
    while !matchIndent && currentLine != line('$') + 1 && currentLine != -1
        let currentLine += a:inc
        let matchIndent = indent(currentLine) == indent('.')
    endwhile

    " If a line is found go to this line
    if (matchIndent)
        let currentPos[1] = currentLine
        call setpos('.', currentPos)
        d
    endif
endfunction

nnoremap di :call DeleteWithSameIndent(1)<CR>

这很酷!!!它删除了外部的 do 行并将光标移动到外部的 end 行。我使用与问题相同的示例进行了测试。我认为最后一个 if 没有执行,这没关系,因为我可以使用 dw 删除 end - geckos
我原本计划做类似的事情(查找 do/end -> 查找 do 前的表达式,删除表达式,插入 do 和 end,恢复光标位置),但是我的 vimscript 技能不够好。谢谢,这给了我一些想法! - geckos
@geckos 太好了!听到这个消息很高兴。我不擅长vimscript,所以你可以自定义你自己的。祝你编程愉快! - seuling

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