It hasn't been too long since Pathogen first came into being and widely adopted by the Vim community. Obviously the rapid growth of GitHub has played a crucial role in the progress. Since then, we have observed the emergence of a wide variety of plugin managers, Vundle, vim-addon-manager, NeoBundle, and so on. And even I came up with a small plugin manager called vim-plug.
Before Pathogen and GitHub, we used to make our
all muddled up with the files downloaded from vim.org,
practically making it impossible to manage afterwards. But now we take it for
granted that we have version-controlled plugins in their own separate
directories, and use fancy installers from plugin managers every day. So yeah,
definitely we've come a long way, and I'm mostly happy with the status quo.
However, there's one thing that has always irked me about Vim plugins, which is the lack of proper dependency control mechanism. There's currently no way the developer of a plugin can effectively enforce the users of the plugin to install the prerequisites as well. The only option is to tell them to do so in the installation guide.
"... so in order to use my plugin you have to install A as well. And since A requires B and C, you also have to install them."
But what if at one point plugin C is updated and suddenly requires yet another plugin? If you are the plugin developer, how can you keep track of such changes and how are you going to notify the users of your plugin? This rarely happens in practice, but I'm just suggesting that passing the burden of dependency management on to the users has an inherent flaw. Also, a user with many plugins can easily lose track of the dependencies among them and will not be able to remove a plugin without worrying about breaking the other ones.
It's a headache. So instead of reusing preexisting plugins, a plugin developer is tempted to duplicate the code from them. Simply put, the lack of automatic dependency resolution discourages proper modularization of code. And I don't like it.
"But they're just plugins for a text editor. Why do you care so much?"
I ask myself this and I know it's a fair question. Perhaps I'm being too serious about Vim plugins. But my justification is that I'm a software engineer trained to frown upon any mindless copy-and-paste code so I couldn't just close my eyes on this issue regarding my favorite everyday tool.
I believe that Vundle was heavily inspired by Rubygems (and Bundler), however it misses the most important point of it, dependency management. There are requests for it, but I don't see it coming anytime soon. And its successor NeoBundle which offers much broader range of features, also has yet to address the issue. The author of NeoBundle argues that vim.org should be responsible for keeping track of the dependencies between the plugins and build a centralized database, which I agree to a certain extent, but I don't think it's happening in the near future.
There is a community-attempt to build such a database with dependency information, which is for vim-addon-manager. But I'm a bit skeptical about the scalability of this centralized approach of building a single registry. Can we keep it up to date at all times? Can we make every plugin developer voluntarily update the registry?
Instead, I believe each plugin should store its dependency information on its own repository, effectively building a distributed dependency database. The problem is, there is no consensus on how it should be done. Obviously we don't have "Vim Plugin Standards Committee" or something like that.
Anyway, I mentioned in an earlier post that I had accidentally created a plugin manager called vim-plug, whose most prominent feature is its lack of features. It's so primitive that I have the luxury of prototyping an experimental feature on it without too much headache.
I had this simple idea of resolving the dependency of a Vim plugin. Each plugin
has a file called Plugfile in its root directory, which is simply a set of
Plug commands. For example, if the content of Plugfile is as follows,
Plug 'junegunn/vim-emoji' Plug 'junegunn/vim-easy-align'
it means that this plugin requires those two other plugins to be installed. So if you install a plugin with a Plugfile using vim-plug (wow, that's a lot of plugs in a sentence),
- vim-plug first installs the plugin
- And sees if it has Plugfile
- The Plugfile is loaded and vim-plug discovers its dependent plugins
- Dependent plugins are installed as well, then their Plugfiles are examined and their dependencies are resolved recursively.
See below how vim-plug installer handles plugins with Plugfiles:
Despite the simplicity, it works just fine. (Yes, for now I'm completely ignoring subtle issues like possible branch conflicts, etc.)
However, this scheme has some fundamental problems.
There is no plugin out there yet with the suggested Plugfile. This is no wonder since currently a very few people are using vim-plug, and I came up with this method just a few days ago. I'll definitely consider including Plugfile in my future projects, but will the other plugin developers agree on the concept of it and add it to their repositories? I don't know.
Plugcommand, so the users of the other plugin managers will not be likely to benefit from the presence of it. I decided to use
Plugcommand simply because it was easier for me to implement with it at the moment, but using a neutral data format such as JSON or YAML seems to be a better idea.
It is always possible that a certain repository is renamed or removed from GitHub. In that case, all the references to it must be updated accordingly.
So basically this is still just a proof-of-concept implementation of dependency resolution and I cannot know how it will turn out. If you are a Vim plugin developer and maintain a plugin with dependency, please consider adding a Plugfile to your repository.
Happy Vimming. And don't miss the final episode of Breaking Bad.
After I published this post, I found an interesting project tackling Vim plugin dependency, called vim-flavor. vim-flavor is a Vim plugin manager distributed as a Ruby gem, which implements Bundler-like dependency resolution scheme with semantic versioning. It relies on the presence of Flavorfile to discover the dependency of a plugin. The concept is similar to Plugfile, but it also allows you to specify the required versions of the dependent plugins, while with Plugfile you can only specifiy the branch or tag for each repository. It's a great project and you should check it out. However, it holds the same problem as vim-plug, that it uses its own syntax for dependency specification rather than using a neutral data format. The situation here is a bit different from that of the Ruby community which unanimously agreed upon the use of Gemfile from Bundler (and gemspec of course). Many of the Vim users are already using a number of different plugin managers, and we can't really expect vim-plug or vim-flavor to be a game changer. And although its ambitious implementation of semantic versioning looks promising, in practice most of the users and developers of Vim plugins don't seem to care much about versioning.