%%
# 纲要
> 主干纲要、Hint/线索/路标
# Q&A
#### 已明确
#### 待明确
> 当下仍存有的疑惑
**❓<font color="#c0504d"> 有什么问题?</font>**
# Buffer
## 闪念
> sudden idea
- 普通模式
- 光标移动(motion,movement commands)
- 编辑命令(editing commands)
- (`c` 、`d`、`y` 都需要 motion 作为参数)
- `7dw` 与 `d7w` 都是同样有效的
- `.` 重复执行前一个编辑命令
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-27B2160693988455C09C2FA19C66FE21.png|787]]
`C-v{cold}`:使用字符编码插入字符(插入模式下)(vim 接受 3 位数字,超过 3 位数的需要通过 4 位 16 进制`u{code}`来输入)
`t{char}`:直到某个字符(不包括该字符),till。
- `yt{char}`, `dt{char}`, `ct{char}`。
**字符信息显示**:
`<C-g>`:显示当前光标位置的行号列号
`ga`:显示当前光标位置的字符编码,包括十进制和十六进制形式。
以波纹线 (~) 开头的行表示该行在文件中不存在。换句话说,如果 Vim 打开的文件不能充满这个显示的屏幕,它就会显示以波纹线开头的行。
`<C-a>`
`<C-x>`:将当前光标
单字符操作汇总
- `r` + 字符:替换字符
- `x`:删除字符
## 候选资料
> Read it later
用 f{char} 跳到当前行的某个字符上,然后用 `;` 和 `,` 命令相应地正向或反向重复此跳转
%%
# Vim 帮助手册

