Neovim 新闻 #11 - 圣诞节特刊

2021 年 7 月

我们一路走来,真正的 0.5 是我们交的朋友

期待已久的 Neovim v0.5.0 版本终于在 2021 年 7 月 2 日发布。发布过程比大家预期的要长,但这都是值得的:它包含了超过 4000 次提交,规模之大甚至导致了一些发布工具的故障。因此,本篇笔记无法涵盖开发过程中所做的所有变更,只会关注对用户来说最显着的改进,其中最大的改进包括

  1. Lua 作为一等公民的脚本和配置语言,
  2. 语言服务器协议 (LSP),
  3. Treesitter(抢先体验)。

Lua 无处不在!

Neovim 0.5 在将 Lua 打造成 Neovim 的一等公民脚本语言方面取得了长足的进步,无论是在插件开发还是用户配置方面都是如此。

需要提醒的是,Lua 是一种小型脚本语言,专为嵌入式设计,通常用于游戏开发等领域。此外,它还配备了一个即时编译器(LuaJIT,Neovim 在可用的平台上使用它),可以在相关任务中提供令人印象深刻的性能。本质上,Lua 被选中替代其他语言是因为它

  1. 体积小巧——非常适合嵌入式(与远程插件主机相反),
  2. 速度快——LuaJIT 的速度可以比 Vimscript(和非 JIT 的 Lua)快几个数量级,
  3. 简单——简洁但富有表现力的语法(Lua 5.1)专为脚本设计,Neovim 本身通过 API 公开内部函数,从而提供“标准库”。

有关此选择的更多详细信息,请参见 Justin M Keyes 在 2019 年 Vim Conf 上的演讲,以及 TJ DeVries 在 Vimconf.live 上的演讲

让我们看看这对插件作者和用户意味着什么。

Lua 插件

Neovim 通过例如 vim.api.nvim_open_win() 将 API 本地暴露给 Lua。它还提供方法通过例如 vim.cmd("echo 'foo'")vim.g.syntax_on 分别访问 vimscript (ex) 命令和变量。这样可以编写与 Vimscript 编写的插件具有相同功能的插件,同时在核心编程语言任务(例如循环)中利用 Lua(JIT) 的性能。也可以使用 Lua 自己的 luarocks 插件生态系统。

相应地,在 0.5 的开发周期中,Lua 插件的数量呈爆炸式增长,从流行的 Vimscript 插件的重写到完全无法用 Vimscript 实现的新插件,这些插件通常来自以前从未参与过 (neo)vim 插件开发、并且不愿为了这项任务而学习 Vimscript 的贡献者。作为漫长开发周期的积极副作用,许多插件在 0.5 发布时就已经功能齐全且稳定了!

以下列出了一些非代表性的 Lua 插件

  • Plenary —— 用于开发 Neovim 插件的实用程序库(其中一些将在以后集成到核心)。
  • Packer —— 一个支持插件依赖项、延迟加载和安装 luarocks 的包管理器。
  • Telescope —— 一个高度可扩展的模糊查找器,可用于查找列表。
  • Gitsigns —— 用于显示和交互 Git 仓库中文件变更的插件(异步)。
  • Nvim-compe —— 用于各种来源(包括 Neovim 的内置 LSP 客户端)的自动完成框架。
  • Nvim-dap —— 用于代码逐步调试的调试适配器协议实现。
  • Colorizer —— Neovim 的高性能颜色高亮器,没有任何外部依赖项。
  • Formatter —— 一个用于在当前缓冲区或范围内异步执行外部格式化工具的插件。
  • Hop.nvim - 一个类似于 EasyMotion 的移动插件,不需要修改缓冲区。
  • Neogit - 一个类似于 Magit 的 Git 接口。

可以在用户贡献的 Awesome Neovim 集合中找到更全面的 Neovim 插件列表。

并非所有这些插件都是用 Lua 编写的:还有许多其他语言(其中一些是类型化的)可以编译成 Lua,例如

Lua 配置

也可以用 Lua 编写用户配置:如果存在 init.lua ,则会读取它而不是 init.vim (它们不能共存,在您的配置文件目录中同时存在这两个文件会导致错误),并且运行时目录(plugin/colorscheme/after/ 等)中的 .lua 文件将与 Vimscript 文件一起(之后)被来源。请注意,这完全是可选的,并非享受 Neovim 0.5 中引入的新功能所必需;此外,并非所有 Vimscript 配置选项都具有完全原生的 Lua 等效项。将原生 API 扩展以涵盖这些选项也是 Neovim 0.6 的目标之一。

有关使用 Lua 进行 Neovim 脚本和配置的全面且最新的指南,请参见 在 Neovim 中开始使用 Lua 。一个使用 init.lua 的 Lua 配置的好例子是 Defaults.nvim

语言服务器协议 (LSP)

