VIM | 提升Vim导航效率:深入解析vim-easymotion和vim-sneak插件的使用技巧(适合前端开发使用)

1,334 阅读5分钟

vim-easymotion和vim-sneak都是vscode中vim内集成的插件,我们可以更改vim的默认配置很快的开启并使用

vim-easymotion

vim-easymotion是为了解决什么问题?

在使用vim的过程中经常会遇到组合按键的情况,比如18j10k这样的组合指令,遇到这种指令手就需要经常向上移动去按数字按键,导致打起来并不舒服,而vim-easymotion的设计就可以减少手去按数字按键的频率,也可以实现在屏幕可视范围内让光标进行快速跳转的操作。

如何开启easymotion插件

打开VScode的settings.json配置文件,加入如下配置:

{
	...,
	"vim.easymotion": true,
	"vim.leader": "<space>",
}
  • vim.easymotion设置为true表示启用vim内置的vim-easymotion插件。
  • vim.leader设置vim中对应的leader

什么是 <Leader>

  • vim 中有本身内置了不少快捷键以及各种插件,为了防止按键冲突以及进一步丰富按键的组合,vim推出了<Leader>的概念,实际上可以将这个概念理解为vim中的老板键,通过老板键配合其他按键的组合可以完成各种各样的效果。

vim-easymotion的内置指令

  • <Leader> <Leader> w:高亮光标后的所有单词的开头
  • <Leader> <Leader> b:高亮光标前的所有单词的开头
  • <Leader> <Leader> e:高亮光标后的所有单词的结尾
  • <Leader> <Leader> ge:高亮光标前的所有单词的结尾
  • <Leader> <Leader> h:高亮光标前的所有单词的开头和结尾、驼峰、_或者#之后的内容
  • <Leader> <Leader> l:高亮光标后的所有单词的开头和结尾、驼峰、_或者#之后的内容
  • <Leader> <Leader> j:高亮光标下方的所有行的开头
  • <Leader> <Leader> k:高亮光标上方的所有行的开头
  • <Leader> <Leader> <Leader> j:高亮所有单词的开头和结尾、驼峰、_或者#之后的内容

输入对应命令后,会有高亮的文本,此时输入对应的字符就可以快速将光标跳转到对应的位置了

image.png

vim-sneak

vim-sneak解决了什么问题?

我们知道在vim中使用fF在只能在行内进行快速跳转,并且在使用的时候只能快速搜索单个字符,很难满足大部分的使用场景,而vim-sneak插件可以解决这个问题。vim-sneak相比vim自带的f以及F解决了上述的两个问题,即在按下s后可以跟上两个字符进行全局快速搜索,并未可以使用;不断的向下搜索,将光标移动到相同匹配结果的内容上。为了使用更方便,则这里会对vscode进行配置,将Ff分别映射到Ss上,用于替换(增强)原先的Ff的功能。

开启vim-sneak并对vscode进行配置

打开vscodesetting.json这个加入如下的配置选项开启vim-sneak的基本功能:

{
	...,
	"vim.sneak": true,
}

启用了sneak后,现在需要对fF做重新映射,将其映射到sS上:

首先,如果将f/F映射到s/S上,就会产生不能使用sS两个按键原先对应的功能:

  • s:删除光标所在字符并进入 insert 模式;
  • S:删除光标所在行从开头非 blank 字符到行尾的内容

所以我们需要重新设置sS对应的按键功能,这里我们将s设置为clc删除并进入编辑模式,l代表影响的范围,删除光标右侧的字符),而S设置为^C^移动到本行第一个【非空字段】的位置,C删除从光标当前位置到行尾的内容)。

看到这里有没有发现到这里的按键配置很奇怪?是的,这样配置会产生递归映射按键的情况如f->s->cl,而vscodevim插件为了防止出现递归映射的情况,给了对应的解决方案——配置项:"vim.normalModeKeyBindingsNonRecursive"

扩展阅读:

"vim.normalModeKeyBindingsNonRecursive"和"vim.normalModeKeyBindings"有什么区别?

官方文档中截取的相关内容: image.png 这里的解释是如果我们在"vim.normalModeKeyBindings"的模式下,进行jk两个按键的交换,此时按下j相当于按下了k,而按下k又会触发按下j,这样就会不换递归循环调用下去,如果将其配置到"vim.normalModeKeyBindingsNonRecursive",则就不会有这种递归调用的问题,非递归键绑定意味着键绑定不会递归地再次触发其他键绑定。换句话说,如果一个键绑定包含在另一个键绑定中,设定为非递归将会阻止第一个键绑定再次触发第二个键绑定。

总结:

  • vim.normalModeKeyBindingsNonRecursive 确保设置的键绑定不会触发其他键绑定,避免递归问题。
  • vim.normalModeKeyBindings 允许设置键绑定,但可能会触发递归的链式调用问题。

setting.json中加入vim.normalModeKeyBindingsNonRecursive的基本配置:

{
	...
	"vim.normalModeKeyBindingsNonRecursive": [
		// 通过将F映射为S,F映射为s,启用更好用的sneak插件
		// 通过将s重新映射为cl,S映射为^C,从而不影响s/S原本的功能
		{
			"before": ["f"],
			"after": ["s"]
		},
		{
			"before": ["F"],
			"after": ["S"]
		},
		{
			"before": ["s"],
			"after": ["c", "l"]
		},
		{
			"before": ["S"],
			"after": ["^", "C"]
		}]
}

如果现在只是在normal模式下配置完成了对应的配置,但是要知道vim还有可视化模式(visual mode)和处于操作等待(opratorPending)的状态(输入d或者c之后就会处于这个状态),对应这两个状态下也需要进行一定的配置:

  • 在处于操作等待(opratorPending)下sneak是使用z来进行操作的,但是现在我们需要的效果是df + 两个字符组合(该效果为删除匹配到的范围)的这种操作,所以需要配置在该状态下按下fF分别对应的按键为zZ
  • 在可视化模式下,F无法使用,所以之需要配置f映射为s即可。
  • 这两个配置因为也要防止绑定按键后递归调用的问题,所以需要分别在"vim.visualModeKeyBindingsNonRecursive""vim.operatorPendingModeKeyBindingsNonRecursive"进行配置,下面是上述选项的具体配置:
{
	...,
	"vim.visualModeKeyBindingsNonRecursive": [
		{
			"before": ["f"],
			"after": ["s"]
		}
	],
	"vim.operatorPendingModeKeyBindingsNonRecursive": [
		{
			"before": ["f"],
			"after": ["z"]
		},
		{
			"before": ["F"],
			"after": ["Z"]
		}
	],
}

参考文献