vim 为什么ci”和ci(,ci{....行为不同?

u5rb5r59  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(178)

我们都知道ci"ci'ci(ci[.是的。在日常编辑中非常方便。我发现了一些奇怪的东西,并检查了帮助,没有找到原因。
我有一个文件:

foo "target"
foo 'target'
foo (target)
foo {target}
foo [target]
foo <target>

如果我的光标在每一行的开头,(在'f'上),那么我键入ci”,ci ',ci(.
cix工程只与引号(单或双),不工作的括号.为什么他们的行为不同呢?
dixvix相同)
测试使用--noplugin,Vim 7.3
谢谢

更新

谢谢@romainl的回答。我仍然对“Vim中的pair处理”有疑问
看看这个例子:

foo "targ\"eti\" some\"thing else "

如果我有一个像上面这样的行,我输入ci",无论光标是在开始还是在引号之间,它都能完美地工作,看来Vim确实有“配对”的想法?
这可能就是你说的配对

foo "target x some"thing else "
foo (target x some(thing else )

我上面有两行,如果(光标在x)我输入ci"ci(,第二行什么也没发生,但第一行变成了:

foo "I"thing else " (I is cursor)
ukqbszuj

ukqbszuj1#

  • 2023年编辑 *

今天,我被一次投票提醒了这个答案,必须说的是,这个Q&A中提到的所有文本对象都是一样的,现在:如果你在一对圆括号或一对引号之外,下一对将被操作。
更改发生在8.1和9.0之间的某个时间,但我找不到确切的版本。

  • 2023年底编辑 *

ci(ci[ci{cit以及所有其他<action>i<something>一致。只有ci'ci"像它们一样工作。异常值是引号,这里,不是括号。
Vim不认为引号是成对的,而方括号是成对的。它有一个匹配对的内部逻辑,可以与实际对一起工作,但不能与引号一起工作,因此行为上存在差异。
你不是第一个抱怨这种差异的人:this is one solution,也许你可以找到其他人。

  • 编辑 *

不幸的是,我对Vim的内部结构没有深入的了解,所以在这里我只能做一些假设。
如果你让Vim执行ci",它会尽力找到一对双引号,但双引号不会成对出现:没有办法告诉如果一个"是关闭一个或打开一个相反的括号。正因为如此,Vim必须做出一些选择。在国际海事组织,考虑到家庭其他成员的工作方式,最有意义的选择是假设光标在引号之间,并从第一个到右边的第一个到左边的第一个选择。我只能假设这种方法在某种程度上被证明是错误的,或者由于某种原因不起作用,而另一种方法(当前的方法)占了上风。
另一种解释可能是,i<something>机制以某种方式绑定到特定的子系统(可能与showmatch相同?)无法正确处理报价。
无论如何,就像你一样,我发现这种差异很奇怪,我已经在某种程度上内化了它,并将我对<action>i"的使用与其他人的工作方式相一致。到了实际执行2t"ci"或其他变体而不是ci"的地步!我知道这很没效率
你读过:h a'吗?我完全忘记了我是从哪里得到我对这个问题的“有限理解”的,但它就在那里!上面写着:
“只在一条线上工作。当光标从一个引号开始时,Vim将通过从行的开头搜索来找出哪些引号对构成了一个字符串。”
我从中得到的是:由于某些我们不知道的原因,Vim使用另一种机制来匹配引号,而不是其他对,这就是为什么ci"cib和朋友不同。根本原因还不清楚,但我相当肯定,大局看起来很像我想象的。
对我来说,它看起来很像一个bug或伪装成功能的限制。
如果你仍然好奇,我建议你问任何关于vim-dev的问题。

ffscu2ro

ffscu2ro2#

使用%

" nnoremap cb cib
nnoremap cb %cib
" nnoremap vb vib
nnoremap vb %vib
nnoremap yb %yib
nnoremap db %dab

增强%
https://github.com/andymass/vim-matchup#tocbar-dopjfd
b可以匹配([{
想要使用'来匹配'"吗?

nnoremap c' :call DoubleAsSingleC()<CR>
func! DoubleAsSingleC()
    " When [!] is added, error messages will also be skipped,
    " and commands and mappings will not be aborted
    " when an error is detected.  |v:errmsg| is still set.
    let v:errmsg = ""
    silent! :s#\"\([^"]*\)\"#'\1'#g
    if (v:errmsg == "")
        echo "双变单"
    endif

    exec "normal ci'"
endfunc

类似于:
d'y'v'

相关问题