diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2019-09-09 14:42:20 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-09 14:42:20 -0700 |
commit | 0809533b88899b11516461d0c9997b917a153135 (patch) | |
tree | bb72a1afa35e69dd93011c3826ab6c39e52ff535 | |
parent | 853683e72a780afef3ecebd8d46e32983abe1798 (diff) | |
parent | e5d5fc0857935b4f67058a6a2dcfbc573331e3f6 (diff) | |
download | rneovim-0809533b88899b11516461d0c9997b917a153135.tar.gz rneovim-0809533b88899b11516461d0c9997b917a153135.tar.bz2 rneovim-0809533b88899b11516461d0c9997b917a153135.zip |
Merge #10546 'doc'
-rw-r--r-- | MAINTAIN.md | 16 | ||||
-rw-r--r-- | man/nvim.1 | 8 | ||||
-rw-r--r-- | runtime/doc/api.txt | 315 | ||||
-rw-r--r-- | runtime/doc/channel.txt | 2 | ||||
-rw-r--r-- | runtime/doc/develop.txt | 44 | ||||
-rw-r--r-- | runtime/doc/eval.txt | 47 | ||||
-rw-r--r-- | runtime/doc/help.txt | 1 | ||||
-rw-r--r-- | runtime/doc/if_lua.txt | 53 | ||||
-rw-r--r-- | runtime/doc/intro.txt | 5 | ||||
-rw-r--r-- | runtime/doc/job_control.txt | 2 | ||||
-rw-r--r-- | runtime/doc/msgpack_rpc.txt | 239 | ||||
-rw-r--r-- | runtime/doc/repeat.txt | 43 | ||||
-rw-r--r-- | runtime/doc/starting.txt | 7 | ||||
-rw-r--r-- | runtime/doc/syntax.txt | 5 | ||||
-rw-r--r-- | runtime/doc/ui.txt | 4 | ||||
-rw-r--r-- | runtime/doc/usr_41.txt | 7 | ||||
-rw-r--r-- | runtime/doc/vim_diff.txt | 12 | ||||
-rw-r--r-- | runtime/nvim.appdata.xml | 3 | ||||
-rwxr-xr-x | scripts/gen_vimdoc.py | 4 | ||||
-rw-r--r-- | src/nvim/README.md | 2 | ||||
-rw-r--r-- | src/nvim/api/buffer.c | 8 | ||||
-rw-r--r-- | src/nvim/api/tabpage.c | 18 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 20 | ||||
-rw-r--r-- | src/nvim/api/window.c | 44 | ||||
-rw-r--r-- | src/nvim/lua/vim.lua | 6 | ||||
-rw-r--r-- | test/README.md | 36 |
26 files changed, 507 insertions, 444 deletions
diff --git a/MAINTAIN.md b/MAINTAIN.md index e102d7a94b..58d977f247 100644 --- a/MAINTAIN.md +++ b/MAINTAIN.md @@ -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 +-------- -See also: https://github.com/neovim/neovim/issues/862 +- https://github.com/neovim/neovim/issues/862 +- https://github.com/git/git/blob/master/Documentation/howto/maintain-git.txt diff --git a/man/nvim.1 b/man/nvim.1 index bf60c80a37..bc11739747 100644 --- a/man/nvim.1 +++ b/man/nvim.1 @@ -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. diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 1af327e572..21cc114598 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -14,26 +14,113 @@ 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* *api-types* 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-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. + ============================================================================== -API metadata *api-metadata* +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 API metadata as a Dictionary. Some items are described below: +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 diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt index f3fa3fa180..967f4b26f2 100644 --- a/runtime/doc/channel.txt +++ b/runtime/doc/channel.txt @@ -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. diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index 3262d9dec7..90c2e30771 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -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 ~ - -For C/C++ projects, consider libmpack instead of the msgpack.org library. +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. + 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 diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 5032dc16ee..53a5f247f9 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -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|) diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 68e94ef5c5..284cd26583 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -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 diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt index 1837e14623..11950da91e 100644 --- a/runtime/doc/if_lua.txt +++ b/runtime/doc/if_lua.txt @@ -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: diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index c240f08a75..887ef764bd 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -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 diff --git a/runtime/doc/job_control.txt b/runtime/doc/job_control.txt index ae208c0755..bf01e8e266 100644 --- a/runtime/doc/job_control.txt +++ b/runtime/doc/job_control.txt @@ -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. diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt index b24e706aa9..f5d42dfeb2 100644 --- a/runtime/doc/msgpack_rpc.txt +++ b/runtime/doc/msgpack_rpc.txt @@ -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|. diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index 425ef4e926..8f6d3aec2e 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -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: diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index fa4d87e915..7dbbb2d424 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -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 diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index f813717eeb..a027f66a3f 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -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* diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index 3b7debd99e..872049b356 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -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, diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 2a2885b4d3..c770950a96 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -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 diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index a358da460c..7381ae4e2b 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -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) diff --git a/runtime/nvim.appdata.xml b/runtime/nvim.appdata.xml index fb409ff0b8..32d3c523c6 100644 --- a/runtime/nvim.appdata.xml +++ b/runtime/nvim.appdata.xml @@ -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> diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index edfb38e617..373a58d11e 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -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())) diff --git a/src/nvim/README.md b/src/nvim/README.md index 35ca2944e9..3f7c05757a 100644 --- a/src/nvim/README.md +++ b/src/nvim/README.md @@ -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" diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 690497159a..3e1209d1b1 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -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 diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c index b6830d9fcf..dd17bc03e5 100644 --- a/src/nvim/api/tabpage.c +++ b/src/nvim/api/tabpage.c @@ -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) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 27344fc093..ce49045f24 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -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) { diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 02670c0513..3e9f292eb9 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -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. diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua index f0f24e4d16..9149285efd 100644 --- a/src/nvim/lua/vim.lua +++ b/src/nvim/lua/vim.lua @@ -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 = {...} diff --git a/test/README.md b/test/README.md index 60279589b1..64892b5576 100644 --- a/test/README.md +++ b/test/README.md @@ -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. |