vim 从嫌弃到依赖(10)——缓冲区列表
之前的一系列文章主要介绍了vim文本相关的操作,并且也介绍了vim的几种模式。通过前面的内容,相信各位小伙伴们已经对vim有了一个基本的了解,同时也能够使用vim快速编辑文本,从这篇开始,我们将要介绍vim针对多个文件的操作,例如如何在多个文件中查找、跳转等等方式方法。让我们先从vim如何管理打开的多个文件开始吧
缓冲区列表简介
有过编程经验的小伙伴应该知道,将文件从磁盘读取到内存中时,都会事先分配一块内存缓冲区用来保存读取到的文件内容,vim同样是这么干的。
vim在读取文件时会通过内存映射的方式,将磁盘中的内容映射到一块内存的缓冲中。vim可以打开多个文件,每个文件独立的占有一个缓冲区。为了管理这些打开的文件,vim中有了缓冲区列表的概念,同时也提供了一些配套的命令来操作缓冲区列表。
假设现在在某个目录中有多个文件,我们使用vim同时打开,例如使用vim init.lua test.py
。我们发现vim默认只展示一个文件中的内容,但是它打开了两个文件,现在有两个以文件名命名的缓冲区。通过命令:ls
查看当前打开的缓冲区。
:ls
命令显示的内容每一行代表一个缓冲区的信息。它显示的信息如下:
:ls
1 %a ".\test.py" line 1
2 ".\init.lua" line 0
第一列的数字代表缓冲区的编号,该编号由vim随机指定,第二列的%a
代表缓冲区为激活的缓冲区(active)当前窗口显示的内容为激活缓冲区的内容。第三列则是缓冲区的名称,一般vim会将文件名作为缓冲区的名称
我们可以使用:bnext
按:ls
的显示顺序,显示下一个缓冲区,:bprev
显示上一个缓冲区。:blast
显示最后一个缓冲区,:bfirst
显示第一个缓冲区。
在切换过缓冲区之后再次执行:ls
之后发现此时显示的内容已有一些变化。现在显示的内容如下:
:ls
1 #h ".\test.py" line 1
2 %a ".\init.lua" line 1
此时我们发现除了%a
代表当前处于激活状态的缓冲区外,另外一个缓冲区的前面多了个#h
,#
代表上一次处于激活状态的缓冲区,我们可以使用<ctrl + ^>
来切换到上次处于激活状态的缓冲区。而h
则代表隐藏缓冲区,当一个缓冲区由激活状态变为非激活状态的时候,vim会将其标记为隐藏缓冲区。
除了按照顺序显示缓冲区,还可以通过缓冲区名称或者序号来指定显示某个缓冲区。例如使用:buffer 1
来显示编号为1的缓冲区。
还可以更直观的使用buffer {bufname}
来显示指定缓冲区,其中{bufname}
代表的是缓冲区的名称,例如:buffer init.lua
看到这里,各位小伙伴肯定会觉得不管使用:bnext
之类的命令切换还是使用:buffer
来切换缓冲区,都需要输入这么长的命令,显得既繁琐又低效,那么有没有什么办法来解决这个问题呢?答案是通过快捷键映射。后面介绍我自己的配置时会介绍如何将其映射到快捷键上
如果要删除某个缓冲区可以使用:bdelete {bufname}
。该命令支持前面几篇文章中提到的范围操作,即:nstart, nend bdelete
来删除编号nstart
到 nend
的所有缓冲区。缓冲区缓冲区编号是vim自己分配的,要通过编号删除得执行:ls
命令,并且有时候删除了后续可能还要再次打开,再退一步说,如果暂时不想用它,vim也只显示后面打开的缓冲区,我们使用这个场景很少,除非有充足的理由,否则不会去删除它。
缓冲区列表参数
在实际开发项目的时候,我们会打开很多文件,如果仅仅使用上述介绍的命令会发现在管理上有诸多不便。例如项目中有ui文件、有python代码、也有c代码、甚至还有java代码,我现在要找一个名为showUserName
的函数,而且我很清楚我要的ui中的内容,但是在python、c或者java中都有类似的函数名,采用全局搜索肯定都搜出来了,但是我只想在ui文件中搜索。这就涉及到项目文件的模块化。使用上述命令肯定无法满足模块化的要求。这个工作可以使用列表参数来完成。
假设现在目录有3个python
文件,5个cpp
文件,还有2个txt
文件,我们按照文件类型进行分组打开,先打开cpp
文件
vim *.cpp
使用 :args
显示参数列表。
它输出的内容如下:
[a.cpp] b.cpp c.cpp d.cpp e.cpp
该列表记录了通过命令行另vim打开的所有文件缓冲区。其中使用[]
包裹起来的是当前处于激活状态也就是当前窗口显示的的缓冲。注意请不要被这个名字迷惑了,它并不是传递给vim的参数,而是作为参数传递给vim的文件的列表。也就是这条命令所打开的文件的列表。本质上仍然是一个缓冲区列表
除了使用:args
查看参数列表,也可以在:args
命令后添加缓冲区名称,例如:args init.lua
这样就将一个新的文件纳入之前的缓冲区列表中进行管理。后续可以将需要统一管理的缓冲区使用该命令添加进来,除了使用详细的文件名一个个添加之外,vim也支持使用通配符来进行匹配。甚至也可以在后面添加shell命令,以shell命令的输出作为缓冲区列表的参数,添加到参数列表,它的形式为
:args `cmd`
上述事例中,我们通过args
来将ls
输出的结果作为参数列表。再通过:ls
命令查看一下当前缓冲区列表,发现之前打开的仍然存在,只是我们将test.py
和 init.lua
这两个文件形成一组作为缓冲区的参数列表。
当我们指定好了一组缓冲区列表参数之后,可以使用:next
、 :prev
、first
、last
在这组缓冲区列表中进行切换。
:args
命令本身也支持使用通配符来将所有匹配的文件名设置为缓冲区列表参数,例如:args *.py
将当前目录中所有py文件加入,或者使用:args **/*.py
来将当前目录下所有子目录中的py文件加入。一般来说使用shell命令或者使用通配符的方式居多,但是也有直接使用文件名的情况出现
后面我们可以根据参数列表,对列表中所有的缓冲区进行统一的修改或者在这些缓冲区中进行跳转之类的操作,当然这些等我们介绍到了对应的基础知识后再进行演示。
vim退出
好像现在才讲到退出操作已经有点晚了,很多用上vim的小伙伴肯定也搜到如何退出了。不知道怎么退出的,应该已经退坑了。但是我在这里并不介绍使用何种命令来退出。而是介绍vim如何处理未同步到磁盘上的缓冲区的。
我们随便打开多个文件,在任意一个或者多个缓冲区中执行o
或者其他能另其修改的命令。然后执行切换缓冲区的命令,例如:bnext
之类的,切换之后再次执行:ls
1 #h + ".\init.lua" line 2
2 %a ".\test.py" line 1
我们发现在之前的基础之上,多了一个 +
它代表着这个缓冲区上的修改并未同步到磁盘文件中。此时如果执行:q
进行退出的话,会提示当前有缓冲区未同步到文件中,并且跳转到未同步的缓冲区。我们可以执行:w
来写入将缓冲区内容磁盘,也可以使用:q!
来忽略该缓冲区的修改,或者使用:edit!
来强行的从磁盘读取内容并覆盖本次修改。这个时候vim将会切换到下一个未保存的缓冲区。如果嫌每次都这样比较麻烦,可以执行:qall!
忽略所有未修改的缓冲区并退出,或者使用:wall
来写入所有修改。
总结
本文到此就结束了,最后再来总结一下该文中使用到的命令和快捷键:
- bnext: 切换到缓冲区列表中的下一个缓冲区
- bprev: 切换到缓冲区列表中的下一个缓冲区
- blast: 切换到缓冲区列表中的最后一个缓冲区
- bfirst: 切换到缓冲区列表中的第一个缓冲区
- <Ctrl+^>: 在上一个被激活的缓冲区和当前被激活的缓冲区之间进行轮换
- args: 显示当前缓冲区列表参数。后面也可以跟上文件名、shell命令和通配符,设置对应的缓冲区列表参数
- next: 切换到缓冲区列表参数中的下一个缓冲区
- prev: 切换到缓冲区列表参数中的上一个缓冲区
- last: 切换到缓冲区列表参数中的最后一个缓冲区
- first: 切换到缓冲区列表参数中的第一个缓冲区