Files
rikako-note/vim/vim.md
2025-08-03 21:54:15 +08:00

15 KiB
Raw Permalink Blame History

vim

Buffers,Windows,Tabs

在现代的文本编辑器,通常会存在windowstabs两种抽象。但是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打开一个window
  • ctrl + w + v: 垂直方向对当前buffer打开一个window
  • ctrl + w + c关闭当前window
  • ctrl + 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

例如当前存在三个windowsw1, w2, w3,其打开文件分别为f1, f2, f3,可以切换到w2 window并且调用:b f3命令,此时会将当前的w2的buffer切换到f3,此时,w1, w2, w3对应的打开文件则变成了f1, f3, f3

通常在图形操作系统中使用vimterminal(如windows系的Windows TerminalLinux系的KConsole,其终端本身就支持tab功能此时可以无需使用vim本身的tab功能。

但是在非图形化系统如通过ssh访问服务器此时在服务端未提供图形支持的前提下可以使用vim tab来实现多tab打开。

Registers

Register Types

vim中拥有如下10中register类型

  • unnamed register: ""
  • numbered register: "0-9
  • small delete register: "-
  • named register: "a-z
  • read 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 mode
  • d: delete text

通常在操作删除文本时都会将文本保存在register中。

为了粘贴存储在register中的文本可以使用如下方式

  • p: 在cursor之后粘贴文本内容
  • P: 在cursor之前粘贴文本内容

pP都接收一个countregister 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: 0
  • numbered 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: 包含内容为222
  • register 2 包含内容为111
.

当使用"1p粘贴完register 1中的内容时直接多次调用.其会自动粘贴"2"3"4寄存器中的内容。

如果从"5p开始粘贴,调用.后,其会自动粘贴"6p

对于small deletion(例如dwcw其并不会被存储到numbered register中而是会被存储到small deletion register"-)中。

small deletion register

对于小于一行的deletion或change其并不会被存储在numbered registers中而是会被存储在small deletion register("-)中

例如,

  • diw
  • ciw

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("/)。

如果想要对最后搜索的内容进行粘贴,可以使用"/pinsert mode模式下可以使用Ctrl-r /