mirror of
https://github.com/neovim/neovim.git
synced 2024-12-29 14:41:06 -07:00
runtime: Refer to plugins running outside Nvim as "remote plugins"
- Rename autoload/rpc to autoload/remote - External plugins are now remote plugins - External plugins directory is "rplugin"
This commit is contained in:
parent
9a774e726c
commit
6b17082d3c
@ -11,11 +11,11 @@ let s:loaded_python_provider = 1
|
|||||||
let s:plugin_path = expand('<sfile>:p:h').'/script_host.py'
|
let s:plugin_path = expand('<sfile>:p:h').'/script_host.py'
|
||||||
" The python provider plugin will run in a separate instance of the python
|
" The python provider plugin will run in a separate instance of the python
|
||||||
" host.
|
" host.
|
||||||
call rpc#host#RegisterClone('legacy-python-provider', 'python')
|
call remote#host#RegisterClone('legacy-python-provider', 'python')
|
||||||
call rpc#host#RegisterPlugin('legacy-python-provider', s:plugin_path, [])
|
call remote#host#RegisterPlugin('legacy-python-provider', s:plugin_path, [])
|
||||||
" Ensure that we can load the python host before bootstrapping
|
" Ensure that we can load the python host before bootstrapping
|
||||||
try
|
try
|
||||||
let s:host = rpc#host#Require('legacy-python-provider')
|
let s:host = remote#host#Require('legacy-python-provider')
|
||||||
catch
|
catch
|
||||||
echomsg v:exception
|
echomsg v:exception
|
||||||
finish
|
finish
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
function! rpc#define#CommandOnHost(host, method, sync, name, opts)
|
function! remote#define#CommandOnHost(host, method, sync, name, opts)
|
||||||
let prefix = ''
|
let prefix = ''
|
||||||
|
|
||||||
if has_key(a:opts, 'range')
|
if has_key(a:opts, 'range')
|
||||||
@ -28,7 +28,7 @@ function! rpc#define#CommandOnHost(host, method, sync, name, opts)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
exe s:GetCommandPrefix(a:name, a:opts)
|
exe s:GetCommandPrefix(a:name, a:opts)
|
||||||
\ .' call rpc#define#CommandBootstrap("'.a:host.'"'
|
\ .' call remote#define#CommandBootstrap("'.a:host.'"'
|
||||||
\ . ', "'.a:method.'"'
|
\ . ', "'.a:method.'"'
|
||||||
\ . ', "'.a:sync.'"'
|
\ . ', "'.a:sync.'"'
|
||||||
\ . ', "'.a:name.'"'
|
\ . ', "'.a:name.'"'
|
||||||
@ -38,11 +38,11 @@ function! rpc#define#CommandOnHost(host, method, sync, name, opts)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! rpc#define#CommandBootstrap(host, method, sync, name, opts, forward)
|
function! remote#define#CommandBootstrap(host, method, sync, name, opts, forward)
|
||||||
let channel = rpc#host#Require(a:host)
|
let channel = remote#host#Require(a:host)
|
||||||
|
|
||||||
if channel
|
if channel
|
||||||
call rpc#define#CommandOnChannel(channel, a:method, a:sync, a:name, a:opts)
|
call remote#define#CommandOnChannel(channel, a:method, a:sync, a:name, a:opts)
|
||||||
exe a:forward
|
exe a:forward
|
||||||
else
|
else
|
||||||
exe 'delcommand '.a:name
|
exe 'delcommand '.a:name
|
||||||
@ -51,7 +51,7 @@ function! rpc#define#CommandBootstrap(host, method, sync, name, opts, forward)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! rpc#define#CommandOnChannel(channel, method, sync, name, opts)
|
function! remote#define#CommandOnChannel(channel, method, sync, name, opts)
|
||||||
let rpcargs = [a:channel, '"'.a:method.'"']
|
let rpcargs = [a:channel, '"'.a:method.'"']
|
||||||
if has_key(a:opts, 'nargs')
|
if has_key(a:opts, 'nargs')
|
||||||
" -nargs, pass arguments in a list
|
" -nargs, pass arguments in a list
|
||||||
@ -87,12 +87,12 @@ function! rpc#define#CommandOnChannel(channel, method, sync, name, opts)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! rpc#define#AutocmdOnHost(host, method, sync, name, opts)
|
function! remote#define#AutocmdOnHost(host, method, sync, name, opts)
|
||||||
let group = s:GetNextAutocmdGroup()
|
let group = s:GetNextAutocmdGroup()
|
||||||
let forward = '"doau '.group.' '.a:name.' ".'.'expand("<amatch>")'
|
let forward = '"doau '.group.' '.a:name.' ".'.'expand("<amatch>")'
|
||||||
let a:opts.group = group
|
let a:opts.group = group
|
||||||
let bootstrap_def = s:GetAutocmdPrefix(a:name, a:opts)
|
let bootstrap_def = s:GetAutocmdPrefix(a:name, a:opts)
|
||||||
\ .' call rpc#define#AutocmdBootstrap("'.a:host.'"'
|
\ .' call remote#define#AutocmdBootstrap("'.a:host.'"'
|
||||||
\ . ', "'.a:method.'"'
|
\ . ', "'.a:method.'"'
|
||||||
\ . ', "'.a:sync.'"'
|
\ . ', "'.a:sync.'"'
|
||||||
\ . ', "'.a:name.'"'
|
\ . ', "'.a:name.'"'
|
||||||
@ -103,12 +103,12 @@ function! rpc#define#AutocmdOnHost(host, method, sync, name, opts)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! rpc#define#AutocmdBootstrap(host, method, sync, name, opts, forward)
|
function! remote#define#AutocmdBootstrap(host, method, sync, name, opts, forward)
|
||||||
let channel = rpc#host#Require(a:host)
|
let channel = remote#host#Require(a:host)
|
||||||
|
|
||||||
exe 'autocmd! '.a:opts.group
|
exe 'autocmd! '.a:opts.group
|
||||||
if channel
|
if channel
|
||||||
call rpc#define#AutocmdOnChannel(channel, a:method, a:sync, a:name,
|
call remote#define#AutocmdOnChannel(channel, a:method, a:sync, a:name,
|
||||||
\ a:opts)
|
\ a:opts)
|
||||||
exe eval(a:forward)
|
exe eval(a:forward)
|
||||||
else
|
else
|
||||||
@ -118,7 +118,7 @@ function! rpc#define#AutocmdBootstrap(host, method, sync, name, opts, forward)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! rpc#define#AutocmdOnChannel(channel, method, sync, name, opts)
|
function! remote#define#AutocmdOnChannel(channel, method, sync, name, opts)
|
||||||
let rpcargs = [a:channel, '"'.a:method.'"']
|
let rpcargs = [a:channel, '"'.a:method.'"']
|
||||||
call s:AddEval(rpcargs, a:opts)
|
call s:AddEval(rpcargs, a:opts)
|
||||||
|
|
||||||
@ -128,10 +128,10 @@ function! rpc#define#AutocmdOnChannel(channel, method, sync, name, opts)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! rpc#define#FunctionOnHost(host, method, sync, name, opts)
|
function! remote#define#FunctionOnHost(host, method, sync, name, opts)
|
||||||
let group = s:GetNextAutocmdGroup()
|
let group = s:GetNextAutocmdGroup()
|
||||||
exe 'autocmd! '.group.' FuncUndefined '.a:name
|
exe 'autocmd! '.group.' FuncUndefined '.a:name
|
||||||
\ .' call rpc#define#FunctionBootstrap("'.a:host.'"'
|
\ .' call remote#define#FunctionBootstrap("'.a:host.'"'
|
||||||
\ . ', "'.a:method.'"'
|
\ . ', "'.a:method.'"'
|
||||||
\ . ', "'.a:sync.'"'
|
\ . ', "'.a:sync.'"'
|
||||||
\ . ', "'.a:name.'"'
|
\ . ', "'.a:name.'"'
|
||||||
@ -141,13 +141,13 @@ function! rpc#define#FunctionOnHost(host, method, sync, name, opts)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! rpc#define#FunctionBootstrap(host, method, sync, name, opts, group)
|
function! remote#define#FunctionBootstrap(host, method, sync, name, opts, group)
|
||||||
let channel = rpc#host#Require(a:host)
|
let channel = remote#host#Require(a:host)
|
||||||
|
|
||||||
exe 'autocmd! '.a:group
|
exe 'autocmd! '.a:group
|
||||||
exe 'augroup! '.a:group
|
exe 'augroup! '.a:group
|
||||||
if channel
|
if channel
|
||||||
call rpc#define#FunctionOnChannel(channel, a:method, a:sync, a:name,
|
call remote#define#FunctionOnChannel(channel, a:method, a:sync, a:name,
|
||||||
\ a:opts)
|
\ a:opts)
|
||||||
else
|
else
|
||||||
echoerr 'Host "'a:host.'" for "'.a:name.'" function is not available'
|
echoerr 'Host "'a:host.'" for "'.a:name.'" function is not available'
|
||||||
@ -155,7 +155,7 @@ function! rpc#define#FunctionBootstrap(host, method, sync, name, opts, group)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! rpc#define#FunctionOnChannel(channel, method, sync, name, opts)
|
function! remote#define#FunctionOnChannel(channel, method, sync, name, opts)
|
||||||
let rpcargs = [a:channel, '"'.a:method.'"', 'a:000']
|
let rpcargs = [a:channel, '"'.a:method.'"', 'a:000']
|
||||||
call s:AddEval(rpcargs, a:opts)
|
call s:AddEval(rpcargs, a:opts)
|
||||||
|
|
@ -2,12 +2,12 @@ let s:hosts = {}
|
|||||||
let s:plugin_patterns = {
|
let s:plugin_patterns = {
|
||||||
\ 'python': '*.py'
|
\ 'python': '*.py'
|
||||||
\ }
|
\ }
|
||||||
let s:external_plugins = fnamemodify($MYVIMRC, ':p:h')
|
let s:remote_plugins_manifest = fnamemodify($MYVIMRC, ':p:h')
|
||||||
\.'/.'.fnamemodify($MYVIMRC, ':t').'-external-plugins~'
|
\.'/.'.fnamemodify($MYVIMRC, ':t').'-rplugin~'
|
||||||
|
|
||||||
|
|
||||||
" Register a host by associating it with a factory(funcref)
|
" Register a host by associating it with a factory(funcref)
|
||||||
function! rpc#host#Register(name, factory)
|
function! remote#host#Register(name, factory)
|
||||||
let s:hosts[a:name] = {'factory': a:factory, 'channel': 0, 'initialized': 0}
|
let s:hosts[a:name] = {'factory': a:factory, 'channel': 0, 'initialized': 0}
|
||||||
if type(a:factory) == type(1) && a:factory
|
if type(a:factory) == type(1) && a:factory
|
||||||
" Passed a channel directly
|
" Passed a channel directly
|
||||||
@ -20,7 +20,7 @@ endfunction
|
|||||||
" as `source`, but it will run as a different process. This can be used by
|
" as `source`, but it will run as a different process. This can be used by
|
||||||
" plugins that should run isolated from other plugins created for the same host
|
" plugins that should run isolated from other plugins created for the same host
|
||||||
" type
|
" type
|
||||||
function! rpc#host#RegisterClone(name, orig_name)
|
function! remote#host#RegisterClone(name, orig_name)
|
||||||
if !has_key(s:hosts, a:orig_name)
|
if !has_key(s:hosts, a:orig_name)
|
||||||
throw 'No host named "'.a:orig_name.'" is registered'
|
throw 'No host named "'.a:orig_name.'" is registered'
|
||||||
endif
|
endif
|
||||||
@ -30,7 +30,7 @@ endfunction
|
|||||||
|
|
||||||
|
|
||||||
" Get a host channel, bootstrapping it if necessary
|
" Get a host channel, bootstrapping it if necessary
|
||||||
function! rpc#host#Require(name)
|
function! remote#host#Require(name)
|
||||||
if !has_key(s:hosts, a:name)
|
if !has_key(s:hosts, a:name)
|
||||||
throw 'No host named "'.a:name.'" is registered'
|
throw 'No host named "'.a:name.'" is registered'
|
||||||
endif
|
endif
|
||||||
@ -43,7 +43,7 @@ function! rpc#host#Require(name)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! rpc#host#IsRunning(name)
|
function! remote#host#IsRunning(name)
|
||||||
if !has_key(s:hosts, a:name)
|
if !has_key(s:hosts, a:name)
|
||||||
throw 'No host named "'.a:name.'" is registered'
|
throw 'No host named "'.a:name.'" is registered'
|
||||||
endif
|
endif
|
||||||
@ -55,7 +55,7 @@ endfunction
|
|||||||
" autocmd(async) and one function(sync):
|
" autocmd(async) and one function(sync):
|
||||||
"
|
"
|
||||||
" let s:plugin_path = expand('<sfile>:p:h').'/nvim_plugin.py'
|
" let s:plugin_path = expand('<sfile>:p:h').'/nvim_plugin.py'
|
||||||
" call rpc#host#RegisterPlugin('python', s:plugin_path, [
|
" call remote#host#RegisterPlugin('python', s:plugin_path, [
|
||||||
" \ {'type': 'command', 'name': 'PyCmd', 'sync': 1, 'opts': {}},
|
" \ {'type': 'command', 'name': 'PyCmd', 'sync': 1, 'opts': {}},
|
||||||
" \ {'type': 'command', 'name': 'PyAsyncCmd', 'sync': 0, 'opts': {'eval': 'cursor()'}},
|
" \ {'type': 'command', 'name': 'PyAsyncCmd', 'sync': 0, 'opts': {'eval': 'cursor()'}},
|
||||||
" \ {'type': 'autocmd', 'name': 'BufEnter', 'sync': 0, 'opts': {'eval': 'expand("<afile>")'}},
|
" \ {'type': 'autocmd', 'name': 'BufEnter', 'sync': 0, 'opts': {'eval': 'expand("<afile>")'}},
|
||||||
@ -64,7 +64,7 @@ endfunction
|
|||||||
"
|
"
|
||||||
" The third item in a declaration is a boolean: non zero means the command,
|
" The third item in a declaration is a boolean: non zero means the command,
|
||||||
" autocommand or function will be executed synchronously with rpcrequest.
|
" autocommand or function will be executed synchronously with rpcrequest.
|
||||||
function! rpc#host#RegisterPlugin(host, path, specs)
|
function! remote#host#RegisterPlugin(host, path, specs)
|
||||||
let plugins = s:PluginsForHost(a:host)
|
let plugins = s:PluginsForHost(a:host)
|
||||||
|
|
||||||
for plugin in plugins
|
for plugin in plugins
|
||||||
@ -73,7 +73,7 @@ function! rpc#host#RegisterPlugin(host, path, specs)
|
|||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
if rpc#host#IsRunning(a:host)
|
if remote#host#IsRunning(a:host)
|
||||||
" For now we won't allow registration of plugins when the host is already
|
" For now we won't allow registration of plugins when the host is already
|
||||||
" running.
|
" running.
|
||||||
throw 'Host "'.a:host.'" is already running'
|
throw 'Host "'.a:host.'" is already running'
|
||||||
@ -87,7 +87,7 @@ function! rpc#host#RegisterPlugin(host, path, specs)
|
|||||||
let rpc_method = a:path
|
let rpc_method = a:path
|
||||||
if type == 'command'
|
if type == 'command'
|
||||||
let rpc_method .= ':command:'.name
|
let rpc_method .= ':command:'.name
|
||||||
call rpc#define#CommandOnHost(a:host, rpc_method, sync, name, opts)
|
call remote#define#CommandOnHost(a:host, rpc_method, sync, name, opts)
|
||||||
elseif type == 'autocmd'
|
elseif type == 'autocmd'
|
||||||
" Since multiple handlers can be attached to the same autocmd event by a
|
" Since multiple handlers can be attached to the same autocmd event by a
|
||||||
" single plugin, we need a way to uniquely identify the rpc method to
|
" single plugin, we need a way to uniquely identify the rpc method to
|
||||||
@ -95,10 +95,10 @@ function! rpc#host#RegisterPlugin(host, path, specs)
|
|||||||
" name(This still has a limit: one handler per event/pattern combo, but
|
" name(This still has a limit: one handler per event/pattern combo, but
|
||||||
" there's no need to allow plugins define multiple handlers in that case)
|
" there's no need to allow plugins define multiple handlers in that case)
|
||||||
let rpc_method .= ':autocmd:'.name.':'.get(opts, 'pattern', '*')
|
let rpc_method .= ':autocmd:'.name.':'.get(opts, 'pattern', '*')
|
||||||
call rpc#define#AutocmdOnHost(a:host, rpc_method, sync, name, opts)
|
call remote#define#AutocmdOnHost(a:host, rpc_method, sync, name, opts)
|
||||||
elseif type == 'function'
|
elseif type == 'function'
|
||||||
let rpc_method .= ':function:'.name
|
let rpc_method .= ':function:'.name
|
||||||
call rpc#define#FunctionOnHost(a:host, rpc_method, sync, name, opts)
|
call remote#define#FunctionOnHost(a:host, rpc_method, sync, name, opts)
|
||||||
else
|
else
|
||||||
echoerr 'Invalid declaration type: '.type
|
echoerr 'Invalid declaration type: '.type
|
||||||
endif
|
endif
|
||||||
@ -108,9 +108,9 @@ function! rpc#host#RegisterPlugin(host, path, specs)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! rpc#host#LoadExternalPlugins()
|
function! remote#host#LoadRemotePlugins()
|
||||||
if filereadable(s:external_plugins)
|
if filereadable(s:remote_plugins_manifest)
|
||||||
exe 'source '.s:external_plugins
|
exe 'source '.s:remote_plugins_manifest
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@ -118,17 +118,17 @@ endfunction
|
|||||||
function! s:RegistrationCommands(host)
|
function! s:RegistrationCommands(host)
|
||||||
" Register a temporary host clone for discovering specs
|
" Register a temporary host clone for discovering specs
|
||||||
let host_id = a:host.'-registration-clone'
|
let host_id = a:host.'-registration-clone'
|
||||||
call rpc#host#RegisterClone(host_id, a:host)
|
call remote#host#RegisterClone(host_id, a:host)
|
||||||
let pattern = s:plugin_patterns[a:host]
|
let pattern = s:plugin_patterns[a:host]
|
||||||
let paths = globpath(&rtp, 'external-plugin/'.a:host.'/'.pattern, 0, 1)
|
let paths = globpath(&rtp, 'rplugin/'.a:host.'/'.pattern, 0, 1)
|
||||||
for path in paths
|
for path in paths
|
||||||
call rpc#host#RegisterPlugin(host_id, path, [])
|
call remote#host#RegisterPlugin(host_id, path, [])
|
||||||
endfor
|
endfor
|
||||||
let channel = rpc#host#Require(host_id)
|
let channel = remote#host#Require(host_id)
|
||||||
let lines = []
|
let lines = []
|
||||||
for path in paths
|
for path in paths
|
||||||
let specs = rpcrequest(channel, 'specs', path)
|
let specs = rpcrequest(channel, 'specs', path)
|
||||||
call add(lines, "call rpc#host#RegisterPlugin('".a:host
|
call add(lines, "call remote#host#RegisterPlugin('".a:host
|
||||||
\ ."', '".path."', [")
|
\ ."', '".path."', [")
|
||||||
for spec in specs
|
for spec in specs
|
||||||
call add(lines, " \\ ".string(spec).",")
|
call add(lines, " \\ ".string(spec).",")
|
||||||
@ -143,7 +143,7 @@ function! s:RegistrationCommands(host)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! s:UpdateExternalPlugins()
|
function! s:UpdateRemotePlugins()
|
||||||
let commands = []
|
let commands = []
|
||||||
let hosts = keys(s:hosts)
|
let hosts = keys(s:hosts)
|
||||||
for host in hosts
|
for host in hosts
|
||||||
@ -154,11 +154,11 @@ function! s:UpdateExternalPlugins()
|
|||||||
\ + ['', '']
|
\ + ['', '']
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
call writefile(commands, s:external_plugins)
|
call writefile(commands, s:remote_plugins_manifest)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
command! UpdateExternalPlugins call s:UpdateExternalPlugins()
|
command! UpdateRemotePlugins call s:UpdateRemotePlugins()
|
||||||
|
|
||||||
|
|
||||||
let s:plugins_for_host = {}
|
let s:plugins_for_host = {}
|
||||||
@ -239,5 +239,5 @@ function! s:RequirePythonHost(name)
|
|||||||
throw 'Failed to load python host'
|
throw 'Failed to load python host'
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
call rpc#host#Register('python', function('s:RequirePythonHost'))
|
call remote#host#Register('python', function('s:RequirePythonHost'))
|
||||||
" }}}
|
" }}}
|
@ -21,7 +21,7 @@ DOCS = \
|
|||||||
digraph.txt \
|
digraph.txt \
|
||||||
editing.txt \
|
editing.txt \
|
||||||
eval.txt \
|
eval.txt \
|
||||||
external_plugin.txt \
|
remote_plugin.txt \
|
||||||
farsi.txt \
|
farsi.txt \
|
||||||
filetype.txt \
|
filetype.txt \
|
||||||
fold.txt \
|
fold.txt \
|
||||||
@ -142,7 +142,7 @@ HTMLS = \
|
|||||||
digraph.html \
|
digraph.html \
|
||||||
editing.html \
|
editing.html \
|
||||||
eval.html \
|
eval.html \
|
||||||
external_plugin.html \
|
remote_plugin.html \
|
||||||
farsi.html \
|
farsi.html \
|
||||||
filetype.html \
|
filetype.html \
|
||||||
fold.html \
|
fold.html \
|
||||||
|
@ -17,7 +17,7 @@ differentiate Nvim from Vim:
|
|||||||
2. Job control |job-control|
|
2. Job control |job-control|
|
||||||
3. Python plugins |nvim-python|
|
3. Python plugins |nvim-python|
|
||||||
4. Clipboard integration |nvim-clipboard|
|
4. Clipboard integration |nvim-clipboard|
|
||||||
5. External plugins |external-plugin|
|
5. Remote plugins |remote-plugin|
|
||||||
6. Provider infrastructure |nvim-provider|
|
6. Provider infrastructure |nvim-provider|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
*external_plugin.txt* For Nvim. {Nvim}
|
*remote_plugin.txt* For Nvim. {Nvim}
|
||||||
|
|
||||||
|
|
||||||
NVIM REFERENCE MANUAL by Thiago de Arruda
|
NVIM REFERENCE MANUAL by Thiago de Arruda
|
||||||
|
|
||||||
|
|
||||||
Nvim support for external plugins *external-plugin*
|
Nvim support for remote plugins *remote-plugin*
|
||||||
|
|
||||||
1. Introduction |external-plugin-intro|
|
1. Introduction |remote-plugin-intro|
|
||||||
2. Plugin hosts |external-plugin-hosts|
|
2. Plugin hosts |remote-plugin-hosts|
|
||||||
3. Example |external-plugin-example|
|
3. Example |remote-plugin-example|
|
||||||
4. Plugin manifest |external-plugin-manifest|
|
4. Plugin manifest |remote-plugin-manifest|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
1. Introduction *external-plugin-intro*
|
1. Introduction *remote-plugin-intro*
|
||||||
|
|
||||||
A big Nvim goal is to allow extensibility in arbitrary programming languages
|
A big Nvim goal is to allow extensibility in arbitrary programming languages
|
||||||
without requiring direct support from the editor. This is achieved with
|
without requiring direct support from the editor. This is achieved with
|
||||||
external plugins, coprocesses that have a direct communication channel(via
|
remote plugins, coprocesses that have a direct communication channel(via
|
||||||
|msgpack-rpc|) with the Nvim process.
|
|msgpack-rpc|) with the Nvim process.
|
||||||
|
|
||||||
Even though these plugins are running in separate processes, they can call, be
|
Even though these plugins are running in separate processes, they can call, be
|
||||||
@ -24,7 +24,7 @@ called, and receive events just as if the code was being executed in the main
|
|||||||
process.
|
process.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
2. Plugin hosts *external-plugin-hosts*
|
2. Plugin hosts *remote-plugin-hosts*
|
||||||
|
|
||||||
While plugins can be implemented as arbitrary programs that communicate
|
While plugins can be implemented as arbitrary programs that communicate
|
||||||
directly with Nvim API and are called via |rpcrequest()| and |rpcnotify()|,
|
directly with Nvim API and are called via |rpcrequest()| and |rpcnotify()|,
|
||||||
@ -39,9 +39,9 @@ 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.
|
Nvim startup as fast a possible despite the number of installed plugins/hosts.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
3. Example *external-plugin-example*
|
3. Example *remote-plugin-example*
|
||||||
|
|
||||||
The best way to learn about external plugins is with an example, so let's see
|
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
|
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
|
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:
|
limit the number of requests made to it. Here's the plugin source code:
|
||||||
@ -93,31 +93,31 @@ 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
|
approach with |rpcnotify()|(return values or exceptions raised in the handler
|
||||||
function are ignored)
|
function are ignored)
|
||||||
|
|
||||||
To test the above plugin, it must be saved in "external-plugin/python" in a
|
To test the above plugin, it must be saved in "rplugin/python" in a
|
||||||
'runtimepath' directory(~/.nvim/external-plugin/python/limit.py for example).
|
'runtimepath' directory(~/.nvim/rplugin/python/limit.py for example).
|
||||||
Then, the external plugin manifest must be generated with
|
Then, the remote plugin manifest must be generated with
|
||||||
`:UpdateExternalPlugins`.
|
`:UpdateRemotePlugins`.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
4. External plugin manifest *external-plugin-manifest*
|
4. remote plugin manifest *remote-plugin-manifest*
|
||||||
|
|
||||||
Just installing external plugins to "external-plugin/{host}" isn't enough to
|
Just installing remote plugins to "rplugin/{host}" isn't enough to
|
||||||
load them at startup. The `:UpdateExternalPlugins` command must be executed
|
load them at startup. The `:UpdateRemotePlugins` command must be executed
|
||||||
every time an external plugin is installed, updated, or deleted.
|
every time a remote plugin is installed, updated, or deleted.
|
||||||
|
|
||||||
`:UpdateExternalPlugins` will generate the external plugin manifest, a special
|
`:UpdateRemotePlugins` will generate the remote plugin manifest, a special
|
||||||
vimscript file containing declarations for all vimscript entities
|
vimscript file containing declarations for all vimscript entities
|
||||||
(commands/autocommands/functions) defined by all external plugins, with each
|
(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
|
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
|
generated extension to the user's vimrc(it even has the vimrc filename
|
||||||
prepended).
|
prepended).
|
||||||
|
|
||||||
The manifest declarations are nothing but calls to the rpc#host#RegisterPlugin
|
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
|
function, which will take care of bootstrapping the host as soon as the
|
||||||
declared command, autocommand or function is used for the first time.
|
declared command, autocommand or function is used for the first time.
|
||||||
|
|
||||||
The manifest generation step is necessary to keep editor startup fast in
|
The manifest generation step is necessary to keep editor startup fast in
|
||||||
situations where a user has external plugins with different hosts. For
|
situations where a user has remote plugins with different hosts. For
|
||||||
example, imagine a user that has three plugins, for python, java and .NET
|
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
|
hosts respectively, if we were to load all three plugins at startup, then
|
||||||
three language runtimes would also be spawned which could take seconds!
|
three language runtimes would also be spawned which could take seconds!
|
||||||
@ -127,7 +127,7 @@ 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
|
java files, if it defines an BufEnter *.java autocommand then the java host
|
||||||
will only be spawned when java source files are loaded.
|
will only be spawned when java source files are loaded.
|
||||||
|
|
||||||
If the explicit call to `:UpdateExternalPlugins` seems incovenient, try
|
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
|
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
|
still keeping it a fast/lightweight editor for general use. It can also be
|
||||||
seen as an analogous to the |:helptags| facility.
|
seen as an analogous to the |:helptags| facility.
|
@ -1,5 +0,0 @@
|
|||||||
if exists('loaded_external_plugins') || &cp
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
let loaded_external_plugins = 1
|
|
||||||
call rpc#host#LoadExternalPlugins()
|
|
5
runtime/plugin/rplugin.vim
Normal file
5
runtime/plugin/rplugin.vim
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
if exists('loaded_remote_plugins') || &cp
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
let loaded_remote_plugins = 1
|
||||||
|
call remote#host#LoadRemotePlugins()
|
@ -346,20 +346,20 @@ local function host()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function register()
|
local function register()
|
||||||
eval('rpc#host#Register("busted", '..channel()..')')
|
eval('remote#host#Register("busted", '..channel()..')')
|
||||||
end
|
end
|
||||||
|
|
||||||
command_specs_for('rpc#define#CommandOnChannel', true, channel)
|
command_specs_for('remote#define#CommandOnChannel', true, channel)
|
||||||
command_specs_for('rpc#define#CommandOnChannel', false, channel)
|
command_specs_for('remote#define#CommandOnChannel', false, channel)
|
||||||
command_specs_for('rpc#define#CommandOnHost', true, host, register)
|
command_specs_for('remote#define#CommandOnHost', true, host, register)
|
||||||
command_specs_for('rpc#define#CommandOnHost', false, host, register)
|
command_specs_for('remote#define#CommandOnHost', false, host, register)
|
||||||
|
|
||||||
autocmd_specs_for('rpc#define#AutocmdOnChannel', true, channel)
|
autocmd_specs_for('remote#define#AutocmdOnChannel', true, channel)
|
||||||
autocmd_specs_for('rpc#define#AutocmdOnChannel', false, channel)
|
autocmd_specs_for('remote#define#AutocmdOnChannel', false, channel)
|
||||||
autocmd_specs_for('rpc#define#AutocmdOnHost', true, host, register)
|
autocmd_specs_for('remote#define#AutocmdOnHost', true, host, register)
|
||||||
autocmd_specs_for('rpc#define#AutocmdOnHost', false, host, register)
|
autocmd_specs_for('remote#define#AutocmdOnHost', false, host, register)
|
||||||
|
|
||||||
function_specs_for('rpc#define#FunctionOnChannel', true, channel)
|
function_specs_for('remote#define#FunctionOnChannel', true, channel)
|
||||||
function_specs_for('rpc#define#FunctionOnChannel', false, channel)
|
function_specs_for('remote#define#FunctionOnChannel', false, channel)
|
||||||
function_specs_for('rpc#define#FunctionOnHost', true, host, register)
|
function_specs_for('remote#define#FunctionOnHost', true, host, register)
|
||||||
function_specs_for('rpc#define#FunctionOnHost', false, host, register)
|
function_specs_for('remote#define#FunctionOnHost', false, host, register)
|
Loading…
Reference in New Issue
Block a user