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

392 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

- [vim](#vim)
- [Buffers,Windows,Tabs](#bufferswindowstabs)
- [Buffer](#buffer)
- [`:bnext` `:bprevious`](#bnext-bprevious)
- [`:buffer {filename}`](#buffer-filename)
- [`:buffer {n}`](#buffer-n)
- [`ctrl + ^`](#ctrl--)
- [`:bdelete`](#bdelete)
- [exit vim with all buffers closed](#exit-vim-with-all-buffers-closed)
- [`:e {filepath}`](#e-filepath)
- [windows](#windows)
- [`:split {filename}`](#split-filename)
- [切换窗口](#切换窗口)
- [关闭窗口](#关闭窗口)
- [split窗口快捷键](#split窗口快捷键)
- [窗口相关命令行](#窗口相关命令行)
- [tabs](#tabs)
- [`:tabnew`](#tabnew)
- [`:tabclose`](#tabclose)
- [`:tabnext`](#tabnext)
- [`:tabprevious`](#tabprevious)
- [`:tablast`](#tablast)
- [`:tabfirst`](#tabfirst)
- [`gt`](#gt)
- [`gT`](#gt-1)
- [`{n}gt`](#ngt)
- [`vim -p`](#vim--p)
- [window和buffer的组合](#window和buffer的组合)
- [Registers](#registers)
- [Register Types](#register-types)
- [register operators](#register-operators)
- [Calling register from insert mode](#calling-register-from-insert-mode)
- [unnamed register](#unnamed-register)
- [numbered register](#numbered-register)
- [yanked register](#yanked-register)
- [non-zero numbered register](#non-zero-numbered-register)
- [`.`](#)
- [small deletion register](#small-deletion-register)
- [named register](#named-register)
- [append to named register](#append-to-named-register)
- [read-only register](#read-only-register)
- [alternate file register](#alternate-file-register)
- [expression register](#expression-register)
- [selection register](#selection-register)
- [black hole register](#black-hole-register)
- [last search register](#last-search-register)
# vim
## Buffers,Windows,Tabs
在现代的文本编辑器,通常会存在`windows``tabs`两种抽象。但是vim和常用的文本编辑器不同其抽象组成如下
- windows
- tabs
- buffers
### Buffer
buffer是一个内存空间可以向buffer`写文本``编辑文本`。当通过vim打开一个文件后文件的内容就被关联到buffer中当打开3个文件就存在3个buffer。
可以通过如下命令打开多个buffer
```bash
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示例如下
```bash
:bdelete 1
```
```bash
:bdelete file1.txt
```
#### exit vim with all buffers closed
如果存在多个buffer想要关闭所有buffers可以使用如下方式
```bash
:qall
```
关闭所有buffer并且不保存修改
```bash
:qall!
```
保存并关闭所有buffer
```bash
:wqall
```
#### `:e {filepath}`
在当前存在buffer list的同时还想打开新的文件可以通过`:e {filepath}`的命令来实现
```bash
:e ~/f2.txt
```
### windows
window是一个buffer的viewport。和目前主流的编辑器类似vim同样支持打开多个windows在界面同时展示多个buffer的内容。
#### `:split {filename}`
在当前已经存在buffer被展示到window的情况下如果想要同时展示多个window可以使用`:split {filename}`,示例如下:
```bash
# 打开一个文件
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`:切换到上侧窗口
之后,可以运行如下命令
```bash
: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中打开文件使用示例如下
```bash
:tabnew file1.txt
```
`:tabnew`并不实际依托于buffer存在可以直接调用`:tabnew`先创建一个tab然后在新tab中调用`:e`打开文件进行编辑。
```bash
: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`选项,示例如下
```bash
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-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之前粘贴文本内容
`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`: `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`(例如`dw``cw`其并不会被存储到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(`"/`)。
如果想要对最后搜索的内容进行粘贴,可以使用`"/p`insert mode模式下可以使用`Ctrl-r /`