给 MinGW64 / MSYS2 配置一个简单的 Neovim
1. 废话
我本来没有给 Windows 配置开发环境,只装了个 MSYS2 ,给 MinGW64 装了一套最简单的工具链,因为一般都直接在我的另一台 ArchLinux 机器下进行开发,但是最近有时需要 #include "windows.h" 来对 Windows 进行适配(比如 argv 的编码这种 libstdc++ 没有解决/解决不了的问题),只用 Neovim 没有 completion 、没有 diagnostic 实在是难用,所以为什么不配置一个最简单的 Neovim 呢。
Q: 为啥不用 VSCode
A: 能避免 electron 就避免,感觉用久了会让我分辨不出巧克力味的屎和屎味的巧克力
Q: 为啥不用宇宙第一的 Visual Studio
A: 宇宙第一的称号不容置疑,但体积大又笨重也是不容置疑
Q: Windows 下 shell 性能一坨,为啥还要折腾 neovim - tui
A: 我是失败人士,失败人士配失败工具
2. 环境相关
我的 Windows 装了 MSYS2 ,目录为 C:/msys64 ,主要使用里面的 MinGW64 环境,里面提供了所有基本的开发工具,我主要用 neovim 进行编辑, gcc 用于编译, cmake 用于组织项目,因为 Python 之类的其他语言对于 Windows 的适配做的比较好,至少我目前没有遇到 Windows exlusive 的问题
MSYS2 中提供了很丰富软件包,以 C++ 开发为例, MinGW64 环境下需要安装:
mingw-w64-x86_64-toolchain包含了gcc,gdb一类的开发工具mingw-w64-x86_64-cmake用来组织项目mingw-w64-x86_64-neovim用来编辑mingw-w64-x86_64-clang提供了clang-format格式化工具mingw-w64-x86_64-clang-tools-extra提供了clangd,clang-tidy一类 lint 工具
当前 ArchLinux 下( 2023.11.01 )
extra/clang软件包包含了clang-analyzer和clang-tools-extra,而 MSYS2 则是分开的mingw-w64-x86_64-clang-analyzer和mingw-w64-x86_64-clang-tools-extra
3. neovim 基本配置
既然选择了编辑器中的原神 neovim ,自然要选择用 lua 做配置文件, neovim 在 vim 的基础上把许多功能设置为默认启用了,我设置的功能:
1 | vim.opt.cursorcolumn = true -- 高亮光标所在列 |
Windows 剪切板默认状态下是不可用的,其实 neovim 会尝试在 Windows 调用 win32yank 以实现剪切板功能,去 Releases · equalsraf/win32yank 里下载解压,把
win32yank.exe放进PATH里就可以。
4. 常用插件
写到这里的时候我在现实生活中发生了一件很重要的事,大体上是因为我过于失败引起的,总之痛苦、丑陋不堪的挣扎了几天,现在算是尽力处理了,但还不知道结果,所以心理状态可能有一些变化
既然决定用 lua 写配置文件了,那不如 lua 到底,尽量选择以 lua 为主语言编写的插件。
4.1. 插件管理器
之前我一直在用 vim-plug ,这绝对是一个简洁又好用的插件管理器,但现在我非要找一个更时髦,更 lua 的插件管理器,好评如潮的 packer.nvim 停止维护了,所以采用多半好评的 lazy.nvim ,项目里给了一段自动 clone 并加载自己的 lua 代码,可以放进 init.lua 里:
1 | local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim' |
这样就不用像我之前 clone 之后 ln 了,以后配置一个新的开发环境就真的只需要把 init.lua 复制过去。
在 init.lua 里是这种格式:
1 | require('lazy').setup({ |
4.2. OneDark 主题
之前一直在用 material.vim ,但它不够 lua ,所以打算换成 material.nvim ,用了之后发现这个东西有很多小问题,比如浮动窗口的背景颜色与普通的背景颜色相同,十分难以分辨、它会改变光标颜色,退出 neovim 不会恢复等等。所以改用一个看起来不错的 onedark.nvim ,用 lazy.nvim 加载这个插件:
1 | require('lazy').setup({ |
然后设置主题:
1 | -- 更丰富的色彩 |
4.3. 提示缩进等级
之前一直在用 indentLine ,但这个东西是 Vim Script 写的,而且也 archived 了,所以找到了一个功能更丰富的 indent-blankline.nvim ,用 lazy.nvim 加载这个插件:
1 | require('lazy').setup({ |
这里注册一个 <Leader>ii 来 toggle 缩进提示:
1 | local ibl = require('ibl') |
4.4. 更好看的 statusline
之前一直在用 vim-airline ,现在改用 lualine.nvim ,感觉自由度更高一些。用 lazy.nvim 加载这个插件:
1 | require('lazy').setup({ |
配置:
1 | require('lualine').setup({ |
5. 进阶配置
之前一直在用 coc.nvim ,现在看来这种完全另起炉灶的做法有点用力过猛,而且现在有点讨厌把 js/ts 放进开发环境里,所以决定使用 Neovim 内置的 LSP Client 。
5.1. LSP 支持
现在用 nvim-lspconfig ,算是比较方便了,用 lazy.nvim 加载这个插件:
1 | require('lazy').setup({ |
C++ 使用 clangd 作为 LSP Server ,在 mingw-w64-x86_64-clang-tools-extra 里,配置几乎是开箱即用:
1 | local lspconfig = require('lspconfig') |
Python 使用 pyright 作为 LSP Server ,但 MSYS2 貌似没有打包,可以先安装 mingw-w64-x86_64-nodejs ,用里面的 npm 安装 pyright ,虽然需要捏着鼻子用 ts/js ,但目前也没有更好的 LSP Server 了 。配置稍微复杂一点,因为 npm 安装的 pyright 不在 PATH 里,直接运行里面的 pyright-langserver 会因为环境不完整出现各种问题,所以我最后采用了这样的配置:
1 | local lspconfig = require('lspconfig') |
5.2. 快速注释
之前一直在用 vim-commentary ,现在看来也是简洁好用的插件,但还是不够 lua ,所以改用 Comment.nvim ,这个插件对块注释的支持更好一些,用 lazy.nvim 加载这个插件:
1 | require('lazy').setup({ |
项目 Readme 说要加
lazy = false。
gcc 是行注释, gbc 是块注释
5.3. LSP 符号列表
之前在用 Vista.vim ,这个插件虽然简洁可用,但有点过于简洁,自定义程度太低了,顺便不够 lua ,所以改用 symbols-outline.nvim ,用 lazy.nvim 加载这个插件:
1 | require('lazy').setup({ |
因为不喜欢图标所以换成 ASCII 字符:
1 | require('symbols-outline').setup({ |
5.4. 文件浏览器
之前在用 coc-explorer ,现在不用 Coc 体系了,所以换成 nvim-tree.lua ,用 lazy.nvim 加载:
1 | require('lazy').setup({ |
因为不喜欢图标所以禁用:
1 | require('nvim-tree').setup({ renderer = { icons = { show = { file = false, folder = false, folder_arrow = false, git = false, }, }, }, }) |
5.5. LSP 热键&指令
我绑了下面这些热键:
1 | -- <Leader>? 显示 hover 信息 |
这样可以实现高亮光标下的符号:
CursorHold事件触发与updatetime有关,想要更灵敏地触发CursorHold需要设置更小的updatetime比如我设置成500(毫秒)
1 vim.opt.updatetime = 500
1 | vim.api.nvim_create_autocmd({'CursorHold', 'CursorHoldI'}, { callback = function(opts) vim.lsp.buf.document_highlight() end }) |
定义 LspRefs 列出光标下符号的所有出现位置
1 | vim.api.nvim_create_user_command('LspRefs', function(opts) vim.lsp.buf.references() end, { nargs = 0 }) |
定义 LspRename 重命名光标下符号
1 | vim.api.nvim_create_user_command('LspRename', function(opts) vim.lsp.buf.rename() end, { nargs = 0 }) |
6. 小结
到现在为止的配置:
点击展开: init.lua
1 | vim.opt.cursorcolumn = true |
目前没有配置补全,因为加上补全时候卡顿十分严重,所以我个人觉得到这里就是极限了,现在大概像这样:

之后有动力给 Linux 的 neovim 做 migrate 的时候估计会补上补全部分,到时候再说吧。