123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- *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 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: >python
- 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:
|