mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 18:55:14 -07:00
Merge #11604 "LSP: shrink API, improve docs"
This commit is contained in:
commit
070bd3ea23
17
README.md
17
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
|
||||
|
@ -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: ~
|
||||
|
@ -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,
|
||||
|
@ -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*
|
||||
|
1116
runtime/doc/lsp.txt
1116
runtime/doc/lsp.txt
File diff suppressed because it is too large
Load Diff
@ -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>
|
||||
<
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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'))
|
||||
|
||||
|
@ -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
|
||||
Lua-to-Doxygen converter
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
A hack lua2dox converter
|
||||
Version 0.2
|
||||
|
||||
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.
|
||||
This file "lua2dox.lua" gets called by "lua2dox_filter" (bash).
|
||||
|
||||
<li> Run "doxygen -g" to create a default Doxyfile.
|
||||
Doxygen must be on your system. You can experiment like so:
|
||||
|
||||
Then alter it to let it recognise lua. Add the two following lines:
|
||||
|
||||
\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
|
||||
--!
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>')
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user