> [!NOTE] 注: `:help w` 与 `:help :w` 不同,前者是普通模式下的`w` 按键,后者是命令行模式中的 `w` 命令
<br><br><br>
# Vim "七种基本模式" 与 "七种附加模式"
Vim 有七种基本模式:
- **普通模式 Normal Mode / Command Mode**
- vim 启动后的默认模式。可输入所有**普通编辑命令**,例如光标移动、删除、复制和粘贴、查找等。
- **插入模式 Insert Mode**
- 该模式下可直接编辑文本。
- 从普通模式切换到插入模式可以用这些命令: "i"、"I"、"a"、"A"、"o"、"O"、"c" "C"、"s" 或 "S"。
- **命令行模式 Command-Line Mode**
- 普通模式下按 `:` 进入。
- **可视模式 Visual Mode**
- 该模式用于**选择文本块**,以便对其执行操作(类似于按住鼠标左键进行框选)
- 普通模式按 `v` 进入可视模式,然后通过移动光标选择文本。
- **选择模式 Select Mode**
- 不常用。和可视模式类似,不同在于:
- 选择模式下,只能通过方向键移动光标,**输入任何文本都会替换掉选定的文本**,并**使 Vim 回到插入模式**。
- 可视模式中,使用编辑命令(如复制、删除)不会退出模式。
- **Ex 模式 Ex Mode**
- 普通模式下按 `Q` 进入。执行完命令后会继续停留在该模式。
- 类似于命令行模式,但支持输入更多命令。
七种附加模式:
- **替换模式 Replace Mode**
- 普通模式下按 `R` 进入替换模式。替换模式是插入模式的特殊情况,输入的字符将直接替换原字符。
- **插入普通模式 Insert Normal Mode**
- 插入模式下按 `<C-o>` 进入,允许**运行一个普通模式命令后**返回插入模式,回到原来的位置**继续输入**。
- **命令符待决模式** Operator-pending Mode
- 在输入一个操作符命令时(如 `d`, `y` 等)后**等待指定作用范围**
<br><br><br>
# Vim 的文本编辑理念 ⭐
Vim 中定义了以下概念:
- **文本对象**(Text Object)
- **文本对象修饰符**(Text Object Modifiers)
- **动作**(Motion) 即**光标移动**
- **操作符**(operator)
Vim 中的 "**==普通模式==**" 下基于这些 "概念" 的**组合**,可实现对 "**==特定范围文本==**" 的操作。
<br>
## 文本对象 Text object
> 参见[^1](P117)
Vim 中的 "**文本对象**" 概念指代**一个特定的 "文本范围"**。
文本对象用于同 "**文本对象修饰符**" & "**操作符**" 结合使用,从而实现**操作特定范围的文本**。
| 文本对象标识 | 文本对象 | 说明 |
| ------ | --------- | ---------------------------------- |
| w | word | |
| W | WORD | |
| s | sentence | 以句号、问号或感叹号结束,后跟一个或多个空格或换行符 |
| p | paragraph | 一个段落(以空行或行首的某些字符分隔的文本块) |
| ( 或 b | 括号内的内容 | |
| { 或 B | 大括号内的内容 | |
| `[` | 方括号内的内容 | |
| < | 尖括号内的内容 | |
| t | 标签内的内容 | 示例:`<a>op the content of here</a>` |
| " | 双引号内的内容 | |
| ' | 单引号内的内容 | |
| \` | 反引号内的内容 | |
| | | |
> [!info] 空白字符包括:`<SPACE>`、`<TAB>`、`<EOL>`(End of line)
> [!tip] 可视模式下支持通过 `修饰符 & 文本对象` 来选中特定范围 ^594ccf
<br>
### word 与 WORD

- 「**word**」:由**空白字符**分隔的,下列**字符序列**之一:
- 由连续的"**==字母==、==数字==、 ==下划线==**" 构成的字符序列
- 由其它 "**==连续非空白字符==** " 构成的字符序列
- **空行视为一个 word**
- 「**WORD**」:由**空白字符**分隔的 **任何==非空字符序列==** 都视为一个 WORD
- **空行视为一个 Word**
> [!example] 示例:`foo_32-:.:,Jd342`
>
> 该字符串中:
> - 共有三个 word:`"foo_32"`,`"-:.:,"`, "`"Jd342"`"
> - 共有一个 WORD:`"foo_32-:.:,Jd342"` ,即整个字符串本身
<br>
## 文本对象修饰符 Modifiers
文本对象修饰符用于 "**定义文本对象范围**",用于与**操作符**结合使用,实现**对特定范围文本的操作**。
常用的文本对象修饰符包括:
- `a`:around,表示**一个文本对象==周围==——包含其==前方或后方的空白字符 or 空行==**。
- `i`:inner/inside,表示**一个文本对象==内部==——仅其本身,不包括其前方或后方的空白字符 or 空行**。
> [!caution] `a` 只会包含 "**前方或者后方==其中一侧==的任意空白字符 or 空行**"
<br>
## 光标移动 Motion
Vim 中,将 "**==光标移动==**" 命令称之为 "motion",也称 "movement"。
`CTRL+G`:显示**当前光标所在位置
#### motion 移动
操作格式:`[number] motion`,可**搭配操作符 `operator` 实现范围操作**。
| 按键 | 光标移动说明 |
| --------------------------- | ------------------------------------------------------------- |
| `h`, `j`, `k`, `l` \| 方向键 | 左、下、上、右 |
| `0` \| `Home` | 移动到**当前行首** |
| `
\| `End` | 移动到**当前行尾** |
| `^` | 移动到**当前行的第一个非空白字符** |
| `g_` | 移动到**当前行的最后一个非空白字符** |
| | |
| `gj`、`gk` | **屏幕行**的 "下" 与 "上" |
| `g0`、`g
、`g^` | 移动到**当前 "屏幕行" 的行首、行尾、行内第一个非空白字符** |
| | |
| `b` | 移至**当前 word 首**(若已在头部则移至前一个单词头部; move backward one words) |
| `e` | 移至**当前 word 尾**(若已在尾部则移至下一个单词尾部; forwards to the end of word) |
| `w` | 移至**下一个 word 首**(move forward one word) |
| `ge` | 移至**上一个 word 尾**(backwards to the end of word) |
| | |
| `gg` | 移至**第一行**的**首个非空白字符** |
| `G` | 移至**最后一行**的**首个非空白字符** |
| | |
| `<N>G` \| `:<N>` | 移动到**指定行**首 |
| `H`、`M`、`L` | 移动到**当前屏幕的顶行、中间行、尾行** |
#### 其他光标移动(不属于 motion)
| 按键 | 光标移动说明 |
| ----------------------- | -------------------------------------------- |
| `Ctrl-U` | 向上滚动**半屏** |
| `Ctrl-D` | 向下滚动**半屏** |
| `Ctrl-F` \| `PageDown` | **向后翻页**(滚动一屏) |
| `Ctrl-B` \| `PageUp` | **向前翻页**(滚动一屏) |
| | |
| `Ctrl-I` | 跳转到后一个 "**跳转**" 位置 |
| `Ctrl-O` \| `` \`\` `` | 回退到前一个 "**跳转**" 位置 |
| | |
| `gi` | 返回 "**上次插入位置**"(上次退出插入模式时光标所在位置),并**进入插入模式** |
| `g,` | 正向遍历 "**修改**" 列表 |
| `g;` | 反向遍历 "**修改**" 列表 |
###### 跳转至位置标记
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-E75868CA515B531163202F83FEB1AEEF.png|386]]
#### 注意事项
> [!NOTE] 屏幕行与逻辑行——`j`, `k` 与 `gj`, `gk`
>
> 当在 Vim 中启用了 `wrap` 设置时,超出窗口宽度的文本行将会**自动折行显示**。
>
> - **逻辑行**:**以 `\n` 结尾的实际一行内容**
> - **屏幕行**:**在屏幕上实际显示的各个行**,也称 "**物理行**"。
>
> `j` 与 `k` 移动的单位是 "**逻辑行**",而 **==`gj` 与 `gk`== 移动的单位是 "==屏幕行=="** [^1] (P105)。
>
> ![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-CDBD26EC5B2433301568344A2D6381A8.png|432]]
> [!NOTE] `w`、`b`、`e`、`ge` 以 word 为单位进行移动
>
> ![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-240D6AA43622EBDF32D8167F3D21D48C.png|311]]
>
> [!NOTE] `B`、`E`、`W`、`gE` 对应为以 `WORD` 为单位的移动
> [!NOTE] 部分 motion 不支持重复,例如 `0`、`^`、`gg`、`G`
> [!info] 关于 "跳转" [^1](P126)
>
> `:jumps` 可查看跳转列表,`<C-i>` 与 `<C-o>` 用以在此列表中记录的 "**跳转项**" 之间进退。
>
> "**任何改变当前窗口中活动文件的命令**"(例如打开不同文件) 都属于 "**跳转命令**",此外还包括一下行为:
>
> ![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-1C0BCCEB8D85A6AB522E1FB5F01C9C96.png|477]]
>
> 常规的 motion 移动并不属于 "跳转",因此不能通过 `<C-i>` 或 `<C-o>` 进退。 ^esfo0a
<br><br>
## 操作符 Operator
> 参见[^1](P51)

常用的 **Vim 操作符**如上表,这些操作符均**需要搭配** "**光标移动** motion",从而实现 "**范围操作**",
命令格式:`operator [n] motion` 或 `[n] operator motion`,其中 `[n]` 表示操作**重复次数**。
> [!NOTE] 当一个操作符被**连续调用两次**时,将**作用于==当前行==**。
>
> - 例如 `dd`、`cc`、`yy`、`>>`、`<<`。
> - 由两个按键构成的操作符例如 `g~`,`gu`,`gU`,其重复模式支持两种形式:
> - 重复为`gUgU`
> - **视`g` 为前缀按键**,仅重复后一按键:`g~~`,`guu`, `gUU`
>
> 当需要重复这些**作用于整行**的命令时,可加上**前缀数字**,例如 `[n]dd`,`[n]cc`,`[n]>>`。
>
> ^zp8ffv
<br><br>
## 范围操作使用说明 🌠
上述几个概念在 "**普通模式**" 下搭配使用的方式有多种:
- **操作符 & 光标移动**: `operator motion`
- **操作符 \* 2**(表示**作用于整行**)
- **操作符 & 修饰符 & 文本对象** : `operator modifier text-obj`
### (1)操作符 & 光标移动使用示例
命令格式: `[N] operator motion` 或 `operator [N] motion`,其中 `[N]` 表示操作**重复次数**。
下标**以 `d` 为例**,其他操作符 **`c`,`y`, `>` 等格式类同**。
| 示例 | 说明 |
| ----------------------- | ----------------------------------------------- |
| `dl` | 删除光标位置的字符,等价于 `x` |
| `d0` | 删除从光标位置 "**之前** "至**行首**的所有内容 |
| `d[N]
\| `D` | 删除从光标位置到**行尾**的所有内容 |
| | |
| `dgg`,`dG` | 删除从光标位置到**文件首行、文件尾行**的所有内容 |
| | |
| `d[N]j`,`d[N]k` | 删除**当前行**及**下一行**(或**上一行**)的内容 |
| | |
| `d[N]w`、`d[N]e`、`d[N]b` | 删除**从光标位置至下一个 word 头、当前 word 尾部、当前 word 头部**的内容 |
| | |
| `d%` | 删除**括号及括号内的内容**(等价于 `da(`, `da{`, `da[` ) |
> [!NOTE] 部分 motion 不支持重复,例如 `0`、`^`、`gg`、`G`
> [!caution] 向前删除时,不包括光标起始位置
>
> ![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-681C032FC16EFAAB9DC6C89600EC90A8.png|562]]
### (2)操作符 "作用于整行" 使用示例
![[05-工具/vim/vim 使用#^zp8ffv]]
### (3)操作符 & 修饰符 & 文本对象使用示例
命令格式:`operator modifier text-object`
- 对 word:
- `daw` , `yaw` , `caw` , `vaw`:删除,复制,更改,选中**光标处的单词及==前或后==方的空白字符**
- `diw` , `yiw` , `ciw` , `viw`:删除,复制,更改,选中**光标处的单词**
- 对 paragraph:
- `dap` , `yap` , `cap` , `vap`: 删除,复制,更改,选中**整个段落及其==前或后==方的空白行**
- `dip` , `yip` , `cip` , `vip`: 删除,复制,更改,选中**整个段落**
- 对 **==括号==** 及其内容(其他 **括号** 格式类同):
- `da(` , `ai(` , `ca(` , `va(`:删除,复制,更改,选中 **==括号及其中内容==**
- `di(` , `yi(` , `ci(` , `vi(`:删除,复制,更改,选中 **括号内内容**
- 对 **==引号==** 及其内容(其他**引号**的格式类同)
- `da"` , `ai"` , `ca"` , `va"`:删除,复制,更改,选中 **==双引号及其中内容==**
- `di"` , `yi"` , `ci"` , `vi"`:删除,复制,更改,选中 **双引号内内容**
<br><br><br>
# Vim 的缓冲区概念
Vim 支持**同时打开多个文件**,通过维护**一组缓冲区列表**实现,**每个缓冲区对应==一个打开的文件==**。
缓冲区相关命令参见[[#缓冲区处理相关]]
> [!NOTE] 什么是缓冲区?
>
> 通过 Vim 打开一个文件时,**文件内容被从磁盘上读入内存**,其**在内存中的映像**即称之为 "**缓冲区**"。
> Vim 中**编辑的实际上是 =="缓冲区" 的内容==**,执行 `:w` 命令后才会**将缓冲区内容写回磁盘上文件进行覆盖**。
#### 缓冲区列表标识说明
`:ls` 命令可**查看当前的缓冲区列表**。
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-769765DE8272D8DDA6A56C930AC3D343.png|459]]
- `%`:标识**当前窗口对应的缓冲区**
- `#`:标识可通过 `Ctrl-^` 快速轮换的缓冲区
- `+`:标识该**缓冲区内容已发生过修改**
- `a`:标识 "**当前活动缓冲区**"(active)
- `h`:标识 "**当前隐藏缓冲区**"
<br><br>
# Vim 交换文件
当通过 Vim 打开一个文件进行编辑时,**Vim 默认会在文件所在目录创建一个交换文件**。
每次**对缓冲区内容进行修改时,交换文件都会更新**,以确保在崩溃时能够恢复尽可能多的内容。
使用 "**交换文件**" 的目的:
- **崩溃恢复**:如果 Vim 或系统崩溃,交换文件可以**帮助恢复未保存的修改**。
- **防止多次编辑冲突**:如果在另一个 Vim 实例中打开同一个文件,交换文件会**警告文件已经在编辑中**。
若当前目录下存在**某个文件的 "`.swap`交换文件"**,则**用 Vim 打开该文件**时将显示以下信息:
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-27B2160693988455C09C2FA19C66FE21-3.png|642]]
> [!NOTE] 可通过 `:set noswapfile` 禁用交换文件
<br><br><br>
# Vim 状态栏说明
![[05-工具/vim/vim 配置#^zut8et]]
<br><br><br>
# Vim 标签页 & 窗口管理
Vim 中的 **"标签页" 是对 "窗口" 的分组管理**,Vim 支持**打开多个标签页**,**每个标签页下可容纳多个窗口**。
- Tab 标签页
- Window 窗口
> [!NOTE] 标签页、窗口与 "**缓冲区**" 不是一一对应的关系:
>
> - 一个 "缓冲区" 可能**仅在后台打开**,未对应**任何标签页或窗口**;
> - **多个 "窗口"** (同一标签页或不同标签页下)可以关联到 "**同一个缓冲区**"
<br>
## 标签页管理
##### 新建标签页 Tab
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-306C1DF70557FC759164E65F079C4351.png|480]]
- `:tabe[edit]` 同 `:tabnew`
##### 标签页间切换
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-72CB8BF0D933FD33BB161439B65809C1.png|559]]
##### 重排标签页
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-1CE570D414E0D68AF704BB3B1494E81B.png|547]]
##### 设置标签页中窗口的当前工作目录
- `:windo lcd <path>`: 为**当前标签页中所有窗口**设置该工作目录
<br>
## 窗口管理
##### 其他命令
- `:lcd <path>`: **设置当前窗口的本地工作目录**
##### 新建/拆分窗口(Split Windows)
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-0B86B2A836A8073553CA43267F3F37E6.png|534]]
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-A19E0907757C1AF1A7BD9D92C9B63491.png|414]]
> [!NOTE] Vim 启动时指定多文件窗口布局
>
> - `vim -o {file1} {file2} {file3}` 以水平拆分的方式打开多个文件
> - `vim -O {file1} {file2} {file3}` 以垂直拆分的方式打开多个文件
##### 关闭窗口
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-BE8E1DD9E5BC720262A638D3946AF592.png|522]]
- `:q`:关闭**当前窗口**
- `:qa`:退出**所有窗口**
##### 窗口间切换

