云计算、AI、云原生、大数据等一站式技术学习平台

网站首页 > 教程文章 正文

Neovim:将 Neovim实例完全嵌入到 VSCode,具有更大可扩展性集成性

jxf315 2025-02-26 12:33:08 教程文章 18 ℃

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在插入模式下键入,则将光标移至abc并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接受它。看动图:

多个光标

多个游标适用于:

  1. 插入模式
  2. 视线模式
  3. 视觉块模式

要从视线/块模式生成多个光标,请键入ma/mA或mi/ mI (默认情况下)。效果不同:

  • 对于可视行模式,mi将在每个选定行的第一个非空白字符上启动插入模式,并将ma在行尾启动插入模式。
  • 对于可视块模式,mi将在光标块之前和 ma之后开始在每个选定行上插入。
  • mA/mI版本占空行(仅适用于可视行模式,对于可视块模式它们与ma/相同mi)。

查看实际操作中的 gif:

内置的多光标支持可能无法满足您的需求。更多多光标功能请参考插件 vscode-multi-cursor.nvim

?? API

加载模块:

local vscode = require('vscode-neovim')
  1. vscode.action():异步执行vscode命令。
  2. vscode.call():同步执行vscode命令。
  3. vscode.on():定义一些 Nvim UI 事件的处理程序。
  4. vscode.has_config():检查 vscode 设置是否存在。
  5. vscode.get_config():获取vscode设置值。
  6. vscode.update_config():设置 vscode 设置。
  7. vscode.notify():显示 vscode 消息(另请参阅 Nvim 的vim.notify)。
  8. vscode.to_op(): 的帮手map-operator。使用方法见code_actions.lua
  9. vscode.get_status_item:获取 vscode 状态栏项。可以分配属性,这会神奇地更新状态栏项目。
  10. g:vscode_clipboard:使用 VSCode 剪贴板 API 的剪贴板提供程序。在 WSL 中时默认使用。请参阅 :h g:clipboard了解更多详情。用法:let g:clipboard = g:vscode_clipboard
  11. vscode.eval():在vscode中同步计算javascript并返回结果
  12. 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('') } })

目前,提供了两个内置操作用于测试目的:

  1. _ping回报"pong"
  2. _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": ""
}

禁用键绑定

切换键绑定有三种配置:

  1. ctrlKeysForInsertMode:切换 ctrl 键进入插入模式。
  2. ctrlKeysForNormalMode:切换 ctrl 键为正常模式。
  3. editorLangIdExclusions:在某些文件类型中禁用此扩展定义的键绑定。请注意,这不会影响所有键绑定。

如果您发现这些选项不起作用,您可以手动修改 VSCode 中的键绑定(见下文)。

删除按键绑定

  • 要删除 vscode 键绑定,请编辑您的settings.json,或使用 VSCode 键绑定编辑器:

代码导航

请参阅键绑定帮助查看所有定义的快捷方式及其文档。

钥匙

VSCode 命令

=/==

editor.action.formatSelection

gh/K

editor.action.showHover

gd/C-]


editor.action.revealDefinition

也适用于 vim 帮助。

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

Tags:

最近发表
标签列表