docs: types, news, lua-plugin

- mention "lua_ls", not "luals". https://github.com/neovim/neovim/discussions/36182

Co-authored-by: Maria Solano <majosolano99@gmail.com>
This commit is contained in:
Justin M. Keyes
2025-10-14 19:22:03 -04:00
parent 07d0da64ed
commit 7838c242e9
13 changed files with 106 additions and 52 deletions

View File

@@ -24,9 +24,29 @@ Data structures
Use `kvec.h` for most lists. When you absolutely need a linked list, use Use `kvec.h` for most lists. When you absolutely need a linked list, use
`lib/queue_defs.h` which defines an "intrusive" linked list. `lib/queue_defs.h` which defines an "intrusive" linked list.
==============================================================================
Events
All new events must be implemented using `aucmd_defer()` (and where possible,
old events should be migrated to this), so that they are processed in
a predictable manner, which avoids crashes and race conditions. See
`do_markset_autocmd` for an example.
============================================================================== ==============================================================================
UI events UI events
The long-term vision is that UI events are just another type of "editor event"
(formerly known as "autocmds"). There is no real reason that we have separate
types of user-facing or plugin-facing events. Events are events. Their
"transport" is irrelevant and any event should be possible to emit over any
transport (editor or RPC).
Meanwhile the current situation is that UI events are a particular RPC event
packaged in a generic `redraw` notification. They also can be listened to
in-process via |vim.ui_attach()|.
UI events are deferred to UIs, which implies a deepcopy of the UI event data.
The source files most directly involved with UI events are: The source files most directly involved with UI events are:
1. `src/nvim/ui.*`: calls handler functions of registered UI structs (independent from msgpack-rpc) 1. `src/nvim/ui.*`: calls handler functions of registered UI structs (independent from msgpack-rpc)
2. `src/nvim/api/ui.*`: forwards messages over msgpack-rpc to remote UIs. 2. `src/nvim/api/ui.*`: forwards messages over msgpack-rpc to remote UIs.
@@ -38,12 +58,8 @@ functions used by the source files above. It also generates metadata
accessible as `api_info().ui_events`. accessible as `api_info().ui_events`.
See commit d3a8e9217f39c59dd7762bd22a76b8bd03ca85ff for an example of adding See commit d3a8e9217f39c59dd7762bd22a76b8bd03ca85ff for an example of adding
a new UI event. a new UI event. Remember to bump NVIM_API_LEVEL if it wasn't already during
this development cycle.
UI events are deferred to UIs, which implies a deepcopy of the UI event data.
Remember to bump NVIM_API_LEVEL if it wasn't already during this development
cycle.
Other references: Other references:
- |msgpack-rpc| - |msgpack-rpc|

View File

@@ -475,6 +475,7 @@ everywhere, not "buffer" in some places and "buf" in others.
- chan: |channel| - chan: |channel|
- cmd: Command - cmd: Command
- cmdline: Command-line UI or input - cmdline: Command-line UI or input
- dir: Directory
- fn: Function - fn: Function
- hl: Highlight - hl: Highlight
- pos: Position - pos: Position

View File

@@ -87,6 +87,9 @@ g CTRL-G Prints the current position of the cursor in five
If the buffer did have a name, that name becomes the If the buffer did have a name, that name becomes the
|alternate-file| name. An unlisted buffer is created |alternate-file| name. An unlisted buffer is created
to hold the old name. to hold the old name.
See |nvim_buf_set_name()| to avoid filename escaping.
*:0file* *:0file*
:0f[ile][!] Remove the name of the current buffer. The optional ! :0f[ile][!] Remove the name of the current buffer. The optional !
avoids truncating the message, as with |:file|. avoids truncating the message, as with |:file|.

View File

@@ -30,7 +30,7 @@ Follow these steps to get LSP features:
2. Define a new config |lsp-new-config| (or install https://github.com/neovim/nvim-lspconfig). 2. Define a new config |lsp-new-config| (or install https://github.com/neovim/nvim-lspconfig).
Example: >lua Example: >lua
vim.lsp.config['luals'] = { vim.lsp.config['lua_ls'] = {
-- Command and arguments to start the server. -- Command and arguments to start the server.
cmd = { 'lua-language-server' }, cmd = { 'lua-language-server' },
-- Filetypes to automatically attach to. -- Filetypes to automatically attach to.
@@ -52,7 +52,7 @@ Follow these steps to get LSP features:
3. Use |vim.lsp.enable()| to enable the config. 3. Use |vim.lsp.enable()| to enable the config.
Example: >lua Example: >lua
vim.lsp.enable('luals') vim.lsp.enable('lua_ls')
< <
4. Open a code file matching one of the `filetypes` specified in the config. 4. Open a code file matching one of the `filetypes` specified in the config.
Note: Depending on the LSP server, you may need to ensure your project has Note: Depending on the LSP server, you may need to ensure your project has
@@ -997,8 +997,8 @@ config({name}, {cfg}) *vim.lsp.config()*
filetypes = { 'c', 'cpp' }, filetypes = { 'c', 'cpp' },
} }
< <
• Get the resolved configuration for "luals": >lua • Get the resolved configuration for "lua_ls": >lua
local cfg = vim.lsp.config.luals local cfg = vim.lsp.config.lua_ls
< <
Attributes: ~ Attributes: ~
@@ -1014,7 +1014,7 @@ enable({name}, {enable}) *vim.lsp.enable()*
Examples: >lua Examples: >lua
vim.lsp.enable('clangd') vim.lsp.enable('clangd')
vim.lsp.enable({'luals', 'pyright'}) vim.lsp.enable({'lua_ls', 'pyright'})
< <
Example: *lsp-restart* Passing `false` stops and detaches the client(s). Example: *lsp-restart* Passing `false` stops and detaches the client(s).
@@ -1689,12 +1689,12 @@ Lua module: vim.lsp.client *lsp-client*
Fields: ~ Fields: ~
• {before_init}? (`fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)`) • {before_init}? (`fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)`)
Callback invoked before the LSP "initialize" Callback which can modify parameters before
phase, where `params` contains the parameters they are sent to the server. Invoked before LSP
being sent to the server and `config` is the "initialize" phase (after `cmd` is invoked),
config that was passed to |vim.lsp.start()|. where `params` is the parameters being sent to
You can use this to modify parameters before the server and `config` is the config passed to
they are sent. |vim.lsp.start()|.
• {capabilities}? (`lsp.ClientCapabilities`) Map overriding the • {capabilities}? (`lsp.ClientCapabilities`) Map overriding the
default capabilities defined by default capabilities defined by
|vim.lsp.protocol.make_client_capabilities()|, |vim.lsp.protocol.make_client_capabilities()|,

View File

@@ -217,6 +217,11 @@ Consider making use of 'filetype' for any functionality that is specific to
a filetype, by putting the initialization logic in a `ftplugin/{filetype}.lua` a filetype, by putting the initialization logic in a `ftplugin/{filetype}.lua`
script. script.
For buffers owned by your plugin (often used to show a custom UI or view),
typically your plugin will set a custom 'filetype'. In that case, it's useful
to set the 'filetype' "as late as possible", so that users can override
buffer-local settings after your plugin has (re)initialized the buffer.
FILETYPE EXAMPLE FILETYPE EXAMPLE
A plugin tailored to Rust development might have initialization in A plugin tailored to Rust development might have initialization in
@@ -240,6 +245,10 @@ A plugin tailored to Rust development might have initialization in
============================================================================== ==============================================================================
Configuration *lua-plugin-config* Configuration *lua-plugin-config*
To allow users to override buffer-local configuration for filetypes owned by
your plugin, publish a |FileType| event, "as late as possible".
|lua-plugin-filetype|
Once you have merged the default configuration with the user's config, you Once you have merged the default configuration with the user's config, you
should validate configs. should validate configs.
@@ -250,6 +259,32 @@ Validations could include:
This can be tricky to implement, and may be better suited for a |health| This can be tricky to implement, and may be better suited for a |health|
check, to reduce overhead. check, to reduce overhead.
==============================================================================
UI *lua-plugin-ui*
Some plugins have their own "UI" which they present in a buffer that the
plugin "owns". In that buffer typically you will want to provide custom
actions.
Besides creating |<Plug>| mappings, you may want to consider providing actions
by defining an in-process LSP server. Offering actions as code-actions
|vim.lsp.buf.code_action()| means the user can see all available actions using
the default |gra| mapping to view the code-actions menu. They can even define
mappings to a specific action by invoking `vim.lsp.buf.code_action()` with the
`filter` + `apply` parameters: >lua
vim.lsp.buf.code_action({
apply = true,
filter = function(a)
return a.title == 'Do something'
end,
})
<
Example: See `runtime/lua/vim/pack/_lsp.lua` for how vim.pack defines an
in-process LSP server to provide interactive features in its `nvim-pack://`
buffer.
============================================================================== ==============================================================================
Troubleshooting *lua-plugin-troubleshooting* Troubleshooting *lua-plugin-troubleshooting*

View File

@@ -1710,7 +1710,7 @@ vim.is_callable({f}) *vim.is_callable()*
Returns true if object `f` can be called as a function. Returns true if object `f` can be called as a function.
Parameters: ~ Parameters: ~
• {f} (`any`) Any object • {f} (`any?`) Any object
Return: ~ Return: ~
(`boolean`) `true` if `f` is callable, else `false` (`boolean`) `true` if `f` is callable, else `false`
@@ -1727,7 +1727,7 @@ vim.isarray({t}) *vim.isarray()*
|rpcrequest()| or |vim.fn|. |rpcrequest()| or |vim.fn|.
Parameters: ~ Parameters: ~
• {t} (`table?`) • {t} (`any?`)
Return: ~ Return: ~
(`boolean`) `true` if array-like table, else `false`. (`boolean`) `true` if array-like table, else `false`.

View File

@@ -80,7 +80,6 @@ EVENTS
message UI that mimics the legacy message grid. Benefit: reduced UI event message UI that mimics the legacy message grid. Benefit: reduced UI event
traffic and more flexibility for UIs. traffic and more flexibility for UIs.
The `msg_history_show` event has an additional "prev_cmd" argument. The `msg_history_show` event has an additional "prev_cmd" argument.
• A new `empty` message kind is emitted for an empty (e.g. `:echo ""`) message.
HIGHLIGHTS HIGHLIGHTS
@@ -88,12 +87,11 @@ HIGHLIGHTS
LSP LSP
`root_markers` in |vim.lsp.Config| can now be ordered by priority. JSON "null" values in LSP messages are represented as |vim.NIL| instead of `nil`.
Missing fields (as opposed to JSON "null") are still represented as `nil`.
• The function set with |vim.lsp.log.set_format_func()| is now given all • The function set with |vim.lsp.log.set_format_func()| is now given all
arguments corresponding to a log entry instead of the individual arguments. arguments corresponding to a log entry instead of the individual arguments.
• `vim.lsp.semantic_tokens.start/stop` now renamed to Renamed `vim.lsp.semantic_tokens` `start()/stop()` to `enable()`.
`vim.lsp.semantic_tokens.enable`
• Missing fields in LSP messages are now represented using |vim.NIL| instead of nil.
• |vim.lsp.util.convert_signature_help_to_markdown_lines()| activeParameter • |vim.lsp.util.convert_signature_help_to_markdown_lines()| activeParameter
handling updated: handling updated:
• Values < 0 are now treated as `nil` instead of 0. • Values < 0 are now treated as `nil` instead of 0.
@@ -103,7 +101,6 @@ LSP
LUA LUA
• Renamed `vim.diff` to `vim.text.diff`. • Renamed `vim.diff` to `vim.text.diff`.
• |vim.net.request()| adds a minimal HTTP GET API using curl.
OPTIONS OPTIONS
@@ -120,7 +117,6 @@ TREESITTER
`metadata[capture_id].offset`. The offset will be applied in `metadata[capture_id].offset`. The offset will be applied in
|vim.treesitter.get_range()|, which should be preferred over reading |vim.treesitter.get_range()|, which should be preferred over reading
metadata directly for retrieving node ranges. metadata directly for retrieving node ranges.
• |Query:iter_captures()| supports specifying starting and ending columns.
TUI TUI
@@ -203,6 +199,7 @@ EDITOR
EVENTS EVENTS
• A new `empty` message kind is emitted for an empty (e.g. `:echo ""`) message.
• |CmdlineLeave| sets |v:char| to the character that stops the Cmdline mode. • |CmdlineLeave| sets |v:char| to the character that stops the Cmdline mode.
• |CmdlineLeavePre| triggered before preparing to leave the command line. • |CmdlineLeavePre| triggered before preparing to leave the command line.
• New `append` parameter for |ui-messages| `msg_show` event. • New `append` parameter for |ui-messages| `msg_show` event.
@@ -220,7 +217,7 @@ HIGHLIGHTS
LSP LSP
• |vim.lsp.ClientConfig| gained `workspace_required`. • |vim.lsp.ClientConfig| gained `workspace_required`.
• You can control priority of |vim.lsp.Config| `root_markers`. • You can control the priority of |vim.lsp.Config| `root_markers`.
• Support for `textDocument/documentColor`: |lsp-document_color| • Support for `textDocument/documentColor`: |lsp-document_color|
https://microsoft.github.io/language-server-protocol/specification/#textDocument_documentColor https://microsoft.github.io/language-server-protocol/specification/#textDocument_documentColor
• Support for `textDocument/colorPresentation |lsp-document_color| • Support for `textDocument/colorPresentation |lsp-document_color|
@@ -261,6 +258,7 @@ LSP
LUA LUA
• |vim.net.request()| can fetch files via HTTP GET requests.
• |vim.wait()| returns the callback results. • |vim.wait()| returns the callback results.
• Lua type annotations for `vim.uv`. • Lua type annotations for `vim.uv`.
• |vim.hl.range()| now allows multiple timed highlights. • |vim.hl.range()| now allows multiple timed highlights.
@@ -330,6 +328,7 @@ TERMINAL
TREESITTER TREESITTER
• |Query:iter_captures()| supports specifying starting and ending columns.
• |:EditQuery| command gained tab-completion, works with injected languages. • |:EditQuery| command gained tab-completion, works with injected languages.
TUI TUI

View File

@@ -301,9 +301,9 @@ end
--- filetypes = { 'c', 'cpp' }, --- filetypes = { 'c', 'cpp' },
--- } --- }
--- ``` --- ```
--- - Get the resolved configuration for "luals": --- - Get the resolved configuration for "lua_ls":
--- ```lua --- ```lua
--- local cfg = vim.lsp.config.luals --- local cfg = vim.lsp.config.lua_ls
--- ``` --- ```
--- ---
---@since 13 ---@since 13
@@ -522,7 +522,7 @@ end
--- ---
--- ```lua --- ```lua
--- vim.lsp.enable('clangd') --- vim.lsp.enable('clangd')
--- vim.lsp.enable({'luals', 'pyright'}) --- vim.lsp.enable({'lua_ls', 'pyright'})
--- ``` --- ```
--- ---
--- Example: [lsp-restart]() Passing `false` stops and detaches the client(s). Thus you can --- Example: [lsp-restart]() Passing `false` stops and detaches the client(s). Thus you can

