Neovim Remote Plugins: NodeJS Strikes Back
Neovim Remote Plugins: NodeJS Strikes Back
Recap: I've been on a life-long quest to custom Vim to the point where it'd become impossible to know where the editor stops and the man begins. I experimented with Vim's embedded Perl interperter and created a [plugin system][cpan:Vim-X] for it (as documented here. Then I discovered Neovim. Highly compatible, but with less cruft and a few extra goodies over classic Vim. One of those goodies was an asynchronous RPC interface for external plugins. That's not the kind of shininess that can be resisted, so I migrated. Writing another plugin system for Perl-based plugins along the way, because of course I had to.
But this week, I found out that while I had to, I might not have to anymore.
When I wrote Neovim::RPC, I only knew of the core msgpack RPC support of Neovim. Writing plugins was the (relatively) easy part. The devilish details were in the trimmings: the VimL code needed to start the child Perl process, the on-demand loading of plugins the Perl process itself had to have so that it'd not have to load the world on startup all the time, etc.
As it turns out, Neovim has this concept of remote plugins, which provides a standard way of dealing with that heavy lifting.
Remote Host Powered Plugins
~/.config/nvim/rplugin/node. Then from within neovim you'd run the command
:UpdateRemotePlugins, which visits all plugins and generates the list of commands, functions, and autocommands they provides, which is then saved in
That file will look something like:
The cool part is that thanks to that file, Neovim is aware of the available functions and commands, but will only evaluate the plugins' code when they are invoked. Better still: the remote host itself will only spin to life when one of its plugins is used.
That pay-as-you-go approach means much faster startup time, and let me have as many plugins as I want without the fear of savaging my memory budget each time I open a new log file.
A Perl Remote Host?
As you might have noticed, Perl is missing from the list of supported remote host languages. This is something that could be rectified with a little bit of elbow grease.
Neovim::RPC already does most of what the other remote hosts are doing, the trick would be to tweak it to conform to the standard remote host behavior, taking of the already-implemented host as an example.
It's already there. Although I love building my own monuments to Hubris, sometimes a freebie does feel good.
async / await, and that mechanism does makes writing asynchronous code much more legible.
All that to say that, for once, I was curious to try what was already on offer before rushing in and reimplenting it myself. What do you know, I might actually getting wiser in my old age...
Comparison study #1
For a first comparison, I picked a very simple plugin. Its whole purpose in life is to replace the token
__PACKAGE__ in the current line into the Perl module representation of the filename -- the end-goal being having a snippet/macro take automatically inserting
package Foo::Bar; in the Perl file
Neovim::RPC, the plugin looks like
And it needs the following glue in the neovim config:
It's... not bad. We request the filename and the current line's content from neovim (in the form of promises, because asynchronicity), munge the line with the resolved package name, and then push it back to the editor. Admittedly not cristal-clear at first read, but nothing that will straight-up make you reach for the bottle.
The regular expression leger-de-main isn't as crisp, but
setPackageName is much more straightforward than
file_to_package_name, mostly thanks to the
Comparison study #2
TW_show from my neovim-based Taskwarrior UI. In Perl, it looks like:
I have to admit: I dig it. I dig it a lot.
Although I'm still awfully proud of the
Neovim::RPC monster I've cobbled together, right now it seems that wisdom lies in joining the side favored by the winds of victory. The node client is officially supported by the Neovim crew and works pretty much out of the box. This means that remote plugins are fairly easy to share bundled as regular plugins -- a huge difference with the
So... what I guess I'm saying is: looks like I have a few plugins to convert. Should keep me busy for a few days.