语言服务器协议 (LSP) 是一种开放的基于 JSON-RPC 的协议,用于代码编辑器和语言服务器之间的通信,语言服务器提供特定于编程语言的功能,例如

  • 自动完成,
  • 悬停/工具提示,
  • 转到定义,
  • 显示/转到引用,
  • 显示方法签名,
  • 重命名,
  • 代码操作(自动格式化、整理导入等),

等等。

其理念是将这些功能分离到一个与编辑器无关但与语言相关的服务器和一个与语言无关但与编辑器相关的客户端,它们通过 RPC 使用语言服务器协议进行通信。(需要注意的是,并非所有服务器都实现了所有功能,并且响应的质量可能千差万别。“参考实现”在 VS Code 中也经常添加 LSP 本身未涵盖的非标准功能。)

Neovim 0.5 提供一个用 Lua(大部分)编写的 LSP 客户端,它提供了一种高度可配置且可扩展的方式来访问这些功能。它并不旨在与 CoC.nvim 等功能更丰富、开箱即用的插件竞争,而是旨在根据您的偏好进行定制(同时仍然可以正常使用默认值)。有关概述,请参见 TJ DeVries 的 Vimconf.live 演示 以及他的短视频

对于许多语言服务器,Nvim-lspconfig 已经提供了必要的配置,可以轻松地设置所有内容。或者,某些语言还具有特定的 LSP 插件,可以提供更加集成的设置,例如用于 JavaScala

要详细了解 LSP 以及如何在 Neovim 中使用它,请访问 Nvim-lspconfig (包括它的Wiki ),并阅读:h lsp

在 0.5.x 的开发周期中,预计将对 LSP 进行更多工作,以提供改进的配置选项和对最新 LSP 规范(截至编写本文时为 3.16 版本)的更好支持,包括语义突出显示。

Tree-sitter

Neovim 0.5 添加了对 tree-sitter 的实验性 支持,tree-sitter 是一个库,它以增量和容错的方式将一段代码解析成语法树;这意味着在编辑后重新解析代码非常快,并且由于例如打字错误导致的解析错误会保持局部化,不会中断后续的解析。然后可以有效地查询此树,以获取有关代码的语法信息。这可以提高和/或加速

  • 语法高亮,
  • 代码导航,
  • 重构,
  • 文本对象和动作,
  • 搜索和替换,

等等。Tree-sitter 还使得轻松地以不同的方式突出显示文件中的不同部分成为可能,如果这些部分包含不同语言的代码。要详细了解 tree-sitter,请观看 Tree-sitter - A new parsing system for programming tools - Max Brunsfield

目标是使用 tree-sitter 替换当前基于 vim 正则表达式的语法,这不仅是为了获得更好、更快的语法高亮,也是为了提供新的、改进的结构化文本编辑方法。但是,0.5 中的 tree-sitter 支持仍然应该被视为“抢先体验”:它工作得很好,足以进行测试并查看可能性,但由于存在一些严重的错误和性能回归,因此不应在生产环境中依赖它,这些问题需要在 Neovim 中的 tree-sitter 宣布稳定之前得到解决。另外请注意,为某种语言启用基于 tree-sitter 的高亮会完全禁用这种文件类型的内部基于正则表达式的语法引擎,这可能会破坏依赖它的其他功能。修复这些问题并改进 API 将是通往 0.6 版本发布的开发周期的主要目标。

此外,Neovim 本身只提供(Lua)API,用于使用捆绑的 tree-sitter 库生成和查询语法树;请参见:h treesitter 。面向用户的功能(如上面提到的功能)是在插件中实现的,例如

  • Nvim-treesitter —— 高亮、折叠、增量选择。
  • Playground —— 用于轻松显示解析树并对其运行查询的实用程序函数。
  • Nvim-treesitter-textobjects —— 更好的文本对象,用于 vim 样式的动作和运算符。
  • Nvim-refactor —— 高亮定义、导航、智能重命名。
  • Architext —— 结构化文本编辑(即语法感知的搜索和替换)。

有关使用这些功能的更多信息,请参阅Nvim-treesitter README 或观看 Thomas Vigouroux 的 Vimconf.live 演示

LSP 和 tree-sitter 之间有什么区别?

这是一个常见问题,尤其是因为 LSP 从 3.16 版本开始提供“语义突出显示”。简而言之,tree-sitter 作用于单个文件,将文件解析成语法树,然后使用它来支持各种增强的代码导航和操作功能。另一方面,语言服务器作用于多个文件和项目库,使用各种不同的服务器依赖方法来解析每个文件的语法树。(当然,tree-sitter 是其中一种可行的选择,事实上它被例如 bash-language-serverwasm-language-server 使用。)

具体来说,这意味着语言服务器可以使用来自不同文件的语义 信息来注释当前文件的树:例如,在一个文件中声明为 const 的变量可以在另一个文件中被突出显示为红色——这是 tree-sitter 无法做到的,因为它在突出显示时只能访问后一个文件。

有关更多详细信息,请观看 TJ DeVries 的关于此主题的演示

其他变更

当然,这些并不是 0.5 版本中唯一的重大变化。以下是代表性新功能的简要概述。

装饰

