如何创建一个插件来扩展现有 vim 插件的功能?

How can I create a plugin that extends the functionality of an existing vim plugin?

我想扩展现有且流行的 vim 插件的功能。该功能不属于插件本身,因为它不是插件功能的核心,但是,它对很多人都有帮助,因此分叉和编辑插件本身没有意义。

我正在寻找有关如何或参考另一个执行此操作的 vim 插件的指导,我可以将其用作示例。我的 Google-fu 没有发现任何有用的东西。我如何开发一个 vim 插件来扩展另一个插件的功能,而无需创建上游插件的完整编辑版本?

这实际上取决于现有的插件和您想要的扩展类型。

如果幸运的话,Vim 已经提供了一个内置的扩展点; :help after-directory 在这里想到,对于扩展语法或文件类型插件非常有用。


其他插件提供的映射和命令可以通过您自己的变体进行扩充。理想情况下,您可以使它们不同(例如,将 :Foo 命令细化为扩展的 :FooExtended)。 如果您需要覆盖其中一个,您的插件需要确保首先获取现有插件。这可以用这样的代码来完成:

:runtime! plugin/existingPlugin.vim
if ! exists('g:loaded_existingPlugin')
    " Plugin does not exist, skip extending.
    finish
endif

" Must use ! to override defined command.
command! Foo ...

这里的一个常见问题是您想从未公开的现有插件调用函数(如 autoload 函数)。有一些技巧(从 :scriptnames 解析插件脚本 ID),但我会首先尝试提交一个拉取请求,要求原作者为您公开该功能。


对于真正深入的扩展,即当您需要现有插件了解您并调用您的代码时,您可能需要现有插件的支持和(继续)协调。根据您的想法写一份提案,并概述您需要的 API。选择最通用的集成点,而不是只适合您的最简单的集成点。可用技术有:

  • 额外的插件配置(g:PluginName_ConfigName
  • Vim 命令或 :help Funcref 传递给插件函数,或在变量中配置
  • 由现有插件触发的自定义 :help User 事件,您(和其他人)可以挂钩(通过 :autocmd User PluginName ...
  • 一些插件甚至通过 :help Dictionaries 实现了一种面向对象的形式,然后可以交换/扩充

如果您可以为您的功能提出一个令人信服的案例(1 + 1 = 3 的协同作用,扩大用户群),如果它不属于原始插件(或者它的作者不知道提供),并且如果您可以确定一组不会破坏现有插件或使现有插件过于复杂的集成点,那么这可能是一个成功的策略;我个人已经对多个插件这样做了。


作为最后的手段,始终可以选择分叉现有插件。如果原作者没有时间或者不喜欢你的提议,你别无选择。一些集成点太麻烦或引入太多开销。在这些情况下,您必须决定是否有时间跟上上游的变化;如果用户必须在让你的扩展具有过时的基础,或者切换到更新的基础但失去你的扩展之间做出选择,那将是非常糟糕的。