Neovim 中文周刊 第 11 期

点击查看原文

欢迎收看第 11 期 Neovim 中文周刊!

本期周刊包含以下版块:

  • Neovim 开发近况:摘录近期合并的 PR,以新功能为主
  • 社区资讯:摘录近期更新的 Issue 讨论以及 Reddit 等论坛的热门话题
  • 插件推荐
  • 插件对比

Neovim 开发近况

feat(exrc): search in parent directories (#33889)

现在启用 'exrc' 时,Neovim 除了在当前目录下搜索 .nvim.lua/.nvimrc/.exrc,还会在上级目录搜索,并且会持续向上搜索,运行每一级上级目录下找到的 'exrc' 文件。值得注意的是 Neovim 只会在 VimEnter 时读取 'exrc',即不会在切换当前目录等事件发生时重新搜索。

fix(diagnostic): accept multiple namespaces when setting loclist/qflist (#33982)

vim.diagnostic.setloclist()vim.diagnostic.setqflist()opts 参数的 namespace 字段现在可以接受 integer[] 值,可在 Location/Quickfix List 中显示来自多个 namespace 的 diagnostic。

feat(diagnostic): add format option to setloclist/setqflist (#33977)

vim.diagnostic.setloclist()vim.diagnostic.setqflist()opts 参数新增字段 format,可用于自定义 Location/Quickfix List 中的 diagnostic 条目的格式。

该 PR 旨在解决 #26130,该 Issue 报告 vim.diagnostic.open_float() 以及 vim.diagnostic.Opts.VirtualText 都有字段 source 可显示 diagnostic 来源,但 vim.diagnostic.setloclist() 没有,导致存在多个 LSP 时难以判断来源。

因此该 PR 合并后,

  • vim.diagnostic.Opts.VirtualLinesvim.diagnostic.setloclist()/vim.diagnostic.setqflist() 仅有 format 字段
  • vim.diagnostic.Opts.Floatvim.diagnostic.Opts.VirtualText 同时拥有 formatsource 字段

feat(diagnostic): add enabled filter (#33981)

vim.diagnostic.get()opts 参数(即 vim.diagnostic.GetOpts)新增字段 enabledvim.diagnostic.enable() 可用于启用/禁用特定 buffer 或 namespace 的 diagnostic,通过设置 enabledtrue/false,可指定仅获取被启用/禁用的 diagnostic。

该 PR 旨在解决 #25131,该 Issue 报告尽管被 vim.diagnostic.enable() 禁用的 diagnostic 不会再显示为 virtual text,但是使用 vim.diagnostic.get() 依然会获取到这些被禁用的 diagnostic,从而导致 vim.diagnostic.setloclist() 等一系列 API 都无法过滤掉这些被禁用的 diagnostic。

社区资讯

feat(lua): add minimal vim.net.download wrapper using curl (#33964)

该 PR 实现了 Lua 模块 vim.net,用于支持网络访问的功能。目前该模块仅实现了一个 API vim.net.download(),用于从指定的 URL 下载文件。据我所知,这是第三位尝试实现 vim.net 的勇士 :)

vim.net 可用于以下用途:

  • 使用 Lua 实现网络访问是替换 :h netrw 的前置任务。#32280 希望能够将 Netrw 替换为若干个独立的 Lua 模块,主要原因是 Netrw 包含了太多功能,这意味着用户为了使用 Netrw 的某一个功能就必须启用 Netrw 提供的所有功能,不符合 Neovim 的设计哲学。而目前 Netrw 承担了 Neovim 所有的网络访问功能,包括
    • 下载 spellfile (#7189)
    • 访问远端文件 (:e ftp://foo.bar/baz)
  • 下载 tree-sitter parser。目前 Neovim 仅将若干个语言的 parser 随软件分发,而大部分用户则依靠 nvim-treesitter 来安装其他语言的 parser。此外,nvim-treesitter 还需要一个 C 编译器来编译 parser。实现 vim.net 后,可直接使用其下载 :h treesitter-parsers-wasm
  • 用于插件管理器下载其自身。
  • #30889 实现后,用于下载远端的图片资源。

mrshmllow 首先发起了 #23461 实现 vim.net。在该 PR 中,社区针对 vim.net 的实现方式展开了激烈的讨论,主要有三种方案:

  • 使用 libuv 从头实现。
    • 实现难度较大,几乎没有人考虑。
  • 通过子进程调用 curl 可执行文件实现
    • 实现难度较小。
    • 尽管操作系统提供的 curl 版本可能较旧,但是发行版供应商会为其应用安全补丁。(评论
    • 比起 Neovim,用户通常更加频繁地更新系统 curl。此外,操作系统有能力保证应用安全补丁,但 Neovim 却无法迫使用户更新。(评论
  • 使用 libcurl 的 API 实现
    • 性能开销更小,使用更灵活,这对插件作者更有吸引力。(评论
    • Linux 发行版没有要求一定有 curl,需要处理系统没有 curl 的情况。此外,使用 curl 子进程无法控制 curl 的版本,需要小心处理使用的参数选项。(评论
    • 用户通常使用较老版本的操作系统,导致 curl 版本也较老。通过集成 libcurl,Neovim 可以提供更新更安全的 curl 实现。(评论
    • 即便 Neovim 捆绑了 libcurl,发行版在打包 Neovim 时依然可以通过动态链接将 Neovim 链接到更新的 libcurl。(评论

mfussenegger 对以上讨论做出了非常好的总结。最后 justinmk 盖棺定论:使用子进程调用 curl 的方案,主要原因是由于 Netrw 的存在 Neovim 其实从一开始就依赖 curl 程序,至于集成 libcurl 这些复杂的功能都可以日后再议。讨论结束后,该 PR 沉寂了一段时间,最后被 mrshmllow 关闭,我没有找到任何公开的解释。

随后我们的第二位勇士 TheLeoP 发起了 #29104,延续了 #23461 的工作。在该 PR 接受一系列 review 后,clason 认为该 PR 实现的内容过多,建议拆分成多个 PR 逐一实现,并关闭了该 PR。随后 TheLeoP 重新发起了 #29327,该 PR 在经历了一系列 review 和讨论后不再活跃,并最后被 TheLeoP 关闭。同样,我没有找到任何公开的解释。

目前我们的第三位勇士 tampueroc 的实现的核心思路基本上就是一个使用 vim.system() 的 curl wrapper,这是特意维持该 PR 的实现最简化。根据规划,如果该 PR 能够顺利合并,接下来将逐步实现

  • 认证、header 和代理等功能支持
  • 实现 vim.net.request() API
  • 基于 vim.net 实现 spellfile 下载等功能

feat(pack): add built-in plugin manager vim.pack (#34009)

实现内置插件管理器 vim.pack。PR 作者是 mini.nvim 的作者 echasnovski,设计的思路也是沿用的 mini.deps。当前实现效果如下,注意右上角的通知弹窗属于 mini.notify

此外,vim.pack 还实现了一个 in-process LSP,用于为 nvimpack 提供目录等功能,当前实现的效果如下:

值得注意的是,根据当前的设计,有两个功能是明确不被考虑的:

  • 位于 pack/*/start 的插件。所有由 vim.pack 管理的插件都会被放到 $XDG_DATA_HOME/nvim/site/pack/core/opt,这引起了一定的争议
  • 插件懒加载。

由于内置插件管理器一直是社区关注的焦点,echasnovski 恳请所有非 Nvim Team 成员的用户在仔细思考留言是否有帮助后再添加评论,以避免该 PR 有过多的留言。

Is there any distribution, such as LazyVim, but that is behind a community and not 1 dev only?

LazyVim 是一个相当热门的 Neovim 发行版,然而长期以来,只有其维护者 folke 拥有该仓库的 push 权限。这令一些用户感到担忧,并询问是否有由多人社区维护的发行版选择。该 Reddit 讨论下的多数回应是 NvChadAstroNvim

除了 LazyVim,folke 还持有众多热门 Neovim 插件,其中包括目前最流行的插件管理器 lazy.nvim,这些项目都随着 folke 的旅行假期完全停止了开发。

值得注意的是,folke 表示他们已经在旅行的返途中,并即将回到 Neovim 相关的开发中。此外,folke 还预告了他们计划在 7 ~ 9 月份还有一次旅行。

I am still new to neovim, but at this point folke's vacations have been mentioned so many times, that I feel like it's return will be akin to the second coming of christ ;p

iusevimbtw.com

一个邮箱服务,提供 iusevimbtw.com 域名的邮箱,有点搞。更搞的是 iuseemacsbtw.com 被重定向到了这个网站 :)

插件推荐

showkeys

在 Neovim 中显示按下的按键,作者是 NvChad 的维护者。

插件对比

nvim-cmp vs blink.cmp

特性 nvim-cmp blink.cmp
开发者 hrsh7th Saghen
GitHub 星标数 8.8k 4.5k
Fork 数量 420 245
问题数量 266 98
拉取请求数 30 5
主要编程语言 Lua (98.6%) Lua (94.6%), Rust (4.6%)
最新版本 v0.0.2 v1.3.1
许可证 MIT MIT
首次发布 较早 较新
贡献者数量 183+ 165+

从特性来看,两个插件均支持以下功能:

  • Lsp、缓冲区、终端补全支持
  • 代码片段支持
  • 命令行补全支持
  • UI 自定义
  • 键位映射

不同之处:

  • cmp 补全源更多,blink 补全源要少(虽然可以通过兼容层实现,但是效果不是很好,部分源会有问题)
  • cmp 无需额外的二进制文件,blink 需要下载额外的二进制文件
  • cmp 的补全源支持更多,cmp 已经有不少冷门语言的补全源
  • blink 更快,cmp在大型项目上会有卡顿感
  • blink 的模糊匹配算法和排序算法更好,可定制程度更高
  • blink 有一些实验性的功能,例如 signalture 的支持

客观来讲,两个插件都很优秀,nvim-cmp 的生态更成熟,功能更全面,blink.cmp 则是一个新生的项目,功能上有些欠缺,但是性能上更好。

如果对速度和性能有要求,或者对补全源的支持没有那么高的要求,可以考虑使用 blink.cmp。

如果对补全源的支持有要求,或者对于补全的功能有要求,可以考虑使用 nvim-cmp。

鸣谢

关于

那么,一如既往,希望本期周刊能对您有所裨益,感谢您的阅读。

  • 周刊网站 | 周刊项目地址 | RSS 订阅
  • 我不是 Neovim 贡献者,也不是任何有影响力的插件贡献者,甚至算不上一个 (Neo)vim 老手,我的观点很可能错漏百出。如果您希望贡献本周刊,请收下我的感谢并查看贡献指南
  • 发布日期:2025-05-17 修订日期:2025-05-17