有一个改进的装饰提供程序 API,允许设置和交互 extmarks(不可见的锚定文本标记,在周围文本被编辑时移动)、虚拟文本(可以在屏幕上的任何位置绘制的文本叠加层)和高亮显示(被 nvim-treesitter 大量利用)。

来自帖子的这个模型,由@sunjon展示了可以通过这个 API 实现什么。

浮动窗口

浮动窗口的 API 现在包括一个“z 轴”(允许控制浮动窗口的堆叠顺序)和对边框的支持。

粘贴时高亮显示

Neovim 现在有一个内置函数,可以短暂地高亮显示粘贴区域(类似于 https://github.com/machakann/vim-highlightedyank),可以在 Lua 中配置。要使用它,您可以在您的 init.vim 中添加以下内容。

au TextYankPost * lua vim.highlight.on_yank {higroup="IncSearch", timeout=150, on_visual=true}

查看 :h vim.highlight.on_yank() 以获取更多配置选项。

Vim 修补程序

在这个版本中超过 4000 个提交中,大约 1000 个是来自 Vim 的移植补丁和运行时更新——几乎所有这些都是由很棒的 @janlazo 编写或在他们的帮助下完成的。特别是,运行时文件(语法文件、文档等)与 Vim 的同步时间直到 2021 年 5 月,其中许多较新的更改也已包含在内。

社区

为了与本通讯的格言保持一致,最显着积极的变化之一是社区的增长以及与之互动的新方式。

Discourse

以前,支持请求和讨论分散在 Reddit、Gitter 和 GitHub Discussions 上,并且要么是短暂的,要么是难以搜索的。我们现在已经围绕一个新的 Neovim Discourse 进行了整合,这是一个免费的开源论坛平台,除了一个不错的网络界面之外,还具有邮件列表和 RSS 功能。Neovim Discourse 是一个官方的核心项目,由核心团队成员管理。

Matrix

Neovim 的官方聊天室位于 Gitter 上。在 Matrix(一个联合聊天协议)收购 Gitter 之后,现在也可以从 Matrix 访问此房间;它还与 IRC 网络 Libera.chat 相连。由于用户数量不断增加,现在有额外的、更具体的房间用于 neovim 的开发及其周围GUI非主题聊天

(上面的链接指向通过 Element 访问的房间,Element 是一个基于 Web 的 Matrix 客户端;您也可以通过许多其他 Matrix 客户端 访问它。)

Vimconf.live

由于全球 COVID-19 大流行,VimConf 2020 不幸地不得不取消。取而代之的是,举办了一个虚拟的 Vimconf.live 会议,有 16 位演讲者和来自 12 个国家的 1000 多名注册参与者。如果您错过了它,您可以在 Youtube 播放列表 上观看讲座。

Twitch

大流行的另一个影响是对 Twitch 上开源开发的直播流的兴趣上升。许多 Vimconf.live 的演讲者都是活跃的流媒体;特别是,TJ DeVries 定期直播他在 Neovim 上的工作作为“开放开源”,Neovim 0.5 的发布是在 他的频道上直播的。(**更新:**发布流的编辑播放列表现在在 YouTube 上。)

Neovim 开发

积极参与 Neovim 开发的人数也在增长。在 0.4.4 和 0.5.0 之间,有 301 个独特的提交作者,而在 0.3.8 和 0.4.4 之间(一个类似的时间范围)则有 112 个。

赞助

您现在可以通过 Github SponsorsOpenCollective 赞助 Neovim。(BountySource 开始在他们的服务条款协议中引入令人担忧的更改,因此不再推荐。)

接下来是什么?

如前所述,对 0.5 中引入的 headlight 功能的进一步改进将在 0.5.x 版本周期中进行。

使 tree-sitter 成为语法高亮显示(以及更多)的稳定且更快的替代方案是 0.6.0 版本的主要目标。这包括对装饰 API 的基础工作,以允许进行诸如内联折叠或插入虚拟行和列(“反隐藏”)之类的操作。

除此之外,值得注意的目标是 更好的文件更改检测,以及进一步将 TUI(终端 UI)与 Neovim 核心分离,目的是允许远程 TUI 实例。

最后,我们的目标是发布更多定期和频繁的版本(至少对于补丁版本),这将有望消除对“neovim 0.6 什么时候发布?”这个梗的需求。

感谢

感谢所有参与该项目并帮助 Neovim 0.5 成为现实的人——无论是贡献者、赞助商、错误报告者还是支持者。代替完整的致谢,这里列出了一些您可以感谢他们在本文中列出的功能的人。

最后,感谢 @justinmk@brammool 为您奠定的基础工作和您的愿景——*vim 社区更团结更强大!*

新闻

新闻档案 中找到更多更新。还有一个 RSS 订阅

什么是 Neovim?

Neovim 是一个基于 Vim 的文本编辑器,专为 可扩展性可用性 而设计,以鼓励新的应用程序和 贡献

讨论

访问 #neovim:matrix.org 或 irc.libera.chat 上的 #neovim 与团队聊天。