NeoVim/Vim 按键映射

2017-11-30 Program Python

使用 NeoVim/Vim 的主要就是为了可以减少鼠标的使用,而且提供了极高的配置,按键映射主要还是为了适合自己的操作习惯。

简介

使用时会分成高频和低频使用按键,不同的使用场景会略有所区别,例如编写代码、办公场景、整理文档等等,而且根个人的使用习惯也有关系,这里还是尽量统一。

对于高频的,尽量使用键程段方便使用的按键,个人习惯使用 CtrlLeader=, 作为组合键,其它的如 Alt Leader=Space 等,使用的不太习惯。

另外,尽量不要与原有的快捷键发生冲突,如下是 VIM 原有的快捷键。

vim keymap

按键映射

除了一些基本的快捷键之外,还可以通过 vim 的按键映射将一些常见的功能映射为快捷键。

" 可使用 - 删除一行,仍可使用 dd
map - dd

上述的 map 实际上是 nmap 表示在 Normal 模式下的映射,除此还包括 nmap imap vmap cmap 分别对应了四种不同的模式。例如,可以使用类似 Emacs 的快捷键映射,将 Ctrl-a Ctrl-e 映射为定位行首和行尾,与 VIM 中的 I A 效果相同。

nmap <c-a> I
nmap <c-e> A
imap <c-a> <esc>I
imap <c-e> <esc>A

其中 <c-a> 表示 Ctrl-a 组合按键,而 <esc> 也就是 esc 按键,还有一个 <leader> 指定一个前导快捷键,可以通过 let mapleader=',' 指定,其它还有 Alt 对应 aShift 对应 s 等。不同的 Modes 映射可参考 Neovim Mapping And Modes 介绍。

通过一系列的组合键,就可以完成很复杂的功能。

避免递归

另外,有一种场景可能会导致递归,如 nmap dd jddk ,当执行完 j 要执行 dd 时,会认为又需要重新映射,从而导致循环递归,将会导致异常。

这一场景,对于 Vim 可以使用对应的 nnoremap inoremap vnoremap cnoremap 等非递归指令进行映射,而 NeoVim 提供了 noremap = true 配置选项。

Abbreviations

与映射有点类似,不过 abbreviations 用于 Insert ReplaceCommand 模式,在输入字符的时候,VIM 会检查输入是否为 non-keyword 的字符,如果能够匹配到一个字则会自动替换,可以用来替换输入错误,例如。

:iabbrev na an

当输入 This is na apple. 时,na 会自动修改为 an,其中单词的判断是通过 iskeyword 中的字符判定,只有当单词满足 na 的时候才会替换,例如 animal 则不会替换。

另外,也可以映射一些常见的快捷字符,例如:

:iabbrev @@    hello@foobar.com
:iabbrev ccopy Copyright Your Name Here, all rights reserved.

在输入模式中,输入 @@ 或者 ccopy 就可以快速完成替换。

iskeyword

在 normal 模式中,通过 # * 查找字符时,会听过 iskeyword 的配置项来决定是否一个单词,可以通过 :set iskeyword? 命令查看,默认为 iskeyword=@,48-57,_,192-255 ,通过 , 进行分割,对应了:

  • @ 通过 isalpha() 确认为真的所有字符;
  • 48-57 实际上就是数字 09
  • 下划线 _
  • ASCII 中的 192~255 ,已经超过了标准 ASCII 的范围,暂可以忽略。

只要是 iskeyword 指定的字符链接在一起,那么都会被算作是一个单词,例如 abc abc123foo abc_123_foo 等。

为什么不用 map

在 Insert 模式中,可以通过如下设置映射。

:inoremap copy Copyright Your Name Here, all rights reserved.

在输入的时候,会等待 copy 字符串,而且即使因为输入 copyright 时,也会被替换,而之上的方式也可以输入 ccopyright 类似字符。

自动执行

简单来说,就是在指定的事件发生时自动执行指定的命令,尤其是一些重复性操作,格式为 autocmd [group] events pattern [nested] command,对应的参数为:

  • group 组名是可选项,用于分组管理多条自动命令;
  • events 事件名称,指定触发命令的一个或多个事件;
  • pattern 限定针对符合匹配模式的文件执行命令;
  • nested 嵌套标记,也是可选项,允许嵌套自动命令;
  • command 需要执行的命令、函数或脚本。

内置的事件比较多,可以通过 :help autocommand-events 命令查看,对于匹配模式可以通过 :help autocmd-patterns 命令查看,当前所有自动执行命令可以通过 :autocmd 查看,如下是简单的示例:

----- 对于.c和.h文件设置textwidth选项
:autocmd BufRead,BufNewFile *.c,*.h set tw=0

一般来说,自动命令不会嵌套执行,例如执行了 BufRead 之后,不会再次执行,如果需要,可使用 nested 参数。

执行组

通过 augroup 命令,可以将多个相关联的自动命令分组管理,以便于按组来查看或删除自动命令,如下是设置与 C 语言相关的配置。

augroup cprograms
    autocmd!
    autocmd FileReadPost *.c :set cindent
    autocmd FileReadPost *.cpp :set cindent
augroup END

其中开始的 autocmd! 用来确保没有重复的自动命令存在。