neovim/runtime/doc/develop.txt

357 lines
14 KiB
Plaintext
Raw Normal View History

*develop.txt* Nvim
NVIM REFERENCE MANUAL
Development of Nvim *development* *dev*
This reference describes design constraints and guidelines, for developing
Nvim applications or Nvim itself.
Architecture and internal concepts are covered in src/nvim/README.md
Nvim is free and open source. Everybody is encouraged to contribute.
https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md
Type |gO| to see the table of contents.
==============================================================================
2017-04-17 17:52:38 -04:00
Design goals *design-goals*
Most important things come first (roughly). Some items conflict; this is
intentional. A balance must be found.
NVIM IS... IMPROVED *design-improved*
The Neo bits of Nvim should make it a better Vim, without becoming a
completely different editor.
- In matters of taste, prefer Vim/Unix tradition. If there is no relevant
Vim/Unix tradition, consider the "common case".
- A feature that people do not know about is a useless feature. Don't add
obscure features, or at least add hints in documentation that they exist.
- There is no limit to the features that can be added. Selecting new features
2017-04-17 17:52:38 -04:00
is based on (1) what users ask for, (2) how much effort it takes to
implement and (3) someone actually implementing it.
- Backwards compatibility is a feature. The RPC API in particular should
never break.
NVIM IS... WELL DOCUMENTED *design-documented*
- A feature that isn't documented is a useless feature. A patch for a new
feature must include the documentation.
2017-04-17 17:52:38 -04:00
- Documentation should be comprehensive and understandable. Use examples.
- Don't make the text unnecessarily long. Less documentation means that an
item is easier to find.
NVIM IS... HIGH SPEED AND SMALL IN SIZE *design-speed-size*
2017-04-17 17:52:38 -04:00
Keep Nvim small and fast.
- Computers are becoming faster and bigger each year. Vim can grow too, but
no faster than computers are growing. Keep Vim usable on older systems.
- Many users start Vim from a shell very often. Startup time must be short.
- Commands must work efficiently. The time they consume must be as small as
possible. Useful commands may take longer.
- Don't forget that some people use Vim over a slow connection. Minimize the
communication overhead.
- Vim is a component among other components. Don't turn it into a massive
application, but have it work well together with other programs.
NVIM IS... MAINTAINABLE *design-maintain*
- The source code should not become a mess. It should be reliable code.
- Use comments in a useful way! Quoting the function name and argument names
is NOT useful. Do explain what they are for.
- Porting to another platform should be made easy, without having to change
too much platform-independent code.
- Use the object-oriented spirit: Put data and code together. Minimize the
knowledge spread to other parts of the code.
NVIM IS... NOT *design-not*
Nvim is not an operating system; instead it should be composed with other
tools or hosted as a component. Marvim once said: "Unlike Emacs, Nvim does not
2017-04-17 17:52:38 -04:00
include the kitchen sink... but it's good for plumbing."
==============================================================================
Developer guidelines *dev-guidelines*
2017-04-17 17:52:38 -04:00
PROVIDERS *dev-provider*
A primary goal of Nvim is to allow extension of the editor without special
knowledge in the core. Some core functions are delegated to "providers"
implemented as external scripts.
Examples:
1. In the Vim source code, clipboard logic accounts for more than 1k lines of
C source code (ui.c), to perform two tasks that are now accomplished with
shell commands such as xclip or pbcopy/pbpaste.
2. Python scripting support: Vim has three files dedicated to embedding 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. In contrast, Nvim Python
scripting is performed by an external host process implemented in ~2k lines
of Python.
The provider framework invokes VimL from C. It is composed of two functions
in eval.c:
- eval_call_provider(name, method, arguments): calls provider#{name}#Call
with the method and arguments.
- eval_has_provider(name): Checks the `g:loaded_{name}_provider` variable
which must be set to 2 by the provider script to indicate that it is
"enabled and working". Called by |has()| to check if features are available.
For example, the Python provider is implemented by the
"autoload/provider/python.vim" script, which sets `g:loaded_python_provider`
to 2 only if a valid external Python host is found. Then `has("python")`
reflects whether Python support is working.
*provider-reload*
Sometimes a GUI or other application may want to force a provider to
"reload". To reload a provider, undefine its "loaded" flag, then use
|:runtime| to reload it: >
:unlet g:loaded_clipboard_provider
:runtime autoload/provider/clipboard.vim
DOCUMENTATION *dev-doc*
- Do not prefix help tags with "nvim-". Use |vim_diff.txt| to document
differences from Vim; no other distinction is necessary.
- If a Vim feature is removed, delete its help section and move its tag to
|vim_diff.txt|.
- Move deprecated features to |deprecated.txt|.
- Use consistent language.
- "terminal" in a help tag always means "the embedded terminal emulator", not
"the user host terminal".
- Use "tui-" to prefix help tags related to the host terminal, and "TUI"
in prose if possible.
2018-12-08 19:49:59 -05:00
- Docstrings: do not start parameter descriptions with "The" or "A" unless it
is critical to avoid ambiguity.
GOOD: >
/// @param dirname Path fragment before `pend`
< BAD: >
/// @param dirname The path fragment before `pend`
<
C docstrings ~
Nvim API documentation lives in the source code, as docstrings (Doxygen
comments) on the function definitions. The |api| :help is generated
from the docstrings defined in src/nvim/api/*.c.
Docstring format:
- Lines start with `///`
- Special tokens start with `@` followed by the token name:
`@note`, `@param`, `@returns`
- Limited markdown is supported.
- List-items start with `-` (useful to nest or "indent")
- Use `<pre>` for code samples.
Example: the help for |nvim_open_win()| is generated from a docstring defined
in src/nvim/api/vim.c like this: >
/// Opens a new window.
/// ...
///
/// Example (Lua): window-relative float
/// <pre>
/// vim.api.nvim_open_win(0, false,
/// {relative='win', row=3, col=3, width=12, height=3})
/// </pre>
///
/// @param buffer Buffer to display
/// @param enter Enter the window
/// @param config Map defining the window configuration. Keys:
/// - relative: Sets the window layout, relative to:
/// - "editor" The global editor grid.
/// - "win" Window given by the `win` field.
/// - "cursor" Cursor position in current window.
/// ...
/// @param[out] err Error details, if any
///
/// @return Window handle, or 0 on error
Lua docstrings ~
*dev-lua-doc*
Lua documentation lives in the source code, as docstrings on the function
definitions. The |lua-vim| :help is generated from the docstrings.
Docstring format:
- Lines in the main description start with `---`
- Special tokens start with `--@` followed by the token name:
`--@see`, `--@param`, `--@returns`
- Limited markdown is supported.
- List-items start with `-` (useful to nest or "indent")
- Use `<pre>` for code samples.
Example: the help for |vim.paste()| is generated from a docstring decorating
vim.paste in src/nvim/lua/vim.lua like this: >
--- Paste handler, invoked by |nvim_paste()| when a conforming UI
--- (such as the |TUI|) pastes text into the editor.
---
--- Example: To remove ANSI color codes when pasting:
--- <pre>
--- vim.paste = (function()
--- local overridden = vim.paste
--- ...
--- end)()
--- </pre>
---
--@see |paste|
---
--@param lines ...
--@param phase ...
--@returns false if client should cancel the paste.
LUA *dev-lua*
- Keep the core Lua modules |lua-stdlib| simple. Avoid elaborate OOP or
pseudo-OOP designs. Plugin authors just want functions to call, they don't
want to learn a big, fancy inheritance hierarchy. So we should avoid complex
objects: tables are usually better.
2017-04-17 17:52:38 -04:00
API *dev-api*
Use this template to name new API functions:
nvim_{thing}_{action}_{arbitrary-qualifiers}
If the function acts on an object then {thing} is the name of that object
(e.g. "buf" or "win"). If the function operates in a "global" context then
{thing} is usually omitted (but consider "namespacing" your global operations
with a {thing} that groups functions under a common concept).
Use existing common {action} names if possible:
add Append to, or insert into, a collection
2019-05-11 10:58:47 -04:00
get Get a thing (or group of things by query)
set Set a thing (or group of things)
del Delete a thing (or group of things)
list Get all things
Use consistent names for {thing} in all API functions. E.g. a buffer is called
"buf" everywhere, not "buffer" in some places and "buf" in others.
2019-05-11 10:58:47 -04:00
Example:
`nvim_get_current_line` acts on the global editor state; the common
{action} "get" is used but {thing} is omitted.
2019-05-11 10:58:47 -04:00
Example:
`nvim_buf_add_highlight` acts on a `Buffer` object (the first parameter)
and uses the common {action} "add".
2019-05-11 10:58:47 -04:00
Example:
`nvim_list_bufs` operates in a global context (first parameter is not
a Buffer). The common {action} "list" indicates that it lists all bufs
(plural) in the global context.
Use this template to name new API events:
nvim_{thing}_{event}_event
2019-05-11 10:58:47 -04:00
Example:
`nvim_buf_changedtick_event`
2017-08-19 08:13:14 -04:00
API-CLIENT *dev-api-client*
*api-client*
API clients wrap the Nvim |API| to provide idiomatic "SDKs" for their
respective platforms (see |jargon|). You can build a new API client for your
favorite platform or programming language.
List of API clients:
https://github.com/neovim/neovim/wiki/Related-projects#api-clients
*pynvim*
The Python client is the reference implementation for API clients.
https://github.com/neovim/pynvim
Standard Features ~
- API clients exist to hide msgpack-rpc details. The wrappers can be
automatically generated by reading the |api-metadata| from Nvim. |api-mapping|
- Clients should call |nvim_set_client_info()| after connecting, so users and
plugins can detect the client by handling the |ChanInfo| event. This avoids
the need for special variables or other client hints.
- Clients should handle |nvim_error_event| notifications, which will be sent
if an async request to nvim was rejected or caused an error.
2017-08-19 08:13:14 -04:00
Package Naming ~
2017-08-19 08:13:14 -04:00
API client packages should NOT be named something ambiguous like "neovim" or
"python-client". Use "nvim" as a prefix/suffix to some other identifier
following ecosystem conventions.
For example, Python packages tend to have "py" in the name, so "pynvim" is
a good name: it's idiomatic and unambiguous. If the package is named "neovim",
it confuses users, and complicates documentation and discussions.
Examples of API-client package names:
GOOD: nvim-racket
GOOD: pynvim
BAD: python-client
BAD: neovim
API client implementation guidelines ~
- Separate the transport layer from the rest of the library. |rpc-connecting|
- Use a MessagePack library that implements at least version 5 of the
MessagePack spec, which supports the BIN and EXT types used by Nvim.
- Use a single-threaded event loop library/pattern.
- Use a fiber/coroutine library for the language being used for implementing
a client. These greatly simplify concurrency and allow the library to
expose a blocking API on top of a non-blocking event loop without the
complexity that comes with preemptive multitasking.
- Don't assume anything about the order of responses to RPC requests.
- Clients should expect requests, which must be handled immediately because
Nvim is blocked while waiting for the client response.
- Clients should expect notifications, but these can be handled "ASAP" (rather
than immediately) because they won't block Nvim.
- For C/C++ projects, consider libmpack instead of the msgpack.org library.
https://github.com/libmpack/libmpack/
libmpack is small (no dependencies, can inline into your C/C++ project) and
efficient (no allocations). It also implements msgpack-RPC, the protocol
required by Nvim.
https://github.com/msgpack-rpc/msgpack-rpc
2017-08-19 08:13:14 -04:00
2017-04-17 17:52:38 -04:00
EXTERNAL UI *dev-ui*
External UIs should be aware of the |api-contract|. In particular, future
2017-08-19 08:13:14 -04:00
versions of Nvim may add new items to existing events. The API is strongly
2018-06-27 18:48:17 -04:00
backwards-compatible, but clients must not break if new (optional) fields are
added to existing events.
2017-04-17 17:52:38 -04:00
Standard Features ~
2017-08-19 08:13:14 -04:00
External UIs are expected to implement these common features:
- Call |nvim_set_client_info()| after connecting, so users and plugins can
detect the UI by handling the |ChanInfo| event. This avoids the need for
special variables and UI-specific config files (gvimrc, macvimrc, …).
2018-06-27 18:48:17 -04:00
- Cursor style (shape, color) should conform to the 'guicursor' properties
2017-08-19 08:13:14 -04:00
delivered with the mode_info_set UI event.
- Send the ALT/META ("Option" on macOS) key as a |<M-| chord.
2017-08-19 08:13:14 -04:00
- Send the "super" key (Windows key, Apple key) as a |<D-| chord.
2018-06-27 18:48:17 -04:00
- Avoid mappings that conflict with the Nvim keymap-space; GUIs have many new
chords (<C-,> <C-Enter> <C-S-x> <D-x>) and patterns ("shift shift") that do
not potentially conflict with Nvim defaults, plugins, etc.
- Consider the "option_set" |ui-global| event as a hint for other GUI
behaviors. UI-related options ('guifont', 'ambiwidth', …) are published in
this event.
2017-04-17 17:52:38 -04:00
vim:tw=78:ts=8:noet:ft=help:norl: