mirror of
https://github.com/neovim/neovim.git
synced 2025-09-21 10:48:18 +00:00

- Rename autoload/rpc to autoload/remote - External plugins are now remote plugins - External plugins directory is "rplugin"
137 lines
6.1 KiB
Plaintext
137 lines
6.1 KiB
Plaintext
*remote_plugin.txt* For Nvim. {Nvim}
|
|
|
|
|
|
NVIM REFERENCE MANUAL by Thiago de Arruda
|
|
|
|
|
|
Nvim support for remote plugins *remote-plugin*
|
|
|
|
1. Introduction |remote-plugin-intro|
|
|
2. Plugin hosts |remote-plugin-hosts|
|
|
3. Example |remote-plugin-example|
|
|
4. Plugin manifest |remote-plugin-manifest|
|
|
|
|
==============================================================================
|
|
1. Introduction *remote-plugin-intro*
|
|
|
|
A big Nvim goal is to allow extensibility in arbitrary programming languages
|
|
without requiring direct support from the editor. This is achieved with
|
|
remote plugins, coprocesses that have a direct communication channel(via
|
|
|msgpack-rpc|) with the Nvim process.
|
|
|
|
Even though these plugins are running in separate processes, they can call, be
|
|
called, and receive events just as if the code was being executed in the main
|
|
process.
|
|
|
|
==============================================================================
|
|
2. Plugin hosts *remote-plugin-hosts*
|
|
|
|
While plugins can be implemented as arbitrary programs that communicate
|
|
directly with Nvim API and are called via |rpcrequest()| and |rpcnotify()|,
|
|
that is not the best approach available. Instead, developers should first
|
|
check if a plugin host implementation is available for their favorite
|
|
programming language.
|
|
|
|
Plugin hosts are programs that provide a high level environment for plugins,
|
|
and also take care of most boilerplate involved in defining commands, autocmds
|
|
and functions that are implemented over msgpack-rpc connections. They are
|
|
loaded the first time one of its registered plugins are required, keeping
|
|
Nvim startup as fast a possible despite the number of installed plugins/hosts.
|
|
|
|
==============================================================================
|
|
3. Example *remote-plugin-example*
|
|
|
|
The best way to learn about remote plugins is with an example, so let's see
|
|
how a very useless python plugin looks like. This plugin exports a command, a
|
|
function and an autocmd. The plugin is called 'Limit', and all it does is
|
|
limit the number of requests made to it. Here's the plugin source code:
|
|
>
|
|
import neovim
|
|
|
|
@neovim.plugin
|
|
class Limit(object):
|
|
def __init__(self, vim):
|
|
self.vim = vim
|
|
self.calls = 0
|
|
|
|
@neovim.command('Cmd', range='', nargs='*', sync=True)
|
|
def command_handler(self, args, range):
|
|
self._increment_calls()
|
|
self.vim.current.line = (
|
|
'Command: Called %d times, args: %s, range: %s' % (self.calls,
|
|
args,
|
|
range))
|
|
|
|
@neovim.autocmd('BufEnter', pattern='*.py', eval='expand("<afile>")',
|
|
sync=True)
|
|
def autocmd_handler(self, filename):
|
|
self._increment_calls()
|
|
self.vim.current.line = (
|
|
'Autocmd: Called %s times, file: %s' % (self.calls, filename))
|
|
|
|
@neovim.function('Func')
|
|
def function_handler(self, args):
|
|
self._increment_calls()
|
|
self.vim.current.line = (
|
|
'Function: Called %d times, args: %s' % (self.calls, args))
|
|
|
|
def _increment_calls(self):
|
|
if self.calls == 5:
|
|
raise Exception('Too many calls!')
|
|
self.calls += 1
|
|
<
|
|
|
|
As can be seen, the plugin is implemented using pure python idioms(classes,
|
|
methods and decorators), the translation between these language-specific
|
|
idioms to vimscript occurs while the plugin manifest is being generated(see
|
|
below).
|
|
|
|
Notice that the exported command and autocmd are defined with the "sync" flag,
|
|
which affects how Nvim calls the plugin: with "sync" the |rpcrequest()|
|
|
function is used, which will block Nvim until the handler function returns a
|
|
value. Without the "sync" flag, the call is made using a fire and forget
|
|
approach with |rpcnotify()|(return values or exceptions raised in the handler
|
|
function are ignored)
|
|
|
|
To test the above plugin, it must be saved in "rplugin/python" in a
|
|
'runtimepath' directory(~/.nvim/rplugin/python/limit.py for example).
|
|
Then, the remote plugin manifest must be generated with
|
|
`:UpdateRemotePlugins`.
|
|
|
|
==============================================================================
|
|
4. remote plugin manifest *remote-plugin-manifest*
|
|
|
|
Just installing remote plugins to "rplugin/{host}" isn't enough to
|
|
load them at startup. The `:UpdateRemotePlugins` command must be executed
|
|
every time a remote plugin is installed, updated, or deleted.
|
|
|
|
`:UpdateRemotePlugins` will generate the remote plugin manifest, a special
|
|
vimscript file containing declarations for all vimscript entities
|
|
(commands/autocommands/functions) defined by all remote plugins, with each
|
|
entity associated with the host and plugin path. The manifest can be seen as a
|
|
generated extension to the user's vimrc(it even has the vimrc filename
|
|
prepended).
|
|
|
|
The manifest declarations are nothing but calls to the remote#host#RegisterPlugin
|
|
function, which will take care of bootstrapping the host as soon as the
|
|
declared command, autocommand or function is used for the first time.
|
|
|
|
The manifest generation step is necessary to keep editor startup fast in
|
|
situations where a user has remote plugins with different hosts. For
|
|
example, imagine a user that has three plugins, for python, java and .NET
|
|
hosts respectively, if we were to load all three plugins at startup, then
|
|
three language runtimes would also be spawned which could take seconds!
|
|
|
|
With the manifest, each host will only be loaded when required. Continuing
|
|
with the example, imagine the java plugin is a semantic completion engine for
|
|
java files, if it defines an BufEnter *.java autocommand then the java host
|
|
will only be spawned when java source files are loaded.
|
|
|
|
If the explicit call to `:UpdateRemotePlugins` seems incovenient, try
|
|
to see it like this: Its a way to give IDE-like capabilities to nvim while
|
|
still keeping it a fast/lightweight editor for general use. It can also be
|
|
seen as an analogous to the |:helptags| facility.
|
|
|
|
==============================================================================
|
|
vim:tw=78:ts=8:noet:ft=help:norl:
|