| 快捷键 | 说明 |
| -------------------- | -------------------------------------- |
| `<Ctrl-W>-[n]w` | 在窗口之间循环切换,**正向移动**(从上到下,从左到右,从最低到最高层级) |
| `<Ctrl-W>-[n]W` | 在窗口之间循环切换,**反向移动** |
| `<Ctrl-W>-<j,k,l,r>` | 移动到**上、下、左、右方**的窗口 |
| `<Ctrl-W>-p` | 返回**上一个访问**的窗口 |
| `<Ctrl-W>-t` | 移动到**左上角**的窗口 |
| `<Ctrl-W>-b` | 移动到**右下角**的窗口 |
##### 改变窗口大小
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-C4C602BE4C276F5FA9D1F5A72B5F504A.png|538]]
<br>
# Vim 运行参数
- `vim [OPTION] <filename>...`
- `-R`:**只读模式**打开(等同于 `view <filename>`)
- `-o` 以**水平拆分**的方式打开多个文件
- `-O` 以**垂直拆分**的方式打开多个文件
<br><br><br>
# 普通模式下的行为
## 屏幕滚动
光标不动,**除非将溢出屏幕时,将移动到屏幕边界**
| 按键 | 说明 |
| ------- | ---------------- |
| `zz` | 将当前行显示在**屏幕正中间** |
| `zt` | 将当前行显示在**屏幕顶部** |
| `zb` | 将当前行显示在**屏幕底部** |
| `<C-e>` | 屏幕内容向上滚动 |
| `<C-y>` | 屏幕内容向下滚动 |
## 光标移动
参见[[#光标移动 Motion]]
## 进入可视模式
三种可视模式:
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-DF48AB64AD71074B9E0332EC351BA6A2.png|249]]
| 按键 | 说明 |
| ------------------ | ----------------------------------------------------------------------- |
| `v` | 进入 **"常规可视模式"**(regular visual mode)——选中 **"当前光标位置"与"起始位置"之间的内容** |
| `V` | 进入 "**行可视模式**"(visual line mode)——选中 **"当前光标位置"与"起始位置"之间的所有==整行==内容** |
| `<C-v>` \| `<C-q>` | 进入 "**块可视模式**"(visual block mode)——选中 **"当前光标位置"与"起始位置"之间的==矩形框区域==内容** |
- `gv`:重选**上次的高亮选区**
## 进入插入模式
> 按键后,将**移动光标位置**并进入 "**插入模式**"
| 按键 | 说明 |
| --- | -------------- |
| `i` | 在光标位置插入 |
| `a` | 在光标**之后**插入 |
| `I` | 在当前**行首**插入 |
| `A` | 在当前**行尾**插入 |
| `o` | 在当前行**下方**插入新行 |
| `O` | 在当前行**上方**插入新行 |
> [!NOTE] `[N]i{input some text}<Esc>` 会将从 "**进入插入模式**" 到 "**退出插入模式**" 过程中的修改**重复 N 次**。
>
> 示例:`10+i+Hello World<Enter>+<Esc>` 将插入 10 行 Hello world
>
> ![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-47BB2A384D0D60F9D713BEEAE5465B7B.png|672]]
>
## 进入替换模式
- `R` :进入**替换模式**,随后**每次输入都将替换掉光标位置的字符**(替换模式下可通过方向键移动光标)
## 重复上次修改
- `.`:重复上次**修改**——vim 会记录两种 "**==修改==**":
- 重复上一次 "**编辑命令**" 带来的 **==修改==**
- 重复上一次 "**进入插入模式**" 到 "**退出插入模式**" 过程中带来的 **==修改==**
> [!caution] `.` 是 "重复上次修改",而不是 "上次命令"!
> [!NOTE] 关于 "修改"
>
> 一次 "修改" 是 "**改变文档内文本的任意操作**",包括:
> - **在普通模式、可视模式、命令行模式中所触发的命令**,
> - 以及"**插入模式下所完成的修改**"(`i{insert some text}<ESC>`)
## 编辑相关操作
### 撤销与重做
- `u`: 撤销 undo
- `[N]u`: 重做 N 步。
- `U`:撤销**整行内**发生的**所有修改**
- `CTRL + R`:重做 redo
### 复制
| | 说明 |
| ----------- | -------------------------- |
| `y` | 复制**当前选中的内容**(到特定 Vim 寄存器) |
| `yy` \| `Y` | 复制**整行** |
其余与 motion 的结合使用参见[[#范围操作使用说明 🌠]]
### 粘贴
- `[N]p`:粘贴到光标位置**之后**
- `[N]P`:粘贴到光标位置**之前**
> [!NOTE] 若缓冲区内的内容是"整行"(例如执行了 `yy` 或 `dd` 后),则会将**整行内容**粘贴到**当前行**的**上一行/下一行**)
### 更改
> "更改":下列操作将首先 "**删除**" 内容,而后自动进入 "**插入模式**"
| | 说明 |
| ------------ | ---------------------- |
| `s` \| `cl` | 更改**光标位置**处字符 |
| `S` \| `cc` | 更改**整行** |
| | |
| `cw` \| `ce` | 更改光标位置**至`word`尾部**的内容 |
| `C` \| `c
| 更改光标位置**至行尾**的内容 |
其余与 motion 的结合使用参见[[#范围操作使用说明 🌠]]
### 替换字符
- `r<char>` :替换**光标位置**处字符为 `char`
### 删除
- `x`:删除光标位置的字符
- `[n]x` 删除包含光标位置在内的 n 个字符
- `X`:删除光标位置**之前**的字符
- `d`:删除**当前选中区域内容**,常与 motion 结合使用
###### 插入模式下的删除快捷键

### 缩进
- `>`:增加当前行的缩减层级
- `<`:减少当前行的缩进层级
- `=`:自动缩进
- `gg=G`:**自动缩进全文**
与 motion 的结合使用参见[[#范围操作使用说明 🌠]],示例:
- `>G` 增加**从当前行到文件末尾行**的缩进层级
- `<4j` | `4<<`:缩进下面 4 行
### 改变大小写
- `~`:切换**当前光标位置处字符**大小写
- `g~`:切换 "**当前选中区域**" 的大小写
- `gu`:将 "**当前选中区域**" 全小写
- `gU`:将 "**当前选中区域**" 全大写
`g~`, `gu`, `gU` 与 motion 的结合使用参见[[#范围操作使用说明 🌠]]
### 数字加减
- `[N]<Ctrl-A>`:**将当前光标处(或光标后的首个数字处)==增加==整数值 N**
- `[N]<Ctrl-X>`:**将当前光标处(或光标后的首个数字处)==减少==整数值 N**
### 连接行
- `[n]J`:连接多行,去除行之间的缩进和换行符等,两行间会插入空格。
## 搜索查找

![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-BF45BBEA3153AFEC7A76F57BC4AA9FEE.png|401]]
#### 行内字符搜索
- `f<char>`:跳转至**当前行内光标位置后的==下==一字符 `char` 的位置**
- `F<char>`:跳转至**当前行内光标位置前的==上==一字符 `char` 的位置**
- `t<char>`:跳转至**当前行内光标位置后的==下==一字符 `char` 的左侧**
- `T<char>`:跳转至**当前行内光标位置前的==上==一字符 `char` 的位置**
- `;`:**重复**最近执行的 `f`, `t`, `F` 或 `T` 命令
- `,`:**反向重复**最近执行的 `f`, `t`, `F` 或 `T` 命令
> [!NOTE] `f<char>` 搭配 `;` 与 `,` 可实现在行内 "==同一字符==" 间跳转
#### 括号间匹配
- `%` :**匹配括号间跳转**
- 若光标位置为括号,则**跳转至其==相匹配的括号==位置处**;
- 否则,**跳转至==光标位置之后的括号==处**(如果存在)
#### word 搜索
- **`*`** : **搜索**光标位置附近的 `word` 并跳转至该 `word` 的**下一个匹配位置**
- `#` : **搜索**光标位置附近的 `word` 并跳转至该 `word` 的**上一个匹配位置**
> [!NOTE] `*` 与 `#` 按以下顺序进行搜索匹配
>
> 1. **光标处**由 **数字、小写字母、`@`** 组成的字符系列
> 2. 光标之后的**首个** "**数字** | **小写字母** | `@`"
> 3. **光标处**的**非空 `word`**
> 4. 光标之后的**非空 `word`**
#### 匹配内容搜索
- `/<expr>` : **向后查找内容** `expr`
- `/<expr>\c` :`\c`, 单次查找时忽略大小写
- `//`: 重复上一次查找
- `?<expr>` : **向前查找内容 `expr`**
- `??` : 重复上一次查找
- `n`:重复**前一次 `/?*#` 查找**,**跳转至下一个匹配位置**
- `N`:反向重复**前一次 `/?*#` 查找**,**跳转至下一个匹配位置**
> [!NOTE]
> - 如果**前一次查找是 `/*`(向后)**,则 `n` 就是继续**向后跳**至下一位置,而 `N` 则是**向前跳**至下一个匹配位置
> - 如果**前一次查找是 `?#`(向前)**,则 `n` 就是继续**向前跳**至下一位置,而 `N` 则是**向后跳**至下一个匹配位置。
<br><br><br>
# 插入模式下的行为
#### 插入模式下的快捷键
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-ED0C79D0073E3A4F2EAF39529EF0E143.png|360]]
- 整行缩进:`<C-t>` 增加,`<C-d>` 减少
- 删除:`Ctrl-W`、`Ctrl-U` (**同 bash shell 快捷键**)
- `<C-p>`: 触发**关键字自动补全**,将在根据输入内容在**当前缓冲区、已打开的缓冲区以及标签列表中查找匹配的单词**,并显示一个补全选项列表。
- `<C-p>` 键可循环选项
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-2860FD0385939C3827AA6897E2D61399.png|722]]
#### 插入模式与普通模式的转换
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-FFAA043F4748B2A669DE40D69D91B3EB.png|326]]
- `Ctrl-O`:进入"**==插入-普通模式==**",可执行一条 "**普通模式下的命令**" 后**回到插入模式**
- 示例:`<Ctrl-O>zz`
<br><br><br>
# 可视模式下的行为
### 通用
##### 特有命令
- `o`:切换选区的 **==活动端==**
![[05-工具/vim/vim 使用#^594ccf]]
##### 操作符命令
可视模式下支持所有 "普通模式下的**操作符命令**",区别在于这些**按键命令**将作用于 "**当前选中区域**":
| 操作符 | 说明 |
| --------- | ------------------ |
| `c` | **删除选中内容并进入插入模式** |
| `d` & `x` | **删除选中内容** |
| `r{char}` | **替换选中内容为指定字符** |
| `y` | **复制选中内容** |
| `>` | **缩进选中行** |
| `.` | 重复上次修改 |
| ...... | |
##### 可视模式切换
可视模式切换:`v`、`V`、`Ctrl-V` 可**在三种可视模式间切换**
> [!caution] 在可视模式下,选中**多行后键入`c` 进入插入模式**,**对多行选中内容的修改只会=="显示"在顶行==**,而**在退出插入模式后才应用于所有行**。
### 块可视模式下的行为
块可视模式用以操作 "**列**" 中文本——**对==一列中的各行==分别应用操作**
| 操作 | 说明 |
| --- | ------------------------- |
| `I` | **在选中块的每行头部插入内容** |
| `A` | **在选中块的每行末尾插入内容** |
| `c` | **更改选中块的每一行内容(独立应用于各个行)** |
| `d` | **删除选中块的每一行内容(独立应用于各个行)** |
### 可视模式编辑示例
- `Vr-`:选中**当前整行**并替换为 `-`
- `V4jr|`:选中**当前列(4 行)** 并替换为 `|`
---
<br><br><br>
# 命令行模式下的行为
普通模式下键入 `:` 后即进入**命令行模式**。
命令行模式中执行的命令称为 "**==Ex 命令==**"。
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-76F69FBA30F71175A9E09ED3E63335FE.png|475]]
- `:undolist` 查看可用的 undo 列表。
## 展开
- `%<Tab>`:展开为 "**当前活动缓冲区对应文件的绝对路径**"
- `%:h<Tab>`:展开为 "**当前文件所在目录的路径**"
## 退出
- `:q`:退出(关闭**当前窗口**)
- `:q!`:强制退出(**不保存任何更改**)
## 命令行模式下的快捷键
- `Ctrl-W`:删除至前一个单词
- `Ctrl-U`:删除至行首
## 命令补全
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-31B19536C42D427CD648859CA78B81DD.png|451]]
- `CTRL+D` :键入前缀后,显示命令列表
- `<TAB>` :补全命令
## 当前工作目录相关
- `:pwd`:查看当前工作目录
- `:lcd <path>`: **设置当前窗口的本地工作目录**
- `:windo lcd <path>`: 为**当前标签页中所有窗口**设置该工作目录
## 文件 & 缓冲区相关
### 打开文件
- `:e[dit] <filename>` :打开文件
- `:e!`:打开文件(使用**磁盘上文件内容**覆盖**当前缓冲区中内容**,意味着 "**丢弃所有修改**")
### 保存文件
- `:w[rite] [filename]`:**保存缓冲区内容**(**将缓冲区内容写入到磁盘上,覆盖文件内容**)
- `:wa`:**保存所有缓冲区中的内容**
- `:wq`:保存并退出 (同 `:x` 或 `ZZ`)
> [!NOTE] 保存选中内容为文件
>
> 按 `v` 进入可视模式,选中内容后再通过 `:w filename` 将选中内容保存到文件
### 读取文件内容并插入到当前缓冲区
- `:r <filename>`:读取 **文件系统上指定文件内容**,插入到**当前光标位置处**
- `:r !<command>`:读取 **外部命令的输出**,插入到当**前光标位置处**
### 缓冲区处理相关
| 命令或快捷键 | 说明 |
| ----------------------------- | ----------------- |
| `:ls` | 查看**缓冲区列表** |
| `:bprev`,`:bnext` | 在缓冲区列表中**前后移动** |
| `:bfirst`,`:blast` | 切换至**缓冲区列表首尾** |
| `:buffer N` | 切换至**编号为 N 的缓冲区** |
| `Ctrl-^` | 轮换**缓冲区** |
| `:bdelete N...` 或 `:bd N...` | **删除缓冲区** |
##### 缓冲区列表标识
参见[[#缓冲区列表标识说明]]
##### 隐藏缓存区的处理
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-B27ECF8A9C7F1772EABF4D92DDF5F324.png|441]]
## 缓冲区文本处理
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-4603375BBD5C2C8B5088A98B10D96C49.png|628]]
## 查看修改列表
`:changes`
## 查看跳转列表
`:jumps`
![[05-工具/vim/vim 使用#^esfo0a]]
## 查看寄存器内容
- `:reg 寄存器引用`,例如 `:reg "0`
## 检查更改
- `:diffthis`
## 匹配内容替换
替换命令的格式: `:[range]s/{pattern}/{string}/[flags]`

用法说明:将内容 `old` 替换为 `new`
| | 说明 |
| ----------------- | ---------------------------------------------- |
| `:s/old/new` | 替换当前行的**首项匹配** |
| `:s/old/new/g` | 替换当前行的**全部匹配** |
| `:#,#s/old/new/g` | 替换 `#` 与 `#` 两行之间出现的所有匹配串 (`#` 是行号) |
| | |
| `:%s/old/new/g` | 替换**整个文件**内的**所有匹配** |
| ` :%s/old/new/gc` | 替换**整个文件**内的**所有匹配**,每次替换之前进行询问确认(`c`:confirm) |
| | |
## 匹配内容删除
`:g/pattern/d`:将匹配 `pattern` 的行全部删去
## 执行外部命令
`:!<command>` :执行外部命令 `command`(命令执行完成后,将返回到 vim 中)
## 设置编辑器选项
设置选项:
- `:set ic` 忽略大小写(ignore Case) 查找短语时显示部分匹配
- `:set hls ls` hlsearch 高亮匹配结果、incsearch
- `:set number` 显示行号(在每一行之前显示)
选项前加上 `no` 表示**关闭选项**:
- `:set noic` 禁用忽略大小写
- `:set nohlsearch` 禁用匹配结果高亮
- `:set nonumber` 不显示行号
<br><br><br>
# 寄存器
Vim 中提供了**一组寄存器**(几十个)用以**支持特定操作**,例如 `d`、`y`、`p` 命令。
## 寄存器说明
| 寄存器 | 引用方式 | 说明 |
| --------------------- | ------------------- | -------------------------------------------------------------------------------------------------------- |
| **无名寄存器** | `""` | 默认寄存器,unname。<br>`x`,`s`,`d`,`c`,`y` 系列命令(及其大写命令)都会**默认覆盖该寄存器中内容** |
| **复制专用寄存器** | `"0` | 仅 **`y` 系列命令会覆盖该寄存器内容** |
| | | |
| **有名寄存器**<br>(共 26 个) | `"a-"z` 或 `"A`-`"Z` | 供**明确引用**使用<br>- 通过 "小写字母" 引用时,会**==覆盖==寄存器原有内容** <br>- 通过 "大写字母" 引用时,会**将新内容==追加==到寄存器原有内容末尾** <br><br> |
| | | |
| **表达式寄存器** | `"=` | |
| **黑洞寄存器** | `"_` | 特殊寄存器,**引用该寄存器**时的含义是 "**真正地删除**",即**不存入任何寄存器**中 |
| | | |
| **系统剪贴板** | `"+` | 引用该寄存器表示使用 "**系统剪贴板**",例如 `"+p` 表示粘贴系统剪贴板中内容,`"+y` 表示复制到系统剪贴板 |
| **选择专用寄存器** | `"*` | 引用该寄存器表示使用 "**X11 窗口系统的主剪贴板**"——其中**保存着==上一次被高亮选中的文本==** |
| | | |
#### 只读寄存器
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-BC724C5ED1B0AA131BE2E7767C1F1AAE.png|285]]
> [!NOTE] `y` 系列命令会同时将**复制的文本**写入 "**无名寄存器`""`**"、"**复制专用寄存器`"0`**" 中
> [!NOTE] Vim 中的剪切(cut)、复制(copy)、粘贴(paste)
>
> Vim 中通过 `d`,`y`,`p` 命令来提供上述功能,**对应含义为:delete,yank,put**。
>
> 实际上,`d` 和 `y` 命令分别是将内容 "**==剪切==**" 、"复制" 到**默认的无名寄存器**中,**==`d` 并未实现真正的删除==**。
> 如果要**实现真的删除**,应当使用 `"_d`,即引用 "**黑洞寄存器**"。
> [!info] 关于 "系统剪贴板" 与 "主剪贴板"
>
> 除 "**系统剪贴板**" 外,X11 窗口系统中**独立支持**另一种称为 "**==主剪贴板==**" 的剪贴板,
> 其中**保存着==上一次被高亮选中的文本==**,可通过 "**鼠标中键或右键**" 进行粘贴。
>
> 关于 Linux 中不同剪贴板的说明参见 [[02-开发笔记/11-Linux/Linux 相关#Linux 中的剪贴板|Linux 相关]]
>
> [!caution] Windows 和 Mac OS X 操作系统中没有 "**==主剪贴板==**" 的概念,因此 `"+` 与 `"*` 都表示 "系统剪贴板"
<br>
## 寄存器引用
`x`,`s`,`d`,`c`,`y` 系列命令**默认**使用 "**无名寄存器**",可由以下方式**指定所使用的寄存器**:
- 在**普通模式或可视模式下**,可通过为命令加上 **==`"{register}` 前缀==** 指定所用寄存器——例如 `"0p`。
- 在**插入模式**下,通过**按键 `<C-r>{register}`** **插入该寄存器中的内容**——例如 `<C-r>0` 或
## 查看寄存器内容
- 查看寄存器内容:`:reg "<register>`,例如 `:reg "0`
<br><br><br>
# 参考资料
#### Vim 使用说明
- [VIM 中文用户手册: 目录](https://yianwillis.github.io/vimcdoc/doc/usr_toc.html)
- [Vim: help.txt](https://vimhelp.org/) ⭐
- [Vim Tips Wiki | Fandom](https://vim.fandom.com/wiki/Vim_Tips_Wiki) (Vim 奇技淫巧)
#### Vim 按键说明
- [Vim cheatsheet](https://quickref.me/vim#google_vignette) **速查表**
- [Quickref - Neovim docs](https://neovim.io/doc/user/quickref.html) **详尽的按键说明(cheatsheet 速查表)** ⭐⭐⭐
- [Index - Neovim docs](https://neovim.io/doc/user/vimindex.html) **完整的按键、命令索引** ⭐(若在上面 Quickref 链接中未找到,则可以在其中寻找)
- [Vim/ROADMAP.md at master · VSCodeVim/Vim · GitHub](https://github.com/VSCodeVim/Vim/blob/master/ROADMAP.md) ⭐(说明了 Vim 中常用的 **Motion 等按键效果**)
- ![[_attachment/05-工具/vim/Neovim 说明.assets/IMG-Neovim 说明-A8A694CA9EC48485CA515F988BB78C95.png|551]]
##### 图例
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-9403B3D4F1BE7E12401604F219344633.png|851]]
![[_attachment/05-工具/vim/vim 使用.assets/IMG-vim 使用-C18E29E14A4EBB8F600B7E3E929701A4.png|848]]
# Footnotes
[^1]: 《Practical Vim》
[^2]: Vim Tutor