123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- *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 empty value will 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".
- - See https://developers.google.com/style/tone
- - 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`
- <
- Documentation format ~
- For Nvim-owned docs, use the following strict subset of "vimdoc" to ensure
- the help doc renders nicely in other formats (such as HTML:
- https://neovim.io/doc/user ).
- Strict "vimdoc" subset:
- - Use lists (like this!) prefixed with "-", "*", or "•", for adjacent lines
- that you don't want auto-wrapped. Lists are always rendered with "flow"
- (soft-wrapped) layout instead of preformatted (hard-wrapped) layout common
- in legacy :help docs.
- - Limitation: currently the parser https://github.com/neovim/tree-sitter-vimdoc
- does not understand numbered listitems, so use a bullet symbol (- or •)
- before numbered items, e.g. "- 1." instead of "1.".
- - Separate blocks (paragraphs) of content by a blank line(s).
- - Do not use indentation in random places—that prevents the page from using
- "flow" layout. If you need a preformatted section, put it in
- a |help-codeblock| starting with ">".
- 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/win_config.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 runtime/lua/vim/_editor.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 format 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
- - call Call a function
- - create Create a new (non-trivial) thing
- - del Delete a thing (or group of things)
- - eval Evaluate an expression
- - exec Execute code
- - fmt Format
- - get Get things (often by a query)
- - open Open
- - parse Parse something into a structured form
- - set Set a thing (or group of things)
- Do NOT use these deprecated verbs:
- - list Redundant with "get"
- Use consistent names for {thing} (nouns) in API functions: buffer is called
- "buf" everywhere, not "buffer" in some places and "buf" in others.
- - buf Buffer
- - chan |channel|
- - cmd Command
- - cmdline Command-line UI or input
- - fn Function
- - hl Highlight
- - pos Position
- - proc System process
- - tabpage Tabpage
- - win Window
- Do NOT use these deprecated nouns:
- - buffer
- - command
- - window
- Example:
- `nvim_get_keymap('v')` operates in a global context (first parameter is not
- a Buffer). The "get" {action} indicates that it gets anything matching the
- given filter parameter. There is no need for a "list" action because
- `nvim_get_keymap('')` (i.e., empty filter) returns all items.
- Example:
- `nvim_buf_del_mark` acts on a `Buffer` object (the first parameter)
- and uses the "del" {action}.
- Use this format 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:sw=4:et:ft=help:norl:
|