前言
个人理解:vim是一门实践的技术,用则立,不用则废。使用vim编辑代码不代表要舍弃原有的编辑器,使用偏向无格式化工具、无语法高亮等功能的纯文本模式编辑,而是在已经强健而完备的编辑器基础上,从c+v模式升级成更高级的cv模式,并以简单的命令实现如代码跳转标记、单词替换、剪切板复制多文本等功能,达到如虎添翼的效果。
一、vim的两大使用场景
- shell普遍内置的编辑器
- ide里的快捷键映射(vscode、idea),以插件的形式功能补充
二、人群抉择
2.1 不适配人群
- 不想再折腾,很少接触linux远程服务器的人
- 觉得所使用编辑器,可以完美满足编辑需求的人
- 短时间介入,觉得学习成本大于开发效率提升效果的
2.2 适配人群
- 慕名已久,双向奔赴
- 想要使编程体验更加轻灵悦动
- 想要提升自己的逼格
三、基本模式
大部分操作都在normal和inset模式之间切换,技巧在于以什么样的命令从normal到inset模式。
普通模式(Normal mode)
常用。 Vim 默认模式, 又称为命令模式, 可使用 hjkl 进行移动和简单编辑,是编辑器的初态和终态。
插入模式(Insert Mode)
常用。 该模式下可以尽情地输入, 普通模式通过 i
(insert), a
(append), o
(open a line)等命令可进入插入模式,类似于无vim下的纯文本编辑模式。
可视模式(Visual Mode)
很少。 与普通模式类似, 不同的是当移动时会进行扩展当前的选择区域. 普通模式按 v
(进入字符选择模式) 或 V
(进入行选择模式)进入该模式。一般用于一些批处理动作,比如在连续5行的代码末尾加入分号。
命令行模式(Command Line Mode)
一般,linux下常用。 在该模式下可以在窗口的下方输入一行命令, 然后执行。当一条命令执行完会自动退出命令模式进入普通模式。比如 :w 为保存,此时w看作write的缩写。
命令模式通过输入 :
进行开启
替换模式(Replace Mode)
一般。 新输入的文本会替换光标所在处的文本, 并使光标依次向后移动。已有的编辑器搜索与替换功能已经很强大,故下面的内容不做详解。
普通模式下通过按 r/R
(replace)进入该模式
四、键盘图速查
主要为四大类
- 动作(Motion):指在Vim中移动光标的操作,比如
h
、j
、k
、l
等键用来在文本中左右上下移动光标。 - 命令(Command):指在Vim中执行的命令。
- 操作(Operation):指在Vim中对文本进行的编辑操作,通常由一个动作和一个命令组合而成,比如
dw
用于删除一个单词、yy
用于复制一行文本、dd
用于删除一行文本等。常用的Operation为c、y、d。 - 特殊功能(Extra):需要额外的输入以实现某种目的,如"寄存器。
五、常用功能
5.1 寄存器
复制文本
Vim 提供了许多寄存器。 我们可以将这些寄存器用作多个剪贴板,可以分成数字寄存器、符号寄存器、系统寄存器(ctrl c/v)。数字寄存器、符号寄存器只能在vim编辑器里面使用。
js
"{register-name}{command}
基本的复制命令为 yy ,其中y代表yank,翻译为猛地一拉,代表复制的意思,将文本行复制到未命名的寄存器中,用""表示,其他的如 dd(删除当前行)删除的内容也将放到 "" 寄存器中。
例如,要复制寄存器"a"中的文本
js
"ayy
这样的话,你的寄存器中就有两个你可能之后会使用的文本。
粘贴文本
js
"{register-name}p
其中p是paste粘贴的意思,该命令就是选择对应的寄存器的文本进行粘贴,如果是存放在未命名的寄存器的内容可以直接使用p进行粘贴。
列出可用的寄存器
js
:registers
复制内容到系统寄存器中
可以直接使用ctrl c/v进行复制和粘贴,当然也可以+号寄存器复制和粘贴
5.2 书签标记
书签的作用:标记,快捷跳转
js
m{bookmark-name}
比如mm就创建了一个名为m的书签,跳转到指定书签名的命令为:
js
`{bookmark-name}
为按键1左边的按键,
如```m``则可跳回m标签。
还有比如列出所有标签,删除标签的相关命令,由于不常用就不做介绍。
### 5.3 折叠代码
当定位到某个变量,此时你可能想看他所处在哪个上下文(如函数、html标签等)中,这个时候就用到了折叠代码的功能,命令以z开头。
折叠的英文为fold,之所以没有用f开头,是因为与查找的命令f相冲突,我的速记法为z代表拼音zhe的首字母。
* `zc`:`c` 是 `close` 的缩写,表示关闭折叠。
* `zo`:`o` 是 `open` 的缩写,表示打开折叠。
* `zM`:`M` 是 `close all` 的缩写,表示关闭所有折叠。没有找到M的
* `zR`:`R` 是 `Reduce` 的缩写,表示递归打开折叠。
### 5.4 设置别名
适合一些经常在终端操作的命令,比如常用的git命令git status, git checkout, git merge。在终端输入命令vim \~/.bash_profle进入文件,并按照上文的写入方式输入想要设置快捷键的文本,设置快捷键命令为:
```js
alias {别名}="{执行的命令}"
```
下面是我常用的别名:
![image.png](https://file.jishuzhan.net/article/1772554020053848066/68e001566c566b176ad6486fbf23d685.webp)
### 5.5 改变一个单词
改变即change,命令以小写字母c开头,c是一个典型的"操作Operation",后面跟随操作范围的指示,改变一个单词的命令为ciw/caw
* `ciw` 命令用于编辑当前光标所在的单词。它会删除当前单词的内容并进入插入模式,让用户可以编辑该单词。
* `caw` 命令也用于编辑当前光标所在的单词,但它会删除当前单词的内容以及前后的空格,并进入插入模式,让用户可以编辑该单词。
速记,a表示around围绕的,i表示inner内容的。
其他的一些类似的操作+动作命令如:
d{Operation} 操作可以对一个完整单词(daw)或一整个段落(dap)进行删除操作,整条命令作用的范围由 Operation 后的动作命令决定。
c{Operation}和d{Operation}作用基本类似,不同的是c{Operation}从normal modal变成了insert modal,而d{Operation}维持原来的normal modal。
### 5.6 撤销操作
命令u(undo)表示撤销,将上一组命令动作,或者从普通模式到插入模式又重新回到普通模式之间的输入内容撤销。
反撤销,ctrl + r,撤销本次的撤销的动作。
### 5.7 命令组合技
整体可以以这个公式套用,
```js
{count}operator{motion/text_objects}
```
公式拆解后,常用的公式为:
```js
{count}{motion}
```
* 5j 光标向下五行
```js
{Operation}{text_objects}
```
* y2w 拷贝后面的两个单词
* y$ 拷贝到行尾
* yy 拷贝整行
* dit 删除标签内容的内容
* dt- 删除内容to文本"-"
```js
{count}{Operation}
```
* 3yy 复制3行的内容
### 5.8 跳转文档开头或结尾
* gg跳转到文档开头
* G跳转到文档结尾
## 六、进阶技巧
如果你已经是一名vim的老手,看了上面的内容估计也会有不同的理解,心中可能会想,"原来还可以这样",或者"我还有更简洁的命令步骤",以使用习惯出发,造成这种疑问的原因是,我们的目的相同,但是路径可能不同,欢迎相互讨论。
推荐一本进阶工具书:vim实用技巧(Drew Neil)
### 6.1 Don't repeat yourself
```js
const apple = 'a'
const pen = 'b'
const applepen = apple + pen
```
想要实现在语句结尾加分好的功能,想一下一般的步骤如何操作。
首先针对一行,输入"$"光标跳转到行尾,输入"a"进入光标后insert modal,然后输入内容";",然后按下"esc"回到normal model,按下"j"光标到下一行,接着重复上述的步骤;
优化思路1,将输入"$","a"命令合并成"A"命令,"A"代表行尾附加内容,"A"为"a"的复合命令;
优化思路2,输入"$"后,在输入"."命令重复输入内容";"的内容;
优化思路3,使用visual modal。
常用避免重复的命令还有:O,P,I
### 6.2 能够重复,就别用次数
在处理某些特定工作时,使用次数可以使按键次数变得最少,不过我们并不是非得这样不可。我们需要认真考虑次数与重复各自的优缺点。
```js
Delete more than one word
// 需要变成
Delete one word
```
* "2dw",代表执行2次dw的操作
* "d2w",代表删除2个单词
* "dw.",执行一个dw,并重复dw命令
想象一下,如果不小心多删除了一个单词,如何撤销呢?使用次数的好处是:它保留了一个干净、连贯的撤销历史记录。
### 6.3 不离开插入模式粘贴寄存器内容
插入模式下,使用正常的ctrl v可以正常将系统粘贴板的内容粘贴到光标位置,上面介绍过寄存器的功能,可以复制多个不同的文本,但是一般是在正常模式下使用p粘贴到对应的地方。此时在插入模式下想要粘贴内容,可以使用命令:
```js
<ctrl+r>
```
这样就可以实现在插入模式下想要粘贴内容,使得输入体验更连贯,组成一组动作便于实现可能的撤回操作。