This commit is contained in:
Justin M. Keyes 2019-09-09 14:42:20 -07:00 committed by GitHub
commit 0809533b88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 507 additions and 444 deletions

View File

@ -3,8 +3,6 @@ Maintaining the Neovim project
Notes on maintaining the Neovim project.
See also: https://github.com/git/git/blob/master/Documentation/howto/maintain-git.txt
General guidelines
------------------
@ -14,7 +12,7 @@ General guidelines
* Use automation to solve problems
* Never break the API
Ticket Triage
Ticket triage
-------------
In practice we haven't found a meaningful way to forecast more precisely than
@ -38,14 +36,14 @@ just not something you care very much about, by construction. Post-release you
can review open issues, but chances are your next milestone is already getting
full :)
Release Policy
Release policy
--------------
Release "often", but not "early".
The (unreleased) `master` branch is the "early" channel; it should not be
released if it's not stable. High-risk changes may be merged to `master` if
the next feature-release is not imminent.
the next release is not imminent.
For maintenance releases, create a `release-x.y` branch. If the current release
has a major bug:
@ -55,5 +53,11 @@ has a major bug:
3. Cut a release from `release-x.y`.
- Run `./scripts/release.sh`
- Update (force-push) the remote `stable` tag.
- The [nightly job](https://github.com/neovim/bot-ci/blob/master/ci/nightly.sh)
will update the release assets based on the `stable` tag.
See also: https://github.com/neovim/neovim/issues/862
See also
--------
- https://github.com/neovim/neovim/issues/862
- https://github.com/git/git/blob/master/Documentation/howto/maintain-git.txt

View File

@ -89,10 +89,14 @@ Ex mode, reading stdin as Ex commands.
Ex mode, reading stdin as text.
.Ic :help Ex-mode
.It Fl es
Silent/batch mode, reading stdin as Ex commands.
Silent (non-interactive) Ex mode, reading stdin as Ex commands.
Useful for scripting because it does NOT start a UI, unlike
.Fl e .
.Ic :help silent-mode
.It Fl \&Es
Silent/batch mode, reading stdin as text.
Silent (non-interactive) Ex mode, reading stdin as text.
Useful for scripting because it does NOT start a UI, unlike
.Fl E .
.Ic :help silent-mode
.It Fl d
Diff mode.

View File

@ -13,6 +13,76 @@ Applications can also embed libnvim to work with the C API directly.
Type |gO| to see the table of contents.
==============================================================================
API Usage *api-rpc* *RPC* *rpc*
*msgpack-rpc*
RPC is the typical way to control Nvim programmatically. Nvim implements the
MessagePack-RPC protocol:
https://github.com/msgpack/msgpack/blob/0b8f5ac/spec.md
Many clients use the API: user interfaces (GUIs), remote plugins, scripts like
"nvr" (https://github.com/mhinz/neovim-remote). Even Nvim itself can control
other Nvim instances. API clients can:
- Call any API function
- Listen for events
- Receive remote calls from Nvim
The RPC API is like a more powerful version of Vim's "clientserver" feature.
CONNECTING *rpc-connecting*
See |channel-intro| for various ways to open a channel. Channel-opening
functions take an `rpc` key in the options dictionary. RPC channels can also
be opened by other processes connecting to TCP/IP sockets or named pipes
listened to by Nvim.
Nvim creates a default RPC socket at |startup|, given by |v:servername|. To
start with a TCP/IP socket instead, use |--listen| with a TCP-style address: >
nvim --listen 127.0.0.1:6666
More endpoints can be started with |serverstart()|.
Note that localhost TCP sockets are generally less secure than named pipes,
and can lead to vunerabilities like remote code execution.
Connecting to the socket is the easiest way a programmer can test the API,
which can be done through any msgpack-rpc client library or full-featured
|api-client|. Here's a Ruby script that prints "hello world!" in the current
Nvim instance:
>
#!/usr/bin/env ruby
# Requires msgpack-rpc: gem install msgpack-rpc
#
# To run this script, execute it from a running Nvim instance (notice the
# trailing '&' which is required since Nvim won't process events while
# running a blocking command):
#
# :!./hello.rb &
#
# Or from another shell by setting NVIM_LISTEN_ADDRESS:
# $ NVIM_LISTEN_ADDRESS=[address] ./hello.rb
require 'msgpack/rpc'
require 'msgpack/rpc/transport/unix'
nvim = MessagePack::RPC::Client.new(MessagePack::RPC::UNIXTransport.new, ENV['NVIM_LISTEN_ADDRESS'])
result = nvim.call(:nvim_command, 'echo "hello world!"')
<
A better way is to use the Python REPL with the `neovim` package, where API
functions can be called interactively:
>
>>> from pynvim import attach
>>> nvim = attach('socket', path='[address]')
>>> nvim.command('echo "hello world!"')
<
You can also embed Nvim via |jobstart()|, and communicate using |rpcrequest()|
and |rpcnotify()|:
>
let nvim = jobstart(['nvim', '--embed'], {'rpc': v:true})
echo rpcrequest(nvim, 'nvim_eval', '"Hello " . "world!"')
call jobstop(nvim)
==============================================================================
API Definitions *api-definitions*
@ -20,20 +90,37 @@ API Definitions *api-definitions*
The Nvim C API defines custom types for all function parameters. Some are just
typedefs around C99 standard types, others are Nvim-defined data structures.
Boolean -> bool
Integer (signed 64-bit integer) -> int64_t
Float (IEEE 754 double precision) -> double
String -> {char* data, size_t size} struct
Basic types ~
API Type C type
------------------------------------------------------------------------
Nil
Boolean bool
Integer (signed 64-bit integer) int64_t
Float (IEEE 754 double precision) double
String {char* data, size_t size} struct
Array
Dictionary
Dictionary (msgpack: map)
Object
The following handle types are defined as integer typedefs, but are
discriminated as separate types in an Object:
Note: empty Array is accepted as a valid argument for Dictionary parameter.
Special types (msgpack EXT) ~
These are integer typedefs discriminated as separate Object subtypes. They
can be treated as opaque integers, but are mutually incompatible: Buffer may
be passed as an integer but not as Window or Tabpage.
The EXT object data is the (integer) object handle. The EXT type codes given
in the |api-metadata| `types` key are stable: they will not change and are
thus forward-compatible.
EXT Type C type Data
------------------------------------------------------------------------
Buffer enum value kObjectTypeBuffer |bufnr()|
Window enum value kObjectTypeWindow |window-ID|
Tabpage enum value kObjectTypeTabpage internal handle
Buffer -> enum value kObjectTypeBuffer
Window -> enum value kObjectTypeWindow
Tabpage -> enum value kObjectTypeTabpage
*api-indexing*
Most of the API uses 0-based indices, and ranges are end-exclusive. For the
@ -46,25 +133,70 @@ lines, 0-based columns):
|nvim_win_get_cursor()|
|nvim_win_set_cursor()|
==============================================================================
API metadata *api-metadata*
*api-fast*
Most API functions are "deferred": they are queued on the main loop and
processed sequentially with normal input. So if the editor is waiting for
user input in a "modal" fashion (e.g. the |hit-enter-prompt|), the request
will block. Non-deferred ({fast}) functions such as |nvim_get_mode()| and
|nvim_input()| are served immediately (i.e. without waiting in the input
queue). Lua code can use |vim.in_fast_event()| to detect a {fast} context.
Nvim exposes API metadata as a Dictionary. Some items are described below:
==============================================================================
API metadata *api-metadata*
The Nvim C API is automatically exposed to RPC by the build system, which
parses headers in src/nvim/api/* and generates dispatch-functions mapping RPC
API method names to public C API functions, converting/validating arguments
and return values.
Nvim exposes its API metadata as a Dictionary with these items:
version Nvim version, API level/compatibility
version.api_level API version integer *api-level*
version.api_compatible API is backwards-compatible with this level
version.api_prerelease Declares the API as unstable/unreleased >
(version.api_prerelease && fn.since == version.api_level)
functions API function signatures
ui_events UI event signatures |ui|
functions API function signatures, containing |api-types| info
describing the return value and parameters.
ui_events |UI| event signatures
ui_options Supported |ui-option|s
{fn}.since API level where function {fn} was introduced
{fn}.deprecated_since API level where function {fn} was deprecated
types Custom handle types defined by Nvim
error_types Possible error types returned by API functions
External programs ("clients") can use the metadata to discover the |rpc-api|.
About the `functions` map:
- Container types may be decorated with type/size constraints, e.g.
ArrayOf(Buffer) or ArrayOf(Integer, 2).
- Functions considered to be methods that operate on instances of Nvim
special types (msgpack EXT) have the "method=true" flag. The receiver type
is that of the first argument. Method names are prefixed with `nvim_` plus
a type name, e.g. `nvim_buf_get_lines` is the `get_lines` method of
a Buffer instance. |dev-api|
- Global functions have the "method=false" flag and are prefixed with just
`nvim_`, e.g. `nvim_get_buffers`.
*api-mapping*
External programs (clients) can use the metadata to discover the API, using
any of these approaches:
1. Connect to a running Nvim instance and call |nvim_get_api_info()| via
msgpack-rpc. This is best for clients written in dynamic languages which
can define functions at runtime.
2. Start Nvim with the |--api-info| option. Useful for clients written in
statically-compiled languages.
3. Use the |api_info()| Vimscript function.
Example: To get a human-readable list of API functions: >
:new|put =map(filter(api_info().functions, '!has_key(v:val,''deprecated_since'')'), 'v:val.name')
<
Example: To get a formatted dump of the API using python (requires the
"pyyaml" and "msgpack-python" modules): >
nvim --api-info | python -c 'import msgpack, sys, yaml; print yaml.dump(msgpack.unpackb(sys.stdin.read()))'
<
==============================================================================
API contract *api-contract*
@ -198,13 +330,14 @@ paste a block of 6 lines, emits: >
User reloads the buffer with ":edit", emits: >
nvim_buf_detach_event[{buf}]
<
LUA ~
*api-buffer-updates-lua*
In-process lua plugins can also receive buffer updates, in the form of lua
callbacks. These callbacks are called frequently in various contexts, buffer
contents or window layout should not be changed inside these |textlock|.
|vim.schedule| can be used to defer these operations to the main loop, where
they are allowed.
In-process Lua plugins can receive buffer updates in the form of Lua
callbacks. These callbacks are called frequently in various contexts;
|textlock| prevents changing buffer contents and window layout (use
|vim.schedule| to defer such operations to the main loop instead).
|nvim_buf_attach| will take keyword args for the callbacks. "on_lines" will
receive parameters ("lines", {buf}, {changedtick}, {firstline}, {lastline},
@ -223,6 +356,9 @@ arguments {old_utf32_size} and {old_utf16_size}.
"on_changedtick" is invoked when |b:changedtick| was incremented but no text
was changed. The parameters recieved are ("changedtick", {buf}, {changedtick}).
*api-lua-detach*
In-process Lua callbacks can detach by returning `true`. This will detach all
callbacks attached with the same |nvim_buf_attach| call.
==============================================================================
@ -310,6 +446,7 @@ Here is an example for creating a float with scratch buffer: >
call nvim_win_set_option(win, 'winhl', 'Normal:MyHighlight')
>
To close the float, |nvim_win_close()| can be used.
==============================================================================
Global Functions *api-global*
@ -381,7 +518,7 @@ nvim_input({keys}) *nvim_input()*
|api-level| 6.
Attributes: ~
{async}
{fast}
Parameters: ~
{keys} to be typed
@ -406,7 +543,7 @@ nvim_input_mouse({button}, {action}, {modifier}, {grid}, {row}, {col})
|nvim_input()| has the same limitiation.
Attributes: ~
{async}
{fast}
Parameters: ~
{button} Mouse button: one of "left", "right",
@ -683,7 +820,7 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
Currently this is used to open floating and external windows.
Floats are windows that are drawn above the split layout, at
some anchor position in some other window. Floats can be draw
some anchor position in some other window. Floats can be drawn
internally or by external GUI with the |ui-multigrid|
extension. External windows are only supported with multigrid
GUIs, and are displayed as separate top-level windows.
@ -735,6 +872,14 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
Minimum of 1.
• `width` : window width (in character cells).
Minimum of 1.
• 'bufpos': position float relative text inside
window `win` (only when relative="win"). Takes
a tuple of zero-indexed [line, column]. Note:
`row` and `col` if present, still applies
relative this position. By default `row=1` and
`col=0` are used (with default NW anchor), to
make the float behave like a tooltip under the
buffer text.
• `row` : row position. Screen cell height are
used as unit. Can be floating point.
• `col` : column position. Screen cell width is
@ -748,6 +893,21 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
an external top-level window. Currently
accepts no other positioning configuration
together with this.
• `style` : Configure the apparance of the window.
Currently only takes one non-empty value:
• "minimal" Nvim will display the window with
many UI options disabled. This is useful
when displaing a temporary float where the
text should not be edited. Disables
'number', 'relativenumber', 'cursorline',
'cursorcolumn', 'foldcolumn', 'spell' and
'list' options. 'signcolumn' is changed to
`auto` . The end-of-buffer region is hidden
by setting `eob` flag of 'fillchars' to a
space char, and clearing the |EndOfBuffer|
region in 'winhighlight'.
• top-level window. Currently accepts no other
positioning configuration together with this.
Return: ~
Window handle, or 0 on error
@ -875,6 +1035,23 @@ nvim_get_color_map() *nvim_get_color_map()*
Return: ~
Map of color names and RGB values.
nvim_get_context({types}) *nvim_get_context()*
Gets a map of the current editor state.
Parameters: ~
{types} Context types ("regs", "jumps", "buflist",
"gvars", ...) to gather, or NIL for all (see
|context-types|).
Return: ~
map of global |context|.
nvim_load_context({dict}) *nvim_load_context()*
Sets the current editor state from the given |context| map.
Parameters: ~
{dict} |Context| map.
nvim_get_mode() *nvim_get_mode()*
Gets the current mode. |mode()| "blocking" is true if Nvim is
waiting for input.
@ -883,7 +1060,7 @@ nvim_get_mode() *nvim_get_mode()*
Dictionary { "mode": String, "blocking": Boolean }
Attributes: ~
{async}
{fast}
nvim_get_keymap({mode}) *nvim_get_keymap()*
Gets a list of global (non-buffer-local) |mapping|
@ -953,7 +1130,7 @@ nvim_get_api_info() *nvim_get_api_info()*
2-tuple [{channel-id}, {api-metadata}]
Attributes: ~
{async}
{fast}
*nvim_set_client_info()*
nvim_set_client_info({name}, {version}, {type}, {methods},
@ -1086,7 +1263,7 @@ nvim_parse_expression({expr}, {flags}, {highlight})
Parse a VimL expression.
Attributes: ~
{async}
{fast}
Parameters: ~
{expr} Expression to parse. Always treated as a
@ -1276,7 +1453,7 @@ nvim_select_popupmenu_item({item}, {insert}, {finish}, {opts})
Implies `insert` .
{opts} Optional parameters. Reserved for future use.
nvim__inspect_cell({row}, {col}) *nvim__inspect_cell()*
nvim__inspect_cell({grid}, {row}, {col}) *nvim__inspect_cell()*
TODO: Documentation
@ -1306,7 +1483,8 @@ nvim_buf_line_count({buffer}) *nvim_buf_line_count()*
Line count, or 0 for unloaded buffer. |api-buffer|
nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
Activates buffer-update events on the channel.
Activates buffer-update events on a channel, or as lua
callbacks.
Parameters: ~
{buffer} Buffer handle, or 0 for current buffer
@ -1315,18 +1493,29 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
first notification will be a
`nvim_buf_lines_event` . Otherwise, the
first notification will be a
`nvim_buf_changedtick_event`
{opts} Optional parameters. Reserved for future
use.
`nvim_buf_changedtick_event` . Not used for
lua callbacks.
{opts} Optional parameters.
• `on_lines` : lua callback received on
change.
• `on_changedtick` : lua callback received
on changedtick increment without text
change.
• `utf_sizes` : include UTF-32 and UTF-16
size of the replaced region. See
|api-buffer-updates-lua| for more
information
Return: ~
False when updates couldn't be enabled because the buffer
isn't loaded or `opts` contained an invalid key; otherwise
True.
True. TODO: LUA_API_NO_EVAL
nvim_buf_detach({buffer}) *nvim_buf_detach()*
Deactivates buffer-update events on the channel.
For Lua callbacks see |api-lua-detach|.
Parameters: ~
{buffer} Buffer handle, or 0 for current buffer
@ -1639,6 +1828,9 @@ nvim_buf_set_virtual_text({buffer}, {ns_id}, {line}, {chunks}, {opts})
Return: ~
The ns_id that was used
nvim__buf_stats({buffer}) *nvim__buf_stats()*
TODO: Documentation
==============================================================================
Window Functions *api-window*
@ -1647,7 +1839,7 @@ nvim_win_get_buf({window}) *nvim_win_get_buf()*
Gets the current buffer in a window
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
Return: ~
Buffer handle
@ -1656,7 +1848,7 @@ nvim_win_set_buf({window}, {buffer}) *nvim_win_set_buf()*
Sets the current buffer in a window, without side-effects
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{buffer} Buffer handle
nvim_win_get_cursor({window}) *nvim_win_get_cursor()*
@ -1664,7 +1856,7 @@ nvim_win_get_cursor({window}) *nvim_win_get_cursor()*
|api-indexing|
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
Return: ~
(row, col) tuple
@ -1674,14 +1866,14 @@ nvim_win_set_cursor({window}, {pos}) *nvim_win_set_cursor()*
|api-indexing|
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{pos} (row, col) tuple representing the new position
nvim_win_get_height({window}) *nvim_win_get_height()*
Gets the window height
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
Return: ~
Height as a count of rows
@ -1691,14 +1883,14 @@ nvim_win_set_height({window}, {height}) *nvim_win_set_height()*
is split horizontally.
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{height} Height as a count of rows
nvim_win_get_width({window}) *nvim_win_get_width()*
Gets the window width
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
Return: ~
Width as a count of columns
@ -1708,14 +1900,14 @@ nvim_win_set_width({window}, {width}) *nvim_win_set_width()*
split vertically.
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{width} Width as a count of columns
nvim_win_get_var({window}, {name}) *nvim_win_get_var()*
Gets a window-scoped (w:) variable
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{name} Variable name
Return: ~
@ -1725,7 +1917,7 @@ nvim_win_set_var({window}, {name}, {value}) *nvim_win_set_var()*
Sets a window-scoped (w:) variable
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{name} Variable name
{value} Variable value
@ -1733,14 +1925,14 @@ nvim_win_del_var({window}, {name}) *nvim_win_del_var()*
Removes a window-scoped (w:) variable
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{name} Variable name
nvim_win_get_option({window}, {name}) *nvim_win_get_option()*
Gets a window option value
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{name} Option name
Return: ~
@ -1751,7 +1943,7 @@ nvim_win_set_option({window}, {name}, {value}) *nvim_win_set_option()*
option(only works if there's a global fallback)
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{name} Option name
{value} Option value
@ -1760,7 +1952,7 @@ nvim_win_get_position({window}) *nvim_win_get_position()*
zero.
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
Return: ~
(row, col) tuple with the window position
@ -1769,7 +1961,7 @@ nvim_win_get_tabpage({window}) *nvim_win_get_tabpage()*
Gets the window tabpage
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
Return: ~
Tabpage that contains the window
@ -1778,7 +1970,7 @@ nvim_win_get_number({window}) *nvim_win_get_number()*
Gets the window number
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
Return: ~
Window number
@ -1787,7 +1979,7 @@ nvim_win_is_valid({window}) *nvim_win_is_valid()*
Checks if a window is valid
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
Return: ~
true if the window is valid, false otherwise
@ -1806,7 +1998,7 @@ nvim_win_set_config({window}, {config}) *nvim_win_set_config()*
subset of these is an error.
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{config} Dictionary of window configuration
nvim_win_get_config({window}) *nvim_win_get_config()*
@ -1818,19 +2010,16 @@ nvim_win_get_config({window}) *nvim_win_get_config()*
`relative` will be an empty string for normal windows.
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
Return: ~
Window configuration
nvim_win_close({window}, {force}) *nvim_win_close()*
Close a window.
This is equivalent to |:close| with count except that it takes
a window id.
Closes the window (like |:close| with a |window-ID|).
Parameters: ~
{window} Window handle
{window} Window handle, or 0 for current window
{force} Behave like `:close!` The last window of a
buffer with unwritten changes can be closed. The
buffer will become hidden, even if 'hidden' is
@ -1844,7 +2033,7 @@ nvim_tabpage_list_wins({tabpage}) *nvim_tabpage_list_wins()*
Gets the windows in a tabpage
Parameters: ~
{tabpage} Tabpage
{tabpage} Tabpage handle, or 0 for current tabpage
Return: ~
List of windows in `tabpage`
@ -1853,7 +2042,7 @@ nvim_tabpage_get_var({tabpage}, {name}) *nvim_tabpage_get_var()*
Gets a tab-scoped (t:) variable
Parameters: ~
{tabpage} Tabpage handle
{tabpage} Tabpage handle, or 0 for current tabpage
{name} Variable name
Return: ~
@ -1863,7 +2052,7 @@ nvim_tabpage_set_var({tabpage}, {name}, {value}) *nvim_tabpage_set_var()*
Sets a tab-scoped (t:) variable
Parameters: ~
{tabpage} Tabpage handle
{tabpage} Tabpage handle, or 0 for current tabpage
{name} Variable name
{value} Variable value
@ -1871,14 +2060,14 @@ nvim_tabpage_del_var({tabpage}, {name}) *nvim_tabpage_del_var()*
Removes a tab-scoped (t:) variable
Parameters: ~
{tabpage} Tabpage handle
{tabpage} Tabpage handle, or 0 for current tabpage
{name} Variable name
nvim_tabpage_get_win({tabpage}) *nvim_tabpage_get_win()*
Gets the current window in a tabpage
Parameters: ~
{tabpage} Tabpage handle
{tabpage} Tabpage handle, or 0 for current tabpage
Return: ~
Window handle
@ -1887,7 +2076,7 @@ nvim_tabpage_get_number({tabpage}) *nvim_tabpage_get_number()*
Gets the tabpage number
Parameters: ~
{tabpage} Tabpage handle
{tabpage} Tabpage handle, or 0 for current tabpage
Return: ~
Tabpage number
@ -1896,7 +2085,7 @@ nvim_tabpage_is_valid({tabpage}) *nvim_tabpage_is_valid()*
Checks if a tabpage is valid
Parameters: ~
{tabpage} Tabpage handle
{tabpage} Tabpage handle, or 0 for current tabpage
Return: ~
true if the tabpage is valid, false otherwise

View File

@ -30,7 +30,7 @@ There are several ways to open a channel:
Channels support multiple modes or protocols. In the most basic
mode of operation, raw bytes are read and written to the channel.
The |rpc| protocol, based on the msgpack-rpc standard, enables nvim and the
The |RPC| protocol, based on the msgpack-rpc standard, enables nvim and the
process at the other end to send remote calls and events to each other.
The builtin |terminal-emulator| is also implemented on top of PTY channels.

View File

@ -185,11 +185,25 @@ Example:
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.
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.
@ -209,15 +223,29 @@ Examples of API-client package names:
BAD: python-client
BAD: neovim
Implementation ~
API client implementation guidelines ~
For C/C++ projects, consider libmpack instead of the msgpack.org library.
- 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.
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

View File

@ -2062,6 +2062,13 @@ count({list}, {expr} [, {ic} [, {start}]])
Number count how many {expr} are in {list}
cscope_connection([{num}, {dbpath} [, {prepend}]])
Number checks existence of cscope connection
ctxget([{index}]) Dict return the |context| dict at {index}
ctxpop() none pop and restore |context| from the
|context-stack|
ctxpush([{types}]) none push the current |context| to the
|context-stack|
ctxset({context}[, {index}]) none set |context| at {index}
ctxsize() Number return |context-stack| size
cursor({lnum}, {col} [, {off}])
Number move cursor to {lnum}, {col}, {off}
cursor({list}) Number move cursor to position in {list}
@ -3232,6 +3239,32 @@ cscope_connection([{num} , {dbpath} [, {prepend}]])
cscope_connection(4, "out", "local") 0
cscope_connection(4, "cscope.out", "/usr/local") 1
<
ctxget([{index}]) *ctxget()*
Returns a |Dictionary| representing the |context| at {index}
from the top of the |context-stack| (see |context-dict|).
If {index} is not given, it is assumed to be 0 (i.e.: top).
ctxpop() *ctxpop()*
Pops and restores the |context| at the top of the
|context-stack|.
ctxpush([{types}]) *ctxpush()*
Pushes the current editor state (|context|) on the
|context-stack|.
If {types} is given and is a |List| of |String|s, it specifies
which |context-types| to include in the pushed context.
Otherwise, all context types are included.
ctxset({context}[, {index}]) *ctxset()*
Sets the |context| at {index} from the top of the
|context-stack| to that represented by {context}.
{context} is a Dictionary with context data (|context-dict|).
If {index} is not given, it is assumed to be 0 (i.e.: top).
ctxsize() *ctxsize()*
Returns the size of the |context-stack|.
cursor({lnum}, {col} [, {off}]) *cursor()*
cursor({list})
Positions the cursor at the column (byte count) {col} in the
@ -5416,24 +5449,22 @@ jobstop({id}) *jobstop()*
(if any) will be invoked.
See |job-control|.
jobwait({ids}[, {timeout}]) *jobwait()*
Wait for a set of jobs and their |on_exit| handlers to
complete.
jobwait({jobs}[, {timeout}]) *jobwait()*
Waits for jobs and their |on_exit| handlers to complete.
{ids} is a list of |job-id|s to wait for.
{jobs} is a List of |job-id|s to wait for.
{timeout} is the maximum waiting time in milliseconds, -1
means forever.
Timeout of 0 can be used to check the status of a job: >
let running = jobwait([{job-id}], 0)[0] == -1
<
During jobwait() callbacks for jobs not in the {ids} list may
During jobwait() callbacks for jobs not in the {jobs} list may
be invoked. The screen will not redraw unless |:redraw| is
invoked by a callback.
Returns a list of len({ids}) integers, where each integer is
the wait-result of the corresponding job. Each wait-result is
one of the following:
Returns a list of len({jobs}) integers, where each integer is
the status of the corresponding job:
Exit-code, if the job exited
-1 if the timeout was exceeded
-2 if the job was interrupted (by |CTRL-C|)

View File

@ -137,7 +137,6 @@ Special issues ~
Programming language support ~
|indent.txt| automatic indenting for C and other languages
|syntax.txt| syntax highlighting
|textprop.txt| Attaching properties to text for highlighting or other
|filetype.txt| settings done specifically for a type of file
|quickfix.txt| commands for a quick edit-compile-fix cycle
|ft_ada.txt| Ada (the programming language) support

View File

@ -373,37 +373,31 @@ Example: to use the "nvim_get_current_line()" API function, call
------------------------------------------------------------------------------
VIM.LOOP *lua-loop*
`vim.loop` exposes all features of the Nvim event-loop. This is a lower-level
`vim.loop` exposes all features of the Nvim event-loop. This is a low-level
API that provides functionality for networking, filesystem, and process
management. Try this command to see available functions: >
:lua print(vim.inspect(vim.loop))
See http://docs.libuv.org for complete documentation.
See https://github.com/luvit/luv/tree/master/examples for examples.
Reference: http://docs.libuv.org
Examples: https://github.com/luvit/luv/tree/master/examples
*E5560* *lua-loop-callbacks*
Note: it is not allowed to directly invoke most of the Nvim API from `vim.loop`
callbacks. This will result in an error: >
It is an error to directly invoke `vim.api` functions (except |api-fast|) in
`vim.loop` callbacks. For example, this is an error: >
local timer = vim.loop.new_timer()
timer:start(1000, 0, function()
vim.api.nvim_command('echomsg "test"')
end)
The `vim.schedule_wrap` helper can be used to defer the callback until it
is safe to execute API methods. >
To avoid the error use |vim.schedule_wrap()| to defer the callback: >
local timer = vim.loop.new_timer()
timer:start(1000, 0, vim.schedule_wrap(function()
vim.api.nvim_command('echomsg "test"')
end))
A subset of the API is available in direct luv callbacks ("fast" callbacks),
most notably |nvim_get_mode()| and |nvim_input()|. It is possible to
check whether code is running in this context using |vim.in_fast_event()|.
Example: repeating timer
1. Save this code to a file.
2. Execute it with ":luafile %". >
@ -454,6 +448,13 @@ Example: TCP echo-server *tcp-server*
------------------------------------------------------------------------------
VIM *lua-util*
vim.in_fast_event() *vim.in_fast_event()*
Returns true if the code is executing as part of a "fast" event
handler, where most of the API is disabled. These are low-level events
(e.g. |lua-loop-callbacks|) which can be invoked whenever Nvim polls
for input. When this is `false` most API functions are callable (but
may be subject to other restrictions such as |textlock|).
vim.stricmp({a}, {b}) *vim.stricmp()*
Compares strings case-insensitively. Returns 0, 1 or -1 if strings
are equal, {a} is greater than {b} or {a} is lesser than {b},
@ -481,14 +482,6 @@ vim.schedule({callback}) *vim.schedule()*
Schedules {callback} to be invoked soon by the main event-loop. Useful
to avoid |textlock| or other temporary restrictions.
vim.in_fast_event() *vim.in_fast_event()*
Returns true if the code is executing as part of a "fast" event
handler, where most of the API is disabled. These are low-level event
such as luv callbacks |lua-loop-callbacks|, which can be invoked at
any time nvim polls for input. When this returns `false` most API
functions are callable, but can be subjected to other restrictions,
such as |textlock|.
vim.type_idx *vim.type_idx*
Type index for use in |lua-special-tbl|. Specifying one of the
values from |vim.types| allows typing the empty table (it is
@ -552,6 +545,14 @@ paste({lines}, {phase}) *vim.paste()*
See also: ~
|paste|
schedule_wrap({cb}) *vim.schedule_wrap()*
Defers callback `cb` until the Nvim API is safe to call.
See also: ~
|lua-loop-callbacks|
|vim.schedule()|
|vim.in_fast_event()|
@ -651,4 +652,16 @@ trim({s}) *vim.trim()*
See also: ~
https://www.lua.org/pil/20.2.html
pesc({s}) *vim.pesc()*
Escapes magic chars in a Lua pattern string.
Parameters: ~
{s} String to escape
Return: ~
%-escaped pattern string
See also: ~
https://github.com/rxi/lume
vim:tw=78:ts=8:ft=help:norl:

View File

@ -43,9 +43,8 @@ There are many books on Vi and Vim. We recommend these books:
"Modern Vim" by Drew Neil
https://vimcasts.org/publications/
"Practical Vim" is a popular because of its focus on quickly learning common
editing tasks with Vim. "Modern Vim" explores new features introduced by Nvim
and Vim 8.
"Practical Vim" is acclaimed for its focus on quickly learning common editing
tasks with Vim. "Modern Vim" explores new features in Nvim and Vim 8.
"Vim - Vi Improved" by Steve Oualline

View File

@ -4,7 +4,7 @@
NVIM REFERENCE MANUAL by Thiago de Arruda
Nvim job control *job-control*
Nvim job control *job* *job-control*
Job control is a way to perform multitasking in Nvim, so scripts can spawn and
control multiple processes without blocking the current Nvim instance.

View File

@ -3,242 +3,5 @@
NVIM REFERENCE MANUAL by Thiago de Arruda
RPC API for Nvim *RPC* *rpc* *msgpack-rpc*
Type |gO| to see the table of contents.
==============================================================================
1. Introduction *rpc-intro*
The primary way to control Nvim programmatically is the RPC API, which speaks
MessagePack-RPC ("msgpack-rpc"), a messaging protocol that uses the
MessagePack serialization format:
https://github.com/msgpack/msgpack/blob/0b8f5ac/spec.md
All kinds of Nvim "clients" use the RPC API: user interfaces (GUIs), remote
plugins, scripts like "nvr" (https://github.com/mhinz/neovim-remote), and even
`nvim` itself can control other `nvim` instances. By connecting to the RPC API
programs can:
- Call any API function
- Listen for events
- Receive remote calls from Nvim
The RPC API is like a more powerful version of Vim's `clientserver` feature.
==============================================================================
2. API mapping *rpc-api*
The Nvim C |API| is automatically exposed to the RPC API by the build system,
which parses headers at src/nvim/api/*. A dispatch function is generated which
matches RPC API method names with public API functions, converting/validating
arguments and return values back to msgpack.
Client libraries (|api-client|s) normally provide wrappers that hide
msgpack-rpc details from application developers. The wrappers can be
automatically generated by reading bundled API metadata from a compiled Nvim
instance.
There are three ways to obtain API metadata:
1. Connect to a running Nvim instance and call `nvim_get_api_info` via
msgpack-rpc. This is best for clients written in dynamic languages which
can define functions at runtime.
2. Start Nvim with the |--api-info| option. Useful for clients written in
statically-compiled languages.
3. Use the |api_info()| vimscript function.
To get a human-readable list of API functions: >
:new|put =map(filter(api_info().functions, '!has_key(v:val,''deprecated_since'')'), 'v:val.name')
<
To get a formatted dump of the API using python (requires the `pyyaml` and
`msgpack-python` packages): >
nvim --api-info | python -c 'import msgpack, sys, yaml; print yaml.dump(msgpack.unpackb(sys.stdin.read()))'
<
==============================================================================
3. Connecting *rpc-connecting*
See |channel-intro|, for various ways to open a channel. Most of the channel
opening functions take an `rpc` key in the options dictionary, to enable RPC.
Additionally, RPC channels can be opened by other processes connecting to
TCP/IP sockets or named pipes listened to by nvim.
Nvim creates a default RPC socket at |startup|, given by |v:servername|. To
start with a TCP/IP socket instead, use |--listen| with a TCP-style address: >
nvim --listen 127.0.0.1:6666
Additional sockets and named pipes can be started with |serverstart()|.
Note that localhost TCP sockets are generally less secure than named pipes,
and can lead to vunerabilities like remote code execution.
Connecting to the socket is the easiest way a programmer can test the API,
which can be done through any msgpack-rpc client library or full-featured
|api-client|. Here's a Ruby script that prints 'hello world!' in the current
Nvim instance:
>
#!/usr/bin/env ruby
# Requires msgpack-rpc: gem install msgpack-rpc
#
# To run this script, execute it from a running Nvim instance (notice the
# trailing '&' which is required since Nvim won't process events while
# running a blocking command):
#
# :!./hello.rb &
#
# Or from another shell by setting NVIM_LISTEN_ADDRESS:
# $ NVIM_LISTEN_ADDRESS=[address] ./hello.rb
require 'msgpack/rpc'
require 'msgpack/rpc/transport/unix'
nvim = MessagePack::RPC::Client.new(MessagePack::RPC::UNIXTransport.new, ENV['NVIM_LISTEN_ADDRESS'])
result = nvim.call(:nvim_command, 'echo "hello world!"')
<
A better way is to use the Python REPL with the `neovim` package, where API
functions can be called interactively:
>
>>> from neovim import attach
>>> nvim = attach('socket', path='[address]')
>>> nvim.command('echo "hello world!"')
<
You can also embed an Nvim instance via |jobstart()|, and communicate using
|rpcrequest()| and |rpcnotify()|:
>
let nvim = jobstart(['nvim', '--embed'], {'rpc': v:true})
echo rpcrequest(nvim, 'nvim_eval', '"Hello " . "world!"')
call jobstop(nvim)
<
==============================================================================
4. Implementing API clients *rpc-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.
API clients are listed here:
https://github.com/neovim/neovim/wiki/Related-projects#api-clients
*pynvim*
The Python client is the reference implementation for API clients. It is
always up-to-date with the Nvim API, so its source code and test suite are
authoritative references.
https://github.com/neovim/pynvim
API client implementation guidelines ~
- Separate the transport layer from the rest of the library. See
|rpc-connecting| for details on how clients can connect to Nvim.
- Use a MessagePack library that implements at least version 5 of the
MessagePack spec, which supports the `bin` and `ext` types used by Nvim.
- Read API metadata in order to create client-side wrappers for all
msgpack-rpc methods.
- 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 that responses to msgpack-rpc
requests will arrive.
- Clients should expect msgpack-rpc requests, which need to be handled
immediately because Nvim is blocked while waiting for the client response.
- Clients should expect to receive msgpack-rpc notifications, but these
don't need to be handled immediately because they won't block Nvim
(although they should probably be handled immediately anyway).
Note: Most of the complexity could be handled by a msgpack-rpc library that
supports server to client requests and notifications, but it's not clear if
this is part of the msgpack-rpc spec. At least the Ruby msgpack-rpc library
does not seem to support it:
https://github.com/msgpack-rpc/msgpack-rpc-ruby/blob/master/lib/msgpack/rpc/transport/tcp.rb#L150-L158
API metadata object ~
API clients exist to hide msgpack-rpc details. The API metadata object
contains information that makes this task easier (see also |rpc-types|):
- The "version" key contains the Nvim version, API level, and API
backwards-compatibility level.
- The "functions" key contains a list of metadata objects for individual
functions.
- Each function metadata object has |rpc-types| information about the return
value and parameters. These can be used for generating strongly-typed APIs
in static languages.
- Container types may be decorated with type/size constraints, e.g.
ArrayOf(Buffer) or ArrayOf(Integer, 2). This can be useful to generate
even more strongly-typed APIs.
- Functions that are considered to be methods that operate on instances of
Nvim special types (msgpack EXT) will have the `"method"` attribute set to
`true`. The receiver type is the type of the first argument. The method
names are prefixed with `nvim_` plus a shortened type name, e.g.
`nvim_buf_get_lines` represents the `get_lines` method of a Buffer instance.
- Global functions have `"method"` set to `false` and are prefixed with just
`nvim_`, e.g. `nvim_get_buffers`.
So for an object-oriented language, an API client contains the classes
representing Nvim special types, and the methods of each class could be
defined by stripping the prefix for the type as defined in the `types` metadata
(this will always be the first two "_"-separated parts of the function name).
There could also be a singleton Vim class with methods where the `nvim_`
prefix is stripped off.
==============================================================================
5. Types *rpc-types*
The Nvim C API uses custom types for all functions. |api-types|
At the RPC layer, types form two groups:
- Basic types that map natively to msgpack (and have a default
representation in most msgpack-supported programming languages)
- Special Nvim types that map to msgpack EXT with custom type codes.
Basic types ~
Nil -> msgpack nil
Boolean -> msgpack boolean
Integer (signed 64-bit integer) -> msgpack integer
Float (IEEE 754 double precision) -> msgpack float
String -> msgpack string
Array -> msgpack array
Dictionary -> msgpack map
Note: in function calls, empty Array is accepted for Dictionary parameter.
Special types (msgpack EXT) ~
Buffer -> enum value kObjectTypeBuffer
Window -> enum value kObjectTypeWindow
Tabpage -> enum value kObjectTypeTabpage
API functions expecting one of the special EXT types may be passed an integer
instead, but not another EXT type. E.g. Buffer may be passed as an integer but
not as a Window or Tabpage. The EXT object data is the object id encoded as
a msgpack integer: For buffers this is the |bufnr()| and for windows the
|window-ID|. For tabpages the id is an internal handle, not the tabpage
number.
To determine the type codes of the special EXT types, inspect the `types` key
of the |api-metadata| at runtime. Example JSON representation: >
"types": {
"Buffer": {
"id": 0,
"prefix": "nvim_buf_"
},
"Window": {
"id": 1,
"prefix": "nvim_win_"
},
"Tabpage": {
"id": 2,
"prefix": "nvim_tabpage_"
}
}
Even for statically compiled clients it is good practice to avoid hardcoding
the type codes, because a client may be built against one Nvim version but
connect to another with different type codes.
vim:tw=78:ts=8:ft=help:norl:
This document was merged into |api.txt| and |develop.txt|.

View File

@ -11,7 +11,7 @@ Chapter 26 of the user manual introduces repeating |usr_26.txt|.
Type |gO| to see the table of contents.
==============================================================================
1. Single repeats *single-repeat*
Single repeats *single-repeat*
*.*
. Repeat last change, with count replaced with [count].
@ -35,7 +35,7 @@ of area is used, see |visual-repeat|.
==============================================================================
2. Multiple repeats *multi-repeat*
Multiple repeats *multi-repeat*
*:g* *:global* *E148*
:[range]g[lobal]/{pattern}/[cmd]
@ -103,7 +103,7 @@ repeated for each matching line. While doing this you cannot use ":global".
To abort this type CTRL-C twice.
==============================================================================
3. Complex repeats *complex-repeat*
Complex repeats *complex-repeat*
*q* *recording*
q{0-9a-zA-Z"} Record typed characters into register {0-9a-zA-Z"}
@ -157,7 +157,7 @@ q Stops recording.
line [addr] (default is current line).
==============================================================================
4. Using Vim scripts *using-scripts*
Using Vim scripts *using-scripts*
For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
@ -470,7 +470,7 @@ Rationale:
backslash is to make it very unlikely this is a normal comment line.
==============================================================================
5. Using Vim packages *packages*
Using Vim packages *packages*
A Vim package is a directory that contains one or more plugins. The
advantages over normal plugins:
@ -586,7 +586,7 @@ The "after" directory is most likely not useful in a package. It's not
disallowed though.
==============================================================================
6. Creating Vim packages *package-create*
Creating Vim packages *package-create*
This assumes you write one or more plugins that you distribute as a package.
@ -652,7 +652,7 @@ This works, because loading packages will first add all found directories to
'runtimepath' before sourcing the plugins.
==============================================================================
7. Debugging scripts *debug-scripts*
Debugging scripts *debug-scripts*
Besides the obvious messages that you can add to your scripts to find out what
they are doing, Vim offers a debug mode. This allows you to step through a
@ -876,7 +876,7 @@ OBSCURE
user, don't use typeahead for debug commands.
==============================================================================
8. Profiling *profile* *profiling*
Profiling *profile* *profiling*
Profiling means that Vim measures the time that is spent on executing
functions and/or scripts. The |+profile| feature is required for this.
@ -993,5 +993,32 @@ mind there are various things that may clobber the results:
- The "self" time is wrong when a function is used recursively.
==============================================================================
Context *Context* *context*
The editor state is represented by the Context concept. This includes things
like the current |jumplist|, values of |registers|, and more, described below.
*context-types*
The following Context items are supported:
"jumps" |jumplist|
"regs" |registers|
"buflist" |buffer-list|
"gvars" |global-variable|s
"sfuncs" |script-local| functions
"funcs" global and |script-local| functions
*context-dict*
Context objects are dictionaries with the following key-value pairs:
- "jumps", "regs", "buflist", "gvars":
|readfile()|-style |List| representation of corresponding msgpack
objects (see |msgpackdump()| and |msgpackparse()|).
- "funcs" (includes |script-local| functions as well):
|List| of |:function| definitions.
*context-stack*
An initially-empty internal Context stack is maintained by the ctx-family
functions (see |ctx-functions|).
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -199,9 +199,8 @@ argument.
-E reads stdin as text (into buffer 1).
-es *-es* *-Es* *-s-ex* *silent-mode*
-Es Silent or batch mode. Special case of |-s| (which takes an
argument while "-es" doesn't). Disables most prompts,
messages, warnings and errors.
-Es Silent mode (no UI), for scripting. Unrelated to |-s|.
Disables most prompts, messages, warnings and errors.
-es reads/executes stdin as Ex commands. >
printf "put ='foo'\n%%print\n" | nvim -es
@ -351,7 +350,7 @@ argument.
*--embed*
--embed Use stdin/stdout as a msgpack-RPC channel, so applications can
embed and control Nvim via the |rpc-api|.
embed and control Nvim via the RPC |API|.
Waits for the client ("embedder") to call |nvim_ui_attach()|
before sourcing startup files and reading buffers, so that UIs

View File

@ -5025,11 +5025,6 @@ StatusLine status line of current window
StatusLineNC status lines of not-current windows
Note: if this is equal to "StatusLine" Vim will use "^^^" in
the status line of the current window.
*hl-StatusLineTerm*
StatusLineTerm status line of current window, if it is a |terminal| window.
*hl-StatusLineTermNC*
StatusLineTermNC status lines of not-current windows that is a |terminal|
window.
*hl-TabLine*
TabLine tab pages line, not active tab page label
*hl-TabLineFill*

View File

@ -4,12 +4,12 @@
NVIM REFERENCE MANUAL
Nvim UI protocol *ui*
Nvim UI protocol *UI* *ui*
Type |gO| to see the table of contents.
==============================================================================
UI Events *ui-events*
UI Events *ui-events*
UIs can be implemented as external client processes communicating with Nvim
over the RPC API. The default UI model is a terminal-like grid with a single,

View File

@ -972,6 +972,13 @@ Prompt Buffer: *promptbuffer-functions*
prompt_setinterrupt() set interrupt callback for a buffer
prompt_setprompt() set the prompt text for a buffer
Context Stack: *ctx-functions*
ctxget() return context at given index from top
ctxpop() pop and restore top context
ctxpush() push given context
ctxset() set context at given index from top
ctxsize() return context stack size
Various: *various-functions*
mode() get current editing mode
visualmode() last visual mode used

View File

@ -169,6 +169,7 @@ Highlight groups:
|expr-highlight| highlight groups (prefixed with "Nvim")
|hl-NormalFloat| highlights floating window
|hl-NormalNC| highlights non-current windows
|hl-MsgArea| highlights messages/cmdline area
|hl-MsgSeparator| highlights separator for scrolled messages
|hl-QuickFixLine|
|hl-Substitute|
@ -436,6 +437,17 @@ Compile-time features:
Emacs tags support
X11 integration (see |x11-selection|)
Highlight groups:
*hl-StatusLineTerm* *hl-StatusLineTermNC* are unnecessary because Nvim
supports 'winhighlight' window-local highlights.
For example, to mimic Vim's StatusLineTerm: >
hi StatusLineTerm ctermfg=black ctermbg=green
hi StatusLineTermNC ctermfg=green
autocmd TermOpen,WinEnter * if &buftype=='terminal'
\|setlocal winhighlight=StatusLine:StatusLineTerm,StatusLineNC:StatusLineTermNC
\|else|setlocal winhighlight=|endif
<
Options:
'antialias'
'bioskey' (MS-DOS)

View File

@ -26,6 +26,7 @@
</screenshots>
<releases>
<release date="2019-07-03" version="0.3.8"/>
<release date="2019-04-29" version="0.3.5"/>
<release date="2019-01-13" version="0.3.4"/>
<release date="2019-01-05" version="0.3.3"/>
@ -33,7 +34,7 @@
<release date="2018-07-19" version="0.3.1"/>
<release date="2018-07-11" version="0.3.0"/>
</releases>
<content_rating type="oars-1.1"/>
<launchable type="desktop-id">nvim.desktop</launchable>
<url type="homepage">https://neovim.io/</url>

View File

@ -113,7 +113,7 @@ param_exclude = (
# Annotations are displayed as line items after API function descriptions.
annotation_map = {
'FUNC_API_ASYNC': '{async}',
'FUNC_API_FAST': '{fast}',
}
@ -485,7 +485,7 @@ def parse_source_xml(filename, mode):
# XXX: (doxygen 1.8.11) 'argsstring' only includes attributes of
# non-void functions. Special-case void functions here.
if name == 'nvim_get_mode' and len(annotations) == 0:
annotations += 'FUNC_API_ASYNC'
annotations += 'FUNC_API_FAST'
annotations = filter(None, map(lambda x: annotation_map.get(x),
annotations.split()))

View File

@ -62,6 +62,8 @@ Configure the sanitizer(s) via these environment variables:
# Change to detect_leaks=1 to detect memory leaks (slower).
export ASAN_OPTIONS="detect_leaks=0:log_path=$HOME/logs/asan"
# Show backtraces in the logs.
export UBSAN_OPTIONS=print_stacktrace=1
export MSAN_OPTIONS="log_path=${HOME}/logs/tsan"
export TSAN_OPTIONS="log_path=${HOME}/logs/tsan"

View File

@ -110,10 +110,10 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
/// `nvim_buf_lines_event`. Otherwise, the first notification will be
/// a `nvim_buf_changedtick_event`. Not used for lua callbacks.
/// @param opts Optional parameters.
/// `on_lines`: lua callback received on change.
/// `on_changedtick`: lua callback received on changedtick
/// - `on_lines`: lua callback received on change.
/// - `on_changedtick`: lua callback received on changedtick
/// increment without text change.
/// `utf_sizes`: include UTF-32 and UTF-16 size of
/// - `utf_sizes`: include UTF-32 and UTF-16 size of
/// the replaced region.
/// See |api-buffer-updates-lua| for more information
/// @param[out] err Error details, if any
@ -183,6 +183,8 @@ error:
/// Deactivates buffer-update events on the channel.
///
/// For Lua callbacks see |api-lua-detach|.
///
/// @param channel_id
/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any

View File

@ -14,7 +14,7 @@
/// Gets the windows in a tabpage
///
/// @param tabpage Tabpage
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @param[out] err Error details, if any
/// @return List of windows in `tabpage`
ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err)
@ -43,7 +43,7 @@ ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err)
/// Gets a tab-scoped (t:) variable
///
/// @param tabpage Tabpage handle
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Variable value
@ -61,7 +61,7 @@ Object nvim_tabpage_get_var(Tabpage tabpage, String name, Error *err)
/// Sets a tab-scoped (t:) variable
///
/// @param tabpage Tabpage handle
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @param name Variable name
/// @param value Variable value
/// @param[out] err Error details, if any
@ -82,7 +82,7 @@ void nvim_tabpage_set_var(Tabpage tabpage,
/// Removes a tab-scoped (t:) variable
///
/// @param tabpage Tabpage handle
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @param name Variable name
/// @param[out] err Error details, if any
void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err)
@ -101,7 +101,7 @@ void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err)
///
/// @deprecated
///
/// @param tabpage Tabpage handle
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @param name Variable name
/// @param value Variable value
/// @param[out] err Error details, if any
@ -124,7 +124,7 @@ Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
///
/// @deprecated
///
/// @param tabpage Tabpage handle
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Old value
@ -141,7 +141,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
/// Gets the current window in a tabpage
///
/// @param tabpage Tabpage handle
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @param[out] err Error details, if any
/// @return Window handle
Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
@ -169,7 +169,7 @@ Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
/// Gets the tabpage number
///
/// @param tabpage Tabpage handle
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @param[out] err Error details, if any
/// @return Tabpage number
Integer nvim_tabpage_get_number(Tabpage tabpage, Error *err)
@ -187,7 +187,7 @@ Integer nvim_tabpage_get_number(Tabpage tabpage, Error *err)
/// Checks if a tabpage is valid
///
/// @param tabpage Tabpage handle
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @return true if the tabpage is valid, false otherwise
Boolean nvim_tabpage_is_valid(Tabpage tabpage)
FUNC_API_SINCE(1)

View File

@ -1019,7 +1019,7 @@ fail:
///
/// Currently this is used to open floating and external windows.
/// Floats are windows that are drawn above the split layout, at some anchor
/// position in some other window. Floats can be draw internally or by external
/// position in some other window. Floats can be drawn internally or by external
/// GUI with the |ui-multigrid| extension. External windows are only supported
/// with multigrid GUIs, and are displayed as separate top-level windows.
///
@ -1059,11 +1059,11 @@ fail:
/// - "SE" south-east
/// - `height`: window height (in character cells). Minimum of 1.
/// - `width`: window width (in character cells). Minimum of 1.
/// - 'bufpos': position float relative text inside the window `win` (only
/// when relative="win"). Takes a tuple of [line, column] where
/// both are zero-index. Note: `row` and `col` if present, still
/// applies relative this positio. By default `row=1` and `col=0`
/// is used (with default NW anchor), to make the float
/// - 'bufpos': position float relative text inside window `win` (only
/// when relative="win"). Takes a tuple of zero-indexed
/// [line, column]. Note: `row` and `col` if present, still
/// applies relative this position. By default `row=1` and `col=0`
/// are used (with default NW anchor), to make the float
/// behave like a tooltip under the buffer text.
/// - `row`: row position. Screen cell height are used as unit. Can be
/// floating point.
@ -1416,9 +1416,9 @@ Dictionary nvim_get_color_map(void)
/// Gets a map of the current editor state.
///
/// @param types Context types ("regs", "jumps", "buflist", "gvars", ...)
/// to gather, or NIL for all.
/// to gather, or NIL for all (see |context-types|).
///
/// @return map of global context
/// @return map of global |context|.
Dictionary nvim_get_context(Array types)
FUNC_API_SINCE(6)
{
@ -1453,9 +1453,9 @@ Dictionary nvim_get_context(Array types)
return dict;
}
/// Sets the current editor state to that in given context dictionary.
/// Sets the current editor state from the given |context| map.
///
/// @param ctx_dict Context dictionary.
/// @param dict |Context| map.
Object nvim_load_context(Dictionary dict)
FUNC_API_SINCE(6)
{

View File

@ -22,7 +22,7 @@
/// Gets the current buffer in a window
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return Buffer handle
Buffer nvim_win_get_buf(Window window, Error *err)
@ -39,7 +39,7 @@ Buffer nvim_win_get_buf(Window window, Error *err)
/// Sets the current buffer in a window, without side-effects
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param buffer Buffer handle
/// @param[out] err Error details, if any
void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
@ -78,7 +78,7 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
/// Gets the (1,0)-indexed cursor position in the window. |api-indexing|
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return (row, col) tuple
ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err)
@ -97,7 +97,7 @@ ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err)
/// Sets the (1,0)-indexed cursor position in the window. |api-indexing|
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param pos (row, col) tuple representing the new position
/// @param[out] err Error details, if any
void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
@ -147,7 +147,7 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
/// Gets the window height
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return Height as a count of rows
Integer nvim_win_get_height(Window window, Error *err)
@ -165,7 +165,7 @@ Integer nvim_win_get_height(Window window, Error *err)
/// Sets the window height. This will only succeed if the screen is split
/// horizontally.
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param height Height as a count of rows
/// @param[out] err Error details, if any
void nvim_win_set_height(Window window, Integer height, Error *err)
@ -192,7 +192,7 @@ void nvim_win_set_height(Window window, Integer height, Error *err)
/// Gets the window width
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return Width as a count of columns
Integer nvim_win_get_width(Window window, Error *err)
@ -210,7 +210,7 @@ Integer nvim_win_get_width(Window window, Error *err)
/// Sets the window width. This will only succeed if the screen is split
/// vertically.
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param width Width as a count of columns
/// @param[out] err Error details, if any
void nvim_win_set_width(Window window, Integer width, Error *err)
@ -237,7 +237,7 @@ void nvim_win_set_width(Window window, Integer width, Error *err)
/// Gets a window-scoped (w:) variable
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Variable value
@ -255,7 +255,7 @@ Object nvim_win_get_var(Window window, String name, Error *err)
/// Sets a window-scoped (w:) variable
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param name Variable name
/// @param value Variable value
/// @param[out] err Error details, if any
@ -273,7 +273,7 @@ void nvim_win_set_var(Window window, String name, Object value, Error *err)
/// Removes a window-scoped (w:) variable
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param name Variable name
/// @param[out] err Error details, if any
void nvim_win_del_var(Window window, String name, Error *err)
@ -292,7 +292,7 @@ void nvim_win_del_var(Window window, String name, Error *err)
///
/// @deprecated
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param name Variable name
/// @param value Variable value
/// @param[out] err Error details, if any
@ -315,7 +315,7 @@ Object window_set_var(Window window, String name, Object value, Error *err)
///
/// @deprecated
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param name variable name
/// @param[out] err Error details, if any
/// @return Old value
@ -332,7 +332,7 @@ Object window_del_var(Window window, String name, Error *err)
/// Gets a window option value
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param name Option name
/// @param[out] err Error details, if any
/// @return Option value
@ -352,7 +352,7 @@ Object nvim_win_get_option(Window window, String name, Error *err)
/// works if there's a global fallback)
///
/// @param channel_id
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param name Option name
/// @param value Option value
/// @param[out] err Error details, if any
@ -371,7 +371,7 @@ void nvim_win_set_option(uint64_t channel_id, Window window,
/// Gets the window position in display cells. First position is zero.
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return (row, col) tuple with the window position
ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err)
@ -390,7 +390,7 @@ ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err)
/// Gets the window tabpage
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return Tabpage that contains the window
Tabpage nvim_win_get_tabpage(Window window, Error *err)
@ -408,7 +408,7 @@ Tabpage nvim_win_get_tabpage(Window window, Error *err)
/// Gets the window number
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return Window number
Integer nvim_win_get_number(Window window, Error *err)
@ -429,7 +429,7 @@ Integer nvim_win_get_number(Window window, Error *err)
/// Checks if a window is valid
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @return true if the window is valid, false otherwise
Boolean nvim_win_is_valid(Window window)
FUNC_API_SINCE(1)
@ -451,7 +451,7 @@ Boolean nvim_win_is_valid(Window window)
/// changed. The following restriction apply: `row`, `col` and `relative`
/// must be reconfigured together. Only changing a subset of these is an error.
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param config Dictionary of window configuration
/// @param[out] err Error details, if any
void nvim_win_set_config(Window window, Dictionary config, Error *err)
@ -490,7 +490,7 @@ void nvim_win_set_config(Window window, Dictionary config, Error *err)
///
/// `relative` will be an empty string for normal windows.
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return Window configuration
Dictionary nvim_win_get_config(Window window, Error *err)
@ -537,7 +537,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
/// Closes the window (like |:close| with a |window-ID|).
///
/// @param window Window handle
/// @param window Window handle, or 0 for current window
/// @param force Behave like `:close!` The last window of a buffer with
/// unwritten changes can be closed. The buffer will become
/// hidden, even if 'hidden' is not set.

View File

@ -215,9 +215,11 @@ paste = (function()
end
end)()
--- Defers the wrapped callback until the Nvim API is safe to call.
--- Defers callback `cb` until the Nvim API is safe to call.
---
--@see |vim-loop-callbacks|
---@see |lua-loop-callbacks|
---@see |vim.schedule()|
---@see |vim.in_fast_event()|
local function schedule_wrap(cb)
return (function (...)
local args = {...}

View File

@ -140,7 +140,7 @@ To run a *specific* functional test:
To *repeat* a test:
.deps/usr/bin/busted --lpath='build/?.lua' --filter 'foo' --repeat 1000 test/functional/ui/foo_spec.lua
BUSTED_ARGS="--repeat=100 --no-keep-going" TEST_FILE=test/functional/foo_spec.lua make functionaltest
### Filter by tag
@ -173,43 +173,27 @@ Writing tests
Guidelines
----------
- Consider [BDD](http://en.wikipedia.org/wiki/Behavior-driven_development)
guidelines for organization and readability of tests. Describe what you're
testing (and the environment if applicable) and create specs that assert its
behavior.
- For testing static functions or functions that have side effects visible only
in module-global variables, create accessors for the modified variables. For
example, say you are testing a function in misc1.c that modifies a static
variable, create a file `test/c-helpers/misc1.c` and add a function that
retrieves the value after the function call. Files under `test/c-helpers` will
only be compiled when building the test shared library.
- Luajit needs to know about type and constant declarations used in function
prototypes. The
[helpers.lua](https://github.com/neovim/neovim/blob/master/test/unit/helpers.lua)
file automatically parses `types.h`, so types used in the tested functions
must be moved to it to avoid having to rewrite the declarations in the test
files (even though this is how it's currently done currently in the misc1/fs
modules, but contributors are encouraged to refactor the declarations).
- Macro constants must be rewritten as enums so they can be "visible" to the
tests automatically.
- Busted supports various "output providers". The
**[gtest](https://github.com/Olivine-Labs/busted/pull/394) output provider**
shows verbose details that can be useful to diagnose hung tests. Either modify
the Makefile or compile with `make
CMAKE_EXTRA_FLAGS=-DBUSTED_OUTPUT_TYPE=gtest` to enable it.
- **Use busted's `pending()` feature** to skip tests
could be moved to it to avoid having to rewrite the declarations in the test
files.
- `#define` constants must be rewritten `const` or `enum` so they can be
"visible" to the tests.
- Use **pending()** to skip tests
([example](https://github.com/neovim/neovim/commit/5c1dc0fbe7388528875aff9d7b5055ad718014de#diff-bf80b24c724b0004e8418102f68b0679R18)).
Do not silently skip the test with `if-else`. If a functional test depends on
some external factor (e.g. the existence of `md5sum` on `$PATH`), *and* you
can't mock or fake the dependency, then skip the test via `pending()` if the
external factor is missing. This ensures that the *total* test-count
(success + fail + error + pending) is the same in all environments.
- *Note:* `pending()` is ignored if it is missing an argument _unless_ it is
- *Note:* `pending()` is ignored if it is missing an argument, unless it is
[contained in an `it()` block](https://github.com/neovim/neovim/blob/d21690a66e7eb5ebef18046c7a79ef898966d786/test/functional/ex_cmds/grep_spec.lua#L11).
Provide empty function argument if the `pending()` call is outside of `it()`
([example](https://github.com/neovim/neovim/commit/5c1dc0fbe7388528875aff9d7b5055ad718014de#diff-bf80b24c724b0004e8418102f68b0679R18)).
- Really long `source([=[...]=])` blocks may break syntax highlighting. Try
`:syntax sync fromstart` to fix it.
- Really long `source([=[...]=])` blocks may break Vim's Lua syntax
highlighting. Try `:syntax sync fromstart` to fix it.
Where tests go
--------------
@ -254,6 +238,8 @@ Test behaviour is affected by environment variables. Currently supported
treated as Integer; when defined, treated as String; when defined, treated as
Number; !must be defined to function properly):
- `BUSTED_ARGS` (F) (U): arguments forwarded to `busted`.
- `GDB` (F) (D): makes nvim instances to be run under `gdbserver`. It will be
accessible on `localhost:7777`: use `gdb build/bin/nvim`, type `target remote
:7777` inside.