diff options
-rw-r--r-- | runtime/doc/external_plugin.txt | 104 | ||||
-rw-r--r-- | runtime/doc/nvim_clipboard.txt | 41 | ||||
-rw-r--r-- | runtime/doc/nvim_intro.txt | 2 | ||||
-rw-r--r-- | runtime/doc/nvim_provider.txt | 77 | ||||
-rw-r--r-- | runtime/doc/nvim_python.txt | 7 |
5 files changed, 195 insertions, 36 deletions
diff --git a/runtime/doc/external_plugin.txt b/runtime/doc/external_plugin.txt new file mode 100644 index 0000000000..3f7772c906 --- /dev/null +++ b/runtime/doc/external_plugin.txt @@ -0,0 +1,104 @@ +*external_plugin.txt* For Nvim. {Nvim} + + + NVIM REFERENCE MANUAL by Thiago de Arruda + + +Nvim support for external plugins *external-plugin* + +1. Introduction |external-plugin-intro| +2. Plugin Hosts |external-plugin-hosts| +3. Example |external-plugin-example| + +============================================================================== +1. Introduction *external-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 +external 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 *external-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 it's registered plugins are required, keeping +Nvim startup as fast a possible despite the number of installed plugins/hosts. + +============================================================================== +3. Example *external-plugin-example* + +The best way to learn how to create external plugins is with an example, so +let's see how to implement a very useless python plugin that exports a +command, a function and an autocmd(requires configuration detailed in +|nvim-python| to work). + +The plugin is called 'Limit', and all it does is limit the number of "calls" +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 +< + +This code needs to be saved to "external/python/limit.py" in a runtime +directory(~/.nvim/plugin/external/python/limit.py for example). + +As can be seen, the plugin is implemented using pure python idioms(classes, +methods and decorators). It is the host's responsibility to translate +language-specific idioms to vimscript entities. Notice that the exported +command and autocmd are defined with the "sync" flag, which tells Nvim to call +it using |rpcrequest()|. Since the "Func" doesn't set "sync", it will be +called using |rpcnotify()|. + +Just installing the plugin to ~/.nvim/plugin/external/python/limit.py won't +make Nvim load it at startup. That is because external plugins are loaded +only when required, and for that Nvim must be fed with information about +installed external plugins with the `:UpdateExternalPlugins` command(must be +called whenever plugins are updated, this is analogous to the |:helptags| +command but for external plugins). + +============================================================================== + vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/nvim_clipboard.txt b/runtime/doc/nvim_clipboard.txt index 74c9254c70..cf38dea3d6 100644 --- a/runtime/doc/nvim_clipboard.txt +++ b/runtime/doc/nvim_clipboard.txt @@ -6,42 +6,25 @@ Clipboard integration for Nvim *nvim-clipboard* -By default, Nvim has no connection to the system clipboard. Eventually that -will be implemented by UI programs, which connect to Nvim via |msgpack-rpc|. - -Even though externalized UIs are not available yet, there's a workaround that -enables clipboard usage through the python interface(which also uses -|msgpack-rpc| and consequently can implement the clipboard methods required -by Nvim): - -- Make sure you follow the setup instructions in |nvim-python-quickstart|. -- Install the `xerox` python module: - > - $ pip install xerox -< -- Create a ~/.nvim/pythonx/nvim_clipboard.py file with the following contents: - > - import xerox +Nvim has no connection to the system clipboard, instead it is accessible +through the |nvim-provider| infrastructure which transparently uses shell +commands for communicating with the clipboard. - class NvimClipboard(object): - def __init__(self, vim): - self.provides = ['clipboard'] +To use clipboard on Nvim, make sure you have one of the following programs +installed and available on $PATH: - def clipboard_get(self): - return xerox.paste().split('\n') +- xclip +- xsel(newer alternative to xclip) +- pbcopy/pbpaste(already available on Mac OS X) - def clipboard_set(self, lines): - xerox.copy(u'\n'.join([line.decode('utf-8') for line in lines])) -< -This should enable the '+' and '*' registers. As an optional step, set the -'unnamedclip' option to transparently access clipboard using the unnamed -register. If you use the same |vimrc| for both Vim and Nvim, make sure you -only set the option when `has('nvim')` is true: +Having any of these programs should enable the '+' and '*' registers. As an +optional step, set the 'unnamedclip' option to transparently access clipboard +using the unnamed register. If you use the same |vimrc| for both Vim and Nvim, +make sure you only set the option when `has('nvim')` is true: > if has('nvim') set unnamedclip endif < - ============================================================================== vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/nvim_intro.txt b/runtime/doc/nvim_intro.txt index 7b115b1912..177c906db6 100644 --- a/runtime/doc/nvim_intro.txt +++ b/runtime/doc/nvim_intro.txt @@ -17,6 +17,8 @@ differentiate Nvim from Vim: 2. Job control |job-control| 3. Python plugins |nvim-python| 4. Clipboard integration |nvim-clipboard| +5. External plugins |external-plugin| +6. Provider infrastructure |nvim-provider| ============================================================================== vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/nvim_provider.txt b/runtime/doc/nvim_provider.txt new file mode 100644 index 0000000000..e67a5c174c --- /dev/null +++ b/runtime/doc/nvim_provider.txt @@ -0,0 +1,77 @@ +*nvim_provider.txt* For Nvim. {Nvim} + + + NVIM REFERENCE MANUAL by Thiago de Arruda + + +Nvim provider infrastructure *nvim-provider* + +First of all, this document is meant to be read by developers interested in +contributing to the refactoring effort. If you are a normal user or plugin +developer looking to learn about Nvim |msgpack-rpc| infrastructure for +implementing plugins in other programming languages, see |external-plugin|. +For instructions on how to enable python plugins, see |nvim-python|. For +clipboard, see |nvim-clipboard|. + +Instead of doing everything by itself, Nvim aims to simplify it's own +maintenance by delegating as much work as possible to external systems. But +some Vim components are too tightly coupled and in some cases the refactoring +work necessary to swap in-house implementations by code that integrates to +other systems is too great. Nvim provider infrastructure is a facility that +aims to make this task simpler. + +To understand why the provider infrastructure is useful, let us consider two +examples of integration with external systems that are implemented in Vim and +are now decoupled from Nvim core as providers: + +The first example is clipboard integration: On the original Vim source code, +clipboard functions account for more than 1k lines of C source code(and that +is just on ui.c). All to peform two tasks that are now accomplished with +simple shell commands such as xclip or pbcopy/pbpaste. + +The other example is python scripting support: Vim has three files dedicated +to embed the python interpreter: if_python.c, if_python3.c and if_py_both.h. +Together these files sum about 9.5k lines of C source code. On Nvim, python +scripting is performed by an external host process that is running 2k sloc +python program. + +In a perfect world, we would implement python and clipboard integration in +pure vimscript and without touching the C code. Unfortunately we can't achieve +these goals without severly compromising backwards compatibility with Vim. +Thats where providers comes to rescue. + +In essence, this infrastructure a simple framework that simplifies the task of +calling vimscript from C code, making it simpler to rewrite C functions that +interact with external systems in pure vimscript. It is composed of two +functions in eval.c: + +- eval_call_provider(name, method, arguments): Call a provider(name) method + with arguments +- eval_has_provider(name): Checks if a provider is implemented + +What these functions do is simple: + +- eval_call_provider will call the provider#(name)#Call function passing in + the method and arguments. +- eval_has_provider will return true if the provider#(name)#Call function is + implemented, and is called by the "has" vimscript function to check if + features are available. + +The basic idea is that the provider#(name)#Call function should implement +integration with an external system, because calling shell commands and +|msgpack-rpc| clients(Nvim only) is easier to do in vimscript. + +Now, back to the python example. Instead of modifying vimscript to allow the +definition of lowercase functions and commands(for the |:python|, |:pyfile| +and |:pydo| commands, and the |pyeval()| function), which would break +backwards compatibility with Vim, we implemented the +autoload/provider/python.vim script and the provider#python#Call function +that is only defined if an external python host is started successfully. + +That works well with the has('python') expression (normally used by python +plugins) because if the python host isn't installed then the plugin will +"think" it is running in a Vim compiled without +python feature. + + +============================================================================== + vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/nvim_python.txt b/runtime/doc/nvim_python.txt index 9e6f408657..e60cc93b19 100644 --- a/runtime/doc/nvim_python.txt +++ b/runtime/doc/nvim_python.txt @@ -27,13 +27,6 @@ simple step-by-step: > $ pip install neovim < -- Add the following snippet to your `vimrc`, before any python plugins are - loaded: -> - if has('nvim') - runtime! python_setup.vim - endif -< Most python plugins created for Vim 7.3 should work after these steps. ============================================================================== |