Vim实用技巧-2

背景

继昨天vim实用技巧-1以后,今天看的还是vim模式下光标的移动、选择、内容的快捷修改,毕竟在vim中,快速定位和编辑修改是其操作的核心。

内容

光标移动

vim中,将行分为实际行和屏幕行两种,hjkl操作的是实际行,这对于实际使用中操作屏幕换行存在问题,为此vim也提供了操作屏幕行的方式

1
2
3
4
5
6
# 操作屏幕行的以g开头
gk --> 屏幕行的上一行
gj --> 屏幕行的下一行
g0 --> 屏幕行的行首
g$ --> 屏幕行的行尾
g^ --> 屏幕行的第一个非空字符

在基础篇中,我们常用的是w,b,e这样操作单词的跳跃方式,抑或是W、B、E这样操作字符串的跳跃方式,你会发现其本身同样,对于e而言也有会跳的方案

1
2
ge --> 回跳到上一个单词的末尾
gE --> 回跳到上一个字符串的末尾

同样,在同一行中,vim还提供了另一种跳转的方式,它更加的灵活:f/F、t/T

1
2
3
4
5
6
7
# 直接跳转到单个字符的位置,直达
f{char} --> 向后跳转到查询的字符处
F{char} --> 向前跳转到查询的字符处

# 跳转到单个字符前的一个字符的位置,靠近,但是不抵达
t{char} --> 向后跳转到查询字符的前一个字符处
T{char} --> 向前跳转到查询字符的前一个字符处

而如果我们开始越过行的界限,迈向整个篇幅的时候,此时上述的方法就会渐渐失效,而vim则为我们提供了另一种快捷查询的方式

1
2
# 查询符合条件的位置字符串,并跳转至该位置
/{string}

以上的方式,固然给我们光标的移动带来了极大的便利,但是却还不是其光辉的最顶峰。当它们开始与c/x/y/d/s等指令相结合的时候,就会绽放出异乎寻常的光彩

1
2
3
4
5
# 复制当前光标到.的内容
yt.

# 删除当前光标到下一个get匹配位置之间的所有内容,不包括匹配的内容
d/get

尝试之下,你就会发现待决模式中,这些跳转指令相互配合的巨大作用。但与接下来的文本对象相比,上面的方式则显得不是很智能化。vim中提供了针对成对标点符号)、>、{、[、'、"快捷选中的方式:文本对象,组成文本对象的关键词是i、ai表示选中内部,不包括边框,而a表示选中内部和边框所有的内容。不过文本对象本身并不是指令,它仍然需要搭配x/y/d/c/v等待决指令共同发挥作用。

1
2
3
4
5
6
7
# 选中""中的内容,则将光标移动到双引号中任意一个内容中
yi"

# 选中<>的内容,并且将<>本身也选中
ya>

# 针对其他的符号也是同样的操作

当我们对前端代码内容进行操作的时候,会明显的发现这种方案的局限性,它无法选中成对标签的内容。为此vim还提供了一个指令:t,结合文本对象则可以直接选中xml格式标签的内容

1
2
3
4
5
# 选中<a href="#">shuai</a>中的shuai
vit

# 选中<a href="#">shuai</a>
vat

搭配上述的内容后,你也就会发现文本对象巨大的魔力,但这也只是其一部分,它依然可以与w、b、e等指令协同合作,从而增强x/c/y/d/v等待决指令的能力

1
2
3
4
5
6
7
8
9
10
11
12
13
# 删除光标所在的单词和其后的一个空格
daw

# 修改光标所在的单词
ciw

# 删除光标所在的连贯一句及其后的一个空格
das

# 删除光标所在的段落和一个空行
dap

# 此外还有与字符串相关的指令相结合的没有举出,可一试

通过操作以后,你也可以发现x、d常与a搭配,而c、y常用i搭配,v则视情况而选。

至此,可视区域内的光标移动方案则基本阐述清楚,但还有更广阔的不可视领域的移动方案呢?vim提供了标记指令,用于给用户提供文档中的任意路标,让用户在任何时刻都能随时回到路标处。

1
2
3
4
5
# 路标取值:a-z、A-Z
ma --> 在当前光标处添加a标记

# 返回标记处
'a

上述是vim留给用户的操作空间,这是其高明之处,但同时,vim还针对用户的每次修改、跳转、区域选中都会自动追加标记,便于用户的及时回归,这又是其人性化的体现之处

1
2
3
4
5
6
7
8
9
''  --> 回到上次跳转的位置
'. --> 回到上次修改的位置
'^ --> 回到上次插入的位置

# 下面的暂且记录,还不知道使用频率怎么样
'[ --> 回到上次修改、复制的起始位置
'] --> 回到上次修改、复制的终止位置
'< --> 回到上次选中区域的起始位置
'> --> 回到上次选中区域的终止位置

寄存器

vim本身的x、c、y、d、s会将操作的对象复制进vim自身的寄存器中,这个寄存器本身是不与系统的剪贴板相重合的,而vim的寄存器分的种类挺多的,此处只记录了无名寄存器、有号寄存器、黑洞寄存器、复制寄存器。

无名寄存器是操作的对象默认填充的,它在寄存器中对应的位置为"",如果打印出来则""p,但我们一般不用这么麻烦,直接p即可。同时操作的指令如果没有指定有序寄存器,则新内容会冲掉无名寄存器中的内容。

而无名寄存器中最为特殊的一个是y指令,vim为其预留了一个单独的寄存器:复制寄存器

1
2
3
4
5
6
7
8
# 读取复制寄存器的内容
"0p

# 在插入模式下,或许你会觉得其操作不是很方便,vim也提供了快捷指令
C-r 0

# 与之相对应的在插入模式下,访问无名寄存器的内容
C-r "

有号寄存器是针对多内容无法用一个寄存器存放时,可以通过将不同的内容存放在不同的寄存器中,访问时通过对应的号进行访问即可

1
2
3
4
5
# 创建一个有号寄存器,其编号为a
"ayiw

# 打印出a编号中的内容
"ap

对于有号寄存器而言,上述的编号用小写字母编号,此时如果又重新复制新的内容进入a寄存器,则会覆盖其寄存器的内容,如果想将新的内容追加在原有寄存器的后面呢,可以使用对应的大写字母A。

1
2
# 会将新的单词追加到a寄存器的尾部
"Ayiw

对于黑洞寄存器,本质就是将内容丢弃不要了,使其不占用任何的寄存器空间。

1
2
# 黑洞寄存器以_为标志
"_diw --> 删除当前光标下的单词

说到此,还有一个非常重要的地方,那就是vim本身与系统键贴板之间的交互,寻常情况下我们可以在编辑模式中利用系统的复制/粘贴,但这不是很好,会造成缩进上的错误。其实vim本身也提供了将内容复制到剪贴板上的功能

1
2
3
4
5
6
7
8
# 以+为标志,
"+diw --> 将光标下的内容剪切至系统的剪贴板

# 将键贴板的内容复制到vim作业中
"+p

# 可能你也察觉到将键贴板的内容复制到vim作业中的不便之处,为此vim也提供了简便方案
C-r +

对于寄存器而言,一般来讲,复制的内容会通过命令进行复制(因为别无二法),而对于将寄存器的内容回写至vim作业中,则一般通过C-r 寄存器标志,这样更加的便捷一些。