Neovim是 Vim 的一个分支,具有更大的可扩展性和集成性。该扩展使用完全嵌入的 Neovim 实例,不再是半完整的 Vim 模拟! VSCode 的本机功能用于插入模式和编辑器命令,从而充分利用这两种编辑器。
- 利用 Neovim 作为后端,几乎完全功能完整的 Vim 集成。
- 支持自定义init.vim和许多 Vim 插件。
- 一流且无延迟的插入模式,让 VSCode 做它最擅长的事情。
- 与 VSCode 功能(lsp/自动完成/片段/多光标/等)完全集成。
安装
- 安装vscode-neovim 扩展。
- 安装Neovim 0.9.0或更高版本。
- 在扩展设置中设置 Neovim 路径。您必须指定 Neovim 的完整路径,例如“ C:\Neovim\bin\nvim.exe”或“ /usr/local/bin/nvim”。
- 设置 ID 为“ vscode-neovim.neovimExecutablePaths.win32/linux/darwin”,与您的系统相关。
- 如果您想从 WSL 使用 Neovim,请设置useWSL配置切换并指定 nvim 二进制文件的 Linux 路径。为此需要wsl.exeWindows 二进制文件和Linux 二进制文件。必须通过Linux 环境设置可用。用于检查正确的默认 Linux 发行版。wslpathwslpath$PATHwsl --list
- 分配亲和力值以提高性能。
- 转到“设置”>“功能”>“扩展”>“实验亲和力”。
- 添加项目名称asvetliakov.vscode-neovim和值 1 的条目。
- 或者
- 添加到您的settings.json:
- "extensions.experimental.affinity": { "asvetliakov.vscode-neovim": 1 },
Neovim 配置
由于许多 Vim 插件可能会导致 VSCode 出现问题,因此建议从空的init.vim.有关支持哪些类型的插件的指南,请参阅故障排除。
在 Github 上创建问题之前,请确保您可以使用空init.vim且无 VSCode 扩展来重现问题。
要确定 Neovim 是否在 VSCode 中运行,请添加到您的init.vim:
if exists('g:vscode')
" VSCode extension
else
" ordinary Neovim
endif
在lua中:
if vim.g.vscode then
-- VSCode extension
else
-- ordinary Neovim
end
要有条件地激活插件,vim-plug有 一些解决方案。packer.nvim并lazy.nvim 内置对cond = vim.g.vscode.有关配置 Vim 插件的提示,请参阅 wiki 中的插件。
VSCode 配置
- 在 Mac 上,按住h、j和k移动l键时可能不会重复,要修复此打开的终端并执行以下命令: defaults write com.microsoft.VSCode ApplePressAndHoldEnabled -bool false。
- 要修复重新映射的转义键在 Linux 中不起作用的问题,请设置"keyboard.dispatch": "keyCode"
提示和功能
VSCode 具体差异
- 文件和编辑器管理命令(例如:e/ :w/ :q/ :vsplit/ :tabnext/etc)映射到相应的 VSCode 命令,并且行为可能有所不同(见下文)。不要在脚本/键绑定中使用 vim 命令:w,它们将不起作用。如果您在某些自定义命令/映射中使用它们,您可能需要重新绑定它们以从 Neovim 调用 VSCode 命令 require('vscode-neovim').call()(请参阅API)。
- 当您键入某些命令时,它们可能会被替换为另一个命令,例如:write将被替换为:Write。
- 滚动是由 VSCode 完成的。C-d/ C-u/等略有不同。
- 编辑器自定义(相对行号、滚动等)由 VSCode 处理。
- 点重复 ( .) 略有不同 - 在更改范围内移动光标不会中断重复。顺序。在 Neovim 中,如果您abc
在插入模式下键入,则将光标移至a bc并1 在此处键入重复序列将为1。然而,在 VSCode 中,它将是a1bc.另一个区别是,当您在插入模式下删除某些文本时,点重复只能从右到左工作,这意味着在运行点重复时它将Del把键视为键。BS
故障排除
- 将设置设置vscode-neovim.logLevel为“info”,然后重新启动 vscode。通过查看日志 Output: Focus on Output View并选择vscode-neovim。
- vscode-neovim.neovimClean在 VSCode 设置中启用,这将在没有插件的情况下启动 Nvim ( nvim --clean)。 Nvim 插件可以做任何事情。视觉效果尤其会导致视觉伪影。 vscode-neovim 尽力融合了 Nvim 和 VSCode 的视觉效果,但它还远非完美。您可能需要禁用一些导致视觉效果的 Nvim 插件。
- 如果遇到渲染问题(视觉伪影),请尝试CTRL-L强制 Nvim 重绘。
- 如果收到该Unable to init vscode-neovim: command 'type' already exists消息,请卸载使用的其他 VSCode 扩展registerTextEditorCommand("type", …)(例如 VSCodeVim或 Overtype)。
其他扩展
如果您遇到任何性能问题(通常是光标抖动),请确保您没有使用这些类型的扩展:
- 任何经常渲染装饰器的东西:行号扩展(VSCode 内置了对普通/相对行号的支持)缩进指南扩展(VSCode 具有内置缩进指南)括号荧光笔扩展(VSCode 具有内置功能)
- 延迟扩展主机的 VSCode 扩展,例如“Bracket Pair Colorizer”
- Vim 插件会增加延迟并导致性能问题。确保禁用不需要的插件,因为其中许多插件对 VSCode 没有意义,并且可能会导致问题。您不需要任何代码、突出显示、完成、LSP 插件以及任何生成窗口/缓冲区(nerdtree 和类似)、模糊查找器等的插件。许多导航/文本对象/编辑插件应该没问题。
如果您不确定,请禁用所有其他扩展,重新加载 VSCode 窗口,并在报告之前查看问题是否仍然存在。
复合退出键
由于 VSCode 负责插入模式,因此自定义插入模式 Vim 映射不起作用。要映射复合转义键,请放入 keybindings.json 中:
为了jj
{
"command": "vscode-neovim.compositeEscape1",
"key": "j",
"when": "neovim.mode == insert && editorTextFocus",
"args": "j"
}
要启用jk还添加:
{
"command": "vscode-neovim.compositeEscape2",
"key": "k",
"when": "neovim.mode == insert && editorTextFocus",
"args": "k"
}
目前,无法同时映射jk和kj,或者在jk不映射 的情况下进行映射jj。
跳转列表
使用 VSCode 的跳转列表而不是 Neovim 的。这是为了使 VSCode 原生导航(鼠标单击、跳转到定义等)可通过跳转列表进行导航。
如果您使用自定义映射,请确保绑定到
workbench.action.navigateBack/ 。
workbench.action.navigateForward标记(大写和小写)应该可以正常工作。
命令菜单具有类型上的通配菜单补全。 1.5 秒后出现补全选项(以免在您写入:w或时打扰您:noh)。Up/Down选择该选项并Tab接受它。看动图:
多个光标
多个游标适用于:
- 插入模式
- 视线模式
- 视觉块模式
要从视线/块模式生成多个光标,请键入ma/mA或mi/ mI (默认情况下)。效果不同:
- 对于可视行模式,mi将在每个选定行的第一个非空白字符上启动插入模式,并将ma在行尾启动插入模式。
- 对于可视块模式,mi将在光标块之前和 ma之后开始在每个选定行上插入。
- mA/mI版本占空行(仅适用于可视行模式,对于可视块模式它们与ma/相同mi)。
查看实际操作中的 gif:
内置的多光标支持可能无法满足您的需求。更多多光标功能请参考插件 vscode-multi-cursor.nvim
?? API
加载模块:
local vscode = require('vscode-neovim')
- vscode.action():异步执行vscode命令。
- vscode.call():同步执行vscode命令。
- vscode.on():定义一些 Nvim UI 事件的处理程序。
- vscode.has_config():检查 vscode 设置是否存在。
- vscode.get_config():获取vscode设置值。
- vscode.update_config():设置 vscode 设置。
- vscode.notify():显示 vscode 消息(另请参阅 Nvim 的vim.notify)。
- vscode.to_op(): 的帮手map-operator。使用方法见code_actions.lua
- vscode.get_status_item:获取 vscode 状态栏项。可以分配属性,这会神奇地更新状态栏项目。
- g:vscode_clipboard:使用 VSCode 剪贴板 API 的剪贴板提供程序。在 WSL 中时默认使用。请参阅 :h g:clipboard了解更多详情。用法:let g:clipboard = g:vscode_clipboard
- vscode.eval():在vscode中同步计算javascript并返回结果
- vscode.eval_async():在 vscode 中异步评估 javascript
vscode.action(名称,选项)
异步执行 vscode 命令。请参阅示例。
参数:
- name(字符串):操作的名称,通常是 vscode 命令。
- opts(表):可选参数图:args(表):传递给 vscode 命令的参数列表。如果命令只需要单个对象参数,则可以直接传入类似地图的表。例子:action('foo', { args = { 'foo', 'bar', … } })action('foo', { args = { foo = bar, … } })range(表):动作的具体范围。以视觉模式隐式传递。具有三种可能的形式(所有值都是 0 索引):[start_line, end_line][start_line, start_character, end_line, end_character]{start = { line = start_line, character = start_character}, end = { line = end_line, character = end_character}}restore_selection(布尔值):是否保留当前选择。仅在range指定时有效。默认为true.callback:处理动作结果的函数。必须有这个签名:
- function(err: string|nil, ret: any)
- err是错误消息(如果有)
- ret是结果
- 如果未提供回调,错误将显示为 VSCode 通知。
vscode.call(名称、选项、超时)
同步执行 vscode 命令。请参阅示例。
参数:
- name(字符串):操作的名称,通常是 vscode 命令。
- opts(表):与vscode.action()相同。
- timeout(数字):超时(以毫秒为单位)。默认值为-1,表示没有超时。
返回:操作的结果
例子
- 格式选择(默认绑定):
- xnoremap =
lua require('vscode-neovim').call('editor.action.formatSelection') nnoremap = lua require('vscode-neovim').call('editor.action.formatSelection') nnoremap == lua require('vscode-neovim').call('editor.action.formatSelection') - 开放定义放在一边(默认绑定):
- nnoremap
gd lua require('vscode-neovim').action('editor.action.revealDefinitionAside') - 在文件中查找光标下的单词( 预期参数格式 请参见vscode命令定义):
- nnoremap ?
lua require('vscode-neovim').action('workbench.action.findInFiles', { args = { query = vim.fn.expand(' ') } })
目前,提供了两个内置操作用于测试目的:
- _ping回报"pong"
- _wait等待指定的毫秒数然后返回"ok"
do -- Execute _ping asynchronously and print the result
vscode.action("_ping", {
callback = function(err, res)
if err == nil then
print(res) -- outputs: pong
end
end,
})
end
-- Format current document
vscode.action("editor.action.formatDocument")
do -- Comment the three lines below the cursor
local curr_line = vim.fn.line(".") - 1 -- 0-indexed
vscode.action("editor.action.commentLine", {
range = { curr_line + 1, curr_line + 3 },
})
end
do -- Comment the previous line
local curr_line = vim.fn.line(".") - 1 -- 0-indexed
local prev_line = curr_line - 1
if prev_line >= 0 then
vscode.action("editor.action.commentLine", {
range = { prev_line , prev_line },
})
end
end
do -- Find in files for word under cursor
vscode.action("workbench.action.findInFiles", {
args = { query = vim.fn.expand('') }
})
end
-- Execute _ping synchronously and print the result
print(vscode.call("_ping")) -- outputs: pong
-- Wait for 1 second and print the return value 'ok'
print(vscode.call("_wait", { args = { 1000 } })) -- outputs: ok
-- Wait for 2 seconds with a timeout of 1 second
print(vscode.call("_wait", { args = { 2000 } }), 1000)
-- error: Call '_wait' timed out
vscode.on(事件,回调)
目前没有可供用户使用的可用事件。
VSCode 设置
vscode.has_config(名称)
检查配置是否具有特定值。
参数:
- name(string|string[]):配置名称或配置名称数组。
返回:
- boolean|boolean[]:true如果配置有某个值则返回,false否则返回。如果name是一个数组,则返回一个布尔值数组,指示每个配置是否具有特定值。
vscode.get_config(名称)
获取配置值。
参数:
- name(string|string[]):配置名称或配置名称数组。
返回:
- unknown|unknown[]:配置的值。如果name是一个数组,则返回与每个配置对应的值数组。
vscode.update_config(名称,值,目标)
更新配置值。
参数:
- name(string|string[]):配置名称或配置名称数组。
- value(unknown|unknown[]):配置的新值。
- target("global"|"workspace"):配置目标。选修的
例子:
------------------
--- has_config ---
------------------
-- Check if the configuration "not.exist" exists
print(vscode.has_config("not.exist"))
-- Should return: false
-- Check multiple configurations
vim.print(vscode.has_config({ "not.exist", "existing.config" }))
-- Should return: { false, true }
------------------
--- get_config ---
------------------
-- Get the value of "editor.tabSize"
print(vscode.get_config("editor.tabSize")) -- a number
-- Get multiple configurations
vim.print(vscode.get_config({ "editor.fontFamily", "editor.tabSize" }))
-- Should return: { "the font family", "the editor tabSizse" }
---------------------
--- update_config ---
---------------------
-- Update the value of "editor.tabSize"
vscode.update_config("editor.tabSize", 16, "global")
-- Update multiple configurations
vscode.update_config({ "editor.fontFamily", "editor.tabSize" }, { "Fira Code", 14 })
留言
vscode.notify(消息)
显示 vscode 通知
您可以设置vscode.notify为默认通知功能。
vim.notify = vscode.notify
vscode.get_status_item(id)
创建状态项
- id(字符串):项目的标识符
local test = vscode.get_status_item('test')
test.text = 'hello' -- Show the text
test.text = '' -- Hide the item
test.text = nil -- Close the item
test.text = '' -- error: The status item "test" has been closed
vscode.eval(代码[, opts, 超时])
在 vscode 中评估 javascript 并返回结果。该代码在异步函数上下文中执行(因此await 可以使用)。使用return语句将值返回给 lua。从 lua 传递的参数可用作 args变量。评估的代码可以通过全局访问 VSCode APIvscode。
尖端:
- 确保await在访问 API 时启用异步函数。
- 使用全局logger(例如logger.info(...))将消息记录到 vscode-neovim 的输出(通过设置控制日志级别vscode-neovim.logLevel)。
- 普通数据(如字符串、整数等)可以直接返回,但即使是简单的对象(如字符串、整数等)也会{foo: 123}转换为字符串并以"[object Object]".JSON.stringify()可用于将普通对象序列化为可vim.json.decode()在 lua 中反序列化的 JSON。
- globalThis['some_name'] = ...可用于在调用之间保留值。
参数:
- code(字符串):要执行的 JavaScript。
- opts(表):可选参数图:args(任意):可用作argsjavascript 中的变量的值。可以是单个值,例如字符串或多个值的表。
- timeout(number):取消之前等待评估完成的毫秒数。默认情况下没有超时。
返回:
- 返回执行所提供代码的结果。如果该值无法用 lua 表示(即对象或函数),则结果将转换为字符串。
例子:
local current_file = vscode.eval("return vscode.window.activeTextEditor.document.fileName")
local current_tab_is_pinned = vscode.eval("return vscode.window.tabGroups.activeTabGroup.activeTab.isPinned")
vscode.eval("await vscode.env.clipboard.writeText(args.text)", { args = { text = "some text" } })
vscode.eval_async(代码[, opts])
类似vscode.eval(),但会立即返回并在后台进行评估。
参数:
- code(字符串):要执行的 JavaScript。
- opts(表):可选参数图:args(任意):可用作argsjavascript 中的变量的值。可以是单个值,例如字符串或多个值的表。callback:处理eval结果的函数。必须有这个签名:
- function(err: string|nil, ret: any)
- err是错误消息(如果有)
- ret是结果
- 如果未提供回调,错误将显示为 VSCode 通知。
Vim脚本
注意:从 1.0.0 开始,vimscript 函数已被弃用。请改用Lua api。
- VSCodeNotify()/ VSCodeCall(): 已弃用,请使用Lua require('vscode-neovim').call()代替。
- VSCodeNotifyRange()/ VSCodeCallRange(): 已弃用,请使用Lua require('vscode-neovim').call(…, {range:…})代替。
- VSCodeNotifyRangePos()/ VSCodeCallRangePos(): 已弃用,请使用Lua require('vscode-neovim').call(…, {range:…})代替。
?? 键绑定(快捷键)
可用于文件/滚动/窗口/选项卡管理的默认命令和绑定:
- 有关滚动命令参考,请参阅vscode-scrolling.vim
- 有关文件命令参考,请参阅vscode-file-commands.vim
- 请参阅vscode-tab-commands.vim以获取 tab 命令参考
- 有关窗口命令参考,请参阅vscode-window-commands.vim
“With bang”是指加一个“!”到命令的结尾。
键绑定帮助
本文档仅提到一些特殊情况,并不是按键绑定和命令的详尽列表。使用 VSCode 和 Nvim 功能查看文档和所有定义的快捷方式:
- 运行Preferences: Open Keyboard Shortcutsvscode 命令并搜索“neovim”以查看所有键绑定。
- 使用 Nvim:help命令查看给定命令或键绑定的文档。例如尝试 :help :split或:help zo。请注意,:helpfor
绑定拼写为CTRL-…。例如,要查看帮助 ,请运行 :help CTRL-W. - 搜索在线 Nvim 文档:https://neovim.io/doc/user/
添加按键绑定
每个特殊(control/alt)键盘快捷键都必须在 VSCode 中显式定义才能发送到 neovim。默认情况下,仅发送 Neovim 默认包含的绑定。
要将自定义绑定传递给 Neovim(例如C-h在正常模式下),请添加到 keybindings.json:
{
"command": "vscode-neovim.send",
// the key sequence to activate the binding
"key": "ctrl+h",
// don't activate during insert mode
"when": "editorTextFocus && neovim.mode != insert",
// the input to send to Neovim
"args": ""
}
禁用键绑定
切换键绑定有三种配置:
- ctrlKeysForInsertMode:切换 ctrl 键进入插入模式。
- ctrlKeysForNormalMode:切换 ctrl 键为正常模式。
- editorLangIdExclusions:在某些文件类型中禁用此扩展定义的键绑定。请注意,这不会影响所有键绑定。
如果您发现这些选项不起作用,您可以手动修改 VSCode 中的键绑定(见下文)。
删除按键绑定
- 要删除 vscode 键绑定,请编辑您的settings.json,或使用 VSCode 键绑定编辑器:
代码导航
请参阅键绑定帮助查看所有定义的快捷方式及其文档。
钥匙 | VSCode 命令 |
=/== | editor.action.formatSelection |
gh/K | editor.action.showHover |
gd/C-] |
|
gf | editor.action.revealDeclaration |
gH | editor.action.referenceSearch.trigger |
gO | workbench.action.gotoSymbol |
C-w gd/C-w gf | editor.action.revealDefinitionAside |
gD | editor.action.peekDefinition |
gF | editor.action.peekDeclaration |
Tab | togglePeekWidgetFocus |
C-n/C-p | 导航列表、参数提示、建议、快速打开、命令行历史记录、查看参考列表 |
要指定默认的查看模式,请
editor.peekWidgetDefaultFocus在您的设置中进行修改。
资源管理器/列表导航
请参阅键绑定帮助查看所有定义的快捷方式及其文档。
钥匙 | VSCode 命令 |
j或者k | list.focusDown/Up |
h或者l | list.collapse/select |
Enter | list.select |
gg | list.focusFirst |
G | list.focusLast |
o | list.toggleExpand |
C-u或者C-d | list.focusPageUp/Down |
zo或者zO | list.expand |
zc | list.collapse |
zC | list.collapseAllToFocus |
za或者zA | list.toggleExpand |
zm或者zM | list.collapseAll |
/或者Escape | list.toggleKeyboardNavigation |
资源管理器文件操作
请参阅键绑定帮助查看所有定义的快捷方式及其文档。
钥匙 | VSCode 命令 |
r | renameFile |
d | deleteFile |
y | filesExplorer.copy |
x | filesExplorer.cut |
p | filesExplorer.paste |
v | explorer.openToSide |
a | explorer.newFile |
A | explorer.newFolder |
R | workbench.files.action.refreshFilesExplorer |
悬停小部件操作
请参阅键绑定帮助查看所有定义的快捷方式及其文档。
默认设置以下键绑定: 当悬停不可见时,将 K 发送到 nvim(show hoover);当悬停可见时,再次按 K 聚焦悬停小部件。
{
"command": "editor.action.showHover",
"key": "shift+k",
"when": "neovim.init && neovim.mode == normal && editorTextFocus && editorHoverVisible"
}
钥匙 | VSCode 命令 |
h | editor.action.scrollLeftHover |
j | editor.action.scrollDownHover |
k | editor.action.scrollUpHover |
l | editor.action.scrollRightHover |
gg | editor.action.goToTopHover |
G | editor.action.goToBottomHover |
C-f | editor.action.pageDownHover |
C-b | editor.action.pageUpHover |
文件管理
该扩展将各种 Nvim 命令(:edit、:enew、:find、:write、:saveas、:wall、:quit等)别名为等效的 vscode 命令。还有它们的正常模式等效项(如果适用)C-w q,例如 等。
请参阅键绑定帮助查看所有定义的快捷方式及其文档。
标签管理
该扩展将各种 Nvim tab 命令(:tabedit, :tabnew, :tabfind, :tabclose, :tabnext, :tabprevious, :tabfirst, :tablast)别名为等效的 vscode 命令。还有它们的正常模式等效项(如果适用)gt,例如 等。
请参阅键绑定帮助查看所有定义的快捷方式及其文档。
缓冲区/窗口管理
该扩展将各种 Nvim 缓冲区/窗口命令 ( :split、:vsplit、:new、:vnew、:only) 别名为等效的 vscode 命令。还有它们的正常模式等效项(如果适用)C-w s,例如 等。
请参阅键绑定帮助查看所有定义的快捷方式及其文档。
分割尺寸分布由设置控制
workbench.editor.splitSizing。默认情况下,它是distribute,等于 vim 的equalalways和eadirection = 'both'(默认)。
要使用 VSCode 命令“增加/减少当前视图大小”而不是单独的宽度和高度绑定:
- workbench.action.increaseViewSize
- workbench.action.decreaseViewSize
将其复制到 init.vim 中
插入模式特殊键
启用者ctrlKeysForInsertMode
默认:["a", "d", "h", "j", "m", "o", "r", "t", "u", "w"]
请参阅键绑定帮助查看所有定义的快捷方式及其文档。
普通模式控制键
启用者ctrlKeysForNormalMode
默认: ["a", "b", "d", "e", "f", "h", "i", "j", "k", "l", "m", "o", "r", "t", "u", "v", "w", "x", "y", "z", "/", "]"]
请参阅键绑定帮助查看所有定义的快捷方式及其文档。
项目地址:
https://github.com/vscode-neovim/vscode-neovim