diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2017-11-06 05:04:37 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-06 05:04:37 +0100 |
commit | d31b94ac209d2161f60084d5fa1e18f0cbaf0207 (patch) | |
tree | 9afbf06aaa972109fb218f56e6f3ba06ba7cd6d3 | |
parent | 04b3c327723587fa63f391884b8dfce44233cc77 (diff) | |
parent | 280943d9b938e95fcf77ef5290576630b84511fb (diff) | |
download | rneovim-d31b94ac209d2161f60084d5fa1e18f0cbaf0207.tar.gz rneovim-d31b94ac209d2161f60084d5fa1e18f0cbaf0207.tar.bz2 rneovim-d31b94ac209d2161f60084d5fa1e18f0cbaf0207.zip |
Merge #7188 from justinmk/doc
doc; minor runtime bug fixes
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | runtime/autoload/spellfile.vim | 6 | ||||
-rw-r--r-- | runtime/doc/api.txt | 120 | ||||
-rw-r--r-- | runtime/doc/develop.txt | 44 | ||||
-rw-r--r-- | runtime/doc/eval.txt | 131 | ||||
-rw-r--r-- | runtime/doc/if_lua.txt | 22 | ||||
-rw-r--r-- | runtime/doc/intro.txt | 3 | ||||
-rw-r--r-- | runtime/doc/job_control.txt | 129 | ||||
-rw-r--r-- | runtime/doc/msgpack_rpc.txt | 2 | ||||
-rw-r--r-- | runtime/doc/options.txt | 2 | ||||
-rw-r--r-- | runtime/doc/provider.txt | 14 | ||||
-rw-r--r-- | runtime/doc/vim_diff.txt | 26 | ||||
-rw-r--r-- | runtime/plugin/man.vim | 2 | ||||
-rw-r--r-- | scripts/gen_api_vimdoc.py | 22 | ||||
-rw-r--r-- | src/nvim/api/buffer.c | 37 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 30 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 4 | ||||
-rw-r--r-- | src/nvim/ops.c | 2 | ||||
-rw-r--r-- | test/README.md | 53 |
19 files changed, 373 insertions, 281 deletions
@@ -34,6 +34,11 @@ Install from source make CMAKE_BUILD_TYPE=RelWithDebInfo sudo make install +To install to a non-default location, specify `CMAKE_INSTALL_PREFIX`: + + make CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=/full/path/" + make install + See [the wiki](https://github.com/neovim/neovim/wiki/Building-Neovim) for details. Install from package diff --git a/runtime/autoload/spellfile.vim b/runtime/autoload/spellfile.vim index a5ffa514ea..fe7113b9a4 100644 --- a/runtime/autoload/spellfile.vim +++ b/runtime/autoload/spellfile.vim @@ -88,8 +88,8 @@ function! spellfile#LoadFile(lang) endif endif if newbufnr == winbufnr(0) - " We are back the old buffer, remove any (half-finished) download. - g/^/d_ + " We are back to the old buffer, remove any (half-finished) download. + keeppatterns g/^/d_ else let newbufnr = winbufnr(0) endif @@ -127,7 +127,7 @@ function! spellfile#LoadFile(lang) exe "write " . dirname . '/' . fname " Also download the .sug file. - g/^/d_ + keeppatterns g/^/d_ let fname = substitute(fname, '\.spl$', '.sug', '') echo 'Downloading ' . fname . '...' call spellfile#Nread(fname) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 159dd93c5e..ef8b9c7d47 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -7,7 +7,7 @@ Nvim API *API* *api* Nvim exposes a powerful API that can be used by plugins and external processes -via |msgpack-rpc|, Lua and VimL (|eval-api|). +via |RPC|, |Lua| and VimL (|eval-api|). Applications can also embed libnvim to work with the C API directly. @@ -135,6 +135,26 @@ nvim_command({command}) *nvim_command()* Parameters:~ {command} Ex-command string +nvim_get_hl_by_name({name}, {rgb}) *nvim_get_hl_by_name()* + Gets a highlight definition by name. + + Parameters:~ + {name} Highlight group name + {rgb} Export RGB colors + + Return:~ + Highlight definition map + +nvim_get_hl_by_id({hl_id}, {rgb}) *nvim_get_hl_by_id()* + Gets a highlight definition by id. |hlID()| + + Parameters:~ + {hl_id} Highlight id as returned by |hlID()| + {rgb} Export RGB colors + + Return:~ + Highlight definition map + nvim_feedkeys({keys}, {mode}, {escape_csi}) *nvim_feedkeys()* Passes input keys to Nvim. On VimL error: Does not fail, but updates v:errmsg. @@ -151,7 +171,11 @@ nvim_input({keys}) *nvim_input()* Unlike `nvim_feedkeys`, this uses a lower-level input buffer and the call is not deferred. This is the most reliable way to - emulate real user input. + send real user input. + + Note: + |keycodes| like <CR> are translated, so "<" is special. To + input a literal "<", send <LT>. Attributes:~ {async} @@ -204,14 +228,11 @@ nvim_call_function({fname}, {args}) *nvim_call_function()* Result of the function call nvim_execute_lua({code}, {args}) *nvim_execute_lua()* - Execute lua code. Parameters might be passed, they are - available inside the chunk as `...`. The chunk can return a - value. + Execute lua code. Parameters (if any) are available as `...` + inside the chunk. The chunk can return a value. - To evaluate an expression, it must be prefixed with "return ". - For instance, to call a lua function with arguments sent in - and get its return value back, use the code "return - my_function(...)". + Only statements are executed. To evaluate an expression, + prefix it with `return`: return my_function(...) Parameters:~ {code} lua code to execute @@ -220,7 +241,7 @@ nvim_execute_lua({code}, {args}) *nvim_execute_lua()* Return:~ Return value of lua code if present or NIL. -nvim_strwidth({str}) *nvim_strwidth()* +nvim_strwidth({text}) *nvim_strwidth()* Calculates the number of display cells occupied by `text`. <Tab> counts as one cell. @@ -347,7 +368,7 @@ nvim_set_current_buf({buffer}) *nvim_set_current_buf()* Sets the current buffer Parameters:~ - {id} Buffer handle + {buffer} Buffer handle nvim_list_wins() *nvim_list_wins()* Gets the current list of window handles @@ -365,7 +386,7 @@ nvim_set_current_win({window}) *nvim_set_current_win()* Sets the current window Parameters:~ - {handle} Window handle + {window} Window handle nvim_list_tabpages() *nvim_list_tabpages()* Gets the current list of tabpage handles @@ -383,7 +404,7 @@ nvim_set_current_tabpage({tabpage}) *nvim_set_current_tabpage()* Sets the current tabpage Parameters:~ - {handle} Tabpage handle + {tabpage} Tabpage handle nvim_subscribe({event}) *nvim_subscribe()* Subscribes to event broadcasts @@ -404,26 +425,25 @@ nvim_get_color_map() *nvim_get_color_map()* TODO: Documentation nvim_get_mode() *nvim_get_mode()* - Gets the current mode. - mode: Mode string. |mode()| - blocking: true if Nvim is waiting for input. - - Attributes:~ - {async} + Gets the current mode. |mode()| "blocking" is true if Nvim is + waiting for input. Return:~ Dictionary { "mode": String, "blocking": Boolean } + Attributes:~ + {async} + nvim_get_keymap({mode}) *nvim_get_keymap()* - Get a list of dictionaries describing global (i.e. non-buffer) - mappings Note that the "buffer" key will be 0 to represent - false. + Gets a list of dictionaries describing global (non-buffer) + mappings. The "buffer" key in the returned dictionary is + always zero. Parameters:~ - {mode} The abbreviation for the mode + {mode} Mode short-name ("n", "i", "v", ...) Return:~ - An array of maparg() like dictionaries describing mappings + Array of maparg()-like dictionaries describing mappings nvim_get_api_info() *nvim_get_api_info()* TODO: Documentation @@ -584,16 +604,16 @@ nvim_buf_get_changedtick({buffer}) *nvim_buf_get_changedtick()* b:changedtickvalue. nvim_buf_get_keymap({buffer}, {mode}) *nvim_buf_get_keymap()* - Get a list of dictionaries describing buffer-local mappings - Note that the buffer key in the dictionary will represent the - buffer handle where the mapping is present + Gets a list of dictionaries describing buffer-local mappings. + The "buffer" key in the returned dictionary reflects the + buffer handle where the mapping is present. Parameters:~ - {mode} The abbreviation for the mode - {buffer_id} Buffer handle + {mode} Mode short-name ("n", "i", "v", ...) + {buffer} Buffer handle Return:~ - An array of maparg() like dictionaries describing mappings + Array of maparg()-like dictionaries describing mappings nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()* Sets a buffer-scoped (b:) variable @@ -670,24 +690,24 @@ nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line}, {col_start}, {col_end}) Adds a highlight to buffer. - This can be used for plugins which dynamically generate - highlights to a buffer (like a semantic highlighter or - linter). The function adds a single highlight to a buffer. - Unlike matchaddpos() highlights follow changes to line - numbering (as lines are inserted/removed above the highlighted - line), like signs and marks do. - - "src_id" is useful for batch deletion/updating of a set of - highlights. When called with src_id = 0, an unique source id - is generated and returned. Succesive calls can pass in it as - "src_id" to add new highlights to the same source group. All - highlights in the same group can then be cleared with - nvim_buf_clear_highlight. If the highlight never will be - manually deleted pass in -1 for "src_id". - - If "hl_group" is the empty string no highlight is added, but a - new src_id is still returned. This is useful for an external - plugin to synchrounously request an unique src_id at + Useful for plugins that dynamically generate highlights to a + buffer (like a semantic highlighter or linter). The function + adds a single highlight to a buffer. Unlike matchaddpos() + highlights follow changes to line numbering (as lines are + inserted/removed above the highlighted line), like signs and + marks do. + + `src_id` is useful for batch deletion/updating of a set of + highlights. When called with `src_id = 0`, an unique source id + is generated and returned. Successive calls can pass that + `src_id` to associate new highlights with the same source + group. All highlights in the same group can be cleared with + `nvim_buf_clear_highlight`. If the highlight never will be + manually deleted, pass `src_id = -1`. + + If `hl_group` is the empty string no highlight is added, but a + new `src_id` is still returned. This is useful for an external + plugin to synchrounously request an unique `src_id` at initialization, and later asynchronously add and clear highlights in response to buffer changes. @@ -696,7 +716,7 @@ nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line}, {src_id} Source group to use or 0 to use a new group, or -1 for ungrouped highlight {hl_group} Name of the highlight group to use - {line} Line to highlight + {line} Line to highlight (zero-indexed) {col_start} Start of range of columns to highlight {col_end} End of range of columns to highlight, or -1 to highlight to end of line @@ -948,4 +968,4 @@ nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()* nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()* TODO: Documentation - vim:tw=78:ts=8:ft=help:norl: + vim:tw=78:ts=8:ft=help:norl:
\ No newline at end of file diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index 298f64bbee..36826e2479 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -142,6 +142,8 @@ shell The Vim application. This can cover the whole screen (e.g., window View on a buffer. There can be several windows in Vim, together with the command line, menubar, toolbar, etc. they fit in the shell. +frame Windows are kept in a tree of frames. Each frame contains + a column, row, or window ("leaf" frame). PROVIDERS *dev-provider* @@ -230,23 +232,47 @@ _not_ a Buffer). The common {action} "list" indicates that it lists all bufs (plural) in the global context. +API-CLIENT *dev-api-client* + +Package Naming ~ +API client packages should NOT be named something ambiguous like "neovim" or +"python-client". Use "nvim" as a prefix/suffix to some other identifier +following ecosystem conventions. + +For example, Python packages tend to have "py" in the name, so "pynvim" is +a good name: it's idiomatic and unambiguous. If the package is named "neovim", +it confuses users, and complicates documentation and discussions. + +Examples of API-client package names: + GOOD: nvim-racket + GOOD: pynvim + BAD: python-client + BAD: neovim + +Implementation ~ +Consider using libmpack instead of the msgpack.org C/C++ library. libmpack is +small, efficient, and C89-compatible. It can be easily inlined in your +C project source, too. https://github.com/libmpack/libmpack/ + + EXTERNAL UI *dev-ui* +Compatibility ~ External UIs should be aware of the |api-contract|. In particular, future -versions of Nvim may add optional, new items to existing events. The API is -strongly backwards-compatible, but clients must not break if new fields are -added to existing events. +versions of Nvim may add new items to existing events. The API is strongly +backwards-compatible, but clients must not break if new fields are added to +existing events. -External UIs are expected to implement some common features. +Common Features ~ +External UIs are expected to implement these common features: +- Cursor style (shape, color) should respond to the 'guicursor' properties + delivered with the mode_info_set UI event. +- Send the "super" key (Windows key, Apple key) as a |<D-| chord. -- Users may want to configure UI-specific options. The UI should publish the - |GUIEnter| autocmd after attaching to Nvim: > - doautocmd GUIEnter +Implementation ~ - Options can be monitored for changes by the |OptionSet| autocmd. E.g. if the user sets the 'guifont' option, this autocmd notifies channel 42: > autocmd OptionSet guifont call rpcnotify(42, 'option-changed', 'guifont', &guifont) -- cursor-shape change: 'guicursor' properties are sent in the mode_info_set UI - event. vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 300bdd061e..b0796b8c5d 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1785,7 +1785,7 @@ v:scrollstart String describing the script or function that caused the *v:servername* *servername-variable* *$NVIM_LISTEN_ADDRESS* -v:servername Default {Nvim} server address. Equivalent to +v:servername Default Nvim server address. Equivalent to |$NVIM_LISTEN_ADDRESS| on startup. |serverstop()| Read-only. @@ -4915,42 +4915,48 @@ items({dict}) *items()* entry and the value of this entry. The |List| is in arbitrary order. -jobclose({job}[, {stream}]) {Nvim} *jobclose()* - Close {job}'s {stream}, which can be one of "stdin", "stdout", - "stderr" or "rpc" (closes the rpc channel for a job started - with the "rpc" option.) If {stream} is omitted, all streams - are closed. If the job is a pty job, this will then close the - pty master, sending SIGHUP to the job process. +jobclose({job}[, {stream}]) *jobclose()* + Close {stream} of |job-id| {job}, where {stream} is one of: + "stdin", "stdout", "stderr", "rpc" (RPC channel of a job + started with `"rpc":v:true`). If {stream} is omitted, all + streams are closed. If the job is a pty job, this will close + the pty master, sending SIGHUP to the job process. -jobpid({job}) {Nvim} *jobpid()* - Return the pid (process id) of {job}. +jobpid({job}) *jobpid()* + Return the PID (process id) of |job-id| {job}. -jobresize({job}, {width}, {height}) {Nvim} *jobresize()* - Resize {job}'s pseudo terminal window to {width} and {height}. - This function will fail if used on jobs started without the - "pty" option. +jobresize({job}, {width}, {height}) *jobresize()* + Resize the pseudo terminal window of |job-id| {job} to {width} + columns and {height} rows. + Fails if the job was not started with `"pty":v:true`. -jobsend({job}, {data}) {Nvim} *jobsend()* - Send data to {job} by writing it to the stdin of the process. +jobsend({job}, {data}) *jobsend()* + Writes to stdin of the process associated with |job-id| {job}. Returns 1 if the write succeeded, 0 otherwise. - See |job-control| for more information. + See |job-control|. {data} may be a string, string convertible, or a list. If - {data} is a list, the items will be separated by newlines and - any newlines in an item will be sent as a NUL. A final newline - can be sent by adding a final empty string. For example: > + {data} is a list, the items will be joined by newlines; any + newlines in an item will be sent as NUL. To send a final + newline, include a final empty string. Example: > :call jobsend(j, ["abc", "123\n456", ""]) < will send "abc<NL>123<NUL>456<NL>". - If the job was started with the rpc option this function - cannot be used, instead use |rpcnotify()| and |rpcrequest()| - to communicate with the job. + jobsend() writes raw data, not RPC messages. If the job was + created with `"rpc":v:true` then the channel expects RPC + messages, use |rpcnotify()| and |rpcrequest()| instead. -jobstart({cmd}[, {opts}]) {Nvim} *jobstart()* - Spawns {cmd} as a job. If {cmd} is a |List| it is run - directly. If {cmd} is a |String| it is processed like this: > +jobstart({cmd}[, {opts}]) *jobstart()* + Spawns {cmd} as a job. + If {cmd} is a List it runs directly (no 'shell'). + If {cmd} is a String it runs in the 'shell', like this: > :call jobstart(split(&shell) + split(&shellcmdflag) + ['{cmd}']) -< (Only shows the idea; see |shell-unquoting| for full details.) +< (See |shell-unquoting| for details.) + + Returns |job-id| on success, 0 on invalid arguments (or job + table is full), -1 if {cmd}[0] or 'shell' is not executable. + + See |job-control| and |rpc|. NOTE: on Windows if {cmd} is a List: - cmd[0] must be an executable (not a "built-in"). If it is @@ -4962,6 +4968,7 @@ jobstart({cmd}[, {opts}]) {Nvim} *jobstart()* by CommandLineToArgvW https://msdn.microsoft.com/bb776391 unless cmd[0] is some form of "cmd.exe". + *jobstart-options* {opts} is a dictionary with these keys: |on_stdout|: stdout event handler (function name or |Funcref|) |on_stderr|: stderr event handler (function name or |Funcref|) @@ -4972,9 +4979,9 @@ jobstart({cmd}[, {opts}]) {Nvim} *jobstart()* with the job over stdin and stdout. "on_stdout" is then ignored, but "on_stderr" can still be used. pty : If set, the job will be connected to a new pseudo - terminal, and the job streams are connected to - the master file descriptor. "on_stderr" is ignored - as all output will be received on stdout. + terminal and the job streams are connected to the + master file descriptor. "on_stderr" is ignored, + "on_stdout" receives all output. width : (pty only) Width of the terminal screen height : (pty only) Height of the terminal screen @@ -4982,43 +4989,31 @@ jobstart({cmd}[, {opts}]) {Nvim} *jobstart()* detach : (non-pty only) Detach the job process from the nvim process. The process will not get killed when nvim exits. If the process dies before - nvim exits, on_exit will still be invoked. + nvim exits, "on_exit" will still be invoked. - {opts} is passed as |self| to the callback; the caller may - pass arbitrary data by setting other keys. - Returns: - - The job ID on success, which is used by |jobsend()| (or - |rpcnotify()| and |rpcrequest()| if "rpc" option was used) - and |jobstop()| - - 0 on invalid arguments or if the job table is full - - -1 if {cmd}[0] is not executable. - See |job-control| and |msgpack-rpc| for more information. - -jobstop({job}) {Nvim} *jobstop()* - Stop a job created with |jobstart()| by sending a `SIGTERM` - to the corresponding process. If the process doesn't exit - cleanly soon, a `SIGKILL` will be sent. When the job is - finally closed, the exit handler provided to |jobstart()| or - |termopen()| will be run. - See |job-control| for more information. - -jobwait({ids}[, {timeout}]) {Nvim} *jobwait()* + {opts} is passed as |self| dictionary to the callback; the + caller may set other keys to pass application-specific data. + +jobstop({job}) *jobstop()* + Stop |job-id| {job} by sending SIGTERM to the job process. If + the process does not terminate after a timeout then SIGKILL + will be sent. When the job terminates its |on_exit| handler + (if any) will be invoked. + See |job-control|. + +jobwait({ids}[, {timeout}]) *jobwait()* Wait for a set of jobs to finish. The {ids} argument is a list - of ids for jobs that will be waited for. If passed, {timeout} - is the maximum number of milliseconds to wait. While this - function is executing, callbacks for jobs not in the {ids} - list can be executed. Also, the screen wont be updated unless - |:redraw| is invoked by one of the callbacks. - - Returns a list of integers with the same length as {ids}, with - each integer representing the wait result for the - corresponding job id. The possible values for the resulting - integers are: - - * the job return code if the job exited - * -1 if the wait timed out for the job - * -2 if the job was interrupted - * -3 if the job id is invalid. + of |job-id|s to wait for. {timeout} is the maximum number of + milliseconds to wait. During jobwait(), callbacks for jobs not + in the {ids} 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: + Job exit-code, if the job exited + -1 if the wait timed out for the job + -2 if the job was interrupted + -3 if the |job-id| is invalid. join({list} [, {sep}]) *join()* Join the items in {list} together into one String. @@ -5652,7 +5647,7 @@ mode([expr]) Return a string that indicates the current mode. i Insert R Replace |R| Rv Virtual Replace |gR| - t Terminal {Nvim} + t Terminal c Command-line cv Vim Ex mode |gQ| ce Normal Ex mode |Q| @@ -8201,9 +8196,9 @@ There are four types of features: Example: > :if has("win32") < *has-patch* -3. {Nvim} version. The "nvim-1.2.3" feature means that the Nvim version is - 1.2.3 or later. Example: > - :if has("nvim-1.2.3") +3. Nvim version. The "nvim-0.2.1" feature means that the Nvim version is + 0.2.1 or later. Example: > + :if has("nvim-0.2.1") < 4. Included patches. The "patch123" feature means that patch 123 has been included. Note that this form does not check the version of Vim, you need diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt index a123041866..968d882a22 100644 --- a/runtime/doc/if_lua.txt +++ b/runtime/doc/if_lua.txt @@ -24,7 +24,7 @@ the existing `package.cpath` are used. Example: 1. Given that - 'runtimepath' contains `/foo/bar,/xxx;yyy/baz,/abc`; - - initial (defined at compile time or derived from + - initial (defined at compile-time or derived from `$LUA_CPATH`/`$LUA_INIT`) `package.cpath` contains `./?.so;/def/ghi/a?d/j/g.elf;/def/?.so`. 2. It finds `?`-containing suffixes `/?.so`, `/a?d/j/g.elf` and `/?.so`, in @@ -159,14 +159,17 @@ Examples: > :lua vim.api.nvim_command('echo "Hello, Nvim!"') < +To see the Lua version: > + :lua print(_VERSION) + +To see the LuaJIT version: > + :lua print(jit.version) +< :[range]lua << {endmarker} {script} {endmarker} Execute Lua script {script}. - Note: This command doesn't work when the Lua - feature wasn't compiled in. To avoid errors, see - |script-here|. {endmarker} must NOT be preceded by any white space. If {endmarker} is omitted from after the "<<", a dot '.' must be used after {script}, like @@ -186,15 +189,8 @@ Example: EOF endfunction -Note that the variables are prefixed with `local`: they will disappear when -block finishes. This is not the case for globals. - -To see what version of Lua you have: > - :lua print(_VERSION) - -If you use LuaJIT you can also use this: > - :lua print(jit.version) -< +Note that the `local` variables will disappear when block finishes. This is +not the case for globals. *:luado* :[range]luado {body} Execute Lua function "function (line, linenr) {body} diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index 90b0ff7da3..30524fb6aa 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -373,8 +373,7 @@ CTRL-{char} {char} typed as a control character; that is, typing {char} *key-notation* *key-codes* *keycodes* These names for keys are used in the documentation. They can also be used -with the ":map" command (insert the key name by pressing CTRL-K and then the -key you want the name for). +with the ":map" command. notation meaning equivalent decimal value(s) ~ ----------------------------------------------------------------------- diff --git a/runtime/doc/job_control.txt b/runtime/doc/job_control.txt index 2cf48f0f4f..7ba0acff48 100644 --- a/runtime/doc/job_control.txt +++ b/runtime/doc/job_control.txt @@ -4,41 +4,30 @@ NVIM REFERENCE MANUAL by Thiago de Arruda -Nvim's facilities for job control *job-control* +Nvim job control *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. Type |gO| to see the table of contents. ============================================================================== -1. Introduction *job-control-intro* - -Job control is a simple way to perform multitasking in vimscript. Wikipedia -contains a more generic/detailed description: +Concepts -"Job control in computing refers to the control of multiple tasks or Jobs on a -computer system, ensuring that they each have access to adequate resources to -perform correctly, that competition for limited resources does not cause a -deadlock where two or more jobs are unable to complete, resolving such -situations where they do occur, and terminating jobs that, for any reason, are -not performing as expected." +Job Id *job-id* -In a few words: It allows a vimscript programmer to concurrently spawn and -control multiple processes without blocking the current Nvim instance. +When a job starts it is assigned a number, unique for the life of the current +Nvim session. Functions like |jobstart()| return job ids. Functions like +|jobsend()|, |jobstop()|, |rpcnotify()|, and |rpcrequest()| take job ids. -Nvim's job control was designed to be simple and familiar to vimscript -programmers, instead of being very powerful but complex. Unlike Vim's -facilities for calling with external commands, job control does not depend on -available shells, instead relying on OS functionality for process management. +============================================================================== +Usage *job-control-usage* -Internally, Nvim job control is powered by libuv, which has a nice -cross-platform API for managing processes. See https://github.com/libuv/libuv -for details. +To control jobs, use the "job…" family of functions: |jobstart()|, +|jobsend()|, |jobstop()|. -============================================================================== -2. Usage *job-control-usage* +Example: > -Job control is achieved by calling a combination of the |jobstart()|, -|jobsend()| and |jobstop()| functions. Here's an example: -> function! s:JobHandler(job_id, data, event) dict if a:event == 'stdout' let str = self.shell.' stdout: '.join(a:data) @@ -58,35 +47,41 @@ Job control is achieved by calling a combination of the |jobstart()|, let job1 = jobstart(['bash'], extend({'shell': 'shell 1'}, s:callbacks)) let job2 = jobstart(['bash', '-c', 'for i in {1..10}; do echo hello $i!; sleep 1; done'], extend({'shell': 'shell 2'}, s:callbacks)) +To test the above script, copy it to a file ~/foo.vim and run it: > + nvim -u ~/foo.vim < -To test the above, copy it to the file ~/jobcontrol.vim and start with a clean -nvim instance: -> - nvim -u NONE -S ~/jobcontrol.vim -< -Here's what is happening: - -- Two bash instances are spawned by |jobstart()| with their stdin/stdout/stderr - connected to nvim. -- The first shell is idle, waiting to read commands from its stdin. -- The second shell is started with the -c argument, causing it to execute a - command then exit. In this case, the command is a for loop that will print 0 - through 9 then exit. -- The `JobHandler()` function is a callback passed to |jobstart()| to handle - various job events. It takes care of displaying stdout/stderr received from - the shells. - *on_stdout* *on_stderr* *on_exit* -- The arguments passed to `JobHandler()` are: - - 0: The job id - 1: If the event is "stdout" or "stderr", a list with lines read from the - corresponding stream. For "exit", it is the status returned by the - program. - 2: The event type, which is "stdout", "stderr" or "exit". +Description of what happens: + - Two bash shells are spawned by |jobstart()| with their stdin/stdout/stderr + streams connected to nvim. + - The first shell is idle, waiting to read commands from its stdin. + - The second shell is started with -c which executes the command (a for-loop + printing 0 through 9) and then exits. + - `JobHandler()` callback is passed to |jobstart()| to handle various job + events. It displays stdout/stderr data received from the shells. + + *on_stdout* +Arguments passed to on_stdout callback: + 0: |job-id| + 1: List of lines read from the stream. If the last item is not "" (empty + string), then it is an incomplete line that might be continued at the + next on_stdout invocation. See Note 2 below. + 2: Event type: "stdout" + *on_stderr* +Arguments passed to on_stderr callback: + 0: |job-id| + 1: List of lines read from the stream. If the last item is not "" (empty + string), then it is an incomplete line that might be continued at the + next on_stderr invocation. See Note 2 below. + 2: Event type: "stderr" + *on_exit* +Arguments passed to on_exit callback: + 0: |job-id| + 1: Exit-code of the process. + 2: Event type: "exit" Note: Buffered stdout/stderr data which has not been flushed by the sender - will not trigger the "stdout" callback (but if the process ends, the - "exit" callback will be triggered). + will not trigger the on_stdout/on_stderr callback (but if the process + ends, the on_exit callback will be invoked). For example, "ruby -e" buffers output, so small strings will be buffered unless "auto-flushing" ($stdout.sync=true) is enabled. > function! Receive(job_id, data, event) @@ -97,9 +92,25 @@ Here's what is happening: \ {'on_stdout': 'Receive'}) < https://github.com/neovim/neovim/issues/1592 -The options dictionary is passed as the "self" variable to the callback -function. Here's a more object-oriented version of the above: -> + Note 2: + Job event handlers may receive partial (incomplete) lines. For a given + invocation of on_stdout/on_stderr, `a:data` is not guaranteed to end + with a newline. + - `abcdefg` may arrive as `['abc']`, `['defg']`. + - `abc\nefg` may arrive as `['abc', '']`, `['efg']` or `['abc']`, + `['','efg']`, or even `['ab']`, `['c','efg']`. + Easy way to deal with this: initialize a list as `['']`, then append + to it as follows: > + let s:chunks = [''] + func! s:on_stdout(job_id, data, event) dict + let s:chunks[-1] .= a:data[0] + call extend(s:chunks, a:data[1:]) + endf +< + +The |jobstart-options| dictionary is passed as |self| to the callback. +The above example could be written in this "object-oriented" style: > + let Shell = {} function Shell.on_stdout(_job_id, data, event) @@ -126,19 +137,13 @@ function. Here's a more object-oriented version of the above: let instance = Shell.new('bomb', \ 'for i in $(seq 9 -1 1); do echo $i 1>&$((i % 2 + 1)); sleep 1; done') < -To send data to the job's stdin, one can use the |jobsend()| function, like -this: -> +To send data to the job's stdin, use |jobsend()|: > :call jobsend(job1, "ls\n") :call jobsend(job1, "invalid-command\n") :call jobsend(job1, "exit\n") < -A job may be killed at any time with the |jobstop()| function: -> +A job may be killed with |jobstop()|: > :call jobstop(job1) < -When |jobstop()| is called, `SIGTERM` will be sent to the job. If a job does -not exit after 2 seconds, `SIGKILL` will be sent. - ============================================================================== vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt index 7af6e401da..a1453a6cc6 100644 --- a/runtime/doc/msgpack_rpc.txt +++ b/runtime/doc/msgpack_rpc.txt @@ -175,7 +175,7 @@ contains information that makes this task easier (see also |rpc-types|): 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 reciever type is the type of the first argument. The method + `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 diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 4df08ca5fb..c2018fc511 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -6759,7 +6759,7 @@ A jump table for the options with a short description can be found at |Q_op|. Highlights of vertical separators are determined by the window to the left of the separator. The highlight of a tabpage in |tabline| is - determine by the last-focused window of the tabpage. Highlights of + determined by the last-focused window of the tabpage. Highlights of the popupmenu are determined by the current window. Highlights in the message area cannot be overridden. diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt index 02f3fcab6c..b806b08f95 100644 --- a/runtime/doc/provider.txt +++ b/runtime/doc/provider.txt @@ -133,8 +133,8 @@ registers. Nvim looks for these clipboard tools, in order of priority: - |g:clipboard| - pbcopy/pbpaste (macOS) - - xclip - - xsel (newer alternative to xclip) + - xsel (if $DISPLAY is set) + - xclip (if $DISPLAY is set) - lemonade (for SSH) https://github.com/pocke/lemonade - doitclient (for SSH) http://www.chiark.greenend.org.uk/~sgtatham/doit/ - win32yank (Windows) @@ -162,13 +162,11 @@ process has not died, the cached selection is applied. ============================================================================== X11 selection mechanism *clipboard-x11* *x11-selection* -The clipboard providers for X11 store text in what is known as "selections". -Selections are "owned" by an application, so when the application is closed, -the selection text is lost. - +X11 clipboard providers store text in "selections". Selections are owned by an +application, so when the application gets closed, the selection text is lost. The contents of selections are held by the originating application (e.g., upon -a copy), and only passed on to another application when that other application -asks for them (e.g., upon a paste). +a copy), and only passed to another application when that other application +requests them (e.g., upon a paste). *quoteplus* *quote+* diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index c92fcd8994..6959d64989 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -60,14 +60,17 @@ a complete and centralized reference of those differences. MAJOR COMPONENTS ~ -Embedded terminal emulator |terminal| -RPC API |RPC| -Shared data |shada| -XDG base directories |xdg| +API |API| +Lua scripting |lua| Job control |job-control| Remote plugins |remote-plugin| -Python plugins |provider-python| -Clipboard integration |provider-clipboard| +Providers + Clipboard |provider-clipboard| + Python plugins |provider-python| + Ruby plugins |provider-ruby| +Shared data |shada| +Embedded terminal |terminal| +XDG base directories |xdg| USER EXPERIENCE ~ @@ -87,6 +90,16 @@ Working intuitively and consistently is a major goal of Nvim. - Vim's internal test functions (test_autochdir(), test_settime(), etc.) are not exposed (nor implemented); instead Nvim has a robust API. +- Behaviors, options, documentation are removed if they cost users more time + than they save. + +Usability details have been improved where the benefit outweighs any +backwards-compatibility cost. Some examples: + +- |K| in help documents can be used like |CTRL-]|. +- Directories for 'directory' and 'undodir' are auto-created. +- Terminal features such as 'guicursor' are enabled where possible. + ARCHITECTURE ~ External plugins run in separate processes. |remote-plugin| This improves @@ -130,6 +143,7 @@ Commands: |:checkhealth| |:drop| is available on all platforms |:Man| is available by default, with many improvements such as completion + |:tchdir| tab-local |current-directory| Functions: |dictwatcheradd()| notifies a callback whenever a |Dict| is modified diff --git a/runtime/plugin/man.vim b/runtime/plugin/man.vim index 63faa15213..7bccd4a3b9 100644 --- a/runtime/plugin/man.vim +++ b/runtime/plugin/man.vim @@ -5,7 +5,7 @@ if exists('g:loaded_man') endif let g:loaded_man = 1 -command! -range=0 -complete=customlist,man#complete -nargs=* Man call man#open_page(v:count, v:count1, <q-mods>, <f-args>) +command! -bar -range=0 -complete=customlist,man#complete -nargs=* Man call man#open_page(v:count, v:count1, <q-mods>, <f-args>) augroup man autocmd! diff --git a/scripts/gen_api_vimdoc.py b/scripts/gen_api_vimdoc.py index 4dcb42d685..51e585a007 100644 --- a/scripts/gen_api_vimdoc.py +++ b/scripts/gen_api_vimdoc.py @@ -38,6 +38,10 @@ import subprocess from xml.dom import minidom +if sys.version_info[0] < 3: + print("use Python 3") + sys.exit(1) + doc_filename = 'api.txt' # String used to find the start of the generated part of the doc. section_start_token = '*api-global*' @@ -69,7 +73,7 @@ text_width = 78 script_path = os.path.abspath(__file__) base_dir = os.path.dirname(os.path.dirname(script_path)) src_dir = os.path.join(base_dir, 'src/nvim/api') -out_dir = os.path.join(base_dir, 'tmp/api_doc') +out_dir = os.path.join(base_dir, 'tmp-api-doc') filter_cmd = '%s %s' % (sys.executable, script_path) seen_funcs = set() @@ -217,7 +221,12 @@ def parse_para(parent, width=62): width=width) + '\n') elif child.nodeName == 'simplesect': kind = child.getAttribute('kind') - if kind == 'return': + if kind == 'note': + lines.append('Note:') + lines.append(doc_wrap(parse_para(child), + prefix=' ', + width=width)) + elif kind == 'return': lines.append('%s:~' % kind.title()) lines.append(doc_wrap(parse_para(child), prefix=' ', @@ -280,14 +289,19 @@ def parse_source_xml(filename): parts = return_type.strip('_').split('_') return_type = '%s(%s)' % (parts[0], ', '.join(parts[1:])) + name = get_text(get_child(member, 'name')) + annotations = get_text(get_child(member, 'argsstring')) if annotations and ')' in annotations: annotations = annotations.rsplit(')', 1)[-1].strip() + # XXX: (doxygen 1.8.11) 'argsstring' only includes FUNC_ATTR_* + # attributes if the function signature is non-void. + # Force attributes here for such functions. + if name == 'nvim_get_mode' and len(annotations) == 0: + annotations += 'FUNC_API_ASYNC' annotations = filter(None, map(lambda x: annotation_map.get(x), annotations.split())) - name = get_text(get_child(member, 'name')) - vimtag = '*%s()*' % name args = [] type_length = 0 diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index c381e92dc7..4b6a88e5fa 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -439,6 +439,7 @@ Object nvim_buf_get_var(Buffer buffer, String name, Error *err) /// Gets a changed tick of a buffer /// /// @param[in] buffer Buffer handle. +/// @param[out] err Error details, if any /// /// @return `b:changedtick` value. Integer nvim_buf_get_changedtick(Buffer buffer, Error *err) @@ -453,14 +454,14 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err) return buf->b_changedtick; } -/// Get a list of dictionaries describing buffer-local mappings -/// Note that the buffer key in the dictionary will represent the buffer -/// handle where the mapping is present +/// Gets a list of dictionaries describing buffer-local mappings. +/// The "buffer" key in the returned dictionary reflects the buffer +/// handle where the mapping is present. /// -/// @param mode The abbreviation for the mode -/// @param buffer_id Buffer handle +/// @param mode Mode short-name ("n", "i", "v", ...) +/// @param buffer Buffer handle /// @param[out] err Error details, if any -/// @returns An array of maparg() like dictionaries describing mappings +/// @returns Array of maparg()-like dictionaries describing mappings ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err) FUNC_API_SINCE(3) { @@ -739,29 +740,29 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) /// Adds a highlight to buffer. /// -/// This can be used for plugins which dynamically generate highlights to a -/// buffer (like a semantic highlighter or linter). The function adds a single +/// Useful for plugins that dynamically generate highlights to a buffer +/// (like a semantic highlighter or linter). The function adds a single /// highlight to a buffer. Unlike matchaddpos() highlights follow changes to /// line numbering (as lines are inserted/removed above the highlighted line), /// like signs and marks do. /// -/// "src_id" is useful for batch deletion/updating of a set of highlights. When -/// called with src_id = 0, an unique source id is generated and returned. -/// Succesive calls can pass in it as "src_id" to add new highlights to the same -/// source group. All highlights in the same group can then be cleared with -/// nvim_buf_clear_highlight. If the highlight never will be manually deleted -/// pass in -1 for "src_id". +/// `src_id` is useful for batch deletion/updating of a set of highlights. When +/// called with `src_id = 0`, an unique source id is generated and returned. +/// Successive calls can pass that `src_id` to associate new highlights with +/// the same source group. All highlights in the same group can be cleared +/// with `nvim_buf_clear_highlight`. If the highlight never will be manually +/// deleted, pass `src_id = -1`. /// -/// If "hl_group" is the empty string no highlight is added, but a new src_id +/// If `hl_group` is the empty string no highlight is added, but a new `src_id` /// is still returned. This is useful for an external plugin to synchrounously -/// request an unique src_id at initialization, and later asynchronously add and -/// clear highlights in response to buffer changes. +/// request an unique `src_id` at initialization, and later asynchronously add +/// and clear highlights in response to buffer changes. /// /// @param buffer Buffer handle /// @param src_id Source group to use or 0 to use a new group, /// or -1 for ungrouped highlight /// @param hl_group Name of the highlight group to use -/// @param line Line to highlight +/// @param line Line to highlight (zero-indexed) /// @param col_start Start of range of columns to highlight /// @param col_end End of range of columns to highlight, /// or -1 to highlight to end of line diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 98f4410347..e5ec018795 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -166,7 +166,10 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi) /// On VimL error: Does not fail, but updates v:errmsg. /// /// Unlike `nvim_feedkeys`, this uses a lower-level input buffer and the call -/// is not deferred. This is the most reliable way to emulate real user input. +/// is not deferred. This is the most reliable way to send real user input. +/// +/// @note |keycodes| like <CR> are translated, so "<" is special. +/// To input a literal "<", send <LT>. /// /// @param keys to be typed /// @return Number of bytes actually written (can be fewer than @@ -320,15 +323,15 @@ Object nvim_execute_lua(String code, Array args, Error *err) /// @param text Some text /// @param[out] err Error details, if any /// @return Number of cells -Integer nvim_strwidth(String str, Error *err) +Integer nvim_strwidth(String text, Error *err) FUNC_API_SINCE(1) { - if (str.size > INT_MAX) { + if (text.size > INT_MAX) { api_set_error(err, kErrorTypeValidation, "String length is too high"); return 0; } - return (Integer) mb_string2cells((char_u *) str.data); + return (Integer)mb_string2cells((char_u *)text.data); } /// Gets the paths contained in 'runtimepath'. @@ -578,7 +581,7 @@ Buffer nvim_get_current_buf(void) /// Sets the current buffer /// -/// @param id Buffer handle +/// @param buffer Buffer handle /// @param[out] err Error details, if any void nvim_set_current_buf(Buffer buffer, Error *err) FUNC_API_SINCE(1) @@ -632,7 +635,7 @@ Window nvim_get_current_win(void) /// Sets the current window /// -/// @param handle Window handle +/// @param window Window handle void nvim_set_current_win(Window window, Error *err) FUNC_API_SINCE(1) { @@ -685,7 +688,7 @@ Tabpage nvim_get_current_tabpage(void) /// Sets the current tabpage /// -/// @param handle Tabpage handle +/// @param tabpage Tabpage handle /// @param[out] err Error details, if any void nvim_set_current_tabpage(Tabpage tabpage, Error *err) FUNC_API_SINCE(1) @@ -755,9 +758,8 @@ Dictionary nvim_get_color_map(void) } -/// Gets the current mode. -/// mode: Mode string. |mode()| -/// blocking: true if Nvim is waiting for input. +/// Gets the current mode. |mode()| +/// "blocking" is true if Nvim is waiting for input. /// /// @returns Dictionary { "mode": String, "blocking": Boolean } Dictionary nvim_get_mode(void) @@ -773,11 +775,11 @@ Dictionary nvim_get_mode(void) return rv; } -/// Get a list of dictionaries describing global (i.e. non-buffer) mappings -/// Note that the "buffer" key will be 0 to represent false. +/// Gets a list of dictionaries describing global (non-buffer) mappings. +/// The "buffer" key in the returned dictionary is always zero. /// -/// @param mode The abbreviation for the mode -/// @returns An array of maparg() like dictionaries describing mappings +/// @param mode Mode short-name ("n", "i", "v", ...) +/// @returns Array of maparg()-like dictionaries describing mappings ArrayOf(Dictionary) nvim_get_keymap(String mode) FUNC_API_SINCE(3) { diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 16bb4169c4..8e7b8a1824 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -336,8 +336,8 @@ static lua_State *nlua_init(void) /// Calls nlua_init() if needed. Is responsible for pre-lua call initalization /// like updating `package.[c]path` with directories derived from &runtimepath. /// -/// @return Interprter instance to use. Will either be initialized now or taken -/// from previous initalization. +/// @return Interpreter instance to use. Will either be initialized now or +/// taken from previous initialization. static lua_State *nlua_enter(void) FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT { diff --git a/src/nvim/ops.c b/src/nvim/ops.c index c6df71ea46..432c9a8b47 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -2735,7 +2735,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) // Autocommands may be executed when saving lines for undo, which may make // y_array invalid. Start undo now to avoid that. if (u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1) == FAIL) { - ELOG(_("Failed to save undo information")); + ELOG("Failed to save undo information"); return; } } diff --git a/test/README.md b/test/README.md index 01db5960cd..44558f0981 100644 --- a/test/README.md +++ b/test/README.md @@ -1,31 +1,48 @@ -# Tests +Tests +===== Tests are run by `/cmake/RunTests.cmake` file, using busted. For some failures, `.nvimlog` (or `$NVIM_LOG_FILE`) may provide insight. -## Directory structure +Lint +---- -Directories with tests: `/test/benchmark` for benchmarks, `/test/functional` for -functional tests, `/test/unit` for unit tests. `/test/config` contains `*.in` -files (currently a single one) which are transformed into `*.lua` files using -`configure_file` CMake command: this is for acessing CMake variables in lua -tests. `/test/includes` contains include files for use by luajit `ffi.cdef` -C definitions parser: normally used to make macros not accessible via this -mechanism accessible the other way. +`make lint` (and `make testlint`) runs [luacheck](https://github.com/mpeterv/luacheck) +on the test code. -Files `/test/*/preload.lua` contain modules which will be preloaded by busted, -via `--helper` option. `/test/**/helpers.lua` contain various “library” -functions, (intended to be) used by a number of tests and not just a single one. +If a luacheck warning must be ignored, specify the warning code. Example: -`/test/*/**/*_spec.lua` are files containing actual tests. Files that do not end -with a `_spec.lua` are libraries like `/test/**/helpers.lua`, except that they -have some common topic. + -- luacheck: ignore 621 -Tests inside `/test/unit` and `/test/functional` are normally divided into -groups by the semantic component they are testing. +http://luacheck.readthedocs.io/en/stable/warnings.html -## Environment variables +Ignore the smallest applicable scope (e.g. inside a function, not at the top of +the file). + +Layout +------ + +- `/test/benchmark` : benchmarks +- `/test/functional` : functional tests +- `/test/unit` : unit tests +- `/test/config` : contains `*.in` files which are transformed into `*.lua` + files using `configure_file` CMake command: this is for acessing CMake + variables in lua tests. +- `/test/includes` : include-files for use by luajit `ffi.cdef` C definitions + parser: normally used to make macros not accessible via this mechanism + accessible the other way. +- `/test/*/preload.lua` : modules preloaded by busted `--helper` option +- `/test/**/helpers.lua` : common utility functions for test code +- `/test/*/**/*_spec.lua` : actual tests. Files that do not end with + `_spec.lua` are libraries like `/test/**/helpers.lua`, except that they have + some common topic. + +Tests in `/test/unit` and `/test/functional` are normally divided into groups +by the semantic component they are testing. + +Environment variables +--------------------- Test behaviour is affected by environment variables. Currently supported (Functional, Unit, Benchmarks) (when Defined; when set to _1_; when defined, |