aboutsummaryrefslogtreecommitdiff
path: root/runtime/doc/remote_plugin.txt
blob: ca7e763d1b760be0a1b9d74e6ec31bcd8dd7229f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
*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: