严格意义上来说,快捷键的绑定应该是键盘映射,将某些键映射为另一些键。

在上篇我们介绍了基本的键盘映射操作,知道了如何 :map、:imap、:vmap、:nmap这些命令来映射键盘快捷键。它们很方便,也很简单,但是有一个致命的缺点。他们是递归的,我们先来讨论什么是递归

映射的递归问题

让我们先来执行下面的命令

:nmap jj J
:nmap J j

这里我们原本是想 jj来实现 J的功能,更加快速的实现合并行的功能,但是我们按下之后发现,它只是将光标移动到下一行了。这并不是我们想要的。到底发生什么了呢?

因为这些命令是递归的。如何理解递归呢?我们以函数的思想来考虑,每定义一个快捷键,就相当于定义了一个函数。并且在新定义的函数中调用老函数。依照这个思路我们来分析一下上述两个命令产生的结果:

  1. 首先定义了一个名为 jj的函数,它的函数代码为 J()
  2. 然后我们定义了一个名为 J的函数,它的代码定义为 j()
  3. 我们执行 jj函数的时候,它在函数内部调用 J(),J函数内部调用 j()。因此它表现出来的最终效果就是 jj等效与 j。

这些映射产生的伪代码如下:

void J()
{j();
}void jj()
{J();
}

我们在调用 jj 这个函数的时候就相当于在调用 j

有点绕是不是呢。为了讲述这个问题,我们再来看这么一个例子

:nmap dd o<esc>kddj

我们来分析一下它的本意:

  • 首先使用 o在光标所在行之下插入一行
  • 退回到普通模式,并且让光标向上移动一行
  • 删除光标所在行
  • 移动到下一行,也就是刚刚的插入行

看起来这个命令的作用是清除本行,但是vim并没有这么做,只有按下 <C-c>才能停下来,而且vim中多出了许多空白行。

依照上述分析思路,我们可以对这个命令的执行结果写出如下的伪代码

void dd()
{o();esc();k();dd();j();
}

从上述的代码看出这个映射会陷入无限循环,或者叫死递归。我们只能使用 <Ctrl +c>来终止。

在正式进入下一步之前让我们先删除这个映射。我们可以使用 :nunmpa 来删除一条快捷键映射,输入 :nunmap dd 来终止上述出错的映射。之前介绍的那些映射命令都有 un 系列的命令,例如 map 对应 unmapimap 对应 iunmap

我们从上面的几个例子应该看出来了, 之前介绍的函数好用是好用,但是会形成递归。在上述代码中还算是比较好找,如果我们配置文件大了,不同插件有自己的映射,而我们也会定义一堆自己的映射,这个时候出问题就难查了。

为了解决这个问题,vim提供了一系列的 nore 开头的函数。它相比于之前介绍的函数来说,是非递归的。之前每个命令对应的非递归版本如下:

  • nmap 对应 nnoremap
  • imap 对应 inorempap
  • vmap 对应 vnoremap
  • cmap 对应 cnoremap

相信各位应该看出来了,我们在原来命令的基础之上添加了 nore 作为非递归版本。我们来做一个试验

:nmap x dd
:nnoremap \ x

我们输入 \ 发现它只删除了一个单词,即使用 :nnoremap 只保留了 \ 作为 x 操作符的作用,而斩断了之前 x 被映射为 dd 的操作。

那么我们何时该使用递归版本,何时使用非递归版本呢?答案是在任何时候,永远使用非递归版本,现在就请各位小伙伴忘掉非递归版本把。现在多敲几个单词将来会省去大量排错时间。

lua 配置

到此位置我们学会了怎么使用 :map 系列的命令定义快捷键,同时也知道什么是快捷键之间的递归和非递归。可以说掌握了关于 vimscript 定义快捷键的基本方法。那么如何跟 lua 对应呢?

neovim 定义了一系列的函数帮助我们定义、获取和删除快捷键

  • vim.api.nvim_set_keymap: 设置快捷键
  • vim.api.nvim_get_keymap: 获取快捷键
  • vim.api.nvim_del_keymap: 删除快捷键

我们可以通过帮助文档查到 vim.api.nvim_set_keymap 的定义如下:

nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts})

mode 是一个字符串,对应着一个模式,即我们之前说的可视模式、插入模式或者普通模式,下面是各个模式对应的字符串名称 。

字符串 模式 对应的vim 命令
“” 所有模式 :map
“n” 普通模式 :nmap
“v” 可视模式 :vmap
“i” 插入模式 :imap
“s” 选择模式 :smap
“c” 命令模式 :cmap

lhs 对应着一个键位,即我们想映射的键位,如果传入空字符串,相当于通过 :map传入 <NOP>。表示将要禁用这个键
rhs 对应着将要执行的命令,是 :map 的第二个参数
opts 代表映射的其他属性,主要是一个表,你可以暂时理解为一个字典。比如可以使用 noremap 表示禁止递归,使用 silent 表示执行命令时不回显内容

例如我们在配置文件中定义

vim.api.nvim_set_keymap("n", "<space>", "/nvim<CR>", {noremap = true, silent = false})

通过这段代码,我们将 空格键映射为在文件中查找 nvim 字符。因为 silent 设置的是 false 因此我们在按下空格键之后在vim 的左下角会看到 /nvim 的字样

我们可以通过设置 silent = true来取消这个回显。

vim.api.nvim_set_keymap("n", "<space>", "/nvim<CR>", {norema=true, silent = true});

映射leader 键

常见的映射主要出现在普通模式下,普通模式下的很多按键都有其特殊用途,而且还大多挺常用的,想来想去不怎么使用,而且位置好按的也就 <space>HLD 这些了,将他们进行映射,映射到常用功能,减轻我们的按键负担是再好不过了。但是我们常用功能又那么多,特别是装了插件之后的。这些键完全不够使用的。

这个时候我们要延续 emacs 或者其他软件的思路了,一个键不够就两个键,比如使用下面的映射

:noremap -d dd
:noremap -c ddO

这意味着我们可以使用一个键作为前缀,后面接其他字符,将他们作为一个整体来映射一个功能。多按一个键而已,比你输入整个命令要轻松多了。

这就引入一个新的思路了,我们可以统一定义一个键作为前缀键,后面添加一些字符来整体进行映射。当然我们可以手工这么做,每次需要多个按键的时候的就手动写上 - 或者其他的。但是后期我发现 - 并不容易按到,我觉得 <space> 或者 ,更容易按到,要进行修改,那么修改的量就太大了。

vim 中有一个被称之为 leader 键的东西来解决这个问题,我们可以提前定义一个 leader ,在映射的时候使用 <leader> 来代表对应的前缀键。例如,先设置 leader<space> 后面再定义 <leader>d 作为 dd,后面可以很方便的修改 <space>d 这个映射为 ,d,只需要修改 leader 键的定义。

可以使用 :let mapleader = <space> 来定义 leader 键为空格。这里你可以定义成你喜欢的键,我平时喜欢用空格,因为它比较大,平时也在大拇指的位置,方便按。

然后我们可以使用 :noremap <leader>d dd 来定义映射

如何在 lua 中定义 leader 键呢?
从上面的 vimscript 代码中可以看到 mapleader 是用 let 关键字来设置的,一般 let 是用来设置变量的。lua 中自定义变量可以直接定义,但是 mapleader 明显是vim 自带的变量。跟设置选项类似,neovim 提供了两种访问 vim 内部变量的方式,一种是使用函数,一种是使用 元访问器。

跟变量有关的函数主要有:

  • vim.api.nvim_set_var():设置全局变量的值
  • vim.api.nvim_get_var():获取全局变量
  • vim.api.nvim_del_var():删除全局变量

当然使用元访问器会更加简便,对应的元访问器为 vim.g。所以这里我们可以使用 vim.g.mapleader = " " 来设置

到此我们已经学会了关于映射的所有初级的内容,现在已经可以完成大部分的配置工作了。至于在定义快捷键的时候是使用 leader键还是使用多个普通键,看具体场景和各位小伙伴的使用习惯了。这里我就不给建议了,一切以方便好按为主。

