严格映射

准备好迎接即将到来的疯狂吧。

到目前为止,我们已经用 mapnmapvmap、以及imap 创建按键映射来节省时间。 这些命令能正常工作,但是都有一个缺点。 运行以下命令:

:nmap - dd
:nmap \ -

现在试试按下 \ (在普通模式中)。看看发生了什么?

当按下 \ 键时,Vim 匹配到映射,然后说:“我应该改为运行-键”。 但是,-又被映射到做其他的事情了! Vim 又匹配到了,然后说“哦,我现在必须去运行dd”,所以就把当前行删除了。

当用这些命令来映射按键时,Vim 也会把其他映射考虑在内。 乍一听起来好像挺不错,但实际上是非常的糟糕的。 让我们来看看这是为什么,但首先删除这些映射吧,运行以下命令:

:nunmap -
:nunmap \

递归

运行命令:

:nmap dd O<esc>jddk

乍一看,它似乎会把 dd 映射为:

其实就是“清除当前行内容”。现在试试看。

当按下 dd 后,Vim 就会卡住。 可以通过按 <c-c> 来让 Vim 恢复原样,但是文件中会多出来一大堆空行!到底发生了什么?

这个映射实际上是递归的!当按下 dd 后,Vim 会认为:

映射过程永远不会结束!赶紧把这个可怕的命令删除吧,运行以下命令:

:nunmap dd

副作用

这些 *map 命令的一个缺点就是递归的威胁。 另一个就是映射的行为可能会被其他插件中的映射所改变。

当安装一个新的 Vim 插件时,很可能你并不会用到或者记住它创建的所有映射。 即使能做到,也不得不去 ~/.vimrc 文件中看一遍,以确认自定义的映射没有用到插件中映射过的按键。

这会让安装插件变得枯燥无味,并且极易出错。一定会有其他更好的办法。

非递归映射

Vim 提供了另外一个映射命令的合集,当它们在执行操作时,并不会把其他映射考虑在内。 运行命令:

:nmap x dd
:nnoremap \ x

现在按下 \ 键,看看会发生什么。

当按下 \ 键,Vim 会忽略 x 的映射,并且会执行 x 的默认操作。 它会删除当前字符,而不是删除当前行。

每个 *map 命令都有一个 *noremap 配对命令来忽略其他映射:noremapnnoremapvnoremap、以及 inoremap

什么时候应该使用这些非递归版本而不是普通版本。

任何时候

是的,很认真的说,任何时候。**

用原始的 *map 命令只会在以后安装插件或者增加新的映射时自讨苦吃。 就不要自找麻烦了,输入一些额外的字符来确保那永远不会发生。

练习

把所有之前添加到 ~/.vimrc 文件中的映射转换成前面提到的非递归版本。

阅读 :help unmap

原文地址:http://learnvimscriptthehardway.stevelosh.com/chapters/05.html