我正在尝试编写一个涉及向上或向下移动可变行数的插件。我想创建一些可以用作自定义动画的东西,用于普通,视觉和操作员待定模式。
以下是这个想法的一小部分:(这里的“3”是示例。目标是移动可变数量的行,但这与我的问题无关。)
function! MoveDownThreeLines(mode)
if a:mode == 'v'
normal! gv
endif
if a:mode == 'o'
normal! V3j
else
normal! 3j
endif
endfunction
nnoremap w :call MoveDownThreeLines('n')<CR>
vnoremap w :call MoveDownThreeLines('v')<CR>
onoremap w :call MoveDownThreeLines('o')<CR>
此代码段的目标是创建一个向下移动三行的自定义动画。我希望w
的行为与3j
的行为相同。在正常模式下,它按预期向下移动三行,在操作员待定模式下,操作员按预期行动四条线(当前和下面三条线)。 (虽然我不得不使用V
迫使运动成行,这很奇怪,因为j
已经是一个线性运动。有人知道为什么会这样吗?)
问题出在视觉模式。如果我进入可视模式,然后按w
,光标会向下移动三行,如预期的那样。但是,如果我再次按w
,它只会向下移动两行。
同样,如果我进入可视模式并以其他方式向下扩展选择,按w
只会向下移动两行。另一个奇怪的问题是,如果我进入可视模式并向上扩展选择,w
会将我的选择从旧选择的底部更改为两行。 (目标是让w
将选区的顶部向下移动三行,就像我使用3j
一样。)
如何在所有情况下让w
向下移动三行?
答案 0 :(得分:3)
您应该使用<C-u>
作为[count]
的映射前缀所有(不仅仅是视觉模式,如Peter Rincker评论的那样),因为您可能需要提供:.,+2
映射(而不是硬编码的3)。
在正常模式下,当按下:
时,计数(例如3)会转换为:
。同样,视觉模式:'<,'>
会先于:call
。 range
命令为每行执行一次功能,这通常不是您想要的。 (您可以通过将:function
关键字附加到v:count
定义来更改它,但是避免将计数转换为范围可以让您更灵活地使用它;您可以在函数内使用{ {1}}。)