映射功能是当下各大编辑器的标配,如果你想要熟悉所用的编辑器,必然不能缺少对它的映射机制的学习。对于vim亦是如此。

这里说到的映射功能,指的是编辑器会捕获用户的输入,并且按照事先的设置来执行某些动作。

基础

在vim里面自定义一个映射,格式如下:

maptype key action

如:

inoremap jk <c-[> " 在insert模式下映射jk为Ctrl+[,也即进入normal模式

maptype表示映射的类型,分为两大类,带nore的和不带nore的(具体意义稍后再谈)……每一类中,根据映射的可用范围再分成若干类,具体类型通过:help map-overview可以查到。这里列举下重要的几类:

  1. map: 在所有模式下可用的映射
  2. vmap:在visual和select模式下可用的映射
  3. nmap:在normal模式下可用的映射
  4. imap:在insert模式下可用的映射
  5. omap:用于motion的一部分的映射。比如vw就是visual模式下选中一个词,可以用omap定义类似于w这样的动作操作符。
  6. cmap:用于在命令行下(输入:/之类后)可用的映射

key表示映射的键。什么样的键可以被映射呢?基本上你在键盘上能看到的键都能被映射(实际情况并不如此理想,等会解释)。如果你想映射特殊的键,比如,可不能就直接打个上去,而要使用<space>来表示。各种特殊符号具体的表示方式见:help key-notation。注意不仅能映射单个键,还能映射一组键,比如noremap afhaso; 脸滚键盘

action就是映射出来的动作。可以是一串字符串,或者调用一个函数,还可以是调用一个vim命令。这个就要看大家的想象力了。

进阶

从这里开始就要举出更多映射的例子啦。

Notice! 不要说“为什么要这样映射,XX键本来有YY功能,这样做不对”之类的话,毕竟这个是关乎personal taste的事情。这里提醒下,在映射一组键之前,先看下这个键是不是已经有默认的功能了,然后看下这组键是否被映射了,再来决定要不要映射它。否则等到已经习惯后,一旦想要改,也没那么方便了

通过:help命令查看某组键是否有系统默认功能。
通过:map命令可以显示当前键映射的情况。

noremap VS map

noremap表示不允许映射的结果参与其他的映射规则的匹配。而map会使得映射的结果可以继续匹配其他的映射规则。

举个例子:

nnoremap ; :
nnoremap : ;

这里把;和:两个符号互换了,因为在normal模式下,:用到的频率比;高。假如这里用到的是nmap呢?那会导致vim卡上一段时间,直到你按下Ctrl+c或者抛出个错误。所以基本上都是用noremap作为映射。

当然map也有用武之地,比如当你需要映射的结果来触发另一个映射时,就用得上map了。

cnoremap Or command

cnoremap会在命令行里起作用。
试一下输入::cnoremap w!! w !sudo tee >/dev/null %
然后敲:进入命令行,快速地敲出w!!,你会发现它展开成为w !sudo tee >/dev/null %。这就是cnoremap的效果了。

用cnoremap可以大大缩短常用命令的输入时间。举个例子,你可以使用cnoremap UE UltiSnipsEdit来代替敲入整个命令(或者多次敲打tab键)。不过前提是你的手速要足够快……

其实为什么不用command呢(现在:help command看看)。你可以用command命令给某个命令做别名,这样就不用依赖足够快的手速了。

can map and can't map

前面说过,实际上不是所有的键可以作为vim映射的键。这是因为要想触发vim映射,你要让vim捕获到某一组键才行。但是有些键不会被传递给vim,可能半途就被其他程序偷吃掉了。这种情况在终端vim下特别明显。因为终端会占用一些快捷键,而且有些特殊的键值,比如shift+tab,即使终端它自己不用,也不给vim使用(好过分喔)。所以到底某个键能不能拿来做映射,还是得试了才知道。

脑洞大开

在这一部分,我来分享些自己觉得有用的映射,但求抛砖引玉。

" 切换鼠标模式和无鼠标模式。方便复制
function! ToggleMouse()
    if &mouse ==# 'a'
        set mouse=
        set norelativenumber
        set nonumber
        echo 'no mouse mode'
    else
        set mouse=a
        set number
        set relativenumber
        echo 'mouse mode'
    endif
endfunction

noremap <F2> :call ToggleMouse()<CR>
" 在安装了ag.vim插件后,查询光标下的内容
nnoremap <leader>sc :Ag! <cWORD>
" 在新的tab里编辑当前目录下的其他文件
nnoremap <C-down> :tabedit <c-r>=expand("%:p:h")<cr>/
" 快速开始一个全局替换
nnoremap <leader>s :%s///gc<left><left><left> 
" 编辑shell文件时,调用man命令查看文档
au FileType sh nnoremap <leader>m  :!man <cWORD><cr>

spacewander
5.6k 声望1.5k 粉丝

make building blocks that people can understand and use easily, and people will work together to solve the very largest problems.


引用和评论

0 条评论