Vim 是否可以在操作员挂起的映射中确定运动是直线运动、块运动还是法线运动?

Vim 是否可以在操作员挂起的映射中确定运动是直线运动、块运动还是法线运动?,vim,Vim,当使用omap或onoremap声明映射时,我希望能够处理运动为块、线或标准的情况 例如,让我们考虑下面的块: abcd efgh ijkl mnop 光标位于字母f上。假设我定义了一个从K到:normal的操作符映射!vjl(转到字母k) 但是当我运行dVK时,它将不起作用,我得到的结果与dVK完全相同 我尝试使用visualmode()(映射定义为@=visualmode()jl),但这不起作用。在操作员挂起模式下使用v、v或CTRL-v时,此函数的返回值似乎不会立即受到影响 有人有线索吗

当使用
omap
onoremap
声明映射时,我希望能够处理运动为块、线或标准的情况

例如,让我们考虑下面的块:

abcd
efgh
ijkl
mnop
光标位于字母f上。假设我定义了一个从
K
:normal的操作符映射!vjl
(转到字母k)

但是当我运行
dVK
时,它将不起作用,我得到的结果与
dVK
完全相同

我尝试使用
visualmode()
(映射定义为
@=visualmode()jl
),但这不起作用。在操作员挂起模式下使用
v
v
或CTRL-v时,此函数的返回值似乎不会立即受到影响

有人有线索吗?

谢谢

我已经写了一些关于运算符挂起映射的答案。在1中,我概述了一个函数,该函数应根据文档处理各种情况(字符、行、块选择):

 g@{motion}     Call the function set by the 'operatorfunc' option.
        The '[ mark is positioned at the start of the text
        moved over by {motion}, the '] mark on the last
        character of the text.
        The function is called with one String argument:
            "line"  {motion} was |linewise|
            "char"  {motion} was |characterwise|
            "block" {motion} was |blockwise-visual|
        Although "block" would rarely appear, since it can
        only result from Visual mode where "g@" is not useful.
        {not available when compiled without the |+eval|
        feature}
下面是一个使用
:>

nmap <silent> <F4> :set opfunc=CountSpaces<CR>g@
vmap <silent> <F4> :<C-U>call CountSpaces(visualmode(), 1)<CR>

function! CountSpaces(type, ...)
  let sel_save = &selection
  let &selection = "inclusive"
  let reg_save = @@

  if a:0  " Invoked from Visual mode, use '< and '> marks.
    silent exe "normal! `<" . a:type . "`>y"
  elseif a:type == 'line'
    silent exe "normal! '[V']y"
  elseif a:type == 'block'
    silent exe "normal! `[\<C-V>`]y"
  else
    silent exe "normal! `[v`]y"
  endif

  echomsg strlen(substitute(@@, '[^ ]', '', 'g'))

  let &selection = sel_save
  let @@ = reg_save
endfunction
nmap:set opfunc=CountSpacesg@
vmap:调用CountSpaces(visualmode(),1)
函数!CountSpaces(类型,…)
让选择保存=&选择
让&selection=“包含”
让注册表保存=@@
如果从可视模式调用:0”,请使用“<和”>标记。
静默exe“正常!`y”
elseif a:type=='line'
静默exe“正常!”[V']y
elseif a:type=='block'
静默exe“正常!`[\`]y”
其他的
静默exe“正常!`[v`]y”
恩迪夫
echomsg strlen(替换为(@,“[^]”,“'g'))
让&selection=sel\u保存
让@@@reg\u保存
端功能

1

要实现您想要的,您只需定义

onoremap K :<c-u>normal! jl<cr>
onoremap K:normal!jl
请注意,由ex命令形成的此运动始终是按字符显示的(请参见
:h运动


然后,您可以自由使用
dv
、或
dv
、或
d^V
强制运动成为另一种类型,并获得您想要的结果。

启动视觉选择时,您可以通过点击相应的命令将其更改为其他类型的视觉选择(
->
v
->
->
v
->随便什么)。您是否可以使用
dVK
中的
V
启动逐行视觉选择,但使用
vjl
中的
V
将其类型更改为字符类型?@romainl:您是对的!但它没有解释为什么它对V的行为不同。是否要使用
abcd
mnop
获得两行梅恩:完全正确。如果我从映射中删除
v
,它就会起作用。是的,如果你将映射更改为
Vjl
,那么
dvK
就不再起作用了。我授予奖金是因为我觉得这个答案很接近它(没有其他答案)。但是,如果这对定义一个新的、任意的、需要任何运动的命令是有用的,我看不出如何使用它来定义一个新的、任意的、可能是块、行或字符的运动。请您展开一下好吗?可能有用/感兴趣:
nmap <silent> <F4> :set opfunc=CountSpaces<CR>g@
vmap <silent> <F4> :<C-U>call CountSpaces(visualmode(), 1)<CR>

function! CountSpaces(type, ...)
  let sel_save = &selection
  let &selection = "inclusive"
  let reg_save = @@

  if a:0  " Invoked from Visual mode, use '< and '> marks.
    silent exe "normal! `<" . a:type . "`>y"
  elseif a:type == 'line'
    silent exe "normal! '[V']y"
  elseif a:type == 'block'
    silent exe "normal! `[\<C-V>`]y"
  else
    silent exe "normal! `[v`]y"
  endif

  echomsg strlen(substitute(@@, '[^ ]', '', 'g'))

  let &selection = sel_save
  let @@ = reg_save
endfunction
onoremap K :<c-u>normal! jl<cr>