本来这篇文章的标题是 《speak in vim,speed in vim》。用了英语中压头韵(alliteration or initial rythme)的技巧,多高大上啊。但是这样标题太过隐晦,就改成现在的这个俗气的标题,毕竟公众号阅读量本来就低,不敢玩花的。
这篇文章你将学习和复习到以下单词词组
* yank
* change
* inner
* around
* text object
* motion
* shortcut
引子
在聊 vim
编辑器之前,我们先聊聊一般你会在编辑器里面做什么。
• 移动光标:方向键、home
键、end
键、pageUp
、pageDown
等等
•输入,大量地输入(我就是高级打字员)
•大量地使用 快捷键 (shortcut)
前两个动作在不同的编辑器里面都差不多,但是最后的 快捷键 ,不同的编辑器就大不相同。很多开发者不愿意换编辑器的大部分原因是已经非常地熟悉目前使用的编辑器的快捷键。如果仅仅从快捷键使用的角度来比较编辑器的话,更多快捷键则对应更多丰富文本编辑动作,那就会更有优势。
那么再想另外一个问题,在编辑器中编辑的动作是无穷的,但是键盘上能够组合出来的快捷键却是有限的。所以基于快捷键的方式来编辑文本的编辑器的能力上限非常地明显就是编辑器快捷键数量的上限了。
那如何解决这个问题呢?那我们就必须跳脱出编辑动作和快捷键一一对应的思维方式。vim
是怎么解决的呢?vim
设计了一套“语言”体系来描述你的编辑动作。既然是一种语言,她能表达的东西有很高的上限。想想日常中几乎没有汉语描述不清楚的事情。
首先要让vim
的编辑语言有一个执行的环境,vim
和其他的编辑器最大的不同就是他有模式(mode
),大家熟悉的normal mode
和 insert mode
。insert mode
和大多的编辑器一样,给你直接输入;而normal mode
就是vim
用来执行编辑命令的地方了。既然它叫normal mode
,那就是正常(normal
)情况下你最好待在 normal mode
下。因为多待在normal mode
下你才能更多地使用vim
的编辑语言快捷地完成操作。
语法课???
既然说到了语言,就要说说vim
的语言结构。和自然语言有“主谓宾”的语言元素结构,vim
也一样。vim
的语言结构非常地简单,就是:
“动词 + 宾语”
动词
先说这个"动词",它其实就是 vim
中的“命令”
命令就是我们常常在编辑器里面做的动作,常用的命令有下面几个 d
,c
, v
和 y
。
• 删除文字 delete, 就是 d
命令• 改变文字 change,就是 c
命令• 选中文字,就不是select了,在vim
选中文字就进入visual mode
,所以用的命令是 v
• 复制文字,不是copy
,vim
用的单词是 yank
,所以命令是 y
掌握这个四个基本的编辑动作之后在vim
就能完成大部分的编辑操作了。
宾语 motion
而宾语两个种类,第一类就 motion。
motion 在vim
含义就是能够让光标移动的命令,比如大家入门时学的hjkl
就是motion 命令。 那在vim
的语言结构中,motion 宾语就是指光标移动所扫过的区域的内容。
举个例子(我知道你们都知道 x 命令),比如要删除当前光标下的字符,我可以在normal mode下输入操作 dl
,d命令告诉vim
我要开始删除文字了,那要删除的范围就是光标移动一格的内容,那就是当前光标下的字符了。
motion 作为vim
中重要的一类宾语,所以开始学vim
之后我们就学会如何高效移动光标,比如很多教程一开始让你先不要用方向键,先熟悉hjkl
,然后就希望你更大幅度地移动光标使用 w
(光标移动到一个单词开头),e
(光标移动到单词结尾)命令, 再后来希望你更加准确的移动光标,使用 f
(find 移动卡光标到查找的字符) 和 t
(till 移动光标到查找到的字符之前)命令;比如 dw
来删除一个单词,使用 dt@
可以删除到(但不包括)@字母。这样的编辑效率明显比使用方向键或者 ctrl+方向键高很多。
宾语 text object
了解完 motion,我们再说下另外一类的宾语:text object 文本对象。有了 motion 为何还需要文本对象呢?首先 motion 只能往一个方向移动,就上下左右 4 个方向只能选一个;如果要向上删两行又往下删三行文字,基于 motion 的命令是做不到的。为了解决此类问题就有了 text object 的概念。
先来举两个例子,比如你的光标停在函数体的某一行,你想删除整个函数体({ }包围的区域)的实现。
function demo(){
console.log('demo here')
| <- 光标在这里
console.log('demo there')
}
你就可以使用 di{
, 上面的函数直接变成
function demo(){
}
首先 d
就是删除的命令, i{
就是一个 text object,它表示的是一个有意义的文本范围,即在花括号中的内容,inner {
。
如果你想连花括号都一起删除的话,那就用 a{
这个text object。 a
就是 around 的意思。
一个 text objcet 需要使用 a
或者 i
来指定需要编辑的范围;这个范围常有的是 w(word), 各种括号之间的区域,引号之间的区域,还有标签(tag)之间的区域。
比如你的光标在一个单词中间,你想修改整个单词就可以使用命令 ciw
那各种括号的情况就是上面 di{
的扩展,比如di[
和 di(
而标签 tag 就非常适合前端开发者使用,下面情况只要使用dit
(delete inner tag),就能把 div 标签中的内容全部删除变成 <div></div>
; 如果你连 div 标签都要一起删除的话就直接使用 dat
( delete around tag)。
<div>
| <--光标在这里
<span>1</span>
<span>2</span>
</div>
组织语言
了解vim
的语言的基本构成之后, 我们就会使用这些指令来高效的编辑文本。但是单条命令的能力毕竟有限。有时候我们就需要用组合的方式来提高效率。
比如我们要删除2个单词,就可以使用 2dw
来让 vim 执行两次。更重要的是我们直接可以使用多个命令有机的组合一套操作高效的编辑。
假设我们需要对已经格式化过的JSON 对象的值字符串值都变成空字符串,
"husky": "^7.0.4",
使用命令组合
03f"di"
就会得到
"husky": "",
解释下这条命令就是
0
: 表示让光标回到行首
3f"
: 表示找到第三个引号
di"
: 表示把第三个引号中的内容全部删除清空
当然有小伙伴会说03f"di"
都敲了多少下按键了啊,这能说效率高;其实在vim
可以把这样的组合动作录制成一个宏(Macro),然后在需要的地方执行下宏就可以。关于宏我会写下一篇文章介绍。
完
掌握的vim
的语言之后,你就像是学会了一门新的外语(对于不懂 vim 语言的人 03f"di" 这串东西就是外语:),不仅仅能看懂那些 vim
高手们做的映射(map),还能应用这门外语高效描述编辑的动作,提升编辑效率。
所以码农英语课堂不仅要教英语,还要教 vim language 了。今天的分享就到这里,希望能够帮助到想学
vim
和对 vim
感兴趣的粉丝;如果帮助到你记得转发哦。