View File

@@ -34,9 +34,9 @@ local all_clients = {}
--- @class vim.lsp.ClientConfig --- @class vim.lsp.ClientConfig
--- ---
--- Callback invoked before the LSP "initialize" phase, where `params` contains the parameters --- Callback which can modify parameters before they are sent to the server. Invoked before LSP
--- being sent to the server and `config` is the config that was passed to |vim.lsp.start()|. --- "initialize" phase (after `cmd` is invoked), where `params` is the parameters being sent to the
--- You can use this to modify parameters before they are sent. --- server and `config` is the config passed to |vim.lsp.start()|.
--- @field before_init? fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig) --- @field before_init? fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)
--- ---
--- Map overriding the default capabilities defined by |vim.lsp.protocol.make_client_capabilities()|, --- Map overriding the default capabilities defined by |vim.lsp.protocol.make_client_capabilities()|,

View File

@@ -826,7 +826,7 @@ end
--- ---
---@see https://github.com/openresty/luajit2#tableisarray ---@see https://github.com/openresty/luajit2#tableisarray
--- ---
---@param t? table ---@param t? any
---@return boolean `true` if array-like table, else `false`. ---@return boolean `true` if array-like table, else `false`.
function vim.isarray(t) function vim.isarray(t)
if type(t) ~= 'table' then if type(t) ~= 'table' then
@@ -1246,7 +1246,7 @@ end
--- Returns true if object `f` can be called as a function. --- Returns true if object `f` can be called as a function.
--- ---
---@param f any Any object ---@param f? any Any object
---@return boolean `true` if `f` is callable, else `false` ---@return boolean `true` if `f` is callable, else `false`
function vim.is_callable(f) function vim.is_callable(f)
if type(f) == 'function' then if type(f) == 'function' then

