前言
本系列教程适合零基础想要快速入手的(neo)vim初学者,同时作为LazyVim教程的前置教程。
很多人对vim的印象是密密麻麻的vim键位图,认为vim指令繁多,难以记忆。但事实上,这些并不需要特别去记忆,我们不需要背完键位表再开始使用,而是在使用的过程中逐渐熟悉我们常用的命令,再根据需要去拓展我们原本不熟悉的命令。
Vim除了键位繁多之外,给人的印象是,没有一眼就看出怎么用的界面引导,而又不想为了一个操作专门去搜索教程。网上的教程也往往是大肆罗列各种命令,令人头大。
以及,vim没有IDE那样的完善的集成好的开发环境。
事实上这些问题确实存在,但又不是完全无法克服。
vim有很多优秀的插件,可以提供方便又强大的功能,也有一些成熟的、开箱即用的配置框架。依托于LSP的兴起,Vim的编程体验不说比肩IDE,也足以满足大多数人的大多数要求。
同时vim能带来更高的可拓展性,用户可以根据自己的需要定制自己的编辑器,享受随心所欲的编辑体验。
本教程包括三个部分,第一部分介绍vim的基础知识,第二部分介绍LazyVim和其中包含的各类插件,第三部分引导读者进行简单的配置。
本文将介绍vim的基础知识,帮助读者熟悉vim中的一些常见概念。
如何阅读本文
本文简单地介绍了一些vim中的常见概念,读者不必牢牢记住所有内容,只需大致理解其逻辑即可。可以在原生的vim中稍作尝试,体验各种操作的细节。
本文主要为后续教程作铺垫,下面罗列命令,仅仅是为了让读者知道有这么一回事儿,大多数命令都不是刚需的。
后续教程会引导用户安装配置框架,届时会借助插件获取更方便快捷的体验,会用一些被广泛接受的快捷键替换原生命令。
模式
vim的特点是有多个模式,在不同的模式中进行不同的操作,这样可以缓解快捷键不够用的问题,也可以使我们不必像Emacs那样大量的使用Ctrl、Alt键,减少小指的压力。
vim共计有6中模式,分别为Normal(正常)、Command(命令)、Insert(插入)、Visual(可视),Replace(替换)和Terminal(终端)。。
该篇主要讲解Normal、Command和Insert模式。
Normal模式
Normal模式是我们进入vim后的默认模式。我们仅在有需求时进入其他模式,其余时间皆停留在Normal下。大多数操作都在Normal下完成。
此时我们输入的按键不会被解读为输入的字符,而是被解读为指令。因此我们不必大量使用Ctrl等按键也可以实现方便的输入指令。
该模式下我们主要进行移动光标到我们需要的位置以便后续其他操作或者仅仅阅读文字信息。
Normal模式下我们可以通过简单的按键进行光标的移动,以及一些回退等操作。
方向键
按键 | 操作 |
---|---|
h | 左 |
l | 右 |
j | 下 |
k | 上 |
跳转
按键 | 操作 |
---|---|
$ | 跳转到行尾 |
0 | 跳转到行首 |
^ | 跳转到行首非空字符 |
gg | 跳转到buffer第一行 |
G | 跳转到buffer最后一行 |
单词跳转
按键 | 操作 |
---|---|
w , b | 跳转到下一个,上一个单词开头 |
e , ge | 跳转到下一个,上一个单词末尾 |
回退,再执行
按键 | 操作 |
---|---|
u | 回退上一次操作 |
<C-r> | 重新执行上一次操作 |
删除
案件 | 操作 |
---|---|
d + 跳转命令 | 删除当前位置到跳转目标之间的内容 |
dd | 删除当前行 |
x | 删除光标下文字 |
搜索
Normal模式下,可以进行搜索,按/
后可以开始输入搜索内容,输入完后按下回车执行,可以使用按键快速在搜索结果之间跳转。 支持正则表达式。
按键 | 操作 |
---|---|
n , N | 跳转到下一个,上一个搜索结果 |
Command模式
vim除了按下按键发送指令外,还可以直接输入命令来执行。vim有一套自己专门的脚本语言vimscript,我们在命令模式下输入的便是这种语言,但我们一般只需要输入最简单的命令即可。
在Normal模式要输入命令,只需要按下:
即可进入Command模式,此时我们可以开始输入命令,命令一般会显示在左下角。
这里先介绍必要的几个命令
命令 | 含义 |
---|---|
:q | 退出 |
:w | 写入,即保存 |
:open filename | 打开文件,若不存在则创建 |
在:
和命令之间加!
表示在终端中运行。在命令后加!
表示强制执行。
在q
和w
之后加字母a
表示all,即退出全部、保存全部的意思。
在退出时,可能会询问是否要保存内容,若不想保存可以可以使用:q!
强制退出。
Insert模式
Insert模式是进行字符输入的模式,在Insert模式下大多数快捷键失效,输入的按键会被解读为字符,与一般的文本编辑器无异。
从Normal模式切换到Insert模式有很多种方式,我们只需根据自己的习惯掌握对应的方式即可。
- 按
i
,会在当前光标位置之前开始插入字符。比如如果当前光标(一般是方块状)落在这一句的‘比’字上,按i
将在‘比’字之前插入字符。 - 按
a
,会在当前光标位置之后开始插入字符。 - 按
o
,会在光标所在行的下一行开始插入。 - 按
I
,会在当前行的开头开始插入。 - 按
A
,会在当前行的结尾开始插入。 - 按
O
,会在当前行的上一行开始插入。 - 按
c + 跳转命令
,和d
相似,但会在删除内容后进入insert模式。
要退出Insert模式回到Normal模式,只需要按下<Esc>
即可,或者使用<C-[>
也可以。
<C-[>
是内置快捷键,与<Esc>
相同,由于<Esc>
一般离手比较远,所以很多人不喜欢,这个快捷键便出现了。
Visual模式
Visual模式用于选中文本,按v
可进入Visual模式,vim会选中进入处到当前光标之间的文本内容。在visual模式下,可以使用normal模式下相同的方式进行光标的移动。
Visual模式下可以使用一些按键对选中的文本进行操作,一般操作后自动退回Normal模式。
按键 | 含义 |
---|---|
y | 复制选中内容到寄存器 |
d | 删除选中的内容,并复制到寄存器 |
p | 粘贴当前寄存器的内容覆盖选中内容,再将选中内容复制到寄存器 |
c | 删除选中的内容,并进入Insert模式 |
Vim内部有一个独立的寄存器,用于保存在vim中复制的内容,与系统剪贴板并不互通。
若要与系统剪贴板互通,需要设置寄存器,再使用其他命令进行复制粘贴。本教程不打算涉及这方面,而推荐使用插件来实现vim与系统剪贴板互通。
Replace模式
介绍这个模式前先介绍一个与它关系紧密的命令。在Normal模式下,按下r
键再输入一个字符,这个字符会替换光标下原本的字符。比如你将光标移动到Normal的N上,按下rn
会将N替换为n。
如果按下R
键,会进入Replace模式。在该模式下,你可以想Insert模式下那样输入字符,但是你输入的内容会取代那个位置原本的内容,而不是插入。使用<Esc>
键推出该模式。
比如你可以将光标移动到以上段的Insert的I上,按下R
之后,输入Normal<Esc>
,Insert就会被Normal覆盖(字符数量一样)。
Terminal模式
neovim或新版vim支持内部打开终端。使用:term COMMAND
来打开终端,其中COMMAND
为要执行的命令,比如bash
,zsh
等。Terminal模式下,你的操作都会被传递给终端,可以和终端进行交互。
要退出该模式,输入快捷键<C-\><C-n>
。之后终端页面将会变成一个只读的缓冲区(缓冲区见下节),你可以使用vim的命令去操作,和你操作只读文件没什么不同,你可以自由的浏览和复制其中内容。
要再进入Terminal模式,只需按下i
键即可。
Vim的组成
Vim中有Tab(标签页)、Buffer(缓冲区)、Window(窗口)三个概念。
Vim的高效主要来自于其独特的模式编辑,但也与其Tab、Buffer、Window的紧密结合有关。
Buffer缓冲区
Buffer缓冲区用于存储内容,比如我们打开的文件,它的内容会被vim读取并存储在一个buffer中。
Vim中可以同时打开多个buffer,存储不同的内容,互相独立。我们可以在不同的buffer之间切换,实现多文件同时修改。
我们也可以将一些其它的文本内容加载到buffer中方便查看,比如当前的目录信息,tags列表,帮助文档等等。
buffer命令
按键 | 含义 |
---|---|
:ls | 显示所有buffer |
:bp | 切换上一个buffer |
:bn | 切换下一个buffer |
:bd | 删除buffer,后加索引删除指定buffer,不加删除当前buffer |
Window窗口
Window窗口用于显示buffer的内容,我们调用退出命令时退出的实际上是当前Window。所有windows被退出后,回到终端。
我们进入vim时会默认打开一个window,称为主window。
每个window只能显示一个buffer的内容,因此当我们打开多个文件、有多个buffer之后,只有最后一个buffer的内容会被显示在主window上。
但我们可以将主window分割为多个小window,实现同时查看编辑多个buffer,或者多个window可以同时显示或编辑同一个buffer不同位置的内容。
当我们有多个window时,输入指令:q
会关闭当前window,我们关闭一个window并不会删除该window正在显示的buffer。
因此我们使用vim时可以分割一小部分window用于显示一些内容,左侧显示当前目录树、右侧显示tags列表,下部显示终端等等。
Vim中可见的一切都是buffer和window,因此我们可以使用相同的操作逻辑操作可见的所有内容。这种基于TUI的界面的操作模式与其他基于GUI的编辑器相比,或许显得简陋,但也更具有连贯性,更加随心所欲。
Vim的编辑键位很多其他编辑器/IDE都有不错的插件实现,但往往仅仅局限于文本编辑区,其他部分仍然遵循原本的GUI操作。
window跳转
按键 | 含义 |
---|---|
<C-w>h | 跳转到左侧window |
<C-w>l | 跳转到右侧window |
<C-w>j | 跳转到下册window |
<C-w>k | 跳转到上册window |
window分割
按键 | 含义 |
---|---|
:split | 水平(上下)分割window |
:vsplit | 垂直(左右)分割window |
在分割后可以添加文件名,会在分割出的新window中打开该文件,否则会显示当前buffer。
Tab标签页
Tab就是标签页。Tab保存的是buffer和window的布局信息。
即window的分割情况,包括window的数量、位置、长宽等,以及每个window中显示哪一个buffer。
多个tab之间的buffer是互通的,仅仅window布局不同。
比如我们编辑一个文件时可能打开了很多其他window,我们希望保留这些布局但又需要打开新的文件、新的window,就可以创建新的tab,在不同tab之间可以随意转换,轻松驾驭复杂布局,不用每次都重新打开。
如果读者熟悉tmux,就会发现两者管理方式有很多共通之处。tmux中一个打开的shell就相当于vim中一个buffer,tmux中的panel则相当于vim中window,tmux的window则相当于vim的tab。不过tmux中的终端实例和panel是
对于熟悉其他编辑器的用户来说,可能会尝试这样使用vim的tab:在每个tab中分别打开一个文件,切换tab来实现切换文件。这样做是可行的,但并不是惯常用法。
惯常做法是通过buffer的切换来切换文件,因为切换tab会切换window布局,因此单纯想要切换正在修改的文件没必要切换tab。
标签页命令
按键 | 含义 |
---|---|
:tabs | 显示所有标签页 |
:tabnew | 创建新标签页 |
:tabp | 切换上一个标签页 |
:tabn | 切换下一个标签页 |
:tabc | 删除当前标签页 |
cwd
Vim和shell一样有CWD的概念,在vim中运行一些命令,比如:open
,需要使用相对路径的,都是根据vim的CWD来的。
你可以运行:pwd
来查看cwd,使用:cd
来切换。
在vim中每个tab的cwd是独立的,不会同步改变。
你可以设置让cwd跟随当前buffer改变,始终让当前buffer中的文件所在目录为cwd。一般不推荐这样做,如果你要运行一些项目级的命令,比如lsp相关,这通常需要知道你的项目根目录。
键位与宏
Vim的模式编辑使得vim中用户的所有操作都可以通过一系列按键事件表示。Vim中我们可以将一系列按键映射为一个键,按下这个键便相当于按顺序按下被映射到的一系列键。
因此我们可以直接将输入命令映射为一个键,比如将:bp<CR>
(<CR>``表示回车键) 映射到
H,这样我们按下Shift + h时,便相当于我们输入了
:bp`之后按下回车,实现buffer切换。
又比如我们可以将jj
映射到<ESC>
这样我们在Insert模式只需连按两下j就可以退出插入模式。
有关如何设置快捷键的问题,我们在后续的教程中会涉及。
Leader键
Vim中还有一个特殊的按键机制,称为Leader键。Leader键可以被用户指定为哪个键,而在键位映射中使用<leader>
指代这个键。
我们使用vim的过程中会出现快捷键越来越多,按键序列可能会越来越长,而且很多快捷键其实并不常用,如果绑定在字母按键上,容易误触。
于是我们有了一一个解决方案,就是统一指定一个键作为前缀键,用来存放相对没那么常用的功能。而只将最常用的部分功能映射到普通字母上。
以Leader开头的快捷键往往是按照键的意义,进行分级分类。比如buffer相关的操作,都以<leader>b
开头,相当于这些快捷键都被分到b这一分类中。类似的widnow相关的分到w
,tab相关的分到<TAB>
,terminal相关的分到t
。
又比如可以将一些常用插件,其相关的快捷键占用一个一级字母前缀,没那么常用的,和几个同类型的占用一个一级字母下的二级字母,或者快捷键数量不多的话混合起来。
Leader键可以由用户指定值,那么我们就既可以随我们心意去设置,也不必担心某个插件使用的Leader键和我们不同。
Vim中一般不使用Alt
, Ctrl
也很少使用,对我们的小指非常友好。
LocalLeader
Vim中除了Leader之外还有LocalLeader,特点是仅对当前buffer有效。这常用于某些只在特定场合下使用的快捷键,比如只对某个文件类型有用的快捷键。
若是有快捷键只在特定的场合下有效,那么就没有必要将其作为全局快捷键,因此另外使用一个键作为此类快捷键的前缀键是合适的。这同时使得同一个快捷键可以在不同场合下映射到不同的操作。
同时此类快捷键应当是只在特定场合下才加载的,关于如何在特定场合下加载快捷键,或者说加载配置,后面介绍autocmd时会详细介绍。
宏
Vim中同样提供宏的功能,并且相当便捷和强大。
由于在vim中所有操作基本都可以靠一系列按键事件来完成,因此vim中记录宏也就是记录我们按下的按键,在我们使用宏时原样敲一遍。
我们只需要按q+字母
之后敲下一个个按键或者输入命令(快捷键包括以Leader开头的都可以正常使用)这些指令就会被绑定到对应字母上,之后@+字母
就可以播放对应字母中绑定的宏。
被绑定的宏可以在vim中随意使用,甚至可以在不同的buffer中使用,但只会保存至当前vim实例退出。
重复
Vim中可以通过在指令前输入数字来将指令重复执行指定次数。比如,按下3j
,表示向下移动光标三次,3dd
表示删除当前行及其下两行。
这对于宏也同样适用。比如3@a
,表示播放字母a中绑定的宏三次。
总结
到这里基础篇就已经介绍完毕。读完本篇你应该已经对vim有了大致的了解。在下一篇中,将会介绍LazyVim的安装和配置,届时会介绍上面的操作在LazyVim中如何实现。