从零开始匹配vim(2)——快捷键绑定
如果说 vim有什么最吸引人,我想vim允许你自由的定义各种快捷键算是一个原因吧。你可以通过绑定各种快捷键来使经常使用的功能更加便利。通俗的讲,快捷键映射就是我按下某个键,我想让vim将它当成另一个键,例如我按下 k
,我想让vim把它当做 c
来使用(当然这么映射会把人逼疯)
快捷键映射
我们使用 :map
命令来进行快捷键的映射,例如我们输入如下内容
:map - dd
通过这个命令,我们将 -
映射为 dd
,也就是说现在我们按下 -
就可以删除光标所在行了。
针对功能键,例如 Ctrl
、空格
、Tab键
等,在 vim
中使用 <keyname>
的形式,其中 keyname
是按键名称,下面列举出一些常用的控制键的表示方式:
Ctrl
键对应<c>
空格
键对应<space>
alt
键对应<a>
esc
键对应<esc>
- 退格键对应
<bs>
- 回车键对应
<cr>
shift
键对应<shift>
f1
到f12
对应<f1>
到<f12>
这些功能键与普通字母做配合时,将字母键放入到 <>
中,并以 -
和 功能键做分割,比如 :map <c-d> dd
来将 <Ctrl +d>
映射为 dd
当然有时候为了可读性,我们可以将这些功能键以大写字母来表示,例如 <C-d>
就表示 <Ctrl +d>
快捷键映射就是这么简单,接下来要做的就是思考如何进行映射能提升我们的效率,即提取常用的操作将他们映射为快捷键。我们来通过几个小例子来给小伙伴们提供一些思路。
定义 -为将当前行往下移动移动
我们知道,在普通模式下要将当前行往下移动,可以首先执行 dd
删除一行,然后执行 p
来拷贝到下一行,因此我们可以这样定义快捷键
:map - ddp
定义 _
为将当前行往上移动移动
在这个例子中,第一步仍然是执行删除,但是与上一个例子不同的是,我们要将删除部分往上一行粘贴。如果往上一行粘贴呢,在之前介绍的时候我们并没有提到如何执行这么一个操作。如果你的第一反应是要去翻用户手册或者去查其他的资料,那么我建议你仔细去阅读一下我之前写的内容。体会一下vim的一些思想和技巧。
仔细回想一下 o
(小写)和 O
(大写) 的区别,而且我们曾经提到过,普通模式下,大写字母和小写字母功能类似。说到这我想你应该知道答案了。我们使用 P来粘贴到上一行。因此这里的映射可以写成
:map _ ddP
如果你觉得这两个映射对你有用,你可以将它放入你的 vimrc
中,或者先记下来,等我们介绍完使用 lua
配置之后,再写到 init.lua
中。
其他模式下的映射
map
可以定义映射,但是各位小伙伴可以做一下试验,map
命令定义的快捷键在 visual
模式下仍然有效。这样就会带来一个问题,如果我想在多个模式下都对 -
这个键进行了定义,而且定义成了不同的快捷键,这该怎么处理呢?
其实 vim
针对不同的模式有不同的快捷键定义命令,例如 :nmap
负责在普通模式下定义快捷键, :vmap
负责在 visual
模式下定义快捷键。这个时候你肯定已经猜到了,:imap
可以在插入模式下定义快捷键,或者使用 :cmap
定义命令行模式下的快捷键。
这些命令的格式与 :map
一样。下面还是以例子为主吧
例1: 重新在普通模式下定义 -
例如我们使用 :nmap
重新定义 -
为 ddp
,这个时候我们发现它只在普通模式下有用,而在选择模式下无效。
例2: 定义 为复制粘贴
不知道有没有小伙伴在初学vim的时候希望也能像在Windows中那样,使用 <Ctrl+c>
和 <Ctrl+v>
来进行复制粘贴。学到现在我们终于有能力自己动手实现这个需求了。
虽然不推荐这么干,但是还是满足各位折腾的欲望吧。
仔细回想一下,<Ctrl+c>
实际上是拷贝选中的文本,而<Ctrl+v>
是在输入的时候直接粘贴的。因此我们知道映射 <Ctrl+c>
应该是在 可视模式下。而<Ctrl+v>
应该是在插入模式下。
另外在插入模式下是不支持使用 p
来进行粘贴的。还记得我们在插入模式下介绍的那些技巧吗?其中有一个快速从寄存器中粘贴的技巧。正好可以在这里用到。而复制操作会将复制的文本拷贝到寄存器中(也就是 0
寄存器)。结合这两个知识点,我们可以很方便的映射出这两个快捷键
:vmap <C-c> y
:imap <C-v> <C-r>0
虽然它仍有一些不完美,但是已经够用了。最后还是不推荐这么干,毕竟使用 y
等操作就能搞定的事情没必要弄的这么麻烦。而且在linux平台,特别是在终端上,这些键都另有用途。例如 <C-c>
在vim中可以退回到普通模式。
例3: 定义 <c-d>
为在插入模式下删除一行
我们再举一个例子,我想在插入模式下使用 <C-d>
来删除光标所在行。vim
在插入模式下并没有提供快捷键来删除一行,需要使用退格键一个个的删除,想要快速删除可以回到普通模式使用dd
。那么我们可以使用 :imap <c-d> <esc>dd
。
我们会发现按下 <c-d>
之后它成功删除了一行,但是它自己退回到普通模式去了,我们想要的是它能在删除一行后仍然处于插入模式,这样我们就可以直接输入了,因此我们可以在后面新加一个再次进入插入模式的步骤,即 :imap <c-d> <esc>ddi
。
再次尝试,我们发现它已经满足我们的需求了。
例4: 在插入模式下定义快捷键快速转换单词为全大写
我们定义一个在插入模式下能快速将光标所在单词改为全大写字母。例如 C/C++
语言的编程规范中都会讲到宏或者常量最好以大写字母命名。例如 #define MAX_CONNECTIONS_QUEUE 100
这样长的宏定义,我们在输入的时候要一直按着 shift
键是很痛苦的事情。我们需要有这么一个快捷键我们可以先输入小写字母然后使用快捷键将它改为全大写。
首先我们思考一下,不使用快捷键该是如何操作呢?首先我们将光标移动到单词所在位置并退回到普通模式,接着使用 viw选中,然后使用 U来改为大写。
根据这一串操作命令,我们可以就知道了该如何定义快捷键了,:imap <c-u> <esc>viwU
。根据上面的一个例子我们知道,这样它最终会停留在普通模式下面,我们还是希望能够回到插入模式,考虑到我的使用场景是,我在写完整个单词之后会立马将它转化为大写,然后再编辑后面的其他部分,因此我将光标移动到被大写的单词的尾部,并且进入插入模式。现在命令就变成了 :imap <c-u> <esc>viwUwa
。
这里你可以根据需要灵活的进行调整,例如可以改为 :imap <c-u> <esc>viwUA
,在行尾进入插入模式。
最后做一个总结。本篇提到的比较重要的定义快捷键的命令有:
- map: 定义所有模式下的通用快捷键
- imap: 定义插入模式下的快捷键 (insert)
- nmpa: 定义普通模式下的快捷键 (normal)
- vmap: 定义选择模式下的快捷键 (visual)