运行自定义vim映射键绑定一次有效,但运行x次多次不起作用

时间:2013-04-24 00:38:56

标签: vim

我正在尝试使用逗号映射Ctrl-j键以连接两行。我的.vimrc文件中有以下行

:map <C-j> A<space>,<ESC>J

当我按Ctrl-j一次

时,这可以正常工作
Before           After
test             test , test
test             test
test

但是当我尝试按下&#34; 2Ctrl-j&#34;一次连接多行时我得到以下

Before           After
test             test , , test
test             test
test

我做错了什么?如何将多行连接到一个逗号分隔的行?我尝试用<Esc>替换<C-[>,但这不起作用。

另外,有没有办法参数化加入符号?例如,如果我想映射Ctrl-k后跟任何字符使用指定的字符连接两行,那么地图会是什么?

2 个答案:

答案 0 :(得分:2)

如果您不介意使用其中一个寄存器,可以将命令存储在寄存器中。

例如,您可以将以下内容添加到vimrc

let @j = "A,\eJ"
nnoremap <C-j> @j

@j使用j寄存器来存储命令。当您键入一个数字后跟@j<C-j>时,您将运行命令n次,这将加入由逗号分隔的下n行。

<小时/>

将多行连接在一起的另一种方法是使用下面的函数。

function! CustomJoinLines(delim) range
    for i in range(a:firstline, a:lastline) 
        exec "normal A" . a:delim . "\eJ"
    endfor
endfunction

此函数将使用您传入的分隔符将多行连接在一起。它还将保留J通常添加的空间。

要映射此命令,请将该函数添加到vimrc和以下nnoremaps

nnoremap <C-j> :call CustomJoinLines(" ,")<CR>
nnoremap <C-k> :call CustomJoinLines("!")<CR>

答案 1 :(得分:2)

您的方法存在缺陷,因为2<C-j>

  • 告诉Vim将逗号添加2次到当前行(2A<space>,
  • 并且J不会计算,因此只能使用一次(即使它确实如此,J2J相同......)。

此外,A<space>,<ESC>J等命令序列更适合宏。如果您希望映射与计数一起使用,则应在映射的右侧仅使用一个命令(最好使用Ex命令),如果可能,应使用较少的“行人”方法。

这是一种更好的方法:

:nnoremap <C-j> :s/\n/ , <CR>
:xnoremap <C-j> :s/\n/ , <CR>

通过这些映射,您可以在正常模式下<C-j>3<C-j>以及<C-j>无问题。以下是Vim在上面三个场景中所做的事情:

  • 正常模式<C-j>将EOL替换为当前行的,

    :s/\n/ , <CR>
    
  • 普通模式3<C-j>将此行上的,替换为EOL,以及下面的两个

    :.,.+2s/\n/ , <CR>
    
  • 视觉模式<C-j>在视觉选择的每一行上用,替换EOL

    :'<,'>s/\n/ , <CR>
    

正如您所看到的,使用Ex命令会自动插入正确的范围,使您的映射更具可预测性。

修改

基本上,当您在Ex命令之前使用计数或在可视模式下发出Ex命令时,Vim会自动插入与该计数相对应的范围或命令本身之前的视觉选择为你节省一些打字。

3<C-j>

确实

3:s/\n/ , 

转化为:

:.             " from this line
:.,            " to
:.,.+2         " two lines below this line
:.,.+2s/\n/ ,  " do this substitution