aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2020-01-01 06:30:29 -0800
committerGitHub <noreply@github.com>2020-01-01 06:30:29 -0800
commit070bd3ea231b6b98c9e9f1057fdbcf31d1877a70 (patch)
tree93d5aeb26b595e77041a6b2e73b32e8f1015bfc0
parent99eca048357b8ec72e84b45d21c2a38e25ed6ec0 (diff)
parentac6ebfcc1db8daf30533c42d5c4246bb95ec3d85 (diff)
downloadrneovim-070bd3ea231b6b98c9e9f1057fdbcf31d1877a70.tar.gz
rneovim-070bd3ea231b6b98c9e9f1057fdbcf31d1877a70.tar.bz2
rneovim-070bd3ea231b6b98c9e9f1057fdbcf31d1877a70.zip
Merge #11604 "LSP: shrink API, improve docs"
-rw-r--r--README.md17
-rw-r--r--runtime/doc/api.txt9
-rw-r--r--runtime/doc/eval.txt4
-rw-r--r--runtime/doc/intro.txt2
-rw-r--r--runtime/doc/lsp.txt1116
-rw-r--r--runtime/doc/map.txt5
-rw-r--r--runtime/doc/message.txt9
-rw-r--r--runtime/doc/motion.txt6
-rw-r--r--runtime/doc/options.txt10
-rw-r--r--runtime/doc/vim_diff.txt32
-rw-r--r--runtime/lua/vim/lsp.lua430
-rw-r--r--runtime/lua/vim/lsp/protocol.lua4
-rw-r--r--runtime/lua/vim/lsp/rpc.lua7
-rwxr-xr-xscripts/gen_vimdoc.py162
-rw-r--r--scripts/lua2dox.lua97
-rw-r--r--src/nvim/mark.c14
-rw-r--r--test/functional/normal/jump_spec.lua2
-rw-r--r--test/functional/plugin/lsp/lsp_spec.lua89
18 files changed, 1247 insertions, 768 deletions
diff --git a/README.md b/README.md
index 2249891235..f9a9a7fe8b 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,7 @@
[![Neovim](https://raw.githubusercontent.com/neovim/neovim.github.io/master/logos/neovim-logo-300x87.png)](https://neovim.io)
-[Wiki](https://github.com/neovim/neovim/wiki) |
[Documentation](https://neovim.io/doc) |
-[Chat/Discussion](https://gitter.im/neovim/neovim) |
+[Chat](https://gitter.im/neovim/neovim) |
[Twitter](https://twitter.com/Neovim)
[![Travis build status](https://travis-ci.org/neovim/neovim.svg?branch=master)](https://travis-ci.org/neovim/neovim)
@@ -114,17 +113,9 @@ Project layout
License
-------
-Neovim is licensed under the terms of the Apache 2.0 license, except for
-parts that were contributed under the Vim license.
-
-- Contributions committed before [b17d96][license-commit] remain under the Vim
- license.
-
-- Contributions committed after [b17d96][license-commit] are licensed under
- Apache 2.0 unless those contributions were copied from Vim (identified in
- the commit logs by the `vim-patch` token).
-
-See `LICENSE` for details.
+Neovim contributions since [b17d96][license-commit] are licensed under the
+Apache 2.0 license, except for contributions copied from Vim (identified by the
+`vim-patch` token). See LICENSE for details.
Vim is Charityware. You can use and copy it as much as you like, but you are
encouraged to make a donation for needy children in Uganda. Please see the
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 7d45330b66..f8fdd64a9b 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -569,7 +569,8 @@ nvim_call_atomic({calls}) *nvim_call_atomic()*
occurred, the values from all preceding calls will still
be returned.
-nvim_call_dict_function({dict}, {fn}, {args}) *nvim_call_dict_function()*
+ *nvim_call_dict_function()*
+nvim_call_dict_function({dict}, {fn}, {args})
Calls a VimL |Dictionary-function| with the given arguments.
On execution error: fails with VimL error, does not update
@@ -1878,7 +1879,8 @@ nvim_buf_get_var({buffer}, {name}) *nvim_buf_get_var()*
Return: ~
Variable value
-nvim_buf_get_virtual_text({buffer}, {lnum}) *nvim_buf_get_virtual_text()*
+ *nvim_buf_get_virtual_text()*
+nvim_buf_get_virtual_text({buffer}, {lnum})
Get the virtual text (annotation) for a buffer line.
The virtual text is returned as list of lists, whereas the
@@ -2300,7 +2302,8 @@ nvim_tabpage_list_wins({tabpage}) *nvim_tabpage_list_wins()*
Return: ~
List of windows in `tabpage`
-nvim_tabpage_set_var({tabpage}, {name}, {value}) *nvim_tabpage_set_var()*
+ *nvim_tabpage_set_var()*
+nvim_tabpage_set_var({tabpage}, {name}, {value})
Sets a tab-scoped (t:) variable
Parameters: ~
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index fecb8b5f74..960a42ecbf 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -3771,8 +3771,8 @@ feedkeys({string} [, {mode}]) *feedkeys()*
and "\..." notation |expr-quote|. For example,
feedkeys("\<CR>") simulates pressing of the <Enter> key. But
feedkeys('\<CR>') pushes 5 characters.
- A special code that might be useful is <Ignore>, it exits the
- wait for a character without doing anything. *<Ignore>*
+ The |<Ignore>| keycode may be used to exit the
+ wait-for-character without doing anything.
{mode} is a String, which can contain these character flags:
'm' Remap keys. This is default. If {mode} is absent,
diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt
index c59ed43a47..3c3753df78 100644
--- a/runtime/doc/intro.txt
+++ b/runtime/doc/intro.txt
@@ -339,6 +339,8 @@ notation meaning equivalent decimal value(s) ~
<EOL> end-of-line (can be <CR>, <LF> or <CR><LF>,
depends on system and 'fileformat') *<EOL>*
+<Ignore> cancel wait-for-character *<Ignore>*
+<NOP> no-op: do nothing (useful in mappings) *<Nop>*
<Up> cursor-up *cursor-up* *cursor_up*
<Down> cursor-down *cursor-down* *cursor_down*
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index d6d16b8481..70a3110042 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -1,36 +1,45 @@
-*lsp.txt* Nvim LSP API
+*lsp.txt* LSP
- NVIM REFERENCE MANUAL
+ NVIM REFERENCE MANUAL
-Nvim Language Server Protocol (LSP) API *lsp*
-Nvim is a client to the Language Server Protocol:
+LSP client/framework *lsp*
+Nvim supports the Language Server Protocol (LSP), which means it acts as
+a client to LSP servers and includes a Lua framework `vim.lsp` for building
+enhanced LSP tools.
https://microsoft.github.io/language-server-protocol/
+LSP facilitates features like go-to-definition, find-references, hover,
+completion, rename, format, refactor, etc., using semantic whole-project
+analysis (unlike |ctags|).
+
Type |gO| to see the table of contents.
-================================================================================
-LANGUAGE SERVER PROTOCOL (LSP) CLIENT *lsp-intro*
+==============================================================================
+QUICKSTART *lsp-quickstart*
-The `vim.lsp` Lua module provides a flexible API for consuming LSP servers.
+Nvim provides a LSP client, but the servers are provided by third parties.
+Follow these steps to get LSP features:
-To use LSP in practice, a language server must be installed.
- https://microsoft.github.io/language-server-protocol/implementors/servers/
+ 1. Install the nvim-lsp plugin. It provides common configuration for
+ various servers so you can get started quickly.
+ https://github.com/neovim/nvim-lsp
+ 2. Install a language server. Try ":LspInstall <tab>" or use your system
+ package manager to install the relevant language server:
+ https://microsoft.github.io/language-server-protocol/implementors/servers/
+ 3. Add `nvim_lsp.xx.setup{…}` to your vimrc, where "xx" is the name of the
+ relevant config. See the nvim-lsp README for details.
-After installing a language server to your machine, you must tell Nvim how to
-start and interact with that language server.
-- Easy way: use the configs provided here by the nvim-lsp plugin.
- https://github.com/neovim/nvim-lsp
-- Low-level way: use |vim.lsp.start_client()| and |vim.lsp.buf_attach_client()|
- directly. Useful if you want to build advanced LSP plugins based on the
- Nvim LSP module. |lsp-advanced-js-example|
+To check LSP clients attached to the current buffer: >
+ :lua print(vim.inspect(vim.lsp.buf_get_clients()))
+<
*lsp-config*
-Nvim LSP client will automatically provide inline diagnostics when available.
-|lsp-callbacks| But you probably want to use other features too, such as
-go-to-definition, "hover", etc. Example config: >
+Inline diagnostics are enabled automatically, e.g. syntax errors will be
+annotated in the buffer. But you probably want to use other features like
+go-to-definition, hover, etc. Example config: >
nnoremap <silent> gd <cmd>lua vim.lsp.buf.declaration()<CR>
nnoremap <silent> <c-]> <cmd>lua vim.lsp.buf.definition()<CR>
@@ -38,9 +47,8 @@ go-to-definition, "hover", etc. Example config: >
nnoremap <silent> gD <cmd>lua vim.lsp.buf.implementation()<CR>
nnoremap <silent> <c-k> <cmd>lua vim.lsp.buf.signature_help()<CR>
nnoremap <silent> 1gD <cmd>lua vim.lsp.buf.type_definition()<CR>
+ nnoremap <silent> gr <cmd>lua vim.lsp.buf.references()<CR>
-<
- *vim.lsp.omnifunc()*
Nvim provides the vim.lsp.omnifunc 'omnifunc' handler which allows
|i_CTRL-X_CTRL-O| to consume LSP completion features. Example config (note the
use of |v:lua| to call Lua from Vimscript): >
@@ -69,240 +77,24 @@ Some other plugin may be overriding the option. To avoid that, you could set
the option in an |after-directory| ftplugin, e.g. "after/ftplugin/python.vim".
================================================================================
- *lsp-core-api*
-These are the core api functions for working with clients. You will mainly be
-using |vim.lsp.start_client()| and |vim.lsp.buf_attach_client()| for operations
-and |vim.lsp.get_client_by_id()| to retrieve a client by its id after it has
-initialized (or {config.on_init}. see below)
-
- *vim.lsp.start_client()*
-
-vim.lsp.start_client({config})
-
- The main function used for starting clients.
- Start a client and initialize it.
-
- Its arguments are passed via a configuration object {config}.
-
- Mandatory parameters:~
-
- `root_dir`
- {string} specifying the directory where the LSP server will base
- as its rootUri on initialization.
-
- `cmd`
- {string} or {list} which is the base command to execute for the LSP. A
- string will be run using |'shell'| and a list will be interpreted as a
- bare command with arguments passed. This is the same as |jobstart()|.
-
- Optional parameters:~
-
- `cmd_cwd`
- {string} specifying the directory to launch the `cmd` process. This is not
- related to `root_dir`.
- By default, |getcwd()| is used.
-
- `cmd_env`
- {table} specifying the environment flags to pass to the LSP on spawn.
- This can be specified using keys like a map or as a list with `k=v` pairs
- or both. Non-string values are coerced to a string.
- For example:
- `{ "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }`
-
- `capabilities`
- A {table} which will be used instead of
- `vim.lsp.protocol.make_client_capabilities()` which contains Nvim's
- default capabilities and passed to the language server on initialization.
- You'll probably want to use make_client_capabilities() and modify the
- result.
- NOTE:
- To send an empty dictionary, you should use
- `{[vim.type_idx]=vim.types.dictionary}` Otherwise, it will be encoded as
- an array.
-
- `callbacks`
- A {table} of whose keys are language server method names and the values
- are `function(err, method, params, client_id)` See |lsp-callbacks| for
- more. This will be combined with |lsp-default-callbacks| to resolve
- the callbacks for a client as a fallback.
-
- `init_options`
- A {table} of values to pass in the initialization request as
- `initializationOptions`. See the `initialize` in the LSP spec.
-
- `name`
- A {string} used in log messages. Defaults to {client_id}
-
- `offset_encoding`
- One of "utf-8", "utf-16", or "utf-32" which is the encoding that the LSP
- server expects.
- The default encoding for Language Server Protocol is UTF-16, but there are
- language servers which may use other encodings.
- By default, it is "utf-16" as specified in the LSP specification. The
- client does not verify this is correct.
-
- `on_error(code, ...)`
- A function for handling errors thrown by client operation. {code} is a
- number describing the error. Other arguments may be passed depending on
- the error kind. See |vim.lsp.client_errors| for possible errors.
- `vim.lsp.client_errors[code]` can be used to retrieve a human
- understandable string.
-
- `before_init(initialize_params, config)`
- A function which is called *before* the request `initialize` is completed.
- `initialize_params` contains the parameters we are sending to the server
- and `config` is the config that was passed to `start_client()` for
- convenience. You can use this to modify parameters before they are sent.
-
- `on_init(client, initialize_result)`
- A function which is called after the request `initialize` is completed.
- `initialize_result` contains `capabilities` and anything else the server
- may send. For example, `clangd` sends `initialize_result.offsetEncoding`
- if `capabilities.offsetEncoding` was sent to it. You can *only* modify the
- `client.offset_encoding` here before any notifications are sent.
-
- `on_attach(client, bufnr)`
- A function which is called after the client is attached to a buffer.
-
- `on_exit(code, signal, client_id)`
- A function which is called after the client has exited. code is the exit
- code of the process, and signal is a number describing the signal used to
- terminate (if any).
-
- `trace`
- "off" | "messages" | "verbose" | nil passed directly to the language
- server in the initialize request.
- Invalid/empty values will default to "off"
-
- Returns:~
- {client_id}
- You can use |vim.lsp.get_client_by_id()| to get the actual client object.
- See |lsp-client| for what the client structure will be.
-
- NOTE: The client is only available *after* it has been initialized, which
- may happen after a small delay (or never if there is an error). For this
- reason, you may want to use `on_init` to do any actions once the client has
- been initialized.
-
- *lsp-client*
-
-The client object has some methods and members related to using the client.
-
- Methods:~
-
- `request(method, params, [callback])`
- Send a request to the server. If callback is not specified, it will use
- {client.callbacks} to try to find a callback. If one is not found there,
- then an error will occur.
- This is a thin wrapper around {client.rpc.request} with some additional
- checking.
- Returns a boolean to indicate if the notification was successful. If it
- is false, then it will always be false (the client has shutdown).
- If it was successful, then it will return the request id as the second
- result. You can use this with `notify("$/cancel", { id = request_id })`
- to cancel the request. This helper is made automatically with
- |vim.lsp.buf_request()|
- Returns: status, [client_id]
-
- `notify(method, params)`
- This is just {client.rpc.notify}()
- Returns a boolean to indicate if the notification was successful. If it
- is false, then it will always be false (the client has shutdown).
- Returns: status
-
- `cancel_request(id)`
- This is just {client.rpc.notify}("$/cancelRequest", { id = id })
- Returns the same as `notify()`.
-
- `stop([force])`
- Stop a client, optionally with force.
- By default, it will just ask the server to shutdown without force.
- If you request to stop a client which has previously been requested to
- shutdown, it will automatically escalate and force shutdown.
-
- `is_stopped()`
- Returns true if the client is fully stopped.
-
- Members: ~
- `id` (number)
- The id allocated to the client.
-
- `name` (string)
- If a name is specified on creation, that will be used. Otherwise it is
- just the client id. This is used for logs and messages.
-
- `offset_encoding` (string)
- The encoding used for communicating with the server. You can modify this
- in the `on_init` method before text is sent to the server.
-
- `callbacks` (table)
- The callbacks used by the client as described in |lsp-callbacks|.
-
- `config` (table)
- A copy of the table that was passed by the user to
- |vim.lsp.start_client()|.
-
- `server_capabilities` (table)
- The response from the server sent on `initialize` describing the
- server's capabilities.
-
- `resolved_capabilities` (table)
- A normalized table of capabilities that we have detected based on the
- initialize response from the server in `server_capabilities`.
-
-
- *vim.lsp.buf_attach_client()*
-vim.lsp.buf_attach_client({bufnr}, {client_id})
-
- Implements the `textDocument/did*` notifications required to track a buffer
- for any language server.
-
- Without calling this, the server won't be notified of changes to a buffer.
-
- *vim.lsp.get_client_by_id()*
-vim.lsp.get_client_by_id({client_id})
-
- Look up an active client by its id, returns nil if it is not yet initialized
- or is not a valid id. Returns |lsp-client|
-
- *vim.lsp.stop_client()*
-vim.lsp.stop_client({client_id}, [{force}])
+LSP API *lsp-api*
- Stop a client, optionally with force.
- By default, it will just ask the server to shutdown without force.
- If you request to stop a client which has previously been requested to
- shutdown, it will automatically escalate and force shutdown.
+The `vim.lsp` Lua module is a framework for building LSP plugins.
- You can also use `client.stop()` if you have access to the client.
+ 1. Start with |vim.lsp.start_client()| and |vim.lsp.buf_attach_client()|.
+ 2. Peek at the API: >
+ :lua print(vim.inspect(vim.lsp))
+< 3. See |lsp-extension-example| for a full example.
- *vim.lsp.stop_all_clients()*
-vim.lsp.stop_all_clients([{force}])
+LSP core API is described at |lsp-core|. Those are the core functions for
+creating and managing clients.
- |vim.lsp.stop_client()|, but for all active clients.
+The `vim.lsp.buf_…` functions perform operations for all LSP clients attached
+to the given buffer. |lsp-buf|
- *vim.lsp.get_active_clients()*
-vim.lsp.get_active_clients()
-
- Return a list of all of the active clients. See |lsp-client| for a
- description of what a client looks like.
-
- *vim.lsp.rpc_response_error()*
-vim.lsp.rpc_response_error({code}, [{message}], [{data}])
-
- Helper function to create an RPC response object/table. This is an alias for
- |vim.lsp.rpc.rpc_response_error|. Code must be an RPC error code as
- described in `vim.lsp.protocol.ErrorCodes`.
-
- You can describe an optional {message} string or arbitrary {data} to send to
- the server.
-
-================================================================================
-LSP CALLBACKS *lsp-callbacks*
-
-DEFAULT CALLBACKS ~
- *vim.lsp.callbacks*
-The `vim.lsp.callbacks` table defines default callbacks used when
-creating a new client. Keys are LSP method names: >
+LSP request/response handlers are implemented as Lua callbacks.
+|lsp-callbacks| The `vim.lsp.callbacks` table defines default callbacks used
+when creating a new client. Keys are LSP method names: >
:lua print(vim.inspect(vim.tbl_keys(vim.lsp.callbacks)))
@@ -314,7 +106,7 @@ These LSP requests/notifications are defined by default:
You can check these via `vim.tbl_keys(vim.lsp.callbacks)`.
-These will be used preferrentially in `vim.lsp.buf` methods when handling
+These will be used preferentially in `vim.lsp.buf_…` methods for handling
requests. They will also be used when responding to server requests and
notifications.
@@ -353,114 +145,24 @@ Handlers are called for:
- Handling requests initiated by the client if the request doesn't explicitly
specify a callback (such as in |vim.lsp.buf_request|).
-================================================================================
-VIM.LSP.PROTOCOL *vim.lsp.protocol*
-
-The `vim.lsp.protocol` module provides constants defined in the LSP
-specification, and helper functions for creating protocol-related objects.
-
- https://github.com/microsoft/language-server-protocol/raw/gh-pages/_specifications/specification-3-14.md
-
-Useful examples are `vim.lsp.protocol.ErrorCodes`. These objects allow reverse
-lookup by either the number or string name.
-
- e.g. vim.lsp.protocol.TextDocumentSyncKind.Full == 1
- vim.lsp.protocol.TextDocumentSyncKind[1] == "Full"
-
- Utility functions used internally are:
- `vim.lsp.protocol.make_client_capabilities()`
- Make a ClientCapabilities object. These are the builtin
- capabilities.
- `vim.lsp.protocol.resolve_capabilities(server_capabilites)`
- Creates a normalized object describing capabilities from the server
- capabilities.
-
-================================================================================
- *vim.lsp.util*
-
-TODO: Describe the utils here for handling/applying things from LSP.
-
-================================================================================
- *lsp-buf-methods*
-There are methods which operate on the buffer level for all of the active
-clients attached to the buffer.
-
- *vim.lsp.buf_request()*
-vim.lsp.buf_request({bufnr}, {method}, {params}, [{callback}])
- Send a async request for all the clients active and attached to the buffer.
-
- Parameters: ~
- {bufnr}: The buffer handle or 0 for the current buffer.
-
- {method}: The LSP method name.
-
- {params}: The parameters to send.
-
- {callback}: An optional `function(err, method, params, client_id)` which
- will be called for this request. If you do not specify it, then it will
- use the client's callback in {client.callbacks}. See |lsp-callbacks| for
- more information.
-
- Returns:~
-
- A table from client id to the request id for all of the successful
- requests.
- The second result is a function which can be used to cancel all the
- requests. You can do this individually with `client.cancel_request()`
-
- *vim.lsp.buf_request_sync()*
-vim.lsp.buf_request_sync({bufnr}, {method}, {params}, [{timeout_ms}])
- Calls |vim.lsp.buf_request()|, but it will wait for the result and block Vim
- in the process.
- The parameters are the same as |vim.lsp.buf_request()|, but the return
- result is different.
- It will wait maximum of {timeout_ms} which defaults to 100ms.
-
- Returns:~
-
- If the timeout is exceeded or a cancel is sent or an error, it will cancel
- the request and return `nil, err` where `err` is a string that describes
- the reason why it failed.
-
- If it is successful, it will return a table from client id to result id.
-
- *vim.lsp.buf_notify()*
-vim.lsp.buf_notify({bufnr}, {method}, {params})
- Send a notification to all servers on the buffer.
+VIM.LSP.PROTOCOL *vim.lsp.protocol*
- Parameters: ~
- {bufnr}: The buffer handle or 0 for the current buffer.
+Module `vim.lsp.protocol` defines constants dictated by the LSP specification,
+and helper functions for creating protocol-related objects.
+https://github.com/microsoft/language-server-protocol/raw/gh-pages/_specifications/specification-3-14.md
- {method}: The LSP method name.
+For example `vim.lsp.protocol.ErrorCodes` allows reverse lookup by number or
+name: >
- {params}: The parameters to send.
+ vim.lsp.protocol.TextDocumentSyncKind.Full == 1
+ vim.lsp.protocol.TextDocumentSyncKind[1] == "Full"
================================================================================
- *lsp-logging*
-
- *vim.lsp.set_log_level()*
-vim.lsp.set_log_level({level})
- You can set the log level for language server client logging.
- Possible values: "trace", "debug", "info", "warn", "error"
-
- Default: "warn"
-
- Example: `lua vim.lsp.set_log_level("debug")`
-
- *vim.lsp.get_log_path()*
-vim.lsp.get_log_path()
- Returns the path that LSP logs are written.
+LSP EXAMPLE *lsp-extension-example*
- *vim.lsp.log_levels*
-vim.lsp.log_levels
- Log level dictionary with reverse lookup as well.
-
- Can be used to lookup the number from the name or vice-versa.
- Levels: "trace" (0), "debug" (1), "info" (2), "warn" (3), "error" (4)
-
-================================================================================
-LSP EXAMPLE *lsp-advanced-js-example*
+This example is for plugin authors or users who want a lot of control. If you
+are just getting started see |lsp-quickstart|.
For more advanced configurations where just filtering by filetype isn't
sufficient, you can use the `vim.lsp.start_client()` and
@@ -572,4 +274,712 @@ The example will:
vim.api.nvim_command [[autocmd BufReadPost * lua check_start_javascript_lsp()]]
<
-vim:tw=78:ts=8:ft=help:norl:
+
+
+==============================================================================
+Lua module: vim.lsp *lsp-core*
+
+buf_attach_client({bufnr}, {client_id}) *vim.lsp.buf_attach_client()*
+ Implements the `textDocument/did…` notifications required to
+ track a buffer for any language server.
+
+ Without calling this, the server won't be notified of changes
+ to a buffer.
+
+ Parameters: ~
+ {bufnr} (number) Buffer handle, or 0 for current
+ {client_id} (number) Client id
+
+buf_get_clients({bufnr}) *vim.lsp.buf_get_clients()*
+ Gets a map of client_id:client pairs for the given buffer,
+ where each value is a |vim.lsp.client| object.
+
+ Parameters: ~
+ {bufnr} (optional, number): Buffer handle, or 0 for
+ current
+
+buf_get_full_text({bufnr}) *vim.lsp.buf_get_full_text()*
+ TODO: Documentation
+
+buf_is_attached({bufnr}, {client_id}) *vim.lsp.buf_is_attached()*
+ Checks if a buffer is attached for a particular client.
+
+ Parameters: ~
+ {bufnr} (number) Buffer handle, or 0 for current
+ {client_id} (number) the client id
+
+buf_notify({bufnr}, {method}, {params}) *vim.lsp.buf_notify()*
+ Sends a notification to all servers attached to the buffer.
+
+ Parameters: ~
+ {bufnr} (optional, number) Buffer handle, or 0 for
+ current
+ {method} (string) LSP method name
+ {params} (string) Parameters to send to the server
+
+ Return: ~
+ nil
+
+ *vim.lsp.buf_request()*
+buf_request({bufnr}, {method}, {params}, {callback})
+ Sends an async request for all active clients attached to the
+ buffer.
+
+ Parameters: ~
+ {bufnr} (number) Buffer handle, or 0 for current.
+ {method} (string) LSP method name
+ {params} (optional, table) Parameters to send to the
+ server
+ {callback} (optional, functionnil) Handler
+
+ Return: ~
+ 2-tuple:
+ • Map of client-id:request-id pairs for all successful
+ requests.
+ • Function which can be used to cancel all the requests.
+ You could instead iterate all clients and call their
+ `cancel_request()` methods.
+
+ *vim.lsp.buf_request_sync()*
+buf_request_sync({bufnr}, {method}, {params}, {timeout_ms})
+ Sends a request to a server and waits for the response.
+
+ Calls |vim.lsp.buf_request()| but blocks Nvim while awaiting
+ the result. Parameters are the same as |vim.lsp.buf_request()|
+ but the return result is different. Wait maximum of
+ {timeout_ms} (default 100) ms.
+
+ Parameters: ~
+ {bufnr} (number) Buffer handle, or 0 for current.
+ {method} (string) LSP method name
+ {params} (optional, table) Parameters to send to the
+ server
+ {timeout_ms} (optional, number, default=100) Maximum time
+ in milliseconds to wait for a result.
+
+ Return: ~
+ Map of client_id:request_result. On timeout, cancel or
+ error, returns `(nil, err)` where `err` is a string
+ describing the failure reason.
+
+cancel_request({id}) *vim.lsp.cancel_request()*
+ TODO: Documentation
+
+client() *vim.lsp.client*
+ LSP client object.
+
+ • Methods:
+ • request(method, params, [callback]) Send a request to the
+ server. If callback is not specified, it will use
+ {client.callbacks} to try to find a callback. If one is
+ not found there, then an error will occur. This is a thin
+ wrapper around {client.rpc.request} with some additional
+ checking. Returns a boolean to indicate if the
+ notification was successful. If it is false, then it will
+ always be false (the client has shutdown). If it was
+ successful, then it will return the request id as the
+ second result. You can use this with `notify("$/cancel", {
+ id = request_id })` to cancel the request. This helper is
+ made automatically with |vim.lsp.buf_request()| Returns:
+ status, [client_id]
+ • notify(method, params) This is just {client.rpc.notify}()
+ Returns a boolean to indicate if the notification was
+ successful. If it is false, then it will always be false
+ (the client has shutdown). Returns: status
+ • cancel_request(id) This is just
+ {client.rpc.notify}("$/cancelRequest", { id = id })
+ Returns the same as `notify()` .
+ • stop([force]) Stop a client, optionally with force. By
+ default, it will just ask the server to shutdown without
+ force. If you request to stop a client which has
+ previously been requested to shutdown, it will
+ automatically escalate and force shutdown.
+ • is_stopped() Returns true if the client is fully stopped.
+
+ • Members
+ • id (number): The id allocated to the client.
+ • name (string): If a name is specified on creation, that
+ will be used. Otherwise it is just the client id. This is
+ used for logs and messages.
+ • offset_encoding (string): The encoding used for
+ communicating with the server. You can modify this in the
+ `on_init` method before text is sent to the server.
+ • callbacks (table): The callbacks used by the client as
+ described in |lsp-callbacks|.
+ • config (table): copy of the table that was passed by the
+ user to |vim.lsp.start_client()|.
+ • server_capabilities (table): Response from the server sent
+ on `initialize` describing the server's capabilities.
+ • resolved_capabilities (table): Normalized table of
+ capabilities that we have detected based on the initialize
+ response from the server in `server_capabilities` .
+
+client_is_stopped({client_id}) *vim.lsp.client_is_stopped()*
+ TODO: Documentation
+
+err_message({...}) *vim.lsp.err_message()*
+ TODO: Documentation
+
+ *vim.lsp.for_each_buffer_client()*
+for_each_buffer_client({bufnr}, {callback})
+ TODO: Documentation
+
+get_active_clients() *vim.lsp.get_active_clients()*
+ Gets all active clients.
+
+ Return: ~
+ Table of |vim.lsp.client| objects
+
+get_client_by_id({client_id}) *vim.lsp.get_client_by_id()*
+ Gets an active client by id, or nil if the id is invalid or
+ the client is not yet initialized.
+
+ Parameters: ~
+ {client_id} client id number
+
+ Return: ~
+ |vim.lsp.client| object, or nil
+
+get_log_path() *vim.lsp.get_log_path()*
+ TODO: Documentation
+
+initialize() *vim.lsp.initialize()*
+ TODO: Documentation
+
+is_dir({filename}) *vim.lsp.is_dir()*
+ TODO: Documentation
+
+is_stopped() *vim.lsp.is_stopped()*
+ TODO: Documentation
+
+next_client_id() *vim.lsp.next_client_id()*
+ TODO: Documentation
+
+notification({method}, {params}) *vim.lsp.notification()*
+ TODO: Documentation
+
+notify({...}) *vim.lsp.notify()*
+ TODO: Documentation
+
+omnifunc({findstart}, {base}) *vim.lsp.omnifunc()*
+ TODO: Documentation
+
+on_error({code}, {err}) *vim.lsp.on_error()*
+ TODO: Documentation
+
+on_exit({code}, {signal}) *vim.lsp.on_exit()*
+ TODO: Documentation
+
+once({fn}) *vim.lsp.once()*
+ TODO: Documentation
+
+optional_validator({fn}) *vim.lsp.optional_validator()*
+ TODO: Documentation
+
+request({method}, {params}, {callback}) *vim.lsp.request()*
+ TODO: Documentation
+
+resolve_bufnr({bufnr}) *vim.lsp.resolve_bufnr()*
+ TODO: Documentation
+
+resolve_callback({method}) *vim.lsp.resolve_callback()*
+ TODO: Documentation
+
+server_request({method}, {params}) *vim.lsp.server_request()*
+ TODO: Documentation
+
+set_log_level({level}) *vim.lsp.set_log_level()*
+ Sets the global log level for LSP logging.
+
+ Levels by name: "trace", "debug", "info", "warn", "error"
+ Level numbers begin with "trace" at 0
+
+ Use `lsp.log_levels` for reverse lookup.
+
+ Parameters: ~
+ {level} [number|string] the case insensitive level name
+ or number
+
+ See also: ~
+ |vim.lsp.log_levels|
+
+start_client({config}) *vim.lsp.start_client()*
+ Starts and initializes a client with the given configuration.
+
+ Parameters `cmd` and `root_dir` are required.
+
+ Parameters: ~
+ {root_dir} (required, string) Directory where the
+ LSP server will base its rootUri on
+ initialization.
+ {cmd} (required, string or list treated like
+ |jobstart()|) Base command that
+ initiates the LSP client.
+ {cmd_cwd} (string, default=|getcwd()|) Directory
+ to launch the `cmd` process. Not
+ related to `root_dir` .
+ {cmd_env} (table) Environment flags to pass to
+ the LSP on spawn. Can be specified
+ using keys like a map or as a list with `k=v` pairs or both. Non-string values are
+ coerced to string. Example: >
+
+ { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
+<
+ {capabilities} Map overriding the default capabilities
+ defined by
+ |vim.lsp.protocol.make_client_capabilities()|,
+ passed to the language server on
+ initialization. Hint: use
+ make_client_capabilities() and modify
+ its result.
+ • Note: To send an empty dictionary use
+ `{[vim.type_idx]=vim.types.dictionary}`
+ , else it will be encoded as an
+ array.
+ {callbacks} Map of language server method names to `function(err, method, params,
+ client_id)` handler. Invoked for:
+ • Notifications from the server, where
+ `err` will always be `nil` .
+ • Requests initiated by the server. For
+ these you can respond by returning
+ two values: `result, err` where err
+ must be shaped like a RPC error, i.e.
+ `{ code, message, data? }` . Use
+ |vim.lsp.rpc_response_error()| to
+ help with this.
+ • Default callback for client requests
+ not explicitly specifying a callback.
+ {init_options} Values to pass in the initialization
+ request as `initializationOptions` .
+ See `initialize` in the LSP spec.
+ {name} (string, default=client-id) Name in log
+ messages.
+ {offset_encoding} (default="utf-16") One of "utf-8",
+ "utf-16", or "utf-32" which is the
+ encoding that the LSP server expects.
+ Client does not verify this is correct.
+ {on_error} Callback with parameters (code, ...),
+ invoked when the client operation
+ throws an error. `code` is a number
+ describing the error. Other arguments
+ may be passed depending on the error
+ kind. See |vim.lsp.client_errors| for
+ possible errors. Use
+ `vim.lsp.client_errors[code]` to get
+ human-friendly name.
+ {before_init} Callback with parameters
+ (initialize_params, config) invoked
+ before the LSP "initialize" phase,
+ where `params` contains the parameters
+ being sent to the server and `config`
+ is the config that was passed to
+ `start_client()` . You can use this to
+ modify parameters before they are sent.
+ {on_init} Callback (client, initialize_result)
+ invoked after LSP "initialize", where
+ `result` is a table of `capabilities`
+ and anything else the server may send.
+ For example, clangd sends
+ `initialize_result.offsetEncoding` if
+ `capabilities.offsetEncoding` was sent
+ to it. You can only modify the
+ `client.offset_encoding` here before
+ any notifications are sent.
+ {on_exit} Callback (code, signal, client_id)
+ invoked on client exit.
+ • code: exit code of the process
+ • signal: number describing the signal
+ used to terminate (if any)
+ • client_id: client handle
+ {on_attach} Callback (client, bufnr) invoked when
+ client attaches to a buffer.
+ {trace} "off" | "messages" | "verbose" | nil
+ passed directly to the language server
+ in the initialize request.
+ Invalid/empty values will default to
+ "off"
+
+ Return: ~
+ Client id. |vim.lsp.get_client_by_id()| Note: client is
+ only available after it has been initialized, which may
+ happen after a small delay (or never if there is an
+ error). Use `on_init` to do any actions once the client
+ has been initialized.
+
+stop({force}) *vim.lsp.stop()*
+ TODO: Documentation
+
+stop_client({client_id}, {force}) *vim.lsp.stop_client()*
+ Stops a client(s).
+
+ You can also use the `stop()` function on a |vim.lsp.client|
+ object. To stop all clients:
+>
+
+ vim.lsp.stop_client(lsp.get_active_clients())
+<
+
+ By default asks the server to shutdown, unless stop was
+ requested already for this client, then force-shutdown is
+ attempted.
+
+ Parameters: ~
+ {client_id} client id or |vim.lsp.client| object, or list
+ thereof
+ {force} boolean (optional) shutdown forcefully
+
+ *vim.lsp.text_document_did_open_handler()*
+text_document_did_open_handler({bufnr}, {client})
+ TODO: Documentation
+
+unsupported_method({method}) *vim.lsp.unsupported_method()*
+ TODO: Documentation
+
+validate_client_config({config}) *vim.lsp.validate_client_config()*
+ TODO: Documentation
+
+validate_command({input}) *vim.lsp.validate_command()*
+ TODO: Documentation
+
+validate_encoding({encoding}) *vim.lsp.validate_encoding()*
+ TODO: Documentation
+
+
+==============================================================================
+Lua module: vim.lsp.protocol *lsp-protocol*
+
+ifnil({a}, {b}) *vim.lsp.protocol.ifnil()*
+ TODO: Documentation
+
+ *vim.lsp.protocol.make_client_capabilities()*
+make_client_capabilities()
+ Gets a new ClientCapabilities object describing the LSP client
+ capabilities.
+
+ *vim.lsp.protocol.resolve_capabilities()*
+resolve_capabilities({server_capabilities})
+ `*` to match one or more characters in a path segment `?` to
+ match on one character in a path segment `**` to match any
+ number of path segments, including none `{}` to group
+ conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and
+ JavaScript files) `[]` to declare a range of characters to
+ match in a path segment (e.g., `example.[0-9]` to match on
+ `example.0` , `example.1` , …) `[!...]` to negate a range of
+ characters to match in a path segment (e.g., `example.[!0-9]`
+ to match on `example.a` , `example.b` , but not `example.0` )
+
+ *vim.lsp.protocol.transform_schema_comments()*
+transform_schema_comments()
+ TODO: Documentation
+
+ *vim.lsp.protocol.transform_schema_to_table()*
+transform_schema_to_table()
+ TODO: Documentation
+
+
+==============================================================================
+Lua module: vim.lsp.buf *lsp-buf*
+
+completion({context}) *vim.lsp.buf.completion()*
+ TODO: Documentation
+
+declaration() *vim.lsp.buf.declaration()*
+ TODO: Documentation
+
+definition() *vim.lsp.buf.definition()*
+ TODO: Documentation
+
+formatting({options}) *vim.lsp.buf.formatting()*
+ TODO: Documentation
+
+hover() *vim.lsp.buf.hover()*
+ TODO: Documentation
+
+implementation() *vim.lsp.buf.implementation()*
+ TODO: Documentation
+
+npcall({fn}, {...}) *vim.lsp.buf.npcall()*
+ TODO: Documentation
+
+ok_or_nil({status}, {...}) *vim.lsp.buf.ok_or_nil()*
+ TODO: Documentation
+
+peek_definition() *vim.lsp.buf.peek_definition()*
+ TODO: Documentation
+
+ *vim.lsp.buf.range_formatting()*
+range_formatting({options}, {start_pos}, {end_pos})
+ TODO: Documentation
+
+references({context}) *vim.lsp.buf.references()*
+ TODO: Documentation
+
+rename({new_name}) *vim.lsp.buf.rename()*
+ TODO: Documentation
+
+request({method}, {params}, {callback}) *vim.lsp.buf.request()*
+ TODO: Documentation
+
+signature_help() *vim.lsp.buf.signature_help()*
+ TODO: Documentation
+
+type_definition() *vim.lsp.buf.type_definition()*
+ TODO: Documentation
+
+
+==============================================================================
+Lua module: vim.lsp.callbacks *lsp-callbacks*
+
+err_message({...}) *vim.lsp.callbacks.err_message()*
+ TODO: Documentation
+
+ *vim.lsp.callbacks.location_callback()*
+location_callback({_}, {method}, {result})
+ TODO: Documentation
+
+ *vim.lsp.callbacks.log_message()*
+log_message({_}, {_}, {result}, {client_id})
+ TODO: Documentation
+
+ *vim.lsp.callbacks.signature_help_to_preview_contents()*
+signature_help_to_preview_contents({input})
+ TODO: Documentation
+
+
+==============================================================================
+Lua module: vim.lsp.log *lsp-log*
+
+get_filename() *vim.lsp.log.get_filename()*
+ TODO: Documentation
+
+path_join({...}) *vim.lsp.log.path_join()*
+ TODO: Documentation
+
+set_level({level}) *vim.lsp.log.set_level()*
+ TODO: Documentation
+
+should_log({level}) *vim.lsp.log.should_log()*
+ TODO: Documentation
+
+
+==============================================================================
+Lua module: vim.lsp.rpc *lsp-rpc*
+
+convert_NIL({v}) *vim.lsp.rpc.convert_NIL()*
+ TODO: Documentation
+
+ *vim.lsp.rpc.create_and_start_client()*
+create_and_start_client({cmd}, {cmd_args}, {handlers},
+ {extra_spawn_params})
+ TODO: Documentation
+
+encode_and_send({payload}) *vim.lsp.rpc.encode_and_send()*
+ TODO: Documentation
+
+force_env_list({final_env}) *vim.lsp.rpc.force_env_list()*
+ TODO: Documentation
+
+ *vim.lsp.rpc.format_message_with_content_length()*
+format_message_with_content_length({encoded_message})
+ TODO: Documentation
+
+format_rpc_error({err}) *vim.lsp.rpc.format_rpc_error()*
+ TODO: Documentation
+
+handle_body({body}) *vim.lsp.rpc.handle_body()*
+ TODO: Documentation
+
+is_dir({filename}) *vim.lsp.rpc.is_dir()*
+ TODO: Documentation
+
+json_decode({data}) *vim.lsp.rpc.json_decode()*
+ TODO: Documentation
+
+json_encode({data}) *vim.lsp.rpc.json_encode()*
+ TODO: Documentation
+
+notification({method}, {params}) *vim.lsp.rpc.notification()*
+ TODO: Documentation
+
+on_error({errkind}, {...}) *vim.lsp.rpc.on_error()*
+ TODO: Documentation
+
+on_exit({code}, {signal}) *vim.lsp.rpc.on_exit()*
+ TODO: Documentation
+
+onexit({code}, {signal}) *vim.lsp.rpc.onexit()*
+ TODO: Documentation
+
+parse_headers({header}) *vim.lsp.rpc.parse_headers()*
+ TODO: Documentation
+
+ *vim.lsp.rpc.pcall_handler()*
+pcall_handler({errkind}, {status}, {head}, {...})
+ TODO: Documentation
+
+request_parser_loop() *vim.lsp.rpc.request_parser_loop()*
+ TODO: Documentation
+
+ *vim.lsp.rpc.rpc_response_error()*
+rpc_response_error({code}, {message}, {data})
+ Creates an RPC response object/table.
+
+ Parameters: ~
+ {code} RPC error code defined in
+ `vim.lsp.protocol.ErrorCodes`
+ {message} (optional) arbitrary message to send to server
+ {data} (optional) arbitrary data to send to server
+
+send_notification({method}, {params}) *vim.lsp.rpc.send_notification()*
+ TODO: Documentation
+
+ *vim.lsp.rpc.send_request()*
+send_request({method}, {params}, {callback})
+ TODO: Documentation
+
+ *vim.lsp.rpc.send_response()*
+send_response({request_id}, {err}, {result})
+ TODO: Documentation
+
+server_request({method}, {params}) *vim.lsp.rpc.server_request()*
+ TODO: Documentation
+
+try_call({errkind}, {fn}, {...}) *vim.lsp.rpc.try_call()*
+ TODO: Documentation
+
+
+==============================================================================
+Lua module: vim.lsp.util *lsp-util*
+
+ *vim.lsp.util.apply_text_document_edit()*
+apply_text_document_edit({text_document_edit})
+ TODO: Documentation
+
+ *vim.lsp.util.apply_text_edits()*
+apply_text_edits({text_edits}, {bufnr})
+ TODO: Documentation
+
+ *vim.lsp.util.apply_workspace_edit()*
+apply_workspace_edit({workspace_edit})
+ TODO: Documentation
+
+buf_clear_diagnostics({bufnr}) *vim.lsp.util.buf_clear_diagnostics()*
+ TODO: Documentation
+
+ *vim.lsp.util.buf_diagnostics_save_positions()*
+buf_diagnostics_save_positions({bufnr}, {diagnostics})
+ TODO: Documentation
+
+ *vim.lsp.util.buf_diagnostics_underline()*
+buf_diagnostics_underline({bufnr}, {diagnostics})
+ TODO: Documentation
+
+ *vim.lsp.util.buf_diagnostics_virtual_text()*
+buf_diagnostics_virtual_text({bufnr}, {diagnostics})
+ TODO: Documentation
+
+character_offset({buf}, {row}, {col}) *vim.lsp.util.character_offset()*
+ TODO: Documentation
+
+ *vim.lsp.util.close_preview_autocmd()*
+close_preview_autocmd({events}, {winnr})
+ TODO: Documentation
+
+ *vim.lsp.util.convert_input_to_markdown_lines()*
+convert_input_to_markdown_lines({input}, {contents})
+ TODO: Documentation
+
+ *vim.lsp.util.extract_completion_items()*
+extract_completion_items({result})
+ TODO: Documentation
+
+ *vim.lsp.util.fancy_floating_markdown()*
+fancy_floating_markdown({contents}, {opts})
+ TODO: Documentation
+
+find_window_by_var({name}, {value}) *vim.lsp.util.find_window_by_var()*
+ TODO: Documentation
+
+focusable_float({unique_name}, {fn}) *vim.lsp.util.focusable_float()*
+ TODO: Documentation
+
+ *vim.lsp.util.focusable_preview()*
+focusable_preview({unique_name}, {fn})
+ TODO: Documentation
+
+ *vim.lsp.util.get_current_line_to_cursor()*
+get_current_line_to_cursor()
+ TODO: Documentation
+
+ *vim.lsp.util.get_severity_highlight_name()*
+get_severity_highlight_name({severity})
+ TODO: Documentation
+
+ *vim.lsp.util.highlight_range()*
+highlight_range({bufnr}, {ns}, {hiname}, {start}, {finish})
+ TODO: Documentation
+
+ *vim.lsp.util.highlight_region()*
+highlight_region({ft}, {start}, {finish})
+ TODO: Documentation
+
+jump_to_location({location}) *vim.lsp.util.jump_to_location()*
+ TODO: Documentation
+
+locations_to_items({locations}) *vim.lsp.util.locations_to_items()*
+ TODO: Documentation
+
+ *vim.lsp.util.make_floating_popup_options()*
+make_floating_popup_options({width}, {height}, {opts})
+ TODO: Documentation
+
+make_position_params() *vim.lsp.util.make_position_params()*
+ TODO: Documentation
+
+npcall({fn}, {...}) *vim.lsp.util.npcall()*
+ TODO: Documentation
+
+ok_or_nil({status}, {...}) *vim.lsp.util.ok_or_nil()*
+ TODO: Documentation
+
+ *vim.lsp.util.open_floating_peek_preview()*
+open_floating_peek_preview({bufnr}, {start}, {finish}, {opts})
+ TODO: Documentation
+
+ *vim.lsp.util.open_floating_preview()*
+open_floating_preview({contents}, {filetype}, {opts})
+ TODO: Documentation
+
+set_lines({lines}, {A}, {B}, {new_lines}) *vim.lsp.util.set_lines()*
+ TODO: Documentation
+
+set_loclist({locations}) *vim.lsp.util.set_loclist()*
+ TODO: Documentation
+
+set_qflist({locations}) *vim.lsp.util.set_qflist()*
+ TODO: Documentation
+
+show_line_diagnostics() *vim.lsp.util.show_line_diagnostics()*
+ TODO: Documentation
+
+sort_by_key({fn}) *vim.lsp.util.sort_by_key()*
+ TODO: Documentation
+
+split_lines({value}) *vim.lsp.util.split_lines()*
+ TODO: Documentation
+
+ *vim.lsp.util.text_document_completion_list_to_complete_items()*
+text_document_completion_list_to_complete_items({result})
+ TODO: Documentation
+
+trim_empty_lines({lines}) *vim.lsp.util.trim_empty_lines()*
+ TODO: Documentation
+
+ *vim.lsp.util.try_trim_markdown_code_blocks()*
+try_trim_markdown_code_blocks({lines})
+ TODO: Documentation
+
+validate_lsp_position({pos}) *vim.lsp.util.validate_lsp_position()*
+ TODO: Documentation
+
+ vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index 58c0d832e6..ed31ecc42e 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -522,10 +522,9 @@ single CTRL-V (you have to type CTRL-V two times).
You can create an empty {rhs} by typing nothing after a single CTRL-V (you
have to type CTRL-V two times). Unfortunately, you cannot do this in a vimrc
file.
- *<Nop>*
+ |<Nop>|
An easier way to get a mapping that doesn't produce anything, is to use
-"<Nop>" for the {rhs}. This only works when the |<>| notation is enabled.
-For example, to make sure that function key 8 does nothing at all: >
+"<Nop>" for the {rhs}. For example, to disable function key 8: >
:map <F8> <Nop>
:map! <F8> <Nop>
<
diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt
index bcfd985e71..98e45ac6da 100644
--- a/runtime/doc/message.txt
+++ b/runtime/doc/message.txt
@@ -671,21 +671,20 @@ being disabled. Remove the 'C' flag from the 'cpoptions' option to enable it.
*E471* >
Argument required
-This happens when an Ex command with mandatory argument(s) was executed, but
-no argument has been specified.
+Ex command was executed without a mandatory argument(s).
*E474* *E475* *E983* >
Invalid argument
Invalid argument: {arg}
Duplicate argument: {arg}
-Ex command or function has been executed, but an invalid argument was
-specified. Or a non-executable command was given to |system()|.
+Ex command or function was given an invalid argument. Or |jobstart()| or
+|system()| was given a non-executable command.
*E488* >
Trailing characters
-An argument has been added to an Ex command that does not permit one.
+An argument was given to an Ex command that does not permit one.
*E477* *E478* >
No ! allowed
diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt
index 3947e583b7..a6c072e489 100644
--- a/runtime/doc/motion.txt
+++ b/runtime/doc/motion.txt
@@ -1105,7 +1105,7 @@ Finally, navigate to a different webpage, new.com. The history is
- third.com
- new.com <--
-When the jumpoptions includes "stack", this is the behavior of neovim as well.
+When the jumpoptions includes "stack", this is the behavior of Nvim as well.
That is, given a jumplist like the following in which CTRL-O has been used to
move back three times to location X
@@ -1117,8 +1117,8 @@ move back three times to location X
2 213 2 src/nvim/mark.c
3 181 0 src/nvim/mark.c
-jumping to location Y results in the locations after the current locations being
-removed:
+jumping to (new) location Y results in the locations after the current
+locations being removed:
jump line col file/text
3 1260 8 src/nvim/mark.c
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 4b832a8606..494a265338 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4543,15 +4543,15 @@ A jump table for the options with a short description can be found at |Q_op|.
*'pumheight'* *'ph'*
'pumheight' 'ph' number (default 0)
global
- Determines the maximum number of items to show in the popup menu for
- Insert mode completion. When zero as much space as available is used.
- |ins-completion-menu|.
+ Maximum number of items to show in the popup menu
+ (|ins-completion-menu|). Zero means "use available screen space".
*'pumwidth'* *'pw'*
'pumwidth' 'pw' number (default 15)
global
- Determines the minium width to use for the popup menu for Insert mode
- completion. |ins-completion-menu|.
+ Minimum width for the popup menu (|ins-completion-menu|). If the
+ cursor column + 'pumwidth' exceeds screen width, the popup menu is
+ nudged to fit on the screen.
*'pyxversion'* *'pyx'*
'pyxversion' 'pyx' number (default depends on the build)
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 64b5830575..e19659a4c4 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -195,20 +195,20 @@ Normal commands:
"Outline": Type |gO| in |:Man| and |:help| pages to see a document outline.
Options:
- 'cpoptions' flags: |cpo-_|
- 'display' flag `msgsep` to minimize scrolling when showing messages
- 'guicursor' works in the terminal
- 'fillchars' local to window. flags: `msgsep` (see 'display' above) and `eob`
- for |hl-EndOfBuffer| marker
- 'inccommand' shows interactive results for |:substitute|-like commands
- 'listchars' local to window
- 'pumblend' pseudo-transparent popupmenu
+ 'cpoptions' flags: |cpo-_|
+ 'display' flags: "msgsep" minimizes scrolling when showing messages
+ 'guicursor' works in the terminal
+ 'fillchars' flags: "msgsep" (see 'display'), "eob" for |hl-EndOfBuffer|
+ marker, "foldopen", "foldsep", "foldclose"
+ 'inccommand' shows interactive results for |:substitute|-like commands
+ 'listchars' local to window
+ 'pumblend' pseudo-transparent popupmenu
'scrollback'
- 'signcolumn' supports up to 9 dynamic/fixed columns
- 'statusline' supports unlimited alignment sections
- 'tabline' %@Func@foo%X can call any function on mouse-click
- 'wildoptions' `pum` flag to use popupmenu for wildmode completion
- 'winblend' pseudo-transparency in floating windows |api-floatwin|
+ 'signcolumn' supports up to 9 dynamic/fixed columns
+ 'statusline' supports unlimited alignment sections
+ 'tabline' %@Func@foo%X can call any function on mouse-click
+ 'wildoptions' "pum" flag to use popupmenu for wildmode completion
+ 'winblend' pseudo-transparency in floating windows |api-floatwin|
'winhighlight' window-local highlights
Signs:
@@ -336,16 +336,12 @@ Macro/|recording| behavior
Motion:
The |jumplist| avoids useless/phantom jumps.
- When the new option |jumpoptions| includes 'stack', the jumplist behaves
- like the tagstack or history in a web browser--jumping from the middle of
- the jumplist discards the locations after the jumped-from position
- (|jumplist-stack|).
-
Normal commands:
|Q| is the same as |gQ|
Options:
'ttimeout', 'ttimeoutlen' behavior was simplified
+ |jumpoptions| "stack" behavior
Shell:
Shell output (|:!|, |:make|, …) is always routed through the UI, so it
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 0ecf57f50c..c193fad6a4 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -204,95 +204,153 @@ local function text_document_did_open_handler(bufnr, client)
client.notify('textDocument/didOpen', params)
end
+--- LSP client object.
+---
+--- - Methods:
+---
+--- - request(method, params, [callback])
+--- Send a request to the server. If callback is not specified, it will use
+--- {client.callbacks} to try to find a callback. If one is not found there,
+--- then an error will occur.
+--- This is a thin wrapper around {client.rpc.request} with some additional
+--- checking.
+--- Returns a boolean to indicate if the notification was successful. If it
+--- is false, then it will always be false (the client has shutdown).
+--- If it was successful, then it will return the request id as the second
+--- result. You can use this with `notify("$/cancel", { id = request_id })`
+--- to cancel the request. This helper is made automatically with
+--- |vim.lsp.buf_request()|
+--- Returns: status, [client_id]
+---
+--- - notify(method, params)
+--- This is just {client.rpc.notify}()
+--- Returns a boolean to indicate if the notification was successful. If it
+--- is false, then it will always be false (the client has shutdown).
+--- Returns: status
+---
+--- - cancel_request(id)
+--- This is just {client.rpc.notify}("$/cancelRequest", { id = id })
+--- Returns the same as `notify()`.
+---
+--- - stop([force])
+--- Stop a client, optionally with force.
+--- By default, it will just ask the server to shutdown without force.
+--- If you request to stop a client which has previously been requested to
+--- shutdown, it will automatically escalate and force shutdown.
+---
+--- - is_stopped()
+--- Returns true if the client is fully stopped.
+---
+--- - Members
+--- - id (number): The id allocated to the client.
+---
+--- - name (string): If a name is specified on creation, that will be
+--- used. Otherwise it is just the client id. This is used for
+--- logs and messages.
+---
+--- - offset_encoding (string): The encoding used for communicating
+--- with the server. You can modify this in the `on_init` method
+--- before text is sent to the server.
+---
+--- - callbacks (table): The callbacks used by the client as
+--- described in |lsp-callbacks|.
+---
+--- - config (table): copy of the table that was passed by the user
+--- to |vim.lsp.start_client()|.
+---
+--- - server_capabilities (table): Response from the server sent on
+--- `initialize` describing the server's capabilities.
+---
+--- - resolved_capabilities (table): Normalized table of
+--- capabilities that we have detected based on the initialize
+--- response from the server in `server_capabilities`.
+function lsp.client()
+ error()
+end
---- Start a client and initialize it.
--- Its arguments are passed via a configuration object.
---
--- Mandatory parameters:
---
--- root_dir: {string} specifying the directory where the LSP server will base
--- as its rootUri on initialization.
---
--- cmd: {string} or {list} which is the base command to execute for the LSP. A
--- string will be run using |'shell'| and a list will be interpreted as a bare
--- command with arguments passed. This is the same as |jobstart()|.
---
--- Optional parameters:
-
--- cmd_cwd: {string} specifying the directory to launch the `cmd` process. This
--- is not related to `root_dir`. By default, |getcwd()| is used.
---
--- cmd_env: {table} specifying the environment flags to pass to the LSP on
--- spawn. This can be specified using keys like a map or as a list with `k=v`
--- pairs or both. Non-string values are coerced to a string.
--- For example: `{ "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }`.
---
--- capabilities: A {table} which will be used instead of
--- `vim.lsp.protocol.make_client_capabilities()` which contains neovim's
--- default capabilities and passed to the language server on initialization.
--- You'll probably want to use make_client_capabilities() and modify the
--- result.
--- NOTE:
--- To send an empty dictionary, you should use
--- `{[vim.type_idx]=vim.types.dictionary}` Otherwise, it will be encoded as
--- an array.
---
--- callbacks: A {table} of whose keys are language server method names and the
--- values are `function(err, method, params, client_id)`.
--- This will be called for:
--- - notifications from the server, where `err` will always be `nil`
--- - requests initiated by the server. For these, you can respond by returning
--- two values: `result, err`. The err must be in the format of an RPC error,
--- which is `{ code, message, data? }`. You can use |vim.lsp.rpc_response_error()|
--- to help with this.
--- - as a callback for requests initiated by the client if the request doesn't
--- explicitly specify a callback.
---
--- init_options: A {table} of values to pass in the initialization request
--- as `initializationOptions`. See the `initialize` in the LSP spec.
---
--- name: A {string} used in log messages. Defaults to {client_id}
---
--- offset_encoding: One of 'utf-8', 'utf-16', or 'utf-32' which is the
--- encoding that the LSP server expects. By default, it is 'utf-16' as
--- specified in the LSP specification. The client does not verify this
--- is correct.
---
--- on_error(code, ...): A function for handling errors thrown by client
--- operation. {code} is a number describing the error. Other arguments may be
--- passed depending on the error kind. @see |vim.lsp.client_errors| for
--- possible errors. `vim.lsp.client_errors[code]` can be used to retrieve a
--- human understandable string.
---
--- before_init(initialize_params, config): A function which is called *before*
--- the request `initialize` is completed. `initialize_params` contains
--- the parameters we are sending to the server and `config` is the config that
--- was passed to `start_client()` for convenience. You can use this to modify
--- parameters before they are sent.
---
--- on_init(client, initialize_result): A function which is called after the
--- request `initialize` is completed. `initialize_result` contains
--- `capabilities` and anything else the server may send. For example, `clangd`
--- sends `result.offsetEncoding` if `capabilities.offsetEncoding` was sent to
--- it.
---
--- on_exit(code, signal, client_id): A function which is called after the
--- client has exited. code is the exit code of the process, and signal is a
--- number describing the signal used to terminate (if any).
---
--- on_attach(client, bufnr): A function which is called after the client is
--- attached to a buffer.
---
--- trace: 'off' | 'messages' | 'verbose' | nil passed directly to the language
--- server in the initialize request. Invalid/empty values will default to 'off'
---
--- @returns client_id You can use |vim.lsp.get_client_by_id()| to get the
--- actual client.
---
--- NOTE: The client is only available *after* it has been initialized, which
--- may happen after a small delay (or never if there is an error).
--- For this reason, you may want to use `on_init` to do any actions once the
--- client has been initialized.
+--- Starts and initializes a client with the given configuration.
+---
+--- Parameters `cmd` and `root_dir` are required.
+---
+--@param root_dir: (required, string) Directory where the LSP server will base
+--- its rootUri on initialization.
+---
+--@param cmd: (required, string or list treated like |jobstart()|) Base command
+--- that initiates the LSP client.
+---
+--@param cmd_cwd: (string, default=|getcwd()|) Directory to launch
+--- the `cmd` process. Not related to `root_dir`.
+---
+--@param cmd_env: (table) Environment flags to pass to the LSP on
+--- spawn. Can be specified using keys like a map or as a list with `k=v`
+--- pairs or both. Non-string values are coerced to string.
+--- Example:
+--- <pre>
+--- { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
+--- </pre>
+---
+--@param capabilities Map overriding the default capabilities defined by
+--- |vim.lsp.protocol.make_client_capabilities()|, passed to the language
+--- server on initialization. Hint: use make_client_capabilities() and modify
+--- its result.
+--- - Note: To send an empty dictionary use
+--- `{[vim.type_idx]=vim.types.dictionary}`, else it will be encoded as an
+--- array.
+---
+--@param callbacks Map of language server method names to
+--- `function(err, method, params, client_id)` handler. Invoked for:
+--- - Notifications from the server, where `err` will always be `nil`.
+--- - Requests initiated by the server. For these you can respond by returning
+--- two values: `result, err` where err must be shaped like a RPC error,
+--- i.e. `{ code, message, data? }`. Use |vim.lsp.rpc_response_error()| to
+--- help with this.
+--- - Default callback for client requests not explicitly specifying
+--- a callback.
+---
+--@param init_options Values to pass in the initialization request
+--- as `initializationOptions`. See `initialize` in the LSP spec.
+---
+--@param name (string, default=client-id) Name in log messages.
+---
+--@param offset_encoding (default="utf-16") One of "utf-8", "utf-16",
+--- or "utf-32" which is the encoding that the LSP server expects. Client does
+--- not verify this is correct.
+---
+--@param on_error Callback with parameters (code, ...), invoked
+--- when the client operation throws an error. `code` is a number describing
+--- the error. Other arguments may be passed depending on the error kind. See
+--- |vim.lsp.client_errors| for possible errors.
+--- Use `vim.lsp.client_errors[code]` to get human-friendly name.
+---
+--@param before_init Callback with parameters (initialize_params, config)
+--- invoked before the LSP "initialize" phase, where `params` contains the
+--- parameters being sent to the server and `config` is the config that was
+--- passed to `start_client()`. You can use this to modify parameters before
+--- they are sent.
+---
+--@param on_init Callback (client, initialize_result) invoked after LSP
+--- "initialize", where `result` is a table of `capabilities` and anything else
+--- the server may send. For example, clangd sends
+--- `initialize_result.offsetEncoding` if `capabilities.offsetEncoding` was
+--- sent to it. You can only modify the `client.offset_encoding` here before
+--- any notifications are sent.
+---
+--@param on_exit Callback (code, signal, client_id) invoked on client
+--- exit.
+--- - code: exit code of the process
+--- - signal: number describing the signal used to terminate (if any)
+--- - client_id: client handle
+---
+--@param on_attach Callback (client, bufnr) invoked when client
+--- attaches to a buffer.
+---
+--@param trace: "off" | "messages" | "verbose" | nil passed directly to the language
+--- server in the initialize request. Invalid/empty values will default to "off"
+---
+--@returns Client id. |vim.lsp.get_client_by_id()| Note: client is only
+--- available after it has been initialized, which may happen after a small
+--- delay (or never if there is an error). Use `on_init` to do any actions once
+--- the client has been initialized.
function lsp.start_client(config)
local cleaned_config = validate_client_config(config)
local cmd, cmd_args, offset_encoding = cleaned_config.cmd, cleaned_config.cmd_args, cleaned_config.offset_encoding
@@ -402,8 +460,8 @@ function lsp.start_client(config)
initializationOptions = config.init_options;
-- The capabilities provided by the client (editor or tool)
capabilities = config.capabilities or protocol.make_client_capabilities();
- -- The initial trace setting. If omitted trace is disabled ('off').
- -- trace = 'off' | 'messages' | 'verbose';
+ -- The initial trace setting. If omitted trace is disabled ("off").
+ -- trace = "off" | "messages" | "verbose";
trace = valid_traces[config.trace] or 'off';
-- The workspace folders configured in the client when the server starts.
-- This property is only available if the client supports workspace folders.
@@ -634,10 +692,13 @@ function lsp._text_document_did_save_handler(bufnr)
end)
end
--- Implements the textDocument/did* notifications required to track a buffer
--- for any language server.
--- @param bufnr [number] buffer handle or 0 for current
--- @param client_id [number] the client id
+--- Implements the `textDocument/did…` notifications required to track a buffer
+--- for any language server.
+---
+--- Without calling this, the server won't be notified of changes to a buffer.
+---
+--- @param bufnr (number) Buffer handle, or 0 for current
+--- @param client_id (number) Client id
function lsp.buf_attach_client(bufnr, client_id)
validate {
bufnr = {bufnr, 'n', true};
@@ -683,62 +744,58 @@ function lsp.buf_attach_client(bufnr, client_id)
return true
end
--- Check if a buffer is attached for a particular client.
--- @param bufnr [number] buffer handle or 0 for current
--- @param client_id [number] the client id
+--- Checks if a buffer is attached for a particular client.
+---
+---@param bufnr (number) Buffer handle, or 0 for current
+---@param client_id (number) the client id
function lsp.buf_is_attached(bufnr, client_id)
return (all_buffer_active_clients[bufnr] or {})[client_id] == true
end
--- Look up an active client by its id, returns nil if it is not yet initialized
--- or is not a valid id.
--- @param client_id number the client id.
+--- Gets an active client by id, or nil if the id is invalid or the
+--- client is not yet initialized.
+---
+--@param client_id client id number
+---
+--@return |vim.lsp.client| object, or nil
function lsp.get_client_by_id(client_id)
return active_clients[client_id]
end
--- Stop a client by its id, optionally with force.
--- You can also use the `stop()` function on a client if you already have
--- access to it.
--- By default, it will just ask the server to shutdown without force.
--- If you request to stop a client which has previously been requested to shutdown,
--- it will automatically force shutdown.
--- @param client_id number the client id.
--- @param force boolean (optional) whether to use force or request shutdown
+--- Stops a client(s).
+---
+--- You can also use the `stop()` function on a |vim.lsp.client| object.
+--- To stop all clients:
+---
+--- <pre>
+--- vim.lsp.stop_client(lsp.get_active_clients())
+--- </pre>
+---
+--- By default asks the server to shutdown, unless stop was requested
+--- already for this client, then force-shutdown is attempted.
+---
+--@param client_id client id or |vim.lsp.client| object, or list thereof
+--@param force boolean (optional) shutdown forcefully
function lsp.stop_client(client_id, force)
- local client
- client = active_clients[client_id]
- if client then
- client.stop(force)
- return
- end
- client = uninitialized_clients[client_id]
- if client then
- client.stop(true)
+ local ids = type(client_id) == 'table' and client_id or {client_id}
+ for _, id in ipairs(ids) do
+ if type(id) == 'table' and id.stop ~= nil then
+ id.stop(force)
+ elseif active_clients[id] then
+ active_clients[id].stop(force)
+ elseif uninitialized_clients[id] then
+ uninitialized_clients[id].stop(true)
+ end
end
end
--- Returns a list of all the active clients.
+--- Gets all active clients.
+---
+--@return Table of |vim.lsp.client| objects
function lsp.get_active_clients()
return vim.tbl_values(active_clients)
end
--- Stop all the clients, optionally with force.
--- You can also use the `stop()` function on a client if you already have
--- access to it.
--- By default, it will just ask the server to shutdown without force.
--- If you request to stop a client which has previously been requested to shutdown,
--- it will automatically force shutdown.
--- @param force boolean (optional) whether to use force or request shutdown
-function lsp.stop_all_clients(force)
- for _, client in pairs(uninitialized_clients) do
- client.stop(true)
- end
- for _, client in pairs(active_clients) do
- client.stop(force)
- end
-end
-
function lsp._vim_exit_handler()
log.info("exit_handler", active_clients)
for _, client in pairs(uninitialized_clients) do
@@ -761,17 +818,21 @@ end
nvim_command("autocmd VimLeavePre * lua vim.lsp._vim_exit_handler()")
----
---- Buffer level client functions.
----
---- Send a request to a server and return the response
--- @param bufnr [number] Buffer handle or 0 for current.
--- @param method [string] Request method name
--- @param params [table|nil] Parameters to send to the server
--- @param callback [function|nil] Request callback (or uses the client's callbacks)
+--- Sends an async request for all active clients attached to the
+--- buffer.
+---
+--@param bufnr (number) Buffer handle, or 0 for current.
+--@param method (string) LSP method name
+--@param params (optional, table) Parameters to send to the server
+--@param callback (optional, functionnil) Handler
+-- `function(err, method, params, client_id)` for this request. Defaults
+-- to the client callback in `client.callbacks`. See |lsp-callbacks|.
--
--- @returns: client_request_ids, cancel_all_requests
+--@returns 2-tuple:
+--- - Map of client-id:request-id pairs for all successful requests.
+--- - Function which can be used to cancel all the requests. You could instead
+--- iterate all clients and call their `cancel_request()` methods.
function lsp.buf_request(bufnr, method, params, callback)
validate {
bufnr = { bufnr, 'n', true };
@@ -789,31 +850,39 @@ function lsp.buf_request(bufnr, method, params, callback)
end
end)
- local function cancel_all_requests()
+ local function _cancel_all_requests()
for client_id, request_id in pairs(client_request_ids) do
local client = active_clients[client_id]
client.cancel_request(request_id)
end
end
- return client_request_ids, cancel_all_requests
+ return client_request_ids, _cancel_all_requests
end
---- Send a request to a server and wait for the response.
--- @param bufnr [number] Buffer handle or 0 for current.
--- @param method [string] Request method name
--- @param params [string] Parameters to send to the server
--- @param timeout_ms [number|100] Maximum ms to wait for a result
---
--- @returns: The table of {[client_id] = request_result}
+--- Sends a request to a server and waits for the response.
+---
+--- Calls |vim.lsp.buf_request()| but blocks Nvim while awaiting the result.
+--- Parameters are the same as |vim.lsp.buf_request()| but the return result is
+--- different. Wait maximum of {timeout_ms} (default 100) ms.
+---
+--@param bufnr (number) Buffer handle, or 0 for current.
+--@param method (string) LSP method name
+--@param params (optional, table) Parameters to send to the server
+--@param timeout_ms (optional, number, default=100) Maximum time in
+--- milliseconds to wait for a result.
+---
+--@returns Map of client_id:request_result. On timeout, cancel or error,
+--- returns `(nil, err)` where `err` is a string describing the failure
+--- reason.
function lsp.buf_request_sync(bufnr, method, params, timeout_ms)
local request_results = {}
local result_count = 0
- local function callback(err, _method, result, client_id)
+ local function _callback(err, _method, result, client_id)
request_results[client_id] = { error = err, result = result }
result_count = result_count + 1
end
- local client_request_ids, cancel = lsp.buf_request(bufnr, method, params, callback)
+ local client_request_ids, cancel = lsp.buf_request(bufnr, method, params, _callback)
local expected_result_count = 0
for _ in pairs(client_request_ids) do
expected_result_count = expected_result_count + 1
@@ -828,12 +897,13 @@ function lsp.buf_request_sync(bufnr, method, params, timeout_ms)
return request_results
end
---- Send a notification to a server
--- @param bufnr [number] (optional): The number of the buffer
--- @param method [string]: Name of the request method
--- @param params [string]: Arguments to send to the server
---
--- @returns nil
+--- Sends a notification to all servers attached to the buffer.
+---
+--@param bufnr (optional, number) Buffer handle, or 0 for current
+--@param method (string) LSP method name
+--@param params (string) Parameters to send to the server
+---
+--@returns nil
function lsp.buf_notify(bufnr, method, params)
validate {
bufnr = { bufnr, 'n', true };
@@ -888,12 +958,10 @@ function lsp.client_is_stopped(client_id)
return active_clients[client_id] == nil
end
+--- Gets a map of client_id:client pairs for the given buffer, where each value
+--- is a |vim.lsp.client| object.
---
---- Miscellaneous utilities.
----
-
--- Retrieve a map from client_id to client of all active buffer clients.
--- @param bufnr [number] (optional): buffer handle or 0 for current
+--@param bufnr (optional, number): Buffer handle, or 0 for current
function lsp.buf_get_clients(bufnr)
bufnr = resolve_bufnr(bufnr)
local result = {}
@@ -903,30 +971,24 @@ function lsp.buf_get_clients(bufnr)
return result
end
--- Print some debug information about the current buffer clients.
--- The output of this function should not be relied upon and may change.
-function lsp.buf_print_debug_info(bufnr)
- print(vim.inspect(lsp.buf_get_clients(bufnr)))
-end
-
--- Print some debug information about all LSP related things.
--- The output of this function should not be relied upon and may change.
-function lsp.print_debug_info()
- print(vim.inspect({ clients = active_clients }))
-end
-
-- Log level dictionary with reverse lookup as well.
--
-- Can be used to lookup the number from the name or the
-- name from the number.
--- Levels by name: 'trace', 'debug', 'info', 'warn', 'error'
--- Level numbers begin with 'trace' at 0
+-- Levels by name: "trace", "debug", "info", "warn", "error"
+-- Level numbers begin with "trace" at 0
lsp.log_levels = log.levels
--- Set the log level for lsp logging.
--- Levels by name: 'trace', 'debug', 'info', 'warn', 'error'
--- Level numbers begin with 'trace' at 0
--- @param level [number|string] the case insensitive level name or number @see |vim.lsp.log_levels|
+--- Sets the global log level for LSP logging.
+---
+--- Levels by name: "trace", "debug", "info", "warn", "error"
+--- Level numbers begin with "trace" at 0
+---
+--- Use `lsp.log_levels` for reverse lookup.
+---
+--@see |vim.lsp.log_levels|
+---
+--@param level [number|string] the case insensitive level name or number
function lsp.set_log_level(level)
if type(level) == 'string' or type(level) == 'number' then
log.set_level(level)
@@ -935,7 +997,7 @@ function lsp.set_log_level(level)
end
end
--- Return the path of the logfile used by the LSP client.
+--- Gets the path of the logfile used by the LSP client.
function lsp.get_log_path()
return log.get_filename()
end
diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index ead90cc75a..f64b0b50e7 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -603,6 +603,8 @@ export interface WorkspaceClientCapabilities {
}
--]=]
+--- Gets a new ClientCapabilities object describing the LSP client
+--- capabilities.
function protocol.make_client_capabilities()
return {
textDocument = {
@@ -821,6 +823,8 @@ interface ServerCapabilities {
experimental?: any;
}
--]]
+
+--- Creates a normalized object describing LSP server capabilities.
function protocol.resolve_capabilities(server_capabilities)
local general_properties = {}
local text_document_sync_properties
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 72a0bf8d6f..e13b05610b 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -166,9 +166,14 @@ local function format_rpc_error(err)
return table.concat(message_parts, ' ')
end
+--- Creates an RPC response object/table.
+---
+--@param code RPC error code defined in `vim.lsp.protocol.ErrorCodes`
+--@param message (optional) arbitrary message to send to server
+--@param data (optional) arbitrary data to send to server
local function rpc_response_error(code, message, data)
-- TODO should this error or just pick a sane error (like InternalError)?
- local code_name = assert(protocol.ErrorCodes[code], 'Invalid rpc error code')
+ local code_name = assert(protocol.ErrorCodes[code], 'Invalid RPC error code')
return setmetatable({
code = code;
message = message or code_name;
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index e30ed92e8f..bdfe52addb 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -55,6 +55,7 @@ if sys.version_info[0] < 3 or sys.version_info[1] < 5:
sys.exit(1)
DEBUG = ('DEBUG' in os.environ)
+TARGET = os.environ.get('TARGET', None)
INCLUDE_C_DECL = ('INCLUDE_C_DECL' in os.environ)
INCLUDE_DEPRECATED = ('INCLUDE_DEPRECATED' in os.environ)
@@ -62,13 +63,14 @@ fmt_vimhelp = False # HACK
text_width = 78
script_path = os.path.abspath(__file__)
base_dir = os.path.dirname(os.path.dirname(script_path))
-out_dir = os.path.join(base_dir, 'tmp-{mode}-doc')
+out_dir = os.path.join(base_dir, 'tmp-{target}-doc')
filter_cmd = '%s %s' % (sys.executable, script_path)
seen_funcs = set()
lua2dox_filter = os.path.join(base_dir, 'scripts', 'lua2dox_filter')
CONFIG = {
'api': {
+ 'mode': 'c',
'filename': 'api.txt',
# String used to find the start of the generated part of the doc.
'section_start_token': '*api-global*',
@@ -85,17 +87,24 @@ CONFIG = {
# file patterns used by doxygen
'file_patterns': '*.h *.c',
# Only function with this prefix are considered
- 'func_name_prefix': 'nvim_',
+ 'fn_name_prefix': 'nvim_',
# Section name overrides.
'section_name': {
'vim.c': 'Global',
},
+ # For generated section names.
+ 'section_fmt': lambda name: f'{name} Functions',
+ # Section helptag.
+ 'helptag_fmt': lambda name: f'*api-{name.lower()}*',
+ # Per-function helptag.
+ 'fn_helptag_fmt': lambda fstem, name: f'*{name}()*',
# Module name overrides (for Lua).
'module_override': {},
# Append the docs for these modules, do not start a new section.
'append_only': [],
},
'lua': {
+ 'mode': 'lua',
'filename': 'lua.txt',
'section_start_token': '*lua-vim*',
'section_order': [
@@ -107,8 +116,13 @@ CONFIG = {
os.path.join(base_dir, 'runtime/lua/vim/shared.lua'),
]),
'file_patterns': '*.lua',
- 'func_name_prefix': '',
- 'section_name': {},
+ 'fn_name_prefix': '',
+ 'section_name': {
+ 'lsp.lua': 'core',
+ },
+ 'section_fmt': lambda name: f'Lua module: {name.lower()}',
+ 'helptag_fmt': lambda name: f'*lua-{name.lower()}*',
+ 'fn_helptag_fmt': lambda fstem, name: f'*{fstem}.{name}()*',
'module_override': {
# `shared` functions are exposed on the `vim` module.
'shared': 'vim',
@@ -117,6 +131,48 @@ CONFIG = {
'shared.lua',
],
},
+ 'lsp': {
+ 'mode': 'lua',
+ 'filename': 'lsp.txt',
+ 'section_start_token': '*lsp-core*',
+ 'section_order': [
+ 'lsp.lua',
+ 'protocol.lua',
+ 'buf.lua',
+ 'callbacks.lua',
+ 'log.lua',
+ 'rpc.lua',
+ 'util.lua'
+ ],
+ 'files': ' '.join([
+ os.path.join(base_dir, 'runtime/lua/vim/lsp'),
+ os.path.join(base_dir, 'runtime/lua/vim/lsp.lua'),
+ ]),
+ 'file_patterns': '*.lua',
+ 'fn_name_prefix': '',
+ 'section_name': {},
+ 'section_fmt': lambda name: (
+ 'Lua module: vim.lsp'
+ if name.lower() == 'lsp'
+ else f'Lua module: vim.lsp.{name.lower()}'),
+ 'helptag_fmt': lambda name: (
+ '*lsp-core*'
+ if name.lower() == 'lsp'
+ else f'*lsp-{name.lower()}*'),
+ 'fn_helptag_fmt': lambda fstem, name: (
+ f'*vim.lsp.{name}()*'
+ if fstem == 'lsp' and name != 'client'
+ else (
+ '*vim.lsp.client*'
+ # HACK. TODO(justinmk): class/structure support in lua2dox
+ if 'lsp.client' == f'{fstem}.{name}'
+ else f'*vim.lsp.{fstem}.{name}()*')),
+ 'module_override': {
+ # Combine are exposed on the `vim` module.
+ 'shared': 'vim',
+ },
+ 'append_only': [],
+ },
}
param_exclude = (
@@ -516,7 +572,7 @@ def fmt_node_as_vimhelp(parent, width=62, indent=''):
return clean_lines('\n'.join(rendered_blocks).strip())
-def extract_from_xml(filename, mode, width):
+def extract_from_xml(filename, target, width):
"""Extracts Doxygen info as maps without formatting the text.
Returns two maps:
@@ -567,12 +623,12 @@ def extract_from_xml(filename, mode, width):
if not fmt_vimhelp:
pass
- elif mode == 'lua':
- fstem = compoundname.split('.')[0]
- fstem = CONFIG[mode]['module_override'].get(fstem, fstem)
- vimtag = '*{}.{}()*'.format(fstem, name)
else:
- vimtag = '*{}()*'.format(name)
+ fstem = '?'
+ if '.' in compoundname:
+ fstem = compoundname.split('.')[0]
+ fstem = CONFIG[target]['module_override'].get(fstem, fstem)
+ vimtag = CONFIG[target]['fn_helptag_fmt'](fstem, name)
params = []
type_length = 0
@@ -583,8 +639,8 @@ def extract_from_xml(filename, mode, width):
declname = get_child(param, 'declname')
if declname:
param_name = get_text(declname).strip()
- elif mode == 'lua':
- # that's how it comes out of lua2dox
+ elif CONFIG[target]['mode'] == 'lua':
+ # XXX: this is what lua2dox gives us...
param_name = param_type
param_type = ''
@@ -614,7 +670,7 @@ def extract_from_xml(filename, mode, width):
' ')
# Minimum 8 chars between signature and vimtag
- lhs = (width - 8) - len(prefix)
+ lhs = (width - 8) - len(vimtag)
if len(prefix) + len(suffix) > lhs:
signature = vimtag.rjust(width) + '\n'
@@ -663,7 +719,7 @@ def extract_from_xml(filename, mode, width):
if 'Deprecated' in str(xrefs):
deprecated_fns[name] = fn
- elif name.startswith(CONFIG[mode]['func_name_prefix']):
+ elif name.startswith(CONFIG[target]['fn_name_prefix']):
fns[name] = fn
xrefs.clear()
@@ -673,7 +729,7 @@ def extract_from_xml(filename, mode, width):
return (fns, deprecated_fns)
-def fmt_doxygen_xml_as_vimhelp(filename, mode):
+def fmt_doxygen_xml_as_vimhelp(filename, target):
"""Entrypoint for generating Vim :help from from Doxygen XML.
Returns 3 items:
@@ -684,7 +740,7 @@ def fmt_doxygen_xml_as_vimhelp(filename, mode):
fmt_vimhelp = True
fns_txt = {} # Map of func_name:vim-help-text.
deprecated_fns_txt = {} # Map of func_name:vim-help-text.
- fns, _ = extract_from_xml(filename, mode, width=text_width)
+ fns, _ = extract_from_xml(filename, target, width=text_width)
for name, fn in fns.items():
# Generate Vim :help for parameters.
@@ -714,7 +770,7 @@ def fmt_doxygen_xml_as_vimhelp(filename, mode):
if 'Deprecated' in xrefs:
deprecated_fns_txt[name] = func_doc
- elif name.startswith(CONFIG[mode]['func_name_prefix']):
+ elif name.startswith(CONFIG[target]['fn_name_prefix']):
fns_txt[name] = func_doc
xrefs.clear()
@@ -730,9 +786,13 @@ def delete_lines_below(filename, tokenstr):
"""
lines = open(filename).readlines()
i = 0
+ found = False
for i, line in enumerate(lines, 1):
if tokenstr in line:
+ found = True
break
+ if not found:
+ raise RuntimeError(f'not found: "{tokenstr}"')
i = max(0, i - 2)
with open(filename, 'wt') as fp:
fp.writelines(lines[0:i])
@@ -746,21 +806,28 @@ def main(config):
Doxygen is called and configured through stdin.
"""
- for mode in CONFIG:
+ for target in CONFIG:
+ if TARGET is not None and target != TARGET:
+ continue
mpack_file = os.path.join(
base_dir, 'runtime', 'doc',
- CONFIG[mode]['filename'].replace('.txt', '.mpack'))
+ CONFIG[target]['filename'].replace('.txt', '.mpack'))
if os.path.exists(mpack_file):
os.remove(mpack_file)
- output_dir = out_dir.format(mode=mode)
- p = subprocess.Popen(['doxygen', '-'], stdin=subprocess.PIPE)
+ output_dir = out_dir.format(target=target)
+ p = subprocess.Popen(
+ ['doxygen', '-'],
+ stdin=subprocess.PIPE,
+ # silence warnings
+ # runtime/lua/vim/lsp.lua:209: warning: argument 'foo' not found
+ stderr=subprocess.DEVNULL)
p.communicate(
config.format(
- input=CONFIG[mode]['files'],
+ input=CONFIG[target]['files'],
output=output_dir,
filter=filter_cmd,
- file_patterns=CONFIG[mode]['file_patterns'])
+ file_patterns=CONFIG[target]['file_patterns'])
.encode('utf8')
)
if p.returncode:
@@ -797,24 +864,20 @@ def main(config):
if filename.endswith('.c') or filename.endswith('.lua'):
# Extract unformatted (*.mpack).
fn_map, _ = extract_from_xml(os.path.join(base, '{}.xml'.format(
- compound.getAttribute('refid'))), mode, width=9999)
+ compound.getAttribute('refid'))), target, width=9999)
# Extract formatted (:help).
functions_text, deprecated_text = fmt_doxygen_xml_as_vimhelp(
os.path.join(base, '{}.xml'.format(
- compound.getAttribute('refid'))), mode)
+ compound.getAttribute('refid'))), target)
if not functions_text and not deprecated_text:
continue
else:
- name = os.path.splitext(os.path.basename(filename))[0]
- if name == 'ui':
- name = name.upper()
- else:
- name = name.title()
-
+ name = os.path.splitext(
+ os.path.basename(filename))[0].lower()
+ sectname = name.upper() if name == 'ui' else name.title()
doc = ''
-
- intro = intros.get('api-%s' % name.lower())
+ intro = intros.get(f'api-{name}')
if intro:
doc += '\n\n' + intro
@@ -822,36 +885,31 @@ def main(config):
doc += '\n\n' + functions_text
if INCLUDE_DEPRECATED and deprecated_text:
- doc += '\n\n\nDeprecated %s Functions: ~\n\n' % name
+ doc += f'\n\n\nDeprecated {sectname} Functions: ~\n\n'
doc += deprecated_text
if doc:
filename = os.path.basename(filename)
- name = CONFIG[mode]['section_name'].get(filename, name)
-
- if mode == 'lua':
- title = 'Lua module: {}'.format(name.lower())
- helptag = '*lua-{}*'.format(name.lower())
- else:
- title = '{} Functions'.format(name)
- helptag = '*api-{}*'.format(name.lower())
+ sectname = CONFIG[target]['section_name'].get(
+ filename, sectname)
+ title = CONFIG[target]['section_fmt'](sectname)
+ helptag = CONFIG[target]['helptag_fmt'](sectname)
sections[filename] = (title, helptag, doc)
fn_map_full.update(fn_map)
- if not sections:
- return
+ assert sections
+ if len(sections) > len(CONFIG[target]['section_order']):
+ raise RuntimeError(
+ 'found new modules "{}"; update the "section_order" map'.format(
+ set(sections).difference(CONFIG[target]['section_order'])))
docs = ''
i = 0
- for filename in CONFIG[mode]['section_order']:
- if filename not in sections:
- raise RuntimeError(
- 'found new module "{}"; update the "section_order" map'.format(
- filename))
+ for filename in CONFIG[target]['section_order']:
title, helptag, section_doc = sections.pop(filename)
i += 1
- if filename not in CONFIG[mode]['append_only']:
+ if filename not in CONFIG[target]['append_only']:
docs += sep
docs += '\n%s%s' % (title,
helptag.rjust(text_width - len(title)))
@@ -862,9 +920,9 @@ def main(config):
docs += ' vim:tw=78:ts=8:ft=help:norl:\n'
doc_file = os.path.join(base_dir, 'runtime', 'doc',
- CONFIG[mode]['filename'])
+ CONFIG[target]['filename'])
- delete_lines_below(doc_file, CONFIG[mode]['section_start_token'])
+ delete_lines_below(doc_file, CONFIG[target]['section_start_token'])
with open(doc_file, 'ab') as fp:
fp.write(docs.encode('utf8'))
diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
index 171621e38d..d4e68f9e45 100644
--- a/scripts/lua2dox.lua
+++ b/scripts/lua2dox.lua
@@ -17,61 +17,28 @@
-- Free Software Foundation, Inc., --
-- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --
----------------------------------------------------------------------------]]
---[[!
-\file
-\brief a hack lua2dox converter
-]]
--[[!
-\mainpage
-
-Introduction
-------------
-
-A hack lua2dox converter
-Version 0.2
+Lua-to-Doxygen converter
-This lets us make Doxygen output some documentation to let
-us develop this code.
-
-It is partially cribbed from the functionality of lua2dox
-(http://search.cpan.org/~alec/Doxygen-Lua-0.02/lib/Doxygen/Lua.pm).
-Found on CPAN when looking for something else; kinda handy.
-
-Improved from lua2dox to make the doxygen output more friendly.
-Also it runs faster in lua rather than Perl.
-
-Because this Perl based system is called "lua2dox"., I have decided to add ".lua" to the name
-to keep the two separate.
+Partially from lua2dox
+http://search.cpan.org/~alec/Doxygen-Lua-0.02/lib/Doxygen/Lua.pm
Running
-------
-<ol>
-<li> Ensure doxygen is installed on your system and that you are familiar with its use.
-Best is to try to make and document some simple C/C++/PHP to see what it produces.
-You can experiment with the enclosed example code.
-
-<li> Run "doxygen -g" to create a default Doxyfile.
+This file "lua2dox.lua" gets called by "lua2dox_filter" (bash).
-Then alter it to let it recognise lua. Add the two following lines:
+Doxygen must be on your system. You can experiment like so:
-\code{.bash}
-FILE_PATTERNS = *.lua
-
-FILTER_PATTERNS = *.lua=lua2dox_filter
-\endcode
-
-
-Either add them to the end or find the appropriate entry in Doxyfile.
-
-There are other lines that you might like to alter, but see further documentation for details.
-
-<li> When Doxyfile is edited run "doxygen"
+- Run "doxygen -g" to create a default Doxyfile.
+- Then alter it to let it recognise lua. Add the two following lines:
+ FILE_PATTERNS = *.lua
+ FILTER_PATTERNS = *.lua=lua2dox_filter
+- Then run "doxygen".
The core function reads the input file (filename or stdin) and outputs some pseudo C-ish language.
It only has to be good enough for doxygen to see it as legal.
-Therefore our lua interpreter is fairly limited, but "good enough".
One limitation is that each line is treated separately (except for long comments).
The implication is that class and function declarations must be on the same line.
@@ -81,40 +48,8 @@ so it will probably not document accurately if we do do this.
However I have put in a hack that will insert the "missing" close paren.
The effect is that you will get the function documented, but not with the parameter list you might expect.
-</ol>
-
-Installation
-------------
-
-Here for linux or unix-like, for any other OS you need to refer to other documentation.
-
-This file is "lua2dox.lua". It gets called by "lua2dox_filter"(bash).
-Somewhere in your path (e.g. "~/bin" or "/usr/local/bin") put a link to "lua2dox_filter".
-
-Documentation
--------------
-
-Read the external documentation that should be part of this package.
-For example look for the "README" and some .PDFs.
-
]]
--- we won't use our library code, so this becomes more portable
-
--- require 'elijah_fix_require'
--- require 'elijah_class'
---
---! \brief ``declare'' as class
---!
---! use as:
---! \code{.lua}
---! TWibble = class()
---! function TWibble.init(this,Str)
---! this.str = Str
---! -- more stuff here
---! end
---! \endcode
---!
function class(BaseClass, ClassInitialiser)
local newClass = {} -- a new class newClass
if not ClassInitialiser and type(BaseClass) == 'function' then
@@ -165,8 +100,6 @@ function class(BaseClass, ClassInitialiser)
return newClass
end
--- require 'elijah_clock'
-
--! \class TCore_Clock
--! \brief a clock
TCore_Clock = class()
@@ -201,9 +134,6 @@ function TCore_Clock.getTimeStamp(this,T0)
end
---require 'elijah_io'
-
---! \class TCore_IO
--! \brief io to console
--!
--! pseudo class (no methods, just to keep documentation tidy)
@@ -225,8 +155,6 @@ function TCore_IO_writeln(Str)
end
---require 'elijah_string'
-
--! \brief trims a string
function string_trim(Str)
return Str:match("^%s*(.-)%s*$")
@@ -257,8 +185,6 @@ function string_split(Str, Pattern)
end
---require 'elijah_commandline'
-
--! \class TCore_Commandline
--! \brief reads/parses commandline
TCore_Commandline = class()
@@ -279,9 +205,6 @@ function TCore_Commandline.getRaw(this,Key,Default)
return val
end
-
---require 'elijah_debug'
-
-------------------------------
--! \brief file buffer
--!
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 93bc497cf0..8b2f342142 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -179,8 +179,8 @@ void setpcmark(void)
}
if (jop_flags & JOP_STACK) {
- // If we're somewhere in the middle of the jumplist discard everything
- // after the current index.
+ // jumpoptions=stack: if we're somewhere in the middle of the jumplist
+ // discard everything after the current index.
if (curwin->w_jumplistidx < curwin->w_jumplistlen - 1) {
// Discard the rest of the jumplist by cutting the length down to
// contain nothing beyond the current index.
@@ -1214,14 +1214,14 @@ void cleanup_jumplist(win_T *wp, bool checktail)
break;
}
}
+
bool mustfree;
- if (i >= wp->w_jumplistlen) { // not duplicate
+ if (i >= wp->w_jumplistlen) { // not duplicate
mustfree = false;
- } else if (i > from + 1) { // non-adjacent duplicate
- // When the jump options include "stack", duplicates are only removed from
- // the jumplist when they are adjacent.
+ } else if (i > from + 1) { // non-adjacent duplicate
+ // jumpoptions=stack: remove duplicates only when adjacent.
mustfree = !(jop_flags & JOP_STACK);
- } else { // adjacent duplicate
+ } else { // adjacent duplicate
mustfree = true;
}
diff --git a/test/functional/normal/jump_spec.lua b/test/functional/normal/jump_spec.lua
index d53b5f7415..9e7158e2f7 100644
--- a/test/functional/normal/jump_spec.lua
+++ b/test/functional/normal/jump_spec.lua
@@ -48,7 +48,7 @@ describe('jumplist', function()
end)
end)
-describe('jumpoptions=stack behaves like browser history', function()
+describe("jumpoptions=stack behaves like 'tagstack'", function()
before_each(function()
clear()
feed(':clearjumps<cr>')
diff --git a/test/functional/plugin/lsp/lsp_spec.lua b/test/functional/plugin/lsp/lsp_spec.lua
index f10fd5c185..e54275e820 100644
--- a/test/functional/plugin/lsp/lsp_spec.lua
+++ b/test/functional/plugin/lsp/lsp_spec.lua
@@ -3,6 +3,8 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local exec_lua = helpers.exec_lua
local eq = helpers.eq
+local iswin = helpers.iswin
+local retry = helpers.retry
local NIL = helpers.NIL
-- Use these to get access to a coroutine so that I can run async tests and use
@@ -11,9 +13,8 @@ local run, stop = helpers.run, helpers.stop
if helpers.pending_win32(pending) then return end
-local is_windows = require'luv'.os_uname().sysname == "Windows"
local lsp_test_rpc_server_file = "test/functional/fixtures/lsp-test-rpc-server.lua"
-if is_windows then
+if iswin() then
lsp_test_rpc_server_file = lsp_test_rpc_server_file:gsub("/", "\\")
end
@@ -101,8 +102,8 @@ local function test_rpc_server(config)
end
end
-describe('Language Client API', function()
- describe('server_name is specified', function()
+describe('LSP', function()
+ describe('server_name specified', function()
before_each(function()
clear()
-- Run an instance of nvim on the file which contains our "scripts".
@@ -111,14 +112,17 @@ describe('Language Client API', function()
exec_lua([=[
lsp = require('vim.lsp')
local test_name, fixture_filename = ...
- TEST_RPC_CLIENT_ID = lsp.start_client {
- cmd = {
- vim.api.nvim_get_vvar("progpath"), '-Es', '-u', 'NONE', '--headless',
- "-c", string.format("lua TEST_NAME = %q", test_name),
- "-c", "luafile "..fixture_filename;
- };
- root_dir = vim.loop.cwd();
- }
+ function test__start_client()
+ return lsp.start_client {
+ cmd = {
+ vim.api.nvim_get_vvar("progpath"), '-Es', '-u', 'NONE', '--headless',
+ "-c", string.format("lua TEST_NAME = %q", test_name),
+ "-c", "luafile "..fixture_filename;
+ };
+ root_dir = vim.loop.cwd();
+ }
+ end
+ TEST_CLIENT1 = test__start_client()
]=], test_name, lsp_test_rpc_server_file)
end)
@@ -127,25 +131,48 @@ describe('Language Client API', function()
-- exec_lua("lsp.stop_all_clients(true)")
end)
- describe('start_client and stop_client', function()
- it('should return true', function()
- for _ = 1, 20 do
- helpers.sleep(10)
- if exec_lua("return #lsp.get_active_clients()") > 0 then
- break
- end
- end
- eq(1, exec_lua("return #lsp.get_active_clients()"))
- eq(false, exec_lua("return lsp.get_client_by_id(TEST_RPC_CLIENT_ID) == nil"))
- eq(false, exec_lua("return lsp.get_client_by_id(TEST_RPC_CLIENT_ID).is_stopped()"))
- exec_lua("return lsp.get_client_by_id(TEST_RPC_CLIENT_ID).stop()")
- for _ = 1, 20 do
- helpers.sleep(10)
- if exec_lua("return #lsp.get_active_clients()") == 0 then
- break
- end
- end
- eq(true, exec_lua("return lsp.get_client_by_id(TEST_RPC_CLIENT_ID) == nil"))
+ it('start_client(), stop_client()', function()
+ retry(nil, 4000, function()
+ eq(1, exec_lua('return #lsp.get_active_clients()'))
+ end)
+ eq(2, exec_lua([[
+ TEST_CLIENT2 = test__start_client()
+ return TEST_CLIENT2
+ ]]))
+ eq(3, exec_lua([[
+ TEST_CLIENT3 = test__start_client()
+ return TEST_CLIENT3
+ ]]))
+ retry(nil, 4000, function()
+ eq(3, exec_lua('return #lsp.get_active_clients()'))
+ end)
+
+ eq(false, exec_lua('return lsp.get_client_by_id(TEST_CLIENT1) == nil'))
+ eq(false, exec_lua('return lsp.get_client_by_id(TEST_CLIENT1).is_stopped()'))
+ exec_lua('return lsp.get_client_by_id(TEST_CLIENT1).stop()')
+ retry(nil, 4000, function()
+ eq(2, exec_lua('return #lsp.get_active_clients()'))
+ end)
+ eq(true, exec_lua('return lsp.get_client_by_id(TEST_CLIENT1) == nil'))
+
+ exec_lua('lsp.stop_client({TEST_CLIENT2, TEST_CLIENT3})')
+ retry(nil, 4000, function()
+ eq(0, exec_lua('return #lsp.get_active_clients()'))
+ end)
+ end)
+
+ it('stop_client() also works on client objects', function()
+ exec_lua([[
+ TEST_CLIENT2 = test__start_client()
+ TEST_CLIENT3 = test__start_client()
+ ]])
+ retry(nil, 4000, function()
+ eq(3, exec_lua('return #lsp.get_active_clients()'))
+ end)
+ -- Stop all clients.
+ exec_lua('lsp.stop_client(lsp.get_active_clients())')
+ retry(nil, 4000, function()
+ eq(0, exec_lua('return #lsp.get_active_clients()'))
end)
end)
end)