如何使用v:count in Vim 来换行n行?

How to use v:count in Vim to switch line with line n lines away?

我想在 vim 中创建一个映射,将当前行切换到 n 行之外的行。

到目前为止,我有这样的事情:

:nnoremap gl:<C-U> dd{v:count1}jO<Esc>pjdd{v:count1}o<Esc>p

但是不行。我如何在这种情况下使用 v:count 变量?

映射的计算与键入的完全相同。 v:count 之类的东西是特殊的 Vim 脚本变量,因此它的值需要以某种方式插入到右侧的键中。使用映射,有两种可能性:

执行

使用:execute,可以从普通模式(由:nnoremap启动)跳出到Ex模式和assemble命令;您需要 :normal! 到 运行 之前放在右侧的正常模式命令。由于 Vim 自动将给定映射的任何 [count] 转换为 Ex 范围,因此需要 <C-u> 来清除它。

nnoremap <silent> gl :<C-u>execute 'normal! yyma' . v:count1 . "jVp'aVp"<CR>

地图表达式

<expr> 修饰符为映射添加了一个间接层:计算右侧,仅将结果作为 运行 的命令。 [count] 这里也有类似的并发症;前面的 <Esc> 命令取消它(所以你只抽出一行)。

nnoremap <expr> gl '<Esc>yyma' . v:count1 . "jVp'aVp"

您的实施

我假设您选择 gl 作为左侧,而 :<C-U> 是一种逃避尝试,就像我在第一种方法中所做的那样。分隔左右两侧的 space 不见了,:normal 也不见了。

我对实现进行了以下更改:

  • 在它旁边删除和粘贴会使计数复杂化;相反,我在视觉选择上使用了粘贴 (Vp);这会自动将删除的文本放入未命名的寄存器中(因此它可以重新用于交换的第二部分)。
  • 为了简单起见,我设置了一个标记 (ma),而不是第二次使用计数返回。您也可以为此使用 跳转列表 (<C-o>)。

其他实现

对于简单的交换,您的实现可能就足够了,但还远非完美。可能需要交换多条(例如视觉选择的)线路,使用 . 在其他地方重新交换,并检查目标线路是否确实存在。

unimpaired.vim plugin has a swap mapping [e. My LineJuggler plugin 也有一个强大而通用的实现(以及许多其他相关的实现)。