mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 11:15:14 -07:00
381 lines
15 KiB
Plaintext
381 lines
15 KiB
Plaintext
*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.
|
|
|
|
==============================================================================
|
|
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
|
|
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.
|
|
- 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... FAST AND SMALL *design-speed-size*
|
|
|
|
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
|
|
include the kitchen sink... but it's good for plumbing."
|
|
|
|
|
|
==============================================================================
|
|
Developer guidelines *dev-guidelines*
|
|
|
|
|
|
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, discard): calls
|
|
provider#{name}#Call with the method and arguments. If discard is true, any
|
|
value returned by the provider will be discarded and and empty value be
|
|
returned.
|
|
- 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*
|
|
|
|
- "Just say it". Avoid mushy, colloquial phrasing in all documentation
|
|
(docstrings, user manual, website materials, newsletters, …). Don't mince
|
|
words. Personality and flavor, used sparingly, are welcome--but in general,
|
|
optimize for the reader's time and energy: be "precise yet concise".
|
|
- Prefer the active voice: "Foo does X", not "X is done by Foo".
|
|
- Vim differences:
|
|
- Do not prefix help tags with "nvim-". Use |vim_diff.txt| to catalog
|
|
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|.
|
|
- Mention deprecated features in |deprecated.txt| and delete their old doc.
|
|
- 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.
|
|
- 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. Thus avoid specialized
|
|
objects; tables or values are usually better.
|
|
|
|
|
|
API *dev-api*
|
|
|
|
Use this template to name new RPC |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
|
|
del Delete a thing (or group of things)
|
|
exec Execute code
|
|
get Get a thing (or group of things by query)
|
|
list Get all things
|
|
set Set a thing (or group of 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.
|
|
|
|
Example:
|
|
`nvim_get_current_line` acts on the global editor state; the common
|
|
{action} "get" is used but {thing} is omitted.
|
|
|
|
Example:
|
|
`nvim_buf_add_highlight` acts on a `Buffer` object (the first parameter)
|
|
and uses the common {action} "add".
|
|
|
|
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
|
|
|
|
Example:
|
|
`nvim_buf_changedtick_event`
|
|
|
|
|
|
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.
|
|
|
|
Package Naming ~
|
|
|
|
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
|
|
|
|
|
|
EXTERNAL UI *dev-ui*
|
|
|
|
External UIs should be aware of the |api-contract|. In particular, future
|
|
versions of Nvim may add new items to existing events. The API is strongly
|
|
backwards-compatible, but clients must not break if new (optional) fields are
|
|
added to existing events.
|
|
|
|
Standard Features ~
|
|
|
|
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, …).
|
|
- Cursor style (shape, color) should conform to the 'guicursor' properties
|
|
delivered with the mode_info_set UI event.
|
|
- Send the ALT/META ("Option" on macOS) key as a |<M-| chord.
|
|
- Send the "super" key (Windows key, Apple key) as a |<D-| chord.
|
|
- 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. Various UI-related options ('guifont', 'ambiwidth', …) are
|
|
published in this event. See also "mouse_on", "mouse_off".
|
|
|
|
|
|
NAMING *dev-naming*
|
|
|
|
Naming is important. Consistent naming in the API and UI helps both users and
|
|
developers discover and intuitively understand related concepts ("families"),
|
|
and reduces cognitive burden. Discoverability encourages code re-use and
|
|
likewise avoids redundant, overlapping mechanisms, which reduces code
|
|
surface-area, and thereby minimizes bugs...
|
|
|
|
Naming conventions ~
|
|
|
|
Use the "on_" prefix to name event handlers and also the interface for
|
|
"registering" such handlers (on_key). The dual nature is acceptable to avoid
|
|
a confused collection of naming conventions for these related concepts.
|
|
|
|
|
|
vim:tw=78:ts=8:noet:ft=help:norl:
|