I would like to extend the functionality of an existing and popular vim plugin. The functionality does not belong in the plugin itself as it's not core to the plugin's functionality, however, it will be helpful to a lot of people thus it doesn't make sense to fork and edit the plugin itself.
I am looking for guidance on how to or reference to another vim plugin that does this that I can use as an example. My Google-fu has not turned up anything helpful. How can I develop a vim plugin that extends another plugin's functionality without creating a full, edited version of the upstream plugin?
That really depends on the existing plugin and the kind of extension you have in mind.
If you're lucky, Vim already provides a built-in extension point; the :help after-directory
comes into mind here, very useful for extending syntax or filetype plugins.
Mappings and commands provided by another plugin can be augmented by your own variant. Ideally, you can make them distinct (e.g. refine the :Foo
command into the extended :FooExtended
).
If you need to override one of those, your plugin needs to ensure that the existing plugin is sourced first. This can be done with code like this:
: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 ...
One common issue here is that you want to invoke functions from the existing plugin that is not exposed (as autoload functions). There are hacks around that (parsing the plugins script ID from :scriptnames
), but I would first try to submit a pull request asking the original author to expose the function for you.
For a really deep extension, i.e. when you need the existing plugin to be aware of you, and invoke your code as well, you likely need support from and (continued) coordination with the existing plugin. Write up a proposal with your idea, and outline the APIs that you would need. Choose the most generic integration point, not the simplest one that will suit just you. Available technologies are:
g:PluginName_ConfigName
):help Funcref
passed to plugin functions, or configured in variables:help User
events that are triggered by the existing plugin, and that you (and others) can hook into (via :autocmd User PluginName ...
):help Dictionaries
, which could then be exchanged / augmentedIf you can make a compelling case for your functionality (synergy of 1 + 1 = 3, broaden user base), if it doesn't belong into the original plugin (or its author doesn't have the knowledge to provide that), and if you can identify a set of integration points that don't disfigure or complicate the existing plugin too much, this can be a successful strategy; I've personally done that to multiple plugins.
As a last resort, there's always the option of forking the existing plugin. If the original author doesn't have the time or doesn't like your proposal, you don't have any other choice. Some integration points are too cumbersome or introduce too much overhead. In these cases, you have to decide whether you have the time to keep up with upstream changes; it would be really bad if users have to choose between having your extensions with an outdated base, or switch to the updated base but lose your extensions.