从零开始配置 vim(3)—— 键盘映射进阶相关推荐

  1. 从零开始配置vim(23)——lsp基础配置

    上一章,我们初步认识了lsp,并且对 nvim-treesitter插件进行了配置,为编辑器提供了代码着色.自动格式化以及增量选中功能.算是初步体验了 lsp的相关功能.从这篇开始我们通过lsp的功能 ...

  2. VIM使用系列之一——配置VIM下编程和代码阅读环境

    作者:gnuhpc from http://blog.csdn.net/gnuhpc  http://gnuhpc.wordpress.com/ 本文环境:ubuntu 10.10/vim7.2 前言 ...

  3. mac 使用Karabiner配置键盘映射(2)-核心标签的解读

    2019独角兽企业重金招聘Python工程师标准>>> mac 使用Karabiner配置键盘映射(2)-核心标签的解读 KeyOverlaidModifier 使用场景:一般用在 ...

  4. VIM妙用及linux使用技巧(包括vim插件管理器、指令与键盘映射、打开多个文件、奇偶删除行、vim替换等)

    前言 vim 是个非常高效.非常好用的工具,很多人一旦开始使用 Vim 之后就再也无法自拔.然而, Vim 仍然有其自身缺陷,对于普通用户来说,很难在入门的时候就体会到Vim的所谓高效性,同时,为了展 ...

  5. macOS配置vim

    本教程适用于刚刚使用mac的小白,大神可以路过- MacOS的vim配置和Linux下面相似.在我电脑配置效果如下 1.前言 配置之前首先注意下两个文件目录的作用,如下 /usr/bin /usr/l ...

  6. vscode 逗号不换行_在VSCode里面配置Vim正确姿势(细节解析)

    一.导论 对于不用vim的人来说,vim简直是个噩梦,复杂的指令.丑陋的界面.令人头痛的配置文件,任何一项都足以劝退一大波人,但是对于已经习惯了使用vim的人来说,vim简直就是马良神笔,似乎vim除 ...

  7. linux红外键盘映射表,linux下修改键盘映射

    有段时间特别喜欢HHKB(一款适合专业人士使用的键盘),不过被它超高的价位给打败了.后来想想喜欢它的缘由有两个,第一就是它control键的位置,它的control键位于常规键盘的capslock键的 ...

  8. 行号 设置vim_在VSCode里面配置Vim正确姿势(细节解析)

    一.导论 对于不用vim的人来说,vim简直是个噩梦,复杂的指令.丑陋的界面.令人头痛的配置文件,任何一项都足以劝退一大波人,但是对于已经习惯了使用vim的人来说,vim简直就是马良神笔,似乎vim除 ...

  9. AI应用开发实战系列之一: 从零开始配置环境

    AI应用开发实战 - 从零开始配置环境 与本篇配套的视频教程请访问:https://www.bilibili.com/video/av24421492/ 零.前提条件 一台能联网的电脑,使用win10 ...

  10. vscode emmet默认模板_从零开始配置 vscode

    我们在进行开发工作时,选择一个顺手好用的编辑器是必不可免的, 其中 vscode 就是一个很好的选择.它能让你大部分的工作都在编辑器内完成, 大大的提高开发效率~ 概述 vscode 内置了前端相关的 ...

最新文章

  1. 6D姿态估计和3D 目标检测(区别)
  2. vscode使用教程python-教你正确使用VSCode写Python
  3. 【HDU2582 关于 gcd( C[n][1],C[n][2],C[n][3],........C[n][n-1) 】
  4. 窗口分析函数_3_生成不间断重复排名序号
  5. 给JAVA初学者的50个忠告
  6. 嵌入式基础认识1:存储器(如RAM、ROM和FLASH)
  7. 佳博打印机ip地址修改软件_win10系统搜索不到共享打印机的问题
  8. jar包里java.lang.NoSuchMethodError异常,
  9. karto探秘之slam_karto
  10. BZOJ3680 吊打XXX
  11. 【Python】字符串的一些操作
  12. Vue 监听浏览器页面窗口切换, 窗口最小化
  13. 组态软件mcgs入库mysql_昆仑通态专题(四):MCGS嵌入版组态软件的数据报表
  14. java 商品库存修改
  15. 【转】Apache——世界使用排名第一的Web服务器
  16. c语言结构体编程时钟,c语言简单数学时钟(结构体,指针),求大佬帮助
  17. You must address the points described in the following [1] lines before starting Elasticsearch.
  18. fantastic-matplotlib: 第一回:Matplotlib初相识
  19. C# WPF MVVM 实战 – 2.4 单元测试
  20. 前度构建工具gulp

热门文章

  1. 【现控】系统状态空间表达式
  2. python 模块下载成功,却无法导入?
  3. 文献补充材料怎么下载?
  4. 原声php 读取excel乱码_php读取excel文件,输出的值乱码解决方法
  5. Fragstats 提示错误与警告
  6. EasyRecovery帮你一招找回网易云下载的单曲
  7. 彩虹自助下单平台对接爱代挂插件程序
  8. 【c++思维导图与代码示例】02 函数
  9. VGG-16网络结构详解
  10. c语言入门-程序运行的过程