`vi{` 增加了视觉选择,但我可以用类似的方式减少视觉选择吗?

`vi{` increases the visual selection, but can I reduce the visual selection in a similar way?

所以如果我有这样的文字:

if answer == 42 {                        #1
    if bugs == 'bunny' {                 #2
        if injury == 'but a scratch' {   #3
            // do the thing              #4
        }                                #5
    }                                    #6
}                                        #7

并且我将光标放在 // do the thing 上并执行 va{ 命令,然后我将从第 3 行到第 5 行 select {},并且如果我再次 a{ 那么我将从第 2 行到第 6 行 select {}

但是,哦,不,我现在意识到我实际上只想 select 第 3 行到第 5 行的 {}。令我恐惧的是,通常的 vim 方法 capitalisation => opposite 不起作用,A{ 只是在行尾附加一个 {

我可以在不取消 selection 的情况下从大的 selection 转到较小的 ion,移动光标并重新做一遍吗?在这个例子中,使用一些 hjklwbeo 手动更改 selection 也很简单,但实际上代码块很长且不平凡。

我知道如果在一个父块中有多个同级块,这将是模棱两可的,但我很乐意只 select 第一个,因为我很少发生这种情况。

谢谢!

编辑:执行此操作的插件将是一个不错的选择。如果它看起来像 none 存在,那么我会做一个快速的 MVP 和 post 一个 link 在这里征求意见。

文本对象总是向外,所以,即使您尝试像 i{ 这样覆盖比 a{ 更小的区域,选择也将不可避免地扩大。

正如您所提到的,您可以使用 o 和各种动作更改选区的几何形状,但这很麻烦,而另一种方法是离开可视模式,移动光标,然后再次选择,遗憾的是同样麻烦.

不过,构建一个自定义的“收缩”伪文本对象是可能的,并且社区可能会很高兴地欢迎它。

--- 编辑 ---

下面的快速粗略代码似乎对 a{a(a[a<:

工作得相当好
function! InvertObject()
    call getline('.')[getcurpos()[2] - 1]->search('b')
endfunction
xnoremap A{ <Esc><Cmd>call InvertObject()<CR>va{
xnoremap A{ <Esc><Cmd>call InvertObject()<CR>va(
xnoremap A[ <Esc><Cmd>call InvertObject()<CR>va[
xnoremap A< <Esc><Cmd>call InvertObject()<CR>va<

参见 :help getcurpos():help getline():help search()

添加“内部”变体可能更复杂,因为根据各种参数,光标可能并不总是在同一位置结束。

出于多种原因,上述代码段不能用于 as-is 以下文本对象:

  • awaWasap,因为它们并不是真正由特定标记分隔的。不过,as 可能是最容易添加的。
  • at,因为定界符比单个字符更复杂。
  • a'a"a`,因为它们的扩展方式与它们的“parens”表兄弟不同,所以它们需要完全不同的逻辑。

基于您的 post,我决定制作 vim-visual-history 插件 [v]v[V]V 的先前视觉选择的可遍历记录。这些命令的小写版本也进行计数。所以 在你的情况下,你只需 [v 返回一个选择。

[count][v : Reselect previous visual selection
[count]]v : Reselect next visual selection
[V : Reselect first visual selection
]V : Reselect last visual selection

计数命令演示: