mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 11:15:14 -07:00
fbaee922d1
closes #9719
142 lines
6.1 KiB
Plaintext
142 lines
6.1 KiB
Plaintext
*remote_plugin.txt* Nvim
|
|
|
|
|
|
NVIM REFERENCE MANUAL by Thiago de Arruda
|
|
|
|
|
|
Nvim support for remote plugins *remote-plugin*
|
|
|
|
Type |gO| to see the table of contents.
|
|
|
|
==============================================================================
|
|
1. Introduction *remote-plugin-intro*
|
|
|
|
Extensibility is a primary goal of Nvim. Any programming language may be used
|
|
to extend Nvim without changes to Nvim itself. This is achieved with remote
|
|
plugins, coprocesses that have a direct communication channel (via |RPC|) with
|
|
the Nvim process.
|
|
|
|
Even though these plugins run in separate processes they can call, be called,
|
|
and receive events just as if the plugin's code were executed in the main
|
|
process.
|
|
|
|
==============================================================================
|
|
2. Plugin hosts *remote-plugin-hosts*
|
|
|
|
While plugins can be implemented as arbitrary programs that communicate
|
|
directly with the high-level Nvim API and are called via |rpcrequest()| and
|
|
|rpcnotify()|, that is not the best approach. Instead, developers should first
|
|
check whether a plugin host is available for their chosen programming language.
|
|
|
|
Plugin hosts are programs that provide a high-level environment for plugins,
|
|
taking care of most boilerplate involved in defining commands, autocmds, and
|
|
functions that are implemented over |RPC| connections. Hosts are loaded only
|
|
when one of their registered plugins require it, keeping Nvim's startup as
|
|
fast as possible, even if many plugins/hosts are installed.
|
|
|
|
==============================================================================
|
|
3. Example *remote-plugin-example*
|
|
|
|
The best way to learn about remote plugins is with an example, so let's see
|
|
what a 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 pynvim
|
|
|
|
@pynvim.plugin
|
|
class Limit(object):
|
|
def __init__(self, vim):
|
|
self.vim = vim
|
|
self.calls = 0
|
|
|
|
@pynvim.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))
|
|
|
|
@pynvim.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))
|
|
|
|
@pynvim.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 idiomatic Python (classes,
|
|
methods, and decorators). The translation between these language-specific
|
|
idioms to Vimscript occurs while the plugin manifest is being generated (see
|
|
the next section).
|
|
|
|
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()|, meaning 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 (~/.config/nvim/rplugin/python/limit.py for example).
|
|
Then, the remote plugin manifest must be generated with
|
|
|:UpdateRemotePlugins|.
|
|
|
|
==============================================================================
|
|
4. Remote plugin manifest *remote-plugin-manifest*
|
|
*:UpdateRemotePlugins*
|
|
|
|
Just installing remote plugins to "rplugin/{host}" isn't enough for them to be
|
|
automatically loaded when required. You must execute |:UpdateRemotePlugins|
|
|
every time a remote plugin is installed, updated, or deleted.
|
|
|
|
|:UpdateRemotePlugins| generates 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.
|
|
|
|
Manifest declarations are just calls to the `remote#host#RegisterPlugin`
|
|
function, which takes 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 Nvim's startup fast in
|
|
situations where a user has remote plugins with different hosts. For example,
|
|
say a user 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, say the Java plugin is a semantic completion engine for Java code.
|
|
If it defines the autocommand "BufEnter *.java", then the Java host is spawned
|
|
only when Nvim loads a buffer matching "*.java".
|
|
|
|
If the explicit call to |:UpdateRemotePlugins| seems inconvenient, try to see
|
|
it like this: It's a way to provide IDE capabilities in Nvim while still
|
|
keeping it fast and lightweight for general use. It's also analogous to the
|
|
|:helptags| command.
|
|
|
|
*$NVIM_RPLUGIN_MANIFEST*
|
|
Unless $NVIM_RPLUGIN_MANIFEST is set the manifest will be written to a file
|
|
named `rplugin.vim` at:
|
|
|
|
Unix ~
|
|
$XDG_DATA_HOME/nvim/ or ~/.local/share/nvim/
|
|
|
|
Windows ~
|
|
$LOCALAPPDATA/nvim/ or ~/AppData/Local/nvim/
|
|
|
|
==============================================================================
|
|
vim:tw=78:ts=8:noet:ft=help:norl:
|