替换到文本对象的末尾

Posted

技术标签:

【中文标题】替换到文本对象的末尾【英文标题】:Replace to end of text-object 【发布时间】:2012-07-25 07:31:32 【问题描述】:

在 Vim 中,我不断发现自己希望通过击键来重写某些参数列表的其余部分。例如,在以下 Python 函数中:

def myfun(a, b=12, c=(1,2,3), d=15):
    pass

我希望将c=(1,2,3), d=15 替换为e=12。击键ci( 允许我替换整个参数列表中的所有内容,但我发现我经常想保留一些 Vim 文本对象的前缀。一般来说,我假设我正在搜索的这个击键在替换函数调用的最终参数和定义的上下文中会很有用。

这个问题的理想答案也适用于带引号的字符串、[] 块和其他文本对象。请注意,我了解“How to select between brackets (or quotes or ...) in Vim?”中回答的所有有关文本对象的信息。

@pb2q 和 @romainl 都提供了很好的搜索快捷方式,但它们要求我在视觉上找到封闭块的结尾,以设计一个明确的搜索,就块中的任何其他垃圾而言(例如,考虑嵌套函数来电)。特别是,当我在要操作的括号集中嵌套括号时,我经常发现自己想要这个。我真正想要的答案类似于ci)ca),它们在概念上完全基于最近的封闭括号),并完全优雅地处理其他嵌套的) 块。

【问题讨论】:

【参考方案1】:

ct: 在这种情况下会将所有内容更改为:,但不包括在内。在 t 前面加上一个数字参数将允许您轻松更改嵌套的大括号/括号/引号,例如c2t).

如果光标已经在要更改的行上,fc 将使用上述命令将您放在要开始更改的字符上,或使用搜索,例如: /c= 用于更一般的情况,即如果您在该行前面有 c 个字符,或者光标当前位于前一行。

【讨论】:

是的,既真实又有用,但我不得不说我对细节非常挑剔。例如,我可能有一个函数调用 "... f(a, b, g(c, d)) ..." 并希望用 "e" 替换 "b, g(c, d)" 以获得结果“... f(a, e) ...”。 @jbmohler,fb 然后cf)e 应该没问题。使用fc 后跟cf5e=12c2t)e=12 作为您问题中的示例。【参考方案2】:

有一堆以 ] 开头的命令会到达某种结构的末尾,并且尊重嵌套。 ]) 到带括号的块的末尾,] 到大括号的末尾块,]/ 转到 C 注释的末尾(/*...*/ 样式)。使用 [ 代替 ] 转到开头而不是结尾。

所以要替换你的 c=(1,2,3), d=15 类型 c])

这些命令的完整列表在:help various-motions 下列出。不幸的是,没有用括号分隔的块,因为 [[]] 已经有不同的在经典 vi 中的含义,vim 定义了 ][[] 以很好地适应这些。

【讨论】:

我相信这是我在寻找原生 vim 的答案。它不像我希望的那样完整,但我怀疑它与当前的 vim 一样好。我想要这个替换为关闭)(这个答案很优雅)并替换为关闭"(这个答案似乎没有实现)。 由于引号不可嵌套,您可以使用/ 搜索下一个。如果这是您第一次听说它,那可能会有点令人惊讶,但/ 是一个运动命令,因此作为c 命令的参数有效。只需输入 c/" 并按 Enter。 实际上它们可以与\" 嵌套,不是吗?我想我对此没有很好的答案。向 vim 提交一个愿望清单错误以获取 ["]" 命令,它可能会出现在下一个版本中 我最喜欢这个答案,因为键序列更短。但请注意,我建议的技术可以轻松更新以使用 ] @darcyparker 是的,你的也不错。您还教了我有关视觉模式 o 命令的知识,我以前不知道,但我可能很快就会使用。【参考方案3】:

用这个创建地图

mavi)o`a
标记当前位置a 在 () 内直观地选择以选择您所在的 () 内的完整字符集 转到突出显示文本的另一端 :h v_o 了解更多信息 移动到之前标记的位置

现在您可以执行诸如 c 或 d 之类的操作...

编辑:我仍然最喜欢@Alan-Curry 的解决方案,因为键序列很短。然而,这种技术的好处是也可以与 ] 一起使用。

我还发现了我的解决方案的简化:

vi)o``

`` 跳转到最后一个位置。所以你不需要创建标记。

【讨论】:

【参考方案4】:

我拼凑了一个小解决方案。它可能有一些边缘情况,并且可能有一些错误,但我今天没有时间测试了。有时间我再去看看。

function! UntilTextObject(op)
    " Save marks
    let save_a = getpos("'a")
    let save_b = getpos("'b")

    " Read in the object type and set '< and '> to the ends of the
    " range of the text-object and 'a to the current position
    let object_type = nr2char(getchar())
    execute "normal! mavi" . object_type . "\<esc>"

    " Adjust end position (off by one)
    let pos = getpos("'>")
    let pos[2] += 1
    call setpos("'b", pos)

    " Operate on the range `a to `b
    execute "normal! `a" . a:op . "`b"

    " Restore marks
    call setpos("'a", save_a)
    call setpos("'b", save_b)
endfunction

onoremap u :call UntilTextObject(v:operator)<cr>

这允许您执行du) 删除-直到-the-end-of-the-)-text-object。也适用于其他文本对象。

我添加了一些更改,通过不踩你的标记使这更加礼貌。如果你给它一个不选择任何东西的文本对象,它仍然有点古怪。我会在以后重新审视这个,看看我是否能解决这个问题。出于演示目的,它故意过度注释。

【讨论】:

【参考方案5】:

如果您不介意使用插件,我相信 vim-ninja-feet 完全符合您的要求。

c]i) 将更改参数列表的其余部分, d[i"会 向后删除到引用的开头,并且 z]i] 会将您置于 [] 块末尾的插入模式。

【讨论】:

以上是关于替换到文本对象的末尾的主要内容,如果未能解决你的问题,请参考以下文章

在javascript替换中阻止光标跳转到输入字段的末尾

VBscript 替换文本但添加空行

使用扩展运算符替换集合的对象

vim 简单操作

vim 简单操作

Vim文本编辑器