打造vscode般的neovim
偶然在Youtube上看到一个大佬的Neovim配置教程,深入浅出,逻辑条理,加了一点自己的内容,就产生了这么一个授人以渔的教程。
打造VS Code般的Neovim
一点废话
Neovim是什么就不过多介绍了,有兴趣可以自行Google,没兴趣那我就一句话介绍Neovim:
一个可以变得很好看很好用的基于TUI的文本编辑器。由于Vim拒绝了两个大补丁,作者一怒之下开的新分支。- Neovim是一个积极重构Vim的项目,旨在简化维护和鼓励贡献,在多个开发人员之间分配工作,在不修改核心的情况下创建高级UI,最大化可扩展性。
就是单纯用vim觉得丑,所以跑路,尝试配置一个媲美VS Code体验的Neovim。教程来自于油管一个大佬,讲的很不错,不像某些教程,只告诉你怎么做,不告诉你为什么。这里附上链接,有兴趣可以自行观看。Neovim for Newbs. FREE NEOVIM COURSE - YouTube
后面的内容有一个很重要的宗旨,你不是非得按照这个文档描述的步骤一步一步来做,这个文档最重要的目的是告诉你Neovim配置的方法。当你学会这个方法之后,可以完全自定义想要的内容。当然,这个时代不一定非要自己造轮子,github上有很多别人配置好的预制菜,你只需要clone下来就可以用。但本文档可以让你了解整个流程,在抄别人作业过程中遇到问题可以自己解决掉。
依赖
安装之前,你大致需要以下这些依赖工具,请确保环境中已经安装。
1 |
|
安装Neovim
官方仓库:neovim/neovim
Windows系统可以直接下载zip包,解压到任何位置,然后运行nvim.exe
。
Linux下可以下载nvim.appimage
,然后执行chmod u+x nvim.appimage && ./nvim.appimage
。
安装好后在终端里运行nvim
,就能得到下图。
安装Nerd fonts
我建议在安装完Neovim后先把字体安装好,后面用到的一些美化插件是比较依赖于Nerd fonts
的。打开官方网站Nerd
Fonts,选一个喜欢的字体下载。这里推荐Hack Nerd Font
。
Windows下只需要双击ttf文件,点击安装即可。
Linux下需要执行以下步骤。
1 |
|
初始化配置文件
Neovim的配置全部是基于lua
的,所以后面创建的所以脚本均为lua
脚本。
创建初始化配置文件init.lua
,进行一些基础配置。
Windows中配置文件放在
C:\Users\username\AppData\Local\nvim
下;Linux中放在
~/.config/nvim
下
1 |
|
然后在命令模式下执行source %
,激活当前配置文件。
插件管理器
目前主流的插件管理器有两个:lazy
和packer
。
官方仓库:
两个包管理的差别不大,为了贯彻好看的宗旨,这里我们选择lazy
作为包管理器。
安装lazy
非常简单,只需要将README中Installation部分的语句复制粘贴到init.lua
中即可。下面这些语句实现的大致功能为,为lazy
指定一个存放数据的目录,然后检查lazy
是否被安装,若没有则从github
上拉取安装。
这里注意要修改一下链接,将仓库链接从
https
协议改为ssh
协议。如果你的网络条件支持稳定的通过https
访问github
,那当我这句话没说过。
1 |
|
然后我们创建两个变量来存放插件和选项,并调用setup()
函数来配置它。这个setup()
函数将伴随整个插件配置过程,具体细节无需关心,毕竟我们也不写lua
,我们只是lua
的搬运工。
1 |
|
完成上面的步骤后,同样source %
激活一下,这里可能会卡顿一会儿,因为此时后台在从github
上拉取并安装lazy
。
安装好后,命令模式下执行: Lazy
就可以打开lazy
的管理界面了。
主题
主题这里,大佬推荐catppuccin
,确实挺好看,无脑跟!
官方仓库:catppuccin/nvim
有了lazy
,安装这些插件及其简单,只需要将下面这行放入我们上一步中创建的plugins
变量中。
1 |
|
此时:q
退出Neovim,然后重新打开,你会发现lazy
管理界面跳了出来,然后提示你正在安装。等待一会儿就可以看到,主题颜色已经变了。但还没结束,现在主题颜色变了只是因为lazy
帮你安装完成后自动加载了该插件。如果此时你再退出重开一次,会发现主题又变回了默认状态。我们需要再添加两行代码,将默认的主题配置成catppuccin
。
1 |
|
到此,catppuccin
就配置完成了,不出意外你将得到下面这样的状态。
核心插件
Telescope
telescope
是一个基于列表模糊查找器,可以用来查找文件。其他更高级的功能可以参考官方仓库。
安装插件同样及其简单,在plugins
变量中增加一项即可。
1 |
|
退出Neovim再重新打开,你又会看到lazy
在帮你安装插件。
上图是已经安装好的状态。然后在init.lua
中对telescope
进行一些配置。这里主要介绍两个功能,基本能够满足需要,其余的功能可以参考官方仓库自行配置。
文件搜索
在init.lua
中添加如下两行。
1 |
|
再重开Neovim,然后按Ctrl + P
就可以打开telescope
,输入文件名即可搜索文件。
字符搜索
同样在init.lua
中添加语句。
1 |
|
配置完后:source %
一下,按上面配置好的快捷键即可打开字符搜索。下图是一个搜索lazy
字符串的例子。
到这一步可能会出现一个问题,搜索框可以正常打开,但是搜什么都是空白的。原因是缺少一个依赖工具
ripgrep
,只需要按官方仓库的提示安装即可。
ripgrep
官方仓库:BurntSushi/ripgrep安装Installation章节的提示安装即可。
- Windows下执行
winget install BurntSushi.ripgrep.MSVC
。- Linux下,以Ubuntu为例执行
sudo apt-get install ripgrep
。其余操作系统官方仓库中写的都很清楚,安装完成该工具,重启终端并打开Neovim就可以正常使用了。
Treesitter
treesitter
是一个基于语法树的语法高亮插件。
安装过程类似,还是在plugins
中加入一行。
1 |
|
重启Neovim,lazy
会帮你安装,然后对其进行配置。
在配置
treesitter
之前,请确保你的系统路径中有可用的C编译器,gcc
、clang
、MSVC
都可以。如果你是Windows用户,要确保开启开发者模式。打开
设置 -> 系统 -> 开发者选项 -> 开发人员模式
。
在init.lua
中添加如下代码。
1 |
|
此时:source %
一下,treesitter
就会开始安装语言相关的内容。安装完后会发现,当前打开的这个lua
脚本已经拥有了语法高亮。
你可以用:TSInstall
来安装新的语言支持,用:TSModuleInfo
来查看已经支持的语言。
Neo-tree
neo-tree
,就如同该插件的名称一样,是一个文件tree
。同样在plugins
中添加。
1 |
|
重启Neovim,等待lazy
安装插件,安装完成后即可使用neo-tree
。
输入命令:Neotree filesystem reveal left
就可以在左侧显示文件树了。当然,为这条命令设置一个快捷键会更方便。
1 |
|
这里为了保持VS
Code的习惯,设置成了Ctrl + b
,你可以根据自己的习惯来配置。
模块化插件配置
配置到这里聪明的你可能已经发现一个问题了,我们所有的配置都集中在同一个文件init.lua
中,这显然是不合理的。所以我们接下来将之前所做过的所有配置,拆分开来,同时体验一下neo-tree
带来的便利。
按下Ctrl + b
打开文件树,按a
创建文件夹及文件lua/plugins.lua
。将我们之前的plugins
变量丢进plugins.lua
脚本中,然后返回该变量,脚本内容如下。
1 |
|
然后将init.lua
中的plugins
变量删除,并修改下面的语句。
1 |
|
我们创建的plugins.lua
脚本相对init.lua
的路径为./lua/plugins.lua
,这里只需要写"plugins"
即可,lazy
会自动找到这个路径。重启Neovim确保工作正常。
但是这样的模块化依然不够,这只是将依托答辩从旱厕搬进了马桶,并没有好多少,所以我们需要对插件配置进一步拆分。
在lua
文件夹下创建plugins
文件夹,在plugins
文件夹下创建我们第一个配置的插件catppuccin
对应的脚本,命名为catppuccin.lua
。
此时左下角提示
Config Change Detected. Reloading...
,这都要归功于lazy
插件管理器,它会实时的检测插件配置的变换,自动帮你重新加载。
将plugins.lua
中关于catppuccin
的配置都转移到catppuccin.lua
中,同样的方式进行返回。
1 |
|
同时init.lua
中还有一些关于catppuccin
的配置。
1 |
|
想要将这些配置也搬入catppuccin.lua
脚本,就需要用到lazy
提供的一个配置项config
。这个config
需要我们定义一个函数,在函数体中对插件进行配置。同时,使用config
就相当于自动调用了require("...").setup(opts)
。所以我们对catppuccin.lua
进行修改。
1 |
|
至此就实现了catppuccin
插件的模块化,其他的所有插件都是同理的。我们将所有的插件都模块化,最终得到这样的文件结构。
现在我们的init.lua
已经比之前简洁多了,这种模式可以更方便的管理插件,并且可以随时添加新的插件,只需要添加一个新的lua
脚本即可。
到这一步,我们之前用作过渡的
plugins.lua
脚本就可以删掉了,因为lazy
会去找plugins
文件夹下的子模块。
但是!init.lua
中还有一些关于Vim的基本配置,这些配置如果慢慢增多,还是会导致init.lua
混乱不堪。所以我们将关于Vim的配置一并模块化。
在lua
文件夹下创建一个名为vim-options.lua
的脚本,将init.lua
中关于Vim配置的语句全部丢进去。
同时在init.lua
中添加一句。
1 |
|
代码相关插件
LSP
先来说说什么是LSP,下面是wiki对于LSP的定义:
The Language Server Protocol (LSP) is an open, JSON-RPC-based protocol for use between source code editors or integrated development environments (IDEs) and servers that provide "language intelligence tools": programming language-specific features like code completion, syntax highlighting and marking of warnings and errors, as well as refactoring routines. The goal of the protocol is to allow programming language support to be implemented and distributed independently of any given editor or IDE.
感觉还是有点抽象,我觉得视频中的大佬解释的非常形象,这里转述一下。
将编辑器想象成客户端,LSP想象成服务器。编辑器打开一个文件的时候,会向LSP发送一个DID OPEN
信号,告知LSP目前打开了一个文件。当文件发生任何改动的时候,会向LSP发送一个DID UPDATE
信号,告知LSP代码被更改过。此时LSP会返回一个JSON文件,其中包含了类似下面这样的信息,告知编辑器哪里有错误、警告等等。
1 |
|
所以,编写代码的过程中,能够有这样一个LSP提示错误和警告是非常必要的功能。
LSP管理
创建一个lsp-config.lua
脚本来配置LSP。首先需要一个插件Mason
,可以帮助我们很方便的安装各种语言的LSP、Linter、Formatter等。
Mason官方仓库:williamboman/mason.nvim
脚本中添加如下内容。
1 |
|
重启Neovim等待安装完成,输入:Mason
即可打开mason
的管理界面,在这里可以看到各种LSP、Linter、Formatter等。
LSP配置
除了mason
我们还需要另一个工具mason-lspconfig
来辅助配置mason
的LSP。修改lsp-config.lua
脚本如下。
1 |
|
各种编程语言对应的LSP服务名称可以参考官方仓库的READMEavailable-lsp-servers。这里选择预装了
lua
、C/C++
、python
的LSP服务。
重启Neovim等待安装,输入:Mason
检查是否安装成果,不出意外你会得到如下所示的状态。
这里有一个需要注意的地方,有些LSP是基于
node.js
和npm
包管理器的,所以请确保你的环境已经安装了node.js
。同时,如果你使用了代理,请给
npm
也配置代理,具体方法自行Google。
LSP客户端
接下来我们还需要用到一个叫做nvim-lspconfig
的插件,使得Neovim能够和LSP进行通信
继续修改lsp-config.lua
脚本如下。
1 |
|
老样子,重启Neovim等待安装,然后输入:LspInfo
查看当前LSP服务的状态。
可以看到检测到一个客户端,所配置的LSP服务叫做lua_ls
。
然后配置一些快捷键,以便进行LSP相关的操作。
1 |
|
代码格式化
这里用到一个名为null-ls
的插件,通过和特定语言的formatter配合进行操作,这里的formatter通过mason
来安装。
添加none-ls.lua
配置脚本。
1 |
|
这里配置了lua
、C/C++
和Python
的formatter。
代码自动补全
关于代码自动补全,有一系列的插件,这里推荐先捋清它们之间的关系。我们先列出可能用到的插件并附上仓库链接:
nvim-cmp
(hrsh7th/nvim-cmp);LuaSnip
(L3MON4D3/LuaSnip);cmp.luasnip
(saadparwaiz1/cmp_luasnip);friendly-snippets
(rafamadriz/friendly-snippets);cmp.nvim.lsp
(hrsh7th/cmp-nvim-lsp)。
nvim-cmp
是一个代码补全引擎,可以根据输入来显示补全信息。nvim-cmp
这个补全引擎只能提供代码补全的能力,它本身并没有补全的”素材“。这时就需要一些第三方插件来提高代码补全的来源,也就是“素材”(Snippets
),并赋予这些Snippets展开的能力。
LuaSnip
是一个lua
写的Snippets
引擎,它属于扩展Snippets
的工具。是为nvim-cmp
提供服务的。
cmp.luasnip
则是LuaSnip
的“素材”来源,它为nvim-cmp
提供一系列可能的Snippets
,然后LuaSnip
会将这些Snippets
展开。
friendly-snippets
是一个针对不同编程语言的Snippets
集合,可以将不同语言的“素材”集中在一起,并使得LuaSnip
可以加载。
cmp.nvim.lsp
也是一个Snippets
来源,但可以从任何缓存中存在的LSP来获取“素材”。
解释清楚上述几个插件的关系后,就可以开始配置了。先来进行nvim-cmp
的基本配置,初步配置文件如下所示。
1 |
|
接下来配置LuaSnip
及其Snippets
来源:cmp.luasnip
、friendly-snippets
。将上面对nvim-cmp
的配置放入一个{}
中,然后在它的上面再创建一个新的{}
,内容如下。
1 |
|
然后需要在nvim-cmp
的配置中添加一行。
1 |
|
重启Neovim就发现,现在已经有了一定程度的代码补全能力。
最后安装cpm.nvim.lsp
来提高补全的质量,使得引擎能从LSP中获取Snippets
。同样地,在上面脚本的基础上再添加一个{}
。
1 |
|
同时,在lsp-config.lua
脚本中关于nvim-lspconfig
插件的配置中增加一项,并在所配置的每一项LSP中增加语句,内容如下。
1 |
|
再次尝试代码补全,发现补全的来源中已经多了来自LSP的内容。
Debugger
在安装Debugger之前,我们需要介绍一个概念叫做Debug Adapter Protocol
(DAP)。也许你在之前配置LSP的时候就已经在Mason
中见过这个缩写了。DAP是微软为VS
Code开发的,是为了使得编辑器和Debugger能够顺畅的交流。视频中的大佬描述的非常形象,编辑器和Debugger就像酷酷的西部牛仔一样,每个人都有自己交流的方式,而DAP站出来对Debugger说“Let's
make things
easier.”。DAP提供了一套通用的API,使得不同语言的不同Debugger能够使用这一套API为编辑器提供统一的格式,而编辑器要做的只是利用DAP提供的这套统一格式而已。
其实这套概念和LSP有点类似。我们需要一个服务端,也需要一个客户端。服务端我们可以借助Mason
来安装,客户端我们这里用到的是nvim-dap
,是一个为Neovim实现的DAP客户端。
同时我们还需要一个叫做nvim-dap-ui
的UI插件来辅助Debugger工作。然后进行一些配置使得UI能够根据DAP自动打开或关闭。
官方仓库:rcarriga/nvim-dap-ui
新建一个debugger.lua
的配置文件。
1 |
|
除了上面的配置,我们还需要针对你要debug的语言安装对应的DAP,并在nvim-dap
中配置。这里以C/C++为例,使用codelldb作为DAP。首先在Mason
中安装codelldb,然后对nvim-dap
进行如下配置。
1 |
|
用一个简单的C程序测试一下。
美化插件
lualine
lualine
是一个非常美观的底部状态栏。安装它只需要在plugins
下添加一个lua
脚本即可。
1 |
|
重启Neovim,然后就得到了如下图所示的效果。
好好好,越来越像VS Code了。
Telescope-ui-select
该插件是telescope
插件的一个扩展,可以配合vim.lsp.buf.code_action()
使用,使其以一种悬浮窗的形式显示,而不是底部命令栏。
alpha-nvim
该插件可以提供一个类似于VS Code的欢迎界面,配置脚本如下。
官方仓库:goolord/alpha-nvim
1 |
|
header
和buttons
两项配置是最具有可玩性的,官方仓库中有许多用户提供了他们自定义的配置文件。上面的最简配置文件效果如下图所示。
快捷键列表
经过上面的一系列配置,我们就得到了下表中的功能。
编辑器相关
快捷键 | 功能 |
---|---|
<C-p> |
文件模糊搜索 |
<leader>fg |
字符串搜索 |
<C-b> |
打开文件树 |
LSP相关
快捷键 | 功能 |
---|---|
K |
悬浮窗显示函数信息 |
gD |
转到声明 |
gd |
转到定义 |
gi |
转到实现 |
<C-k> |
函数签名帮助信息 |
<leader>rn |
重命名 |
<leader>ca |
代码动作 |
<leader>gf |
代码格式化 |
DAP相关
快捷键 | 功能 |
---|---|
<leader>b |
添加断点 |
<F5> |
开始/继续执行 |
<F6> |
终止debug会话 |
<F7> |
重新开启debug会话 |
<F9> |
单步执行 |
<F10> |
单步跳出 |
<F12> |
逐过程执行 |
写在最后
上面讲了这么多插件,但依然希望你不要教条的按照这个教程来做,重要的是学会配置的方法,同时善用Google寻找更加优秀的插件。当然,最推荐的还是直接抄作业,在巨人的肩膀上进行自定义。
打造vscode般的neovim