与自定义快捷键相关的四个系列命令
map系列命令
这个命令的声明如下: :map {lhs} {rhs}。这个命令就是将{lhs}代表的按键映射成{rhs}所代表的按键。例如map L $就是将$键映射成L。此外需要注意的是map命令定义的快捷键是可以嵌套的,例如下面这样的命令:
map L $
map Y yL
就是将Y按键映射成了y$按键。
noremap系列命令
这个命令的声明如下: :no[remap] {lhs} {rhs},顾名思义,就是不可以重新映射的命令。这个命令和map命令类似,不过它所定义的命令不可以被重新映射,例如下面的例子:
map L $
map Y yL
此时我们映射的Y按键的效果就不会和y$按键的效果相同了。此命令的主要作用是为了防止按键重新定义时出现冲突,所以一般推荐使用此命令来映射快捷键。
unmap系列命令
unmap,顾名思义,就是用来取消所在模式下快捷键的定义(关于模式我们下一小结会将)。
mapclear系命令
mapclear,清除所在模式下定义的所有快捷键。
自定义快捷键相关的六种模式
在Vim中,共有六种模式,不同的定义快捷键的命令生效的模式不同,这六种模式如下:
N ormal Mode: 即Vim的普通模式,我们打开Vim后进入的第一个模式即此模式。
V isual Mode: 即Vim的Visual模式,我们在选中了一定的文本之后(通过v或者V命令)即进入此模式。
S elect Mode: 这种模式和Visual模式相似,不过输入的文本都会替换选中的文本。在普通模式下,通过鼠标选中或者使用gH命令都可以进入此模式。
O perator-pending Mode: 当我们输入一个操作符后(例如,d,y,c等等),就会进入此模式。
I nsert Mode: 即Vim的插入模式,普通模式下我们输入i(或者s,a等等)就会进入此模式。
C ommand-line Mode: 命令行模式,我们在普通模式下输入:或者/等就会进入此模式。
命令模式对应表
下表表示了每个自定义快捷键的命令和其对应的生效模式,需要注意的是Lang-Arg并不是一种新的模式,而是表示了这样一种情况。当我们键入一个字符的时候,它是缓冲区中文本的一部分,而不是一个Vim命令。上面这句话我翻译自Vim文档,我感觉自己也没有很是搞懂,所以还是把原文贴出了吧(参见:help language-mapping):
通过观察上面这些命令的前缀,我们可以发现,命令前缀和生效的模式有关。例如,v表示Visual和Select模式,s表示Select模式,c表示Command-line模式,等等。
分享两个我自己定义的快捷键
Ok,扯了那么多和自定义快捷键相关的东西,接下来我和大家分享几个我自定义的快捷键吧,感觉用起来很爽,希望对大家有帮助。
Tab键映射成搜索
搜索无疑是一个使用频率非常高的快捷键,但在原始的Vim中使用的却是/或者?,当要使用搜索功能的时候,我的右手要离开HomeRow(就是 爱上对方过后就哭了 那一行),然后使用中指或者食指去按/,感觉虽然也可以用右手小拇指去按/,但实在是太费劲。
所以我就把/映射成了<Tab>,<Tab>键在普通模式下基本用不到,同时左手小拇指又非常容易按到,感觉一下子方便了许多。映射命令如下:
" 映射/为<Tab>
noremap <Tab> /
1
2
大家可以看到,我这里使用的是noremap映射的(防止以后再来映射和<Tab>键相关的组合键时出现错误),同时,这个命令生效的模式是Normal,Visual,Select,Operator-pending。这样我不仅可以在普通模式下搜索,也可以在选择文本(Visual),删除文本(通过d命令)时进行搜索。
后来我才发现,<Tab>和<C-i>的keycode是一样的,无法分别映射,所以将<Tab>映射为搜索按键会影响到<C-i>的功能,所以还是先删除掉吧。
快速定位当前文件
这条映射是我在《VIM 实用技巧》中看到的,感觉很好用,特意来分享给大家。此映射命令如下:
" 将%:h映射为%%,%:h的功能是显示当前缓冲区文件的相对路径
cnoremap <expr> %% getcmdtype() == ':' ? expand('%:h').'/' : '%%'
这条命令比较复杂,首先cnoremap表示在命令行模式下进行映射,<expr>表示将映射命令的右边的参数当做一个表达式来对待(详见: :help :map-<expr>)。
%%就是我们定义的快捷键,getcmdtype() == ':' ? expand('%:h').'/' : '%%'就是我们要执行的表达式,此命令的含义就是每当我们在命令行模式下输入%%,就会得到表达式getcmdtype() == ':' ? expand('%:h').'/' : '%%'运算的结果。
接着我们再来分析一下这个表达式,getcmdtype() == ':' ? expand('%:h').'/' : '%%'。
首先来看调用的两个函数,getcmdtype表示获取当前命令行模式的类型,:表示是Ex-Mode,就是在普通模式下输入:进入的模式,此外其他的返回结果参见:help getcmdtype()。
expand()函数表示对通配符进行扩展,其中传入的参数为%和:h,%表示当前缓冲区文件,:h相当于一个函数,传入一个文件参数,返回文件所在的文件夹(相当于Python中的os.path.dirname()),我们可以看到expand('%:h')函数的功能就是返回当前缓冲区文件所在的路径。
整体来看这个表达式的话,就是一个三元运算符,如果当前模式是Ex-Mode的话,返回当前缓冲区文件所在的文件夹,否则的话返回%%。
有待考证和完善之处
写文章之前,我觉得我应该已经了解了Vim的map相关的命令,但是写完以后,发现还是有很多疑问,写到最后发现还有新东西自己没有涉及,这里先记录下来,以待以后完善:
map的递归定义的用法。我看到:help :map文档中说,This allows for nested and recursive use of mappings.也就是说map可以进行递归定义的,只是不知道怎么用,递归出口在哪?
map命令还有一个map-<expr>的用法,这次还没有讲,以后加上。
关于文档中Lang-arg还不是很懂。
前缀键
前缀键。各类 vim 插件帮助文档中经常出现 <leader>,即,前缀键。vim 自带有很多快捷键,再加上各类插件的快捷键,大量快捷键出现在单层空间中难免引起冲突,为缓解该问题,引入了前缀键 <leader>,这样,键 r 可以配置成 r、<leader>r、<leader><leader>r 等等多个快捷键。前缀键是 vim 使用率较高的一个键(最高的当属 Esc),选一个最方便输入的键作为前缀键,将有助于提高编辑效率。找个无须眼睛查找、无须移动手指的键 —— 分号键,挺方便的,就在你右手小指处:
" 定义快捷键的前缀,即<Leader> let mapleader=";"
举例
- 使用set命令:
set pastetoggle=<F9>
- 使用imap命令:
用Esc退出插入模式很麻烦,可以将另外的键映射到这个键上,比如将Ctrl-i映射为Esc:imap <C-I> <Esc>
- "配置F4为Ack快捷键:
:map <F4> :Ack -i
- 在插入模式,设置ctrl+为退出文件 :
:map! <C-> <ESC>:q<CR>
<Esc>代表Escape键:<CR>代表Enter键;<D>代表Command键。
Alt键可以使用<M-key>或<A-key>来表示。<C>代表Ctrl.
对于组合键,可以用<C-Esc>代表Ctrl-Esc;使用<S-F1>表示Shift-F1.