

Neovim 问题解决及 VSCode Neovim 插件体验
你看着我好像在用 VSCode, 其实我在使用 Neovim
Neovim 配置#
我的 Neovim 配置使用了有一段时间了, 体验蛮不错, 不过有些偶尔遇到的小问题, 这次集中解决一下.
注释风格#
Neovim 中 C/C++ 默认的注释风格是 /* comment */
, 但是个人还是更加喜欢 // comment
的形式. 而且有的时候使用前者会导致代码乱掉.
解决方案: 安装 Comment.nvim ↗ 插件.
format 只能作用于整个文件#
解决方案: 来自 neovim - How to add keymapping for LSP code formatting in visual mode? - Vi and Vim Stack Exchange ↗, 注意将 vim.lsp.buf.format
放在 function
内.
vim.keymap.set('v', '<leader>fm', function()
vim.lsp.buf.format { async = true }
vim.cmd('normal! \27')
end, { noremap = true, silent = true })
lua报错信息容易超过窗口#
经常有报错信息太长在右边看不全或有好几个重复的报错信息.
解决方法: 让报错信息显示在 notify 中, 或使用 telescope 查看全部的报错.
nmap("<leader>da", require("telescope.builtin").diagnostics, "[D]i[A]gnostics")
nmap("<leader>ds", "<cmd>Lspsaga show_line_diagnostics<CR>", "[D]iagnostics [S]how")
luaNeovim 操作#
有一些操作之前用的少不熟练, 有些遗忘, 这次温习一下以及安装了一些增强插件.
打开链接#
gx
到行末操作#
Vim 中按下 $
表示到行末, 但是 $
比较难按, 有一些更加简单的操作:
A
: 在行末插入D
: 删除到行末C
: 删除到行末并插入cc
: 删除整行并在合适的缩进位置插入
text-object#
最常用的操作就是删除/重写. 例如想要重写括号中的参数, 就可以按 ci(
, 非常方便. 其他例如 {
和 "
等都可以用类似的方法. 例如删除一整个字符串以及引号, 可以使用 da"
.
另外, 这次我安装了 mini.ai 和 nvim-treesitter-textobjects 来增强 text-object 的功能, 可以应用到包括函数, 类以及参数. 此外, 还可以实现类似 “移动到上一个函数参数” 这样的功能.
部分关键的配置如下:
custom_textobjects = {
f = ai.gen_spec.treesitter({ a = '@function.outer', i = '@function.inner' }, {}),
p = ai.gen_spec.treesitter({ a = '@parameter.outer', i = '@parameter.inner' }, {}),
c = ai.gen_spec.treesitter({ a = '@class.outer', i = '@class.inner' }, {}),
},
lua重复命令#
这在类似如下的场合特别有用:
enum class Color {
Red;
Blue;
Green;
};
cpp显然这里不应该使用 ;
, 但有的时候就是会有些不小心. 要方便地更改它们, 可以先将光标移动到 Red
上, 之后 A backspace ,
完成修改, 按 j
移动到下一行, 使用 .
就可以在这一行重复上一行的操作了.
VSCode Neovim 插件体验#
众所周知 VSCode 编辑器非常强大, 可以使用各种插件. 特别是在 debug 等方面, 要使用 Neovim 的话就不得不配置很久, 而 VSCode 可以基本上算是开箱即用. 我个人也没有安装 dap 等 debug 用的插件, 因为我认为 Neovim 它就不是用来干这活的. 对我来说, 使用 Neovim 是因为它的轻便优雅, 以及各种提高效率的插件, 例如 flash.nvim. 现在的我在敲代码时已经离不开 Neovim 这一套的操作逻辑了.
但是 VSCode 的各种功能也确实很香, 虽说也可以用它的 vim 模式, 但是少了一些插件还是用着不顺手. 怎样才能 “我全都要” 呢? 可以试试 VSCode Neovim 插件. 它使用 Neovim 程序本身作为后端, 这样很多在 Neovim 中才能用的插件在 VSCode 中也能用了. 由于它使用真正的 Neovim, 所以配置文件也是同一个. 不过之前听说 BUG 比较多没有尝试. 现在过去很久功能应该也完善了, 趁有空赶紧体验一下.
VSCode 安装与在 Wayland 下运行#
参考 Visual Studio Code - Arch Linux 中文维基 ↗, 直接使用 yay -S visual-studio-code-bin
安装即可.
由于我使用的是 Wayland, electron 不兼容, 所以还需要额外加上下面这些选项:
code --unity-launch --enable-features=UseOzonePlatform,WaylandWindowDecorations --ozone-platform=wayland --enable-wayland-ime --disable-gpu --disable-gpu-sandbox
bash我需要将它们加入到 code.desktop
中, 以及在 .zshrc
中设置 alias
, 方便直接从命令行打开. 下面是除了 code .
以外的一些常用的命令:
code -r . # -r 复用窗口打开目录或文件
code -g package.json:128 # -g 指定文件名及行号
code -d a.txt b.txt # -d 比较两个文件的内容
ls | code -
bash初始配置#
首先, 安装 Code Runner 插件, 尝试运行代码. 具体可以参见 VS Code - OI Wiki ↗. 其次可以安装喜欢的主题或设置字体字号等.
个人的额外基础配置:
"window.titleBarStyle": "custom",
"editor.lineNumbers": "relative", // 相对行号
"editor.cursorSurroundingLines": 5,
"editor.minimap.size": "fill",
"editor.colorDecorators": false,
"editor.inlayHints.enabled": "off",
json在安装 Neovim 插件之前, 你可以去 Github 仓库查看一下文档. 文档中有提到, 对于代码补全等, 我们应该优先使用 VSCode 中插件的功能, 所以大部分在原生 Neovim 中使用的插件是不需要的.
使用 vim.g.vscode
变量可以判断是否在 VSCode 中. 在第一次使用 VSCode Neovim 前, 可以先修改 init.lua
隔绝不必要的配置. 例如在我的配置中:
vim.loader.enable()
require [[config.option]]
if not vim.g.vscode then
require [[config.lazy]]
end
require [[config.keymap]]
lua现在安装 VSCode Neovim 插件, 测试基本功能都正常后, 可以将 init.lua
恢复原样, 进行更细化的配置.
按键映射#
有些按键映射需要修改以调用 VSCode 自己的功能. 调用的 ID 可以在 VSCode 的 Keyboard Shotcuts 中查看. 你需要使用 vim.g.vscode
来让 VSCode 知道选择哪个. 下面是一些个人的修改:
map("n", "<leader>q", "<Cmd>lua require('vscode').call('workbench.action.closeWindow')<CR>")
map("n", "<Tab>", "<Cmd>lua require('vscode').call('workbench.action.nextEditor')<CR>")
map("n", "<S-Tab>", "<Cmd>lua require('vscode').call('workbench.action.previousEditor')<CR>")
map("n", "<leader>x", "<Cmd>lua require('vscode').call('workbench.action.closeEditorInAllGroups')<CR>")
map("n", "<leader>r", "<Cmd>lua require('vscode').call('editor.action.startFindReplaceAction')<CR>")
lua上面的映射分别是退出 VSCode, 按 Tab 切换代码页面, 关闭当前代码页面, 替换 (我的 Ctrl-F 被覆盖了)
在 VSCode 中也要进行特殊的设置. 主要是使这些按键交给 Neovim 处理. 一个是更改设置中的 ctrlKeysForInsertMode
, 另一个是在 Keyboard Shotcuts 中增加下面类似的内容.
{
"key": "alt+j",
"command": "vscode-neovim.send",
"args": "<A-j>"
},
{
"key": "alt+k",
"command": "vscode-neovim.send",
"args": "<A-k>"
}
json插件配置#
Lazy.nvim 插件管理器提供了 cond
参数, 我们可以用 cond = not vim.g.vscode
来让插件在 VSCode 中不启用. 我启用的插件只有如下几个:
'brenoprata10/nvim-highlight-colors',
'wakatime/vim-wakatime',
"rainbowhxch/accelerated-jk.nvim",
"folke/flash.nvim",
'numToStr/Comment.nvim',
lua对于使用 jk
来 escape
, VSCode Neovim 插件文档中指出了更好的做法:
"vscode-neovim.compositeKeys": {
"jk": {
"command": "vscode-neovim.escape",
},
"kj": {
"command": "vscode-neovim.escape",
},
}
cpp对于 telescope 打开文件等, 我个人使用了 FindItFaster 这个插件, 配合以下的按键绑定:
map("n", "<leader>ff", "<Cmd>lua require('vscode').call('find-it-faster.findFiles')<CR>")
map("n", "<leader>fg", "<Cmd>lua require('vscode').call('find-it-faster.findWithinFiles')<CR>")
map("n", "<leader>tf", "<Cmd>lua require('vscode').call('find-it-faster.findFilesWithType')<CR>")
map("n", "<leader>tg", "<Cmd>lua require('vscode').call('find-it-faster.findWithinFilesWithType')<CR>")
lua对于行内显示警告与错误, 使用 Error Lens 插件.
遇到的问题#
暂时还没怎么用, 只遇到以下几个问题.
VSCode 的代码补全和 Neovim 的不太一样, 还是更习惯按一下 Neovim 的 Tab
用法, 但是 VSCode 还要额外再多按一次 Enter
, 让我很不舒服. 暂时只做了这样的按键映射:
{
"key": "tab",
"command": "selectNextSuggestion",
"when": "editorTextFocus && suggestWidgetMultipleSuggestions && suggestWidgetVisible"
},
{
"key": "shift+tab",
"command": "selectPrevSuggestion",
"when": "editorTextFocus && suggestWidgetMultipleSuggestions && suggestWidgetVisible"
}
jsonclangd 的 inlay hints 无法设置显示在行尾, 并且 Neovim 的拓展也移除了这个功能. 也有可能是我没有找到对应的选项.
最后就是代码高亮问题了. 这个问题浪费了我一下午. 总之还是很迷惑.
- 更改下面的配置后, 代码高亮才正确 (和语义相关联).
- 虽然正确了, 但是和 Neovim 中的不一样.
- 虽然正确了, 但是和 Dark Modern 还是有区别, 例如
operator
的着色. - 此问题可能并不是 Rosepine 主题的问题, 因为 Dark (Visual Studio) 等默认主题也有问题.
"editor.semanticHighlighting.enabled": true,
jsonNeovim:
VSCode Dark Modern:
VSCode Rosepine: