13 KiB
vim
Buffers,Windows,Tabs
在现代的文本编辑器,通常会存在windows和tabs两种抽象。但是,vim和常用的文本编辑器不同,其抽象组成如下:
- windows
- tabs
- buffers
Buffer
buffer是一个内存空间,可以向buffer写文本或编辑文本。当通过vim打开一个文件后,文件的内容就被关联到buffer中,当打开3个文件,就存在3个buffer。
可以通过如下命令打开多个buffer:
vim file1.txt file2.txt
每当通过vim打开一个新文件,都会为vim创建一个buffer。
如果想要在多个buffer之间进行切换,可以使用如下方式。
:bnext :bprevious
通过:bnext和:bprevious命令,其支持在多个buffer之间进行切换,切换到前一个/后一个buffer。
:buffer {filename}
通过:buffer {filename}的方式,可以切换到{filename}关联的buffer。
filename可以通过
tab进行自动补全。
:buffer {n}
通过:buffer {n}的形式,可以通过数字来进行buffer的跳转。
ctrl + ^
通过ctrl + ^的快捷键组合能够跳转到上次编辑的buffer。
如果想要对查看所有buffer,可以通过如下方式:
:ls:files:buffers
:bdelete
一旦vim创建了buffer,其将会存在于buffer list中。如果想要移除buffer list中的buffer,可以通过:bdelete的方式移除,其支持接收buffer number和file name,示例如下:
:bdelete 1
:bdelete file1.txt
exit vim with all buffers closed
如果存在多个buffer,想要关闭所有buffers,可以使用如下方式:
:qall
关闭所有buffer,并且不保存修改
:qall!
保存并关闭所有buffer
:wqall
:e {filepath}
在当前存在buffer list的同时,还想打开新的文件,可以通过:e {filepath}的命令来实现
:e ~/f2.txt
windows
window是一个buffer的viewport。和目前主流的编辑器类似,vim同样支持打开多个windows,在界面同时展示多个buffer的内容。
:split {filename}
在当前已经存在buffer被展示到window的情况下,如果想要同时展示多个window,可以使用:split {filename},示例如下:
# 打开一个文件
vim f1
# 打开f1后,此时目前只有一个buffer和一个window,如果此时想要再打开一个window
# 打开f2并展示到f1 window的上部分
:split f2
# 执行完上述命令后,vim被分割为两个window,上面为f2,下面为f1
切换窗口
如果想要在多个window之间切换焦点,可以使用如下快捷键(仅在normal模式下)
ctrl + w + h:切换到左侧窗口ctrl + w + l:切换到右侧窗口ctrl + w + j:切换到下侧窗口ctrl + w + k:切换到上侧窗口
之后,可以运行如下命令
:vsplit f3
运行之后,vim会展示3个窗口,上半部分展示f3, f2两个窗口,下半部分展示f1窗口。
关闭窗口
如果想要关闭当前窗口,可以调用ctrl + w + c快捷键,或是通过:q命令。即使关闭window,关闭文件的buffer仍然存在于buffers中。
split窗口快捷键
ctrl + w + s: 水平方向针对当前buffer打开一个windowctrl + w + v: 垂直方向对当前buffer打开一个windowctrl + w + c:关闭当前windowctrl + w + o:关闭其他window,仅保留当前window
窗口相关命令行
:vsplit {filename}:split {filename}:new {filename}
tabs
vim除了支持同时展示多个windows之外,也同样支持tab。在vim中,tab和浏览器/现代编辑器类似,tab为对window的布局(垂直/水平多个window的布局)。
在vim中,tab并不表示打开的文件,即使当tab被关闭,文件的buffer仍然会存在。
tab的常用命令如下
:tabnew
:tabnew {filename}用于在新tab中打开文件,使用示例如下:
:tabnew file1.txt
:tabnew并不实际依托于buffer存在,可以直接调用:tabnew先创建一个tab,然后在新tab中调用:e打开文件进行编辑。
:tabnew
:e file2.txt
:tabclose
:tabclose命令用于关闭当前tab
:tabnext
:tabnext命令用于切换到下个tab
:tabprevious
:tabprevious命令用于切换到前一个tab
:tablast
:tablast用于切换到最后一个tab
:tabfirst
:tabfirst用于切换到第一个tab
gt
除了通过命令外,还可以通过快捷键gt切换到下一个tab页面。
gT
快捷键gT则是可以切换到前一个tab页面。
{n}gt
{n}gt支持通过tab序号快速切换tab,例如3gt可以切换到第三个tab。
vim -p
在进入vim时,如果想打开多个tab,可以添加-p选项,示例如下
vim -p f1.txt f2.txt f3.txt
window和buffer的组合
vim支持同时打开多个window,并且,每一个window都包含了一个buffer。可以通过ctrl + w + {dir}快捷键的方式在window之间切换,但是,对于当前的焦点window,仍可以通过 :buffer {filename} 的方式来切换当前焦点window对应的buffer。
例如,当前存在三个windows,w1, w2, w3,其打开文件分别为f1, f2, f3,可以切换到w2 window,并且调用:b f3命令,此时会将当前的w2的buffer切换到f3,此时,w1, w2, w3对应的打开文件则变成了f1, f3, f3。
通常,在图形操作系统中使用vim,其
terminal(如windows系的Windows Terminal和Linux系的KConsole,其终端本身就支持tab功能,此时可以无需使用vim本身的tab功能。但是,在非图形化系统(如通过ssh访问服务器),此时在服务端未提供图形支持的前提下,可以使用vim tab来实现多tab打开。
Registers
Register Types
vim中拥有如下10中register类型:
unnamed register:""numbered register:"0-9small delete register:"-named register:"a-zread only register:":,".,"%alternate file register:"#expression register:"=selection register:"*,"+black hole register:"_last search pattern register:"/
register operators
在使用register之前,必须通过操作向register中存储值。可以通过如下操作向register中存值:
y:yank(copy)c:delete text and start isnert moded:delete text
通常,在操作删除文本时,都会将文本保存在register中。
为了粘贴存储在register中的文本,可以使用如下方式:
p: 在cursor之后粘贴文本内容P: 在cursor之前粘贴文本内容
p和P都接收一个count和register symbol作为参数,例如,
10p: 将register中的文本粘贴10次"ap: 从register a中粘贴文本10"ap:从register a中获取文本并粘贴10次
Calling register from insert mode
当处于insert mode,并且需要从指定register中粘贴时,可以使用如下方式:
Ctrl + R a:其会将register a中的内容粘贴到cursor之后
unnamed register
在unnamed register中,存储着最后一次delete, yank, change的内容,可以通过""p。
如果做了多次yank/delete/change操作,那么新操作的text会自动覆盖旧操作的text。
默认情况下,p/P命令会默认关联unnamed register。
numbered register
numbered register会自动按照升序对其自身进行填充,存在两种不同类型的numbered register,
yanked register:0numbered register 1-9:1-9
yanked register
如果通过yy进行了整行复制,那么vim实际会将文本保存在两个regiser中:
- unnamed register:通过
p粘贴 - yanked register:通过
"0p粘贴
当之后再次yank一个不同text时,vim会对yanked register和unnamed register都随之变化。
除了yank之外的操作都不会被存储到register 0。故而,即使yank操作后发生了delete/change操作,register 0中的内容也不会被修改。
当处于insert mode时,可以通过ctrl + R 0来快速粘贴register 0中的内容。
non-zero numbered register
当change/delete长度超过1行的文本时,该文本将会被存储在non-zero numbered register中,按照most-recent的顺序存储在1-9寄存器中。
其中,
长度超过一行可以指文本未包含完整的某一行,但是出现跨行的场景,示例如下111 222 # 选中范围为第一行末尾的`11`和第二行开头的`2`,此时对选中内容 进行change/delete,选中文本仍然会包含在non-zero register中但是,如果选中内容位于同一行,并且不包含完整行,那么change/delete内容不会填充到non-zero numbered register中
例如,
111
222
上述对第一行111内容进行删除后,111文本将会被包含在register 1中。
再次针对222调用dd删除后,non-zero numbered registers内容如下:
register 1: 包含内容为222register 2: 包含内容为111
.
当使用"1p粘贴完register 1中的内容时,直接多次调用.其会自动粘贴"2,"3,"4寄存器中的内容。
如果从"5p开始粘贴,调用.后,其会自动粘贴"6p。
对于small deletion(例如dw或cw),其并不会被存储到numbered register中,而是会被存储到small deletion register("-)中。
small deletion register
对于小于一行的deletion或change,其并不会被存储在numbered registers中,而是会被存储在small deletion register("-)中
例如,
diwciw
named register
named register是vim中最通用的register,其可以针对yank/change/delete的text进行存储,其范围为a-z。
named register和前面介绍的registers不同,named register并不会被自动存储,而是需要手动指定存储的named register。
例如,需要将文本存储到register a,需要执行如下命令"ayiw:
- 其中
"a告知vim将内容存储到"a寄存器中 yiw用于复制word
如果需要获取register a中的内容,可以通过"ap命令。
append to named register
如果,想要对named register中的内容进行新增而不是完全替换,可以使用如下方式:
- register a中已经存在内容“hello”
- 想要添加“world”到register a中,可以调用
"Ayiw
此时,register a中的内容将会变为helloworld,而不是被替换为world
read-only register
vim中含有3个read-only register:
.:存储了最后插入的文本(处于insert modez最后入的内容)::存储了上次执行的命令%:存储了当前文件名称(绝对路径)
alternate file register
alternate file代表最后打开的文件,alternate file register代表最后打开文件的名称。
expression register
vim中拥有expression register,并可以通过"=来执行表达式。
例如,执行表达式1 + 1,可以进行如下操作"=1+1<Enter>p
- 其会执行
1+1的运算 p则是会拿到运算结果
在insert mode下,则是可以通过Ctrl-r =1+1来执行表达式。
expression register还支持获取其他寄存器的值,示例如下
"=@a<Enter>p可以获取register a的值。
在insert mode下,Ctrl-r =@a也可以获取register a的值。
selection register
通过selection register,可以从外系统中粘贴文本。
vim中拥有两种selection register:*, +。当在vim之外的程序(例如chrome browser)中复制文本时,并不能直接通过p在vim中粘贴。但是,vim的"*和"+会和系统的剪切板相关联,可以通过"+p和"*p来粘贴外部程序中复制的文本。
同样的,如果通过"+yiw和"*yiw来复制内容,那么复制的内容可以在外部程序中进行粘贴。(需要启用+clipboard选项)
如果想要直接通过p来粘贴外部程序中复制的内容,可以通过在.vimrc中添加如下配置:
set clipboard=unnamed
black hole register
每次当对文本进行delete/change时,文本都会自动保存在vim的寄存器中。如果,此次操作不想保存任何内容到寄存器中,可以使用black hole register "_。
例如,想要删除行但是不保存到任何寄存器中,可以使用"_dd。
black hole register类似于/dev/null
last search register
如果想要对最后搜索的内容(通过/或?进行搜索)进行粘贴,可以使用last search register("/)。
如果想要对最后搜索的内容进行粘贴,可以使用"/p,insert mode模式下可以使用Ctrl-r /。