View File

@@ -135,7 +135,7 @@ char *server_address_new(const char *name)
return xstrdup(fmt); return xstrdup(fmt);
} }
/// Check if this instance owns a pipe address. /// Check if this instance owns a pipe address (loopback).
bool server_owns_pipe_address(const char *address) bool server_owns_pipe_address(const char *address)
{ {
bool result = false; bool result = false;

View File

@@ -46,8 +46,7 @@ enum {
/// Compare two file names. /// Compare two file names.
/// ///
/// @param s1 First file name. Environment variables in this name will be /// @param s1 First file name. Environment variables in this name will be expanded.
/// expanded.
/// @param s2 Second file name. /// @param s2 Second file name.
/// @param checkname When both files don't exist, only compare their names. /// @param checkname When both files don't exist, only compare their names.
/// @param expandenv Whether to expand environment variables in file names. /// @param expandenv Whether to expand environment variables in file names.
@@ -540,7 +539,6 @@ bool path_has_wildcard(const char *p)
return false; return false;
} }
// Unix style wildcard expansion code.
static int pstrcmp(const void *a, const void *b) static int pstrcmp(const void *a, const void *b)
{ {
return pathcmp(*(char **)a, *(char **)b, -1); return pathcmp(*(char **)a, *(char **)b, -1);
@@ -1956,8 +1954,10 @@ bool same_directory(char *f1, char *f2)
} }
// Compare path "p[]" to "q[]". // Compare path "p[]" to "q[]".
// If "maxlen" >= 0 compare "p[maxlen]" to "q[maxlen]" // If `maxlen` >= 0 compare `p[maxlen]` to `q[maxlen]`
// Return value like strcmp(p, q), but consider path separators. // Return value like strcmp(p, q), but consider path separators.
//
// See also `path_full_compare`.
int pathcmp(const char *p, const char *q, int maxlen) int pathcmp(const char *p, const char *q, int maxlen)
{ {
int i, j; int i, j;
@@ -2314,12 +2314,12 @@ int append_path(char *path, const char *to_append, size_t max_len)
return OK; return OK;
} }
/// Expand a given file to its absolute path. /// Used by `vim_FullName` and `fix_fname` to expand a filename to its full path.
/// ///
/// @param fname filename which should be expanded. /// @param fname Filename to expand.
/// @param buf buffer to store the absolute path of "fname". /// @param buf Where to store the absolute path of "fname".
/// @param len length of "buf". /// @param len Length of `buf`.
/// @param force also expand when "fname" is already absolute. /// @param force Also expand when `fname` is already absolute.
/// ///
/// @return FAIL for failure, OK for success. /// @return FAIL for failure, OK for success.
static int path_to_absolute(const char *fname, char *buf, size_t len, int force) static int path_to_absolute(const char *fname, char *buf, size_t len, int force)

View File

@@ -4616,7 +4616,7 @@ describe('API', function()
}, },
}, api.nvim_parse_cmd('4,6MyCommand! test it', {})) }, api.nvim_parse_cmd('4,6MyCommand! test it', {}))
end) end)
it('works for commands separated by bar', function() it('sets nextcmd for bar-separated commands', function()
eq({ eq({
cmd = 'argadd', cmd = 'argadd',
args = { 'a.txt' }, args = { 'a.txt' },
@@ -4655,6 +4655,12 @@ describe('API', function()
}, },
}, api.nvim_parse_cmd('argadd a.txt | argadd b.txt', {})) }, api.nvim_parse_cmd('argadd a.txt | argadd b.txt', {}))
end) end)
it('sets nextcmd after expr-arg commands #36029', function()
local result = api.nvim_parse_cmd('exe "ls"|edit foo', {})
eq({ '"ls"' }, result.args)
eq('execute', result.cmd)
eq('edit foo', result.nextcmd)
end)
it('parses :map commands with space in RHS', function() it('parses :map commands with space in RHS', function()
eq({ eq({
addr = 'none', addr = 'none',
@@ -4849,12 +4855,6 @@ describe('API', function()
result = api.nvim_parse_cmd('copen 5', {}) result = api.nvim_parse_cmd('copen 5', {})
eq(5, result.count) eq(5, result.count)
end) end)
it('parses nextcmd for commands #36029', function()
local result = api.nvim_parse_cmd('exe "ls"|edit foo', {})
eq({ '"ls"' }, result.args)
eq('execute', result.cmd)
eq('edit foo', result.nextcmd)
end)
end) end)
describe('nvim_cmd', function() describe('nvim_cmd', function()