vim 特殊标记行为?

vim special mark behavior?

我刚开始研究 vim 插件并尝试为自己编写一个。我想使用 Vim 的标记功能。我在一本书中找到以下内容:

nnoremap <leader>g :set operatorfunc=GrepOperator<cr>g@
vnoremap <leader>g :<c-u>call GrepOperator(visualmode())<cr>

function! GrepOperator(type)
   if a:type ==# 'char'
        normal! `[v`]y
    else
        return
    endif

    echom shellescape(@@)
endfunction

vim 帮助和此处函数中提到的 `[ 和 `] 的行为是不一样的。 Vim 帮助说:

`[            To the first character of previously changed or yanked text.
`]            To the last character of the previously changed or yanked text.

当我在 vim 中以正常模式键入以下命令时:

normal! `[v`]y

使用一个文件,它根据我之前所做的操作提取行(我更改了文本或提取了多少行以上或以下)。

但是如果我调用与上述函数绑定的相同命令与运动运算符 该行为与回显当前光标下的字符不同。

The motion i used is: vi(<leader>g

为什么这两种行为都不符合 vim 帮助文档。

谢谢。

你是对的,Vim "overloads" '['] 更改标记以表示运算符函数中移动的文本。这避免了引入另一个特殊标记。一般的:help '[这里不适用

严格来说,运算符函数仅适用于普通模式 {opfunc}{motion},但通常您也希望它们也适用于可视模式 ({Visual}{opfunc})。您也定义了 :nmap:vmap

type 函数参数是运算符函数能够区分两种模式的方式。正如您使用的 vi(<leader>g,这是视觉模式变体(<leader>gi( 应该已经可以工作了)。不幸的是,您的实现遗漏了相关代码;到目前为止,它只处理正常模式(并且只处理字符运动)。在可视模式下,type 参数包含一个 v / V / <C-v> 值;你也需要处理它:

function! GrepOperator(type)
    if a:type ==# 'char'
        normal! `[v`]y
    elseif a:type ==# 'v'
        normal! `<v`>y
    else
        return
    endif

    echom shellescape(@@)
endfunction

由于视觉选择是由 '<,'> 标记定义的,因此您需要使用这些标记,而不是前面提到的 '[,']

:help :map-operator 有另一个示例(并使用了稍微不同的方法),还展示了如何正确处理 'selection' 的不同值。